@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,16 +1,33 @@
|
|
|
1
1
|
// src/agent/wrongstack-acp-agent.ts
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
2
|
import { createServer } from "node:http";
|
|
4
|
-
import {
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { writeErr as writeErr2 } from "@wrongstack/core/utils";
|
|
5
5
|
|
|
6
6
|
// src/types/acp-v1.ts
|
|
7
7
|
var ACP_PROTOCOL_VERSION = 1;
|
|
8
8
|
|
|
9
|
-
// src/
|
|
9
|
+
// src/version.ts
|
|
10
|
+
import { createRequire } from "node:module";
|
|
11
|
+
var require2 = createRequire(import.meta.url);
|
|
12
|
+
function readPackageVersion(load = () => require2("../package.json")) {
|
|
13
|
+
try {
|
|
14
|
+
const packageJson = load();
|
|
15
|
+
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
16
|
+
return packageJson.version;
|
|
17
|
+
}
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
return "dev";
|
|
21
|
+
}
|
|
22
|
+
var ACP_PACKAGE_VERSION = readPackageVersion();
|
|
23
|
+
|
|
24
|
+
// src/agent/protocol-contract.ts
|
|
10
25
|
function toWire(msg) {
|
|
11
26
|
return msg;
|
|
12
27
|
}
|
|
13
|
-
var WRONGSTACK_VERSION =
|
|
28
|
+
var WRONGSTACK_VERSION = ACP_PACKAGE_VERSION;
|
|
29
|
+
|
|
30
|
+
// src/agent/protocol-handler.ts
|
|
14
31
|
var WRONGSTACK_AUTH_METHODS = [
|
|
15
32
|
{
|
|
16
33
|
id: "wrongstack-auth",
|
|
@@ -21,6 +38,7 @@ var WRONGSTACK_AUTH_METHODS = [
|
|
|
21
38
|
}
|
|
22
39
|
];
|
|
23
40
|
var DEFAULT_MODE_ID = "code";
|
|
41
|
+
var DEFAULT_MAX_SESSIONS = 64;
|
|
24
42
|
var DEFAULT_MODES = [
|
|
25
43
|
{
|
|
26
44
|
id: DEFAULT_MODE_ID,
|
|
@@ -38,6 +56,8 @@ var ACPProtocolHandler = class {
|
|
|
38
56
|
agentName;
|
|
39
57
|
replayFor;
|
|
40
58
|
seedFor;
|
|
59
|
+
disposeFor;
|
|
60
|
+
maxSessions;
|
|
41
61
|
store;
|
|
42
62
|
initialized = false;
|
|
43
63
|
clientCapabilities = {};
|
|
@@ -58,6 +78,8 @@ var ACPProtocolHandler = class {
|
|
|
58
78
|
this.agentName = opts.agentName ?? "wrongstack";
|
|
59
79
|
this.replayFor = opts.replayFor;
|
|
60
80
|
this.seedFor = opts.seedFor;
|
|
81
|
+
this.disposeFor = opts.disposeFor;
|
|
82
|
+
this.maxSessions = Number.isFinite(opts.maxSessions) && opts.maxSessions > 0 ? Math.floor(opts.maxSessions) : DEFAULT_MAX_SESSIONS;
|
|
61
83
|
this.store = opts.store;
|
|
62
84
|
if (typeof this.transport.onMessage === "function") {
|
|
63
85
|
this.transport.onMessage((m) => this.maybeResolvePending(m));
|
|
@@ -115,8 +137,9 @@ var ACPProtocolHandler = class {
|
|
|
115
137
|
}
|
|
116
138
|
/** Abort all active turns and drop session state. */
|
|
117
139
|
close() {
|
|
118
|
-
for (const [, session] of this.sessions) {
|
|
140
|
+
for (const [sessionId, session] of this.sessions) {
|
|
119
141
|
session.abort.abort();
|
|
142
|
+
this.disposeSession(sessionId);
|
|
120
143
|
}
|
|
121
144
|
this.sessions.clear();
|
|
122
145
|
for (const [, p] of this.pendingOut) {
|
|
@@ -125,6 +148,12 @@ var ACPProtocolHandler = class {
|
|
|
125
148
|
}
|
|
126
149
|
this.pendingOut.clear();
|
|
127
150
|
}
|
|
151
|
+
disposeSession(sessionId) {
|
|
152
|
+
try {
|
|
153
|
+
this.disposeFor?.(sessionId);
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
}
|
|
128
157
|
// ────────────────────────────────────────────────────────────────────
|
|
129
158
|
// Requests
|
|
130
159
|
// ────────────────────────────────────────────────────────────────────
|
|
@@ -244,6 +273,10 @@ var ACPProtocolHandler = class {
|
|
|
244
273
|
return false;
|
|
245
274
|
}
|
|
246
275
|
async handleSessionNew(id, params) {
|
|
276
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
277
|
+
await this.sendError(id, -32e3, `active session limit reached (${this.maxSessions})`);
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
247
280
|
const p = params ?? {};
|
|
248
281
|
const cwd = typeof p.cwd === "string" ? p.cwd : this.defaultCwd;
|
|
249
282
|
const sessionId = `sess_${this.allocId()}`;
|
|
@@ -294,6 +327,10 @@ var ACPProtocolHandler = class {
|
|
|
294
327
|
if (!existing && sessionId && this.store) {
|
|
295
328
|
const persisted = await this.store.load(sessionId);
|
|
296
329
|
if (persisted) {
|
|
330
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
331
|
+
await this.sendError(id, -32e3, `active session limit reached (${this.maxSessions})`);
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
297
334
|
const restored = {
|
|
298
335
|
id: sessionId,
|
|
299
336
|
cwd: persisted.cwd ?? loadCwd ?? this.defaultCwd,
|
|
@@ -324,7 +361,7 @@ var ACPProtocolHandler = class {
|
|
|
324
361
|
}
|
|
325
362
|
if (existing) {
|
|
326
363
|
existing.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
327
|
-
const replay =
|
|
364
|
+
const replay = this.replayFor?.(sessionId);
|
|
328
365
|
if (replay) {
|
|
329
366
|
for (const update of replay) {
|
|
330
367
|
await this.sendNotification({ sessionId, update });
|
|
@@ -389,7 +426,8 @@ var ACPProtocolHandler = class {
|
|
|
389
426
|
return false;
|
|
390
427
|
}
|
|
391
428
|
session.abort.abort();
|
|
392
|
-
|
|
429
|
+
this.sessions.delete(sessionId);
|
|
430
|
+
this.disposeSession(sessionId);
|
|
393
431
|
await this.transport.send(toWire({
|
|
394
432
|
jsonrpc: "2.0",
|
|
395
433
|
id,
|
|
@@ -411,6 +449,7 @@ var ACPProtocolHandler = class {
|
|
|
411
449
|
const session = this.sessions.get(sessionId);
|
|
412
450
|
session.abort.abort();
|
|
413
451
|
this.sessions.delete(sessionId);
|
|
452
|
+
this.disposeSession(sessionId);
|
|
414
453
|
await this.transport.send(toWire({
|
|
415
454
|
jsonrpc: "2.0",
|
|
416
455
|
id,
|
|
@@ -426,6 +465,10 @@ var ACPProtocolHandler = class {
|
|
|
426
465
|
await this.sendError(id, -32e3, `session not found: ${sourceId}`);
|
|
427
466
|
return false;
|
|
428
467
|
}
|
|
468
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
469
|
+
await this.sendError(id, -32e3, `active session limit reached (${this.maxSessions})`);
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
429
472
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
430
473
|
const sessionId = `sess_${this.allocId()}`;
|
|
431
474
|
const forked = {
|
|
@@ -692,7 +735,13 @@ function errorToJsonRpc(err) {
|
|
|
692
735
|
}
|
|
693
736
|
|
|
694
737
|
// src/agent/stdio-transport.ts
|
|
695
|
-
import { expectDefined, writeErr } from "@wrongstack/core";
|
|
738
|
+
import { expectDefined, writeErr } from "@wrongstack/core/utils";
|
|
739
|
+
import { treeKill } from "@wrongstack/core/utils/tree-kill";
|
|
740
|
+
var DEFAULT_MAX_FRAME_CHARS = 20 * 1024 * 1024;
|
|
741
|
+
var DEFAULT_MAX_QUEUED_MESSAGES = 1e3;
|
|
742
|
+
function positiveLimit(value, fallback) {
|
|
743
|
+
return value !== void 0 && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
744
|
+
}
|
|
696
745
|
var StdioTransport = class {
|
|
697
746
|
stdin = process.stdin;
|
|
698
747
|
stdout = process.stdout;
|
|
@@ -702,7 +751,11 @@ var StdioTransport = class {
|
|
|
702
751
|
closed = false;
|
|
703
752
|
resolveRead = null;
|
|
704
753
|
messageQueue = [];
|
|
705
|
-
|
|
754
|
+
maxFrameChars;
|
|
755
|
+
maxQueuedMessages;
|
|
756
|
+
constructor(opts = {}) {
|
|
757
|
+
this.maxFrameChars = positiveLimit(opts.maxFrameChars, DEFAULT_MAX_FRAME_CHARS);
|
|
758
|
+
this.maxQueuedMessages = positiveLimit(opts.maxQueuedMessages, DEFAULT_MAX_QUEUED_MESSAGES);
|
|
706
759
|
this.stdin.resume();
|
|
707
760
|
this.stdin.setEncoding("utf8");
|
|
708
761
|
this.stdin.on("data", (chunk) => this.onData(chunk));
|
|
@@ -723,7 +776,8 @@ var StdioTransport = class {
|
|
|
723
776
|
this.stdout.write(chunk, "utf8");
|
|
724
777
|
}
|
|
725
778
|
read() {
|
|
726
|
-
if (this.messageQueue.length > 0)
|
|
779
|
+
if (this.messageQueue.length > 0)
|
|
780
|
+
return Promise.resolve(expectDefined(this.messageQueue.shift()));
|
|
727
781
|
if (this.closed) return Promise.resolve(null);
|
|
728
782
|
return new Promise((resolve) => {
|
|
729
783
|
this.resolveRead = resolve;
|
|
@@ -738,13 +792,34 @@ var StdioTransport = class {
|
|
|
738
792
|
this.stdin.pause();
|
|
739
793
|
this.resolveRead?.(null);
|
|
740
794
|
this.resolveRead = null;
|
|
795
|
+
this.buffer = "";
|
|
796
|
+
this.messageQueue.length = 0;
|
|
797
|
+
this.handlers.clear();
|
|
741
798
|
}
|
|
742
799
|
onData(chunk) {
|
|
743
800
|
this.buffer += chunk;
|
|
744
801
|
const lines = this.buffer.split("\n");
|
|
745
802
|
this.buffer = lines.pop() ?? "";
|
|
803
|
+
if (this.buffer.length > this.maxFrameChars) {
|
|
804
|
+
this.stderr.write(
|
|
805
|
+
`[wstack-acp frame error] pending frame exceeds ${this.maxFrameChars} characters
|
|
806
|
+
`,
|
|
807
|
+
"utf8"
|
|
808
|
+
);
|
|
809
|
+
this.close();
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
746
812
|
for (const raw of lines) {
|
|
747
813
|
if (!raw.trim()) continue;
|
|
814
|
+
if (raw.length > this.maxFrameChars) {
|
|
815
|
+
this.stderr.write(
|
|
816
|
+
`[wstack-acp frame error] frame exceeds ${this.maxFrameChars} characters
|
|
817
|
+
`,
|
|
818
|
+
"utf8"
|
|
819
|
+
);
|
|
820
|
+
this.close();
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
748
823
|
try {
|
|
749
824
|
this.dispatch(JSON.parse(raw));
|
|
750
825
|
} catch (err) {
|
|
@@ -759,6 +834,15 @@ var StdioTransport = class {
|
|
|
759
834
|
this.resolveRead = null;
|
|
760
835
|
resolve(msg);
|
|
761
836
|
} else {
|
|
837
|
+
if (this.messageQueue.length >= this.maxQueuedMessages) {
|
|
838
|
+
this.stderr.write(
|
|
839
|
+
`[wstack-acp queue error] pending message queue exceeds ${this.maxQueuedMessages} entries
|
|
840
|
+
`,
|
|
841
|
+
"utf8"
|
|
842
|
+
);
|
|
843
|
+
this.close();
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
762
846
|
this.messageQueue.push(msg);
|
|
763
847
|
}
|
|
764
848
|
for (const handler of this.handlers) {
|
|
@@ -771,9 +855,7 @@ var StdioTransport = class {
|
|
|
771
855
|
}
|
|
772
856
|
}
|
|
773
857
|
handleClose() {
|
|
774
|
-
this.
|
|
775
|
-
this.resolveRead?.(null);
|
|
776
|
-
this.resolveRead = null;
|
|
858
|
+
this.close();
|
|
777
859
|
}
|
|
778
860
|
failAll(err) {
|
|
779
861
|
this.stderr.write(`[wstack-acp stdin error] ${err.message}
|
|
@@ -801,6 +883,7 @@ var WrongStackACPServer = class {
|
|
|
801
883
|
agentName: opts.agentName,
|
|
802
884
|
...opts.replayFor ? { replayFor: opts.replayFor } : {},
|
|
803
885
|
...opts.seedFor ? { seedFor: opts.seedFor } : {},
|
|
886
|
+
...opts.disposeFor ? { disposeFor: opts.disposeFor } : {},
|
|
804
887
|
...opts.store ? { store: opts.store } : {}
|
|
805
888
|
});
|
|
806
889
|
}
|
|
@@ -822,13 +905,17 @@ var WrongStackACPServer = class {
|
|
|
822
905
|
this.transport.sendStartupMarker();
|
|
823
906
|
}
|
|
824
907
|
this.running = true;
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
908
|
+
try {
|
|
909
|
+
while (this.running) {
|
|
910
|
+
const msg = await this.transport.read();
|
|
911
|
+
if (!msg) break;
|
|
912
|
+
const terminal = await this.handler.handleMessage(msg);
|
|
913
|
+
if (terminal) break;
|
|
914
|
+
}
|
|
915
|
+
} finally {
|
|
916
|
+
this.handler.close();
|
|
917
|
+
this.transport.close();
|
|
830
918
|
}
|
|
831
|
-
this.transport.close();
|
|
832
919
|
}
|
|
833
920
|
async startHttp(port) {
|
|
834
921
|
const host = this.options.host ?? "127.0.0.1";
|
|
@@ -837,10 +924,9 @@ var WrongStackACPServer = class {
|
|
|
837
924
|
let httpChain = Promise.resolve();
|
|
838
925
|
this.httpServer = createServer(async (req, res) => {
|
|
839
926
|
if (authToken) {
|
|
840
|
-
const url = new URL(req.url
|
|
927
|
+
const url = new URL(requestPath(req.url), `http://${host}:${port}`);
|
|
841
928
|
const queryToken = url.searchParams.get("token");
|
|
842
|
-
const
|
|
843
|
-
const bearerToken = Array.isArray(authHeader) ? authHeader[0]?.replace(/^Bearer\s+/i, "") : authHeader?.replace(/^Bearer\s+/i, "");
|
|
929
|
+
const bearerToken = headerValue(req.headers.authorization)?.replace(/^Bearer\s+/i, "");
|
|
844
930
|
const supplied = queryToken ?? bearerToken ?? "";
|
|
845
931
|
if (supplied !== authToken) {
|
|
846
932
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
@@ -849,7 +935,7 @@ var WrongStackACPServer = class {
|
|
|
849
935
|
}
|
|
850
936
|
}
|
|
851
937
|
const selfOrigin = `http://${host}:${port}`;
|
|
852
|
-
const reqOrigin =
|
|
938
|
+
const reqOrigin = headerValue(req.headers.origin);
|
|
853
939
|
if (reqOrigin && reqOrigin !== selfOrigin) {
|
|
854
940
|
res.writeHead(403);
|
|
855
941
|
res.end(JSON.stringify({ error: "cross-origin request forbidden" }));
|
|
@@ -929,6 +1015,8 @@ var WrongStackACPServer = class {
|
|
|
929
1015
|
try {
|
|
930
1016
|
await requestPromise;
|
|
931
1017
|
} catch {
|
|
1018
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1019
|
+
res.end(JSON.stringify({ error: { code: -32603, message: "Internal error" } }));
|
|
932
1020
|
}
|
|
933
1021
|
});
|
|
934
1022
|
return new Promise((resolve) => {
|
|
@@ -943,6 +1031,7 @@ var WrongStackACPServer = class {
|
|
|
943
1031
|
/** Stop the server. */
|
|
944
1032
|
stop() {
|
|
945
1033
|
this.running = false;
|
|
1034
|
+
this.handler.close();
|
|
946
1035
|
this.transport.close();
|
|
947
1036
|
if (this.httpServer) {
|
|
948
1037
|
this.httpServer.close();
|
|
@@ -953,6 +1042,13 @@ var WrongStackACPServer = class {
|
|
|
953
1042
|
var defaultEchoRunTurn = async (_input, _emit) => {
|
|
954
1043
|
return { stopReason: "end_turn" };
|
|
955
1044
|
};
|
|
1045
|
+
function headerValue(value) {
|
|
1046
|
+
return Array.isArray(value) ? value[0] : value;
|
|
1047
|
+
}
|
|
1048
|
+
function requestPath(value) {
|
|
1049
|
+
return value ?? "/";
|
|
1050
|
+
}
|
|
1051
|
+
var wrongStackACPServerCoverage = { defaultEchoRunTurn, headerValue, requestPath };
|
|
956
1052
|
async function main() {
|
|
957
1053
|
const server = new WrongStackACPServer();
|
|
958
1054
|
await server.start();
|
|
@@ -966,6 +1062,7 @@ if (isEntrypoint) {
|
|
|
966
1062
|
});
|
|
967
1063
|
}
|
|
968
1064
|
export {
|
|
969
|
-
WrongStackACPServer
|
|
1065
|
+
WrongStackACPServer,
|
|
1066
|
+
wrongStackACPServerCoverage
|
|
970
1067
|
};
|
|
971
1068
|
//# sourceMappingURL=wrongstack-acp-agent.js.map
|