@ycodium-ai/agent-kimi 0.2.2106 → 0.2.2510
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/README.md +16 -15
- package/dist/index.js +839 -305
- package/locales/en.json +14 -0
- package/locales/zh-CN.json +14 -0
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
import { definePlugin } from "@ycodium-ai/plugin-api";
|
|
9
9
|
|
|
10
10
|
// src/card.ts
|
|
11
|
-
var KIMI_DRIVER_KIND = "
|
|
11
|
+
var KIMI_DRIVER_KIND = "kimiCode";
|
|
12
12
|
var KIMI_CARD = {
|
|
13
13
|
driverKind: KIMI_DRIVER_KIND,
|
|
14
14
|
displayName: "Kimi Code",
|
|
@@ -17,20 +17,20 @@ var KIMI_CARD = {
|
|
|
17
17
|
launchArgs: "acp",
|
|
18
18
|
homeEnvVar: "KIMI_CODE_HOME",
|
|
19
19
|
environment: [],
|
|
20
|
+
// 官方安装器装进 ~/.kimi-code(安装器的 KIMI_INSTALL_DIR 默认值)。
|
|
20
21
|
install: {
|
|
21
22
|
kind: "vendorScript",
|
|
22
23
|
posixCommand: "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash",
|
|
23
24
|
windowsCommand: "irm https://code.kimi.com/kimi-code/install.ps1 | iex",
|
|
24
|
-
// 安装器的 KIMI_INSTALL_DIR 默认就是 $HOME/.kimi-code。
|
|
25
25
|
installedPathSegment: "/.kimi-code/"
|
|
26
26
|
},
|
|
27
|
-
// `kimi login` 就是设备码流程(CLI 自述 "via the device-code flow"
|
|
28
|
-
// ACP
|
|
27
|
+
// `kimi login` 就是设备码流程(CLI 自述 "via the device-code flow"),无头机器也登得上;
|
|
28
|
+
// ACP 子进程复用缓存下来的凭据,不需要环境变量。
|
|
29
29
|
signIn: [{ kind: "command", command: "kimi login" }],
|
|
30
30
|
deviceCodeSignInArgs: ["login"],
|
|
31
31
|
npmPackage: "@moonshot-ai/kimi-code",
|
|
32
32
|
homebrewFormula: "",
|
|
33
|
-
// 是 `upgrade` 不是 `update`(`update`
|
|
33
|
+
// 是 `upgrade` 不是 `update`(`update` 只是它的别名)。
|
|
34
34
|
selfUpdateArgs: ["upgrade"],
|
|
35
35
|
docsUrl: "https://github.com/MoonshotAI/kimi-code",
|
|
36
36
|
setupNote: "",
|
|
@@ -38,33 +38,43 @@ var KIMI_CARD = {
|
|
|
38
38
|
defaultTextGenerationModel: "",
|
|
39
39
|
customModelIdExample: "",
|
|
40
40
|
modelSlugAliases: null,
|
|
41
|
-
// 两份都是 Moonshot 自家目录,id 空间不相交,按序精确匹配不撞车。
|
|
42
|
-
modelsDevProviderIds: ["kimi-for-coding", "moonshotai"],
|
|
43
|
-
modelsDevSlugPrefixed: false,
|
|
44
|
-
// ACP 上报的 id 一律带这个命名空间(`kimi-code/k3`),models.dev 那边是裸的。
|
|
45
|
-
modelSlugPrefix: "kimi-code/",
|
|
46
|
-
// 与宿主 acp driver 今天的注入面一致。
|
|
47
41
|
mcpTransports: ["stdio", "http", "sse"],
|
|
48
42
|
pluginManaged: true,
|
|
49
43
|
verifiedSkills: false,
|
|
50
44
|
everydayHarness: false,
|
|
51
45
|
capabilities: {
|
|
52
|
-
// ycodium-acp-executor 尚不支持会话内换模型,名片必须说实话。
|
|
53
46
|
sessionModelSwitch: "unsupported",
|
|
54
|
-
|
|
47
|
+
// 与通用 ACP 同:`setRuntimeMode` 只改自己的会话记录,用户真正切得动的是
|
|
48
|
+
// `nativeModeSwitch`。kimi `acp` 的 `session/set_mode plan` 实测回 `{}` 并推
|
|
49
|
+
// `current_mode_update`,不存在的 modeId 被 `-32602 Unknown modeId` 拒掉。
|
|
50
|
+
runtimeModeSwitch: "in-session",
|
|
51
|
+
nativeModeSwitch: true
|
|
55
52
|
},
|
|
56
|
-
// 凭据由 CLI 自己保管在它 home 里,宿主不读 token。
|
|
57
53
|
credentialSources: [],
|
|
58
54
|
diagnostics: [],
|
|
55
|
+
// 设置表单照这份画:带 x-ycodium-form 的属性才进表单(enabled、customModels 等另有入口,不在此列),
|
|
56
|
+
// 顺序看 x-ycodium-form-order;文案键在本插件 locales/<locale>.json 里解析,宿主不兜底。
|
|
59
57
|
configSchema: {
|
|
60
58
|
type: "object",
|
|
59
|
+
"x-ycodium-form-order": ["binaryPath", "homePath"],
|
|
61
60
|
properties: {
|
|
62
|
-
binaryPath: {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
binaryPath: {
|
|
62
|
+
type: "string",
|
|
63
|
+
"x-ycodium-form": {
|
|
64
|
+
titleKey: "form.binaryPath.title",
|
|
65
|
+
descriptionKey: "form.binaryPath.description",
|
|
66
|
+
placeholderKey: "form.binaryPath.placeholder",
|
|
67
|
+
control: "executable-path"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
homePath: {
|
|
71
|
+
type: "string",
|
|
72
|
+
"x-ycodium-form": {
|
|
73
|
+
titleKey: "form.homePath.title",
|
|
74
|
+
descriptionKey: "form.homePath.description",
|
|
75
|
+
placeholderKey: "form.homePath.placeholder"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
68
78
|
enabled: { type: "boolean" },
|
|
69
79
|
customModels: { type: "array" },
|
|
70
80
|
driver: { type: "string" },
|
|
@@ -74,40 +84,16 @@ var KIMI_CARD = {
|
|
|
74
84
|
additionalProperties: true
|
|
75
85
|
},
|
|
76
86
|
modelConnectivity: {
|
|
77
|
-
dialects: [
|
|
78
|
-
acceptsExternalEndpoints:
|
|
79
|
-
|
|
80
|
-
// `applyEnvModelConfig` 逐行读出来的):
|
|
81
|
-
//
|
|
82
|
-
// KIMI_MODEL_NAME 门闩。没设它,后面三个一律不读。
|
|
83
|
-
// KIMI_MODEL_API_KEY 设了 NAME 却缺它会硬报错。
|
|
84
|
-
// KIMI_MODEL_BASE_URL 地址。
|
|
85
|
-
// KIMI_MODEL_PROVIDER_TYPE kimi(默认) / anthropic / openai,决定它说哪种话。
|
|
86
|
-
//
|
|
87
|
-
// 别用 ANTHROPIC_BASE_URL——「Kimi 是 Claude Code fork」在这个 CLI 上不成立:
|
|
88
|
-
// ANTHROPIC_* 只存在于它内嵌的 SDK 里,而 Kimi 显式传 baseUrl 进去,显式值赢过
|
|
89
|
-
// SDK 的环境变量兜底。KIMI_BASE_URL 也不行,那个读的是 config 文件里的
|
|
90
|
-
// provider.env 映射,不是进程环境。
|
|
91
|
-
//
|
|
92
|
-
// 这里钉死 `openai` 类型 = chat-completions。代理按手实际打的路径认方言,所以
|
|
93
|
-
// 就算这一栏将来改成别的,代理那边不用跟着动。
|
|
94
|
-
// 它 `openai` 类型的默认 base 是 `https://api.openai.com/v1`——base 含 /v1,
|
|
95
|
-
// 后面自己加 /chat/completions,跟 dsh 一样。
|
|
96
|
-
nativePathSuffix: "/chat/completions",
|
|
97
|
-
baseUrlEnvKey: "KIMI_MODEL_BASE_URL",
|
|
98
|
-
credentialEnvKey: "KIMI_MODEL_API_KEY",
|
|
99
|
-
extraEnv: [
|
|
100
|
-
{ name: "KIMI_MODEL_NAME", value: "$model" },
|
|
101
|
-
{ name: "KIMI_MODEL_PROVIDER_TYPE", value: "openai" }
|
|
102
|
-
]
|
|
103
|
-
},
|
|
104
|
-
// 存量 `driver: "acp"` 信封里命令是 kimi 或账号目录变量是 KIMI_CODE_HOME 的归这双手。
|
|
105
|
-
legacyAcpClaim: { commandName: "kimi", homeEnvVar: "KIMI_CODE_HOME" }
|
|
87
|
+
dialects: [],
|
|
88
|
+
acceptsExternalEndpoints: false
|
|
89
|
+
}
|
|
106
90
|
};
|
|
107
91
|
|
|
108
92
|
// src/kimiInstance.ts
|
|
109
|
-
import * as
|
|
110
|
-
import * as
|
|
93
|
+
import * as NodeOS2 from "node:os";
|
|
94
|
+
import * as NodePath3 from "node:path";
|
|
95
|
+
import { mergeLaunchEnv, modelSelectionStringOption } from "@ycodium-ai/plugin-api/executor";
|
|
96
|
+
import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
111
97
|
|
|
112
98
|
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
113
99
|
import * as NodeCrypto from "node:crypto";
|
|
@@ -23497,10 +23483,44 @@ var legacyClientNotificationMethods = /* @__PURE__ */ new Set([
|
|
|
23497
23483
|
CLIENT_METHODS.elicitation_complete
|
|
23498
23484
|
]);
|
|
23499
23485
|
|
|
23500
|
-
// ../../packages/ycodium-acp-
|
|
23486
|
+
// ../../packages/ycodium-acp-executor/src/connection.ts
|
|
23501
23487
|
import * as NodeStream from "node:stream";
|
|
23502
23488
|
|
|
23503
|
-
// ../../packages/ycodium-acp-
|
|
23489
|
+
// ../../packages/ycodium-acp-executor/src/errors.ts
|
|
23490
|
+
var AcpExecutorError = class extends Error {
|
|
23491
|
+
code;
|
|
23492
|
+
constructor(code, message) {
|
|
23493
|
+
super(message);
|
|
23494
|
+
this.name = "AcpExecutorError";
|
|
23495
|
+
this.code = code;
|
|
23496
|
+
}
|
|
23497
|
+
};
|
|
23498
|
+
var AcpExecutorDisposedError = class extends AcpExecutorError {
|
|
23499
|
+
constructor(message = "ACP executor has been disposed") {
|
|
23500
|
+
super("disposed", message);
|
|
23501
|
+
this.name = "AcpExecutorDisposedError";
|
|
23502
|
+
}
|
|
23503
|
+
};
|
|
23504
|
+
var AcpExecutorNotStartedError = class extends AcpExecutorError {
|
|
23505
|
+
constructor(message = "ACP session has not been started") {
|
|
23506
|
+
super("not-started", message);
|
|
23507
|
+
this.name = "AcpExecutorNotStartedError";
|
|
23508
|
+
}
|
|
23509
|
+
};
|
|
23510
|
+
var AcpExecutorCancelTimeoutError = class extends AcpExecutorError {
|
|
23511
|
+
constructor(message = "Timed out waiting for session/prompt to finish after cancellation") {
|
|
23512
|
+
super("cancel-timeout", message);
|
|
23513
|
+
this.name = "AcpExecutorCancelTimeoutError";
|
|
23514
|
+
}
|
|
23515
|
+
};
|
|
23516
|
+
var AcpExecutorRequestError = class extends AcpExecutorError {
|
|
23517
|
+
method;
|
|
23518
|
+
constructor(method, message) {
|
|
23519
|
+
super("request-failed", message);
|
|
23520
|
+
this.name = "AcpExecutorRequestError";
|
|
23521
|
+
this.method = method;
|
|
23522
|
+
}
|
|
23523
|
+
};
|
|
23504
23524
|
var AcpConnectionClosedError = class extends Error {
|
|
23505
23525
|
constructor(message = "ACP connection closed") {
|
|
23506
23526
|
super(message);
|
|
@@ -23508,7 +23528,7 @@ var AcpConnectionClosedError = class extends Error {
|
|
|
23508
23528
|
}
|
|
23509
23529
|
};
|
|
23510
23530
|
|
|
23511
|
-
// ../../packages/ycodium-acp-
|
|
23531
|
+
// ../../packages/ycodium-acp-executor/src/jsonrpc.ts
|
|
23512
23532
|
function isRecord2(value) {
|
|
23513
23533
|
return typeof value === "object" && value !== null;
|
|
23514
23534
|
}
|
|
@@ -23546,7 +23566,7 @@ function readJsonRpcError(value) {
|
|
|
23546
23566
|
};
|
|
23547
23567
|
}
|
|
23548
23568
|
|
|
23549
|
-
// ../../packages/ycodium-acp-
|
|
23569
|
+
// ../../packages/ycodium-acp-executor/src/line-buffer.ts
|
|
23550
23570
|
var newline2 = 10;
|
|
23551
23571
|
var LineBuffer2 = class {
|
|
23552
23572
|
#pending = [];
|
|
@@ -23590,7 +23610,7 @@ var LineBuffer2 = class {
|
|
|
23590
23610
|
}
|
|
23591
23611
|
};
|
|
23592
23612
|
|
|
23593
|
-
// ../../packages/ycodium-acp-
|
|
23613
|
+
// ../../packages/ycodium-acp-executor/src/session-update.ts
|
|
23594
23614
|
var KNOWN_SESSION_UPDATES = /* @__PURE__ */ new Set([
|
|
23595
23615
|
"user_message_chunk",
|
|
23596
23616
|
"agent_message_chunk",
|
|
@@ -23635,7 +23655,7 @@ function decodeSessionUpdate(payload) {
|
|
|
23635
23655
|
return { status: "raw", params: payload };
|
|
23636
23656
|
}
|
|
23637
23657
|
|
|
23638
|
-
// ../../packages/ycodium-acp-
|
|
23658
|
+
// ../../packages/ycodium-acp-executor/src/connection.ts
|
|
23639
23659
|
var textDecoder = new TextDecoder();
|
|
23640
23660
|
var textEncoder = new TextEncoder();
|
|
23641
23661
|
function asBytes(chunk) {
|
|
@@ -23725,6 +23745,7 @@ function createAcpConnection(options) {
|
|
|
23725
23745
|
options.readable.off("data", onData);
|
|
23726
23746
|
options.readable.off("end", onEnd);
|
|
23727
23747
|
options.readable.off("error", onError);
|
|
23748
|
+
options.writable.off("error", onWritableError);
|
|
23728
23749
|
try {
|
|
23729
23750
|
await byteWriter.close();
|
|
23730
23751
|
} catch {
|
|
@@ -23863,8 +23884,17 @@ function createAcpConnection(options) {
|
|
|
23863
23884
|
endInboundBatch();
|
|
23864
23885
|
}
|
|
23865
23886
|
};
|
|
23887
|
+
const failInbound = (error62) => {
|
|
23888
|
+
if (closedError !== void 0) return;
|
|
23889
|
+
options.onInboundFailure?.(error62);
|
|
23890
|
+
void shutdown(
|
|
23891
|
+
new AcpConnectionClosedError(
|
|
23892
|
+
`ACP inbound handling failed: ${error62 instanceof Error ? error62.message : String(error62)}`
|
|
23893
|
+
)
|
|
23894
|
+
);
|
|
23895
|
+
};
|
|
23866
23896
|
const enqueueInbound = (work) => {
|
|
23867
|
-
inboundTail = inboundTail.then(work
|
|
23897
|
+
inboundTail = inboundTail.then(work).catch(failInbound);
|
|
23868
23898
|
};
|
|
23869
23899
|
const onData = (chunk) => {
|
|
23870
23900
|
if (closedError !== void 0) {
|
|
@@ -23914,9 +23944,15 @@ function createAcpConnection(options) {
|
|
|
23914
23944
|
);
|
|
23915
23945
|
});
|
|
23916
23946
|
};
|
|
23947
|
+
const onWritableError = (error62) => {
|
|
23948
|
+
void shutdown(
|
|
23949
|
+
error62 instanceof Error ? error62 : new AcpConnectionClosedError("ACP output stream error")
|
|
23950
|
+
);
|
|
23951
|
+
};
|
|
23917
23952
|
options.readable.on("data", onData);
|
|
23918
23953
|
options.readable.on("end", onEnd);
|
|
23919
23954
|
options.readable.on("error", onError);
|
|
23955
|
+
options.writable.once("error", onWritableError);
|
|
23920
23956
|
const request = (async (method, params) => {
|
|
23921
23957
|
failIfClosed();
|
|
23922
23958
|
const id = nextRequestId;
|
|
@@ -23925,7 +23961,7 @@ function createAcpConnection(options) {
|
|
|
23925
23961
|
pending.set(String(id), { method, resolve: resolve2, reject });
|
|
23926
23962
|
const message = params === void 0 ? { jsonrpc: "2.0", id, method } : { jsonrpc: "2.0", id, method, params };
|
|
23927
23963
|
try {
|
|
23928
|
-
await writeMessage(message);
|
|
23964
|
+
await Promise.race([writeMessage(message), promise2]);
|
|
23929
23965
|
} catch (error62) {
|
|
23930
23966
|
if (pending.delete(String(id))) {
|
|
23931
23967
|
reject(error62);
|
|
@@ -23977,6 +24013,12 @@ function acpApprovalOptions(request) {
|
|
|
23977
24013
|
}
|
|
23978
24014
|
return options;
|
|
23979
24015
|
}
|
|
24016
|
+
function selectAutoApprovedAcpPermissionOption(request) {
|
|
24017
|
+
if (new Set(request.options.map((option) => option.kind)).size !== request.options.length) {
|
|
24018
|
+
return void 0;
|
|
24019
|
+
}
|
|
24020
|
+
return selectAcpPermissionOptionId(request, "acceptForSession") ?? selectAcpPermissionOptionId(request, "accept");
|
|
24021
|
+
}
|
|
23980
24022
|
function parseAcpResumeCursor(raw, schemaVersion) {
|
|
23981
24023
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return void 0;
|
|
23982
24024
|
const record2 = raw;
|
|
@@ -24138,42 +24180,6 @@ var UnboundedEventStream = class {
|
|
|
24138
24180
|
}
|
|
24139
24181
|
};
|
|
24140
24182
|
|
|
24141
|
-
// ../../packages/ycodium-acp-executor/src/errors.ts
|
|
24142
|
-
var AcpExecutorError = class extends Error {
|
|
24143
|
-
code;
|
|
24144
|
-
constructor(code, message) {
|
|
24145
|
-
super(message);
|
|
24146
|
-
this.name = "AcpExecutorError";
|
|
24147
|
-
this.code = code;
|
|
24148
|
-
}
|
|
24149
|
-
};
|
|
24150
|
-
var AcpExecutorDisposedError = class extends AcpExecutorError {
|
|
24151
|
-
constructor(message = "ACP executor has been disposed") {
|
|
24152
|
-
super("disposed", message);
|
|
24153
|
-
this.name = "AcpExecutorDisposedError";
|
|
24154
|
-
}
|
|
24155
|
-
};
|
|
24156
|
-
var AcpExecutorNotStartedError = class extends AcpExecutorError {
|
|
24157
|
-
constructor(message = "ACP session has not been started") {
|
|
24158
|
-
super("not-started", message);
|
|
24159
|
-
this.name = "AcpExecutorNotStartedError";
|
|
24160
|
-
}
|
|
24161
|
-
};
|
|
24162
|
-
var AcpExecutorCancelTimeoutError = class extends AcpExecutorError {
|
|
24163
|
-
constructor(message = "Timed out waiting for session/prompt to finish after cancellation") {
|
|
24164
|
-
super("cancel-timeout", message);
|
|
24165
|
-
this.name = "AcpExecutorCancelTimeoutError";
|
|
24166
|
-
}
|
|
24167
|
-
};
|
|
24168
|
-
var AcpExecutorRequestError = class extends AcpExecutorError {
|
|
24169
|
-
method;
|
|
24170
|
-
constructor(method, message) {
|
|
24171
|
-
super("request-failed", message);
|
|
24172
|
-
this.name = "AcpExecutorRequestError";
|
|
24173
|
-
this.method = method;
|
|
24174
|
-
}
|
|
24175
|
-
};
|
|
24176
|
-
|
|
24177
24183
|
// ../../packages/ycodium-acp-executor/src/events.ts
|
|
24178
24184
|
function canonicalRequestTypeFromAcpKind(kind) {
|
|
24179
24185
|
switch (kind) {
|
|
@@ -24370,6 +24376,168 @@ function makeAcpContentDeltaEvent(input2) {
|
|
|
24370
24376
|
};
|
|
24371
24377
|
}
|
|
24372
24378
|
|
|
24379
|
+
// ../../packages/ycodium-acp-executor/src/config-options.ts
|
|
24380
|
+
function isRecord3(value) {
|
|
24381
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24382
|
+
}
|
|
24383
|
+
function asString(value) {
|
|
24384
|
+
return typeof value === "string" ? value : void 0;
|
|
24385
|
+
}
|
|
24386
|
+
function normalizedField(option, key) {
|
|
24387
|
+
return asString(option[key])?.trim().toLowerCase() ?? "";
|
|
24388
|
+
}
|
|
24389
|
+
function looksLikeEffortOption(option) {
|
|
24390
|
+
const id = normalizedField(option, "id");
|
|
24391
|
+
const name = normalizedField(option, "name");
|
|
24392
|
+
return id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") || normalizedField(option, "category") === "thought_level";
|
|
24393
|
+
}
|
|
24394
|
+
function flattenChoices(rawOptions, currentValue) {
|
|
24395
|
+
if (!Array.isArray(rawOptions)) return [];
|
|
24396
|
+
const out = [];
|
|
24397
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24398
|
+
const push = (entry) => {
|
|
24399
|
+
if (!isRecord3(entry)) return;
|
|
24400
|
+
const value = asString(entry["value"]);
|
|
24401
|
+
if (value === void 0 || seen.has(value)) return;
|
|
24402
|
+
seen.add(value);
|
|
24403
|
+
const description = asString(entry["description"])?.trim();
|
|
24404
|
+
const name = asString(entry["name"])?.trim();
|
|
24405
|
+
out.push({
|
|
24406
|
+
value,
|
|
24407
|
+
...name ? { name } : {},
|
|
24408
|
+
label: name || value,
|
|
24409
|
+
...description ? { description } : {},
|
|
24410
|
+
...currentValue !== void 0 && currentValue === value ? { isDefault: true } : {}
|
|
24411
|
+
});
|
|
24412
|
+
};
|
|
24413
|
+
for (const entry of rawOptions) {
|
|
24414
|
+
if (isRecord3(entry) && Array.isArray(entry["options"])) {
|
|
24415
|
+
for (const nested of entry["options"]) push(nested);
|
|
24416
|
+
continue;
|
|
24417
|
+
}
|
|
24418
|
+
push(entry);
|
|
24419
|
+
}
|
|
24420
|
+
return out;
|
|
24421
|
+
}
|
|
24422
|
+
function findAcpEffortConfig(configOptions) {
|
|
24423
|
+
if (!Array.isArray(configOptions)) return void 0;
|
|
24424
|
+
const candidates = configOptions.filter(isRecord3).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
|
|
24425
|
+
if (candidates.length === 0) return void 0;
|
|
24426
|
+
const picked = candidates.find((option) => normalizedField(option, "category") === "model_option") ?? candidates.find((option) => normalizedField(option, "id") === "effort") ?? candidates.find((option) => normalizedField(option, "category") === "thought_level") ?? candidates[0];
|
|
24427
|
+
if (picked === void 0) return void 0;
|
|
24428
|
+
const configId = asString(picked["id"])?.trim();
|
|
24429
|
+
if (!configId) return void 0;
|
|
24430
|
+
const choices = flattenChoices(picked["options"], asString(picked["currentValue"])?.trim());
|
|
24431
|
+
if (choices.length === 0) return void 0;
|
|
24432
|
+
return {
|
|
24433
|
+
configId,
|
|
24434
|
+
label: asString(picked["name"])?.trim() ?? "",
|
|
24435
|
+
choices
|
|
24436
|
+
};
|
|
24437
|
+
}
|
|
24438
|
+
|
|
24439
|
+
// ../../packages/ycodium-acp-executor/src/runtime-mode.ts
|
|
24440
|
+
function isRecord4(value) {
|
|
24441
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24442
|
+
}
|
|
24443
|
+
function asString2(value) {
|
|
24444
|
+
return typeof value === "string" ? value : void 0;
|
|
24445
|
+
}
|
|
24446
|
+
function acpModeConfigId(setup) {
|
|
24447
|
+
if (!isRecord4(setup)) return void 0;
|
|
24448
|
+
const configOptions = setup["configOptions"];
|
|
24449
|
+
if (!Array.isArray(configOptions)) return void 0;
|
|
24450
|
+
for (const option of configOptions) {
|
|
24451
|
+
if (!isRecord4(option)) continue;
|
|
24452
|
+
if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
|
|
24453
|
+
const id = asString2(option["id"])?.trim();
|
|
24454
|
+
if (id) return id;
|
|
24455
|
+
}
|
|
24456
|
+
return void 0;
|
|
24457
|
+
}
|
|
24458
|
+
function acpCurrentModeId(setup) {
|
|
24459
|
+
if (!isRecord4(setup)) return void 0;
|
|
24460
|
+
const modes = setup["modes"];
|
|
24461
|
+
if (isRecord4(modes)) {
|
|
24462
|
+
const current = asString2(modes["currentModeId"])?.trim();
|
|
24463
|
+
if (current) return current;
|
|
24464
|
+
}
|
|
24465
|
+
const configOptions = setup["configOptions"];
|
|
24466
|
+
if (Array.isArray(configOptions)) {
|
|
24467
|
+
for (const option of configOptions) {
|
|
24468
|
+
if (!isRecord4(option)) continue;
|
|
24469
|
+
if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
|
|
24470
|
+
const current = asString2(option["currentValue"])?.trim();
|
|
24471
|
+
if (current) return current;
|
|
24472
|
+
}
|
|
24473
|
+
}
|
|
24474
|
+
return void 0;
|
|
24475
|
+
}
|
|
24476
|
+
|
|
24477
|
+
// ../../packages/ycodium-acp-executor/src/handshake.ts
|
|
24478
|
+
function acpInitializePayload(clientInfo, overrides) {
|
|
24479
|
+
return {
|
|
24480
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
24481
|
+
clientCapabilities: {
|
|
24482
|
+
fs: {
|
|
24483
|
+
readTextFile: false,
|
|
24484
|
+
writeTextFile: false,
|
|
24485
|
+
...overrides?.fs
|
|
24486
|
+
},
|
|
24487
|
+
terminal: overrides?.terminal ?? false
|
|
24488
|
+
},
|
|
24489
|
+
clientInfo
|
|
24490
|
+
};
|
|
24491
|
+
}
|
|
24492
|
+
|
|
24493
|
+
// ../../packages/ycodium-acp-executor/src/config-option-wiring.ts
|
|
24494
|
+
var VENDOR_CATEGORY_PREFIX = "_";
|
|
24495
|
+
var ACP_CONFIG_CATEGORY_HANDLING = {
|
|
24496
|
+
mode: {
|
|
24497
|
+
consumed: true,
|
|
24498
|
+
via: "runtime-mode.ts\uFF1AacpAvailableModes / acpCurrentModeId / acpModeConfigId"
|
|
24499
|
+
},
|
|
24500
|
+
model: {
|
|
24501
|
+
consumed: true,
|
|
24502
|
+
via: "runtime-model.ts:extractModelConfigId \u2192 executor.ts:applyRequestedModel"
|
|
24503
|
+
},
|
|
24504
|
+
thought_level: {
|
|
24505
|
+
consumed: true,
|
|
24506
|
+
via: "config-options.ts:findAcpEffortConfig \u2192 executor.ts:applyRequestedEffort"
|
|
24507
|
+
},
|
|
24508
|
+
model_option: {
|
|
24509
|
+
consumed: true,
|
|
24510
|
+
// 精确说法:它不是**识别器**,是**优先级**。`looksLikeEffortOption` 先筛出候选,
|
|
24511
|
+
// 标了 `model_option` 的在候选里排第一(厂商自己标的最准),排在 id 叫 `effort`
|
|
24512
|
+
// 的和标 `thought_level` 的前面。光有这个 category 而 id/name 不像力度档的,
|
|
24513
|
+
// 压根进不了候选。
|
|
24514
|
+
via: "config-options.ts:findAcpEffortConfig\uFF08\u5019\u9009\u91CC\u7684\u6700\u9AD8\u4F18\u5148\u7EA7\uFF0C\u538B\u8FC7 thought_level\uFF09"
|
|
24515
|
+
},
|
|
24516
|
+
model_config: {
|
|
24517
|
+
consumed: false,
|
|
24518
|
+
note: "\u53EA\u6709\u5BBF\u4E3B\u7684 CursorProvider \u6D88\u8D39\u8FC7\uFF08context / fast / thinking \u4E09\u4E2A\u5F00\u5173\uFF09\u3002Cursor 2026-09-20 \u5E9F\u5F03\u5220\u9664\uFF0C\u8FD9\u4E00\u7C7B\u73B0\u5728\u6CA1\u6709\u6D88\u8D39\u70B9\uFF1B\u6CA1\u89C1\u8FC7\u522B\u5BB6\u7684\u771F\u5B9E\u8F7D\u8377\uFF0C\u5148\u8BB0\u8D26\u4E0D\u731C\u5F62\u72B6\u3002"
|
|
24519
|
+
}
|
|
24520
|
+
};
|
|
24521
|
+
var KNOWN_CATEGORIES = new Set(Object.keys(ACP_CONFIG_CATEGORY_HANDLING));
|
|
24522
|
+
function unhandledConfigCategories(configOptions) {
|
|
24523
|
+
if (!configOptions) return [];
|
|
24524
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24525
|
+
const out = [];
|
|
24526
|
+
for (const option of configOptions) {
|
|
24527
|
+
const category = option.category?.trim();
|
|
24528
|
+
if (!category) continue;
|
|
24529
|
+
if (KNOWN_CATEGORIES.has(category)) continue;
|
|
24530
|
+
if (seen.has(category)) continue;
|
|
24531
|
+
seen.add(category);
|
|
24532
|
+
out.push({
|
|
24533
|
+
category,
|
|
24534
|
+
optionId: option.id.trim(),
|
|
24535
|
+
vendorExtension: category.startsWith(VENDOR_CATEGORY_PREFIX)
|
|
24536
|
+
});
|
|
24537
|
+
}
|
|
24538
|
+
return out;
|
|
24539
|
+
}
|
|
24540
|
+
|
|
24373
24541
|
// ../../packages/ycodium-acp-executor/src/mutex.ts
|
|
24374
24542
|
var Mutex = class {
|
|
24375
24543
|
locked = false;
|
|
@@ -24412,7 +24580,7 @@ var Mutex = class {
|
|
|
24412
24580
|
};
|
|
24413
24581
|
|
|
24414
24582
|
// ../../packages/ycodium-acp-executor/src/util.ts
|
|
24415
|
-
function
|
|
24583
|
+
function isRecord5(value) {
|
|
24416
24584
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24417
24585
|
}
|
|
24418
24586
|
function asTrimmedString(value) {
|
|
@@ -24458,11 +24626,11 @@ function extractCommandFromTitle(title) {
|
|
|
24458
24626
|
return backtickMatch?.[1]?.trim() || void 0;
|
|
24459
24627
|
}
|
|
24460
24628
|
function extractToolCommand(data, title) {
|
|
24461
|
-
const item =
|
|
24462
|
-
const itemInput = item &&
|
|
24463
|
-
const itemResult = item &&
|
|
24464
|
-
const rawInput =
|
|
24465
|
-
const dataInput =
|
|
24629
|
+
const item = isRecord5(data?.["item"]) ? data["item"] : void 0;
|
|
24630
|
+
const itemInput = item && isRecord5(item["input"]) ? item["input"] : void 0;
|
|
24631
|
+
const itemResult = item && isRecord5(item["result"]) ? item["result"] : void 0;
|
|
24632
|
+
const rawInput = isRecord5(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
24633
|
+
const dataInput = isRecord5(data?.["input"]) ? data["input"] : void 0;
|
|
24466
24634
|
const candidates = [
|
|
24467
24635
|
normalizeCommandValue(item?.["command"]),
|
|
24468
24636
|
normalizeCommandValue(itemInput?.["command"]),
|
|
@@ -24507,7 +24675,7 @@ function collectPaths(value, paths, seen, depth) {
|
|
|
24507
24675
|
}
|
|
24508
24676
|
return;
|
|
24509
24677
|
}
|
|
24510
|
-
if (!
|
|
24678
|
+
if (!isRecord5(value)) {
|
|
24511
24679
|
return;
|
|
24512
24680
|
}
|
|
24513
24681
|
for (const key of ["path", "filePath", "relativePath", "filename", "newPath", "oldPath"]) {
|
|
@@ -24570,7 +24738,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
24570
24738
|
const title = asTrimmedString(input2.title);
|
|
24571
24739
|
const detail = stripTrailingExitCode(asTrimmedString(input2.detail));
|
|
24572
24740
|
const fallbackSummary = asTrimmedString(input2.fallbackSummary) ?? "Tool";
|
|
24573
|
-
const data =
|
|
24741
|
+
const data = isRecord5(input2.data) ? input2.data : void 0;
|
|
24574
24742
|
const command = extractToolCommand(data, title);
|
|
24575
24743
|
const primaryPath = extractPrimaryPath(data);
|
|
24576
24744
|
const action = classifyToolAction({
|
|
@@ -24602,7 +24770,7 @@ function deriveToolActivityPresentation(input2) {
|
|
|
24602
24770
|
};
|
|
24603
24771
|
}
|
|
24604
24772
|
if (action === "search") {
|
|
24605
|
-
const rawInput =
|
|
24773
|
+
const rawInput = isRecord5(data?.["rawInput"]) ? data["rawInput"] : void 0;
|
|
24606
24774
|
const query = asTrimmedString(rawInput?.["query"]) ?? asTrimmedString(rawInput?.["pattern"]) ?? asTrimmedString(rawInput?.["searchTerm"]);
|
|
24607
24775
|
return {
|
|
24608
24776
|
summary: "Searched files",
|
|
@@ -24641,6 +24809,46 @@ function findSessionConfigOption(configOptions, configId) {
|
|
|
24641
24809
|
}
|
|
24642
24810
|
return configOptions.find((option) => option.id.trim() === normalizedConfigId);
|
|
24643
24811
|
}
|
|
24812
|
+
function collectSessionConfigOptionValues(configOption) {
|
|
24813
|
+
if (configOption.type !== "select" || !configOption.options) {
|
|
24814
|
+
return [];
|
|
24815
|
+
}
|
|
24816
|
+
return configOption.options.flatMap(
|
|
24817
|
+
(entry) => "value" in entry ? [entry.value] : entry.options.map((option) => option.value)
|
|
24818
|
+
);
|
|
24819
|
+
}
|
|
24820
|
+
function collectSessionModelIds(models) {
|
|
24821
|
+
if (!isRecord5(models) || !Array.isArray(models["availableModels"])) {
|
|
24822
|
+
return [];
|
|
24823
|
+
}
|
|
24824
|
+
return models["availableModels"].flatMap(
|
|
24825
|
+
(model) => isRecord5(model) && typeof model["modelId"] === "string" ? [model["modelId"]] : []
|
|
24826
|
+
);
|
|
24827
|
+
}
|
|
24828
|
+
function catalogModelLastSegment(value) {
|
|
24829
|
+
if (value.startsWith("[")) {
|
|
24830
|
+
let parsed;
|
|
24831
|
+
try {
|
|
24832
|
+
parsed = JSON.parse(value);
|
|
24833
|
+
} catch {
|
|
24834
|
+
return void 0;
|
|
24835
|
+
}
|
|
24836
|
+
if (!Array.isArray(parsed) || parsed.length < 2) return void 0;
|
|
24837
|
+
const last = parsed[parsed.length - 1];
|
|
24838
|
+
return typeof last === "string" ? last : void 0;
|
|
24839
|
+
}
|
|
24840
|
+
const separator = value.indexOf("/");
|
|
24841
|
+
return separator > 0 && separator < value.length - 1 ? value.slice(separator + 1) : void 0;
|
|
24842
|
+
}
|
|
24843
|
+
function matchAdvertisedModelValue(requestedModelId, advertisedValues) {
|
|
24844
|
+
const wanted = requestedModelId.trim();
|
|
24845
|
+
if (!wanted) return void 0;
|
|
24846
|
+
if (advertisedValues.includes(wanted)) return wanted;
|
|
24847
|
+
const byLastSegment = advertisedValues.filter(
|
|
24848
|
+
(value) => catalogModelLastSegment(value) === wanted
|
|
24849
|
+
);
|
|
24850
|
+
return byLastSegment.length === 1 ? byLastSegment[0] : void 0;
|
|
24851
|
+
}
|
|
24644
24852
|
function parseSessionModeState(sessionResponse) {
|
|
24645
24853
|
const modes = sessionResponse.modes;
|
|
24646
24854
|
if (!modes) return void 0;
|
|
@@ -24679,7 +24887,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
24679
24887
|
}
|
|
24680
24888
|
const commands = [];
|
|
24681
24889
|
for (const command of availableCommands) {
|
|
24682
|
-
if (!
|
|
24890
|
+
if (!isRecord5(command)) {
|
|
24683
24891
|
continue;
|
|
24684
24892
|
}
|
|
24685
24893
|
const name = typeof command["name"] === "string" ? command["name"].trim() : "";
|
|
@@ -24687,7 +24895,7 @@ function parseAvailableCommandsUpdate(params) {
|
|
|
24687
24895
|
continue;
|
|
24688
24896
|
}
|
|
24689
24897
|
const description = typeof command["description"] === "string" ? command["description"].trim() || void 0 : void 0;
|
|
24690
|
-
const input2 =
|
|
24898
|
+
const input2 = isRecord5(command["input"]) ? command["input"] : void 0;
|
|
24691
24899
|
const inputHint = typeof input2?.["hint"] === "string" ? input2["hint"].trim() || void 0 : void 0;
|
|
24692
24900
|
commands.push({
|
|
24693
24901
|
name,
|
|
@@ -24749,7 +24957,7 @@ function extractCommandFromTitle2(title) {
|
|
|
24749
24957
|
return match?.[1]?.trim() || void 0;
|
|
24750
24958
|
}
|
|
24751
24959
|
function extractToolCallCommand(rawInput, title) {
|
|
24752
|
-
if (
|
|
24960
|
+
if (isRecord5(rawInput)) {
|
|
24753
24961
|
const directCommand = normalizeCommandValue2(rawInput["command"]);
|
|
24754
24962
|
if (directCommand) {
|
|
24755
24963
|
return directCommand;
|
|
@@ -24776,7 +24984,7 @@ function boundToolCallOutputText(text) {
|
|
|
24776
24984
|
}
|
|
24777
24985
|
var RAW_OUTPUT_TEXT_FIELDS = ["content", "stdout", "stderr", "output"];
|
|
24778
24986
|
function boundToolCallRawOutput(rawOutput) {
|
|
24779
|
-
if (!
|
|
24987
|
+
if (!isRecord5(rawOutput)) {
|
|
24780
24988
|
return rawOutput;
|
|
24781
24989
|
}
|
|
24782
24990
|
let changed = false;
|
|
@@ -25006,7 +25214,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
25006
25214
|
const entries = Array.isArray(upd["entries"]) ? upd["entries"] : [];
|
|
25007
25215
|
const plan = entries.map((entry, index) => ({
|
|
25008
25216
|
step: readAcpText(entry, "content") ?? `Step ${index + 1}`,
|
|
25009
|
-
status: normalizePlanStepStatus(
|
|
25217
|
+
status: normalizePlanStepStatus(isRecord5(entry) ? entry["status"] : void 0)
|
|
25010
25218
|
}));
|
|
25011
25219
|
if (plan.length > 0) {
|
|
25012
25220
|
events.push({
|
|
@@ -25045,7 +25253,7 @@ function parseSessionUpdateEvent(params) {
|
|
|
25045
25253
|
}
|
|
25046
25254
|
case "agent_message_chunk":
|
|
25047
25255
|
case "agent_thought_chunk": {
|
|
25048
|
-
const content =
|
|
25256
|
+
const content = isRecord5(upd["content"]) ? upd["content"] : void 0;
|
|
25049
25257
|
const contentType = content?.["type"];
|
|
25050
25258
|
const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
|
|
25051
25259
|
if (contentType === "text") {
|
|
@@ -25112,16 +25320,18 @@ function normalizeModelId(value) {
|
|
|
25112
25320
|
return value?.trim() || void 0;
|
|
25113
25321
|
}
|
|
25114
25322
|
function modelSelectionStateFromSetup(setup) {
|
|
25115
|
-
const sessionModels =
|
|
25323
|
+
const sessionModels = isRecord5(setup.models) ? setup.models : void 0;
|
|
25116
25324
|
const modelConfigId = extractModelConfigId(setup);
|
|
25117
25325
|
const strategy = sessionModels === void 0 && modelConfigId !== void 0 ? "config-option" : "session/set_model";
|
|
25118
|
-
const
|
|
25326
|
+
const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
|
|
25327
|
+
const configModel = modelConfigOption?.currentValue;
|
|
25119
25328
|
const currentModelId = strategy === "config-option" ? typeof configModel === "string" ? normalizeModelId(configModel) : void 0 : typeof sessionModels?.["currentModelId"] === "string" ? normalizeModelId(sessionModels["currentModelId"]) : void 0;
|
|
25120
25329
|
return {
|
|
25121
25330
|
strategy,
|
|
25122
25331
|
sessionModelsAdvertised: sessionModels !== void 0,
|
|
25123
25332
|
modelConfigId,
|
|
25124
|
-
currentModelId
|
|
25333
|
+
currentModelId,
|
|
25334
|
+
advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels)
|
|
25125
25335
|
};
|
|
25126
25336
|
}
|
|
25127
25337
|
function createAcpExecutor(options) {
|
|
@@ -25140,8 +25350,10 @@ function createAcpExecutor(options) {
|
|
|
25140
25350
|
strategy: "session/set_model",
|
|
25141
25351
|
sessionModelsAdvertised: false,
|
|
25142
25352
|
modelConfigId: void 0,
|
|
25143
|
-
currentModelId: void 0
|
|
25353
|
+
currentModelId: void 0,
|
|
25354
|
+
advertisedModelValues: []
|
|
25144
25355
|
};
|
|
25356
|
+
let lastUnmatchedModelId;
|
|
25145
25357
|
let initializeResult;
|
|
25146
25358
|
let startResult;
|
|
25147
25359
|
let startInFlight;
|
|
@@ -25466,6 +25678,12 @@ function createAcpExecutor(options) {
|
|
|
25466
25678
|
const userInputOutcome = await handlePermissionAsUserInput(params);
|
|
25467
25679
|
if (userInputOutcome !== void 0) return userInputOutcome;
|
|
25468
25680
|
const permissionRequest = parsePermissionRequest(params);
|
|
25681
|
+
if (options.autoApprove?.(permissionRequest) === true) {
|
|
25682
|
+
const optionId = selectAutoApprovedAcpPermissionOption(params);
|
|
25683
|
+
if (optionId !== void 0) {
|
|
25684
|
+
return { outcome: { outcome: "selected", optionId } };
|
|
25685
|
+
}
|
|
25686
|
+
}
|
|
25469
25687
|
const requestId = randomId();
|
|
25470
25688
|
const outcome = await new Promise((resolve2) => {
|
|
25471
25689
|
const pending = {
|
|
@@ -25500,6 +25718,12 @@ function createAcpExecutor(options) {
|
|
|
25500
25718
|
const connection = createAcpConnection({
|
|
25501
25719
|
readable: options.readable,
|
|
25502
25720
|
writable: options.writable,
|
|
25721
|
+
onInboundFailure: (error62) => {
|
|
25722
|
+
options.log?.warn?.("acp connection closed: an inbound request could not be answered", {
|
|
25723
|
+
threadId: options.threadId,
|
|
25724
|
+
error: error62 instanceof Error ? error62.message : String(error62)
|
|
25725
|
+
});
|
|
25726
|
+
},
|
|
25503
25727
|
onNotification: (notification) => {
|
|
25504
25728
|
if (notification.method === "session/update") {
|
|
25505
25729
|
handleSessionUpdate(notification.params);
|
|
@@ -25553,36 +25777,70 @@ function createAcpExecutor(options) {
|
|
|
25553
25777
|
if (requestedModelId === void 0 || requestedModelId === input2.state.currentModelId || input2.state.strategy === "session/set_model" && !input2.state.sessionModelsAdvertised || input2.state.strategy === "config-option" && input2.state.modelConfigId === void 0) {
|
|
25554
25778
|
return input2.state;
|
|
25555
25779
|
}
|
|
25780
|
+
const value = matchAdvertisedModelValue(requestedModelId, input2.state.advertisedModelValues);
|
|
25781
|
+
if (value === void 0) {
|
|
25782
|
+
if (requestedModelId !== lastUnmatchedModelId) {
|
|
25783
|
+
lastUnmatchedModelId = requestedModelId;
|
|
25784
|
+
options.log?.info("requested model is not in the agent catalog; keeping its own model", {
|
|
25785
|
+
requestedModelId,
|
|
25786
|
+
currentModelId: input2.state.currentModelId,
|
|
25787
|
+
advertisedModelValues: input2.state.advertisedModelValues
|
|
25788
|
+
});
|
|
25789
|
+
}
|
|
25790
|
+
return input2.state;
|
|
25791
|
+
}
|
|
25792
|
+
if (value === input2.state.currentModelId) {
|
|
25793
|
+
return input2.state;
|
|
25794
|
+
}
|
|
25556
25795
|
if (input2.state.strategy === "config-option") {
|
|
25557
25796
|
await connection.request("session/set_config_option", {
|
|
25558
25797
|
sessionId: input2.acpSessionId,
|
|
25559
25798
|
configId: input2.state.modelConfigId,
|
|
25560
|
-
value
|
|
25799
|
+
value
|
|
25561
25800
|
});
|
|
25562
25801
|
} else {
|
|
25563
25802
|
await connection.request("session/set_model", {
|
|
25564
25803
|
sessionId: input2.acpSessionId,
|
|
25565
|
-
modelId:
|
|
25804
|
+
modelId: value
|
|
25566
25805
|
});
|
|
25567
25806
|
}
|
|
25568
25807
|
if (!isLive(input2.expectedGeneration)) {
|
|
25569
25808
|
throw new AcpExecutorDisposedError();
|
|
25570
25809
|
}
|
|
25571
|
-
return { ...input2.state, currentModelId:
|
|
25810
|
+
return { ...input2.state, currentModelId: value };
|
|
25811
|
+
};
|
|
25812
|
+
const applyRequestedEffort = async (input2) => {
|
|
25813
|
+
const requested = input2.requestedEffort?.trim();
|
|
25814
|
+
if (!requested) return;
|
|
25815
|
+
const configOptions = typeof input2.setup === "object" && input2.setup !== null ? input2.setup.configOptions : void 0;
|
|
25816
|
+
const effort = findAcpEffortConfig(configOptions);
|
|
25817
|
+
if (effort === void 0) return;
|
|
25818
|
+
const matched = effort.choices.find((choice) => choice.value === requested);
|
|
25819
|
+
if (matched === void 0) {
|
|
25820
|
+
options.log?.info("requested effort is not in the agent catalog; keeping its own", {
|
|
25821
|
+
requestedEffort: requested,
|
|
25822
|
+
advertised: effort.choices.map((choice) => choice.value)
|
|
25823
|
+
});
|
|
25824
|
+
return;
|
|
25825
|
+
}
|
|
25826
|
+
if (matched.isDefault === true) return;
|
|
25827
|
+
if (!isLive(input2.expectedGeneration)) return;
|
|
25828
|
+
try {
|
|
25829
|
+
await connection.request("session/set_config_option", {
|
|
25830
|
+
sessionId: input2.acpSessionId,
|
|
25831
|
+
configId: effort.configId,
|
|
25832
|
+
value: requested
|
|
25833
|
+
});
|
|
25834
|
+
} catch (error62) {
|
|
25835
|
+
options.log?.info("setting the effort level failed; the session keeps its own", {
|
|
25836
|
+
requestedEffort: requested,
|
|
25837
|
+
configId: effort.configId,
|
|
25838
|
+
error: error62 instanceof Error ? error62.message : String(error62)
|
|
25839
|
+
});
|
|
25840
|
+
}
|
|
25572
25841
|
};
|
|
25573
25842
|
const startOnce = async (expectedGeneration) => {
|
|
25574
|
-
const initializePayload =
|
|
25575
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
25576
|
-
clientCapabilities: {
|
|
25577
|
-
fs: {
|
|
25578
|
-
readTextFile: false,
|
|
25579
|
-
writeTextFile: false,
|
|
25580
|
-
...options.clientCapabilities?.fs
|
|
25581
|
-
},
|
|
25582
|
-
terminal: options.clientCapabilities?.terminal ?? false
|
|
25583
|
-
},
|
|
25584
|
-
clientInfo: options.clientInfo
|
|
25585
|
-
};
|
|
25843
|
+
const initializePayload = acpInitializePayload(options.clientInfo, options.clientCapabilities);
|
|
25586
25844
|
const initialized = await connection.request(
|
|
25587
25845
|
"initialize",
|
|
25588
25846
|
initializePayload
|
|
@@ -25626,12 +25884,27 @@ function createAcpExecutor(options) {
|
|
|
25626
25884
|
nextSessionId = created.sessionId;
|
|
25627
25885
|
setup = created;
|
|
25628
25886
|
}
|
|
25887
|
+
const unhandledCategories = unhandledConfigCategories(
|
|
25888
|
+
setup.configOptions
|
|
25889
|
+
);
|
|
25890
|
+
if (unhandledCategories.length > 0) {
|
|
25891
|
+
options.log?.info("acp session reported config option categories we do not handle", {
|
|
25892
|
+
sessionId: nextSessionId,
|
|
25893
|
+
categories: unhandledCategories
|
|
25894
|
+
});
|
|
25895
|
+
}
|
|
25629
25896
|
const nextModelSelectionState = await applyRequestedModel({
|
|
25630
25897
|
state: modelSelectionStateFromSetup(setup),
|
|
25631
25898
|
acpSessionId: nextSessionId,
|
|
25632
25899
|
requestedModelId: options.requestedModelId,
|
|
25633
25900
|
expectedGeneration
|
|
25634
25901
|
});
|
|
25902
|
+
await applyRequestedEffort({
|
|
25903
|
+
setup,
|
|
25904
|
+
acpSessionId: nextSessionId,
|
|
25905
|
+
requestedEffort: options.requestedEffort,
|
|
25906
|
+
expectedGeneration
|
|
25907
|
+
});
|
|
25635
25908
|
if (options.beforeApplyResult) {
|
|
25636
25909
|
await options.beforeApplyResult();
|
|
25637
25910
|
}
|
|
@@ -25996,6 +26269,26 @@ function createAcpExecutor(options) {
|
|
|
25996
26269
|
};
|
|
25997
26270
|
apply();
|
|
25998
26271
|
};
|
|
26272
|
+
const setNativeMode = async (modeId) => {
|
|
26273
|
+
failIfDisposed();
|
|
26274
|
+
const started = startResult;
|
|
26275
|
+
if (started === void 0) {
|
|
26276
|
+
throw new AcpExecutorRequestError("session/set_mode", "session has not started yet");
|
|
26277
|
+
}
|
|
26278
|
+
const configId = acpModeConfigId(started.sessionSetupResult);
|
|
26279
|
+
if (configId !== void 0) {
|
|
26280
|
+
await connection.request("session/set_config_option", {
|
|
26281
|
+
sessionId: started.sessionId,
|
|
26282
|
+
configId,
|
|
26283
|
+
value: modeId
|
|
26284
|
+
});
|
|
26285
|
+
return;
|
|
26286
|
+
}
|
|
26287
|
+
await connection.request("session/set_mode", {
|
|
26288
|
+
sessionId: started.sessionId,
|
|
26289
|
+
modeId
|
|
26290
|
+
});
|
|
26291
|
+
};
|
|
25999
26292
|
const respondToUserInput = async (requestId, answers) => {
|
|
26000
26293
|
failIfDisposed();
|
|
26001
26294
|
const pending = pendingUserInputs.get(requestId);
|
|
@@ -26012,7 +26305,7 @@ function createAcpExecutor(options) {
|
|
|
26012
26305
|
pendingUserInputs.delete(requestId);
|
|
26013
26306
|
pending.resolve({
|
|
26014
26307
|
kind: "answered",
|
|
26015
|
-
answers:
|
|
26308
|
+
answers: isRecord5(answers) ? answers : {}
|
|
26016
26309
|
});
|
|
26017
26310
|
};
|
|
26018
26311
|
const dispose = async () => {
|
|
@@ -26062,12 +26355,84 @@ function createAcpExecutor(options) {
|
|
|
26062
26355
|
cancel,
|
|
26063
26356
|
respondToRequest,
|
|
26064
26357
|
respondToUserInput,
|
|
26358
|
+
setNativeMode,
|
|
26065
26359
|
dispose
|
|
26066
26360
|
};
|
|
26067
26361
|
}
|
|
26068
26362
|
|
|
26363
|
+
// ../../packages/ycodium-acp-executor/src/probe.ts
|
|
26364
|
+
function withProbeTimeout(promise2, timeoutMs, what) {
|
|
26365
|
+
return new Promise((resolve2, reject) => {
|
|
26366
|
+
const timer = setTimeout(() => {
|
|
26367
|
+
reject(new Error(`${what} timed out after ${timeoutMs}ms`));
|
|
26368
|
+
}, timeoutMs);
|
|
26369
|
+
timer.unref?.();
|
|
26370
|
+
promise2.then(
|
|
26371
|
+
(value) => {
|
|
26372
|
+
clearTimeout(timer);
|
|
26373
|
+
resolve2(value);
|
|
26374
|
+
},
|
|
26375
|
+
(error62) => {
|
|
26376
|
+
clearTimeout(timer);
|
|
26377
|
+
reject(error62 instanceof Error ? error62 : new Error(String(error62)));
|
|
26378
|
+
}
|
|
26379
|
+
);
|
|
26380
|
+
});
|
|
26381
|
+
}
|
|
26382
|
+
var CLI_VERSION_PATTERN = /(?<![\d.])(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)/;
|
|
26383
|
+
function parseCliVersion(output2) {
|
|
26384
|
+
return CLI_VERSION_PATTERN.exec(output2)?.[1] ?? null;
|
|
26385
|
+
}
|
|
26386
|
+
async function collectCappedText(stream, maxBytes) {
|
|
26387
|
+
const decoder = new TextDecoder();
|
|
26388
|
+
let text = "";
|
|
26389
|
+
let total = 0;
|
|
26390
|
+
for await (const chunk of stream) {
|
|
26391
|
+
total += chunk.byteLength;
|
|
26392
|
+
if (total <= maxBytes) text += decoder.decode(chunk, { stream: true });
|
|
26393
|
+
}
|
|
26394
|
+
return { text: text + decoder.decode(), overflowed: total > maxBytes };
|
|
26395
|
+
}
|
|
26396
|
+
async function collectProbeProcess(child, input2) {
|
|
26397
|
+
try {
|
|
26398
|
+
await child.closeStdin().catch(() => void 0);
|
|
26399
|
+
const [stdout, stderr, exitCode] = await withProbeTimeout(
|
|
26400
|
+
Promise.all([
|
|
26401
|
+
collectCappedText(child.stdout, input2.maxOutputBytes),
|
|
26402
|
+
collectCappedText(child.stderr, input2.maxOutputBytes),
|
|
26403
|
+
child.exited
|
|
26404
|
+
]),
|
|
26405
|
+
input2.timeoutMs,
|
|
26406
|
+
input2.what
|
|
26407
|
+
);
|
|
26408
|
+
return { stdout: stdout.overflowed ? void 0 : stdout.text, stderr: stderr.text, exitCode };
|
|
26409
|
+
} finally {
|
|
26410
|
+
await child.kill("SIGTERM").catch(() => void 0);
|
|
26411
|
+
}
|
|
26412
|
+
}
|
|
26413
|
+
var MAX_VERSION_OUTPUT_BYTES = 64 * 1024;
|
|
26414
|
+
async function probeCliVersion(input2) {
|
|
26415
|
+
let child;
|
|
26416
|
+
try {
|
|
26417
|
+
child = await input2.spawn();
|
|
26418
|
+
} catch {
|
|
26419
|
+
return null;
|
|
26420
|
+
}
|
|
26421
|
+
try {
|
|
26422
|
+
const run = await collectProbeProcess(child, {
|
|
26423
|
+
timeoutMs: input2.timeoutMs,
|
|
26424
|
+
maxOutputBytes: MAX_VERSION_OUTPUT_BYTES,
|
|
26425
|
+
what: "--version"
|
|
26426
|
+
});
|
|
26427
|
+
if (run.exitCode !== 0) return null;
|
|
26428
|
+
return parseCliVersion(run.stdout ?? "") ?? parseCliVersion(run.stderr);
|
|
26429
|
+
} catch {
|
|
26430
|
+
return null;
|
|
26431
|
+
}
|
|
26432
|
+
}
|
|
26433
|
+
|
|
26069
26434
|
// src/config.ts
|
|
26070
|
-
function
|
|
26435
|
+
function isRecord6(value) {
|
|
26071
26436
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26072
26437
|
}
|
|
26073
26438
|
function readString(value) {
|
|
@@ -26080,7 +26445,7 @@ function readEnvironment(value) {
|
|
|
26080
26445
|
if (!Array.isArray(value)) return {};
|
|
26081
26446
|
const env = {};
|
|
26082
26447
|
for (const entry of value) {
|
|
26083
|
-
if (!
|
|
26448
|
+
if (!isRecord6(entry)) continue;
|
|
26084
26449
|
const name = readTrimmed(entry["name"]);
|
|
26085
26450
|
if (name.length === 0) continue;
|
|
26086
26451
|
env[name] = readString(entry["value"]);
|
|
@@ -26088,23 +26453,23 @@ function readEnvironment(value) {
|
|
|
26088
26453
|
return env;
|
|
26089
26454
|
}
|
|
26090
26455
|
function parseKimiInstanceConfig(config2) {
|
|
26091
|
-
if (!
|
|
26456
|
+
if (!isRecord6(config2)) {
|
|
26092
26457
|
return {
|
|
26093
26458
|
binaryPath: "",
|
|
26094
|
-
launchArgs:
|
|
26459
|
+
launchArgs: KIMI_CARD.launchArgs,
|
|
26095
26460
|
homePath: "",
|
|
26096
|
-
homeEnvVar:
|
|
26461
|
+
homeEnvVar: KIMI_CARD.homeEnvVar,
|
|
26097
26462
|
environment: {},
|
|
26098
26463
|
envelopeDriver: void 0
|
|
26099
26464
|
};
|
|
26100
26465
|
}
|
|
26101
|
-
const nested =
|
|
26466
|
+
const nested = isRecord6(config2["config"]) ? config2["config"] : void 0;
|
|
26102
26467
|
const settings = nested ?? config2;
|
|
26103
26468
|
return {
|
|
26104
26469
|
binaryPath: readTrimmed(settings["binaryPath"]),
|
|
26105
|
-
launchArgs: readString(settings["launchArgs"]),
|
|
26470
|
+
launchArgs: readString(settings["launchArgs"]) || KIMI_CARD.launchArgs,
|
|
26106
26471
|
homePath: readTrimmed(settings["homePath"]) || readTrimmed(config2["homePath"]),
|
|
26107
|
-
homeEnvVar:
|
|
26472
|
+
homeEnvVar: KIMI_CARD.homeEnvVar,
|
|
26108
26473
|
environment: readEnvironment(config2["environment"]),
|
|
26109
26474
|
envelopeDriver: readTrimmed(config2["driver"]) || void 0
|
|
26110
26475
|
};
|
|
@@ -26161,13 +26526,51 @@ function tokenizeLaunchArgs(value) {
|
|
|
26161
26526
|
return tokens;
|
|
26162
26527
|
}
|
|
26163
26528
|
|
|
26164
|
-
// src/
|
|
26165
|
-
import * as
|
|
26529
|
+
// src/kimi.ts
|
|
26530
|
+
import * as NodeFS from "node:fs";
|
|
26166
26531
|
import * as NodePath from "node:path";
|
|
26532
|
+
var KIMI_USER_INPUT_TITLES = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
|
|
26533
|
+
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26534
|
+
function questionTextFromContent(content) {
|
|
26535
|
+
if (!Array.isArray(content)) return "";
|
|
26536
|
+
const parts = [];
|
|
26537
|
+
for (const entry of content) {
|
|
26538
|
+
if (!isRecord7(entry) || entry["type"] !== "content") continue;
|
|
26539
|
+
const inner = entry["content"];
|
|
26540
|
+
if (!isRecord7(inner) || inner["type"] !== "text") continue;
|
|
26541
|
+
const text = inner["text"];
|
|
26542
|
+
if (typeof text === "string") parts.push(text);
|
|
26543
|
+
}
|
|
26544
|
+
return parts.join("\n\n").trim();
|
|
26545
|
+
}
|
|
26546
|
+
function kimiPermissionUserInput(request) {
|
|
26547
|
+
const title = request.toolCall.title;
|
|
26548
|
+
if (typeof title !== "string" || !KIMI_USER_INPUT_TITLES.has(title)) return void 0;
|
|
26549
|
+
const ids = new Set(request.options.map((option) => option.optionId));
|
|
26550
|
+
if (request.options.length === 0 || ids.size !== request.options.length) {
|
|
26551
|
+
throw new Error("Kimi interaction must provide distinct response options.");
|
|
26552
|
+
}
|
|
26553
|
+
const question = questionTextFromContent(request.toolCall.content);
|
|
26554
|
+
if (question.length === 0) {
|
|
26555
|
+
throw new Error("Kimi interaction is missing a question or plan.");
|
|
26556
|
+
}
|
|
26557
|
+
return {
|
|
26558
|
+
id: request.toolCall.toolCallId,
|
|
26559
|
+
header: title,
|
|
26560
|
+
question,
|
|
26561
|
+
kind: title === "ExitPlanMode" ? "plan" : "question",
|
|
26562
|
+
allowFreeform: false,
|
|
26563
|
+
multiSelect: false,
|
|
26564
|
+
options: request.options.map((option) => ({
|
|
26565
|
+
id: option.optionId,
|
|
26566
|
+
label: option.name,
|
|
26567
|
+
description: ""
|
|
26568
|
+
}))
|
|
26569
|
+
};
|
|
26570
|
+
}
|
|
26167
26571
|
var WIRE_LOG_SEGMENTS = ["agents", "main", "wire.jsonl"];
|
|
26168
26572
|
var SESSIONS_DIR = "sessions";
|
|
26169
26573
|
var TAIL_SCAN_BYTES = 256 * 1024;
|
|
26170
|
-
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26171
26574
|
var positiveInt = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : void 0;
|
|
26172
26575
|
function parseKimiContextWindow(contents) {
|
|
26173
26576
|
let usedTokens;
|
|
@@ -26181,7 +26584,7 @@ function parseKimiContextWindow(contents) {
|
|
|
26181
26584
|
} catch {
|
|
26182
26585
|
continue;
|
|
26183
26586
|
}
|
|
26184
|
-
if (!
|
|
26587
|
+
if (!isRecord7(record2)) continue;
|
|
26185
26588
|
const type = record2["type"];
|
|
26186
26589
|
if (type === "token_counting.turn_recorded" || type === "token_counting.measured") {
|
|
26187
26590
|
usedTokens = positiveInt(record2["tokens"]) ?? usedTokens;
|
|
@@ -26191,31 +26594,35 @@ function parseKimiContextWindow(contents) {
|
|
|
26191
26594
|
maxTokens = positiveInt(record2["maxTokens"]) ?? maxTokens;
|
|
26192
26595
|
}
|
|
26193
26596
|
}
|
|
26194
|
-
|
|
26597
|
+
if (usedTokens === void 0) return void 0;
|
|
26598
|
+
return maxTokens === void 0 ? { usedTokens } : { usedTokens, maxTokens };
|
|
26195
26599
|
}
|
|
26196
|
-
|
|
26600
|
+
function readTail(filePath) {
|
|
26197
26601
|
let handle;
|
|
26198
26602
|
try {
|
|
26199
|
-
|
|
26200
|
-
const info = await handle.stat();
|
|
26201
|
-
const size = info.size;
|
|
26603
|
+
const size = NodeFS.statSync(filePath).size;
|
|
26202
26604
|
if (!Number.isFinite(size) || size <= 0) return void 0;
|
|
26203
|
-
const
|
|
26204
|
-
const length = size - offset;
|
|
26605
|
+
const length = size > TAIL_SCAN_BYTES ? TAIL_SCAN_BYTES : size;
|
|
26205
26606
|
const buffer = Buffer.alloc(length);
|
|
26206
|
-
|
|
26607
|
+
handle = NodeFS.openSync(filePath, "r");
|
|
26608
|
+
NodeFS.readSync(handle, buffer, 0, length, size - length);
|
|
26207
26609
|
return buffer.toString("utf8");
|
|
26208
26610
|
} catch {
|
|
26209
26611
|
return void 0;
|
|
26210
26612
|
} finally {
|
|
26211
|
-
|
|
26613
|
+
if (handle !== void 0) {
|
|
26614
|
+
try {
|
|
26615
|
+
NodeFS.closeSync(handle);
|
|
26616
|
+
} catch {
|
|
26617
|
+
}
|
|
26618
|
+
}
|
|
26212
26619
|
}
|
|
26213
26620
|
}
|
|
26214
|
-
|
|
26621
|
+
function findKimiSessionWireLog(input2) {
|
|
26215
26622
|
const sessionsRoot = NodePath.join(input2.homePath, SESSIONS_DIR);
|
|
26216
26623
|
let workspaces;
|
|
26217
26624
|
try {
|
|
26218
|
-
workspaces =
|
|
26625
|
+
workspaces = NodeFS.readdirSync(sessionsRoot);
|
|
26219
26626
|
} catch {
|
|
26220
26627
|
return void 0;
|
|
26221
26628
|
}
|
|
@@ -26226,126 +26633,175 @@ async function findKimiSessionWireLog(input2) {
|
|
|
26226
26633
|
input2.acpSessionId,
|
|
26227
26634
|
...WIRE_LOG_SEGMENTS
|
|
26228
26635
|
);
|
|
26229
|
-
|
|
26230
|
-
await NodeFSP.access(candidate);
|
|
26231
|
-
return candidate;
|
|
26232
|
-
} catch {
|
|
26233
|
-
}
|
|
26636
|
+
if (NodeFS.existsSync(candidate)) return candidate;
|
|
26234
26637
|
}
|
|
26235
26638
|
return void 0;
|
|
26236
26639
|
}
|
|
26237
|
-
|
|
26640
|
+
function readKimiContextWindow(input2) {
|
|
26238
26641
|
if (input2.homePath.trim().length === 0) return void 0;
|
|
26239
|
-
const wireLog =
|
|
26642
|
+
const wireLog = findKimiSessionWireLog(input2);
|
|
26240
26643
|
if (wireLog === void 0) return void 0;
|
|
26241
|
-
const contents =
|
|
26644
|
+
const contents = readTail(wireLog);
|
|
26242
26645
|
return contents === void 0 ? void 0 : parseKimiContextWindow(contents);
|
|
26243
26646
|
}
|
|
26244
26647
|
|
|
26245
|
-
// src/
|
|
26246
|
-
|
|
26247
|
-
|
|
26248
|
-
|
|
26249
|
-
|
|
26250
|
-
|
|
26251
|
-
|
|
26252
|
-
|
|
26253
|
-
|
|
26254
|
-
|
|
26255
|
-
|
|
26256
|
-
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
if (entry["type"] !== "content") continue;
|
|
26261
|
-
const inner = entry["content"];
|
|
26262
|
-
if (!isRecord6(inner)) continue;
|
|
26263
|
-
if (inner["type"] !== "text") continue;
|
|
26264
|
-
const text = inner["text"];
|
|
26265
|
-
if (typeof text === "string") texts.push(text);
|
|
26648
|
+
// src/kimiAccount.ts
|
|
26649
|
+
import * as NodeFS2 from "node:fs";
|
|
26650
|
+
import * as NodeOS from "node:os";
|
|
26651
|
+
import * as NodePath2 from "node:path";
|
|
26652
|
+
function kimiCredentialsPath(resolvedHomePath) {
|
|
26653
|
+
const home = resolvedHomePath.trim().length > 0 ? resolvedHomePath : NodePath2.join(NodeOS.homedir(), ".kimi-code");
|
|
26654
|
+
return NodePath2.join(home, "credentials", "kimi-code.json");
|
|
26655
|
+
}
|
|
26656
|
+
var nonEmptyString = (value) => typeof value === "string" && value.length > 0;
|
|
26657
|
+
function readKimiAuthState(resolvedHomePath) {
|
|
26658
|
+
let raw;
|
|
26659
|
+
try {
|
|
26660
|
+
raw = NodeFS2.readFileSync(kimiCredentialsPath(resolvedHomePath), "utf8");
|
|
26661
|
+
} catch (error62) {
|
|
26662
|
+
return error62.code === "ENOENT" ? "signed-out" : "unreadable";
|
|
26266
26663
|
}
|
|
26267
|
-
|
|
26268
|
-
|
|
26269
|
-
|
|
26270
|
-
|
|
26271
|
-
|
|
26272
|
-
const title = request.toolCall.title;
|
|
26273
|
-
if (title !== KIMI_QUESTION_TITLE && title !== KIMI_PLAN_TITLE) return void 0;
|
|
26274
|
-
const question = questionText(request.toolCall.content);
|
|
26275
|
-
const optionIds = new Set(request.options.map((option) => option.optionId));
|
|
26276
|
-
if (request.options.length === 0 || optionIds.size !== request.options.length) {
|
|
26277
|
-
throw new Error("Kimi interaction must provide distinct response options.");
|
|
26664
|
+
let parsed;
|
|
26665
|
+
try {
|
|
26666
|
+
parsed = JSON.parse(raw);
|
|
26667
|
+
} catch {
|
|
26668
|
+
return "unreadable";
|
|
26278
26669
|
}
|
|
26279
|
-
|
|
26280
|
-
const
|
|
26281
|
-
|
|
26282
|
-
|
|
26283
|
-
|
|
26284
|
-
|
|
26285
|
-
|
|
26286
|
-
|
|
26287
|
-
|
|
26670
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return "unreadable";
|
|
26671
|
+
const record2 = parsed;
|
|
26672
|
+
return nonEmptyString(record2["refresh_token"]) || nonEmptyString(record2["access_token"]) ? "signed-in" : "signed-out";
|
|
26673
|
+
}
|
|
26674
|
+
|
|
26675
|
+
// src/kimiModels.ts
|
|
26676
|
+
import {
|
|
26677
|
+
ExecutorSpawnRefusedError
|
|
26678
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
26679
|
+
|
|
26680
|
+
// src/probeModels.ts
|
|
26681
|
+
var ACP_EFFORT_OPTION_ID = "reasoning";
|
|
26682
|
+
var probeFailureDetail = (error62) => (error62 instanceof Error ? error62.message : String(error62)).trim() || void 0;
|
|
26683
|
+
|
|
26684
|
+
// src/kimiModels.ts
|
|
26685
|
+
var PROBE_TIMEOUT_MS = 15e3;
|
|
26686
|
+
var MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
26687
|
+
var KIMI_MODEL_LIST_ARGS = ["provider", "list", "--json"];
|
|
26688
|
+
function isRecord8(value) {
|
|
26689
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26690
|
+
}
|
|
26691
|
+
function asString3(value) {
|
|
26692
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
26693
|
+
}
|
|
26694
|
+
function positiveInt2(value) {
|
|
26695
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : void 0;
|
|
26696
|
+
}
|
|
26697
|
+
function kimiProbeModels(stdout) {
|
|
26698
|
+
let parsed;
|
|
26699
|
+
try {
|
|
26700
|
+
parsed = JSON.parse(stdout);
|
|
26701
|
+
} catch {
|
|
26702
|
+
return void 0;
|
|
26288
26703
|
}
|
|
26289
|
-
if (
|
|
26290
|
-
|
|
26704
|
+
if (!isRecord8(parsed)) return void 0;
|
|
26705
|
+
const models = parsed["models"];
|
|
26706
|
+
if (!isRecord8(models)) return void 0;
|
|
26707
|
+
const out = [];
|
|
26708
|
+
for (const [slug, entry] of Object.entries(models)) {
|
|
26709
|
+
const trimmed = slug.trim();
|
|
26710
|
+
if (trimmed.length === 0 || !isRecord8(entry)) continue;
|
|
26711
|
+
const name = asString3(entry["displayName"]);
|
|
26712
|
+
const contextWindow = positiveInt2(entry["maxContextSize"]);
|
|
26713
|
+
out.push({
|
|
26714
|
+
slug: trimmed,
|
|
26715
|
+
...name === void 0 ? {} : { name },
|
|
26716
|
+
...contextWindow === void 0 ? {} : { contextWindow }
|
|
26717
|
+
});
|
|
26291
26718
|
}
|
|
26292
|
-
return
|
|
26293
|
-
|
|
26294
|
-
|
|
26295
|
-
|
|
26296
|
-
|
|
26297
|
-
|
|
26298
|
-
|
|
26299
|
-
|
|
26300
|
-
|
|
26301
|
-
|
|
26302
|
-
|
|
26303
|
-
|
|
26304
|
-
|
|
26305
|
-
|
|
26306
|
-
|
|
26307
|
-
|
|
26308
|
-
|
|
26309
|
-
|
|
26310
|
-
|
|
26311
|
-
|
|
26312
|
-
|
|
26313
|
-
|
|
26314
|
-
|
|
26315
|
-
|
|
26316
|
-
|
|
26317
|
-
|
|
26318
|
-
|
|
26319
|
-
|
|
26320
|
-
|
|
26321
|
-
|
|
26322
|
-
|
|
26323
|
-
|
|
26324
|
-
readable.destroy(error62 instanceof Error ? error62 : new Error(String(error62)));
|
|
26325
|
-
return;
|
|
26326
|
-
}
|
|
26327
|
-
if (readable.writable) readable.end();
|
|
26328
|
-
})();
|
|
26329
|
-
void (async () => {
|
|
26330
|
-
for await (const _chunk of handle.stderr) {
|
|
26331
|
-
}
|
|
26332
|
-
})().catch(() => void 0);
|
|
26333
|
-
const writable = new NodeStream2.Writable({
|
|
26334
|
-
write(chunk, _encoding, callback) {
|
|
26335
|
-
const bytes = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
26336
|
-
handle.writeStdin(bytes).then(
|
|
26337
|
-
() => callback(),
|
|
26338
|
-
(error62) => callback(error62 instanceof Error ? error62 : new Error(String(error62)))
|
|
26339
|
-
);
|
|
26340
|
-
},
|
|
26341
|
-
final(callback) {
|
|
26342
|
-
handle.closeStdin().then(
|
|
26343
|
-
() => callback(),
|
|
26344
|
-
(error62) => callback(error62 instanceof Error ? error62 : new Error(String(error62)))
|
|
26345
|
-
);
|
|
26719
|
+
return out;
|
|
26720
|
+
}
|
|
26721
|
+
async function probeKimiModels(input2) {
|
|
26722
|
+
const { recipe, host, env } = input2;
|
|
26723
|
+
let handle;
|
|
26724
|
+
try {
|
|
26725
|
+
handle = await host.process.spawn({
|
|
26726
|
+
program: recipe.binaryPath,
|
|
26727
|
+
// 实例信封里的启动参数(Kimi 那行预填 `acp`)在这一栏用不上:读配置要换成
|
|
26728
|
+
// `provider list --json`,留着 `acp` 就等于让它起 ACP 服务然后什么都不问。
|
|
26729
|
+
args: KIMI_MODEL_LIST_ARGS,
|
|
26730
|
+
cwd: process.cwd(),
|
|
26731
|
+
owner: { bindingId: host.bindingId },
|
|
26732
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
26733
|
+
});
|
|
26734
|
+
} catch (error62) {
|
|
26735
|
+
if (error62 instanceof ExecutorSpawnRefusedError) throw error62;
|
|
26736
|
+
return { kind: "not-started", detail: probeFailureDetail(error62) };
|
|
26737
|
+
}
|
|
26738
|
+
try {
|
|
26739
|
+
const run = await collectProbeProcess(handle, {
|
|
26740
|
+
timeoutMs: input2.timeoutMs ?? PROBE_TIMEOUT_MS,
|
|
26741
|
+
// 这份 JSON 实测 1.7KB;封顶是防 CLI 抽风刷日志把内存吃掉。
|
|
26742
|
+
maxOutputBytes: MAX_OUTPUT_BYTES,
|
|
26743
|
+
what: "kimi provider list"
|
|
26744
|
+
});
|
|
26745
|
+
if (run.exitCode !== 0) {
|
|
26746
|
+
const stderr = run.stderr.trim();
|
|
26747
|
+
return {
|
|
26748
|
+
kind: "failed",
|
|
26749
|
+
detail: stderr.length > 0 ? stderr : run.exitCode === null ? "kimi provider list was killed by a signal" : `kimi provider list exited with code ${run.exitCode}`
|
|
26750
|
+
};
|
|
26346
26751
|
}
|
|
26752
|
+
return {
|
|
26753
|
+
kind: "answered",
|
|
26754
|
+
models: run.stdout === void 0 ? void 0 : kimiProbeModels(run.stdout)
|
|
26755
|
+
};
|
|
26756
|
+
} catch (error62) {
|
|
26757
|
+
return { kind: "failed", detail: probeFailureDetail(error62) };
|
|
26758
|
+
}
|
|
26759
|
+
}
|
|
26760
|
+
async function probeKimiVersion(input2) {
|
|
26761
|
+
const { recipe, host, env } = input2;
|
|
26762
|
+
return probeCliVersion({
|
|
26763
|
+
spawn: () => host.process.spawn({
|
|
26764
|
+
program: recipe.binaryPath,
|
|
26765
|
+
args: ["--version"],
|
|
26766
|
+
cwd: process.cwd(),
|
|
26767
|
+
owner: { bindingId: host.bindingId },
|
|
26768
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
26769
|
+
}),
|
|
26770
|
+
timeoutMs: PROBE_TIMEOUT_MS
|
|
26347
26771
|
});
|
|
26348
|
-
|
|
26772
|
+
}
|
|
26773
|
+
async function probeKimi(input2) {
|
|
26774
|
+
const [listed, version2] = await Promise.all([probeKimiModels(input2), probeKimiVersion(input2)]);
|
|
26775
|
+
switch (listed.kind) {
|
|
26776
|
+
case "not-started":
|
|
26777
|
+
return { kind: "not-started", detail: listed.detail };
|
|
26778
|
+
case "failed":
|
|
26779
|
+
return { kind: "failed", detail: listed.detail, version: version2 };
|
|
26780
|
+
case "answered":
|
|
26781
|
+
return {
|
|
26782
|
+
kind: "answered",
|
|
26783
|
+
version: version2,
|
|
26784
|
+
models: listed.models,
|
|
26785
|
+
nativeModes: [],
|
|
26786
|
+
currentNativeModeId: void 0
|
|
26787
|
+
};
|
|
26788
|
+
}
|
|
26789
|
+
}
|
|
26790
|
+
|
|
26791
|
+
// src/runtimeModeApproval.ts
|
|
26792
|
+
function acpRuntimeModeAutoApproves(runtimeMode, toolKind) {
|
|
26793
|
+
switch (runtimeMode) {
|
|
26794
|
+
case "full-access":
|
|
26795
|
+
return true;
|
|
26796
|
+
case "auto-accept-edits":
|
|
26797
|
+
return toolKind === "edit";
|
|
26798
|
+
case "approval-required":
|
|
26799
|
+
case "auto":
|
|
26800
|
+
return false;
|
|
26801
|
+
}
|
|
26802
|
+
}
|
|
26803
|
+
function acpSessionModeToApply(requestedNativeModeId, startedModeId) {
|
|
26804
|
+
return requestedNativeModeId !== void 0 && requestedNativeModeId !== startedModeId ? requestedNativeModeId : void 0;
|
|
26349
26805
|
}
|
|
26350
26806
|
|
|
26351
26807
|
// src/kimiInstance.ts
|
|
@@ -26387,24 +26843,12 @@ var EventBus = class {
|
|
|
26387
26843
|
}
|
|
26388
26844
|
};
|
|
26389
26845
|
function expandHomePath(value) {
|
|
26390
|
-
if (value === "~") return
|
|
26846
|
+
if (value === "~") return NodeOS2.homedir();
|
|
26391
26847
|
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
26392
|
-
return
|
|
26848
|
+
return NodePath3.join(NodeOS2.homedir(), value.slice(2));
|
|
26393
26849
|
}
|
|
26394
26850
|
return value;
|
|
26395
26851
|
}
|
|
26396
|
-
function resolveHomePath(value) {
|
|
26397
|
-
const trimmed = value.trim();
|
|
26398
|
-
if (trimmed.length === 0) return "";
|
|
26399
|
-
return NodePath2.resolve(expandHomePath(trimmed));
|
|
26400
|
-
}
|
|
26401
|
-
function compactEnv(env) {
|
|
26402
|
-
const out = {};
|
|
26403
|
-
for (const [key, value] of Object.entries(env)) {
|
|
26404
|
-
if (value !== void 0) out[key] = value;
|
|
26405
|
-
}
|
|
26406
|
-
return out;
|
|
26407
|
-
}
|
|
26408
26852
|
function modelIdFromSelection(selection) {
|
|
26409
26853
|
if (typeof selection !== "object" || selection === null || Array.isArray(selection)) {
|
|
26410
26854
|
return void 0;
|
|
@@ -26412,18 +26856,39 @@ function modelIdFromSelection(selection) {
|
|
|
26412
26856
|
const model = selection["model"];
|
|
26413
26857
|
return typeof model === "string" ? model.trim() || void 0 : void 0;
|
|
26414
26858
|
}
|
|
26415
|
-
function buildSpawnEnv(recipe,
|
|
26859
|
+
function buildSpawnEnv(recipe, configuredHomePath) {
|
|
26860
|
+
const homePath = configuredHomePath.trim();
|
|
26416
26861
|
const homeEnvVar = recipe.homeEnvVar.trim();
|
|
26417
|
-
const homeInjection =
|
|
26418
|
-
return {
|
|
26419
|
-
|
|
26420
|
-
|
|
26421
|
-
|
|
26422
|
-
};
|
|
26862
|
+
const homeInjection = homePath.length > 0 && homeEnvVar.length > 0 ? { [homeEnvVar]: expandHomePath(homePath) } : {};
|
|
26863
|
+
return mergeLaunchEnv({
|
|
26864
|
+
accountHome: homeInjection,
|
|
26865
|
+
instanceTable: recipe.environment
|
|
26866
|
+
});
|
|
26423
26867
|
}
|
|
26424
26868
|
function nowIso() {
|
|
26425
26869
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
26426
26870
|
}
|
|
26871
|
+
function kimiContinuationKey(recipe) {
|
|
26872
|
+
const homePath = recipe.homePath.trim();
|
|
26873
|
+
const resolvedHomePath = homePath.length > 0 ? NodePath3.resolve(expandHomePath(homePath)) : "";
|
|
26874
|
+
return `kimiCode:home:${recipe.binaryPath.trim()}\0${resolvedHomePath}`;
|
|
26875
|
+
}
|
|
26876
|
+
function resolveHomePath(recipe) {
|
|
26877
|
+
const envVar = recipe.homeEnvVar.trim();
|
|
26878
|
+
const fromEnvironment = envVar.length > 0 ? recipe.environment[envVar]?.trim() : void 0;
|
|
26879
|
+
if (fromEnvironment !== void 0 && fromEnvironment.length > 0) {
|
|
26880
|
+
return expandHomePath(fromEnvironment);
|
|
26881
|
+
}
|
|
26882
|
+
const configured = recipe.homePath.trim();
|
|
26883
|
+
return configured.length > 0 ? expandHomePath(configured) : "";
|
|
26884
|
+
}
|
|
26885
|
+
function kimiHooks(recipe) {
|
|
26886
|
+
const homePath = resolveHomePath(recipe);
|
|
26887
|
+
return {
|
|
26888
|
+
permissionUserInput: kimiPermissionUserInput,
|
|
26889
|
+
readContextWindow: ({ sessionId }) => readKimiContextWindow({ homePath, acpSessionId: sessionId })
|
|
26890
|
+
};
|
|
26891
|
+
}
|
|
26427
26892
|
async function stopBooked(booked) {
|
|
26428
26893
|
await booked.executor.dispose().catch(() => void 0);
|
|
26429
26894
|
await booked.handle.kill("SIGTERM").catch(() => void 0);
|
|
@@ -26447,21 +26912,67 @@ var createKimiInstance = (config2, host) => {
|
|
|
26447
26912
|
version: null,
|
|
26448
26913
|
readiness: "error",
|
|
26449
26914
|
auth: { status: "unknown" },
|
|
26450
|
-
detail: "Kimi program path is not configured"
|
|
26915
|
+
detail: "Kimi Code program path is not configured"
|
|
26451
26916
|
};
|
|
26452
26917
|
}
|
|
26453
|
-
|
|
26454
|
-
|
|
26455
|
-
|
|
26456
|
-
|
|
26457
|
-
|
|
26918
|
+
const env = buildSpawnEnv(recipe, recipe.homePath);
|
|
26919
|
+
const outcome = await probeKimi({ recipe, host, env });
|
|
26920
|
+
const auth = () => {
|
|
26921
|
+
switch (readKimiAuthState(resolveHomePath(recipe))) {
|
|
26922
|
+
case "signed-in":
|
|
26923
|
+
return { status: "authenticated" };
|
|
26924
|
+
case "signed-out":
|
|
26925
|
+
return { status: "unauthenticated" };
|
|
26926
|
+
case "unreadable":
|
|
26927
|
+
return { status: "unknown" };
|
|
26928
|
+
}
|
|
26458
26929
|
};
|
|
26930
|
+
switch (outcome.kind) {
|
|
26931
|
+
case "not-started":
|
|
26932
|
+
return {
|
|
26933
|
+
installed: false,
|
|
26934
|
+
version: null,
|
|
26935
|
+
readiness: "error",
|
|
26936
|
+
auth: { status: "unknown" },
|
|
26937
|
+
...outcome.detail === void 0 ? {} : { detail: outcome.detail }
|
|
26938
|
+
};
|
|
26939
|
+
case "failed":
|
|
26940
|
+
return {
|
|
26941
|
+
installed: true,
|
|
26942
|
+
version: outcome.version,
|
|
26943
|
+
readiness: "error",
|
|
26944
|
+
auth: auth(),
|
|
26945
|
+
...outcome.detail === void 0 ? {} : { detail: outcome.detail }
|
|
26946
|
+
};
|
|
26947
|
+
case "auth-required":
|
|
26948
|
+
return {
|
|
26949
|
+
installed: true,
|
|
26950
|
+
version: outcome.version,
|
|
26951
|
+
readiness: "ready",
|
|
26952
|
+
auth: { status: "unauthenticated" }
|
|
26953
|
+
};
|
|
26954
|
+
case "answered":
|
|
26955
|
+
return {
|
|
26956
|
+
installed: true,
|
|
26957
|
+
version: outcome.version,
|
|
26958
|
+
readiness: "ready",
|
|
26959
|
+
auth: auth(),
|
|
26960
|
+
...outcome.models === void 0 ? {} : { models: outcome.models },
|
|
26961
|
+
// 清单与当前档必须同进同出:只报清单,界面在清单里找不到当前档会整个不画那一格。
|
|
26962
|
+
...outcome.nativeModes.length === 0 ? {} : {
|
|
26963
|
+
nativeModes: outcome.nativeModes,
|
|
26964
|
+
...outcome.currentNativeModeId === void 0 ? {} : { currentNativeModeId: outcome.currentNativeModeId }
|
|
26965
|
+
}
|
|
26966
|
+
};
|
|
26967
|
+
}
|
|
26459
26968
|
},
|
|
26969
|
+
// 暂不处理 input.readOnlyDirectories(有意为之):kimi 经共享的 ycodium-acp-executor 起会话,
|
|
26970
|
+
// 还没用真机确认这家 CLI 对 cwd 之外的读怎么处理、要不要放行。确认之后再接这一栏。
|
|
26460
26971
|
startSession: async (input2, signal) => {
|
|
26461
26972
|
if (disposed) throw new Error("instance disposed");
|
|
26462
26973
|
if (signal?.aborted) throw new Error("aborted");
|
|
26463
26974
|
if (recipe.binaryPath.length === 0) {
|
|
26464
|
-
throw new Error("Kimi program path is not configured");
|
|
26975
|
+
throw new Error("Kimi Code program path is not configured");
|
|
26465
26976
|
}
|
|
26466
26977
|
const cwd = input2.cwd ?? host.workspacePath(input2.threadId);
|
|
26467
26978
|
if (cwd.trim() === "") throw new Error("workspace path missing");
|
|
@@ -26470,8 +26981,7 @@ var createKimiInstance = (config2, host) => {
|
|
|
26470
26981
|
await stopBooked(existing);
|
|
26471
26982
|
threads.delete(input2.threadId);
|
|
26472
26983
|
}
|
|
26473
|
-
const
|
|
26474
|
-
const env = buildSpawnEnv(recipe, input2.launch, resolvedHomePath);
|
|
26984
|
+
const env = buildSpawnEnv(recipe, recipe.homePath);
|
|
26475
26985
|
const handle = await host.process.spawn({
|
|
26476
26986
|
program: recipe.binaryPath,
|
|
26477
26987
|
args: tokenizeLaunchArgs(recipe.launchArgs),
|
|
@@ -26481,31 +26991,30 @@ var createKimiInstance = (config2, host) => {
|
|
|
26481
26991
|
});
|
|
26482
26992
|
const { readable, writable } = nodeStreamsFromHandle(handle);
|
|
26483
26993
|
const resume = input2.discardResumeCursor === true ? void 0 : parseAcpResumeCursor(input2.resumeCursor, RESUME_SCHEMA_VERSION);
|
|
26484
|
-
const requestedModelId =
|
|
26994
|
+
const requestedModelId = modelIdFromSelection(input2.modelSelection);
|
|
26995
|
+
const requestedEffort = modelSelectionStringOption(
|
|
26996
|
+
input2.modelSelection,
|
|
26997
|
+
ACP_EFFORT_OPTION_ID
|
|
26998
|
+
);
|
|
26999
|
+
const hooks = kimiHooks(recipe);
|
|
27000
|
+
const autoApprove = input2.nativeModeId === void 0 ? (request) => acpRuntimeModeAutoApproves(
|
|
27001
|
+
threads.get(input2.threadId)?.session.runtimeMode ?? input2.runtimeMode,
|
|
27002
|
+
request.kind
|
|
27003
|
+
) : void 0;
|
|
26485
27004
|
const executor = createAcpExecutor({
|
|
26486
27005
|
readable,
|
|
26487
27006
|
writable,
|
|
27007
|
+
...requestedEffort === void 0 ? {} : { requestedEffort },
|
|
26488
27008
|
cwd,
|
|
26489
27009
|
threadId: input2.threadId,
|
|
26490
27010
|
provider: KIMI_DRIVER_KIND,
|
|
26491
27011
|
providerInstanceId: host.instanceId,
|
|
26492
27012
|
clientInfo: CLIENT_INFO,
|
|
26493
|
-
|
|
26494
|
-
permissionUserInput: kimiPermissionUserInput,
|
|
26495
|
-
readContextWindow: async ({ sessionId }) => {
|
|
26496
|
-
const reading = await readKimiContextWindow({
|
|
26497
|
-
homePath: resolvedHomePath,
|
|
26498
|
-
acpSessionId: sessionId
|
|
26499
|
-
});
|
|
26500
|
-
if (reading === void 0) return void 0;
|
|
26501
|
-
return {
|
|
26502
|
-
usedTokens: reading.usedTokens,
|
|
26503
|
-
...reading.maxTokens === void 0 ? {} : { maxTokens: reading.maxTokens }
|
|
26504
|
-
};
|
|
26505
|
-
}
|
|
26506
|
-
},
|
|
27013
|
+
log: host.log,
|
|
26507
27014
|
...requestedModelId === void 0 ? {} : { requestedModelId },
|
|
26508
27015
|
...input2.bindingGeneration === void 0 ? {} : { originBindingGeneration: input2.bindingGeneration },
|
|
27016
|
+
hooks,
|
|
27017
|
+
...autoApprove === void 0 ? {} : { autoApprove },
|
|
26509
27018
|
...resume === void 0 ? {} : { resumeSessionId: resume.sessionId }
|
|
26510
27019
|
});
|
|
26511
27020
|
const forwarding = (async () => {
|
|
@@ -26515,6 +27024,13 @@ var createKimiInstance = (config2, host) => {
|
|
|
26515
27024
|
})();
|
|
26516
27025
|
try {
|
|
26517
27026
|
const started = await executor.start();
|
|
27027
|
+
const modeToApply = acpSessionModeToApply(
|
|
27028
|
+
input2.nativeModeId,
|
|
27029
|
+
acpCurrentModeId(started.sessionSetupResult)
|
|
27030
|
+
);
|
|
27031
|
+
if (modeToApply !== void 0) {
|
|
27032
|
+
await executor.setNativeMode(modeToApply);
|
|
27033
|
+
}
|
|
26518
27034
|
await yieldTick();
|
|
26519
27035
|
const createdAt = nowIso();
|
|
26520
27036
|
const resumeCursor = {
|
|
@@ -26526,6 +27042,7 @@ var createKimiInstance = (config2, host) => {
|
|
|
26526
27042
|
providerInstanceId: host.instanceId,
|
|
26527
27043
|
status: "idle",
|
|
26528
27044
|
runtimeMode: input2.runtimeMode,
|
|
27045
|
+
...input2.nativeModeId === void 0 ? {} : { nativeModeId: input2.nativeModeId },
|
|
26529
27046
|
cwd,
|
|
26530
27047
|
threadId: input2.threadId,
|
|
26531
27048
|
createdAt,
|
|
@@ -26609,6 +27126,22 @@ var createKimiInstance = (config2, host) => {
|
|
|
26609
27126
|
const booked = requireThread(threadId);
|
|
26610
27127
|
await booked.executor.respondToUserInput(requestId, answers);
|
|
26611
27128
|
},
|
|
27129
|
+
/**
|
|
27130
|
+
* 切这只手自报的审批档。`nativeModeId` 是它自己报的 id(探测时原样上报的那些),
|
|
27131
|
+
* 一路不翻译成宿主四档。
|
|
27132
|
+
*
|
|
27133
|
+
* 这是 `setRuntimeMode` 做不到的那一半:那个只改插件自己的会话记录,CLI 收不到
|
|
27134
|
+
* (`runtime-mode-never-reaches-cli` 记的那族缺陷)。
|
|
27135
|
+
*/
|
|
27136
|
+
setNativeMode: async (threadId, nativeModeId) => {
|
|
27137
|
+
const booked = requireThread(threadId);
|
|
27138
|
+
await booked.executor.setNativeMode(nativeModeId);
|
|
27139
|
+
booked.session = {
|
|
27140
|
+
...booked.session,
|
|
27141
|
+
nativeModeId,
|
|
27142
|
+
updatedAt: nowIso()
|
|
27143
|
+
};
|
|
27144
|
+
},
|
|
26612
27145
|
setRuntimeMode: async (threadId, runtimeMode) => {
|
|
26613
27146
|
const booked = requireThread(threadId);
|
|
26614
27147
|
booked.session = {
|
|
@@ -26628,6 +27161,7 @@ var createKimiInstance = (config2, host) => {
|
|
|
26628
27161
|
return { threadId, turns: booked.turns };
|
|
26629
27162
|
},
|
|
26630
27163
|
events,
|
|
27164
|
+
continuationKey: kimiContinuationKey(recipe),
|
|
26631
27165
|
dispose: async () => {
|
|
26632
27166
|
if (disposed) return;
|
|
26633
27167
|
disposed = true;
|
|
@@ -26655,7 +27189,7 @@ var index_default = definePlugin({
|
|
|
26655
27189
|
apiVersion: 2,
|
|
26656
27190
|
executors,
|
|
26657
27191
|
activate(ctx) {
|
|
26658
|
-
ctx.log.info("
|
|
27192
|
+
ctx.log.info("Kimi Code executor ready");
|
|
26659
27193
|
}
|
|
26660
27194
|
});
|
|
26661
27195
|
export {
|