@wrongstack/acp 0.293.0 → 0.295.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/README.md +22 -2
- package/dist/agent/protocol-contract.d.ts +210 -0
- package/dist/agent/protocol-contract.d.ts.map +1 -0
- package/dist/agent/protocol-handler.d.ts +15 -189
- package/dist/agent/protocol-handler.d.ts.map +1 -1
- package/dist/agent/server-agent-turn.d.ts +89 -1
- package/dist/agent/server-agent-turn.d.ts.map +1 -1
- package/dist/agent/session-store.d.ts.map +1 -1
- package/dist/agent/stdio-transport.d.ts +30 -1
- package/dist/agent/stdio-transport.d.ts.map +1 -1
- package/dist/agent/tools-registry.d.ts +1 -1
- package/dist/agent/tools-registry.d.ts.map +1 -1
- package/dist/agent/wrongstack-acp-agent.d.ts +37 -0
- package/dist/agent/wrongstack-acp-agent.d.ts.map +1 -1
- package/dist/agent.js +189 -32
- package/dist/agent.js.map +4 -4
- package/dist/client/acp-session.d.ts +13 -1
- package/dist/client/acp-session.d.ts.map +1 -1
- package/dist/client/file-server.d.ts +19 -0
- package/dist/client/file-server.d.ts.map +1 -1
- package/dist/client/index.d.ts +11 -9
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/terminal-server.d.ts +5 -0
- package/dist/client/terminal-server.d.ts.map +1 -1
- package/dist/client/tool-translator.d.ts +1 -1
- package/dist/client/tool-translator.d.ts.map +1 -1
- package/dist/client/trust-boundary-permission.d.ts +31 -0
- package/dist/client/trust-boundary-permission.d.ts.map +1 -0
- package/dist/client/websocket-transport.d.ts +6 -0
- package/dist/client/websocket-transport.d.ts.map +1 -1
- package/dist/client.js +459 -243
- package/dist/client.js.map +4 -4
- package/dist/index.d.ts +29 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2116 -1802
- package/dist/index.js.map +4 -4
- package/dist/integration/acp-bench.d.ts +32 -0
- package/dist/integration/acp-bench.d.ts.map +1 -1
- package/dist/integration/acp-subagent-runner.d.ts +3 -3
- package/dist/integration/acp-subagent-runner.d.ts.map +1 -1
- package/dist/integration/ensemble-runner.d.ts +22 -1
- package/dist/integration/ensemble-runner.d.ts.map +1 -1
- package/dist/legacy.d.ts +8 -0
- package/dist/legacy.d.ts.map +1 -0
- package/dist/legacy.js +6 -0
- package/dist/legacy.js.map +7 -0
- package/dist/registry/acp-registry-fetch.d.ts +1 -1
- package/dist/registry/acp-registry-fetch.d.ts.map +1 -1
- package/dist/registry/ensemble-registry.d.ts +22 -0
- package/dist/registry/ensemble-registry.d.ts.map +1 -1
- package/dist/sdk.d.ts +10 -8
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +22 -0
- package/dist/sdk.js.map +3 -3
- package/dist/v1.d.ts +3 -0
- package/dist/v1.d.ts.map +1 -0
- package/dist/v1.js +12 -0
- package/dist/v1.js.map +7 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/wrongstack-acp-agent.js +121 -24
- package/dist/wrongstack-acp-agent.js.map +4 -4
- package/package.json +10 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ACPMessage } from '../types/acp-messages.js';
|
|
2
|
+
declare function positiveLimit(value: number | undefined, fallback: number): number;
|
|
2
3
|
export interface AgentServerTransport {
|
|
3
4
|
send(msg: ACPMessage): Promise<void>;
|
|
4
5
|
sendRaw(chunk: string): void;
|
|
@@ -26,7 +27,12 @@ export declare class StdioTransport implements AgentServerTransport {
|
|
|
26
27
|
private closed;
|
|
27
28
|
private resolveRead;
|
|
28
29
|
private messageQueue;
|
|
29
|
-
|
|
30
|
+
private readonly maxFrameChars;
|
|
31
|
+
private readonly maxQueuedMessages;
|
|
32
|
+
constructor(opts?: {
|
|
33
|
+
maxFrameChars?: number;
|
|
34
|
+
maxQueuedMessages?: number;
|
|
35
|
+
});
|
|
30
36
|
sendStartupMarker(): void;
|
|
31
37
|
send(msg: ACPMessage): Promise<void>;
|
|
32
38
|
sendRaw(chunk: string): void;
|
|
@@ -52,6 +58,10 @@ export interface ClientTransportOptions {
|
|
|
52
58
|
* server-side transport (the default) keeps the marker check.
|
|
53
59
|
*/
|
|
54
60
|
skipHandshakeMarker?: boolean | undefined;
|
|
61
|
+
/** Maximum pending newline-delimited JSON frame size. Default 20 MiB. */
|
|
62
|
+
maxFrameChars?: number | undefined;
|
|
63
|
+
/** Maximum messages retained for the optional read() API. Default 1000. */
|
|
64
|
+
maxQueuedMessages?: number | undefined;
|
|
55
65
|
}
|
|
56
66
|
export interface ACPChildProcess extends EventEmitter {
|
|
57
67
|
stdout: NodeJS.ReadableStream;
|
|
@@ -68,6 +78,8 @@ export declare class ClientTransport implements ACPClientTransport {
|
|
|
68
78
|
private resolveRead;
|
|
69
79
|
private messageQueue;
|
|
70
80
|
private readonly opts;
|
|
81
|
+
private readonly maxFrameChars;
|
|
82
|
+
private readonly maxQueuedMessages;
|
|
71
83
|
constructor(options: ClientTransportOptions);
|
|
72
84
|
start(): Promise<void>;
|
|
73
85
|
send(msg: ACPMessage): Promise<void>;
|
|
@@ -79,4 +91,21 @@ export declare class ClientTransport implements ACPClientTransport {
|
|
|
79
91
|
private onChildClose;
|
|
80
92
|
private dispatch;
|
|
81
93
|
}
|
|
94
|
+
declare function spawnInvocation(command: string, args: string[], platform: NodeJS.Platform): {
|
|
95
|
+
command: string;
|
|
96
|
+
args: string[];
|
|
97
|
+
windowsVerbatimArguments?: true;
|
|
98
|
+
};
|
|
99
|
+
declare function verbatimOptions(invocation: {
|
|
100
|
+
windowsVerbatimArguments?: true;
|
|
101
|
+
}): {
|
|
102
|
+
windowsVerbatimArguments?: true;
|
|
103
|
+
};
|
|
104
|
+
/** Direct-module test seam; not re-exported by the package barrel. */
|
|
105
|
+
export declare const stdioTransportCoverage: {
|
|
106
|
+
positiveLimit: typeof positiveLimit;
|
|
107
|
+
spawnInvocation: typeof spawnInvocation;
|
|
108
|
+
verbatimOptions: typeof verbatimOptions;
|
|
109
|
+
};
|
|
110
|
+
export {};
|
|
82
111
|
//# sourceMappingURL=stdio-transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio-transport.d.ts","sourceRoot":"","sources":["../../src/agent/stdio-transport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stdio-transport.d.ts","sourceRoot":"","sources":["../../src/agent/stdio-transport.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAM3D,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;IACd,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC3D;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC1D,IAAI,IAAI,IAAI,CAAC;CACd;AAED,qBAAa,cAAe,YAAW,oBAAoB;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAE3C,YAAY,IAAI,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAO,EAQ5E;IAED,iBAAiB,IAAI,IAAI,CAExB;IAED,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnC;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE3B;IAED,IAAI,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAOjC;IAED,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAGxD;IAED,KAAK,IAAI,IAAI,CAQZ;IAED,OAAO,CAAC,MAAM;IAgCd,OAAO,CAAC,QAAQ;IAyBhB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,OAAO;CAIhB;AAMD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,IAAI,IAAI,CAAC;CACd;AAED,qBAAa,eAAgB,YAAW,kBAAkB;IACxD,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CACI;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAE3C,YAAY,OAAO,EAAE,sBAAsB,EAO1C;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAuG3B;IAED,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CASnC;IAED,IAAI,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAOjC;IAED,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI,CAGxD;IAED,IAAI,IAAI,IAAI,CAaX;IAED,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,QAAQ;CAqBjB;AAED,iBAAS,eAAe,CACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,CAAC,QAAQ,GACxB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wBAAwB,CAAC,EAAE,IAAI,CAAC;CACjC,CAGA;AAED,iBAAS,eAAe,CAAC,UAAU,EAAE;IAAE,wBAAwB,CAAC,EAAE,IAAI,CAAA;CAAE,GAAG;IACzE,wBAAwB,CAAC,EAAE,IAAI,CAAC;CACjC,CAIA;AAED,sEAAsE;AACtE,eAAO,MAAM,sBAAsB;;;;CAAsD,CAAC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Translates WrongStack Tool definitions → ACP ACPToolDefinition format.
|
|
5
5
|
* Provides tool lookup and result assembly for the ACP protocol handler.
|
|
6
6
|
*/
|
|
7
|
-
import type { Tool } from '@wrongstack/core';
|
|
7
|
+
import type { Tool } from '@wrongstack/core/types';
|
|
8
8
|
import type { ACPToolList, ACPToolResult } from '../types/acp-messages.js';
|
|
9
9
|
export declare class ACPToolsRegistry {
|
|
10
10
|
private tools;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools-registry.d.ts","sourceRoot":"","sources":["../../src/agent/tools-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"tools-registry.d.ts","sourceRoot":"","sources":["../../src/agent/tools-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAEV,WAAW,EAEX,aAAa,EAEd,MAAM,0BAA0B,CAAC;AAElC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,YAAY,KAAK,SAAe,EAE/B;IAED;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAI5B;IAED;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAG5B;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAElC;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,IAAI,IAAI,IAAI,EAAE,CAEb;IAED,8DAA8D;IAC9D,aAAa,IAAI,WAAW,CAM3B;IAED;;;OAGG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAa/B;CACF"}
|
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WrongStackACPServer — ACP v1 server-side entry point.
|
|
3
|
+
*
|
|
4
|
+
* Exposes WrongStack as an ACP-compatible agent. ACP clients (Zed, JetBrains
|
|
5
|
+
* Junie, VS Code ACP extension) spawn this as a subprocess, send JSON-RPC
|
|
6
|
+
* messages over stdio, and receive v1-protocol responses.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node dist/agent/wrongstack-acp-agent.js
|
|
10
|
+
*
|
|
11
|
+
* Or via the CLI:
|
|
12
|
+
* wstack acp-server
|
|
13
|
+
*
|
|
14
|
+
* Wiring a real agent: this class is the surface; the bootstrap
|
|
15
|
+
* binary uses a no-op echo by default so the binary is a useful
|
|
16
|
+
* connectivity smoke test. For a real server, instantiate
|
|
17
|
+
* `WrongStackACPServer` programmatically and pass a `runTurn`
|
|
18
|
+
* produced by `makeACPServerAgentTurn({ agentFor: ... })` from
|
|
19
|
+
* `./server-agent-turn.js`. The factory is responsible for building
|
|
20
|
+
* a real core `Agent` (with the right provider, model, system prompt,
|
|
21
|
+
* etc.) per session.
|
|
22
|
+
*
|
|
23
|
+
* Startup: stdout is JSON-RPC only by default. The legacy `[wstack-acp]\n`
|
|
24
|
+
* marker can be enabled for older internal harnesses with
|
|
25
|
+
* `legacyStartupMarker`, but ACP clients should rely on v1 initialize.
|
|
26
|
+
*/
|
|
1
27
|
import { type RunTurn, type SessionPersistence } from './protocol-handler.js';
|
|
2
28
|
export interface WrongStackACPServerOptions {
|
|
3
29
|
runTurn?: RunTurn | undefined;
|
|
@@ -37,6 +63,8 @@ export interface WrongStackACPServerOptions {
|
|
|
37
63
|
sessionUpdate: string;
|
|
38
64
|
content: unknown;
|
|
39
65
|
}>) => void) | undefined;
|
|
66
|
+
/** Per-session cleanup hook, normally `makeACPServerAgentTurn(...).dispose`. */
|
|
67
|
+
disposeFor?: ((sessionId: string) => void) | undefined;
|
|
40
68
|
/**
|
|
41
69
|
* Durable session store. When set, sessions + history are persisted and
|
|
42
70
|
* restored across restarts for `session/load`. Pass an `ACPSessionStore`.
|
|
@@ -62,4 +90,13 @@ export declare class WrongStackACPServer {
|
|
|
62
90
|
/** Stop the server. */
|
|
63
91
|
stop(): void;
|
|
64
92
|
}
|
|
93
|
+
declare function headerValue(value: string | string[] | undefined): string | undefined;
|
|
94
|
+
declare function requestPath(value: string | undefined): string;
|
|
95
|
+
/** Direct-module test seam; not re-exported by the package barrel. */
|
|
96
|
+
export declare const wrongStackACPServerCoverage: {
|
|
97
|
+
defaultEchoRunTurn: RunTurn;
|
|
98
|
+
headerValue: typeof headerValue;
|
|
99
|
+
requestPath: typeof requestPath;
|
|
100
|
+
};
|
|
101
|
+
export {};
|
|
65
102
|
//# sourceMappingURL=wrongstack-acp-agent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrongstack-acp-agent.d.ts","sourceRoot":"","sources":["../../src/agent/wrongstack-acp-agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wrongstack-acp-agent.d.ts","sourceRoot":"","sources":["../../src/agent/wrongstack-acp-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAG/B,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C;;;;OAIG;IACH,SAAS,CAAC,EACN,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,GAC3E,SAAS,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EACJ,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC,GAC1F,SAAS,CAAC;IACd,gFAAgF;IAChF,UAAU,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACvD;;;OAGG;IACH,KAAK,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACxC;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,+CAA+C;IAC/C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,IAAI,GAAE,0BAA+B,EAchD;IAED;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAO3B;YAEa,UAAU;YAkBV,SAAS;IA4JvB,uBAAuB;IACvB,IAAI,IAAI,IAAI,CAQX;CACF;AAaD,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEtD;AAED,sEAAsE;AACtE,eAAO,MAAM,2BAA2B;;;;CAAmD,CAAC"}
|
package/dist/agent.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// src/agent/stdio-transport.ts
|
|
2
|
-
import { expectDefined, writeErr } from "@wrongstack/core";
|
|
2
|
+
import { expectDefined, writeErr } from "@wrongstack/core/utils";
|
|
3
|
+
import { treeKill } from "@wrongstack/core/utils/tree-kill";
|
|
4
|
+
var DEFAULT_MAX_FRAME_CHARS = 20 * 1024 * 1024;
|
|
5
|
+
var DEFAULT_MAX_QUEUED_MESSAGES = 1e3;
|
|
6
|
+
function positiveLimit(value, fallback) {
|
|
7
|
+
return value !== void 0 && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
8
|
+
}
|
|
3
9
|
var StdioTransport = class {
|
|
4
10
|
stdin = process.stdin;
|
|
5
11
|
stdout = process.stdout;
|
|
@@ -9,7 +15,11 @@ var StdioTransport = class {
|
|
|
9
15
|
closed = false;
|
|
10
16
|
resolveRead = null;
|
|
11
17
|
messageQueue = [];
|
|
12
|
-
|
|
18
|
+
maxFrameChars;
|
|
19
|
+
maxQueuedMessages;
|
|
20
|
+
constructor(opts = {}) {
|
|
21
|
+
this.maxFrameChars = positiveLimit(opts.maxFrameChars, DEFAULT_MAX_FRAME_CHARS);
|
|
22
|
+
this.maxQueuedMessages = positiveLimit(opts.maxQueuedMessages, DEFAULT_MAX_QUEUED_MESSAGES);
|
|
13
23
|
this.stdin.resume();
|
|
14
24
|
this.stdin.setEncoding("utf8");
|
|
15
25
|
this.stdin.on("data", (chunk) => this.onData(chunk));
|
|
@@ -30,7 +40,8 @@ var StdioTransport = class {
|
|
|
30
40
|
this.stdout.write(chunk, "utf8");
|
|
31
41
|
}
|
|
32
42
|
read() {
|
|
33
|
-
if (this.messageQueue.length > 0)
|
|
43
|
+
if (this.messageQueue.length > 0)
|
|
44
|
+
return Promise.resolve(expectDefined(this.messageQueue.shift()));
|
|
34
45
|
if (this.closed) return Promise.resolve(null);
|
|
35
46
|
return new Promise((resolve) => {
|
|
36
47
|
this.resolveRead = resolve;
|
|
@@ -45,13 +56,34 @@ var StdioTransport = class {
|
|
|
45
56
|
this.stdin.pause();
|
|
46
57
|
this.resolveRead?.(null);
|
|
47
58
|
this.resolveRead = null;
|
|
59
|
+
this.buffer = "";
|
|
60
|
+
this.messageQueue.length = 0;
|
|
61
|
+
this.handlers.clear();
|
|
48
62
|
}
|
|
49
63
|
onData(chunk) {
|
|
50
64
|
this.buffer += chunk;
|
|
51
65
|
const lines = this.buffer.split("\n");
|
|
52
66
|
this.buffer = lines.pop() ?? "";
|
|
67
|
+
if (this.buffer.length > this.maxFrameChars) {
|
|
68
|
+
this.stderr.write(
|
|
69
|
+
`[wstack-acp frame error] pending frame exceeds ${this.maxFrameChars} characters
|
|
70
|
+
`,
|
|
71
|
+
"utf8"
|
|
72
|
+
);
|
|
73
|
+
this.close();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
53
76
|
for (const raw of lines) {
|
|
54
77
|
if (!raw.trim()) continue;
|
|
78
|
+
if (raw.length > this.maxFrameChars) {
|
|
79
|
+
this.stderr.write(
|
|
80
|
+
`[wstack-acp frame error] frame exceeds ${this.maxFrameChars} characters
|
|
81
|
+
`,
|
|
82
|
+
"utf8"
|
|
83
|
+
);
|
|
84
|
+
this.close();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
55
87
|
try {
|
|
56
88
|
this.dispatch(JSON.parse(raw));
|
|
57
89
|
} catch (err) {
|
|
@@ -66,6 +98,15 @@ var StdioTransport = class {
|
|
|
66
98
|
this.resolveRead = null;
|
|
67
99
|
resolve(msg);
|
|
68
100
|
} else {
|
|
101
|
+
if (this.messageQueue.length >= this.maxQueuedMessages) {
|
|
102
|
+
this.stderr.write(
|
|
103
|
+
`[wstack-acp queue error] pending message queue exceeds ${this.maxQueuedMessages} entries
|
|
104
|
+
`,
|
|
105
|
+
"utf8"
|
|
106
|
+
);
|
|
107
|
+
this.close();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
69
110
|
this.messageQueue.push(msg);
|
|
70
111
|
}
|
|
71
112
|
for (const handler of this.handlers) {
|
|
@@ -78,9 +119,7 @@ var StdioTransport = class {
|
|
|
78
119
|
}
|
|
79
120
|
}
|
|
80
121
|
handleClose() {
|
|
81
|
-
this.
|
|
82
|
-
this.resolveRead?.(null);
|
|
83
|
-
this.resolveRead = null;
|
|
122
|
+
this.close();
|
|
84
123
|
}
|
|
85
124
|
failAll(err) {
|
|
86
125
|
this.stderr.write(`[wstack-acp stdin error] ${err.message}
|
|
@@ -206,11 +245,28 @@ function toolToPriority(tool) {
|
|
|
206
245
|
// src/types/acp-v1.ts
|
|
207
246
|
var ACP_PROTOCOL_VERSION = 1;
|
|
208
247
|
|
|
209
|
-
// src/
|
|
248
|
+
// src/version.ts
|
|
249
|
+
import { createRequire } from "node:module";
|
|
250
|
+
var require2 = createRequire(import.meta.url);
|
|
251
|
+
function readPackageVersion(load = () => require2("../package.json")) {
|
|
252
|
+
try {
|
|
253
|
+
const packageJson = load();
|
|
254
|
+
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
255
|
+
return packageJson.version;
|
|
256
|
+
}
|
|
257
|
+
} catch {
|
|
258
|
+
}
|
|
259
|
+
return "dev";
|
|
260
|
+
}
|
|
261
|
+
var ACP_PACKAGE_VERSION = readPackageVersion();
|
|
262
|
+
|
|
263
|
+
// src/agent/protocol-contract.ts
|
|
210
264
|
function toWire(msg) {
|
|
211
265
|
return msg;
|
|
212
266
|
}
|
|
213
|
-
var WRONGSTACK_VERSION =
|
|
267
|
+
var WRONGSTACK_VERSION = ACP_PACKAGE_VERSION;
|
|
268
|
+
|
|
269
|
+
// src/agent/protocol-handler.ts
|
|
214
270
|
var WRONGSTACK_AUTH_METHODS = [
|
|
215
271
|
{
|
|
216
272
|
id: "wrongstack-auth",
|
|
@@ -221,6 +277,7 @@ var WRONGSTACK_AUTH_METHODS = [
|
|
|
221
277
|
}
|
|
222
278
|
];
|
|
223
279
|
var DEFAULT_MODE_ID = "code";
|
|
280
|
+
var DEFAULT_MAX_SESSIONS = 64;
|
|
224
281
|
var DEFAULT_MODES = [
|
|
225
282
|
{
|
|
226
283
|
id: DEFAULT_MODE_ID,
|
|
@@ -238,6 +295,8 @@ var ACPProtocolHandler = class {
|
|
|
238
295
|
agentName;
|
|
239
296
|
replayFor;
|
|
240
297
|
seedFor;
|
|
298
|
+
disposeFor;
|
|
299
|
+
maxSessions;
|
|
241
300
|
store;
|
|
242
301
|
initialized = false;
|
|
243
302
|
clientCapabilities = {};
|
|
@@ -258,6 +317,8 @@ var ACPProtocolHandler = class {
|
|
|
258
317
|
this.agentName = opts.agentName ?? "wrongstack";
|
|
259
318
|
this.replayFor = opts.replayFor;
|
|
260
319
|
this.seedFor = opts.seedFor;
|
|
320
|
+
this.disposeFor = opts.disposeFor;
|
|
321
|
+
this.maxSessions = Number.isFinite(opts.maxSessions) && opts.maxSessions > 0 ? Math.floor(opts.maxSessions) : DEFAULT_MAX_SESSIONS;
|
|
261
322
|
this.store = opts.store;
|
|
262
323
|
if (typeof this.transport.onMessage === "function") {
|
|
263
324
|
this.transport.onMessage((m) => this.maybeResolvePending(m));
|
|
@@ -315,8 +376,9 @@ var ACPProtocolHandler = class {
|
|
|
315
376
|
}
|
|
316
377
|
/** Abort all active turns and drop session state. */
|
|
317
378
|
close() {
|
|
318
|
-
for (const [, session] of this.sessions) {
|
|
379
|
+
for (const [sessionId, session] of this.sessions) {
|
|
319
380
|
session.abort.abort();
|
|
381
|
+
this.disposeSession(sessionId);
|
|
320
382
|
}
|
|
321
383
|
this.sessions.clear();
|
|
322
384
|
for (const [, p] of this.pendingOut) {
|
|
@@ -325,6 +387,12 @@ var ACPProtocolHandler = class {
|
|
|
325
387
|
}
|
|
326
388
|
this.pendingOut.clear();
|
|
327
389
|
}
|
|
390
|
+
disposeSession(sessionId) {
|
|
391
|
+
try {
|
|
392
|
+
this.disposeFor?.(sessionId);
|
|
393
|
+
} catch {
|
|
394
|
+
}
|
|
395
|
+
}
|
|
328
396
|
// ────────────────────────────────────────────────────────────────────
|
|
329
397
|
// Requests
|
|
330
398
|
// ────────────────────────────────────────────────────────────────────
|
|
@@ -444,6 +512,10 @@ var ACPProtocolHandler = class {
|
|
|
444
512
|
return false;
|
|
445
513
|
}
|
|
446
514
|
async handleSessionNew(id, params) {
|
|
515
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
516
|
+
await this.sendError(id, -32e3, `active session limit reached (${this.maxSessions})`);
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
447
519
|
const p = params ?? {};
|
|
448
520
|
const cwd = typeof p.cwd === "string" ? p.cwd : this.defaultCwd;
|
|
449
521
|
const sessionId = `sess_${this.allocId()}`;
|
|
@@ -494,6 +566,10 @@ var ACPProtocolHandler = class {
|
|
|
494
566
|
if (!existing && sessionId && this.store) {
|
|
495
567
|
const persisted = await this.store.load(sessionId);
|
|
496
568
|
if (persisted) {
|
|
569
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
570
|
+
await this.sendError(id, -32e3, `active session limit reached (${this.maxSessions})`);
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
497
573
|
const restored = {
|
|
498
574
|
id: sessionId,
|
|
499
575
|
cwd: persisted.cwd ?? loadCwd ?? this.defaultCwd,
|
|
@@ -524,7 +600,7 @@ var ACPProtocolHandler = class {
|
|
|
524
600
|
}
|
|
525
601
|
if (existing) {
|
|
526
602
|
existing.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
527
|
-
const replay =
|
|
603
|
+
const replay = this.replayFor?.(sessionId);
|
|
528
604
|
if (replay) {
|
|
529
605
|
for (const update of replay) {
|
|
530
606
|
await this.sendNotification({ sessionId, update });
|
|
@@ -589,7 +665,8 @@ var ACPProtocolHandler = class {
|
|
|
589
665
|
return false;
|
|
590
666
|
}
|
|
591
667
|
session.abort.abort();
|
|
592
|
-
|
|
668
|
+
this.sessions.delete(sessionId);
|
|
669
|
+
this.disposeSession(sessionId);
|
|
593
670
|
await this.transport.send(toWire({
|
|
594
671
|
jsonrpc: "2.0",
|
|
595
672
|
id,
|
|
@@ -611,6 +688,7 @@ var ACPProtocolHandler = class {
|
|
|
611
688
|
const session = this.sessions.get(sessionId);
|
|
612
689
|
session.abort.abort();
|
|
613
690
|
this.sessions.delete(sessionId);
|
|
691
|
+
this.disposeSession(sessionId);
|
|
614
692
|
await this.transport.send(toWire({
|
|
615
693
|
jsonrpc: "2.0",
|
|
616
694
|
id,
|
|
@@ -626,6 +704,10 @@ var ACPProtocolHandler = class {
|
|
|
626
704
|
await this.sendError(id, -32e3, `session not found: ${sourceId}`);
|
|
627
705
|
return false;
|
|
628
706
|
}
|
|
707
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
708
|
+
await this.sendError(id, -32e3, `active session limit reached (${this.maxSessions})`);
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
629
711
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
630
712
|
const sessionId = `sess_${this.allocId()}`;
|
|
631
713
|
const forked = {
|
|
@@ -919,8 +1001,10 @@ var ACPSessionStore = class {
|
|
|
919
1001
|
*/
|
|
920
1002
|
async save(state, history) {
|
|
921
1003
|
await this.init();
|
|
1004
|
+
const target = path.join(this.dir, `${state.id}.json`);
|
|
1005
|
+
const tmp = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
922
1006
|
await fsp.writeFile(
|
|
923
|
-
|
|
1007
|
+
tmp,
|
|
924
1008
|
JSON.stringify({
|
|
925
1009
|
id: state.id,
|
|
926
1010
|
cwd: state.cwd,
|
|
@@ -932,6 +1016,7 @@ var ACPSessionStore = class {
|
|
|
932
1016
|
}),
|
|
933
1017
|
"utf8"
|
|
934
1018
|
);
|
|
1019
|
+
await fsp.rename(tmp, target);
|
|
935
1020
|
await this.updateIndex(state.id, state.updatedAt);
|
|
936
1021
|
return state.id;
|
|
937
1022
|
}
|
|
@@ -1092,9 +1177,9 @@ var WsBridgeTransport = class {
|
|
|
1092
1177
|
};
|
|
1093
1178
|
|
|
1094
1179
|
// src/agent/wrongstack-acp-agent.ts
|
|
1095
|
-
import { fileURLToPath } from "node:url";
|
|
1096
1180
|
import { createServer } from "node:http";
|
|
1097
|
-
import {
|
|
1181
|
+
import { fileURLToPath } from "node:url";
|
|
1182
|
+
import { writeErr as writeErr2 } from "@wrongstack/core/utils";
|
|
1098
1183
|
var WrongStackACPServer = class {
|
|
1099
1184
|
transport;
|
|
1100
1185
|
handler;
|
|
@@ -1113,6 +1198,7 @@ var WrongStackACPServer = class {
|
|
|
1113
1198
|
agentName: opts.agentName,
|
|
1114
1199
|
...opts.replayFor ? { replayFor: opts.replayFor } : {},
|
|
1115
1200
|
...opts.seedFor ? { seedFor: opts.seedFor } : {},
|
|
1201
|
+
...opts.disposeFor ? { disposeFor: opts.disposeFor } : {},
|
|
1116
1202
|
...opts.store ? { store: opts.store } : {}
|
|
1117
1203
|
});
|
|
1118
1204
|
}
|
|
@@ -1134,13 +1220,17 @@ var WrongStackACPServer = class {
|
|
|
1134
1220
|
this.transport.sendStartupMarker();
|
|
1135
1221
|
}
|
|
1136
1222
|
this.running = true;
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1223
|
+
try {
|
|
1224
|
+
while (this.running) {
|
|
1225
|
+
const msg = await this.transport.read();
|
|
1226
|
+
if (!msg) break;
|
|
1227
|
+
const terminal = await this.handler.handleMessage(msg);
|
|
1228
|
+
if (terminal) break;
|
|
1229
|
+
}
|
|
1230
|
+
} finally {
|
|
1231
|
+
this.handler.close();
|
|
1232
|
+
this.transport.close();
|
|
1142
1233
|
}
|
|
1143
|
-
this.transport.close();
|
|
1144
1234
|
}
|
|
1145
1235
|
async startHttp(port) {
|
|
1146
1236
|
const host = this.options.host ?? "127.0.0.1";
|
|
@@ -1149,10 +1239,9 @@ var WrongStackACPServer = class {
|
|
|
1149
1239
|
let httpChain = Promise.resolve();
|
|
1150
1240
|
this.httpServer = createServer(async (req, res) => {
|
|
1151
1241
|
if (authToken) {
|
|
1152
|
-
const url = new URL(req.url
|
|
1242
|
+
const url = new URL(requestPath(req.url), `http://${host}:${port}`);
|
|
1153
1243
|
const queryToken = url.searchParams.get("token");
|
|
1154
|
-
const
|
|
1155
|
-
const bearerToken = Array.isArray(authHeader) ? authHeader[0]?.replace(/^Bearer\s+/i, "") : authHeader?.replace(/^Bearer\s+/i, "");
|
|
1244
|
+
const bearerToken = headerValue(req.headers.authorization)?.replace(/^Bearer\s+/i, "");
|
|
1156
1245
|
const supplied = queryToken ?? bearerToken ?? "";
|
|
1157
1246
|
if (supplied !== authToken) {
|
|
1158
1247
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
@@ -1161,7 +1250,7 @@ var WrongStackACPServer = class {
|
|
|
1161
1250
|
}
|
|
1162
1251
|
}
|
|
1163
1252
|
const selfOrigin = `http://${host}:${port}`;
|
|
1164
|
-
const reqOrigin =
|
|
1253
|
+
const reqOrigin = headerValue(req.headers.origin);
|
|
1165
1254
|
if (reqOrigin && reqOrigin !== selfOrigin) {
|
|
1166
1255
|
res.writeHead(403);
|
|
1167
1256
|
res.end(JSON.stringify({ error: "cross-origin request forbidden" }));
|
|
@@ -1241,6 +1330,8 @@ var WrongStackACPServer = class {
|
|
|
1241
1330
|
try {
|
|
1242
1331
|
await requestPromise;
|
|
1243
1332
|
} catch {
|
|
1333
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1334
|
+
res.end(JSON.stringify({ error: { code: -32603, message: "Internal error" } }));
|
|
1244
1335
|
}
|
|
1245
1336
|
});
|
|
1246
1337
|
return new Promise((resolve) => {
|
|
@@ -1255,6 +1346,7 @@ var WrongStackACPServer = class {
|
|
|
1255
1346
|
/** Stop the server. */
|
|
1256
1347
|
stop() {
|
|
1257
1348
|
this.running = false;
|
|
1349
|
+
this.handler.close();
|
|
1258
1350
|
this.transport.close();
|
|
1259
1351
|
if (this.httpServer) {
|
|
1260
1352
|
this.httpServer.close();
|
|
@@ -1265,6 +1357,12 @@ var WrongStackACPServer = class {
|
|
|
1265
1357
|
var defaultEchoRunTurn = async (_input, _emit) => {
|
|
1266
1358
|
return { stopReason: "end_turn" };
|
|
1267
1359
|
};
|
|
1360
|
+
function headerValue(value) {
|
|
1361
|
+
return Array.isArray(value) ? value[0] : value;
|
|
1362
|
+
}
|
|
1363
|
+
function requestPath(value) {
|
|
1364
|
+
return value ?? "/";
|
|
1365
|
+
}
|
|
1268
1366
|
async function main() {
|
|
1269
1367
|
const server = new WrongStackACPServer();
|
|
1270
1368
|
await server.start();
|
|
@@ -1283,8 +1381,11 @@ function makeACPServerAgentTurn(opts) {
|
|
|
1283
1381
|
const agents = /* @__PURE__ */ new Map();
|
|
1284
1382
|
const timeouts = /* @__PURE__ */ new Map();
|
|
1285
1383
|
const history = /* @__PURE__ */ new Map();
|
|
1384
|
+
const historyBytes = /* @__PURE__ */ new Map();
|
|
1286
1385
|
const pendingSeed = /* @__PURE__ */ new Set();
|
|
1287
1386
|
const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
|
|
1387
|
+
const maxHistoryEntries = finitePositiveLimit(opts.maxHistoryEntries, 1e3);
|
|
1388
|
+
const maxHistoryBytes = finitePositiveLimit(opts.maxHistoryBytes, 8 * 1024 * 1024);
|
|
1288
1389
|
const turn = async (input, emit, api) => {
|
|
1289
1390
|
let agent = agents.get(input.sessionId);
|
|
1290
1391
|
if (!agent) {
|
|
@@ -1292,7 +1393,7 @@ function makeACPServerAgentTurn(opts) {
|
|
|
1292
1393
|
agents.set(input.sessionId, agent);
|
|
1293
1394
|
if (pendingSeed.has(input.sessionId)) {
|
|
1294
1395
|
pendingSeed.delete(input.sessionId);
|
|
1295
|
-
seedAgentContext(agent, history.get(input.sessionId)
|
|
1396
|
+
seedAgentContext(agent, history.get(input.sessionId));
|
|
1296
1397
|
}
|
|
1297
1398
|
}
|
|
1298
1399
|
const turnAbort = new AbortController();
|
|
@@ -1348,13 +1449,36 @@ function makeACPServerAgentTurn(opts) {
|
|
|
1348
1449
|
}
|
|
1349
1450
|
const userText = promptToText(input.prompt);
|
|
1350
1451
|
const hist = history.get(input.sessionId) ?? [];
|
|
1452
|
+
let retainedHistoryBytes = historyBytes.get(input.sessionId) ?? 0;
|
|
1351
1453
|
if (userText) {
|
|
1352
|
-
|
|
1454
|
+
const update = {
|
|
1455
|
+
sessionUpdate: "user_message_chunk",
|
|
1456
|
+
content: { type: "text", text: userText }
|
|
1457
|
+
};
|
|
1458
|
+
hist.push(update);
|
|
1459
|
+
retainedHistoryBytes += replayEntryBytes(update);
|
|
1353
1460
|
}
|
|
1354
1461
|
if (text) {
|
|
1355
|
-
|
|
1462
|
+
const update = {
|
|
1463
|
+
sessionUpdate: "agent_message_chunk",
|
|
1464
|
+
content: { type: "text", text }
|
|
1465
|
+
};
|
|
1466
|
+
hist.push(update);
|
|
1467
|
+
retainedHistoryBytes += replayEntryBytes(update);
|
|
1468
|
+
}
|
|
1469
|
+
retainedHistoryBytes = trimHistory(
|
|
1470
|
+
hist,
|
|
1471
|
+
retainedHistoryBytes,
|
|
1472
|
+
maxHistoryEntries,
|
|
1473
|
+
maxHistoryBytes
|
|
1474
|
+
);
|
|
1475
|
+
if (hist.length > 0) {
|
|
1476
|
+
history.set(input.sessionId, hist);
|
|
1477
|
+
historyBytes.set(input.sessionId, retainedHistoryBytes);
|
|
1478
|
+
} else {
|
|
1479
|
+
history.delete(input.sessionId);
|
|
1480
|
+
historyBytes.delete(input.sessionId);
|
|
1356
1481
|
}
|
|
1357
|
-
if (hist.length > 0) history.set(input.sessionId, hist);
|
|
1358
1482
|
const plan = extractPlan(result);
|
|
1359
1483
|
if (plan.length > 0) {
|
|
1360
1484
|
emit({
|
|
@@ -1388,13 +1512,46 @@ function makeACPServerAgentTurn(opts) {
|
|
|
1388
1512
|
for (const u of unsub) u();
|
|
1389
1513
|
}
|
|
1390
1514
|
};
|
|
1391
|
-
const replay = (sessionId) =>
|
|
1515
|
+
const replay = (sessionId) => [
|
|
1516
|
+
...history.get(sessionId) ?? []
|
|
1517
|
+
];
|
|
1392
1518
|
const seed = (sessionId, incoming) => {
|
|
1393
1519
|
if (incoming.length === 0) return;
|
|
1394
|
-
|
|
1520
|
+
const seeded = [...incoming];
|
|
1521
|
+
const retainedBytes = trimHistory(
|
|
1522
|
+
seeded,
|
|
1523
|
+
seeded.reduce((total, entry) => total + replayEntryBytes(entry), 0),
|
|
1524
|
+
maxHistoryEntries,
|
|
1525
|
+
maxHistoryBytes
|
|
1526
|
+
);
|
|
1527
|
+
history.set(sessionId, seeded);
|
|
1528
|
+
historyBytes.set(sessionId, retainedBytes);
|
|
1395
1529
|
pendingSeed.add(sessionId);
|
|
1396
1530
|
};
|
|
1397
|
-
|
|
1531
|
+
const dispose = (sessionId) => {
|
|
1532
|
+
const timer = timeouts.get(sessionId);
|
|
1533
|
+
if (timer) clearTimeout(timer);
|
|
1534
|
+
timeouts.delete(sessionId);
|
|
1535
|
+
agents.delete(sessionId);
|
|
1536
|
+
history.delete(sessionId);
|
|
1537
|
+
historyBytes.delete(sessionId);
|
|
1538
|
+
pendingSeed.delete(sessionId);
|
|
1539
|
+
};
|
|
1540
|
+
return Object.assign(turn, { replay, seed, dispose });
|
|
1541
|
+
}
|
|
1542
|
+
function finitePositiveLimit(value, fallback) {
|
|
1543
|
+
return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
1544
|
+
}
|
|
1545
|
+
function trimHistory(entries, retainedBytes, maxEntries, maxBytes) {
|
|
1546
|
+
while (entries.length > maxEntries || retainedBytes > maxBytes) {
|
|
1547
|
+
const removed = entries.shift();
|
|
1548
|
+
if (!removed) break;
|
|
1549
|
+
retainedBytes -= replayEntryBytes(removed);
|
|
1550
|
+
}
|
|
1551
|
+
return Math.max(0, retainedBytes);
|
|
1552
|
+
}
|
|
1553
|
+
function replayEntryBytes(entry) {
|
|
1554
|
+
return Buffer.byteLength(JSON.stringify(entry), "utf8");
|
|
1398
1555
|
}
|
|
1399
1556
|
function seedAgentContext(agent, history) {
|
|
1400
1557
|
const state = agent.ctx?.state;
|
|
@@ -1410,7 +1567,7 @@ function toolNameToKind(name) {
|
|
|
1410
1567
|
const n = name.toLowerCase();
|
|
1411
1568
|
if (n.includes("read") || n.includes("cat")) return "read";
|
|
1412
1569
|
if (n.includes("write") || n.includes("edit") || n.includes("apply") || n.includes("patch")) return "edit";
|
|
1413
|
-
if (n.includes("delete") || n.
|
|
1570
|
+
if (n.includes("delete") || n === "rm" || n.startsWith("rm_") || n.endsWith("_rm")) return "delete";
|
|
1414
1571
|
if (n.includes("move") || n.includes("rename") || n.includes("mv")) return "move";
|
|
1415
1572
|
if (n.includes("grep") || n.includes("glob") || n.includes("search") || n.includes("find")) return "search";
|
|
1416
1573
|
if (n.includes("bash") || n.includes("shell") || n.includes("exec") || n.includes("run") || n.includes("terminal")) return "execute";
|