mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-31 14:31:05 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
794aa84684 | ||
|
|
12d34e64e5 | ||
|
|
59a098c2b5 |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.46.0"
|
||||
".": "0.47.0"
|
||||
}
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## [0.47.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.46.0...v0.47.0) (2026-06-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Update to claude-agent-sdk 0.3.179 ([#783](https://github.com/agentclientprotocol/claude-agent-acp/issues/783)) ([59a098c](https://github.com/agentclientprotocol/claude-agent-acp/commit/59a098c2b530bbae034e9a2dfbd31f8b4ef2a4d0))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Duplicate assistant messages in feed ([#785](https://github.com/agentclientprotocol/claude-agent-acp/issues/785)) ([12d34e6](https://github.com/agentclientprotocol/claude-agent-acp/commit/12d34e64e53564602ac1c38a30127e234c5c25ff))
|
||||
|
||||
## [0.46.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.1...v0.46.0) (2026-06-16)
|
||||
|
||||
|
||||
|
||||
76
package-lock.json
generated
76
package-lock.json
generated
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.46.0",
|
||||
"version": "0.47.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.46.0",
|
||||
"version": "0.47.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "0.26.0",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.179",
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -41,22 +41,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.178.tgz",
|
||||
"integrity": "sha512-PNsz20jWuahDWq7OU+pjrgYzr2TnpC1oj5yCZDxGWJ8OvucXIdD2AYlf/vUo7oE2JJwGbMTBFqXErNrfPi6Ffw==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.179.tgz",
|
||||
"integrity": "sha512-BlZULVW61ZCcho6mb026QoOQbGZnfxbsEtcoNaW5lF0sIEu7D+/nnQjHSMK8buS/h7HVmIx2RtGbHVX1y4V0uQ==",
|
||||
"license": "SEE LICENSE IN README.md",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.178"
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.179",
|
||||
"@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.179"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@anthropic-ai/sdk": ">=0.93.0",
|
||||
@@ -65,9 +65,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.178.tgz",
|
||||
"integrity": "sha512-RmIJRoZfjwcrd7cHR3fJOL1d4L8SN7oB0REcQPbIuPM1vav2Ft3g5hBX7I86u52A4LLFKBc3SMom3+E6lR1YtQ==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.179.tgz",
|
||||
"integrity": "sha512-2QoEl7p+RTkF4ARZ40N9OWWi+at8Iy9ZZg3UeP6sWoGrM0GL6NJSv8pbYUdoSRySbNeZshqWar5DF41265J5Sg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -78,9 +78,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.178.tgz",
|
||||
"integrity": "sha512-wfNl7JoaUk9IzKWQPr+hyEOX8qnkM+e4GBZnKISh60xVhW9wOOp5RdfnYj5MoJzaLYivMSCbo5rb4ThWguhOMw==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.179.tgz",
|
||||
"integrity": "sha512-U5683Hi4uP5Wkg9IhHayqx8co9rgeZaAJcutLAgJiAN9ZnL128+WT0K4DKaBVuMbeeoORodVs9IJgM38lBxUxg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -91,9 +91,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.178.tgz",
|
||||
"integrity": "sha512-ktBU6EdJoZivf67AxRXe2uSwj0g5tCe20So9QvWVKuEEtRA4sXW5EpgxSWT6LXkgfwUoeNsJK7VAOuVjZumKmg==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.179.tgz",
|
||||
"integrity": "sha512-Io9X2xF5J3cHR20b0oflLe0sLHyT/KFMCA7sVJhwuSvcqeCHqXTxn6sG+4lArD9wNf+RtLVKgSvOt5Oz4j7mew==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -107,9 +107,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.178.tgz",
|
||||
"integrity": "sha512-Z3U0fNatVK3vkki3e5sjlLJMjros+cT6uq//tdohB2kjNK1CugUuPQFQxd6GU1Lq1DokmdSEPL4OGdKiHckNdQ==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.179.tgz",
|
||||
"integrity": "sha512-ehqWR9bV0dJONkoKleKg/LJIGDVevLGLPVIQpol+Bqrgyv05DE1hx68g6mBnfp9IEKo2BMZCba3aHKhkHlZvnQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -123,9 +123,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.178.tgz",
|
||||
"integrity": "sha512-CPTivDz27LMn5m9iQnJSoWkztLo41e8QTbuYKlAC+CTr98gaYy3Mao0M2tirEK/nGno0xRJw/EpZ1G61yEM3yw==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.179.tgz",
|
||||
"integrity": "sha512-Ck2pLG2GJ5lYULK0Rb6FvAUhkLSvIFgJ77MsbVhvBJHG3C31Fuk6FnkXEL614WSZZdI1ST0Y7s7wc9yLI2kmiQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -139,9 +139,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.178.tgz",
|
||||
"integrity": "sha512-K84Ybyr0Olsslg2I1Tzd7KIcSkZgFqqDHn7q1Dfqi7bXVxjMjJ4SaV+LnEAeHSM2es7H8A7ejoTEl89xMZde4Q==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.179.tgz",
|
||||
"integrity": "sha512-Q+clijh01m+Gg/tSNjHQWfPFRvXSVMIQJZqu6v28vFduaucL7ZL+p6o6VOSdlgLjhqtIFFjOO37aL+VkvEu9MQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -155,9 +155,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.178.tgz",
|
||||
"integrity": "sha512-uKH3vgv7cQV3d9BPU4lrUKrFgoU/flmy/1QI62j9JzgE6uWVQKWC+BI4V7iceJ36tYVneRhjjuux+l+Q8egTHA==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.179.tgz",
|
||||
"integrity": "sha512-7wc4j3vDE/TiuiCEPV024U/TDNKXUJ89V0N9WteYJ57YrIUm0RA51WiKCrEmSxSqstQ7Slq26e0gWGHRf7ljDQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -168,9 +168,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": {
|
||||
"version": "0.3.178",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.178.tgz",
|
||||
"integrity": "sha512-wSC5qG6UA1laWGylOU7axuC4NQxZJtibGQ79sYeOQCc05G7CfkUKSzszLOzsPP3eK63cKi/bX5PA6dd4nA5Wow==",
|
||||
"version": "0.3.179",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.179.tgz",
|
||||
"integrity": "sha512-gFad1AVUZOXbEyS9lf3Pr0LDXrLuO6limZoZoUZQmjhjy0LnudnTU8P/VbCY0AHmT46YMZ/ieisFzeq8X5jTcg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "0.46.0",
|
||||
"version": "0.47.0",
|
||||
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
|
||||
"main": "dist/lib.js",
|
||||
"types": "dist/lib.d.ts",
|
||||
@@ -61,7 +61,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "0.26.0",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.178",
|
||||
"@anthropic-ai/claude-agent-sdk": "0.3.179",
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -959,9 +959,8 @@ export class ClaudeAcpAgent implements Agent {
|
||||
// via `stream_event` deltas, split by block type, so the consolidated
|
||||
// `assistant` message can drop the duplicate blocks that already reached the
|
||||
// client as chunks while still forwarding any that a non-streaming gateway
|
||||
// delivered only as an assembled block.
|
||||
let streamedTextIds = new Set<string>();
|
||||
let streamedThinkingIds = new Set<string>();
|
||||
const streamedTextIds = new Set<string>();
|
||||
const streamedThinkingIds = new Set<string>();
|
||||
// Stop reason accumulated for the active turn (result subtype, refusal,
|
||||
// max_tokens, …). Reset per turn; read when the turn settles at idle.
|
||||
let stopReason: StopReason = "end_turn";
|
||||
@@ -974,8 +973,6 @@ export class ClaudeAcpAgent implements Agent {
|
||||
lastRefusalExplanation = null;
|
||||
compactionInProgress = false;
|
||||
currentStreamMessageId = undefined;
|
||||
streamedTextIds = new Set<string>();
|
||||
streamedThinkingIds = new Set<string>();
|
||||
stopReason = "end_turn";
|
||||
session.accumulatedUsage = {
|
||||
inputTokens: 0,
|
||||
@@ -1864,6 +1861,13 @@ export class ClaudeAcpAgent implements Agent {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// The consolidated message is the last place this id is needed for
|
||||
// dedupe — drop it so the streamed-id sets stay bounded to in-flight
|
||||
// streams rather than growing for the session's whole life.
|
||||
if (id !== undefined) {
|
||||
streamedTextIds.delete(id);
|
||||
streamedThinkingIds.delete(id);
|
||||
}
|
||||
} else if (message.type === "assistant") {
|
||||
// Subagent assistant message (`parent_tool_use_id !== null`). It is
|
||||
// never streamed live and its text/thinking is internal to the tool
|
||||
|
||||
@@ -3679,6 +3679,36 @@ describe("assembled assistant text fallback", () => {
|
||||
});
|
||||
}
|
||||
|
||||
// Like injectSession, but the user-message echo is yielded at the position of
|
||||
// the "ECHO" sentinel in `messages` rather than always first — so a test can
|
||||
// reproduce the production ordering where the assistant stream arrives before
|
||||
// the SDK replays the user message.
|
||||
function injectSessionEchoAt(agent: ClaudeAcpAgent, messages: any[]) {
|
||||
const input = new Pushable<any>();
|
||||
async function* messageGenerator() {
|
||||
const iter = input[Symbol.asyncIterator]();
|
||||
const { value: userMessage } = await iter.next();
|
||||
for (const m of messages) {
|
||||
if (m === "ECHO") {
|
||||
yield {
|
||||
type: "user",
|
||||
message: userMessage.message,
|
||||
parent_tool_use_id: null,
|
||||
uuid: userMessage.uuid,
|
||||
session_id: "test-session",
|
||||
isReplay: true,
|
||||
};
|
||||
} else {
|
||||
yield m;
|
||||
}
|
||||
}
|
||||
}
|
||||
agent.sessions["test-session"] = mockSessionState({
|
||||
query: wrapQuery(messageGenerator()),
|
||||
input,
|
||||
});
|
||||
}
|
||||
|
||||
function messageChunkTexts(updates: any[]): string[] {
|
||||
return updates
|
||||
.filter((u) => u.update?.sessionUpdate === "agent_message_chunk")
|
||||
@@ -3723,6 +3753,28 @@ describe("assembled assistant text fallback", () => {
|
||||
expect(messageChunkTexts(updates)).toEqual(["hello ", "world"]);
|
||||
});
|
||||
|
||||
it("dedupes streamed text even when the stream arrives before the user echo", async () => {
|
||||
const { agent, updates } = createMockAgentWithCapture();
|
||||
// Production ordering: the SDK emits the assistant's stream events before it
|
||||
// replays the user message that activates the turn. The streamed-id tracking
|
||||
// must survive activation, or the consolidated block is re-emitted as a
|
||||
// duplicate (regression from the persistent-consumer rework).
|
||||
injectSessionEchoAt(agent, [
|
||||
messageStart("msg-streamed"),
|
||||
textDelta("hello "),
|
||||
textDelta("world"),
|
||||
"ECHO",
|
||||
assistantMessage("msg-streamed", [{ type: "text", text: "hello world" }]),
|
||||
result(),
|
||||
idle,
|
||||
]);
|
||||
|
||||
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "hi" }] });
|
||||
|
||||
// Still just the two streamed deltas — no duplicated assembled block.
|
||||
expect(messageChunkTexts(updates)).toEqual(["hello ", "world"]);
|
||||
});
|
||||
|
||||
it("dedupes per block type: streamed text is dropped but an un-streamed thinking block in the same message is forwarded", async () => {
|
||||
const { agent, updates } = createMockAgentWithCapture();
|
||||
// Gateway streams the text live but delivers the thinking block only in the
|
||||
|
||||
Reference in New Issue
Block a user