@wrongstack/acp 1.0.28 → 1.0.32
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/agent.js +54 -24
- package/dist/client/acp-session-messages.d.ts +24 -0
- package/dist/client/acp-session.d.ts +1 -0
- package/dist/client.js +258 -187
- package/dist/index.js +287 -191
- package/dist/wrongstack-acp-agent.js +24 -1
- package/package.json +4 -3
package/dist/agent.js
CHANGED
|
@@ -236,6 +236,10 @@ async function handleSessionNewOp(ctx, id, params) {
|
|
|
236
236
|
}
|
|
237
237
|
const skipped = [];
|
|
238
238
|
const mcpServers = parseMcpServers(p.mcpServers, (reason) => skipped.push(reason));
|
|
239
|
+
if (ctx.sessions.size >= ctx.maxSessions) {
|
|
240
|
+
await ctx.sendError(id, -32e3, `active session limit reached (${ctx.maxSessions})`);
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
239
243
|
const sessionId = `sess_${ctx.allocId()}`;
|
|
240
244
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
241
245
|
const state = {
|
|
@@ -286,6 +290,9 @@ async function handleSessionLoadOp(ctx, id, params, replayHistory = true) {
|
|
|
286
290
|
if (!existing && sessionId && ctx.store) {
|
|
287
291
|
const persisted = await ctx.store.load(sessionId);
|
|
288
292
|
if (persisted) {
|
|
293
|
+
if (ctx.sessions.has(sessionId)) {
|
|
294
|
+
return handleSessionLoadOp(ctx, id, params, replayHistory);
|
|
295
|
+
}
|
|
289
296
|
if (ctx.sessions.size >= ctx.maxSessions) {
|
|
290
297
|
await ctx.sendError(id, -32e3, `active session limit reached (${ctx.maxSessions})`);
|
|
291
298
|
return false;
|
|
@@ -294,8 +301,15 @@ async function handleSessionLoadOp(ctx, id, params, replayHistory = true) {
|
|
|
294
301
|
await ctx.sendError(id, -32602, `cwd must be an absolute path to an existing directory`);
|
|
295
302
|
return false;
|
|
296
303
|
}
|
|
297
|
-
const candidateCwd = persisted.cwd ??
|
|
304
|
+
const candidateCwd = loadCwd ?? persisted.cwd ?? ctx.defaultCwd;
|
|
298
305
|
const restoredCwd = await resolveSessionCwd(candidateCwd) ?? ctx.defaultCwd;
|
|
306
|
+
if (ctx.sessions.has(sessionId)) {
|
|
307
|
+
return handleSessionLoadOp(ctx, id, params, replayHistory);
|
|
308
|
+
}
|
|
309
|
+
if (ctx.sessions.size >= ctx.maxSessions) {
|
|
310
|
+
await ctx.sendError(id, -32e3, `active session limit reached (${ctx.maxSessions})`);
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
299
313
|
const restored = {
|
|
300
314
|
id: sessionId,
|
|
301
315
|
cwd: restoredCwd,
|
|
@@ -399,9 +413,17 @@ async function handleSessionForkOp(ctx, id, params) {
|
|
|
399
413
|
}
|
|
400
414
|
forkCwd = resolved;
|
|
401
415
|
}
|
|
416
|
+
if (ctx.sessions.get(sourceId) !== source) {
|
|
417
|
+
await ctx.sendError(id, -32e3, `session not found: ${sourceId}`);
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
402
420
|
const forkSkipped = [];
|
|
403
421
|
const forkRequested = parseMcpServers(p.mcpServers, (reason) => forkSkipped.push(reason));
|
|
404
422
|
const forkMcpServers = forkRequested.length > 0 ? forkRequested : source.mcpServers;
|
|
423
|
+
if (ctx.sessions.size >= ctx.maxSessions) {
|
|
424
|
+
await ctx.sendError(id, -32e3, `active session limit reached (${ctx.maxSessions})`);
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
405
427
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
406
428
|
const sessionId = `sess_${ctx.allocId()}`;
|
|
407
429
|
const forked = {
|
|
@@ -475,6 +497,7 @@ async function handleSessionPromptOp(ctx, id, params) {
|
|
|
475
497
|
let result;
|
|
476
498
|
const pendingNotifications = [];
|
|
477
499
|
const emit = (update) => {
|
|
500
|
+
if (ctx.sessions.get(sessionId) !== session) return;
|
|
478
501
|
const notifPromise = ctx.sendNotification({ sessionId, update });
|
|
479
502
|
pendingNotifications.push(notifPromise.catch(() => {
|
|
480
503
|
}));
|
|
@@ -1510,20 +1533,24 @@ var ACPSessionStore = class {
|
|
|
1510
1533
|
const tmp = `${target}.${process.pid}.${Date.now()}.${++this.writeSeq}.tmp`;
|
|
1511
1534
|
let renamed = false;
|
|
1512
1535
|
try {
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1536
|
+
const data = JSON.stringify({
|
|
1537
|
+
id: state.id,
|
|
1538
|
+
cwd: state.cwd,
|
|
1539
|
+
modeId: state.modeId,
|
|
1540
|
+
configOptions: state.configOptions,
|
|
1541
|
+
createdAt: state.createdAt,
|
|
1542
|
+
updatedAt: state.updatedAt,
|
|
1543
|
+
title: state.title,
|
|
1544
|
+
...history && history.length > 0 ? { history } : {}
|
|
1545
|
+
});
|
|
1546
|
+
try {
|
|
1547
|
+
await fsp2.writeFile(tmp, data, "utf8");
|
|
1548
|
+
} catch (err) {
|
|
1549
|
+
if (err.code !== "ENOENT") throw err;
|
|
1550
|
+
this.initialized = false;
|
|
1551
|
+
await this.init();
|
|
1552
|
+
await fsp2.writeFile(tmp, data, "utf8");
|
|
1553
|
+
}
|
|
1527
1554
|
await fsp2.rename(tmp, target);
|
|
1528
1555
|
renamed = true;
|
|
1529
1556
|
} finally {
|
|
@@ -1547,13 +1574,15 @@ var ACPSessionStore = class {
|
|
|
1547
1574
|
}
|
|
1548
1575
|
/** List all persisted sessions. */
|
|
1549
1576
|
async list() {
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1577
|
+
return this.withIndexLock(async () => {
|
|
1578
|
+
const indexEntries = await this.readIndex();
|
|
1579
|
+
if (indexEntries !== null) {
|
|
1580
|
+
return indexEntries.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
1581
|
+
}
|
|
1582
|
+
const sessions = await this.scanForSessions();
|
|
1583
|
+
await this.writeIndex(sessions).catch(() => void 0);
|
|
1584
|
+
return sessions;
|
|
1585
|
+
});
|
|
1557
1586
|
}
|
|
1558
1587
|
/**
|
|
1559
1588
|
* Walk `<dir>` and parse every session file into `{id, updatedAt}`
|
|
@@ -1578,7 +1607,7 @@ var ACPSessionStore = class {
|
|
|
1578
1607
|
try {
|
|
1579
1608
|
const data = await fsp2.readFile(path2.join(this.dir, file), "utf8");
|
|
1580
1609
|
const parsed = JSON.parse(data);
|
|
1581
|
-
if (parsed.id) {
|
|
1610
|
+
if (parsed && typeof parsed.id === "string" && parsed.id !== "" && (parsed.updatedAt === void 0 || typeof parsed.updatedAt === "string")) {
|
|
1582
1611
|
sessions.push({ id: parsed.id, updatedAt: parsed.updatedAt ?? "" });
|
|
1583
1612
|
}
|
|
1584
1613
|
} catch {
|
|
@@ -1962,7 +1991,7 @@ function toACPInputSchema(src) {
|
|
|
1962
1991
|
if (typeof s.maximum === "number") out.maximum = s.maximum;
|
|
1963
1992
|
if (s.items) out.items = toACPInputSchema(s.items);
|
|
1964
1993
|
if (s.properties && typeof s.properties === "object") {
|
|
1965
|
-
const props =
|
|
1994
|
+
const props = /* @__PURE__ */ Object.create(null);
|
|
1966
1995
|
for (const [k, v] of Object.entries(s.properties)) {
|
|
1967
1996
|
props[k] = toACPInputSchema(v);
|
|
1968
1997
|
}
|
|
@@ -2318,6 +2347,7 @@ var WsBridgeTransport = class {
|
|
|
2318
2347
|
receive(msg) {
|
|
2319
2348
|
if (this.closed) return;
|
|
2320
2349
|
for (const handler of [...this.handlers]) {
|
|
2350
|
+
if (this.closed) break;
|
|
2321
2351
|
try {
|
|
2322
2352
|
handler(msg);
|
|
2323
2353
|
} catch {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ACPMessage } from '../types/acp-messages.js';
|
|
2
|
+
import { type ACPCallbackOptions, type ACPResponseSender } from './acp-session-callbacks.js';
|
|
3
|
+
import type { ACPProgressEvent } from './acp-session-types.js';
|
|
4
|
+
export interface AcpSessionMessagesHost {
|
|
5
|
+
sendResult: (id: string | number, result: unknown) => Promise<void>;
|
|
6
|
+
sendErrorResponse: (id: string | number, code: number, message: string) => Promise<void>;
|
|
7
|
+
promptCallbackAbort: AbortController | null;
|
|
8
|
+
callbackAbort: AbortController;
|
|
9
|
+
pending: Map<string | number, import('./acp-request-state.js').PendingRequest>;
|
|
10
|
+
sessionId: import('../types/acp-v1.js').SessionId | null;
|
|
11
|
+
scratch: import('./acp-session-updates.js').ACPSessionScratch;
|
|
12
|
+
emitProgress: (event: import('./acp-session-types.js').ACPProgressEvent) => void;
|
|
13
|
+
permissionPolicy: import('./permission.js').PermissionPolicy;
|
|
14
|
+
responseSender: () => import('./acp-session-callbacks.js').ACPResponseSender;
|
|
15
|
+
callbackOptions: () => import('./acp-session-callbacks.js').ACPCallbackOptions;
|
|
16
|
+
fileServer: import('./file-server.js').FileServer;
|
|
17
|
+
terminalServer: import('./terminal-server.js').TerminalServer;
|
|
18
|
+
progressHandler: import('./acp-session-types.js').ACPProgressHandler | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function responseSender(this: AcpSessionMessagesHost): ACPResponseSender;
|
|
21
|
+
export declare function callbackOptions(this: AcpSessionMessagesHost): ACPCallbackOptions;
|
|
22
|
+
export declare function handleMessage(this: AcpSessionMessagesHost, msg: ACPMessage): void;
|
|
23
|
+
export declare function emitProgress(this: AcpSessionMessagesHost, event: ACPProgressEvent): void;
|
|
24
|
+
//# sourceMappingURL=acp-session-messages.d.ts.map
|