@ycodium-ai/agent-acp 0.2.3254 → 0.2.3272
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 +277 -47
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -10,7 +10,11 @@ import { definePlugin } from "@ycodium-ai/plugin-api";
|
|
|
10
10
|
// src/acpInstance.ts
|
|
11
11
|
import * as NodeOS3 from "node:os";
|
|
12
12
|
import * as NodePath4 from "node:path";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
mergeLaunchEnv,
|
|
15
|
+
modelSelectionStringOption,
|
|
16
|
+
raceAbort as raceAbort2
|
|
17
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
14
18
|
import { nodeStreamsFromHandle as nodeStreamsFromHandle2 } from "@ycodium-ai/plugin-api/process-stdin";
|
|
15
19
|
|
|
16
20
|
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
@@ -25043,11 +25047,15 @@ function createAcpConnection(options) {
|
|
|
25043
25047
|
});
|
|
25044
25048
|
};
|
|
25045
25049
|
const close = (error62) => shutdown(error62 ?? new AcpConnectionClosedError());
|
|
25050
|
+
const abandonPending = (error62) => {
|
|
25051
|
+
rejectPending(error62);
|
|
25052
|
+
};
|
|
25046
25053
|
return {
|
|
25047
25054
|
request,
|
|
25048
25055
|
begin,
|
|
25049
25056
|
notify,
|
|
25050
25057
|
awaitInboundIdle,
|
|
25058
|
+
abandonPending,
|
|
25051
25059
|
close,
|
|
25052
25060
|
closed
|
|
25053
25061
|
};
|
|
@@ -25513,10 +25521,11 @@ function createExecutorPrompt({
|
|
|
25513
25521
|
const prompt = async (input2) => {
|
|
25514
25522
|
failIfPromptUnavailable();
|
|
25515
25523
|
const started = requireStarted();
|
|
25524
|
+
let sessionId = started.sessionId;
|
|
25516
25525
|
let record2;
|
|
25517
25526
|
const settle2 = (rest) => settleTurn({
|
|
25518
25527
|
expectedGeneration: started.generation,
|
|
25519
|
-
expectedSessionId:
|
|
25528
|
+
expectedSessionId: sessionId,
|
|
25520
25529
|
record: record2,
|
|
25521
25530
|
...rest
|
|
25522
25531
|
});
|
|
@@ -25600,12 +25609,32 @@ function createExecutorPrompt({
|
|
|
25600
25609
|
const queuedTurnId = turnId;
|
|
25601
25610
|
const isStale = () => interruptedTurnIds.has(queuedTurnId) || input2.expectedActiveTurnId !== void 0 && shared.activeTurnId !== queuedTurnId;
|
|
25602
25611
|
if (!isStale()) {
|
|
25603
|
-
|
|
25604
|
-
|
|
25605
|
-
|
|
25606
|
-
|
|
25607
|
-
|
|
25608
|
-
|
|
25612
|
+
try {
|
|
25613
|
+
const applied = await applyRequestedModel({
|
|
25614
|
+
state: shared.modelSelectionState,
|
|
25615
|
+
acpSessionId: sessionId,
|
|
25616
|
+
setup: shared.startResult?.sessionSetupResult ?? {},
|
|
25617
|
+
requestedModelId: input2.requestedModelId,
|
|
25618
|
+
expectedGeneration: started.generation
|
|
25619
|
+
});
|
|
25620
|
+
shared.modelSelectionState = applied.state;
|
|
25621
|
+
sessionId = applied.sessionId;
|
|
25622
|
+
record2.sessionId = applied.sessionId;
|
|
25623
|
+
} catch (error62) {
|
|
25624
|
+
const failureCategory = readAcpFailureCategory(error62);
|
|
25625
|
+
if (failureCategory === "model-unavailable") {
|
|
25626
|
+
const errorMessage = error62 instanceof Error && error62.message.trim().length > 0 ? error62.message : "Requested model is not in this agent's catalog. This turn was not sent.";
|
|
25627
|
+
settle2({
|
|
25628
|
+
turnId,
|
|
25629
|
+
stopReason: "error",
|
|
25630
|
+
state: "failed",
|
|
25631
|
+
errorMessage,
|
|
25632
|
+
failureCategory
|
|
25633
|
+
});
|
|
25634
|
+
throw error62 instanceof Error ? withFailureCategory(error62, failureCategory) : error62;
|
|
25635
|
+
}
|
|
25636
|
+
throw error62;
|
|
25637
|
+
}
|
|
25609
25638
|
}
|
|
25610
25639
|
failIfDisposed();
|
|
25611
25640
|
if (isStale()) {
|
|
@@ -25616,7 +25645,7 @@ function createExecutorPrompt({
|
|
|
25616
25645
|
let written = false;
|
|
25617
25646
|
try {
|
|
25618
25647
|
response = await sendPromptRpc(
|
|
25619
|
-
|
|
25648
|
+
sessionId,
|
|
25620
25649
|
promptParts,
|
|
25621
25650
|
() => {
|
|
25622
25651
|
written = true;
|
|
@@ -25666,7 +25695,7 @@ function createExecutorPrompt({
|
|
|
25666
25695
|
if (hooks.readContextWindow !== void 0) {
|
|
25667
25696
|
try {
|
|
25668
25697
|
contextWindow = await hooks.readContextWindow({
|
|
25669
|
-
sessionId
|
|
25698
|
+
sessionId,
|
|
25670
25699
|
promptResponse: response
|
|
25671
25700
|
}) ?? void 0;
|
|
25672
25701
|
} catch {
|
|
@@ -26341,6 +26370,56 @@ function acpInitializePayload(clientInfo, overrides) {
|
|
|
26341
26370
|
};
|
|
26342
26371
|
}
|
|
26343
26372
|
|
|
26373
|
+
// ../../packages/ycodium-acp-executor/src/refreshDeadline.ts
|
|
26374
|
+
var MODEL_CATALOG_REFRESH_TIMEOUT_MS = 9e4;
|
|
26375
|
+
|
|
26376
|
+
// ../../packages/ycodium-acp-executor/src/model-send.ts
|
|
26377
|
+
function judgeRequestedModel(input2) {
|
|
26378
|
+
const requested = normalizeModelId(input2.requestedModelId);
|
|
26379
|
+
const current = input2.state.currentModelId;
|
|
26380
|
+
if (requested === void 0 || requested === current) return { kind: "keep" };
|
|
26381
|
+
const hasCatalog = input2.state.advertisedModelValues.length > 0;
|
|
26382
|
+
const hasCurrent = current !== void 0;
|
|
26383
|
+
if (!hasCatalog && !hasCurrent) return { kind: "keep" };
|
|
26384
|
+
const canSwitch = input2.state.strategy === "session/set_model" && input2.state.sessionModelsAdvertised || input2.state.strategy === "config-option" && input2.state.modelConfigId !== void 0;
|
|
26385
|
+
const value = hasCatalog ? matchAdvertisedModelValue(requested, input2.state.advertisedModelValues) : void 0;
|
|
26386
|
+
if (value !== void 0 && value === current) return { kind: "keep" };
|
|
26387
|
+
if (value !== void 0 && canSwitch) return { kind: "switch", value };
|
|
26388
|
+
return input2.refreshed ? { kind: "unavailable" } : { kind: "refresh" };
|
|
26389
|
+
}
|
|
26390
|
+
function modelUnavailableError(requestedModelId, currentModelId) {
|
|
26391
|
+
const current = currentModelId ?? "its own model";
|
|
26392
|
+
return withFailureCategory(
|
|
26393
|
+
new Error(
|
|
26394
|
+
`Requested model "${requestedModelId}" is not in this agent's catalog; it is on "${current}". This turn was not sent. Refresh the model list in this agent's settings and try again.`
|
|
26395
|
+
),
|
|
26396
|
+
"model-unavailable"
|
|
26397
|
+
);
|
|
26398
|
+
}
|
|
26399
|
+
var ModelCatalogRefreshTimeoutError = class extends Error {
|
|
26400
|
+
constructor() {
|
|
26401
|
+
super("model catalog refresh timed out");
|
|
26402
|
+
this.name = "ModelCatalogRefreshTimeoutError";
|
|
26403
|
+
}
|
|
26404
|
+
};
|
|
26405
|
+
function modelRefreshTimedOutError(requestedModelId) {
|
|
26406
|
+
return withFailureCategory(
|
|
26407
|
+
new Error(
|
|
26408
|
+
`Refreshing this agent's model list timed out, so this turn was not sent. Requested model "${requestedModelId}".`
|
|
26409
|
+
),
|
|
26410
|
+
"model-unavailable"
|
|
26411
|
+
);
|
|
26412
|
+
}
|
|
26413
|
+
function modelRefreshFailedError(requestedModelId, error62) {
|
|
26414
|
+
const detail = error62 instanceof Error && error62.message.trim().length > 0 ? error62.message : "the model list could not be read";
|
|
26415
|
+
return withFailureCategory(
|
|
26416
|
+
new Error(
|
|
26417
|
+
`Refreshing this agent's model list failed (${detail}), so this turn was not sent. Requested model "${requestedModelId}".`
|
|
26418
|
+
),
|
|
26419
|
+
"model-unavailable"
|
|
26420
|
+
);
|
|
26421
|
+
}
|
|
26422
|
+
|
|
26344
26423
|
// ../../packages/ycodium-acp-executor/src/runtime-mode.ts
|
|
26345
26424
|
function isRecord5(value) {
|
|
26346
26425
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -26424,43 +26503,131 @@ function createExecutorSession({
|
|
|
26424
26503
|
failIfDisposed,
|
|
26425
26504
|
shared
|
|
26426
26505
|
}) {
|
|
26427
|
-
const
|
|
26428
|
-
const
|
|
26429
|
-
if (
|
|
26430
|
-
|
|
26431
|
-
}
|
|
26432
|
-
const value = matchAdvertisedModelValue(requestedModelId, input2.state.advertisedModelValues);
|
|
26433
|
-
if (value === void 0) {
|
|
26434
|
-
if (requestedModelId !== shared.lastUnmatchedModelId) {
|
|
26435
|
-
shared.lastUnmatchedModelId = requestedModelId;
|
|
26436
|
-
options.log?.info("requested model is not in the agent catalog; keeping its own model", {
|
|
26437
|
-
requestedModelId,
|
|
26438
|
-
currentModelId: input2.state.currentModelId,
|
|
26439
|
-
advertisedModelValues: input2.state.advertisedModelValues
|
|
26440
|
-
});
|
|
26441
|
-
}
|
|
26442
|
-
return input2.state;
|
|
26506
|
+
const openFreshSession = async (expectedGeneration) => {
|
|
26507
|
+
const initialized = shared.initializeResult;
|
|
26508
|
+
if (initialized === void 0) {
|
|
26509
|
+
throw new Error("no handshake");
|
|
26443
26510
|
}
|
|
26444
|
-
|
|
26445
|
-
|
|
26511
|
+
const mcpServers = filterMcpServersByAgentCapabilities(
|
|
26512
|
+
options.mcpServers ?? [],
|
|
26513
|
+
initialized.agentCapabilities
|
|
26514
|
+
);
|
|
26515
|
+
const additionalDirectories = options.additionalDirectories !== void 0 && options.additionalDirectories.length > 0 ? { additionalDirectories: options.additionalDirectories } : {};
|
|
26516
|
+
const created = await connection.request("session/new", {
|
|
26517
|
+
cwd: options.cwd,
|
|
26518
|
+
mcpServers,
|
|
26519
|
+
...additionalDirectories
|
|
26520
|
+
});
|
|
26521
|
+
if (!isLive(expectedGeneration)) {
|
|
26522
|
+
throw new AcpExecutorDisposedError();
|
|
26523
|
+
}
|
|
26524
|
+
if (created.sessionId === void 0 || created.sessionId.length === 0) {
|
|
26525
|
+
throw new Error("session/new did not return a session id");
|
|
26446
26526
|
}
|
|
26527
|
+
return { sessionId: created.sessionId, setup: created };
|
|
26528
|
+
};
|
|
26529
|
+
const switchModel = async (input2) => {
|
|
26447
26530
|
let configOptions = input2.state.configOptions;
|
|
26448
26531
|
if (input2.state.strategy === "config-option") {
|
|
26449
26532
|
const switched = await connection.request(
|
|
26450
26533
|
"session/set_config_option",
|
|
26451
|
-
{ sessionId: input2.
|
|
26534
|
+
{ sessionId: input2.sessionId, configId: input2.state.modelConfigId, value: input2.value }
|
|
26452
26535
|
);
|
|
26453
26536
|
configOptions = switched?.configOptions ?? configOptions;
|
|
26454
26537
|
} else {
|
|
26455
26538
|
await connection.request("session/set_model", {
|
|
26456
|
-
sessionId: input2.
|
|
26457
|
-
modelId: value
|
|
26539
|
+
sessionId: input2.sessionId,
|
|
26540
|
+
modelId: input2.value
|
|
26458
26541
|
});
|
|
26459
26542
|
}
|
|
26460
26543
|
if (!isLive(input2.expectedGeneration)) {
|
|
26461
26544
|
throw new AcpExecutorDisposedError();
|
|
26462
26545
|
}
|
|
26463
|
-
return { ...input2.state, currentModelId: value, configOptions };
|
|
26546
|
+
return { ...input2.state, currentModelId: input2.value, configOptions };
|
|
26547
|
+
};
|
|
26548
|
+
const adoptReopenedSession = (applied) => {
|
|
26549
|
+
if (shared.sessionId === void 0 && shared.startResult === void 0) return;
|
|
26550
|
+
const setup = applied.setup;
|
|
26551
|
+
shared.sessionId = applied.sessionId;
|
|
26552
|
+
shared.modelSelectionState = applied.state;
|
|
26553
|
+
shared.modeState = parseSessionModeState(setup);
|
|
26554
|
+
if (shared.startResult !== void 0) {
|
|
26555
|
+
shared.startResult = {
|
|
26556
|
+
...shared.startResult,
|
|
26557
|
+
sessionId: applied.sessionId,
|
|
26558
|
+
sessionSetupResult: setup,
|
|
26559
|
+
modelConfigId: extractModelConfigId(setup),
|
|
26560
|
+
modelId: applied.state.currentModelId
|
|
26561
|
+
};
|
|
26562
|
+
}
|
|
26563
|
+
};
|
|
26564
|
+
const applyRequestedModel = async (input2) => {
|
|
26565
|
+
async function applyOnce(state, sessionId, setup, refreshed) {
|
|
26566
|
+
const requestedModelId = normalizeModelId(input2.requestedModelId) ?? "";
|
|
26567
|
+
const judgment = judgeRequestedModel({
|
|
26568
|
+
state,
|
|
26569
|
+
requestedModelId: input2.requestedModelId,
|
|
26570
|
+
refreshed
|
|
26571
|
+
});
|
|
26572
|
+
if (judgment.kind === "keep") return { state, sessionId, setup };
|
|
26573
|
+
if (judgment.kind === "unavailable") {
|
|
26574
|
+
throw modelUnavailableError(requestedModelId, state.currentModelId);
|
|
26575
|
+
}
|
|
26576
|
+
if (judgment.kind === "switch") {
|
|
26577
|
+
return {
|
|
26578
|
+
state: await switchModel({
|
|
26579
|
+
state,
|
|
26580
|
+
sessionId,
|
|
26581
|
+
value: judgment.value,
|
|
26582
|
+
expectedGeneration: input2.expectedGeneration
|
|
26583
|
+
}),
|
|
26584
|
+
sessionId,
|
|
26585
|
+
setup
|
|
26586
|
+
};
|
|
26587
|
+
}
|
|
26588
|
+
return refreshAndRejudge(requestedModelId);
|
|
26589
|
+
}
|
|
26590
|
+
async function refreshAndRejudge(requestedModelId) {
|
|
26591
|
+
const timeoutMs = options.modelCatalogRefreshTimeoutMs ?? MODEL_CATALOG_REFRESH_TIMEOUT_MS;
|
|
26592
|
+
let timedOut = false;
|
|
26593
|
+
const timeoutError = new ModelCatalogRefreshTimeoutError();
|
|
26594
|
+
let timer;
|
|
26595
|
+
const work = (async () => {
|
|
26596
|
+
await options.refreshCatalogForSend?.();
|
|
26597
|
+
if (timedOut) throw timeoutError;
|
|
26598
|
+
const reopened = await openFreshSession(input2.expectedGeneration);
|
|
26599
|
+
if (timedOut) throw timeoutError;
|
|
26600
|
+
const next = modelSelectionStateFromSetup(reopened.setup);
|
|
26601
|
+
const applied = await applyOnce(next, reopened.sessionId, reopened.setup, true);
|
|
26602
|
+
if (timedOut) throw timeoutError;
|
|
26603
|
+
adoptReopenedSession(applied);
|
|
26604
|
+
return applied;
|
|
26605
|
+
})();
|
|
26606
|
+
void work.then(
|
|
26607
|
+
() => void 0,
|
|
26608
|
+
() => void 0
|
|
26609
|
+
);
|
|
26610
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
26611
|
+
timer = setTimeout(() => {
|
|
26612
|
+
timedOut = true;
|
|
26613
|
+
connection.abandonPending(timeoutError);
|
|
26614
|
+
reject(timeoutError);
|
|
26615
|
+
}, timeoutMs);
|
|
26616
|
+
});
|
|
26617
|
+
try {
|
|
26618
|
+
return await Promise.race([work, deadline]);
|
|
26619
|
+
} catch (error62) {
|
|
26620
|
+
if (error62 instanceof AcpExecutorDisposedError) throw error62;
|
|
26621
|
+
if (timedOut || error62 instanceof ModelCatalogRefreshTimeoutError) {
|
|
26622
|
+
throw modelRefreshTimedOutError(requestedModelId);
|
|
26623
|
+
}
|
|
26624
|
+
if (readAcpFailureCategory(error62) === "model-unavailable") throw error62;
|
|
26625
|
+
throw modelRefreshFailedError(requestedModelId, error62);
|
|
26626
|
+
} finally {
|
|
26627
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
26628
|
+
}
|
|
26629
|
+
}
|
|
26630
|
+
return applyOnce(input2.state, input2.acpSessionId, input2.setup, false);
|
|
26464
26631
|
};
|
|
26465
26632
|
const startOnce = async (expectedGeneration) => {
|
|
26466
26633
|
const initializePayload = acpInitializePayload(options.clientInfo, options.clientCapabilities);
|
|
@@ -26529,12 +26696,17 @@ function createExecutorSession({
|
|
|
26529
26696
|
categories: unhandledCategories
|
|
26530
26697
|
});
|
|
26531
26698
|
}
|
|
26532
|
-
const
|
|
26533
|
-
|
|
26699
|
+
const openedSetup = setup;
|
|
26700
|
+
const appliedModel = await applyRequestedModel({
|
|
26701
|
+
state: modelSelectionStateFromSetup(openedSetup),
|
|
26534
26702
|
acpSessionId: nextSessionId,
|
|
26703
|
+
setup: openedSetup,
|
|
26535
26704
|
requestedModelId: options.requestedModelId,
|
|
26536
26705
|
expectedGeneration
|
|
26537
26706
|
});
|
|
26707
|
+
nextSessionId = appliedModel.sessionId;
|
|
26708
|
+
setup = appliedModel.setup;
|
|
26709
|
+
const nextModelSelectionState = appliedModel.state;
|
|
26538
26710
|
await applyRequestedEffort({
|
|
26539
26711
|
connection,
|
|
26540
26712
|
log: options.log,
|
|
@@ -27069,7 +27241,6 @@ function createAcpExecutor(options) {
|
|
|
27069
27241
|
currentModelId: void 0,
|
|
27070
27242
|
advertisedModelValues: []
|
|
27071
27243
|
},
|
|
27072
|
-
lastUnmatchedModelId: void 0,
|
|
27073
27244
|
initializeResult: void 0,
|
|
27074
27245
|
startResult: void 0,
|
|
27075
27246
|
startInFlight: void 0,
|
|
@@ -27724,7 +27895,9 @@ import * as NodeOS2 from "node:os";
|
|
|
27724
27895
|
import * as NodePath3 from "node:path";
|
|
27725
27896
|
import {
|
|
27726
27897
|
describeExecutorSpawnFailure,
|
|
27898
|
+
ExecutorSpawnAbortedError,
|
|
27727
27899
|
ExecutorSpawnRefusedError,
|
|
27900
|
+
raceAbort,
|
|
27728
27901
|
REASONING_OPTION_LABEL
|
|
27729
27902
|
} from "@ycodium-ai/plugin-api/executor";
|
|
27730
27903
|
import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
@@ -27807,22 +27980,28 @@ async function probeAcpModelsViaSession(input2) {
|
|
|
27807
27980
|
args: tokenizeLaunchArgs(recipe.launchArgs),
|
|
27808
27981
|
cwd: probeCwd,
|
|
27809
27982
|
owner: { bindingId: host.bindingId },
|
|
27810
|
-
...Object.keys(env).length > 0 ? { env } : {}
|
|
27983
|
+
...Object.keys(env).length > 0 ? { env } : {},
|
|
27984
|
+
...input2.signal === void 0 ? {} : { signal: input2.signal }
|
|
27811
27985
|
});
|
|
27812
27986
|
} catch (error62) {
|
|
27813
|
-
if (error62 instanceof ExecutorSpawnRefusedError
|
|
27987
|
+
if (error62 instanceof ExecutorSpawnRefusedError || error62 instanceof ExecutorSpawnAbortedError) {
|
|
27988
|
+
throw error62;
|
|
27989
|
+
}
|
|
27814
27990
|
return { kind: "not-started", ...describeExecutorSpawnFailure(error62) };
|
|
27815
27991
|
}
|
|
27816
27992
|
let handshake;
|
|
27817
27993
|
try {
|
|
27818
27994
|
const { readable, writable } = nodeStreamsFromHandle(handle);
|
|
27819
|
-
handshake = await
|
|
27820
|
-
|
|
27821
|
-
|
|
27822
|
-
|
|
27823
|
-
|
|
27824
|
-
|
|
27825
|
-
|
|
27995
|
+
handshake = await raceAbort(
|
|
27996
|
+
openAcpProbeHandshake({
|
|
27997
|
+
readable,
|
|
27998
|
+
writable,
|
|
27999
|
+
clientInfo: CLIENT_INFO,
|
|
28000
|
+
requestTimeoutMs: PROBE_REQUEST_TIMEOUT_MS
|
|
28001
|
+
}),
|
|
28002
|
+
input2.signal
|
|
28003
|
+
);
|
|
28004
|
+
const setup = await raceAbort(probeSessionSetup(handshake, probeCwd), input2.signal);
|
|
27826
28005
|
return {
|
|
27827
28006
|
kind: "answered",
|
|
27828
28007
|
version: acpAgentVersion(handshake.initializeResult),
|
|
@@ -27847,6 +28026,43 @@ async function probeAcpModelsViaSession(input2) {
|
|
|
27847
28026
|
await handle.kill("SIGTERM").catch(() => void 0);
|
|
27848
28027
|
}
|
|
27849
28028
|
}
|
|
28029
|
+
async function probeAcpAgentVersion(input2) {
|
|
28030
|
+
if (input2.recipe.binaryPath.length === 0) return null;
|
|
28031
|
+
const probeCwd = acpProbeSessionCwd(input2.host.instanceId);
|
|
28032
|
+
try {
|
|
28033
|
+
NodeFS2.mkdirSync(probeCwd, { recursive: true });
|
|
28034
|
+
} catch {
|
|
28035
|
+
return null;
|
|
28036
|
+
}
|
|
28037
|
+
let handle;
|
|
28038
|
+
try {
|
|
28039
|
+
handle = await input2.host.process.spawn({
|
|
28040
|
+
program: input2.recipe.binaryPath,
|
|
28041
|
+
args: tokenizeLaunchArgs(input2.recipe.launchArgs),
|
|
28042
|
+
cwd: probeCwd,
|
|
28043
|
+
owner: { bindingId: input2.host.bindingId },
|
|
28044
|
+
...Object.keys(input2.env).length > 0 ? { env: input2.env } : {}
|
|
28045
|
+
});
|
|
28046
|
+
} catch {
|
|
28047
|
+
return null;
|
|
28048
|
+
}
|
|
28049
|
+
let handshake;
|
|
28050
|
+
try {
|
|
28051
|
+
const { readable, writable } = nodeStreamsFromHandle(handle);
|
|
28052
|
+
handshake = await openAcpProbeHandshake({
|
|
28053
|
+
readable,
|
|
28054
|
+
writable,
|
|
28055
|
+
clientInfo: CLIENT_INFO,
|
|
28056
|
+
requestTimeoutMs: PROBE_REQUEST_TIMEOUT_MS
|
|
28057
|
+
});
|
|
28058
|
+
return acpAgentVersion(handshake.initializeResult);
|
|
28059
|
+
} catch {
|
|
28060
|
+
return acpAgentVersion(handshake?.initializeResult);
|
|
28061
|
+
} finally {
|
|
28062
|
+
await handshake?.close().catch(() => void 0);
|
|
28063
|
+
await handle.kill("SIGTERM").catch(() => void 0);
|
|
28064
|
+
}
|
|
28065
|
+
}
|
|
27850
28066
|
|
|
27851
28067
|
// src/runtimeModeApproval.ts
|
|
27852
28068
|
function acpRuntimeModeAutoApproves(runtimeMode, toolKind) {
|
|
@@ -27956,7 +28172,7 @@ var createAcpInstance = (config2, host) => {
|
|
|
27956
28172
|
events.close();
|
|
27957
28173
|
});
|
|
27958
28174
|
const instance = {
|
|
27959
|
-
probe: async () => {
|
|
28175
|
+
probe: async (signal) => {
|
|
27960
28176
|
if (recipe.binaryPath.length === 0) {
|
|
27961
28177
|
return {
|
|
27962
28178
|
installed: false,
|
|
@@ -27966,8 +28182,17 @@ var createAcpInstance = (config2, host) => {
|
|
|
27966
28182
|
detail: "ACP program path is not configured"
|
|
27967
28183
|
};
|
|
27968
28184
|
}
|
|
28185
|
+
if (signal?.aborted) throw new Error("aborted");
|
|
27969
28186
|
const env = buildSpawnEnv(recipe, recipe.homePath);
|
|
27970
|
-
const outcome = await
|
|
28187
|
+
const outcome = await raceAbort2(
|
|
28188
|
+
probeAcpModelsViaSession({
|
|
28189
|
+
recipe,
|
|
28190
|
+
host,
|
|
28191
|
+
env,
|
|
28192
|
+
...signal === void 0 ? {} : { signal }
|
|
28193
|
+
}),
|
|
28194
|
+
signal
|
|
28195
|
+
);
|
|
27971
28196
|
switch (outcome.kind) {
|
|
27972
28197
|
case "not-started":
|
|
27973
28198
|
return {
|
|
@@ -28007,6 +28232,11 @@ var createAcpInstance = (config2, host) => {
|
|
|
28007
28232
|
};
|
|
28008
28233
|
}
|
|
28009
28234
|
},
|
|
28235
|
+
readCliVersion: () => recipe.binaryPath.length === 0 ? Promise.resolve(null) : probeAcpAgentVersion({
|
|
28236
|
+
recipe,
|
|
28237
|
+
host,
|
|
28238
|
+
env: buildSpawnEnv(recipe, recipe.homePath)
|
|
28239
|
+
}),
|
|
28010
28240
|
// 暂不处理 input.readOnlyDirectories(有意为之):acp 经共享的 ycodium-acp-executor 起会话,
|
|
28011
28241
|
// 还没用真机确认这家 CLI 对 cwd 之外的读怎么处理、要不要放行。确认之后再接这一栏。
|
|
28012
28242
|
startSession: async (input2, signal) => {
|
|
@@ -28220,7 +28450,7 @@ var executors = [
|
|
|
28220
28450
|
];
|
|
28221
28451
|
var index_default = definePlugin({
|
|
28222
28452
|
id: "agent-acp",
|
|
28223
|
-
apiVersion:
|
|
28453
|
+
apiVersion: 32,
|
|
28224
28454
|
executors,
|
|
28225
28455
|
activate(ctx) {
|
|
28226
28456
|
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.3272",
|
|
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
|
-
"ycodium-executor
|
|
26
|
-
"
|
|
24
|
+
"@ycodium-ai/plugin-api": "0.2.3272",
|
|
25
|
+
"ycodium-acp-executor": "0.2.0",
|
|
26
|
+
"ycodium-executor-testing": "0.0.0"
|
|
27
27
|
},
|
|
28
28
|
"ycodium": {
|
|
29
29
|
"plugin": "./dist/index.js",
|