Skip to content

Commit a465e2e

Browse files
authored
feat: Sync Claude Agent SDK to v0.20.2 (#1146)
1 parent c538d08 commit a465e2e

5 files changed

Lines changed: 89 additions & 68 deletions

File tree

packages/agent/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
},
8989
"dependencies": {
9090
"@agentclientprotocol/sdk": "^0.14.0",
91-
"@anthropic-ai/claude-agent-sdk": "0.2.63",
91+
"@anthropic-ai/claude-agent-sdk": "0.2.68",
9292
"@anthropic-ai/sdk": "^0.78.0",
9393
"@hono/node-server": "^1.19.9",
9494
"@opentelemetry/api-logs": "^0.208.0",

packages/agent/src/adapters/claude/UPSTREAM.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ Fork of `@anthropic-ai/claude-agent-acp`. Upstream repo: https://github.com/anth
55
## Fork Point
66

77
- **Forked**: v0.10.9, commit `5411e0f4`, Dec 2 2025
8-
- **Last sync**: v0.19.2, March 2 2026
9-
- **SDK**: `@anthropic-ai/claude-agent-sdk` 0.2.63, `@agentclientprotocol/sdk` ^0.14.0
8+
- **Last sync**: v0.20.2, commit `dd9fe3a98ea494ba1982516f8aa0464b48fdd5e1`, March 6 2026
9+
- **SDK**: `@anthropic-ai/claude-agent-sdk` 0.2.68, `@agentclientprotocol/sdk` ^0.14.0
1010

1111
## File Mapping
1212

@@ -55,7 +55,7 @@ Fork of `@anthropic-ai/claude-agent-acp`. Upstream repo: https://github.com/anth
5555

5656
## Next Sync
5757

58-
1. Check upstream changelog since v0.19.2
58+
1. Check upstream changelog since v0.20.2
5959
2. Diff upstream source against Twig using the file mapping above
6060
3. Port in phases: bug fixes first, then features
6161
4. After each phase: `pnpm --filter agent typecheck && pnpm --filter agent build && pnpm lint`

packages/agent/src/adapters/claude/claude-agent.ts

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -385,14 +385,7 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
385385
const result = handleResultMessage(message);
386386
if (result.error) throw result.error;
387387

388-
switch (message.subtype) {
389-
case "error_max_budget_usd":
390-
case "error_max_turns":
391-
case "error_max_structured_output_retries":
392-
return { stopReason: "max_turn_requests", usage };
393-
default:
394-
return { stopReason: "end_turn", usage };
395-
}
388+
return { stopReason: result.stopReason ?? "end_turn", usage };
396389
}
397390

398391
case "stream_event":
@@ -420,6 +413,14 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
420413
}
421414
}
422415

416+
// Skip replayed user messages that aren't pending prompts
417+
if (
418+
"isReplay" in message &&
419+
(message as Record<string, unknown>).isReplay
420+
) {
421+
break;
422+
}
423+
423424
// Store latest assistant usage (excluding subagents)
424425
if (
425426
"usage" in message.message &&
@@ -451,6 +452,8 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
451452
case "tool_progress":
452453
case "auth_status":
453454
case "tool_use_summary":
455+
case "prompt_suggestion":
456+
case "rate_limit_event":
454457
break;
455458

456459
default:
@@ -459,6 +462,28 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
459462
}
460463
}
461464
throw new Error("Session did not end in result");
465+
} catch (error) {
466+
if (error instanceof RequestError || !(error instanceof Error)) {
467+
throw error;
468+
}
469+
const msg = error.message;
470+
if (
471+
msg.includes("ProcessTransport") ||
472+
msg.includes("terminated process") ||
473+
msg.includes("process exited with") ||
474+
msg.includes("process terminated by signal") ||
475+
msg.includes("Failed to write to process stdin")
476+
) {
477+
this.logger.error(`Process died: ${msg}`, {
478+
sessionId: this.sessionId,
479+
});
480+
this.session.input.end();
481+
throw RequestError.internalError(
482+
undefined,
483+
"The Claude Agent process exited unexpectedly. Please start a new session.",
484+
);
485+
}
486+
throw error;
462487
} finally {
463488
if (!handedOff) {
464489
this.session.promptRunning = false;
@@ -704,6 +729,13 @@ export class ClaudeAcpAgent extends BaseAcpAgent {
704729
}
705730
} catch (err) {
706731
settingsManager.dispose();
732+
if (
733+
isResume &&
734+
err instanceof Error &&
735+
err.message === "Query closed before response received"
736+
) {
737+
throw RequestError.resourceNotFound(sessionId);
738+
}
707739
this.logger.error(
708740
isResume
709741
? forkSession

packages/agent/src/adapters/claude/conversion/sdk-to-acp.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {
44
SessionNotification,
55
SessionUpdate,
66
} from "@agentclientprotocol/sdk";
7-
import { RequestError } from "@agentclientprotocol/sdk";
7+
import { RequestError, type StopReason } from "@agentclientprotocol/sdk";
88
import type {
99
SDKAssistantMessage,
1010
SDKMessage,
@@ -574,7 +574,7 @@ export async function handleSystemMessage(
574574

575575
export type ResultMessageHandlerResult = {
576576
shouldStop: boolean;
577-
stopReason?: string;
577+
stopReason?: StopReason;
578578
error?: Error;
579579
usage?: {
580580
inputTokens: number;
@@ -600,6 +600,9 @@ export function handleResultMessage(
600600
usage,
601601
};
602602
}
603+
if ((message as Record<string, unknown>).stop_reason === "max_tokens") {
604+
return { shouldStop: true, stopReason: "max_tokens", usage };
605+
}
603606
if (message.is_error) {
604607
return {
605608
shouldStop: true,
@@ -610,6 +613,9 @@ export function handleResultMessage(
610613
return { shouldStop: true, stopReason: "end_turn", usage };
611614
}
612615
case "error_during_execution":
616+
if ((message as Record<string, unknown>).stop_reason === "max_tokens") {
617+
return { shouldStop: true, stopReason: "max_tokens", usage };
618+
}
613619
if (message.is_error) {
614620
return {
615621
shouldStop: true,

0 commit comments

Comments
 (0)