@agentclientprotocol/claude-agent-acp 0.85.2-preview.13 → 0.85.2-preview.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/v2/agent.d.ts.map +1 -1
- package/dist/v2/agent.js +75 -8
- package/dist/v2/session.d.ts +15 -4
- package/dist/v2/session.d.ts.map +1 -1
- package/dist/v2/session.js +20 -6
- package/package.json +1 -1
package/dist/v2/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/v2/agent.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAkB,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAgB9E;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACvC,EAAE,CAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/v2/agent.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAkB,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAgB9E;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACvC,EAAE,CAAC,QAAQ,CAyCb"}
|
package/dist/v2/agent.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ClaudeAcpAgent } from "../acp-agent.js";
|
|
|
3
3
|
import { v1InitializeRequest, v2InitializeResponse } from "./initialize.js";
|
|
4
4
|
import { v1PermissionResponse, v2PermissionRequest } from "./permission.js";
|
|
5
5
|
import { v2Prompt } from "./prompt.js";
|
|
6
|
-
import { v1NewSessionRequest,
|
|
6
|
+
import { v1NewSessionRequest, v1RestoreSessionRequest, v1SetSessionConfigOptionRequest, v2ConfigOptions, v2NewSessionResponse, v2ResumeSessionResponse, } from "./session.js";
|
|
7
7
|
import { v2SessionUpdate } from "./session-update.js";
|
|
8
8
|
/**
|
|
9
9
|
* The ACP v2 surface, for one connection.
|
|
@@ -27,7 +27,12 @@ export function v2AgentApp(logger, onAgent) {
|
|
|
27
27
|
.onRequest(v2.methods.agent.auth.logout, ({ params }) => agent.logout(params))
|
|
28
28
|
.onRequest(v2.methods.agent.session.new, async ({ params }) => v2NewSessionResponse(await agent.newSession(v1NewSessionRequest(params))))
|
|
29
29
|
.onRequest(v2.methods.agent.session.list, ({ params }) => agent.listSessions(params))
|
|
30
|
-
.onRequest(v2.methods.agent.session.resume, async ({ params }) =>
|
|
30
|
+
.onRequest(v2.methods.agent.session.resume, async ({ params }) => {
|
|
31
|
+
const restore = v1RestoreSessionRequest(params);
|
|
32
|
+
return v2ResumeSessionResponse(restore.method === "resume"
|
|
33
|
+
? await agent.resumeSession(restore.request)
|
|
34
|
+
: await client.replaying(params.sessionId, () => agent.loadSession(restore.request)));
|
|
35
|
+
})
|
|
31
36
|
.onRequest(v2.methods.agent.session.close, ({ params }) => agent.closeSession(params))
|
|
32
37
|
.onRequest(v2.methods.agent.session.delete, ({ params }) => agent.deleteSession(params))
|
|
33
38
|
.onRequest(v2.methods.agent.session.setConfigOption, async ({ params }) => {
|
|
@@ -46,10 +51,32 @@ export function v2AgentApp(logger, onAgent) {
|
|
|
46
51
|
class V2ClientConnection {
|
|
47
52
|
ctx;
|
|
48
53
|
logger;
|
|
54
|
+
/**
|
|
55
|
+
* The sessions whose history replays, each with the messages that the
|
|
56
|
+
* replay has cleared so far.
|
|
57
|
+
*/
|
|
58
|
+
replays = new Map();
|
|
49
59
|
constructor(ctx, logger) {
|
|
50
60
|
this.ctx = ctx;
|
|
51
61
|
this.logger = logger;
|
|
52
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Runs `restore`, which replays the history of `sessionId`.
|
|
65
|
+
*
|
|
66
|
+
* The agent replays messages as chunks. A v2 client may still hold a
|
|
67
|
+
* replayed message, and chunks append, so before the first replayed chunk of
|
|
68
|
+
* each message the client gets the message with no content, which clears it,
|
|
69
|
+
* as v2 requires of a message replayed as chunks.
|
|
70
|
+
*/
|
|
71
|
+
async replaying(sessionId, restore) {
|
|
72
|
+
this.replays.set(sessionId, new Set());
|
|
73
|
+
try {
|
|
74
|
+
return await restore();
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
this.replays.delete(sessionId);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
53
80
|
/**
|
|
54
81
|
* Sends a v2 session update, and logs rather than rejects when that fails.
|
|
55
82
|
* It and {@link sessionUpdate} hand updates to the connection synchronously,
|
|
@@ -72,12 +99,35 @@ class V2ClientConnection {
|
|
|
72
99
|
}
|
|
73
100
|
async sessionUpdate({ update, ...notification }) {
|
|
74
101
|
const v2Update = v2SessionUpdate(update);
|
|
75
|
-
if (v2Update)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
if (!v2Update)
|
|
103
|
+
return;
|
|
104
|
+
const clear = this.replayClear(notification.sessionId, v2Update);
|
|
105
|
+
// Both go to the connection before either is awaited, so a chunk that
|
|
106
|
+
// another call sends meanwhile cannot come between them.
|
|
107
|
+
await Promise.all([
|
|
108
|
+
...(clear
|
|
109
|
+
? [this.ctx.notify(v2.methods.client.session.update, { ...notification, update: clear })]
|
|
110
|
+
: []),
|
|
111
|
+
this.ctx.notify(v2.methods.client.session.update, { ...notification, update: v2Update }),
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The update that clears the message of a replayed chunk, when it is the
|
|
116
|
+
* first replayed chunk of that message (see {@link replaying}).
|
|
117
|
+
*/
|
|
118
|
+
replayClear(sessionId, update) {
|
|
119
|
+
const cleared = this.replays.get(sessionId);
|
|
120
|
+
if (!cleared)
|
|
121
|
+
return undefined;
|
|
122
|
+
const kind = MESSAGE_OF_CHUNK.get(update.sessionUpdate);
|
|
123
|
+
if (!kind)
|
|
124
|
+
return undefined;
|
|
125
|
+
const { messageId } = update;
|
|
126
|
+
const key = `${kind} ${messageId}`;
|
|
127
|
+
if (cleared.has(key))
|
|
128
|
+
return undefined;
|
|
129
|
+
cleared.add(key);
|
|
130
|
+
return emptyMessage(kind, messageId);
|
|
81
131
|
}
|
|
82
132
|
async requestPermission(params, signal) {
|
|
83
133
|
const response = await this.ctx.request(v2.methods.client.session.requestPermission, v2PermissionRequest(params), { cancellationSignal: signal });
|
|
@@ -103,6 +153,23 @@ class V2ClientConnection {
|
|
|
103
153
|
return Promise.reject(new Error("ACP v2 has no client file system"));
|
|
104
154
|
}
|
|
105
155
|
}
|
|
156
|
+
/** The message update of each message chunk. */
|
|
157
|
+
const MESSAGE_OF_CHUNK = new Map([
|
|
158
|
+
["user_message_chunk", "user_message"],
|
|
159
|
+
["agent_message_chunk", "agent_message"],
|
|
160
|
+
["agent_thought_chunk", "agent_thought"],
|
|
161
|
+
]);
|
|
162
|
+
function emptyMessage(kind, messageId) {
|
|
163
|
+
const message = { messageId, content: [] };
|
|
164
|
+
switch (kind) {
|
|
165
|
+
case "user_message":
|
|
166
|
+
return { ...message, sessionUpdate: kind };
|
|
167
|
+
case "agent_message":
|
|
168
|
+
return { ...message, sessionUpdate: kind };
|
|
169
|
+
default:
|
|
170
|
+
return { ...message, sessionUpdate: kind };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
106
173
|
function isExtensionMethod(method) {
|
|
107
174
|
return method.startsWith("_");
|
|
108
175
|
}
|
package/dist/v2/session.d.ts
CHANGED
|
@@ -3,14 +3,25 @@
|
|
|
3
3
|
* `ClaudeAcpAgent`: v2 requests become the v1 requests that the agent serves,
|
|
4
4
|
* and its v1 responses become v2 responses.
|
|
5
5
|
*/
|
|
6
|
-
import { type AvailableCommand, type NewSessionRequest, type NewSessionResponse, type ResumeSessionRequest, type ResumeSessionResponse, type SessionConfigOption, type SetSessionConfigOptionRequest } from "@agentclientprotocol/sdk";
|
|
6
|
+
import { type AvailableCommand, type LoadSessionRequest, type NewSessionRequest, type NewSessionResponse, type ResumeSessionRequest, type ResumeSessionResponse, type SessionConfigOption, type SetSessionConfigOptionRequest } from "@agentclientprotocol/sdk";
|
|
7
7
|
import * as v2 from "@agentclientprotocol/sdk/experimental/v2";
|
|
8
8
|
export declare function v1NewSessionRequest(params: v2.NewSessionRequest): NewSessionRequest;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* The v1 request that a v2 `session/resume` means.
|
|
11
|
+
*
|
|
12
|
+
* v2 restores a session with `session/resume` and replays its history only
|
|
13
|
+
* when `replayFrom` asks for it. v1 has two methods: `session/resume`, which
|
|
14
|
+
* never replays, and `session/load`, which replays the whole history before it
|
|
15
|
+
* responds. `replayFrom: { type: "start" }` is the second; a cursor that
|
|
16
|
+
* starts elsewhere is rejected.
|
|
12
17
|
*/
|
|
13
|
-
export declare function
|
|
18
|
+
export declare function v1RestoreSessionRequest(params: v2.ResumeSessionRequest): {
|
|
19
|
+
method: "resume";
|
|
20
|
+
request: ResumeSessionRequest;
|
|
21
|
+
} | {
|
|
22
|
+
method: "load";
|
|
23
|
+
request: LoadSessionRequest;
|
|
24
|
+
};
|
|
14
25
|
/** v2 drops `modes`: the session mode is the `mode` config option, which the agent always lists. */
|
|
15
26
|
export declare function v2NewSessionResponse(response: NewSessionResponse): v2.NewSessionResponse;
|
|
16
27
|
export declare function v2ResumeSessionResponse(response: ResumeSessionResponse): v2.ResumeSessionResponse;
|
package/dist/v2/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/v2/session.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/v2/session.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EAEvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EAGxB,KAAK,6BAA6B,EACnC,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAE/D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,iBAAiB,GAAG,iBAAiB,CAInF;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,EAAE,CAAC,oBAAoB,GAE7B;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,CAkBlD;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,EAAE,CAAC,kBAAkB,CAExF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,EAAE,CAAC,qBAAqB,CAKjG;AAED,uEAAuE;AACvE,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,EAAE,CAAC,6BAA6B,GACvC,6BAA6B,CAgB/B;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC,mBAAmB,EAAE,CAQxF;AAWD,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE,CAKvF"}
|
package/dist/v2/session.js
CHANGED
|
@@ -11,15 +11,29 @@ export function v1NewSessionRequest(params) {
|
|
|
11
11
|
return { ...request, mcpServers: (mcpServers ?? []).map(v1McpServer) };
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* The v1 request that a v2 `session/resume` means.
|
|
15
|
+
*
|
|
16
|
+
* v2 restores a session with `session/resume` and replays its history only
|
|
17
|
+
* when `replayFrom` asks for it. v1 has two methods: `session/resume`, which
|
|
18
|
+
* never replays, and `session/load`, which replays the whole history before it
|
|
19
|
+
* responds. `replayFrom: { type: "start" }` is the second; a cursor that
|
|
20
|
+
* starts elsewhere is rejected.
|
|
16
21
|
*/
|
|
17
|
-
export function
|
|
22
|
+
export function v1RestoreSessionRequest(params) {
|
|
18
23
|
const { replayFrom, mcpServers, ...request } = params;
|
|
19
|
-
if (replayFrom
|
|
20
|
-
|
|
24
|
+
if (replayFrom == null) {
|
|
25
|
+
return {
|
|
26
|
+
method: "resume",
|
|
27
|
+
request: { ...request, ...(mcpServers ? { mcpServers: mcpServers.map(v1McpServer) } : {}) },
|
|
28
|
+
};
|
|
21
29
|
}
|
|
22
|
-
|
|
30
|
+
if (replayFrom.type !== "start") {
|
|
31
|
+
throw RequestError.invalidParams({ replayFrom }, `Replaying from a ${replayFrom.type} cursor is not supported`);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
method: "load",
|
|
35
|
+
request: { ...request, mcpServers: (mcpServers ?? []).map(v1McpServer) },
|
|
36
|
+
};
|
|
23
37
|
}
|
|
24
38
|
/** v2 drops `modes`: the session mode is the `mode` config option, which the agent always lists. */
|
|
25
39
|
export function v2NewSessionResponse(response) {
|
package/package.json
CHANGED