@ycodium-ai/agent-acp 0.2.3130 → 0.2.3158
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/index.js +269 -104
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -24862,7 +24862,10 @@ function createAcpConnection(options) {
|
|
|
24862
24862
|
}
|
|
24863
24863
|
pending.delete(key);
|
|
24864
24864
|
try {
|
|
24865
|
-
options.onResponse?.(
|
|
24865
|
+
options.onResponse?.(
|
|
24866
|
+
waiter,
|
|
24867
|
+
Object.hasOwn(message, "error") ? { error: message["error"] } : { result: message["result"] }
|
|
24868
|
+
);
|
|
24866
24869
|
} catch {
|
|
24867
24870
|
}
|
|
24868
24871
|
if (Object.hasOwn(message, "error")) {
|
|
@@ -24995,12 +24998,17 @@ function createAcpConnection(options) {
|
|
|
24995
24998
|
options.readable.on("end", onEnd);
|
|
24996
24999
|
options.readable.on("error", onError);
|
|
24997
25000
|
options.writable.once("error", onWritableError);
|
|
24998
|
-
const begin = (method, params) => {
|
|
25001
|
+
const begin = (method, params, promptId) => {
|
|
24999
25002
|
failIfClosed();
|
|
25000
25003
|
const id = nextRequestId;
|
|
25001
25004
|
nextRequestId += 1;
|
|
25002
25005
|
const { promise: promise2, resolve: resolve2, reject } = Promise.withResolvers();
|
|
25003
|
-
pending.set(String(id), {
|
|
25006
|
+
pending.set(String(id), {
|
|
25007
|
+
method,
|
|
25008
|
+
...promptId === void 0 ? {} : { promptId },
|
|
25009
|
+
resolve: resolve2,
|
|
25010
|
+
reject
|
|
25011
|
+
});
|
|
25004
25012
|
const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
|
|
25005
25013
|
const written = Promise.race([writeMessage(message), promise2]).then(
|
|
25006
25014
|
() => void 0,
|
|
@@ -25070,12 +25078,14 @@ function createExecutorLifecycle({
|
|
|
25070
25078
|
notifyPromptSettled,
|
|
25071
25079
|
eventStream,
|
|
25072
25080
|
onInputDead,
|
|
25073
|
-
shared
|
|
25081
|
+
shared,
|
|
25082
|
+
promptResults
|
|
25074
25083
|
}) {
|
|
25075
25084
|
const cancel = async (turnId) => {
|
|
25076
25085
|
failIfDisposed();
|
|
25077
25086
|
const started = requireStarted();
|
|
25078
25087
|
const targetTurnId = turnId ?? shared.activeTurnId;
|
|
25088
|
+
promptResults.stop(targetTurnId);
|
|
25079
25089
|
if (targetTurnId !== void 0) {
|
|
25080
25090
|
interruptedTurnIds.add(targetTurnId);
|
|
25081
25091
|
}
|
|
@@ -25086,6 +25096,9 @@ function createExecutorLifecycle({
|
|
|
25086
25096
|
if (shared.sessionId) {
|
|
25087
25097
|
await connection.notify("session/cancel", { sessionId: shared.sessionId });
|
|
25088
25098
|
}
|
|
25099
|
+
await promptResults.wait(targetTurnId);
|
|
25100
|
+
if (targetTurnId !== void 0 && shared.activeTurnId !== targetTurnId && !interruptedTurnIds.has(targetTurnId))
|
|
25101
|
+
return;
|
|
25089
25102
|
const settled = await waitForPromptIdle(cancelGraceMs);
|
|
25090
25103
|
if (!settled) {
|
|
25091
25104
|
throw new AcpExecutorCancelTimeoutError();
|
|
@@ -25106,6 +25119,7 @@ function createExecutorLifecycle({
|
|
|
25106
25119
|
payload: { state: "cancelled", stopReason: "cancelled" }
|
|
25107
25120
|
});
|
|
25108
25121
|
interruptedTurnIds.delete(targetTurnId);
|
|
25122
|
+
promptResults.forget(targetTurnId);
|
|
25109
25123
|
}
|
|
25110
25124
|
}
|
|
25111
25125
|
}
|
|
@@ -25180,33 +25194,39 @@ function createExecutorLifecycle({
|
|
|
25180
25194
|
if (!shared.disposed) emitSessionState("ready");
|
|
25181
25195
|
}
|
|
25182
25196
|
};
|
|
25183
|
-
|
|
25184
|
-
|
|
25185
|
-
|
|
25186
|
-
|
|
25197
|
+
let disposing;
|
|
25198
|
+
const dispose = () => {
|
|
25199
|
+
if (disposing) return disposing;
|
|
25200
|
+
shared.disposing = true;
|
|
25201
|
+
promptResults.stop();
|
|
25187
25202
|
settleAllApprovals("cancel");
|
|
25188
25203
|
settleAllUserInputs();
|
|
25189
25204
|
abortPendingSettlement("executor disposed");
|
|
25190
25205
|
notifyPromptSettled();
|
|
25191
25206
|
shared.abortLocalPrompt?.();
|
|
25192
|
-
|
|
25193
|
-
|
|
25194
|
-
|
|
25195
|
-
|
|
25196
|
-
|
|
25197
|
-
|
|
25198
|
-
|
|
25199
|
-
|
|
25200
|
-
|
|
25201
|
-
|
|
25202
|
-
|
|
25203
|
-
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
|
|
25208
|
-
|
|
25209
|
-
|
|
25207
|
+
disposing = (async () => {
|
|
25208
|
+
promptResults.finishUnreceived();
|
|
25209
|
+
await promptResults.wait();
|
|
25210
|
+
emit({
|
|
25211
|
+
type: "session.exited",
|
|
25212
|
+
...stamp(),
|
|
25213
|
+
provider: options.provider,
|
|
25214
|
+
threadId: options.threadId,
|
|
25215
|
+
payload: { reason: "disposed" }
|
|
25216
|
+
});
|
|
25217
|
+
shared.disposed = true;
|
|
25218
|
+
shared.generation += 1;
|
|
25219
|
+
shared.status = "disposed";
|
|
25220
|
+
eventStream.close();
|
|
25221
|
+
options.readable.off("end", onInputDead);
|
|
25222
|
+
options.readable.off("error", onInputDead);
|
|
25223
|
+
options.readable.pause();
|
|
25224
|
+
if (!shared.connectionClosed) {
|
|
25225
|
+
await connection.awaitInboundIdle().catch(() => void 0);
|
|
25226
|
+
await connection.close().catch(() => void 0);
|
|
25227
|
+
}
|
|
25228
|
+
})();
|
|
25229
|
+
return disposing;
|
|
25210
25230
|
};
|
|
25211
25231
|
return { cancel, compact, dispose };
|
|
25212
25232
|
}
|
|
@@ -25310,12 +25330,14 @@ function createExecutorPrompt({
|
|
|
25310
25330
|
promptMutex,
|
|
25311
25331
|
applyRequestedModel,
|
|
25312
25332
|
notifyPromptSettled,
|
|
25313
|
-
shared
|
|
25333
|
+
shared,
|
|
25334
|
+
promptResults
|
|
25314
25335
|
}) {
|
|
25315
25336
|
const settleTurn = (input2) => {
|
|
25316
|
-
if (!isLive(input2.expectedGeneration)) {
|
|
25337
|
+
if (!isLive(input2.expectedGeneration) || input2.record.finished) {
|
|
25317
25338
|
return false;
|
|
25318
25339
|
}
|
|
25340
|
+
promptResults.complete(input2.record);
|
|
25319
25341
|
if (!acpPromptSettlementBelongsToContext({
|
|
25320
25342
|
liveAcpSessionId: shared.sessionId ?? "",
|
|
25321
25343
|
expectedAcpSessionId: input2.expectedSessionId,
|
|
@@ -25332,6 +25354,7 @@ function createExecutorPrompt({
|
|
|
25332
25354
|
if (shared.status !== "disposed") {
|
|
25333
25355
|
shared.status = "ready";
|
|
25334
25356
|
}
|
|
25357
|
+
const interrupted = promptResults.hasInterrupted(input2.turnId);
|
|
25335
25358
|
emit({
|
|
25336
25359
|
type: "turn.completed",
|
|
25337
25360
|
...stamp(),
|
|
@@ -25339,30 +25362,44 @@ function createExecutorPrompt({
|
|
|
25339
25362
|
threadId: options.threadId,
|
|
25340
25363
|
turnId: input2.turnId,
|
|
25341
25364
|
payload: {
|
|
25342
|
-
state: input2.state,
|
|
25343
|
-
stopReason: input2.stopReason,
|
|
25365
|
+
state: interrupted ? "cancelled" : input2.state,
|
|
25366
|
+
stopReason: interrupted ? "cancelled" : input2.stopReason,
|
|
25344
25367
|
...input2.errorMessage === void 0 ? {} : { errorMessage: input2.errorMessage },
|
|
25345
25368
|
...input2.state === "failed" ? failureCategoryField(input2.failureCategory) : {}
|
|
25346
25369
|
}
|
|
25347
25370
|
});
|
|
25348
25371
|
interruptedTurnIds.delete(input2.turnId);
|
|
25372
|
+
promptResults.forget(input2.turnId);
|
|
25349
25373
|
return true;
|
|
25350
25374
|
};
|
|
25351
|
-
const sendPromptRpc = async (sessionId, promptParts, onWritten) => {
|
|
25375
|
+
const sendPromptRpc = async (sessionId, promptParts, onWritten, record2) => {
|
|
25352
25376
|
const settlementHooks = hooks.promptSettlement;
|
|
25353
25377
|
const promptKey = settlementHooks === void 0 ? void 0 : randomId();
|
|
25354
|
-
const pending = connection.begin(
|
|
25355
|
-
|
|
25356
|
-
|
|
25357
|
-
|
|
25358
|
-
|
|
25378
|
+
const pending = connection.begin(
|
|
25379
|
+
"session/prompt",
|
|
25380
|
+
{
|
|
25381
|
+
sessionId,
|
|
25382
|
+
prompt: promptParts,
|
|
25383
|
+
...settlementHooks !== void 0 && promptKey !== void 0 ? settlementHooks.requestFields(promptKey) : {}
|
|
25384
|
+
},
|
|
25385
|
+
record2?.promptId
|
|
25386
|
+
);
|
|
25359
25387
|
void pending.written.then(onWritten, () => void 0);
|
|
25360
25388
|
const promptRpc = pending.response;
|
|
25361
25389
|
if (settlementHooks === void 0 || promptKey === void 0) {
|
|
25362
25390
|
return await promptRpc;
|
|
25363
25391
|
} else {
|
|
25364
25392
|
const { promise: early, resolve: settleEarly } = Promise.withResolvers();
|
|
25365
|
-
shared.pendingSettlement = {
|
|
25393
|
+
shared.pendingSettlement = {
|
|
25394
|
+
promptKey,
|
|
25395
|
+
sessionId,
|
|
25396
|
+
settle: settleEarly,
|
|
25397
|
+
...record2 === void 0 ? {} : {
|
|
25398
|
+
onResponse: (response) => promptResults.receive(record2.promptId, response),
|
|
25399
|
+
onError: () => promptResults.reject(record2.promptId),
|
|
25400
|
+
hasResult: () => record2.response !== void 0
|
|
25401
|
+
}
|
|
25402
|
+
};
|
|
25366
25403
|
try {
|
|
25367
25404
|
const outcome = await Promise.race([
|
|
25368
25405
|
promptRpc.then((value) => {
|
|
@@ -25383,9 +25420,11 @@ function createExecutorPrompt({
|
|
|
25383
25420
|
const prompt = async (input2) => {
|
|
25384
25421
|
failIfDisposed();
|
|
25385
25422
|
const started = requireStarted();
|
|
25423
|
+
let record2;
|
|
25386
25424
|
const settle2 = (rest) => settleTurn({
|
|
25387
25425
|
expectedGeneration: started.generation,
|
|
25388
25426
|
expectedSessionId: started.sessionId,
|
|
25427
|
+
record: record2,
|
|
25389
25428
|
...rest
|
|
25390
25429
|
});
|
|
25391
25430
|
let turnId;
|
|
@@ -25398,6 +25437,17 @@ function createExecutorPrompt({
|
|
|
25398
25437
|
randomId
|
|
25399
25438
|
);
|
|
25400
25439
|
shared.promptsInFlight += 1;
|
|
25440
|
+
record2 = promptResults.add(
|
|
25441
|
+
{
|
|
25442
|
+
promptId: randomId(),
|
|
25443
|
+
sessionId: started.sessionId,
|
|
25444
|
+
generation: started.generation,
|
|
25445
|
+
turnId
|
|
25446
|
+
},
|
|
25447
|
+
() => {
|
|
25448
|
+
finishPrompt();
|
|
25449
|
+
}
|
|
25450
|
+
);
|
|
25401
25451
|
shared.activeTurnId = turnId;
|
|
25402
25452
|
shared.status = "running";
|
|
25403
25453
|
if (shared.promptsInFlight === 1) {
|
|
@@ -25414,6 +25464,42 @@ function createExecutorPrompt({
|
|
|
25414
25464
|
threadMutex.release();
|
|
25415
25465
|
}
|
|
25416
25466
|
const promptParts = input2.prompt ?? (input2.text !== void 0 ? [{ type: "text", text: input2.text }] : [{ type: "text", text: "" }]);
|
|
25467
|
+
let contextWindow;
|
|
25468
|
+
const finishPrompt = () => {
|
|
25469
|
+
if (!isLive(started.generation) || record2.finished) throw new AcpExecutorDisposedError();
|
|
25470
|
+
const response2 = record2.response;
|
|
25471
|
+
if (record2.interrupted || response2 === void 0) {
|
|
25472
|
+
settle2({ turnId, stopReason: "cancelled", state: "cancelled" });
|
|
25473
|
+
return { threadId: options.threadId, turnId, stopReason: "cancelled" };
|
|
25474
|
+
}
|
|
25475
|
+
const stopReason = hooks.completedStopReason?.(response2) ?? response2.stopReason;
|
|
25476
|
+
if (contextWindow !== void 0) {
|
|
25477
|
+
emit({
|
|
25478
|
+
type: "thread.token-usage.updated",
|
|
25479
|
+
...stamp(),
|
|
25480
|
+
provider: options.provider,
|
|
25481
|
+
threadId: options.threadId,
|
|
25482
|
+
turnId,
|
|
25483
|
+
payload: {
|
|
25484
|
+
usage: {
|
|
25485
|
+
usedTokens: contextWindow.usedTokens,
|
|
25486
|
+
...contextWindow.maxTokens === void 0 ? {} : { maxTokens: contextWindow.maxTokens }
|
|
25487
|
+
}
|
|
25488
|
+
}
|
|
25489
|
+
});
|
|
25490
|
+
}
|
|
25491
|
+
settle2({
|
|
25492
|
+
turnId,
|
|
25493
|
+
stopReason,
|
|
25494
|
+
state: response2.stopReason === "cancelled" ? "cancelled" : "completed"
|
|
25495
|
+
});
|
|
25496
|
+
return {
|
|
25497
|
+
threadId: options.threadId,
|
|
25498
|
+
turnId,
|
|
25499
|
+
stopReason,
|
|
25500
|
+
...response2.usage !== void 0 && response2.usage !== null ? { usage: response2.usage } : {}
|
|
25501
|
+
};
|
|
25502
|
+
};
|
|
25417
25503
|
await promptMutex.acquire();
|
|
25418
25504
|
let response;
|
|
25419
25505
|
try {
|
|
@@ -25428,6 +25514,7 @@ function createExecutorPrompt({
|
|
|
25428
25514
|
expectedGeneration: started.generation
|
|
25429
25515
|
});
|
|
25430
25516
|
}
|
|
25517
|
+
failIfDisposed();
|
|
25431
25518
|
if (isStale()) {
|
|
25432
25519
|
settle2({ turnId, stopReason: "cancelled", state: "cancelled" });
|
|
25433
25520
|
return { threadId: options.threadId, turnId, stopReason: "cancelled" };
|
|
@@ -25435,10 +25522,15 @@ function createExecutorPrompt({
|
|
|
25435
25522
|
closeActiveAssistantSegment(turnId);
|
|
25436
25523
|
let written = false;
|
|
25437
25524
|
try {
|
|
25438
|
-
response = await sendPromptRpc(
|
|
25439
|
-
|
|
25440
|
-
|
|
25441
|
-
|
|
25525
|
+
response = await sendPromptRpc(
|
|
25526
|
+
started.sessionId,
|
|
25527
|
+
promptParts,
|
|
25528
|
+
() => {
|
|
25529
|
+
written = true;
|
|
25530
|
+
input2.onDispatched?.(turnId);
|
|
25531
|
+
},
|
|
25532
|
+
record2
|
|
25533
|
+
);
|
|
25442
25534
|
} catch (error62) {
|
|
25443
25535
|
if (shared.disposed) {
|
|
25444
25536
|
throw new AcpExecutorDisposedError();
|
|
@@ -25477,8 +25569,7 @@ function createExecutorPrompt({
|
|
|
25477
25569
|
if (turnId === void 0) {
|
|
25478
25570
|
throw new AcpExecutorError("internal", "ACP prompt settled without a turn id");
|
|
25479
25571
|
}
|
|
25480
|
-
|
|
25481
|
-
let contextWindow;
|
|
25572
|
+
if (record2.finished) throw new AcpExecutorDisposedError();
|
|
25482
25573
|
if (hooks.readContextWindow !== void 0) {
|
|
25483
25574
|
try {
|
|
25484
25575
|
contextWindow = await hooks.readContextWindow({
|
|
@@ -25489,43 +25580,6 @@ function createExecutorPrompt({
|
|
|
25489
25580
|
contextWindow = void 0;
|
|
25490
25581
|
}
|
|
25491
25582
|
}
|
|
25492
|
-
const finishPrompt = () => {
|
|
25493
|
-
if (interruptedTurnIds.has(settledTurnId)) {
|
|
25494
|
-
settle2({ turnId: settledTurnId, stopReason: "cancelled", state: "cancelled" });
|
|
25495
|
-
return {
|
|
25496
|
-
threadId: options.threadId,
|
|
25497
|
-
turnId: settledTurnId,
|
|
25498
|
-
stopReason: "cancelled"
|
|
25499
|
-
};
|
|
25500
|
-
}
|
|
25501
|
-
const stopReason = hooks.completedStopReason?.(response) ?? response.stopReason;
|
|
25502
|
-
if (contextWindow !== void 0) {
|
|
25503
|
-
emit({
|
|
25504
|
-
type: "thread.token-usage.updated",
|
|
25505
|
-
...stamp(),
|
|
25506
|
-
provider: options.provider,
|
|
25507
|
-
threadId: options.threadId,
|
|
25508
|
-
turnId: settledTurnId,
|
|
25509
|
-
payload: {
|
|
25510
|
-
usage: {
|
|
25511
|
-
usedTokens: contextWindow.usedTokens,
|
|
25512
|
-
...contextWindow.maxTokens === void 0 ? {} : { maxTokens: contextWindow.maxTokens }
|
|
25513
|
-
}
|
|
25514
|
-
}
|
|
25515
|
-
});
|
|
25516
|
-
}
|
|
25517
|
-
settle2({
|
|
25518
|
-
turnId: settledTurnId,
|
|
25519
|
-
stopReason,
|
|
25520
|
-
state: response.stopReason === "cancelled" ? "cancelled" : "completed"
|
|
25521
|
-
});
|
|
25522
|
-
return {
|
|
25523
|
-
threadId: options.threadId,
|
|
25524
|
-
turnId: settledTurnId,
|
|
25525
|
-
stopReason,
|
|
25526
|
-
...response.usage !== void 0 && response.usage !== null ? { usage: response.usage } : {}
|
|
25527
|
-
};
|
|
25528
|
-
};
|
|
25529
25583
|
if (threadMutex.tryAcquire()) {
|
|
25530
25584
|
try {
|
|
25531
25585
|
return finishPrompt();
|
|
@@ -25543,6 +25597,91 @@ function createExecutorPrompt({
|
|
|
25543
25597
|
return { sendPromptRpc, prompt };
|
|
25544
25598
|
}
|
|
25545
25599
|
|
|
25600
|
+
// ../../packages/ycodium-acp-executor/src/executor/prompt-results.ts
|
|
25601
|
+
function createPromptResults({
|
|
25602
|
+
options,
|
|
25603
|
+
shared
|
|
25604
|
+
}) {
|
|
25605
|
+
const prompts = /* @__PURE__ */ new Map();
|
|
25606
|
+
const add = (identity, finish) => {
|
|
25607
|
+
const { promise: done, resolve: resolve2 } = Promise.withResolvers();
|
|
25608
|
+
const record2 = {
|
|
25609
|
+
...identity,
|
|
25610
|
+
finish,
|
|
25611
|
+
done,
|
|
25612
|
+
resolve: resolve2,
|
|
25613
|
+
rejected: false,
|
|
25614
|
+
interrupted: false,
|
|
25615
|
+
finished: false
|
|
25616
|
+
};
|
|
25617
|
+
prompts.set(record2.promptId, record2);
|
|
25618
|
+
return record2;
|
|
25619
|
+
};
|
|
25620
|
+
const receive = (promptId, response) => {
|
|
25621
|
+
const record2 = prompts.get(promptId);
|
|
25622
|
+
if (!record2 || record2.finished || record2.rejected || record2.response !== void 0) return;
|
|
25623
|
+
if (shared.disposed || shared.generation !== record2.generation || shared.sessionId !== record2.sessionId)
|
|
25624
|
+
return;
|
|
25625
|
+
record2.response = response;
|
|
25626
|
+
};
|
|
25627
|
+
const reject = (promptId) => {
|
|
25628
|
+
const record2 = prompts.get(promptId);
|
|
25629
|
+
if (record2 && record2.response === void 0) record2.rejected = true;
|
|
25630
|
+
};
|
|
25631
|
+
const stop = (turnId) => {
|
|
25632
|
+
for (const record2 of prompts.values()) {
|
|
25633
|
+
if (!record2.finished && (turnId === void 0 || record2.turnId === turnId) && record2.response === void 0) {
|
|
25634
|
+
record2.interrupted = true;
|
|
25635
|
+
}
|
|
25636
|
+
}
|
|
25637
|
+
};
|
|
25638
|
+
const complete = (record2) => {
|
|
25639
|
+
record2.finished = true;
|
|
25640
|
+
record2.resolve();
|
|
25641
|
+
};
|
|
25642
|
+
const hasInterrupted = (turnId) => [...prompts.values()].some((record2) => record2.turnId === turnId && record2.interrupted);
|
|
25643
|
+
const forget = (turnId) => {
|
|
25644
|
+
for (const [id, record2] of prompts) {
|
|
25645
|
+
if (record2.turnId === turnId) {
|
|
25646
|
+
complete(record2);
|
|
25647
|
+
prompts.delete(id);
|
|
25648
|
+
}
|
|
25649
|
+
}
|
|
25650
|
+
};
|
|
25651
|
+
const wait = async (turnId) => {
|
|
25652
|
+
const claimed = [...prompts.values()].filter(
|
|
25653
|
+
(record2) => !record2.finished && record2.response !== void 0 && (turnId === void 0 || record2.turnId === turnId)
|
|
25654
|
+
);
|
|
25655
|
+
if (claimed.length === 0) return;
|
|
25656
|
+
let timer;
|
|
25657
|
+
try {
|
|
25658
|
+
const drained = await Promise.race([
|
|
25659
|
+
Promise.all(claimed.map((record2) => record2.done)).then(() => true),
|
|
25660
|
+
new Promise((resolve2) => {
|
|
25661
|
+
timer = setTimeout(() => resolve2(false), options.resultDrainTimeoutMs ?? 2e3);
|
|
25662
|
+
})
|
|
25663
|
+
]);
|
|
25664
|
+
if (drained) return;
|
|
25665
|
+
options.log?.warn?.("ACP result settlement timed out", { threadId: options.threadId });
|
|
25666
|
+
for (const record2 of claimed) if (!record2.finished) record2.finish();
|
|
25667
|
+
} finally {
|
|
25668
|
+
clearTimeout(timer);
|
|
25669
|
+
}
|
|
25670
|
+
};
|
|
25671
|
+
const finishUnreceived = () => {
|
|
25672
|
+
const claimedTurns = new Set(
|
|
25673
|
+
[...prompts.values()].filter((record2) => !record2.finished && record2.response !== void 0).map((record2) => record2.turnId)
|
|
25674
|
+
);
|
|
25675
|
+
for (const record2 of prompts.values()) {
|
|
25676
|
+
if (!record2.finished && record2.response === void 0) {
|
|
25677
|
+
if (claimedTurns.has(record2.turnId)) record2.finish();
|
|
25678
|
+
else complete(record2);
|
|
25679
|
+
}
|
|
25680
|
+
}
|
|
25681
|
+
};
|
|
25682
|
+
return { add, receive, reject, stop, complete, hasInterrupted, forget, wait, finishUnreceived };
|
|
25683
|
+
}
|
|
25684
|
+
|
|
25546
25685
|
// ../../packages/ycodium-acp-executor/src/user-input-pending.ts
|
|
25547
25686
|
var userInputAnswerOptionId = (question, answers) => {
|
|
25548
25687
|
const answer = answers[question.id];
|
|
@@ -25849,7 +25988,7 @@ function createExecutorRuntime({
|
|
|
25849
25988
|
turnId: () => shared.activeTurnId
|
|
25850
25989
|
});
|
|
25851
25990
|
const failIfDisposed = () => {
|
|
25852
|
-
if (shared.disposed) {
|
|
25991
|
+
if (shared.disposed || shared.disposing) {
|
|
25853
25992
|
throw new AcpExecutorDisposedError();
|
|
25854
25993
|
}
|
|
25855
25994
|
};
|
|
@@ -26441,6 +26580,7 @@ function createExecutorSettlement({
|
|
|
26441
26580
|
const abortPendingSettlement = (reason, failureCategory) => {
|
|
26442
26581
|
const waiting = shared.pendingSettlement;
|
|
26443
26582
|
if (waiting === void 0) return;
|
|
26583
|
+
if (waiting.hasResult?.()) return;
|
|
26444
26584
|
shared.pendingSettlement = void 0;
|
|
26445
26585
|
waiting.settle({
|
|
26446
26586
|
error: withFailureCategory(
|
|
@@ -26462,6 +26602,7 @@ function createExecutorSettlement({
|
|
|
26462
26602
|
shared.pendingSettlement = void 0;
|
|
26463
26603
|
rememberSettledPromptKey(waiting.promptKey);
|
|
26464
26604
|
if (signal.outcome === "error") {
|
|
26605
|
+
waiting.onError?.();
|
|
26465
26606
|
waiting.settle({
|
|
26466
26607
|
error: withFailureCategory(
|
|
26467
26608
|
new AcpExecutorRequestError(
|
|
@@ -26472,8 +26613,10 @@ function createExecutorSettlement({
|
|
|
26472
26613
|
)
|
|
26473
26614
|
});
|
|
26474
26615
|
} else {
|
|
26616
|
+
const response = { stopReason: signal.stopReason ?? "end_turn" };
|
|
26617
|
+
waiting.onResponse?.(response);
|
|
26475
26618
|
waiting.settle({
|
|
26476
|
-
response
|
|
26619
|
+
response
|
|
26477
26620
|
});
|
|
26478
26621
|
}
|
|
26479
26622
|
return true;
|
|
@@ -26803,6 +26946,7 @@ function createAcpExecutor(options) {
|
|
|
26803
26946
|
const shared = {
|
|
26804
26947
|
generation: 0,
|
|
26805
26948
|
disposed: false,
|
|
26949
|
+
disposing: false,
|
|
26806
26950
|
status: "idle",
|
|
26807
26951
|
sessionId: void 0,
|
|
26808
26952
|
modelSelectionState: {
|
|
@@ -26890,6 +27034,7 @@ function createAcpExecutor(options) {
|
|
|
26890
27034
|
shared
|
|
26891
27035
|
});
|
|
26892
27036
|
const { rememberSettledPromptKey, abortPendingSettlement, settleFromNotification } = createExecutorSettlement({ hooks, shared });
|
|
27037
|
+
const promptResults = createPromptResults({ options, shared });
|
|
26893
27038
|
const connection = createAcpConnection({
|
|
26894
27039
|
readable: options.readable,
|
|
26895
27040
|
writable: options.writable,
|
|
@@ -26900,8 +27045,12 @@ function createAcpExecutor(options) {
|
|
|
26900
27045
|
});
|
|
26901
27046
|
},
|
|
26902
27047
|
// 窗口在应答帧到达的那一刻同步收掉:应答之后的通知是真输出,不能再丢。
|
|
26903
|
-
onResponse: (method) => {
|
|
27048
|
+
onResponse: ({ method, promptId }, outcome) => {
|
|
26904
27049
|
if (method === "session/load") shared.sessionLoadInFlight = false;
|
|
27050
|
+
if (promptId !== void 0) {
|
|
27051
|
+
if ("result" in outcome) promptResults.receive(promptId, outcome.result);
|
|
27052
|
+
else promptResults.reject(promptId);
|
|
27053
|
+
}
|
|
26905
27054
|
},
|
|
26906
27055
|
onNotification: (notification) => {
|
|
26907
27056
|
if (notification.method === "session/update") {
|
|
@@ -26966,6 +27115,7 @@ function createAcpExecutor(options) {
|
|
|
26966
27115
|
shared
|
|
26967
27116
|
});
|
|
26968
27117
|
const { sendPromptRpc, prompt } = createExecutorPrompt({
|
|
27118
|
+
promptResults,
|
|
26969
27119
|
isLive,
|
|
26970
27120
|
closeActiveAssistantSegment,
|
|
26971
27121
|
emit,
|
|
@@ -26985,6 +27135,7 @@ function createAcpExecutor(options) {
|
|
|
26985
27135
|
shared
|
|
26986
27136
|
});
|
|
26987
27137
|
const { cancel, compact, dispose } = createExecutorLifecycle({
|
|
27138
|
+
promptResults,
|
|
26988
27139
|
failIfDisposed,
|
|
26989
27140
|
requireStarted,
|
|
26990
27141
|
interruptedTurnIds,
|
|
@@ -27036,6 +27187,27 @@ function createAcpExecutor(options) {
|
|
|
27036
27187
|
};
|
|
27037
27188
|
}
|
|
27038
27189
|
|
|
27190
|
+
// ../../packages/ycodium-acp-executor/src/session-registry.ts
|
|
27191
|
+
function createAcpSessionRegistry(threads, stopBooked2) {
|
|
27192
|
+
const requireThread = (threadId) => {
|
|
27193
|
+
const booked = threads.get(threadId);
|
|
27194
|
+
if (!booked) throw new Error(`unknown thread ${threadId}`);
|
|
27195
|
+
if (booked.closing) throw new Error(`thread ${threadId} is closing`);
|
|
27196
|
+
return booked;
|
|
27197
|
+
};
|
|
27198
|
+
const stopSession = (threadId, booked = threads.get(threadId)) => {
|
|
27199
|
+
if (!booked) return Promise.resolve();
|
|
27200
|
+
booked.closing ??= Promise.resolve().then(() => stopBooked2(booked)).then(() => {
|
|
27201
|
+
if (threads.get(threadId) === booked) threads.delete(threadId);
|
|
27202
|
+
});
|
|
27203
|
+
return booked.closing;
|
|
27204
|
+
};
|
|
27205
|
+
const stopAll = () => Promise.all([...threads].map(([threadId, booked]) => stopSession(threadId, booked))).then(
|
|
27206
|
+
() => void 0
|
|
27207
|
+
);
|
|
27208
|
+
return { requireThread, stopSession, stopAll };
|
|
27209
|
+
}
|
|
27210
|
+
|
|
27039
27211
|
// ../../packages/ycodium-acp-executor/src/prompt-dispatch.ts
|
|
27040
27212
|
var dispatchAcpPrompt = (executor, input2) => {
|
|
27041
27213
|
const { promise: dispatched, resolve: resolve2 } = Promise.withResolvers();
|
|
@@ -27565,11 +27737,8 @@ var createAcpInstance = (config2, host) => {
|
|
|
27565
27737
|
const events = new EventBus();
|
|
27566
27738
|
const threads = /* @__PURE__ */ new Map();
|
|
27567
27739
|
let disposed = false;
|
|
27568
|
-
|
|
27569
|
-
|
|
27570
|
-
if (!booked) throw new Error(`unknown thread ${threadId}`);
|
|
27571
|
-
return booked;
|
|
27572
|
-
};
|
|
27740
|
+
let disposeTask;
|
|
27741
|
+
const { requireThread, stopSession, stopAll } = createAcpSessionRegistry(threads, stopBooked);
|
|
27573
27742
|
const instance = {
|
|
27574
27743
|
probe: async () => {
|
|
27575
27744
|
if (recipe.binaryPath.length === 0) {
|
|
@@ -27634,8 +27803,8 @@ var createAcpInstance = (config2, host) => {
|
|
|
27634
27803
|
if (cwd.trim() === "") throw new Error("workspace path missing");
|
|
27635
27804
|
const existing = threads.get(input2.threadId);
|
|
27636
27805
|
if (existing !== void 0) {
|
|
27637
|
-
await
|
|
27638
|
-
|
|
27806
|
+
await stopSession(input2.threadId, existing);
|
|
27807
|
+
if (disposed) throw new Error("instance disposed");
|
|
27639
27808
|
throwIfStartAborted(signal);
|
|
27640
27809
|
}
|
|
27641
27810
|
const env = buildSpawnEnv(recipe, recipe.homePath);
|
|
@@ -27763,7 +27932,7 @@ var createAcpInstance = (config2, host) => {
|
|
|
27763
27932
|
},
|
|
27764
27933
|
interruptTurn: async (threadId, turnId) => {
|
|
27765
27934
|
const booked = threads.get(threadId);
|
|
27766
|
-
if (booked === void 0) return;
|
|
27935
|
+
if (booked === void 0 || booked.closing) return;
|
|
27767
27936
|
host.log.info("interrupt turn", { threadId, turnId });
|
|
27768
27937
|
await booked.executor.cancel(turnId);
|
|
27769
27938
|
await yieldTick();
|
|
@@ -27804,25 +27973,21 @@ var createAcpInstance = (config2, host) => {
|
|
|
27804
27973
|
updatedAt: nowIso()
|
|
27805
27974
|
};
|
|
27806
27975
|
},
|
|
27807
|
-
stopSession:
|
|
27808
|
-
const booked = threads.get(threadId);
|
|
27809
|
-
if (booked === void 0) return;
|
|
27810
|
-
threads.delete(threadId);
|
|
27811
|
-
await stopBooked(booked);
|
|
27812
|
-
},
|
|
27976
|
+
stopSession: (threadId) => stopSession(threadId),
|
|
27813
27977
|
readThread: async (threadId) => {
|
|
27814
27978
|
const booked = requireThread(threadId);
|
|
27815
27979
|
return { threadId, turns: booked.turns };
|
|
27816
27980
|
},
|
|
27817
27981
|
events,
|
|
27818
27982
|
continuationKey: acpContinuationKey(recipe),
|
|
27819
|
-
dispose:
|
|
27820
|
-
if (
|
|
27983
|
+
dispose: () => {
|
|
27984
|
+
if (disposeTask) return disposeTask;
|
|
27821
27985
|
disposed = true;
|
|
27822
|
-
|
|
27823
|
-
|
|
27824
|
-
|
|
27825
|
-
|
|
27986
|
+
disposeTask = (async () => {
|
|
27987
|
+
await stopAll();
|
|
27988
|
+
events.close();
|
|
27989
|
+
})();
|
|
27990
|
+
return disposeTask;
|
|
27826
27991
|
}
|
|
27827
27992
|
};
|
|
27828
27993
|
return instance;
|
|
@@ -27840,7 +28005,7 @@ var executors = [
|
|
|
27840
28005
|
];
|
|
27841
28006
|
var index_default = definePlugin({
|
|
27842
28007
|
id: "agent-acp",
|
|
27843
|
-
apiVersion:
|
|
28008
|
+
apiVersion: 15,
|
|
27844
28009
|
executors,
|
|
27845
28010
|
activate(ctx) {
|
|
27846
28011
|
ctx.log.info("generic ACP executor ready");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/agent-acp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3158",
|
|
4
4
|
"description": "Generic ACP executor: user-supplied CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"@types/node": "24.12.4",
|
|
22
22
|
"esbuild": "0.28.1",
|
|
23
23
|
"vite-plus": "0.2.2",
|
|
24
|
-
"ycodium-
|
|
25
|
-
"
|
|
26
|
-
"ycodium-
|
|
24
|
+
"ycodium-executor-testing": "0.0.0",
|
|
25
|
+
"ycodium-acp-executor": "0.2.3158",
|
|
26
|
+
"@ycodium-ai/plugin-api": "0.2.3158"
|
|
27
27
|
},
|
|
28
28
|
"ycodium": {
|
|
29
29
|
"plugin": "./dist/index.js",
|