@ycodium-ai/agent-acp 0.2.2126 → 0.2.2143
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 +295 -181
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5098,7 +5098,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5098
5098
|
var NONE = 0;
|
|
5099
5099
|
var ASSUMED = 1;
|
|
5100
5100
|
var PROVEN = 2;
|
|
5101
|
-
function isRecursive(inst, stack,
|
|
5101
|
+
function isRecursive(inst, stack, resolve2) {
|
|
5102
5102
|
const cached2 = recursive.get(inst);
|
|
5103
5103
|
if (cached2 !== void 0)
|
|
5104
5104
|
return cached2 ? PROVEN : NONE;
|
|
@@ -5108,7 +5108,7 @@ function isRecursive(inst, stack, resolve) {
|
|
|
5108
5108
|
let result = NONE;
|
|
5109
5109
|
const check2 = (child) => {
|
|
5110
5110
|
if (result !== PROVEN && child?._zod) {
|
|
5111
|
-
const answer = isRecursive(child, stack,
|
|
5111
|
+
const answer = isRecursive(child, stack, resolve2);
|
|
5112
5112
|
if (answer > result)
|
|
5113
5113
|
result = answer;
|
|
5114
5114
|
}
|
|
@@ -5119,7 +5119,7 @@ function isRecursive(inst, stack, resolve) {
|
|
|
5119
5119
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5120
5120
|
if (spread && !desc.enumerable)
|
|
5121
5121
|
continue;
|
|
5122
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5122
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve2) : NONE;
|
|
5123
5123
|
if (child > answer)
|
|
5124
5124
|
answer = child;
|
|
5125
5125
|
}
|
|
@@ -5183,7 +5183,7 @@ function isRecursive(inst, stack, resolve) {
|
|
|
5183
5183
|
break;
|
|
5184
5184
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5185
5185
|
case "lazy": {
|
|
5186
|
-
const inner = def._cachedInner ?? (
|
|
5186
|
+
const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
|
|
5187
5187
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5188
5188
|
break;
|
|
5189
5189
|
}
|
|
@@ -21847,11 +21847,11 @@ var Connection = class {
|
|
|
21847
21847
|
const id = this.nextRequestId++;
|
|
21848
21848
|
let cancel = () => {
|
|
21849
21849
|
};
|
|
21850
|
-
const response = new Promise((
|
|
21850
|
+
const response = new Promise((resolve2, reject) => {
|
|
21851
21851
|
const pendingResponse = {
|
|
21852
21852
|
resolve: (value) => {
|
|
21853
21853
|
try {
|
|
21854
|
-
|
|
21854
|
+
resolve2(mapResponse ? mapResponse(value) : value);
|
|
21855
21855
|
} catch (error62) {
|
|
21856
21856
|
reject(error62);
|
|
21857
21857
|
}
|
|
@@ -21908,8 +21908,8 @@ var Connection = class {
|
|
|
21908
21908
|
this.stream = stream;
|
|
21909
21909
|
this.staticHandlers = handlers;
|
|
21910
21910
|
this.allowBatches = options?.allowBatches ?? true;
|
|
21911
|
-
this.closedPromise = new Promise((
|
|
21912
|
-
this.abortController.signal.addEventListener("abort", () =>
|
|
21911
|
+
this.closedPromise = new Promise((resolve2) => {
|
|
21912
|
+
this.abortController.signal.addEventListener("abort", () => resolve2());
|
|
21913
21913
|
});
|
|
21914
21914
|
void this.receive();
|
|
21915
21915
|
}
|
|
@@ -22803,8 +22803,8 @@ var AsyncQueue = class {
|
|
|
22803
22803
|
if (this.failed) {
|
|
22804
22804
|
return Promise.reject(this.failure);
|
|
22805
22805
|
}
|
|
22806
|
-
return new Promise((
|
|
22807
|
-
this.waiters.push({ resolve, reject });
|
|
22806
|
+
return new Promise((resolve2, reject) => {
|
|
22807
|
+
this.waiters.push({ resolve: resolve2, reject });
|
|
22808
22808
|
});
|
|
22809
22809
|
}
|
|
22810
22810
|
};
|
|
@@ -23633,6 +23633,7 @@ function createAcpConnection(options) {
|
|
|
23633
23633
|
options.readable.off("data", onData);
|
|
23634
23634
|
options.readable.off("end", onEnd);
|
|
23635
23635
|
options.readable.off("error", onError);
|
|
23636
|
+
options.writable.off("error", onWritableError);
|
|
23636
23637
|
try {
|
|
23637
23638
|
await byteWriter.close();
|
|
23638
23639
|
} catch {
|
|
@@ -23771,8 +23772,17 @@ function createAcpConnection(options) {
|
|
|
23771
23772
|
endInboundBatch();
|
|
23772
23773
|
}
|
|
23773
23774
|
};
|
|
23775
|
+
const failInbound = (error62) => {
|
|
23776
|
+
if (closedError !== void 0) return;
|
|
23777
|
+
options.onInboundFailure?.(error62);
|
|
23778
|
+
void shutdown(
|
|
23779
|
+
new AcpConnectionClosedError(
|
|
23780
|
+
`ACP inbound handling failed: ${error62 instanceof Error ? error62.message : String(error62)}`
|
|
23781
|
+
)
|
|
23782
|
+
);
|
|
23783
|
+
};
|
|
23774
23784
|
const enqueueInbound = (work) => {
|
|
23775
|
-
inboundTail = inboundTail.then(work
|
|
23785
|
+
inboundTail = inboundTail.then(work).catch(failInbound);
|
|
23776
23786
|
};
|
|
23777
23787
|
const onData = (chunk) => {
|
|
23778
23788
|
if (closedError !== void 0) {
|
|
@@ -23822,18 +23832,24 @@ function createAcpConnection(options) {
|
|
|
23822
23832
|
);
|
|
23823
23833
|
});
|
|
23824
23834
|
};
|
|
23835
|
+
const onWritableError = (error62) => {
|
|
23836
|
+
void shutdown(
|
|
23837
|
+
error62 instanceof Error ? error62 : new AcpConnectionClosedError("ACP output stream error")
|
|
23838
|
+
);
|
|
23839
|
+
};
|
|
23825
23840
|
options.readable.on("data", onData);
|
|
23826
23841
|
options.readable.on("end", onEnd);
|
|
23827
23842
|
options.readable.on("error", onError);
|
|
23843
|
+
options.writable.once("error", onWritableError);
|
|
23828
23844
|
const request = (async (method, params) => {
|
|
23829
23845
|
failIfClosed();
|
|
23830
23846
|
const id = nextRequestId;
|
|
23831
23847
|
nextRequestId += 1;
|
|
23832
|
-
const { promise: promise2, resolve, reject } = Promise.withResolvers();
|
|
23833
|
-
pending.set(String(id), { method, resolve, reject });
|
|
23848
|
+
const { promise: promise2, resolve: resolve2, reject } = Promise.withResolvers();
|
|
23849
|
+
pending.set(String(id), { method, resolve: resolve2, reject });
|
|
23834
23850
|
const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
|
|
23835
23851
|
try {
|
|
23836
|
-
await writeMessage(message);
|
|
23852
|
+
await Promise.race([writeMessage(message), promise2]);
|
|
23837
23853
|
} catch (error62) {
|
|
23838
23854
|
if (pending.delete(String(id))) {
|
|
23839
23855
|
reject(error62);
|
|
@@ -23851,8 +23867,8 @@ function createAcpConnection(options) {
|
|
|
23851
23867
|
if (inboundBatches === 0) {
|
|
23852
23868
|
return;
|
|
23853
23869
|
}
|
|
23854
|
-
await new Promise((
|
|
23855
|
-
idleWaiters.push(
|
|
23870
|
+
await new Promise((resolve2) => {
|
|
23871
|
+
idleWaiters.push(resolve2);
|
|
23856
23872
|
if (inboundBatches === 0) {
|
|
23857
23873
|
releaseIdleWaiters();
|
|
23858
23874
|
}
|
|
@@ -24031,8 +24047,8 @@ var UnboundedEventStream = class {
|
|
|
24031
24047
|
iterators.subscribers.delete(subscriber);
|
|
24032
24048
|
return { value: void 0, done: true };
|
|
24033
24049
|
}
|
|
24034
|
-
await new Promise((
|
|
24035
|
-
subscriber.wake =
|
|
24050
|
+
await new Promise((resolve2) => {
|
|
24051
|
+
subscriber.wake = resolve2;
|
|
24036
24052
|
});
|
|
24037
24053
|
}
|
|
24038
24054
|
},
|
|
@@ -24523,8 +24539,8 @@ var Mutex = class {
|
|
|
24523
24539
|
this.locked = true;
|
|
24524
24540
|
return Promise.resolve();
|
|
24525
24541
|
}
|
|
24526
|
-
return new Promise((
|
|
24527
|
-
this.waiters.push(
|
|
24542
|
+
return new Promise((resolve2) => {
|
|
24543
|
+
this.waiters.push(resolve2);
|
|
24528
24544
|
});
|
|
24529
24545
|
}
|
|
24530
24546
|
tryAcquire() {
|
|
@@ -25658,14 +25674,14 @@ function createAcpExecutor(options) {
|
|
|
25658
25674
|
}
|
|
25659
25675
|
}
|
|
25660
25676
|
const requestId = randomId();
|
|
25661
|
-
const outcome = await new Promise((
|
|
25677
|
+
const outcome = await new Promise((resolve2) => {
|
|
25662
25678
|
const pending = {
|
|
25663
25679
|
requestId,
|
|
25664
25680
|
request: params,
|
|
25665
25681
|
permissionRequest,
|
|
25666
25682
|
turnId: activeTurnId,
|
|
25667
25683
|
settled: false,
|
|
25668
|
-
resolve
|
|
25684
|
+
resolve: resolve2
|
|
25669
25685
|
};
|
|
25670
25686
|
approvals.add(pending);
|
|
25671
25687
|
emit(
|
|
@@ -25691,6 +25707,12 @@ function createAcpExecutor(options) {
|
|
|
25691
25707
|
const connection = createAcpConnection({
|
|
25692
25708
|
readable: options.readable,
|
|
25693
25709
|
writable: options.writable,
|
|
25710
|
+
onInboundFailure: (error62) => {
|
|
25711
|
+
options.log?.warn?.("acp connection closed: an inbound request could not be answered", {
|
|
25712
|
+
threadId: options.threadId,
|
|
25713
|
+
error: error62 instanceof Error ? error62.message : String(error62)
|
|
25714
|
+
});
|
|
25715
|
+
},
|
|
25694
25716
|
onNotification: (notification) => {
|
|
25695
25717
|
if (notification.method === "session/update") {
|
|
25696
25718
|
handleSessionUpdate(notification.params);
|
|
@@ -25948,14 +25970,14 @@ function createAcpExecutor(options) {
|
|
|
25948
25970
|
if (!promptMutex.isLocked) {
|
|
25949
25971
|
return true;
|
|
25950
25972
|
}
|
|
25951
|
-
return await new Promise((
|
|
25973
|
+
return await new Promise((resolve2) => {
|
|
25952
25974
|
const timer = setTimeout(() => {
|
|
25953
25975
|
promptWaiters = promptWaiters.filter((waiter) => waiter !== onSettle);
|
|
25954
|
-
|
|
25976
|
+
resolve2(false);
|
|
25955
25977
|
}, timeoutMs);
|
|
25956
25978
|
const onSettle = () => {
|
|
25957
25979
|
clearTimeout(timer);
|
|
25958
|
-
|
|
25980
|
+
resolve2(true);
|
|
25959
25981
|
};
|
|
25960
25982
|
promptWaiters.push(onSettle);
|
|
25961
25983
|
});
|
|
@@ -26328,16 +26350,16 @@ function createAcpExecutor(options) {
|
|
|
26328
26350
|
}
|
|
26329
26351
|
|
|
26330
26352
|
// ../../packages/ycodium-acp-executor/src/probe.ts
|
|
26331
|
-
function withProbeTimeout(promise2, timeoutMs,
|
|
26332
|
-
return new Promise((
|
|
26353
|
+
function withProbeTimeout(promise2, timeoutMs, what) {
|
|
26354
|
+
return new Promise((resolve2, reject) => {
|
|
26333
26355
|
const timer = setTimeout(() => {
|
|
26334
|
-
reject(new Error(
|
|
26356
|
+
reject(new Error(`${what} timed out after ${timeoutMs}ms`));
|
|
26335
26357
|
}, timeoutMs);
|
|
26336
26358
|
timer.unref?.();
|
|
26337
26359
|
promise2.then(
|
|
26338
26360
|
(value) => {
|
|
26339
26361
|
clearTimeout(timer);
|
|
26340
|
-
|
|
26362
|
+
resolve2(value);
|
|
26341
26363
|
},
|
|
26342
26364
|
(error62) => {
|
|
26343
26365
|
clearTimeout(timer);
|
|
@@ -26356,11 +26378,15 @@ async function openAcpProbeHandshake(input2) {
|
|
|
26356
26378
|
const initializeResult = await withProbeTimeout(
|
|
26357
26379
|
connection.request("initialize", acpInitializePayload(input2.clientInfo)),
|
|
26358
26380
|
input2.requestTimeoutMs,
|
|
26359
|
-
"initialize"
|
|
26381
|
+
"ACP probe request 'initialize'"
|
|
26360
26382
|
);
|
|
26361
26383
|
return {
|
|
26362
26384
|
initializeResult,
|
|
26363
|
-
request: (method, params) => withProbeTimeout(
|
|
26385
|
+
request: (method, params) => withProbeTimeout(
|
|
26386
|
+
connection.request(method, params),
|
|
26387
|
+
input2.requestTimeoutMs,
|
|
26388
|
+
`ACP probe request '${method}'`
|
|
26389
|
+
),
|
|
26364
26390
|
close: () => connection.close()
|
|
26365
26391
|
};
|
|
26366
26392
|
} catch (error62) {
|
|
@@ -26368,6 +26394,62 @@ async function openAcpProbeHandshake(input2) {
|
|
|
26368
26394
|
throw error62;
|
|
26369
26395
|
}
|
|
26370
26396
|
}
|
|
26397
|
+
function acpAgentVersion(initializeResult) {
|
|
26398
|
+
if (!isRecord5(initializeResult)) return null;
|
|
26399
|
+
const agentInfo = initializeResult["agentInfo"];
|
|
26400
|
+
return isRecord5(agentInfo) ? asTrimmedString(agentInfo["version"]) ?? null : null;
|
|
26401
|
+
}
|
|
26402
|
+
var CLI_VERSION_PATTERN = /(?<![\d.])(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)/;
|
|
26403
|
+
function parseCliVersion(output2) {
|
|
26404
|
+
return CLI_VERSION_PATTERN.exec(output2)?.[1] ?? null;
|
|
26405
|
+
}
|
|
26406
|
+
async function collectCappedText(stream, maxBytes) {
|
|
26407
|
+
const decoder = new TextDecoder();
|
|
26408
|
+
let text = "";
|
|
26409
|
+
let total = 0;
|
|
26410
|
+
for await (const chunk of stream) {
|
|
26411
|
+
total += chunk.byteLength;
|
|
26412
|
+
if (total <= maxBytes) text += decoder.decode(chunk, { stream: true });
|
|
26413
|
+
}
|
|
26414
|
+
return { text: text + decoder.decode(), overflowed: total > maxBytes };
|
|
26415
|
+
}
|
|
26416
|
+
async function collectProbeProcess(child, input2) {
|
|
26417
|
+
try {
|
|
26418
|
+
await child.closeStdin().catch(() => void 0);
|
|
26419
|
+
const [stdout, stderr, exitCode] = await withProbeTimeout(
|
|
26420
|
+
Promise.all([
|
|
26421
|
+
collectCappedText(child.stdout, input2.maxOutputBytes),
|
|
26422
|
+
collectCappedText(child.stderr, input2.maxOutputBytes),
|
|
26423
|
+
child.exited
|
|
26424
|
+
]),
|
|
26425
|
+
input2.timeoutMs,
|
|
26426
|
+
input2.what
|
|
26427
|
+
);
|
|
26428
|
+
return { stdout: stdout.overflowed ? void 0 : stdout.text, stderr: stderr.text, exitCode };
|
|
26429
|
+
} finally {
|
|
26430
|
+
await child.kill("SIGTERM").catch(() => void 0);
|
|
26431
|
+
}
|
|
26432
|
+
}
|
|
26433
|
+
var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
|
|
26434
|
+
async function probeCliVersion(input2) {
|
|
26435
|
+
let child;
|
|
26436
|
+
try {
|
|
26437
|
+
child = await input2.spawn();
|
|
26438
|
+
} catch {
|
|
26439
|
+
return null;
|
|
26440
|
+
}
|
|
26441
|
+
try {
|
|
26442
|
+
const run = await collectProbeProcess(child, {
|
|
26443
|
+
timeoutMs: input2.timeoutMs,
|
|
26444
|
+
maxOutputBytes: MAX_VERSION_OUTPUT_BYTES,
|
|
26445
|
+
what: "--version"
|
|
26446
|
+
});
|
|
26447
|
+
if (run.exitCode !== 0) return null;
|
|
26448
|
+
return parseCliVersion(run.stdout ?? "") ?? parseCliVersion(run.stderr);
|
|
26449
|
+
} catch {
|
|
26450
|
+
return null;
|
|
26451
|
+
}
|
|
26452
|
+
}
|
|
26371
26453
|
|
|
26372
26454
|
// src/card.ts
|
|
26373
26455
|
var ACP_DRIVER_KIND = "acp";
|
|
@@ -26668,118 +26750,17 @@ function readKimiContextWindow(input2) {
|
|
|
26668
26750
|
}
|
|
26669
26751
|
|
|
26670
26752
|
// src/kimiModels.ts
|
|
26671
|
-
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
function isRecord8(value) {
|
|
26675
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26676
|
-
}
|
|
26677
|
-
function asString3(value) {
|
|
26678
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
26679
|
-
}
|
|
26680
|
-
function positiveInt2(value) {
|
|
26681
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : void 0;
|
|
26682
|
-
}
|
|
26683
|
-
function kimiProbeModels(stdout) {
|
|
26684
|
-
let parsed;
|
|
26685
|
-
try {
|
|
26686
|
-
parsed = JSON.parse(stdout);
|
|
26687
|
-
} catch {
|
|
26688
|
-
return void 0;
|
|
26689
|
-
}
|
|
26690
|
-
if (!isRecord8(parsed)) return void 0;
|
|
26691
|
-
const models = parsed["models"];
|
|
26692
|
-
if (!isRecord8(models)) return void 0;
|
|
26693
|
-
const out = [];
|
|
26694
|
-
for (const [slug, entry] of Object.entries(models)) {
|
|
26695
|
-
const trimmed = slug.trim();
|
|
26696
|
-
if (trimmed.length === 0 || !isRecord8(entry)) continue;
|
|
26697
|
-
const name = asString3(entry["displayName"]);
|
|
26698
|
-
const contextWindow = positiveInt2(entry["maxContextSize"]);
|
|
26699
|
-
out.push({
|
|
26700
|
-
slug: trimmed,
|
|
26701
|
-
...name === void 0 ? {} : { name },
|
|
26702
|
-
...contextWindow === void 0 ? {} : { contextWindow }
|
|
26703
|
-
});
|
|
26704
|
-
}
|
|
26705
|
-
return out;
|
|
26706
|
-
}
|
|
26707
|
-
function withProbeTimeout2(promise2, what) {
|
|
26708
|
-
return new Promise((resolve, reject) => {
|
|
26709
|
-
const timer = setTimeout(
|
|
26710
|
-
() => reject(new Error(`${what} timed out after ${PROBE_TIMEOUT_MS}ms`)),
|
|
26711
|
-
PROBE_TIMEOUT_MS
|
|
26712
|
-
);
|
|
26713
|
-
timer.unref?.();
|
|
26714
|
-
promise2.then(
|
|
26715
|
-
(value) => {
|
|
26716
|
-
clearTimeout(timer);
|
|
26717
|
-
resolve(value);
|
|
26718
|
-
},
|
|
26719
|
-
(error62) => {
|
|
26720
|
-
clearTimeout(timer);
|
|
26721
|
-
reject(error62 instanceof Error ? error62 : new Error(String(error62)));
|
|
26722
|
-
}
|
|
26723
|
-
);
|
|
26724
|
-
});
|
|
26725
|
-
}
|
|
26726
|
-
function concat(chunks) {
|
|
26727
|
-
const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
26728
|
-
const out = new Uint8Array(total);
|
|
26729
|
-
let offset = 0;
|
|
26730
|
-
for (const chunk of chunks) {
|
|
26731
|
-
out.set(chunk, offset);
|
|
26732
|
-
offset += chunk.byteLength;
|
|
26733
|
-
}
|
|
26734
|
-
return out;
|
|
26735
|
-
}
|
|
26736
|
-
async function probeKimiModels(input2) {
|
|
26737
|
-
const { recipe, host, env } = input2;
|
|
26738
|
-
if (recipe.binaryPath.length === 0) return void 0;
|
|
26739
|
-
let handle;
|
|
26740
|
-
try {
|
|
26741
|
-
handle = await host.process.spawn({
|
|
26742
|
-
program: recipe.binaryPath,
|
|
26743
|
-
// 实例信封里的启动参数(Kimi 那行预填 `acp`)在这一栏用不上:读配置要换成
|
|
26744
|
-
// `provider list --json`,留着 `acp` 就等于让它起 ACP 服务然后什么都不问。
|
|
26745
|
-
args: KIMI_MODEL_LIST_ARGS,
|
|
26746
|
-
cwd: process.cwd(),
|
|
26747
|
-
owner: { bindingId: host.bindingId },
|
|
26748
|
-
...Object.keys(env).length > 0 ? { env } : {}
|
|
26749
|
-
});
|
|
26750
|
-
const spawned = handle;
|
|
26751
|
-
const collect = withProbeTimeout2(
|
|
26752
|
-
(async () => {
|
|
26753
|
-
const chunks = [];
|
|
26754
|
-
let total = 0;
|
|
26755
|
-
for await (const chunk of spawned.stdout) {
|
|
26756
|
-
total += chunk.byteLength;
|
|
26757
|
-
if (total > MAX_OUTPUT_BYTES) return void 0;
|
|
26758
|
-
chunks.push(chunk);
|
|
26759
|
-
}
|
|
26760
|
-
return new TextDecoder().decode(concat(chunks));
|
|
26761
|
-
})(),
|
|
26762
|
-
"kimi provider list"
|
|
26763
|
-
);
|
|
26764
|
-
const drain = (async () => {
|
|
26765
|
-
for await (const _chunk of spawned.stderr) {
|
|
26766
|
-
}
|
|
26767
|
-
})().catch(() => void 0);
|
|
26768
|
-
const [stdout, , exitCode] = await Promise.all([collect, drain, spawned.exited]);
|
|
26769
|
-
if (stdout === void 0) return void 0;
|
|
26770
|
-
if (exitCode !== 0) return void 0;
|
|
26771
|
-
return kimiProbeModels(stdout);
|
|
26772
|
-
} catch {
|
|
26773
|
-
return void 0;
|
|
26774
|
-
} finally {
|
|
26775
|
-
await handle?.kill("SIGTERM").catch(() => void 0);
|
|
26776
|
-
}
|
|
26777
|
-
}
|
|
26753
|
+
import {
|
|
26754
|
+
ExecutorSpawnRefusedError as ExecutorSpawnRefusedError2
|
|
26755
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
26778
26756
|
|
|
26779
26757
|
// src/probeModels.ts
|
|
26780
26758
|
import * as NodeFS2 from "node:fs";
|
|
26781
26759
|
import * as NodeOS from "node:os";
|
|
26782
26760
|
import * as NodePath2 from "node:path";
|
|
26761
|
+
import {
|
|
26762
|
+
ExecutorSpawnRefusedError
|
|
26763
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
26783
26764
|
import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
26784
26765
|
var PROBE_REQUEST_TIMEOUT_MS = 15e3;
|
|
26785
26766
|
var CLIENT_INFO = { name: "ycodium-agent-acp-probe", version: "0.2.0" };
|
|
@@ -26788,18 +26769,18 @@ function acpProbeSessionCwd(instanceId) {
|
|
|
26788
26769
|
const safe = instanceId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
26789
26770
|
return NodePath2.join(NodeOS.tmpdir(), `ycodium-acp-probe-${safe}`);
|
|
26790
26771
|
}
|
|
26791
|
-
function
|
|
26772
|
+
function isRecord8(value) {
|
|
26792
26773
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26793
26774
|
}
|
|
26794
|
-
function
|
|
26775
|
+
function asString3(value) {
|
|
26795
26776
|
return typeof value === "string" ? value : void 0;
|
|
26796
26777
|
}
|
|
26797
26778
|
function findAcpProbeSessionId(listed, probeCwd) {
|
|
26798
|
-
if (!
|
|
26779
|
+
if (!isRecord8(listed) || !Array.isArray(listed["sessions"])) return void 0;
|
|
26799
26780
|
for (const entry of listed["sessions"]) {
|
|
26800
|
-
if (!
|
|
26801
|
-
if (
|
|
26802
|
-
const sessionId =
|
|
26781
|
+
if (!isRecord8(entry)) continue;
|
|
26782
|
+
if (asString3(entry["cwd"]) !== probeCwd) continue;
|
|
26783
|
+
const sessionId = asString3(entry["sessionId"]);
|
|
26803
26784
|
if (sessionId !== void 0) return sessionId;
|
|
26804
26785
|
}
|
|
26805
26786
|
return void 0;
|
|
@@ -26814,7 +26795,7 @@ async function probeSessionSetup(handshake, probeCwd) {
|
|
|
26814
26795
|
return handshake.request("session/new", { cwd: probeCwd, mcpServers: [] });
|
|
26815
26796
|
}
|
|
26816
26797
|
function acpProbeModels(setup) {
|
|
26817
|
-
if (!
|
|
26798
|
+
if (!isRecord8(setup)) return void 0;
|
|
26818
26799
|
const rawOptions = setup["configOptions"];
|
|
26819
26800
|
const choices = acpModelChoicesFromConfigOptions(rawOptions) ?? acpModelChoicesFromSessionModels(setup["models"]);
|
|
26820
26801
|
if (choices === void 0 || choices.length === 0) return void 0;
|
|
@@ -26842,14 +26823,16 @@ function acpProbeModels(setup) {
|
|
|
26842
26823
|
};
|
|
26843
26824
|
return models.map((model) => ({ ...model, capabilities }));
|
|
26844
26825
|
}
|
|
26845
|
-
var
|
|
26826
|
+
var probeFailureDetail = (error62) => (error62 instanceof Error ? error62.message : String(error62)).trim() || void 0;
|
|
26827
|
+
var ACP_AUTH_REQUIRED_CODE = RequestError.authRequired().code;
|
|
26828
|
+
var isAcpAuthRequired = (error62) => error62 instanceof RequestError && error62.code === ACP_AUTH_REQUIRED_CODE;
|
|
26846
26829
|
async function probeAcpModelsViaSession(input2) {
|
|
26847
26830
|
const { recipe, host, env } = input2;
|
|
26848
26831
|
const probeCwd = acpProbeSessionCwd(host.instanceId);
|
|
26849
26832
|
try {
|
|
26850
26833
|
NodeFS2.mkdirSync(probeCwd, { recursive: true });
|
|
26851
26834
|
} catch (error62) {
|
|
26852
|
-
return { kind: "failed", detail:
|
|
26835
|
+
return { kind: "failed", detail: probeFailureDetail(error62), version: null };
|
|
26853
26836
|
}
|
|
26854
26837
|
let handle;
|
|
26855
26838
|
try {
|
|
@@ -26861,7 +26844,8 @@ async function probeAcpModelsViaSession(input2) {
|
|
|
26861
26844
|
...Object.keys(env).length > 0 ? { env } : {}
|
|
26862
26845
|
});
|
|
26863
26846
|
} catch (error62) {
|
|
26864
|
-
|
|
26847
|
+
if (error62 instanceof ExecutorSpawnRefusedError) throw error62;
|
|
26848
|
+
return { kind: "not-started", detail: probeFailureDetail(error62) };
|
|
26865
26849
|
}
|
|
26866
26850
|
let handshake;
|
|
26867
26851
|
try {
|
|
@@ -26875,6 +26859,7 @@ async function probeAcpModelsViaSession(input2) {
|
|
|
26875
26859
|
const setup = await probeSessionSetup(handshake, probeCwd);
|
|
26876
26860
|
return {
|
|
26877
26861
|
kind: "answered",
|
|
26862
|
+
version: acpAgentVersion(handshake.initializeResult),
|
|
26878
26863
|
models: acpProbeModels(setup),
|
|
26879
26864
|
// 审批档原样上报:宿主落进 provider 快照的 `nativeModes`,composer 直接画这只手
|
|
26880
26865
|
// 自己的那几档,不再退回宿主四档开关。
|
|
@@ -26886,13 +26871,124 @@ async function probeAcpModelsViaSession(input2) {
|
|
|
26886
26871
|
currentNativeModeId: acpCurrentModeId(setup)
|
|
26887
26872
|
};
|
|
26888
26873
|
} catch (error62) {
|
|
26889
|
-
|
|
26874
|
+
const version2 = acpAgentVersion(handshake?.initializeResult);
|
|
26875
|
+
if (handshake !== void 0 && isAcpAuthRequired(error62)) {
|
|
26876
|
+
return { kind: "auth-required", version: version2 };
|
|
26877
|
+
}
|
|
26878
|
+
return { kind: "failed", detail: probeFailureDetail(error62), version: version2 };
|
|
26890
26879
|
} finally {
|
|
26891
26880
|
await handshake?.close().catch(() => void 0);
|
|
26892
26881
|
await handle.kill("SIGTERM").catch(() => void 0);
|
|
26893
26882
|
}
|
|
26894
26883
|
}
|
|
26895
26884
|
|
|
26885
|
+
// src/kimiModels.ts
|
|
26886
|
+
var PROBE_TIMEOUT_MS = 15e3;
|
|
26887
|
+
var MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
26888
|
+
var KIMI_MODEL_LIST_ARGS = ["provider", "list", "--json"];
|
|
26889
|
+
function isRecord9(value) {
|
|
26890
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26891
|
+
}
|
|
26892
|
+
function asString4(value) {
|
|
26893
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
26894
|
+
}
|
|
26895
|
+
function positiveInt2(value) {
|
|
26896
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : void 0;
|
|
26897
|
+
}
|
|
26898
|
+
function kimiProbeModels(stdout) {
|
|
26899
|
+
let parsed;
|
|
26900
|
+
try {
|
|
26901
|
+
parsed = JSON.parse(stdout);
|
|
26902
|
+
} catch {
|
|
26903
|
+
return void 0;
|
|
26904
|
+
}
|
|
26905
|
+
if (!isRecord9(parsed)) return void 0;
|
|
26906
|
+
const models = parsed["models"];
|
|
26907
|
+
if (!isRecord9(models)) return void 0;
|
|
26908
|
+
const out = [];
|
|
26909
|
+
for (const [slug, entry] of Object.entries(models)) {
|
|
26910
|
+
const trimmed = slug.trim();
|
|
26911
|
+
if (trimmed.length === 0 || !isRecord9(entry)) continue;
|
|
26912
|
+
const name = asString4(entry["displayName"]);
|
|
26913
|
+
const contextWindow = positiveInt2(entry["maxContextSize"]);
|
|
26914
|
+
out.push({
|
|
26915
|
+
slug: trimmed,
|
|
26916
|
+
...name === void 0 ? {} : { name },
|
|
26917
|
+
...contextWindow === void 0 ? {} : { contextWindow }
|
|
26918
|
+
});
|
|
26919
|
+
}
|
|
26920
|
+
return out;
|
|
26921
|
+
}
|
|
26922
|
+
async function probeKimiModels(input2) {
|
|
26923
|
+
const { recipe, host, env } = input2;
|
|
26924
|
+
let handle;
|
|
26925
|
+
try {
|
|
26926
|
+
handle = await host.process.spawn({
|
|
26927
|
+
program: recipe.binaryPath,
|
|
26928
|
+
// 实例信封里的启动参数(Kimi 那行预填 `acp`)在这一栏用不上:读配置要换成
|
|
26929
|
+
// `provider list --json`,留着 `acp` 就等于让它起 ACP 服务然后什么都不问。
|
|
26930
|
+
args: KIMI_MODEL_LIST_ARGS,
|
|
26931
|
+
cwd: process.cwd(),
|
|
26932
|
+
owner: { bindingId: host.bindingId },
|
|
26933
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
26934
|
+
});
|
|
26935
|
+
} catch (error62) {
|
|
26936
|
+
if (error62 instanceof ExecutorSpawnRefusedError2) throw error62;
|
|
26937
|
+
return { kind: "not-started", detail: probeFailureDetail(error62) };
|
|
26938
|
+
}
|
|
26939
|
+
try {
|
|
26940
|
+
const run = await collectProbeProcess(handle, {
|
|
26941
|
+
timeoutMs: input2.timeoutMs ?? PROBE_TIMEOUT_MS,
|
|
26942
|
+
// 这份 JSON 实测 1.7KB;封顶是防 CLI 抽风刷日志把内存吃掉。
|
|
26943
|
+
maxOutputBytes: MAX_OUTPUT_BYTES,
|
|
26944
|
+
what: "kimi provider list"
|
|
26945
|
+
});
|
|
26946
|
+
if (run.exitCode !== 0) {
|
|
26947
|
+
const stderr = run.stderr.trim();
|
|
26948
|
+
return {
|
|
26949
|
+
kind: "failed",
|
|
26950
|
+
detail: stderr.length > 0 ? stderr : run.exitCode === null ? "kimi provider list was killed by a signal" : `kimi provider list exited with code ${run.exitCode}`
|
|
26951
|
+
};
|
|
26952
|
+
}
|
|
26953
|
+
return {
|
|
26954
|
+
kind: "answered",
|
|
26955
|
+
models: run.stdout === void 0 ? void 0 : kimiProbeModels(run.stdout)
|
|
26956
|
+
};
|
|
26957
|
+
} catch (error62) {
|
|
26958
|
+
return { kind: "failed", detail: probeFailureDetail(error62) };
|
|
26959
|
+
}
|
|
26960
|
+
}
|
|
26961
|
+
async function probeKimiVersion(input2) {
|
|
26962
|
+
const { recipe, host, env } = input2;
|
|
26963
|
+
return probeCliVersion({
|
|
26964
|
+
spawn: () => host.process.spawn({
|
|
26965
|
+
program: recipe.binaryPath,
|
|
26966
|
+
args: ["--version"],
|
|
26967
|
+
cwd: process.cwd(),
|
|
26968
|
+
owner: { bindingId: host.bindingId },
|
|
26969
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
26970
|
+
}),
|
|
26971
|
+
timeoutMs: PROBE_TIMEOUT_MS
|
|
26972
|
+
});
|
|
26973
|
+
}
|
|
26974
|
+
async function probeKimi(input2) {
|
|
26975
|
+
const [listed, version2] = await Promise.all([probeKimiModels(input2), probeKimiVersion(input2)]);
|
|
26976
|
+
switch (listed.kind) {
|
|
26977
|
+
case "not-started":
|
|
26978
|
+
return { kind: "not-started", detail: listed.detail };
|
|
26979
|
+
case "failed":
|
|
26980
|
+
return { kind: "failed", detail: listed.detail, version: version2 };
|
|
26981
|
+
case "answered":
|
|
26982
|
+
return {
|
|
26983
|
+
kind: "answered",
|
|
26984
|
+
version: version2,
|
|
26985
|
+
models: listed.models,
|
|
26986
|
+
nativeModes: [],
|
|
26987
|
+
currentNativeModeId: void 0
|
|
26988
|
+
};
|
|
26989
|
+
}
|
|
26990
|
+
}
|
|
26991
|
+
|
|
26896
26992
|
// src/runtimeModeApproval.ts
|
|
26897
26993
|
function acpRuntimeModeAutoApproves(runtimeMode, toolKind) {
|
|
26898
26994
|
switch (runtimeMode) {
|
|
@@ -26912,8 +27008,8 @@ function acpSessionModeToApply(requestedNativeModeId, startedModeId) {
|
|
|
26912
27008
|
// src/acpInstance.ts
|
|
26913
27009
|
var RESUME_SCHEMA_VERSION = 1;
|
|
26914
27010
|
var CLIENT_INFO2 = { name: "ycodium-agent-acp", version: "0.2.0" };
|
|
26915
|
-
var yieldTick = () => new Promise((
|
|
26916
|
-
setImmediate(
|
|
27011
|
+
var yieldTick = () => new Promise((resolve2) => {
|
|
27012
|
+
setImmediate(resolve2);
|
|
26917
27013
|
});
|
|
26918
27014
|
var EventBus = class {
|
|
26919
27015
|
#queued = [];
|
|
@@ -26940,8 +27036,8 @@ var EventBus = class {
|
|
|
26940
27036
|
const queued = this.#queued.shift();
|
|
26941
27037
|
if (queued !== void 0) return Promise.resolve({ done: false, value: queued });
|
|
26942
27038
|
if (this.#closed) return Promise.resolve({ done: true, value: void 0 });
|
|
26943
|
-
return new Promise((
|
|
26944
|
-
this.#waiters.push(
|
|
27039
|
+
return new Promise((resolve2) => {
|
|
27040
|
+
this.#waiters.push(resolve2);
|
|
26945
27041
|
});
|
|
26946
27042
|
}
|
|
26947
27043
|
};
|
|
@@ -26975,6 +27071,11 @@ function buildSpawnEnv(recipe, configuredHomePath, launchEnv = {}) {
|
|
|
26975
27071
|
function nowIso() {
|
|
26976
27072
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
26977
27073
|
}
|
|
27074
|
+
function acpContinuationKey(recipe) {
|
|
27075
|
+
const homePath = recipe.homePath.trim();
|
|
27076
|
+
const resolvedHomePath = homePath.length > 0 ? NodePath3.resolve(expandHomePath(homePath)) : "";
|
|
27077
|
+
return `acp:home:${recipe.binaryPath.trim()}\0${resolvedHomePath}`;
|
|
27078
|
+
}
|
|
26978
27079
|
function resolveHomePath(recipe, launchHomePath) {
|
|
26979
27080
|
const envVar = recipe.homeEnvVar.trim();
|
|
26980
27081
|
const fromEnvironment = envVar.length > 0 ? recipe.environment[envVar]?.trim() : void 0;
|
|
@@ -27023,34 +27124,46 @@ var createAcpInstance = (config2, host) => {
|
|
|
27023
27124
|
detail: "ACP program path is not configured"
|
|
27024
27125
|
};
|
|
27025
27126
|
}
|
|
27026
|
-
const
|
|
27027
|
-
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
|
|
27036
|
-
|
|
27037
|
-
|
|
27038
|
-
|
|
27039
|
-
|
|
27040
|
-
|
|
27041
|
-
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27127
|
+
const env = buildSpawnEnv(recipe, recipe.homePath);
|
|
27128
|
+
const outcome = isKimiInstance(recipe) ? await probeKimi({ recipe, host, env }) : await probeAcpModelsViaSession({ recipe, host, env });
|
|
27129
|
+
switch (outcome.kind) {
|
|
27130
|
+
case "not-started":
|
|
27131
|
+
return {
|
|
27132
|
+
installed: false,
|
|
27133
|
+
version: null,
|
|
27134
|
+
readiness: "error",
|
|
27135
|
+
auth: { status: "unknown" },
|
|
27136
|
+
...outcome.detail === void 0 ? {} : { detail: outcome.detail }
|
|
27137
|
+
};
|
|
27138
|
+
case "failed":
|
|
27139
|
+
return {
|
|
27140
|
+
installed: true,
|
|
27141
|
+
version: outcome.version,
|
|
27142
|
+
readiness: "error",
|
|
27143
|
+
auth: { status: "unknown" },
|
|
27144
|
+
...outcome.detail === void 0 ? {} : { detail: outcome.detail }
|
|
27145
|
+
};
|
|
27146
|
+
case "auth-required":
|
|
27147
|
+
return {
|
|
27148
|
+
installed: true,
|
|
27149
|
+
version: outcome.version,
|
|
27150
|
+
readiness: "ready",
|
|
27151
|
+
auth: { status: "unauthenticated" }
|
|
27152
|
+
};
|
|
27153
|
+
case "answered":
|
|
27154
|
+
return {
|
|
27155
|
+
installed: true,
|
|
27156
|
+
version: outcome.version,
|
|
27157
|
+
readiness: "ready",
|
|
27158
|
+
auth: { status: "unknown" },
|
|
27159
|
+
...outcome.models === void 0 ? {} : { models: outcome.models },
|
|
27160
|
+
// 清单与当前档必须同进同出:只报清单,界面在清单里找不到当前档会整个不画那一格。
|
|
27161
|
+
...outcome.nativeModes.length === 0 ? {} : {
|
|
27162
|
+
nativeModes: outcome.nativeModes,
|
|
27163
|
+
...outcome.currentNativeModeId === void 0 ? {} : { currentNativeModeId: outcome.currentNativeModeId }
|
|
27164
|
+
}
|
|
27165
|
+
};
|
|
27166
|
+
}
|
|
27054
27167
|
},
|
|
27055
27168
|
startSession: async (input2, signal) => {
|
|
27056
27169
|
if (disposed) throw new Error("instance disposed");
|
|
@@ -27249,6 +27362,7 @@ var createAcpInstance = (config2, host) => {
|
|
|
27249
27362
|
return { threadId, turns: booked.turns };
|
|
27250
27363
|
},
|
|
27251
27364
|
events,
|
|
27365
|
+
continuationKey: acpContinuationKey(recipe),
|
|
27252
27366
|
dispose: async () => {
|
|
27253
27367
|
if (disposed) return;
|
|
27254
27368
|
disposed = true;
|
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.2143",
|
|
4
4
|
"description": "Generic ACP executor: user-supplied CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@types/node": "24.12.4",
|
|
21
21
|
"esbuild": "0.28.1",
|
|
22
22
|
"vite-plus": "0.2.2",
|
|
23
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
23
|
+
"@ycodium-ai/plugin-api": "0.2.2143",
|
|
24
24
|
"ycodium-acp-executor": "0.0.0",
|
|
25
25
|
"ycodium-acp-protocol": "0.0.0"
|
|
26
26
|
},
|