@wrongstack/acp 1.0.32 → 1.0.35
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/protocol-contract.d.ts +0 -10
- package/dist/agent/protocol-handler.d.ts +1 -6
- package/dist/agent/server-agent-turn-content.d.ts +117 -0
- package/dist/agent/server-agent-turn.d.ts +4 -67
- package/dist/agent.js +138 -136
- package/dist/client/acp-session-prompt.d.ts +23 -0
- package/dist/client/acp-session.d.ts +1 -0
- package/dist/client.js +193 -169
- package/dist/index.js +193 -169
- package/package.json +3 -3
package/dist/client.js
CHANGED
|
@@ -691,39 +691,6 @@ async function ensureAuthenticated(host) {
|
|
|
691
691
|
);
|
|
692
692
|
}
|
|
693
693
|
|
|
694
|
-
// src/client/acp-session-content.ts
|
|
695
|
-
function textContent(text) {
|
|
696
|
-
return { type: "text", text };
|
|
697
|
-
}
|
|
698
|
-
function imageContent(mimeType, data) {
|
|
699
|
-
return { type: "image", mimeType, data };
|
|
700
|
-
}
|
|
701
|
-
function audioContent(mimeType, data) {
|
|
702
|
-
return { type: "audio", mimeType, data };
|
|
703
|
-
}
|
|
704
|
-
function extractText(block) {
|
|
705
|
-
if (typeof block !== "object" || block === null) return "";
|
|
706
|
-
const b = block;
|
|
707
|
-
if (b.type === "text" && typeof b.text === "string") return b.text;
|
|
708
|
-
if (b.type === "resource" && b.resource && typeof b.resource === "object" && typeof b.resource.text === "string") {
|
|
709
|
-
return b.resource.text;
|
|
710
|
-
}
|
|
711
|
-
return "";
|
|
712
|
-
}
|
|
713
|
-
function isRecord(v) {
|
|
714
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
715
|
-
}
|
|
716
|
-
function emptyRunResult(stopReason) {
|
|
717
|
-
return {
|
|
718
|
-
text: "",
|
|
719
|
-
stopReason,
|
|
720
|
-
hasText: false,
|
|
721
|
-
toolCalls: [],
|
|
722
|
-
diffs: [],
|
|
723
|
-
thoughts: ""
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
|
|
727
694
|
// src/client/acp-message-routing.ts
|
|
728
695
|
function isBestEffortAckMethod(method) {
|
|
729
696
|
return method === "mcp/connect" || method === "mcp/message" || method === "mcp/disconnect" || method === "elicitation/create" || method === "elicitation/complete";
|
|
@@ -1195,6 +1162,39 @@ function resolvePermissionDeadline(value) {
|
|
|
1195
1162
|
return DEFAULT_PERMISSION_TIMEOUT_MS;
|
|
1196
1163
|
}
|
|
1197
1164
|
|
|
1165
|
+
// src/client/acp-session-content.ts
|
|
1166
|
+
function textContent(text) {
|
|
1167
|
+
return { type: "text", text };
|
|
1168
|
+
}
|
|
1169
|
+
function imageContent(mimeType, data) {
|
|
1170
|
+
return { type: "image", mimeType, data };
|
|
1171
|
+
}
|
|
1172
|
+
function audioContent(mimeType, data) {
|
|
1173
|
+
return { type: "audio", mimeType, data };
|
|
1174
|
+
}
|
|
1175
|
+
function extractText(block) {
|
|
1176
|
+
if (typeof block !== "object" || block === null) return "";
|
|
1177
|
+
const b = block;
|
|
1178
|
+
if (b.type === "text" && typeof b.text === "string") return b.text;
|
|
1179
|
+
if (b.type === "resource" && b.resource && typeof b.resource === "object" && typeof b.resource.text === "string") {
|
|
1180
|
+
return b.resource.text;
|
|
1181
|
+
}
|
|
1182
|
+
return "";
|
|
1183
|
+
}
|
|
1184
|
+
function isRecord(v) {
|
|
1185
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1186
|
+
}
|
|
1187
|
+
function emptyRunResult(stopReason) {
|
|
1188
|
+
return {
|
|
1189
|
+
text: "",
|
|
1190
|
+
stopReason,
|
|
1191
|
+
hasText: false,
|
|
1192
|
+
toolCalls: [],
|
|
1193
|
+
diffs: [],
|
|
1194
|
+
thoughts: ""
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
1198
|
// src/client/acp-session-updates.ts
|
|
1199
1199
|
function createSessionScratch() {
|
|
1200
1200
|
return { text: "", thoughts: "", toolCalls: /* @__PURE__ */ new Map(), diffs: [] };
|
|
@@ -1390,6 +1390,146 @@ function emitProgress(event) {
|
|
|
1390
1390
|
}
|
|
1391
1391
|
}
|
|
1392
1392
|
|
|
1393
|
+
// src/client/acp-session-prompt.ts
|
|
1394
|
+
async function prompt(host, blocks, signal, onProgress) {
|
|
1395
|
+
if (host.closed) {
|
|
1396
|
+
throw new ACPSessionError("closed", "session is closed");
|
|
1397
|
+
}
|
|
1398
|
+
if (host.state !== "ready" && host.state !== "authenticated" && host.state !== "done") {
|
|
1399
|
+
throw new ACPSessionError("protocol_error", `prompt called in state=${host.state}`);
|
|
1400
|
+
}
|
|
1401
|
+
if (host.promptCallbackAbort) {
|
|
1402
|
+
throw new ACPSessionError("protocol_error", "prompt called while another prompt is running");
|
|
1403
|
+
}
|
|
1404
|
+
if (signal.aborted) {
|
|
1405
|
+
return emptyRunResult("cancelled");
|
|
1406
|
+
}
|
|
1407
|
+
const caps = host.agentCapabilities.promptCapabilities;
|
|
1408
|
+
for (const block of blocks) {
|
|
1409
|
+
const supported = block.type === "image" ? caps?.image : block.type === "audio" ? caps?.audio : block.type === "resource" ? caps?.embeddedContext : true;
|
|
1410
|
+
if (supported !== true) {
|
|
1411
|
+
throw new ACPSessionError(
|
|
1412
|
+
"unsupported_capability",
|
|
1413
|
+
`agent does not support ${block.type} prompt content`
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
let cancelled = false;
|
|
1418
|
+
host.promptCallbackAbort = new AbortController();
|
|
1419
|
+
const onAbort = () => {
|
|
1420
|
+
cancelled = true;
|
|
1421
|
+
host.promptCallbackAbort?.abort();
|
|
1422
|
+
if (host.sessionId) {
|
|
1423
|
+
host.transport.send({
|
|
1424
|
+
jsonrpc: "2.0",
|
|
1425
|
+
method: "session/cancel",
|
|
1426
|
+
params: { sessionId: host.sessionId }
|
|
1427
|
+
}).catch(() => {
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1432
|
+
let rejectCreate;
|
|
1433
|
+
const onCreateAbort = () => {
|
|
1434
|
+
signal.removeEventListener("abort", onAbort);
|
|
1435
|
+
rejectCreate?.(new ACPSessionError("aborted", "prompt was aborted by the parent"));
|
|
1436
|
+
};
|
|
1437
|
+
if (!host.sessionId) {
|
|
1438
|
+
let sessionId;
|
|
1439
|
+
const createPromise = host.createSessionWithAuth();
|
|
1440
|
+
try {
|
|
1441
|
+
sessionId = await Promise.race([
|
|
1442
|
+
createPromise,
|
|
1443
|
+
new Promise((_, reject) => {
|
|
1444
|
+
rejectCreate = reject;
|
|
1445
|
+
signal.addEventListener("abort", onCreateAbort, { once: true });
|
|
1446
|
+
})
|
|
1447
|
+
]);
|
|
1448
|
+
} catch (err) {
|
|
1449
|
+
signal.removeEventListener("abort", onAbort);
|
|
1450
|
+
signal.removeEventListener("abort", onCreateAbort);
|
|
1451
|
+
rejectCreate = void 0;
|
|
1452
|
+
host.promptCallbackAbort?.abort();
|
|
1453
|
+
host.promptCallbackAbort = null;
|
|
1454
|
+
if (err instanceof ACPSessionError && err.kind === "aborted") {
|
|
1455
|
+
host.cancelLateSession(createPromise);
|
|
1456
|
+
return emptyRunResult("cancelled");
|
|
1457
|
+
}
|
|
1458
|
+
throw err;
|
|
1459
|
+
}
|
|
1460
|
+
signal.removeEventListener("abort", onCreateAbort);
|
|
1461
|
+
rejectCreate = void 0;
|
|
1462
|
+
host.sessionId = sessionId;
|
|
1463
|
+
}
|
|
1464
|
+
if (signal.aborted) {
|
|
1465
|
+
host.promptCallbackAbort = null;
|
|
1466
|
+
return emptyRunResult("cancelled");
|
|
1467
|
+
}
|
|
1468
|
+
host.resetScratch();
|
|
1469
|
+
host.progressHandler = onProgress ?? null;
|
|
1470
|
+
const promptId = host.allocId();
|
|
1471
|
+
let rejectTurn;
|
|
1472
|
+
const onTurnAbort = () => {
|
|
1473
|
+
rejectTurn?.(new ACPSessionError("aborted", "prompt was aborted by the parent"));
|
|
1474
|
+
};
|
|
1475
|
+
signal.addEventListener("abort", onTurnAbort, { once: true });
|
|
1476
|
+
const turnPromise = Promise.race([
|
|
1477
|
+
host.sendRequest(
|
|
1478
|
+
promptId,
|
|
1479
|
+
"session/prompt",
|
|
1480
|
+
{
|
|
1481
|
+
sessionId: host.sessionId,
|
|
1482
|
+
prompt: blocks
|
|
1483
|
+
},
|
|
1484
|
+
host.timeoutMs
|
|
1485
|
+
),
|
|
1486
|
+
new Promise((_, reject) => {
|
|
1487
|
+
rejectTurn = reject;
|
|
1488
|
+
})
|
|
1489
|
+
]);
|
|
1490
|
+
host.state = "prompting";
|
|
1491
|
+
let response;
|
|
1492
|
+
try {
|
|
1493
|
+
response = await turnPromise;
|
|
1494
|
+
} catch (err) {
|
|
1495
|
+
host.state = "done";
|
|
1496
|
+
const abortedKind = err instanceof ACPSessionError && err.kind === "aborted";
|
|
1497
|
+
if (cancelled || abortedKind) {
|
|
1498
|
+
return emptyRunResult("cancelled");
|
|
1499
|
+
}
|
|
1500
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1501
|
+
if (signal.aborted) {
|
|
1502
|
+
throw new ACPSessionError("aborted", "prompt was aborted by the parent", err);
|
|
1503
|
+
}
|
|
1504
|
+
throw new ACPSessionError("prompt_failed", `session/prompt failed: ${msg}`, err);
|
|
1505
|
+
} finally {
|
|
1506
|
+
signal.removeEventListener("abort", onAbort);
|
|
1507
|
+
signal.removeEventListener("abort", onTurnAbort);
|
|
1508
|
+
signal.removeEventListener("abort", onCreateAbort);
|
|
1509
|
+
rejectTurn = void 0;
|
|
1510
|
+
rejectCreate = void 0;
|
|
1511
|
+
host.promptCallbackAbort?.abort();
|
|
1512
|
+
host.promptCallbackAbort = null;
|
|
1513
|
+
host.progressHandler = null;
|
|
1514
|
+
}
|
|
1515
|
+
host.state = "done";
|
|
1516
|
+
if (isJsonRpcError(response)) {
|
|
1517
|
+
throw new ACPSessionError("prompt_failed", `agent error: ${response.message}`, response);
|
|
1518
|
+
}
|
|
1519
|
+
const stopReason = response.stopReason ?? "end_turn";
|
|
1520
|
+
const finalText = host.scratch.text;
|
|
1521
|
+
return {
|
|
1522
|
+
text: finalText,
|
|
1523
|
+
stopReason,
|
|
1524
|
+
hasText: finalText.length > 0,
|
|
1525
|
+
usage: host.scratch.usage,
|
|
1526
|
+
plan: host.scratch.plan,
|
|
1527
|
+
toolCalls: [...host.scratch.toolCalls.values()],
|
|
1528
|
+
diffs: host.scratch.diffs,
|
|
1529
|
+
thoughts: host.scratch.thoughts
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1393
1533
|
// src/client/permission.ts
|
|
1394
1534
|
function pickAllow(options) {
|
|
1395
1535
|
const ranked = [...options].sort((a, b) => {
|
|
@@ -2288,142 +2428,7 @@ var ACPSession = class _ACPSession {
|
|
|
2288
2428
|
// Prompt
|
|
2289
2429
|
// ──────────────────────────────────────────────────────────────────────
|
|
2290
2430
|
async prompt(blocks, signal, onProgress) {
|
|
2291
|
-
|
|
2292
|
-
throw new ACPSessionError("closed", "session is closed");
|
|
2293
|
-
}
|
|
2294
|
-
if (this.state !== "ready" && this.state !== "authenticated" && this.state !== "done") {
|
|
2295
|
-
throw new ACPSessionError("protocol_error", `prompt called in state=${this.state}`);
|
|
2296
|
-
}
|
|
2297
|
-
if (this.promptCallbackAbort) {
|
|
2298
|
-
throw new ACPSessionError("protocol_error", "prompt called while another prompt is running");
|
|
2299
|
-
}
|
|
2300
|
-
if (signal.aborted) {
|
|
2301
|
-
return emptyRunResult("cancelled");
|
|
2302
|
-
}
|
|
2303
|
-
const caps = this.agentCapabilities.promptCapabilities;
|
|
2304
|
-
for (const block of blocks) {
|
|
2305
|
-
const supported = block.type === "image" ? caps?.image : block.type === "audio" ? caps?.audio : block.type === "resource" ? caps?.embeddedContext : true;
|
|
2306
|
-
if (supported !== true) {
|
|
2307
|
-
throw new ACPSessionError(
|
|
2308
|
-
"unsupported_capability",
|
|
2309
|
-
`agent does not support ${block.type} prompt content`
|
|
2310
|
-
);
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
let cancelled = false;
|
|
2314
|
-
this.promptCallbackAbort = new AbortController();
|
|
2315
|
-
const onAbort = () => {
|
|
2316
|
-
cancelled = true;
|
|
2317
|
-
this.promptCallbackAbort?.abort();
|
|
2318
|
-
if (this.sessionId) {
|
|
2319
|
-
this.transport.send({
|
|
2320
|
-
jsonrpc: "2.0",
|
|
2321
|
-
method: "session/cancel",
|
|
2322
|
-
params: { sessionId: this.sessionId }
|
|
2323
|
-
}).catch(() => {
|
|
2324
|
-
});
|
|
2325
|
-
}
|
|
2326
|
-
};
|
|
2327
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
2328
|
-
let rejectCreate;
|
|
2329
|
-
const onCreateAbort = () => {
|
|
2330
|
-
signal.removeEventListener("abort", onAbort);
|
|
2331
|
-
rejectCreate?.(new ACPSessionError("aborted", "prompt was aborted by the parent"));
|
|
2332
|
-
};
|
|
2333
|
-
if (!this.sessionId) {
|
|
2334
|
-
let sessionId;
|
|
2335
|
-
const createPromise = this.createSessionWithAuth();
|
|
2336
|
-
try {
|
|
2337
|
-
sessionId = await Promise.race([
|
|
2338
|
-
createPromise,
|
|
2339
|
-
new Promise((_, reject) => {
|
|
2340
|
-
rejectCreate = reject;
|
|
2341
|
-
signal.addEventListener("abort", onCreateAbort, { once: true });
|
|
2342
|
-
})
|
|
2343
|
-
]);
|
|
2344
|
-
} catch (err) {
|
|
2345
|
-
signal.removeEventListener("abort", onAbort);
|
|
2346
|
-
signal.removeEventListener("abort", onCreateAbort);
|
|
2347
|
-
rejectCreate = void 0;
|
|
2348
|
-
this.promptCallbackAbort?.abort();
|
|
2349
|
-
this.promptCallbackAbort = null;
|
|
2350
|
-
if (err instanceof ACPSessionError && err.kind === "aborted") {
|
|
2351
|
-
this.cancelLateSession(createPromise);
|
|
2352
|
-
return emptyRunResult("cancelled");
|
|
2353
|
-
}
|
|
2354
|
-
throw err;
|
|
2355
|
-
}
|
|
2356
|
-
signal.removeEventListener("abort", onCreateAbort);
|
|
2357
|
-
rejectCreate = void 0;
|
|
2358
|
-
this.sessionId = sessionId;
|
|
2359
|
-
}
|
|
2360
|
-
if (signal.aborted) {
|
|
2361
|
-
this.promptCallbackAbort = null;
|
|
2362
|
-
return emptyRunResult("cancelled");
|
|
2363
|
-
}
|
|
2364
|
-
this.resetScratch();
|
|
2365
|
-
this.progressHandler = onProgress ?? null;
|
|
2366
|
-
const promptId = this.allocId();
|
|
2367
|
-
let rejectTurn;
|
|
2368
|
-
const onTurnAbort = () => {
|
|
2369
|
-
rejectTurn?.(new ACPSessionError("aborted", "prompt was aborted by the parent"));
|
|
2370
|
-
};
|
|
2371
|
-
signal.addEventListener("abort", onTurnAbort, { once: true });
|
|
2372
|
-
const turnPromise = Promise.race([
|
|
2373
|
-
this.sendRequest(
|
|
2374
|
-
promptId,
|
|
2375
|
-
"session/prompt",
|
|
2376
|
-
{
|
|
2377
|
-
sessionId: this.sessionId,
|
|
2378
|
-
prompt: blocks
|
|
2379
|
-
},
|
|
2380
|
-
this.timeoutMs
|
|
2381
|
-
),
|
|
2382
|
-
new Promise((_, reject) => {
|
|
2383
|
-
rejectTurn = reject;
|
|
2384
|
-
})
|
|
2385
|
-
]);
|
|
2386
|
-
this.state = "prompting";
|
|
2387
|
-
let response;
|
|
2388
|
-
try {
|
|
2389
|
-
response = await turnPromise;
|
|
2390
|
-
} catch (err) {
|
|
2391
|
-
this.state = "done";
|
|
2392
|
-
const abortedKind = err instanceof ACPSessionError && err.kind === "aborted";
|
|
2393
|
-
if (cancelled || abortedKind) {
|
|
2394
|
-
return emptyRunResult("cancelled");
|
|
2395
|
-
}
|
|
2396
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2397
|
-
if (signal.aborted) {
|
|
2398
|
-
throw new ACPSessionError("aborted", "prompt was aborted by the parent", err);
|
|
2399
|
-
}
|
|
2400
|
-
throw new ACPSessionError("prompt_failed", `session/prompt failed: ${msg}`, err);
|
|
2401
|
-
} finally {
|
|
2402
|
-
signal.removeEventListener("abort", onAbort);
|
|
2403
|
-
signal.removeEventListener("abort", onTurnAbort);
|
|
2404
|
-
signal.removeEventListener("abort", onCreateAbort);
|
|
2405
|
-
rejectTurn = void 0;
|
|
2406
|
-
rejectCreate = void 0;
|
|
2407
|
-
this.promptCallbackAbort?.abort();
|
|
2408
|
-
this.promptCallbackAbort = null;
|
|
2409
|
-
this.progressHandler = null;
|
|
2410
|
-
}
|
|
2411
|
-
this.state = "done";
|
|
2412
|
-
if (isJsonRpcError(response)) {
|
|
2413
|
-
throw new ACPSessionError("prompt_failed", `agent error: ${response.message}`, response);
|
|
2414
|
-
}
|
|
2415
|
-
const stopReason = response.stopReason ?? "end_turn";
|
|
2416
|
-
const finalText = this.scratch.text;
|
|
2417
|
-
return {
|
|
2418
|
-
text: finalText,
|
|
2419
|
-
stopReason,
|
|
2420
|
-
hasText: finalText.length > 0,
|
|
2421
|
-
usage: this.scratch.usage,
|
|
2422
|
-
plan: this.scratch.plan,
|
|
2423
|
-
toolCalls: [...this.scratch.toolCalls.values()],
|
|
2424
|
-
diffs: this.scratch.diffs,
|
|
2425
|
-
thoughts: this.scratch.thoughts
|
|
2426
|
-
};
|
|
2431
|
+
return prompt(this.acpSessionPromptHost(), blocks, signal, onProgress);
|
|
2427
2432
|
}
|
|
2428
2433
|
/**
|
|
2429
2434
|
* Best-effort cancel for a session the server confirmed after we already
|
|
@@ -2593,6 +2598,25 @@ var ACPSession = class _ACPSession {
|
|
|
2593
2598
|
void this.progressHandler;
|
|
2594
2599
|
return this;
|
|
2595
2600
|
}
|
|
2601
|
+
acpSessionPromptHost() {
|
|
2602
|
+
void {
|
|
2603
|
+
closed: this.closed,
|
|
2604
|
+
state: this.state,
|
|
2605
|
+
promptCallbackAbort: this.promptCallbackAbort,
|
|
2606
|
+
agentCapabilities: this.agentCapabilities,
|
|
2607
|
+
sessionId: this.sessionId,
|
|
2608
|
+
transport: this.transport,
|
|
2609
|
+
createSessionWithAuth: this.createSessionWithAuth,
|
|
2610
|
+
cancelLateSession: this.cancelLateSession,
|
|
2611
|
+
resetScratch: this.resetScratch,
|
|
2612
|
+
progressHandler: this.progressHandler,
|
|
2613
|
+
allocId: this.allocId,
|
|
2614
|
+
sendRequest: this.sendRequest,
|
|
2615
|
+
timeoutMs: this.timeoutMs,
|
|
2616
|
+
scratch: this.scratch
|
|
2617
|
+
};
|
|
2618
|
+
return this;
|
|
2619
|
+
}
|
|
2596
2620
|
};
|
|
2597
2621
|
|
|
2598
2622
|
// src/integration/acp-subagent-runner.ts
|