@intentius/chant-lexicon-fountain 0.106.3 → 0.107.1
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/acp/protocol.d.ts +13 -0
- package/dist/acp/protocol.d.ts.map +1 -1
- package/dist/acp/server.d.ts +10 -0
- package/dist/acp/server.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/src/acp/acp.test.ts +55 -0
- package/src/acp/protocol.ts +13 -0
- package/src/acp/server.ts +31 -3
package/dist/acp/protocol.d.ts
CHANGED
|
@@ -62,6 +62,10 @@ export interface InitializeResult {
|
|
|
62
62
|
audio: boolean;
|
|
63
63
|
embeddedContext: boolean;
|
|
64
64
|
};
|
|
65
|
+
/** `resume` present: the agent answers `session/resume`. */
|
|
66
|
+
sessionCapabilities: {
|
|
67
|
+
resume: Record<string, never>;
|
|
68
|
+
};
|
|
65
69
|
};
|
|
66
70
|
authMethods: unknown[];
|
|
67
71
|
}
|
|
@@ -75,6 +79,15 @@ export interface NewSessionParams {
|
|
|
75
79
|
export interface NewSessionResult {
|
|
76
80
|
sessionId: string;
|
|
77
81
|
}
|
|
82
|
+
/** `session/resume` params: a session an earlier process opened, and the cwd to open it in. */
|
|
83
|
+
export interface ResumeSessionParams {
|
|
84
|
+
sessionId: string;
|
|
85
|
+
cwd?: string;
|
|
86
|
+
mcpServers?: unknown[];
|
|
87
|
+
_meta?: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
/** `session/resume` result. Nothing to report: there is no mode or model to restore. */
|
|
90
|
+
export type ResumeSessionResult = Record<string, never>;
|
|
78
91
|
/**
|
|
79
92
|
* The out-of-band bag a client attaches to `session/prompt` to resume a
|
|
80
93
|
* durable permission request (#2125). ACP's `_meta` is the extension point
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/acp/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,+CAA+C;AAC/C,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAC1C,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAC9C,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAC/C,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1E,uDAAuD;AACvD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEhF,+CAA+C;AAC/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,2BAA2B;AAC3B,MAAM,WAAW,gBAAgB;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,2BAA2B;AAC3B,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,iBAAiB,EAAE;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB,kBAAkB,EAAE;YAAE,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,eAAe,EAAE,OAAO,CAAA;SAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/acp/protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/acp/server.d.ts
CHANGED
|
@@ -69,6 +69,16 @@ export declare class AcpServer implements JsonRpcHandler {
|
|
|
69
69
|
private enqueue;
|
|
70
70
|
private initialize;
|
|
71
71
|
private newSession;
|
|
72
|
+
/**
|
|
73
|
+
* Take up a session by the id a client already holds. A chant session is a
|
|
74
|
+
* working directory and nothing else, so one this process never opened —
|
|
75
|
+
* the usual case, since a client spawns a new process per turn — is opened
|
|
76
|
+
* again under the same id with the cwd the client sends. A gate a previous
|
|
77
|
+
* process asked about under `--durable-requests` is not carried over: its
|
|
78
|
+
* answer finds no request waiting and says to prompt the line again.
|
|
79
|
+
*/
|
|
80
|
+
private resumeSession;
|
|
81
|
+
private openSession;
|
|
72
82
|
private prompt;
|
|
73
83
|
/**
|
|
74
84
|
* Answer a `session/request_permission` this agent sent in an earlier turn.
|
package/dist/acp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/acp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAEL,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/acp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAEL,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAsBnB,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGvE,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;IACxC,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD,qBAAa,SAAU,YAAW,cAAc;IAC9C,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA6B;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,6CAA6C;IAC7C,OAAO,CAAC,KAAK,CAAuC;IAEpD,YAAY,IAAI,GAAE,gBAAqB,EAMtC;IAED,4CAA4C;IAC5C,OAAO,CAAC,SAAS,EAAE,aAAa,GAAG,WAAW,CAG7C;IAEK,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAa/D;IAED,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAQ5C;IAED,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,UAAU;IA4BlB,OAAO,CAAC,UAAU;IAMlB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,WAAW;YASL,MAAM;IAcpB;;;;;;OAMG;YACW,MAAM;YAuCN,cAAc;IAkC5B,8DAA8D;IAC9D,OAAO,CAAC,OAAO;CA0DhB"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "90bfb9690a0554836309f588cdd722c62f48dc2a74893f5d674d68e9b97e6a25",
|
|
5
5
|
"meta.json": "3301437a2a56eaf1a5cc8f6eabb18a40767f916e09701b2d9bf20aba4066738c",
|
|
6
6
|
"types/index.d.ts": "cf6b634fe0a8e9e96f1d9d07e3df53838def2683dc93dbe3c7fd971c6d3908ae",
|
|
7
7
|
"rules/ftn001-no-secret-literals.ts": "a417b194cd7039911cca9a0f14c49b042dfa6b1ee48517f7c2e22b16590a8599",
|
|
@@ -23,5 +23,5 @@
|
|
|
23
23
|
"skills/chant-fountain-ops.md": "4e72f0a0c7477a9e98f85ea45e49ba69e8a699f9c13ba0f0cf1cb20a88151373",
|
|
24
24
|
"skills/chant-fountain-locked-sandboxes.md": "7404ece96f2a3bc9105942fd3b6db156a3537db7e34c8cf2faa9ba87f5512567"
|
|
25
25
|
},
|
|
26
|
-
"composite": "
|
|
26
|
+
"composite": "e3f4c55cb18423b29f7ae8744298db583368bf983cebef8d51b6f4ea48428c4b"
|
|
27
27
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-fountain",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.107.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Fountain lexicon for chant — sandboxed agent environments, vaults, and agents as typed estate",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"bundle": "tsx src/package-cli.ts"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@intentius/chant": "^0.
|
|
53
|
+
"@intentius/chant": "^0.107.1",
|
|
54
54
|
"typescript": "^5.9.3",
|
|
55
55
|
"zod": "^4.3.6"
|
|
56
56
|
},
|
package/src/acp/acp.test.ts
CHANGED
|
@@ -347,6 +347,7 @@ describe("chant acp", () => {
|
|
|
347
347
|
expect(init.agentCapabilities).toMatchObject({
|
|
348
348
|
loadSession: false,
|
|
349
349
|
promptCapabilities: { image: false, audio: false, embeddedContext: false },
|
|
350
|
+
sessionCapabilities: { resume: {} },
|
|
350
351
|
});
|
|
351
352
|
|
|
352
353
|
const session = (await client.peer.request("session/new", {
|
|
@@ -371,6 +372,60 @@ describe("chant acp", () => {
|
|
|
371
372
|
expect(seen).toEqual(["/tmp/project-a"]);
|
|
372
373
|
});
|
|
373
374
|
|
|
375
|
+
// Fountain spawns `chant acp` once per turn and, from a conversation's
|
|
376
|
+
// second turn on, resumes the session the first turn opened. A fresh
|
|
377
|
+
// process has never seen that id, and must take it up rather than fail.
|
|
378
|
+
it("resumes a session another process opened, in the cwd the client sends", async () => {
|
|
379
|
+
const seen: string[] = [];
|
|
380
|
+
const host = stubHost({ records: okRecords });
|
|
381
|
+
const server = new AcpServer({
|
|
382
|
+
createHost: (cwd) => {
|
|
383
|
+
seen.push(cwd);
|
|
384
|
+
return host;
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
const client = connect(server);
|
|
388
|
+
await client.peer.request("initialize", {});
|
|
389
|
+
|
|
390
|
+
const result = await client.peer.request("session/resume", {
|
|
391
|
+
sessionId: "sess-from-turn-1",
|
|
392
|
+
cwd: "/tmp/project-b",
|
|
393
|
+
mcpServers: [],
|
|
394
|
+
});
|
|
395
|
+
expect(result).toEqual({});
|
|
396
|
+
expect(seen).toEqual(["/tmp/project-b"]);
|
|
397
|
+
|
|
398
|
+
await client.peer.request("session/prompt", {
|
|
399
|
+
sessionId: "sess-from-turn-1",
|
|
400
|
+
prompt: promptOf("chant run demo-op"),
|
|
401
|
+
});
|
|
402
|
+
expect(host.started).toEqual(["demo-op"]);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it("keeps a session this process already holds when it is resumed", async () => {
|
|
406
|
+
const seen: string[] = [];
|
|
407
|
+
const server = new AcpServer({
|
|
408
|
+
createHost: (cwd) => {
|
|
409
|
+
seen.push(cwd);
|
|
410
|
+
return stubHost();
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
const client = connect(server);
|
|
414
|
+
await client.peer.request("initialize", {});
|
|
415
|
+
const { sessionId } = (await client.peer.request("session/new", { cwd: "/tmp/project-a" })) as {
|
|
416
|
+
sessionId: string;
|
|
417
|
+
};
|
|
418
|
+
await client.peer.request("session/resume", { sessionId, cwd: "/tmp/project-a" });
|
|
419
|
+
expect(seen).toEqual(["/tmp/project-a"]);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it("refuses a session/resume with no sessionId", async () => {
|
|
423
|
+
const server = new AcpServer({ createHost: () => stubHost() });
|
|
424
|
+
const client = connect(server);
|
|
425
|
+
await client.peer.request("initialize", {});
|
|
426
|
+
await expect(client.peer.request("session/resume", { cwd: "/tmp/x" })).rejects.toThrow(/sessionId/);
|
|
427
|
+
});
|
|
428
|
+
|
|
374
429
|
it("rejects an unknown method with -32601", async () => {
|
|
375
430
|
const server = new AcpServer({ createHost: () => stubHost() });
|
|
376
431
|
const client = connect(server);
|
package/src/acp/protocol.ts
CHANGED
|
@@ -61,6 +61,8 @@ export interface InitializeResult {
|
|
|
61
61
|
agentCapabilities: {
|
|
62
62
|
loadSession: boolean;
|
|
63
63
|
promptCapabilities: { image: boolean; audio: boolean; embeddedContext: boolean };
|
|
64
|
+
/** `resume` present: the agent answers `session/resume`. */
|
|
65
|
+
sessionCapabilities: { resume: Record<string, never> };
|
|
64
66
|
};
|
|
65
67
|
authMethods: unknown[];
|
|
66
68
|
}
|
|
@@ -77,6 +79,17 @@ export interface NewSessionResult {
|
|
|
77
79
|
sessionId: string;
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
/** `session/resume` params: a session an earlier process opened, and the cwd to open it in. */
|
|
83
|
+
export interface ResumeSessionParams {
|
|
84
|
+
sessionId: string;
|
|
85
|
+
cwd?: string;
|
|
86
|
+
mcpServers?: unknown[];
|
|
87
|
+
_meta?: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** `session/resume` result. Nothing to report: there is no mode or model to restore. */
|
|
91
|
+
export type ResumeSessionResult = Record<string, never>;
|
|
92
|
+
|
|
80
93
|
/**
|
|
81
94
|
* The out-of-band bag a client attaches to `session/prompt` to resume a
|
|
82
95
|
* durable permission request (#2125). ACP's `_meta` is the extension point
|
package/src/acp/server.ts
CHANGED
|
@@ -46,6 +46,8 @@ import {
|
|
|
46
46
|
type PromptParams,
|
|
47
47
|
type PromptResult,
|
|
48
48
|
type RequestPermissionParams,
|
|
49
|
+
type ResumeSessionParams,
|
|
50
|
+
type ResumeSessionResult,
|
|
49
51
|
type RequestPermissionResult,
|
|
50
52
|
type SessionNotification,
|
|
51
53
|
type SessionUpdate,
|
|
@@ -125,6 +127,8 @@ export class AcpServer implements JsonRpcHandler {
|
|
|
125
127
|
return this.initialize((params ?? {}) as InitializeParams);
|
|
126
128
|
case "session/new":
|
|
127
129
|
return this.newSession((params ?? {}) as NewSessionParams);
|
|
130
|
+
case "session/resume":
|
|
131
|
+
return this.resumeSession((params ?? {}) as ResumeSessionParams);
|
|
128
132
|
case "session/prompt":
|
|
129
133
|
return this.enqueue(() => this.prompt((params ?? {}) as PromptParams));
|
|
130
134
|
default:
|
|
@@ -161,6 +165,11 @@ export class AcpServer implements JsonRpcHandler {
|
|
|
161
165
|
// directory and nothing else, so there is no transcript to replay
|
|
162
166
|
// that the run ledger does not already hold.
|
|
163
167
|
loadSession: false,
|
|
168
|
+
// `session/resume` is: fountain spawns `chant acp` afresh for every
|
|
169
|
+
// turn and resumes the conversation's session from the second turn
|
|
170
|
+
// on, and an agent that offers no way back in fails that turn
|
|
171
|
+
// before its prompt is sent.
|
|
172
|
+
sessionCapabilities: { resume: {} },
|
|
164
173
|
// A chant command line is text. Claiming otherwise would invite a
|
|
165
174
|
// client to send bytes this agent would have to drop.
|
|
166
175
|
promptCapabilities: { image: false, audio: false, embeddedContext: false },
|
|
@@ -172,15 +181,34 @@ export class AcpServer implements JsonRpcHandler {
|
|
|
172
181
|
}
|
|
173
182
|
|
|
174
183
|
private newSession(params: NewSessionParams): NewSessionResult {
|
|
175
|
-
const cwd = params.cwd && params.cwd.length > 0 ? params.cwd : process.cwd();
|
|
176
184
|
const id = randomUUID();
|
|
185
|
+
this.openSession(id, params.cwd);
|
|
186
|
+
return { sessionId: id };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Take up a session by the id a client already holds. A chant session is a
|
|
191
|
+
* working directory and nothing else, so one this process never opened —
|
|
192
|
+
* the usual case, since a client spawns a new process per turn — is opened
|
|
193
|
+
* again under the same id with the cwd the client sends. A gate a previous
|
|
194
|
+
* process asked about under `--durable-requests` is not carried over: its
|
|
195
|
+
* answer finds no request waiting and says to prompt the line again.
|
|
196
|
+
*/
|
|
197
|
+
private resumeSession(params: ResumeSessionParams): ResumeSessionResult {
|
|
198
|
+
if (typeof params.sessionId !== "string" || params.sessionId.length === 0) {
|
|
199
|
+
throw new JsonRpcError(JSONRPC_INVALID_PARAMS, "session/resume needs a sessionId");
|
|
200
|
+
}
|
|
201
|
+
if (!this.sessions.has(params.sessionId)) this.openSession(params.sessionId, params.cwd);
|
|
202
|
+
return {};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private openSession(id: string, cwd: string | undefined): void {
|
|
177
206
|
this.sessions.set(id, {
|
|
178
207
|
id,
|
|
179
|
-
host: this.createHost(cwd),
|
|
208
|
+
host: this.createHost(cwd && cwd.length > 0 ? cwd : process.cwd()),
|
|
180
209
|
permissions: new Map(),
|
|
181
210
|
earlyAnswers: new Map(),
|
|
182
211
|
});
|
|
183
|
-
return { sessionId: id };
|
|
184
212
|
}
|
|
185
213
|
|
|
186
214
|
private async prompt(params: PromptParams): Promise<PromptResult> {
|