@ycodium-ai/agent-kimi 0.2.2092 → 0.2.2488
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 +861 -308
- 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) {
|
|
@@ -24359,7 +24365,7 @@ function makeAcpContentDeltaEvent(input2) {
|
|
|
24359
24365
|
...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
|
|
24360
24366
|
...input2.itemId ? { itemId: input2.itemId } : {},
|
|
24361
24367
|
payload: {
|
|
24362
|
-
streamKind: "assistant_text",
|
|
24368
|
+
streamKind: input2.streamKind ?? "assistant_text",
|
|
24363
24369
|
delta: input2.text
|
|
24364
24370
|
},
|
|
24365
24371
|
raw: {
|
|
@@ -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({
|
|
@@ -25043,21 +25251,24 @@ function parseSessionUpdateEvent(params) {
|
|
|
25043
25251
|
}
|
|
25044
25252
|
break;
|
|
25045
25253
|
}
|
|
25046
|
-
case "agent_message_chunk":
|
|
25047
|
-
|
|
25254
|
+
case "agent_message_chunk":
|
|
25255
|
+
case "agent_thought_chunk": {
|
|
25256
|
+
const content = isRecord5(upd["content"]) ? upd["content"] : void 0;
|
|
25048
25257
|
const contentType = content?.["type"];
|
|
25258
|
+
const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
|
|
25049
25259
|
if (contentType === "text") {
|
|
25050
25260
|
const text = typeof content?.["text"] === "string" ? content["text"] : "";
|
|
25051
25261
|
if (text.length > 0) {
|
|
25052
25262
|
events.push({
|
|
25053
25263
|
_tag: "ContentDelta",
|
|
25054
25264
|
text,
|
|
25265
|
+
streamKind,
|
|
25055
25266
|
rawPayload: params
|
|
25056
25267
|
});
|
|
25057
25268
|
}
|
|
25058
25269
|
break;
|
|
25059
25270
|
}
|
|
25060
|
-
if (content && contentType !== "audio") {
|
|
25271
|
+
if (streamKind === "assistant_text" && content && contentType !== "audio") {
|
|
25061
25272
|
events.push({
|
|
25062
25273
|
_tag: "AssistantContentBlock",
|
|
25063
25274
|
content,
|
|
@@ -25109,16 +25320,18 @@ function normalizeModelId(value) {
|
|
|
25109
25320
|
return value?.trim() || void 0;
|
|
25110
25321
|
}
|
|
25111
25322
|
function modelSelectionStateFromSetup(setup) {
|
|
25112
|
-
const sessionModels =
|
|
25323
|
+
const sessionModels = isRecord5(setup.models) ? setup.models : void 0;
|
|
25113
25324
|
const modelConfigId = extractModelConfigId(setup);
|
|
25114
25325
|
const strategy = sessionModels === void 0 && modelConfigId !== void 0 ? "config-option" : "session/set_model";
|
|
25115
|
-
const
|
|
25326
|
+
const modelConfigOption = modelConfigId === void 0 ? void 0 : findSessionConfigOption(setup.configOptions, modelConfigId);
|
|
25327
|
+
const configModel = modelConfigOption?.currentValue;
|
|
25116
25328
|
const currentModelId = strategy === "config-option" ? typeof configModel === "string" ? normalizeModelId(configModel) : void 0 : typeof sessionModels?.["currentModelId"] === "string" ? normalizeModelId(sessionModels["currentModelId"]) : void 0;
|
|
25117
25329
|
return {
|
|
25118
25330
|
strategy,
|
|
25119
25331
|
sessionModelsAdvertised: sessionModels !== void 0,
|
|
25120
25332
|
modelConfigId,
|
|
25121
|
-
currentModelId
|
|
25333
|
+
currentModelId,
|
|
25334
|
+
advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels)
|
|
25122
25335
|
};
|
|
25123
25336
|
}
|
|
25124
25337
|
function createAcpExecutor(options) {
|
|
@@ -25137,8 +25350,10 @@ function createAcpExecutor(options) {
|
|
|
25137
25350
|
strategy: "session/set_model",
|
|
25138
25351
|
sessionModelsAdvertised: false,
|
|
25139
25352
|
modelConfigId: void 0,
|
|
25140
|
-
currentModelId: void 0
|
|
25353
|
+
currentModelId: void 0,
|
|
25354
|
+
advertisedModelValues: []
|
|
25141
25355
|
};
|
|
25356
|
+
let lastUnmatchedModelId;
|
|
25142
25357
|
let initializeResult;
|
|
25143
25358
|
let startResult;
|
|
25144
25359
|
let startInFlight;
|
|
@@ -25273,6 +25488,23 @@ function createAcpExecutor(options) {
|
|
|
25273
25488
|
continue;
|
|
25274
25489
|
}
|
|
25275
25490
|
if (event._tag === "ContentDelta") {
|
|
25491
|
+
if (event.streamKind === "reasoning_text") {
|
|
25492
|
+
if (event.text.trim().length === 0) {
|
|
25493
|
+
continue;
|
|
25494
|
+
}
|
|
25495
|
+
emit(
|
|
25496
|
+
makeAcpContentDeltaEvent({
|
|
25497
|
+
stamp: stamp(),
|
|
25498
|
+
provider: options.provider,
|
|
25499
|
+
threadId: options.threadId,
|
|
25500
|
+
turnId: activeTurnId,
|
|
25501
|
+
text: event.text,
|
|
25502
|
+
streamKind: "reasoning_text",
|
|
25503
|
+
rawPayload: event.rawPayload
|
|
25504
|
+
})
|
|
25505
|
+
);
|
|
25506
|
+
continue;
|
|
25507
|
+
}
|
|
25276
25508
|
if (event.text.trim().length === 0 && !assistantSegment.activeItemId) {
|
|
25277
25509
|
continue;
|
|
25278
25510
|
}
|
|
@@ -25285,6 +25517,7 @@ function createAcpExecutor(options) {
|
|
|
25285
25517
|
turnId: activeTurnId,
|
|
25286
25518
|
...itemId ? { itemId } : {},
|
|
25287
25519
|
text: event.text,
|
|
25520
|
+
streamKind: "assistant_text",
|
|
25288
25521
|
rawPayload: event.rawPayload
|
|
25289
25522
|
})
|
|
25290
25523
|
);
|
|
@@ -25445,6 +25678,12 @@ function createAcpExecutor(options) {
|
|
|
25445
25678
|
const userInputOutcome = await handlePermissionAsUserInput(params);
|
|
25446
25679
|
if (userInputOutcome !== void 0) return userInputOutcome;
|
|
25447
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
|
+
}
|
|
25448
25687
|
const requestId = randomId();
|
|
25449
25688
|
const outcome = await new Promise((resolve2) => {
|
|
25450
25689
|
const pending = {
|
|
@@ -25479,6 +25718,12 @@ function createAcpExecutor(options) {
|
|
|
25479
25718
|
const connection = createAcpConnection({
|
|
25480
25719
|
readable: options.readable,
|
|
25481
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
|
+
},
|
|
25482
25727
|
onNotification: (notification) => {
|
|
25483
25728
|
if (notification.method === "session/update") {
|
|
25484
25729
|
handleSessionUpdate(notification.params);
|
|
@@ -25532,36 +25777,70 @@ function createAcpExecutor(options) {
|
|
|
25532
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) {
|
|
25533
25778
|
return input2.state;
|
|
25534
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
|
+
}
|
|
25535
25795
|
if (input2.state.strategy === "config-option") {
|
|
25536
25796
|
await connection.request("session/set_config_option", {
|
|
25537
25797
|
sessionId: input2.acpSessionId,
|
|
25538
25798
|
configId: input2.state.modelConfigId,
|
|
25539
|
-
value
|
|
25799
|
+
value
|
|
25540
25800
|
});
|
|
25541
25801
|
} else {
|
|
25542
25802
|
await connection.request("session/set_model", {
|
|
25543
25803
|
sessionId: input2.acpSessionId,
|
|
25544
|
-
modelId:
|
|
25804
|
+
modelId: value
|
|
25545
25805
|
});
|
|
25546
25806
|
}
|
|
25547
25807
|
if (!isLive(input2.expectedGeneration)) {
|
|
25548
25808
|
throw new AcpExecutorDisposedError();
|
|
25549
25809
|
}
|
|
25550
|
-
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
|
+
}
|
|
25551
25841
|
};
|
|
25552
25842
|
const startOnce = async (expectedGeneration) => {
|
|
25553
|
-
const initializePayload =
|
|
25554
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
25555
|
-
clientCapabilities: {
|
|
25556
|
-
fs: {
|
|
25557
|
-
readTextFile: false,
|
|
25558
|
-
writeTextFile: false,
|
|
25559
|
-
...options.clientCapabilities?.fs
|
|
25560
|
-
},
|
|
25561
|
-
terminal: options.clientCapabilities?.terminal ?? false
|
|
25562
|
-
},
|
|
25563
|
-
clientInfo: options.clientInfo
|
|
25564
|
-
};
|
|
25843
|
+
const initializePayload = acpInitializePayload(options.clientInfo, options.clientCapabilities);
|
|
25565
25844
|
const initialized = await connection.request(
|
|
25566
25845
|
"initialize",
|
|
25567
25846
|
initializePayload
|
|
@@ -25605,12 +25884,27 @@ function createAcpExecutor(options) {
|
|
|
25605
25884
|
nextSessionId = created.sessionId;
|
|
25606
25885
|
setup = created;
|
|
25607
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
|
+
}
|
|
25608
25896
|
const nextModelSelectionState = await applyRequestedModel({
|
|
25609
25897
|
state: modelSelectionStateFromSetup(setup),
|
|
25610
25898
|
acpSessionId: nextSessionId,
|
|
25611
25899
|
requestedModelId: options.requestedModelId,
|
|
25612
25900
|
expectedGeneration
|
|
25613
25901
|
});
|
|
25902
|
+
await applyRequestedEffort({
|
|
25903
|
+
setup,
|
|
25904
|
+
acpSessionId: nextSessionId,
|
|
25905
|
+
requestedEffort: options.requestedEffort,
|
|
25906
|
+
expectedGeneration
|
|
25907
|
+
});
|
|
25614
25908
|
if (options.beforeApplyResult) {
|
|
25615
25909
|
await options.beforeApplyResult();
|
|
25616
25910
|
}
|
|
@@ -25975,6 +26269,26 @@ function createAcpExecutor(options) {
|
|
|
25975
26269
|
};
|
|
25976
26270
|
apply();
|
|
25977
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
|
+
};
|
|
25978
26292
|
const respondToUserInput = async (requestId, answers) => {
|
|
25979
26293
|
failIfDisposed();
|
|
25980
26294
|
const pending = pendingUserInputs.get(requestId);
|
|
@@ -25991,7 +26305,7 @@ function createAcpExecutor(options) {
|
|
|
25991
26305
|
pendingUserInputs.delete(requestId);
|
|
25992
26306
|
pending.resolve({
|
|
25993
26307
|
kind: "answered",
|
|
25994
|
-
answers:
|
|
26308
|
+
answers: isRecord5(answers) ? answers : {}
|
|
25995
26309
|
});
|
|
25996
26310
|
};
|
|
25997
26311
|
const dispose = async () => {
|
|
@@ -26041,12 +26355,84 @@ function createAcpExecutor(options) {
|
|
|
26041
26355
|
cancel,
|
|
26042
26356
|
respondToRequest,
|
|
26043
26357
|
respondToUserInput,
|
|
26358
|
+
setNativeMode,
|
|
26044
26359
|
dispose
|
|
26045
26360
|
};
|
|
26046
26361
|
}
|
|
26047
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
|
+
|
|
26048
26434
|
// src/config.ts
|
|
26049
|
-
function
|
|
26435
|
+
function isRecord6(value) {
|
|
26050
26436
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26051
26437
|
}
|
|
26052
26438
|
function readString(value) {
|
|
@@ -26059,7 +26445,7 @@ function readEnvironment(value) {
|
|
|
26059
26445
|
if (!Array.isArray(value)) return {};
|
|
26060
26446
|
const env = {};
|
|
26061
26447
|
for (const entry of value) {
|
|
26062
|
-
if (!
|
|
26448
|
+
if (!isRecord6(entry)) continue;
|
|
26063
26449
|
const name = readTrimmed(entry["name"]);
|
|
26064
26450
|
if (name.length === 0) continue;
|
|
26065
26451
|
env[name] = readString(entry["value"]);
|
|
@@ -26067,23 +26453,23 @@ function readEnvironment(value) {
|
|
|
26067
26453
|
return env;
|
|
26068
26454
|
}
|
|
26069
26455
|
function parseKimiInstanceConfig(config2) {
|
|
26070
|
-
if (!
|
|
26456
|
+
if (!isRecord6(config2)) {
|
|
26071
26457
|
return {
|
|
26072
26458
|
binaryPath: "",
|
|
26073
|
-
launchArgs:
|
|
26459
|
+
launchArgs: KIMI_CARD.launchArgs,
|
|
26074
26460
|
homePath: "",
|
|
26075
|
-
homeEnvVar:
|
|
26461
|
+
homeEnvVar: KIMI_CARD.homeEnvVar,
|
|
26076
26462
|
environment: {},
|
|
26077
26463
|
envelopeDriver: void 0
|
|
26078
26464
|
};
|
|
26079
26465
|
}
|
|
26080
|
-
const nested =
|
|
26466
|
+
const nested = isRecord6(config2["config"]) ? config2["config"] : void 0;
|
|
26081
26467
|
const settings = nested ?? config2;
|
|
26082
26468
|
return {
|
|
26083
26469
|
binaryPath: readTrimmed(settings["binaryPath"]),
|
|
26084
|
-
launchArgs: readString(settings["launchArgs"]),
|
|
26470
|
+
launchArgs: readString(settings["launchArgs"]) || KIMI_CARD.launchArgs,
|
|
26085
26471
|
homePath: readTrimmed(settings["homePath"]) || readTrimmed(config2["homePath"]),
|
|
26086
|
-
homeEnvVar:
|
|
26472
|
+
homeEnvVar: KIMI_CARD.homeEnvVar,
|
|
26087
26473
|
environment: readEnvironment(config2["environment"]),
|
|
26088
26474
|
envelopeDriver: readTrimmed(config2["driver"]) || void 0
|
|
26089
26475
|
};
|
|
@@ -26140,13 +26526,51 @@ function tokenizeLaunchArgs(value) {
|
|
|
26140
26526
|
return tokens;
|
|
26141
26527
|
}
|
|
26142
26528
|
|
|
26143
|
-
// src/
|
|
26144
|
-
import * as
|
|
26529
|
+
// src/kimi.ts
|
|
26530
|
+
import * as NodeFS from "node:fs";
|
|
26145
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
|
+
}
|
|
26146
26571
|
var WIRE_LOG_SEGMENTS = ["agents", "main", "wire.jsonl"];
|
|
26147
26572
|
var SESSIONS_DIR = "sessions";
|
|
26148
26573
|
var TAIL_SCAN_BYTES = 256 * 1024;
|
|
26149
|
-
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26150
26574
|
var positiveInt = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : void 0;
|
|
26151
26575
|
function parseKimiContextWindow(contents) {
|
|
26152
26576
|
let usedTokens;
|
|
@@ -26160,7 +26584,7 @@ function parseKimiContextWindow(contents) {
|
|
|
26160
26584
|
} catch {
|
|
26161
26585
|
continue;
|
|
26162
26586
|
}
|
|
26163
|
-
if (!
|
|
26587
|
+
if (!isRecord7(record2)) continue;
|
|
26164
26588
|
const type = record2["type"];
|
|
26165
26589
|
if (type === "token_counting.turn_recorded" || type === "token_counting.measured") {
|
|
26166
26590
|
usedTokens = positiveInt(record2["tokens"]) ?? usedTokens;
|
|
@@ -26170,31 +26594,35 @@ function parseKimiContextWindow(contents) {
|
|
|
26170
26594
|
maxTokens = positiveInt(record2["maxTokens"]) ?? maxTokens;
|
|
26171
26595
|
}
|
|
26172
26596
|
}
|
|
26173
|
-
|
|
26597
|
+
if (usedTokens === void 0) return void 0;
|
|
26598
|
+
return maxTokens === void 0 ? { usedTokens } : { usedTokens, maxTokens };
|
|
26174
26599
|
}
|
|
26175
|
-
|
|
26600
|
+
function readTail(filePath) {
|
|
26176
26601
|
let handle;
|
|
26177
26602
|
try {
|
|
26178
|
-
|
|
26179
|
-
const info = await handle.stat();
|
|
26180
|
-
const size = info.size;
|
|
26603
|
+
const size = NodeFS.statSync(filePath).size;
|
|
26181
26604
|
if (!Number.isFinite(size) || size <= 0) return void 0;
|
|
26182
|
-
const
|
|
26183
|
-
const length = size - offset;
|
|
26605
|
+
const length = size > TAIL_SCAN_BYTES ? TAIL_SCAN_BYTES : size;
|
|
26184
26606
|
const buffer = Buffer.alloc(length);
|
|
26185
|
-
|
|
26607
|
+
handle = NodeFS.openSync(filePath, "r");
|
|
26608
|
+
NodeFS.readSync(handle, buffer, 0, length, size - length);
|
|
26186
26609
|
return buffer.toString("utf8");
|
|
26187
26610
|
} catch {
|
|
26188
26611
|
return void 0;
|
|
26189
26612
|
} finally {
|
|
26190
|
-
|
|
26613
|
+
if (handle !== void 0) {
|
|
26614
|
+
try {
|
|
26615
|
+
NodeFS.closeSync(handle);
|
|
26616
|
+
} catch {
|
|
26617
|
+
}
|
|
26618
|
+
}
|
|
26191
26619
|
}
|
|
26192
26620
|
}
|
|
26193
|
-
|
|
26621
|
+
function findKimiSessionWireLog(input2) {
|
|
26194
26622
|
const sessionsRoot = NodePath.join(input2.homePath, SESSIONS_DIR);
|
|
26195
26623
|
let workspaces;
|
|
26196
26624
|
try {
|
|
26197
|
-
workspaces =
|
|
26625
|
+
workspaces = NodeFS.readdirSync(sessionsRoot);
|
|
26198
26626
|
} catch {
|
|
26199
26627
|
return void 0;
|
|
26200
26628
|
}
|
|
@@ -26205,126 +26633,175 @@ async function findKimiSessionWireLog(input2) {
|
|
|
26205
26633
|
input2.acpSessionId,
|
|
26206
26634
|
...WIRE_LOG_SEGMENTS
|
|
26207
26635
|
);
|
|
26208
|
-
|
|
26209
|
-
await NodeFSP.access(candidate);
|
|
26210
|
-
return candidate;
|
|
26211
|
-
} catch {
|
|
26212
|
-
}
|
|
26636
|
+
if (NodeFS.existsSync(candidate)) return candidate;
|
|
26213
26637
|
}
|
|
26214
26638
|
return void 0;
|
|
26215
26639
|
}
|
|
26216
|
-
|
|
26640
|
+
function readKimiContextWindow(input2) {
|
|
26217
26641
|
if (input2.homePath.trim().length === 0) return void 0;
|
|
26218
|
-
const wireLog =
|
|
26642
|
+
const wireLog = findKimiSessionWireLog(input2);
|
|
26219
26643
|
if (wireLog === void 0) return void 0;
|
|
26220
|
-
const contents =
|
|
26644
|
+
const contents = readTail(wireLog);
|
|
26221
26645
|
return contents === void 0 ? void 0 : parseKimiContextWindow(contents);
|
|
26222
26646
|
}
|
|
26223
26647
|
|
|
26224
|
-
// src/
|
|
26225
|
-
|
|
26226
|
-
|
|
26227
|
-
|
|
26228
|
-
|
|
26229
|
-
|
|
26230
|
-
|
|
26231
|
-
|
|
26232
|
-
|
|
26233
|
-
|
|
26234
|
-
|
|
26235
|
-
|
|
26236
|
-
|
|
26237
|
-
|
|
26238
|
-
|
|
26239
|
-
if (entry["type"] !== "content") continue;
|
|
26240
|
-
const inner = entry["content"];
|
|
26241
|
-
if (!isRecord6(inner)) continue;
|
|
26242
|
-
if (inner["type"] !== "text") continue;
|
|
26243
|
-
const text = inner["text"];
|
|
26244
|
-
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";
|
|
26245
26663
|
}
|
|
26246
|
-
|
|
26247
|
-
|
|
26248
|
-
|
|
26249
|
-
|
|
26250
|
-
|
|
26251
|
-
const title = request.toolCall.title;
|
|
26252
|
-
if (title !== KIMI_QUESTION_TITLE && title !== KIMI_PLAN_TITLE) return void 0;
|
|
26253
|
-
const question = questionText(request.toolCall.content);
|
|
26254
|
-
const optionIds = new Set(request.options.map((option) => option.optionId));
|
|
26255
|
-
if (request.options.length === 0 || optionIds.size !== request.options.length) {
|
|
26256
|
-
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";
|
|
26257
26669
|
}
|
|
26258
|
-
|
|
26259
|
-
const
|
|
26260
|
-
|
|
26261
|
-
|
|
26262
|
-
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26266
|
-
|
|
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;
|
|
26267
26703
|
}
|
|
26268
|
-
if (
|
|
26269
|
-
|
|
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
|
+
});
|
|
26270
26718
|
}
|
|
26271
|
-
return
|
|
26272
|
-
|
|
26273
|
-
|
|
26274
|
-
|
|
26275
|
-
|
|
26276
|
-
|
|
26277
|
-
|
|
26278
|
-
|
|
26279
|
-
|
|
26280
|
-
|
|
26281
|
-
|
|
26282
|
-
|
|
26283
|
-
|
|
26284
|
-
|
|
26285
|
-
|
|
26286
|
-
|
|
26287
|
-
|
|
26288
|
-
|
|
26289
|
-
|
|
26290
|
-
|
|
26291
|
-
|
|
26292
|
-
|
|
26293
|
-
|
|
26294
|
-
|
|
26295
|
-
|
|
26296
|
-
|
|
26297
|
-
|
|
26298
|
-
|
|
26299
|
-
|
|
26300
|
-
|
|
26301
|
-
|
|
26302
|
-
|
|
26303
|
-
readable.destroy(error62 instanceof Error ? error62 : new Error(String(error62)));
|
|
26304
|
-
return;
|
|
26305
|
-
}
|
|
26306
|
-
if (readable.writable) readable.end();
|
|
26307
|
-
})();
|
|
26308
|
-
void (async () => {
|
|
26309
|
-
for await (const _chunk of handle.stderr) {
|
|
26310
|
-
}
|
|
26311
|
-
})().catch(() => void 0);
|
|
26312
|
-
const writable = new NodeStream2.Writable({
|
|
26313
|
-
write(chunk, _encoding, callback) {
|
|
26314
|
-
const bytes = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
26315
|
-
handle.writeStdin(bytes).then(
|
|
26316
|
-
() => callback(),
|
|
26317
|
-
(error62) => callback(error62 instanceof Error ? error62 : new Error(String(error62)))
|
|
26318
|
-
);
|
|
26319
|
-
},
|
|
26320
|
-
final(callback) {
|
|
26321
|
-
handle.closeStdin().then(
|
|
26322
|
-
() => callback(),
|
|
26323
|
-
(error62) => callback(error62 instanceof Error ? error62 : new Error(String(error62)))
|
|
26324
|
-
);
|
|
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
|
+
};
|
|
26325
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
|
|
26326
26771
|
});
|
|
26327
|
-
|
|
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;
|
|
26328
26805
|
}
|
|
26329
26806
|
|
|
26330
26807
|
// src/kimiInstance.ts
|
|
@@ -26366,24 +26843,12 @@ var EventBus = class {
|
|
|
26366
26843
|
}
|
|
26367
26844
|
};
|
|
26368
26845
|
function expandHomePath(value) {
|
|
26369
|
-
if (value === "~") return
|
|
26846
|
+
if (value === "~") return NodeOS2.homedir();
|
|
26370
26847
|
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
26371
|
-
return
|
|
26848
|
+
return NodePath3.join(NodeOS2.homedir(), value.slice(2));
|
|
26372
26849
|
}
|
|
26373
26850
|
return value;
|
|
26374
26851
|
}
|
|
26375
|
-
function resolveHomePath(value) {
|
|
26376
|
-
const trimmed = value.trim();
|
|
26377
|
-
if (trimmed.length === 0) return "";
|
|
26378
|
-
return NodePath2.resolve(expandHomePath(trimmed));
|
|
26379
|
-
}
|
|
26380
|
-
function compactEnv(env) {
|
|
26381
|
-
const out = {};
|
|
26382
|
-
for (const [key, value] of Object.entries(env)) {
|
|
26383
|
-
if (value !== void 0) out[key] = value;
|
|
26384
|
-
}
|
|
26385
|
-
return out;
|
|
26386
|
-
}
|
|
26387
26852
|
function modelIdFromSelection(selection) {
|
|
26388
26853
|
if (typeof selection !== "object" || selection === null || Array.isArray(selection)) {
|
|
26389
26854
|
return void 0;
|
|
@@ -26391,18 +26856,39 @@ function modelIdFromSelection(selection) {
|
|
|
26391
26856
|
const model = selection["model"];
|
|
26392
26857
|
return typeof model === "string" ? model.trim() || void 0 : void 0;
|
|
26393
26858
|
}
|
|
26394
|
-
function buildSpawnEnv(recipe,
|
|
26859
|
+
function buildSpawnEnv(recipe, configuredHomePath) {
|
|
26860
|
+
const homePath = configuredHomePath.trim();
|
|
26395
26861
|
const homeEnvVar = recipe.homeEnvVar.trim();
|
|
26396
|
-
const homeInjection =
|
|
26397
|
-
return {
|
|
26398
|
-
|
|
26399
|
-
|
|
26400
|
-
|
|
26401
|
-
};
|
|
26862
|
+
const homeInjection = homePath.length > 0 && homeEnvVar.length > 0 ? { [homeEnvVar]: expandHomePath(homePath) } : {};
|
|
26863
|
+
return mergeLaunchEnv({
|
|
26864
|
+
accountHome: homeInjection,
|
|
26865
|
+
instanceTable: recipe.environment
|
|
26866
|
+
});
|
|
26402
26867
|
}
|
|
26403
26868
|
function nowIso() {
|
|
26404
26869
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
26405
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
|
+
}
|
|
26406
26892
|
async function stopBooked(booked) {
|
|
26407
26893
|
await booked.executor.dispose().catch(() => void 0);
|
|
26408
26894
|
await booked.handle.kill("SIGTERM").catch(() => void 0);
|
|
@@ -26426,21 +26912,65 @@ var createKimiInstance = (config2, host) => {
|
|
|
26426
26912
|
version: null,
|
|
26427
26913
|
readiness: "error",
|
|
26428
26914
|
auth: { status: "unknown" },
|
|
26429
|
-
detail: "Kimi program path is not configured"
|
|
26915
|
+
detail: "Kimi Code program path is not configured"
|
|
26430
26916
|
};
|
|
26431
26917
|
}
|
|
26432
|
-
|
|
26433
|
-
|
|
26434
|
-
|
|
26435
|
-
|
|
26436
|
-
|
|
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
|
+
}
|
|
26437
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
|
+
}
|
|
26438
26968
|
},
|
|
26439
26969
|
startSession: async (input2, signal) => {
|
|
26440
26970
|
if (disposed) throw new Error("instance disposed");
|
|
26441
26971
|
if (signal?.aborted) throw new Error("aborted");
|
|
26442
26972
|
if (recipe.binaryPath.length === 0) {
|
|
26443
|
-
throw new Error("Kimi program path is not configured");
|
|
26973
|
+
throw new Error("Kimi Code program path is not configured");
|
|
26444
26974
|
}
|
|
26445
26975
|
const cwd = input2.cwd ?? host.workspacePath(input2.threadId);
|
|
26446
26976
|
if (cwd.trim() === "") throw new Error("workspace path missing");
|
|
@@ -26449,8 +26979,7 @@ var createKimiInstance = (config2, host) => {
|
|
|
26449
26979
|
await stopBooked(existing);
|
|
26450
26980
|
threads.delete(input2.threadId);
|
|
26451
26981
|
}
|
|
26452
|
-
const
|
|
26453
|
-
const env = buildSpawnEnv(recipe, input2.launch, resolvedHomePath);
|
|
26982
|
+
const env = buildSpawnEnv(recipe, recipe.homePath);
|
|
26454
26983
|
const handle = await host.process.spawn({
|
|
26455
26984
|
program: recipe.binaryPath,
|
|
26456
26985
|
args: tokenizeLaunchArgs(recipe.launchArgs),
|
|
@@ -26460,31 +26989,30 @@ var createKimiInstance = (config2, host) => {
|
|
|
26460
26989
|
});
|
|
26461
26990
|
const { readable, writable } = nodeStreamsFromHandle(handle);
|
|
26462
26991
|
const resume = input2.discardResumeCursor === true ? void 0 : parseAcpResumeCursor(input2.resumeCursor, RESUME_SCHEMA_VERSION);
|
|
26463
|
-
const requestedModelId =
|
|
26992
|
+
const requestedModelId = modelIdFromSelection(input2.modelSelection);
|
|
26993
|
+
const requestedEffort = modelSelectionStringOption(
|
|
26994
|
+
input2.modelSelection,
|
|
26995
|
+
ACP_EFFORT_OPTION_ID
|
|
26996
|
+
);
|
|
26997
|
+
const hooks = kimiHooks(recipe);
|
|
26998
|
+
const autoApprove = input2.nativeModeId === void 0 ? (request) => acpRuntimeModeAutoApproves(
|
|
26999
|
+
threads.get(input2.threadId)?.session.runtimeMode ?? input2.runtimeMode,
|
|
27000
|
+
request.kind
|
|
27001
|
+
) : void 0;
|
|
26464
27002
|
const executor = createAcpExecutor({
|
|
26465
27003
|
readable,
|
|
26466
27004
|
writable,
|
|
27005
|
+
...requestedEffort === void 0 ? {} : { requestedEffort },
|
|
26467
27006
|
cwd,
|
|
26468
27007
|
threadId: input2.threadId,
|
|
26469
27008
|
provider: KIMI_DRIVER_KIND,
|
|
26470
27009
|
providerInstanceId: host.instanceId,
|
|
26471
27010
|
clientInfo: CLIENT_INFO,
|
|
26472
|
-
|
|
26473
|
-
permissionUserInput: kimiPermissionUserInput,
|
|
26474
|
-
readContextWindow: async ({ sessionId }) => {
|
|
26475
|
-
const reading = await readKimiContextWindow({
|
|
26476
|
-
homePath: resolvedHomePath,
|
|
26477
|
-
acpSessionId: sessionId
|
|
26478
|
-
});
|
|
26479
|
-
if (reading === void 0) return void 0;
|
|
26480
|
-
return {
|
|
26481
|
-
usedTokens: reading.usedTokens,
|
|
26482
|
-
...reading.maxTokens === void 0 ? {} : { maxTokens: reading.maxTokens }
|
|
26483
|
-
};
|
|
26484
|
-
}
|
|
26485
|
-
},
|
|
27011
|
+
log: host.log,
|
|
26486
27012
|
...requestedModelId === void 0 ? {} : { requestedModelId },
|
|
26487
27013
|
...input2.bindingGeneration === void 0 ? {} : { originBindingGeneration: input2.bindingGeneration },
|
|
27014
|
+
hooks,
|
|
27015
|
+
...autoApprove === void 0 ? {} : { autoApprove },
|
|
26488
27016
|
...resume === void 0 ? {} : { resumeSessionId: resume.sessionId }
|
|
26489
27017
|
});
|
|
26490
27018
|
const forwarding = (async () => {
|
|
@@ -26494,6 +27022,13 @@ var createKimiInstance = (config2, host) => {
|
|
|
26494
27022
|
})();
|
|
26495
27023
|
try {
|
|
26496
27024
|
const started = await executor.start();
|
|
27025
|
+
const modeToApply = acpSessionModeToApply(
|
|
27026
|
+
input2.nativeModeId,
|
|
27027
|
+
acpCurrentModeId(started.sessionSetupResult)
|
|
27028
|
+
);
|
|
27029
|
+
if (modeToApply !== void 0) {
|
|
27030
|
+
await executor.setNativeMode(modeToApply);
|
|
27031
|
+
}
|
|
26497
27032
|
await yieldTick();
|
|
26498
27033
|
const createdAt = nowIso();
|
|
26499
27034
|
const resumeCursor = {
|
|
@@ -26505,6 +27040,7 @@ var createKimiInstance = (config2, host) => {
|
|
|
26505
27040
|
providerInstanceId: host.instanceId,
|
|
26506
27041
|
status: "idle",
|
|
26507
27042
|
runtimeMode: input2.runtimeMode,
|
|
27043
|
+
...input2.nativeModeId === void 0 ? {} : { nativeModeId: input2.nativeModeId },
|
|
26508
27044
|
cwd,
|
|
26509
27045
|
threadId: input2.threadId,
|
|
26510
27046
|
createdAt,
|
|
@@ -26588,6 +27124,22 @@ var createKimiInstance = (config2, host) => {
|
|
|
26588
27124
|
const booked = requireThread(threadId);
|
|
26589
27125
|
await booked.executor.respondToUserInput(requestId, answers);
|
|
26590
27126
|
},
|
|
27127
|
+
/**
|
|
27128
|
+
* 切这只手自报的审批档。`nativeModeId` 是它自己报的 id(探测时原样上报的那些),
|
|
27129
|
+
* 一路不翻译成宿主四档。
|
|
27130
|
+
*
|
|
27131
|
+
* 这是 `setRuntimeMode` 做不到的那一半:那个只改插件自己的会话记录,CLI 收不到
|
|
27132
|
+
* (`runtime-mode-never-reaches-cli` 记的那族缺陷)。
|
|
27133
|
+
*/
|
|
27134
|
+
setNativeMode: async (threadId, nativeModeId) => {
|
|
27135
|
+
const booked = requireThread(threadId);
|
|
27136
|
+
await booked.executor.setNativeMode(nativeModeId);
|
|
27137
|
+
booked.session = {
|
|
27138
|
+
...booked.session,
|
|
27139
|
+
nativeModeId,
|
|
27140
|
+
updatedAt: nowIso()
|
|
27141
|
+
};
|
|
27142
|
+
},
|
|
26591
27143
|
setRuntimeMode: async (threadId, runtimeMode) => {
|
|
26592
27144
|
const booked = requireThread(threadId);
|
|
26593
27145
|
booked.session = {
|
|
@@ -26607,6 +27159,7 @@ var createKimiInstance = (config2, host) => {
|
|
|
26607
27159
|
return { threadId, turns: booked.turns };
|
|
26608
27160
|
},
|
|
26609
27161
|
events,
|
|
27162
|
+
continuationKey: kimiContinuationKey(recipe),
|
|
26610
27163
|
dispose: async () => {
|
|
26611
27164
|
if (disposed) return;
|
|
26612
27165
|
disposed = true;
|
|
@@ -26634,7 +27187,7 @@ var index_default = definePlugin({
|
|
|
26634
27187
|
apiVersion: 2,
|
|
26635
27188
|
executors,
|
|
26636
27189
|
activate(ctx) {
|
|
26637
|
-
ctx.log.info("
|
|
27190
|
+
ctx.log.info("Kimi Code executor ready");
|
|
26638
27191
|
}
|
|
26639
27192
|
});
|
|
26640
27193
|
export {
|