@ycodium-ai/agent-acp 0.2.2130 → 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 +260 -152
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -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,9 +23832,15 @@ 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;
|
|
@@ -23833,7 +23849,7 @@ function createAcpConnection(options) {
|
|
|
23833
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);
|
|
@@ -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);
|
|
@@ -26328,10 +26350,10 @@ function createAcpExecutor(options) {
|
|
|
26328
26350
|
}
|
|
26329
26351
|
|
|
26330
26352
|
// ../../packages/ycodium-acp-executor/src/probe.ts
|
|
26331
|
-
function withProbeTimeout(promise2, timeoutMs,
|
|
26353
|
+
function withProbeTimeout(promise2, timeoutMs, what) {
|
|
26332
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(
|
|
@@ -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((resolve2, 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
|
-
resolve2(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) {
|
|
@@ -27028,34 +27124,46 @@ var createAcpInstance = (config2, host) => {
|
|
|
27028
27124
|
detail: "ACP program path is not configured"
|
|
27029
27125
|
};
|
|
27030
27126
|
}
|
|
27031
|
-
const
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
|
|
27036
|
-
|
|
27037
|
-
|
|
27038
|
-
|
|
27039
|
-
|
|
27040
|
-
|
|
27041
|
-
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
|
|
27055
|
-
|
|
27056
|
-
|
|
27057
|
-
|
|
27058
|
-
|
|
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
|
+
}
|
|
27059
27167
|
},
|
|
27060
27168
|
startSession: async (input2, signal) => {
|
|
27061
27169
|
if (disposed) throw new Error("instance disposed");
|
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
|
},
|