@moonshot-ai/kimi-code 0.22.3 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.mjs +1802 -730
- package/dist-web/assets/{CodeBlockNode--K4eRmNh.js → CodeBlockNode-Bi8jIiGS.js} +1 -1
- package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-8z4SytTj.js → CodeBlockShell.vue_vue_type_style_index_0_lang-B0EX64Fy.js} +1 -1
- package/dist-web/assets/DesignSystemView-CxzrbiS1.css +1 -0
- package/dist-web/assets/DesignSystemView-uZVLgoX6.js +12 -0
- package/dist-web/assets/{Tooltip-sFOhW5c-.js → Tooltip-BvXZgTKH.js} +1 -1
- package/dist-web/assets/{arc-b1f-JaXG.js → arc-Dq8eiFQP.js} +1 -1
- package/dist-web/assets/{architectureDiagram-3BPJPVTR-DRV073hL.js → architectureDiagram-3BPJPVTR-b6nIVGZD.js} +1 -1
- package/dist-web/assets/{blockDiagram-GPEHLZMM-BG0TxS08.js → blockDiagram-GPEHLZMM-B3B2WOkj.js} +1 -1
- package/dist-web/assets/{c4Diagram-AAUBKEIU-CsocakY-.js → c4Diagram-AAUBKEIU-BKyN3yLu.js} +1 -1
- package/dist-web/assets/channel-DYPbvBMu.js +1 -0
- package/dist-web/assets/{chunk-2J33WTMH-D7mBRhm2.js → chunk-2J33WTMH-HN_s9nzs.js} +1 -1
- package/dist-web/assets/{chunk-4BX2VUAB-BMOSnPC4.js → chunk-4BX2VUAB-fxHwG6FR.js} +1 -1
- package/dist-web/assets/{chunk-55IACEB6-DH7ZU8ec.js → chunk-55IACEB6-D-XDLZ_9.js} +1 -1
- package/dist-web/assets/{chunk-727SXJPM-CaYu9Tne.js → chunk-727SXJPM-BdVZmbdu.js} +1 -1
- package/dist-web/assets/{chunk-AQP2D5EJ-Dd2oKOPL.js → chunk-AQP2D5EJ-C0q5GUyy.js} +1 -1
- package/dist-web/assets/{chunk-FMBD7UC4-JdHZqUnV.js → chunk-FMBD7UC4-BHvs9p4D.js} +1 -1
- package/dist-web/assets/{chunk-ND2GUHAM-DBm1Ahcp.js → chunk-ND2GUHAM-BCuwZrYk.js} +1 -1
- package/dist-web/assets/{chunk-QZHKN3VN-DmqufK50.js → chunk-QZHKN3VN-sdMQprxY.js} +1 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-7hR3h9FG.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-7hR3h9FG.js +1 -0
- package/dist-web/assets/{cose-bilkent-S5V4N54A-HNWFCNh9.js → cose-bilkent-S5V4N54A-DAKVyg0y.js} +1 -1
- package/dist-web/assets/{dagre-BM42HDAG-Dv6WU7Ym.js → dagre-BM42HDAG-fE0QBWG7.js} +1 -1
- package/dist-web/assets/{diagram-2AECGRRQ-DlQ3gFah.js → diagram-2AECGRRQ-DhTfW7BA.js} +1 -1
- package/dist-web/assets/{diagram-5GNKFQAL-DdXhz5jN.js → diagram-5GNKFQAL-BFxW-PQU.js} +1 -1
- package/dist-web/assets/{diagram-KO2AKTUF-CbAHWTiw.js → diagram-KO2AKTUF-D29F_M5j.js} +1 -1
- package/dist-web/assets/{diagram-LMA3HP47-DhASU77a.js → diagram-LMA3HP47-DVsX1Zqb.js} +1 -1
- package/dist-web/assets/{diagram-OG6HWLK6-vyegCtBh.js → diagram-OG6HWLK6-C1xkLsBo.js} +1 -1
- package/dist-web/assets/{erDiagram-TEJ5UH35-u41T2VU1.js → erDiagram-TEJ5UH35-RExHqUHF.js} +1 -1
- package/dist-web/assets/{flowDiagram-I6XJVG4X-BlZR3M4a.js → flowDiagram-I6XJVG4X-Bb2CxfqX.js} +1 -1
- package/dist-web/assets/{ganttDiagram-6RSMTGT7-CBIULxGb.js → ganttDiagram-6RSMTGT7-CPgclO8f.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-PVQCEYII-C6SGJJUo.js → gitGraphDiagram-PVQCEYII-CkbhTuQx.js} +1 -1
- package/dist-web/assets/index-BBqKjyg_.css +1 -0
- package/dist-web/assets/{index-BNJo44oI.js → index-C20P6k3r.js} +1 -1
- package/dist-web/assets/{index-D3WSVtYV.js → index-CvZ8g4D9.js} +2 -2
- package/dist-web/assets/index-SziNj6Ky.js +292 -0
- package/dist-web/assets/{index10-CizaPNSY.js → index10-C34WriXe.js} +1 -1
- package/dist-web/assets/{index11-C3vBSelg.js → index11-DnWluvv0.js} +1 -1
- package/dist-web/assets/{index5-DCmdgd-c.js → index5-DMfYcwho.js} +1 -1
- package/dist-web/assets/{index6-DeBB3wcO.js → index6-CM7_ALPI.js} +1 -1
- package/dist-web/assets/{index7-D0RS__NS.js → index7-DOz39QJX.js} +1 -1
- package/dist-web/assets/{index8-ByeMRBS0.js → index8-DDNiq5_W.js} +2 -2
- package/dist-web/assets/{infoDiagram-5YYISTIA-BEQeL8qo.js → infoDiagram-5YYISTIA-DhTeo1nz.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-BGEkrGOU.js → ishikawaDiagram-YF4QCWOH-C6zNOyfV.js} +1 -1
- package/dist-web/assets/{journeyDiagram-JHISSGLW-DAEyZppi.js → journeyDiagram-JHISSGLW-GqHLo20m.js} +1 -1
- package/dist-web/assets/{kanban-definition-UN3LZRKU-6nYYByea.js → kanban-definition-UN3LZRKU-COLCFNmp.js} +1 -1
- package/dist-web/assets/{linear-RPDuZEc_.js → linear-BNWcliWU.js} +1 -1
- package/dist-web/assets/{mermaid.core-CmwZMEVS.js → mermaid.core-Dvwdy-Wb.js} +4 -4
- package/dist-web/assets/{mindmap-definition-RKZ34NQL-MLtqKWd1.js → mindmap-definition-RKZ34NQL-MmqWhMt1.js} +1 -1
- package/dist-web/assets/{pieDiagram-4H26LBE5-Bfifo7At.js → pieDiagram-4H26LBE5-D2HeVweL.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-W4KKPZXB-DZRwxAP7.js → quadrantDiagram-W4KKPZXB-D0Gnhh0w.js} +1 -1
- package/dist-web/assets/{requirementDiagram-4Y6WPE33-lazNkbiM.js → requirementDiagram-4Y6WPE33-DV_rvSe0.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-5OEKKPKP-D4yxPAzq.js → sankeyDiagram-5OEKKPKP-CIOHPqwt.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-3UESZ5HK-D7Cjzr6g.js → sequenceDiagram-3UESZ5HK-OMPW2dQZ.js} +1 -1
- package/dist-web/assets/{stateDiagram-AJRCARHV-0z8M0BXQ.js → stateDiagram-AJRCARHV-DGC2N7WX.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-BWIlZ-Ms.js +1 -0
- package/dist-web/assets/{timeline-definition-PNZ67QCA-Cfxia7fX.js → timeline-definition-PNZ67QCA-DVD8syC3.js} +1 -1
- package/dist-web/assets/{vennDiagram-CIIHVFJN-CBtQvJlD.js → vennDiagram-CIIHVFJN-DjolQSRq.js} +1 -1
- package/dist-web/assets/{vue.runtime.esm-bundler-BJW6XsQa.js → vue.runtime.esm-bundler-DOh9SYil.js} +1 -1
- package/dist-web/assets/{wardley-L42UT6IY-lhlQsxcl.js → wardley-L42UT6IY-4aEVZF_y.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-YWT4CUSO-CNRYkXLH.js → wardleyDiagram-YWT4CUSO-CMJ7T5Da.js} +1 -1
- package/dist-web/assets/{xychartDiagram-2RQKCTM6-mUzDW-MM.js → xychartDiagram-2RQKCTM6-SWdAUpzG.js} +1 -1
- package/dist-web/index.html +2 -2
- package/package.json +8 -8
- package/dist-web/assets/DesignSystemView-BskvdBnn.css +0 -1
- package/dist-web/assets/DesignSystemView-gstQZ6Dp.js +0 -12
- package/dist-web/assets/channel-Cwe7TdNc.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-CQ4_AXuT.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-CQ4_AXuT.js +0 -1
- package/dist-web/assets/index-CK7yaL8y.js +0 -279
- package/dist-web/assets/index-D0u_059j.css +0 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-lF1PY-XM.js +0 -1
package/dist/main.mjs
CHANGED
|
@@ -6,7 +6,7 @@ const __dirname = __cjsShimDirname(__filename);
|
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
8
8
|
import * as fs$16 from "node:fs";
|
|
9
|
-
import Vt, { appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
9
|
+
import Vt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
10
10
|
import * as path$15 from "node:path";
|
|
11
11
|
import path, { basename, dirname, extname, isAbsolute, join, normalize, posix, relative, resolve, sep, win32 } from "node:path";
|
|
12
12
|
import { spawn } from "child_process";
|
|
@@ -36,7 +36,7 @@ import { finished, pipeline as pipeline$1 } from "node:stream/promises";
|
|
|
36
36
|
import * as ks from "zlib";
|
|
37
37
|
import qr from "zlib";
|
|
38
38
|
import * as nodeOs from "node:os";
|
|
39
|
-
import os, { arch, homedir as homedir$1, hostname, networkInterfaces, platform, release, tmpdir, type as type$1, userInfo } from "node:os";
|
|
39
|
+
import os, { arch, cpus, freemem, homedir as homedir$1, hostname, loadavg, networkInterfaces, platform, release, tmpdir, totalmem, type as type$1, userInfo } from "node:os";
|
|
40
40
|
import fs, { access, appendFile, chmod, copyFile, cp, lstat as lstat$1, mkdir, mkdtemp, open as open$1, readFile, readdir as readdir$1, realpath as realpath$1, rename, rm, stat as stat$2, unlink, utimes, writeFile as writeFile$1 } from "node:fs/promises";
|
|
41
41
|
import { execFile, execFileSync, execSync, spawn as spawn$1, spawnSync } from "node:child_process";
|
|
42
42
|
import * as posixPath from "node:path/posix";
|
|
@@ -967,6 +967,18 @@ function isContentPart(part) {
|
|
|
967
967
|
const t = part.type;
|
|
968
968
|
return t === "text" || t === "think" || t === "image_url" || t === "audio_url" || t === "video_url";
|
|
969
969
|
}
|
|
970
|
+
/**
|
|
971
|
+
* True for a message whose only payload is `tools` — the dynamic tool-loading
|
|
972
|
+
* primitive (see {@link Message.tools}). Message-level tool declarations are a
|
|
973
|
+
* Kimi wire feature; every other provider must skip such a message entirely:
|
|
974
|
+
* their explicit field construction already keeps the `tools` field off the
|
|
975
|
+
* wire, but the leftover empty message would be rejected (OpenAI: system
|
|
976
|
+
* message without content) or serialized as a garbage `<system></system>`
|
|
977
|
+
* turn (Anthropic/Google system-to-user wrapping).
|
|
978
|
+
*/
|
|
979
|
+
function isToolDeclarationOnlyMessage(message) {
|
|
980
|
+
return message.tools !== void 0 && message.tools.length > 0 && message.content.length === 0 && message.toolCalls.length === 0;
|
|
981
|
+
}
|
|
970
982
|
/** Check if a streamed part is a ToolCall. */
|
|
971
983
|
function isToolCall(part) {
|
|
972
984
|
return part.type === "function";
|
|
@@ -1051,7 +1063,7 @@ var init_provider$1 = __esmMin((() => {}));
|
|
|
1051
1063
|
function isUnknownCapability(capability) {
|
|
1052
1064
|
if (capability === UNKNOWN_CAPABILITY) return true;
|
|
1053
1065
|
if (capability[UNKNOWN_CAPABILITY_MARKER] === true) return true;
|
|
1054
|
-
return !capability.image_in && !capability.video_in && !capability.audio_in && !capability.thinking && !capability.tool_use && capability.max_context_tokens === 0;
|
|
1066
|
+
return !capability.image_in && !capability.video_in && !capability.audio_in && !capability.thinking && !capability.tool_use && capability.select_tools !== true && capability.max_context_tokens === 0;
|
|
1055
1067
|
}
|
|
1056
1068
|
var UNKNOWN_CAPABILITY_MARKER, UNKNOWN_CAPABILITY;
|
|
1057
1069
|
var init_capability = __esmMin((() => {
|
|
@@ -1062,7 +1074,8 @@ var init_capability = __esmMin((() => {
|
|
|
1062
1074
|
audio_in: false,
|
|
1063
1075
|
thinking: false,
|
|
1064
1076
|
tool_use: false,
|
|
1065
|
-
max_context_tokens: 0
|
|
1077
|
+
max_context_tokens: 0,
|
|
1078
|
+
select_tools: false
|
|
1066
1079
|
}, UNKNOWN_CAPABILITY_MARKER, { value: true }));
|
|
1067
1080
|
}));
|
|
1068
1081
|
//#endregion
|
|
@@ -9573,6 +9586,7 @@ function convertAnthropicError(error) {
|
|
|
9573
9586
|
var INTERLEAVED_THINKING_BETA, OPUS_VERSION_RE, ADAPTIVE_MIN_VERSION, ANTHROPIC_TOOL_CALL_ID_POLICY, CEILING_BY_FAMILY_VERSION, FALLBACK_MAX_TOKENS, FAMILY_FIRST_RE, VERSION_FIRST_RE, BARE_FAMILY_RE, CACHE_CONTROL, CACHEABLE_TYPES, OMITTED_MEDIA_PLACEHOLDER, SUPPORTED_B64_MEDIA_TYPES, SUPPORTED_B64_VIDEO_TYPES, AnthropicStreamedMessage, AnthropicChatProvider;
|
|
9574
9587
|
var init_anthropic = __esmMin((() => {
|
|
9575
9588
|
init_errors$12();
|
|
9589
|
+
init_message$3();
|
|
9576
9590
|
init_sdk();
|
|
9577
9591
|
init_merge_user_messages();
|
|
9578
9592
|
init_request_auth();
|
|
@@ -9885,7 +9899,7 @@ var init_anthropic = __esmMin((() => {
|
|
|
9885
9899
|
text: systemPrompt,
|
|
9886
9900
|
cache_control: CACHE_CONTROL
|
|
9887
9901
|
}] : void 0;
|
|
9888
|
-
const messages = mergeConsecutiveUserMessages(normalizeToolCallIdsForProvider(history, ANTHROPIC_TOOL_CALL_ID_POLICY).map((msg) => convertMessage$3(msg, this._model)), {
|
|
9902
|
+
const messages = mergeConsecutiveUserMessages(normalizeToolCallIdsForProvider(history.filter((msg) => !isToolDeclarationOnlyMessage(msg)), ANTHROPIC_TOOL_CALL_ID_POLICY).map((msg) => convertMessage$3(msg, this._model)), {
|
|
9889
9903
|
isUser: (message) => message.role === "user",
|
|
9890
9904
|
isToolResultOnly,
|
|
9891
9905
|
merge: (last, next) => ({
|
|
@@ -44811,10 +44825,10 @@ function normalizeGoogleGenAIFinishReason(raw) {
|
|
|
44811
44825
|
}
|
|
44812
44826
|
}
|
|
44813
44827
|
function toolToGoogleGenAI(tool) {
|
|
44814
|
-
return {
|
|
44828
|
+
return { functionDeclarations: [{
|
|
44815
44829
|
name: tool.name,
|
|
44816
44830
|
description: tool.description,
|
|
44817
|
-
|
|
44831
|
+
parametersJsonSchema: tool.parameters
|
|
44818
44832
|
}] };
|
|
44819
44833
|
}
|
|
44820
44834
|
function toolCallIdToName(toolCallId, toolNameById) {
|
|
@@ -44900,11 +44914,11 @@ function messageToGoogleGenAI(message) {
|
|
|
44900
44914
|
if (error instanceof ChatProviderError) throw error;
|
|
44901
44915
|
throw new ChatProviderError("Tool call arguments must be valid JSON.");
|
|
44902
44916
|
}
|
|
44903
|
-
const functionCallPart = {
|
|
44917
|
+
const functionCallPart = { functionCall: {
|
|
44904
44918
|
name: toolCall.name,
|
|
44905
44919
|
args
|
|
44906
44920
|
} };
|
|
44907
|
-
if (toolCall.extras && "thought_signature_b64" in toolCall.extras) functionCallPart["
|
|
44921
|
+
if (toolCall.extras && "thought_signature_b64" in toolCall.extras) functionCallPart["thoughtSignature"] = toolCall.extras["thought_signature_b64"];
|
|
44908
44922
|
parts.push(functionCallPart);
|
|
44909
44923
|
}
|
|
44910
44924
|
return {
|
|
@@ -44941,7 +44955,7 @@ function toolMessageToFunctionResponseParts(message, toolNameById) {
|
|
|
44941
44955
|
break;
|
|
44942
44956
|
case "think": break;
|
|
44943
44957
|
}
|
|
44944
|
-
return [{
|
|
44958
|
+
return [{ functionResponse: {
|
|
44945
44959
|
name: toolCallIdToName(message.toolCallId, toolNameById),
|
|
44946
44960
|
response: { output: textOutput },
|
|
44947
44961
|
parts: []
|
|
@@ -44954,6 +44968,10 @@ function messagesToGoogleGenAIContents(messages) {
|
|
|
44954
44968
|
while (i < messages.length) {
|
|
44955
44969
|
const message = messages[i];
|
|
44956
44970
|
if (message === void 0) break;
|
|
44971
|
+
if (isToolDeclarationOnlyMessage(message)) {
|
|
44972
|
+
i += 1;
|
|
44973
|
+
continue;
|
|
44974
|
+
}
|
|
44957
44975
|
if (message.role === "system") {
|
|
44958
44976
|
const text = message.content.filter((p) => p.type === "text").map((p) => p.text).join("\n");
|
|
44959
44977
|
if (text.length > 0) contents.push({
|
|
@@ -45021,7 +45039,7 @@ function messagesToGoogleGenAIContents(messages) {
|
|
|
45021
45039
|
}
|
|
45022
45040
|
return mergeConsecutiveUserMessages(contents, {
|
|
45023
45041
|
isUser: (content) => content.role === "user",
|
|
45024
|
-
isToolResultOnly: (content) => content.parts.length > 0 && content.parts.every((part) => part.
|
|
45042
|
+
isToolResultOnly: (content) => content.parts.length > 0 && content.parts.every((part) => part.functionResponse !== void 0),
|
|
45025
45043
|
merge: (last, next) => ({
|
|
45026
45044
|
...last,
|
|
45027
45045
|
parts: [...last.parts, ...next.parts]
|
|
@@ -45046,6 +45064,7 @@ function convertGoogleGenAIError(error) {
|
|
|
45046
45064
|
var GoogleGenAIStreamedMessage, NETWORK_RE, TIMEOUT_RE, GoogleGenAIChatProvider;
|
|
45047
45065
|
var init_google_genai = __esmMin((() => {
|
|
45048
45066
|
init_errors$12();
|
|
45067
|
+
init_message$3();
|
|
45049
45068
|
init_node$6();
|
|
45050
45069
|
init_merge_user_messages();
|
|
45051
45070
|
init_request_auth();
|
|
@@ -45218,19 +45237,19 @@ var init_google_genai = __esmMin((() => {
|
|
|
45218
45237
|
return this._model;
|
|
45219
45238
|
}
|
|
45220
45239
|
get thinkingEffort() {
|
|
45221
|
-
const thinkingConfig = this._generationKwargs.
|
|
45240
|
+
const thinkingConfig = this._generationKwargs.thinkingConfig;
|
|
45222
45241
|
if (thinkingConfig === void 0) return null;
|
|
45223
|
-
if (thinkingConfig.
|
|
45224
|
-
case "MINIMAL": return thinkingConfig.
|
|
45242
|
+
if (thinkingConfig.thinkingLevel !== void 0) switch (thinkingConfig.thinkingLevel) {
|
|
45243
|
+
case "MINIMAL": return thinkingConfig.includeThoughts === false ? "off" : "low";
|
|
45225
45244
|
case "LOW": return "low";
|
|
45226
45245
|
case "MEDIUM": return "medium";
|
|
45227
45246
|
case "HIGH": return "high";
|
|
45228
45247
|
default: return null;
|
|
45229
45248
|
}
|
|
45230
|
-
if (thinkingConfig.
|
|
45231
|
-
if (thinkingConfig.
|
|
45232
|
-
if (thinkingConfig.
|
|
45233
|
-
if (thinkingConfig.
|
|
45249
|
+
if (thinkingConfig.thinkingBudget !== void 0) {
|
|
45250
|
+
if (thinkingConfig.thinkingBudget === 0) return "off";
|
|
45251
|
+
if (thinkingConfig.thinkingBudget <= 1024) return "low";
|
|
45252
|
+
if (thinkingConfig.thinkingBudget <= 4096) return "medium";
|
|
45234
45253
|
return "high";
|
|
45235
45254
|
}
|
|
45236
45255
|
return null;
|
|
@@ -45246,7 +45265,7 @@ var init_google_genai = __esmMin((() => {
|
|
|
45246
45265
|
const contents = messagesToGoogleGenAIContents(history);
|
|
45247
45266
|
const config = {
|
|
45248
45267
|
...this._generationKwargs,
|
|
45249
|
-
|
|
45268
|
+
systemInstruction: systemPrompt,
|
|
45250
45269
|
...tools.length > 0 ? { tools: tools.map((t) => toolToGoogleGenAI(t)) } : {}
|
|
45251
45270
|
};
|
|
45252
45271
|
try {
|
|
@@ -45274,45 +45293,45 @@ var init_google_genai = __esmMin((() => {
|
|
|
45274
45293
|
});
|
|
45275
45294
|
}
|
|
45276
45295
|
withThinking(effort) {
|
|
45277
|
-
const thinkingConfig = {
|
|
45296
|
+
const thinkingConfig = { includeThoughts: true };
|
|
45278
45297
|
if (this._model.includes("gemini-3")) switch (effort) {
|
|
45279
45298
|
case "off":
|
|
45280
|
-
thinkingConfig.
|
|
45281
|
-
thinkingConfig.
|
|
45299
|
+
thinkingConfig.thinkingLevel = "MINIMAL";
|
|
45300
|
+
thinkingConfig.includeThoughts = false;
|
|
45282
45301
|
break;
|
|
45283
45302
|
case "low":
|
|
45284
|
-
thinkingConfig.
|
|
45303
|
+
thinkingConfig.thinkingLevel = "LOW";
|
|
45285
45304
|
break;
|
|
45286
45305
|
case "medium":
|
|
45287
|
-
thinkingConfig.
|
|
45306
|
+
thinkingConfig.thinkingLevel = "MEDIUM";
|
|
45288
45307
|
break;
|
|
45289
45308
|
case "high":
|
|
45290
45309
|
case "xhigh":
|
|
45291
45310
|
case "max":
|
|
45292
|
-
thinkingConfig.
|
|
45311
|
+
thinkingConfig.thinkingLevel = "HIGH";
|
|
45293
45312
|
break;
|
|
45294
45313
|
}
|
|
45295
45314
|
else switch (effort) {
|
|
45296
45315
|
case "off":
|
|
45297
|
-
thinkingConfig.
|
|
45298
|
-
thinkingConfig.
|
|
45316
|
+
thinkingConfig.thinkingBudget = 0;
|
|
45317
|
+
thinkingConfig.includeThoughts = false;
|
|
45299
45318
|
break;
|
|
45300
45319
|
case "low":
|
|
45301
|
-
thinkingConfig.
|
|
45302
|
-
thinkingConfig.
|
|
45320
|
+
thinkingConfig.thinkingBudget = 1024;
|
|
45321
|
+
thinkingConfig.includeThoughts = true;
|
|
45303
45322
|
break;
|
|
45304
45323
|
case "medium":
|
|
45305
|
-
thinkingConfig.
|
|
45306
|
-
thinkingConfig.
|
|
45324
|
+
thinkingConfig.thinkingBudget = 4096;
|
|
45325
|
+
thinkingConfig.includeThoughts = true;
|
|
45307
45326
|
break;
|
|
45308
45327
|
case "high":
|
|
45309
45328
|
case "xhigh":
|
|
45310
45329
|
case "max":
|
|
45311
|
-
thinkingConfig.
|
|
45312
|
-
thinkingConfig.
|
|
45330
|
+
thinkingConfig.thinkingBudget = 32e3;
|
|
45331
|
+
thinkingConfig.includeThoughts = true;
|
|
45313
45332
|
break;
|
|
45314
45333
|
}
|
|
45315
|
-
return this.withGenerationKwargs({
|
|
45334
|
+
return this.withGenerationKwargs({ thinkingConfig });
|
|
45316
45335
|
}
|
|
45317
45336
|
withGenerationKwargs(kwargs) {
|
|
45318
45337
|
const clone = this._clone();
|
|
@@ -45323,7 +45342,7 @@ var init_google_genai = __esmMin((() => {
|
|
|
45323
45342
|
return clone;
|
|
45324
45343
|
}
|
|
45325
45344
|
withMaxCompletionTokens(maxCompletionTokens) {
|
|
45326
|
-
return this.withGenerationKwargs({
|
|
45345
|
+
return this.withGenerationKwargs({ maxOutputTokens: maxCompletionTokens });
|
|
45327
45346
|
}
|
|
45328
45347
|
_clone() {
|
|
45329
45348
|
const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
|
|
@@ -53449,6 +53468,7 @@ function convertMessage$2(message) {
|
|
|
53449
53468
|
});
|
|
53450
53469
|
if (message.toolCallId !== void 0) result.tool_call_id = message.toolCallId;
|
|
53451
53470
|
if (reasoningContent) result.reasoning_content = reasoningContent;
|
|
53471
|
+
if (message.tools !== void 0 && message.tools.length > 0) result.tools = message.tools.map((tool) => convertTool$1(tool));
|
|
53452
53472
|
return result;
|
|
53453
53473
|
}
|
|
53454
53474
|
function convertTool$1(tool) {
|
|
@@ -53828,6 +53848,7 @@ function convertHistoryMessages$1(history, reasoningKey, toolMessageConversion)
|
|
|
53828
53848
|
const messages = [];
|
|
53829
53849
|
const pendingToolResultMedia = [];
|
|
53830
53850
|
for (const msg of history) {
|
|
53851
|
+
if (isToolDeclarationOnlyMessage(msg)) continue;
|
|
53831
53852
|
if (msg.role !== "tool") appendToolResultMediaMessage(messages, pendingToolResultMedia);
|
|
53832
53853
|
messages.push(convertMessage$1(msg, reasoningKey, toolMessageConversion));
|
|
53833
53854
|
if (msg.role === "tool") pendingToolResultMedia.push(...toolResultImageParts(msg));
|
|
@@ -53837,6 +53858,7 @@ function convertHistoryMessages$1(history, reasoningKey, toolMessageConversion)
|
|
|
53837
53858
|
}
|
|
53838
53859
|
var KNOWN_REASONING_KEYS, DEFAULT_OUTBOUND_REASONING_KEY, CHAT_COMPLETIONS_MAX_OUTPUT_TOKENS_CEILING, OPENAI_CHAT_TOOL_CALL_ID_POLICY, OMITTED_AUDIO_PLACEHOLDER$1, OMITTED_VIDEO_PLACEHOLDER$1, OpenAILegacyStreamedMessage, OpenAILegacyChatProvider;
|
|
53839
53860
|
var init_openai_legacy = __esmMin((() => {
|
|
53861
|
+
init_message$3();
|
|
53840
53862
|
init_openai();
|
|
53841
53863
|
init_openai_common();
|
|
53842
53864
|
init_chat_completions_stream();
|
|
@@ -54435,6 +54457,7 @@ function convertHistoryMessages(history, modelName, toolMessageConversion) {
|
|
|
54435
54457
|
pendingToolResultMedia.length = 0;
|
|
54436
54458
|
};
|
|
54437
54459
|
for (const msg of history) {
|
|
54460
|
+
if (isToolDeclarationOnlyMessage(msg)) continue;
|
|
54438
54461
|
if (msg.role !== "tool") flushPendingMedia();
|
|
54439
54462
|
input.push(...convertMessage(msg, modelName, toolMessageConversion));
|
|
54440
54463
|
if (msg.role === "tool" && toolMessageConversion === "extract_text") pendingToolResultMedia.push(...messageContentToFunctionOutputItems(msg.content.filter(isMediaPart)));
|
|
@@ -54895,7 +54918,8 @@ function catalogModelToCapability(model) {
|
|
|
54895
54918
|
audio_in: inputs.includes("audio"),
|
|
54896
54919
|
thinking: Boolean(model.reasoning),
|
|
54897
54920
|
tool_use: model.tool_call ?? true,
|
|
54898
|
-
max_context_tokens: context
|
|
54921
|
+
max_context_tokens: context,
|
|
54922
|
+
select_tools: model.select_tools === true
|
|
54899
54923
|
}
|
|
54900
54924
|
};
|
|
54901
54925
|
}
|
|
@@ -54956,8 +54980,9 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
|
|
|
54956
54980
|
let pendingPart = null;
|
|
54957
54981
|
const toolCallIndexMap = /* @__PURE__ */ new Map();
|
|
54958
54982
|
if (options?.signal?.aborted) throwAbortError();
|
|
54983
|
+
const wireTools = tools.some((tool) => tool.deferred === true) ? tools.filter((tool) => tool.deferred !== true) : tools;
|
|
54959
54984
|
options?.onRequestStart?.();
|
|
54960
|
-
const stream = await provider.generate(systemPrompt,
|
|
54985
|
+
const stream = await provider.generate(systemPrompt, wireTools, history, options);
|
|
54961
54986
|
await throwIfAborted$1(options?.signal, stream);
|
|
54962
54987
|
let serverDecodeMs = 0;
|
|
54963
54988
|
let clientConsumeMs = 0;
|
|
@@ -61843,7 +61868,8 @@ var init_schema = __esmMin((() => {
|
|
|
61843
61868
|
ModelAliasSchema = ModelAliasBaseSchema.extend({ overrides: ModelAliasOverrideSchema.optional() });
|
|
61844
61869
|
ThinkingConfigSchema = object({
|
|
61845
61870
|
enabled: boolean$1().optional(),
|
|
61846
|
-
effort: string().optional()
|
|
61871
|
+
effort: string().optional(),
|
|
61872
|
+
keep: string().optional()
|
|
61847
61873
|
});
|
|
61848
61874
|
PermissionModeSchema = _enum([
|
|
61849
61875
|
"yolo",
|
|
@@ -68383,7 +68409,14 @@ var init_types$15 = __esmMin((() => {}));
|
|
|
68383
68409
|
//#region ../../packages/agent-core/src/flags/registry.ts
|
|
68384
68410
|
var FLAG_DEFINITIONS;
|
|
68385
68411
|
var init_registry$1 = __esmMin((() => {
|
|
68386
|
-
FLAG_DEFINITIONS = [
|
|
68412
|
+
FLAG_DEFINITIONS = [{
|
|
68413
|
+
id: "tool-select",
|
|
68414
|
+
title: "Tool select (progressive tool disclosure)",
|
|
68415
|
+
description: "Keep MCP tool schemas out of the immutable top-level tools[]; the model loads them on demand via the select_tools tool. Only takes effect on models whose capability catalog declares select_tools.",
|
|
68416
|
+
env: "KIMI_CODE_EXPERIMENTAL_TOOL_SELECT",
|
|
68417
|
+
default: false,
|
|
68418
|
+
surface: "core"
|
|
68419
|
+
}];
|
|
68387
68420
|
})), FlagResolver;
|
|
68388
68421
|
var init_resolver = __esmMin((() => {
|
|
68389
68422
|
init_resolve$1();
|
|
@@ -76785,6 +76818,102 @@ var init_background = __esmMin((() => {
|
|
|
76785
76818
|
};
|
|
76786
76819
|
}));
|
|
76787
76820
|
//#endregion
|
|
76821
|
+
//#region ../../packages/agent-core/src/agent/context/dynamic-tools.ts
|
|
76822
|
+
/** True for a message that loads tool definitions (`message.tools` present). */
|
|
76823
|
+
function isDynamicToolSchemaMessage(message) {
|
|
76824
|
+
return message.tools !== void 0 && message.tools.length > 0;
|
|
76825
|
+
}
|
|
76826
|
+
/** True for a `<tools_added>/<tools_removed>` announcement reminder. */
|
|
76827
|
+
function isLoadableToolsAnnouncement(message) {
|
|
76828
|
+
return message.origin?.kind === "system_trigger" && message.origin.name === "loadable-tools";
|
|
76829
|
+
}
|
|
76830
|
+
/**
|
|
76831
|
+
* Shape a history for a consumer that must not see dynamic-tool protocol
|
|
76832
|
+
* context: drop the loadable-tools announcements and strip `message.tools`
|
|
76833
|
+
* (dropping the message entirely when nothing else remains). Two callers:
|
|
76834
|
+
* - projection for a model without the `select_tools` capability (mid-session
|
|
76835
|
+
* model switch — the canonical history keeps its shape, only the outgoing
|
|
76836
|
+
* view changes; announcements would be noise and even reference a
|
|
76837
|
+
* select_tools tool the model does not have);
|
|
76838
|
+
* - the compaction summarizer input (schemas and announcements are protocol
|
|
76839
|
+
* context, not conversation — summarizing them wastes tokens and risks
|
|
76840
|
+
* leaking schema text into the summary).
|
|
76841
|
+
* Returns the input array unchanged when there is nothing to strip, so the
|
|
76842
|
+
* common no-dynamic-tools path costs one scan and no allocation.
|
|
76843
|
+
*/
|
|
76844
|
+
function stripDynamicToolContext(history) {
|
|
76845
|
+
if (!history.some((m) => isDynamicToolSchemaMessage(m) || isLoadableToolsAnnouncement(m))) return history;
|
|
76846
|
+
const out = [];
|
|
76847
|
+
for (const message of history) {
|
|
76848
|
+
if (isLoadableToolsAnnouncement(message)) continue;
|
|
76849
|
+
if (isDynamicToolSchemaMessage(message)) {
|
|
76850
|
+
const { tools: _tools, ...rest } = message;
|
|
76851
|
+
if (rest.content.length === 0 && rest.toolCalls.length === 0) continue;
|
|
76852
|
+
out.push(rest);
|
|
76853
|
+
continue;
|
|
76854
|
+
}
|
|
76855
|
+
out.push(message);
|
|
76856
|
+
}
|
|
76857
|
+
return out;
|
|
76858
|
+
}
|
|
76859
|
+
/** Union of tool names loaded by dynamic tool schema messages in `history`. */
|
|
76860
|
+
function collectLoadedDynamicToolNames(history) {
|
|
76861
|
+
const names = /* @__PURE__ */ new Set();
|
|
76862
|
+
for (const message of history) {
|
|
76863
|
+
if (message.tools === void 0) continue;
|
|
76864
|
+
for (const tool of message.tools) names.add(tool.name);
|
|
76865
|
+
}
|
|
76866
|
+
return names;
|
|
76867
|
+
}
|
|
76868
|
+
/**
|
|
76869
|
+
* Fold every loadable-tools announcement in `history`, in order, into the
|
|
76870
|
+
* currently-announced name set (`tools_removed` deletes, then `tools_added`
|
|
76871
|
+
* adds — last wins). The announcements are the context's own record of what
|
|
76872
|
+
* the model has been told is loadable; there is deliberately no separate
|
|
76873
|
+
* persisted ledger, so undo/compaction/resume all self-heal by re-folding.
|
|
76874
|
+
*/
|
|
76875
|
+
function foldAnnouncedToolNames(history) {
|
|
76876
|
+
const announced = /* @__PURE__ */ new Set();
|
|
76877
|
+
for (const message of history) {
|
|
76878
|
+
if (!isLoadableToolsAnnouncement(message)) continue;
|
|
76879
|
+
const text = message.content.map((part) => part.type === "text" ? part.text : "").join("");
|
|
76880
|
+
for (const name of matchToolNameBlocks(text, TOOLS_REMOVED_BLOCK)) announced.delete(name);
|
|
76881
|
+
for (const name of matchToolNameBlocks(text, TOOLS_ADDED_BLOCK)) announced.add(name);
|
|
76882
|
+
}
|
|
76883
|
+
return announced;
|
|
76884
|
+
}
|
|
76885
|
+
function matchToolNameBlocks(text, pattern) {
|
|
76886
|
+
const names = [];
|
|
76887
|
+
pattern.lastIndex = 0;
|
|
76888
|
+
for (const match of text.matchAll(pattern)) {
|
|
76889
|
+
const body = match[1] ?? "";
|
|
76890
|
+
for (const line of body.split("\n")) {
|
|
76891
|
+
const name = line.trim();
|
|
76892
|
+
if (name.length > 0) names.push(name);
|
|
76893
|
+
}
|
|
76894
|
+
}
|
|
76895
|
+
return names;
|
|
76896
|
+
}
|
|
76897
|
+
/**
|
|
76898
|
+
* Render one diff announcement. Only the blocks with content are emitted; the
|
|
76899
|
+
* guidance sentence never contains a literal block tag, so `foldAnnouncedToolNames`
|
|
76900
|
+
* can anchor on the tags without tripping over prose.
|
|
76901
|
+
*/
|
|
76902
|
+
function renderLoadableToolsAnnouncement(added, removed) {
|
|
76903
|
+
const sections = [];
|
|
76904
|
+
if (added.length > 0) sections.push(`<tools_added>\n${added.join("\n")}\n</tools_added>`);
|
|
76905
|
+
if (removed.length > 0) sections.push(`<tools_removed>\n${removed.join("\n")}\n</tools_removed>`);
|
|
76906
|
+
sections.push("Use the select_tools tool with exact names to load full tool definitions before calling them. Names listed as removed are no longer loadable — do not select them. Fold all announcements in this conversation in order to get the current list.");
|
|
76907
|
+
return sections.join("\n\n");
|
|
76908
|
+
}
|
|
76909
|
+
var DYNAMIC_TOOL_SCHEMA_VARIANT, LOADABLE_TOOLS_TRIGGER, TOOLS_ADDED_BLOCK, TOOLS_REMOVED_BLOCK;
|
|
76910
|
+
var init_dynamic_tools = __esmMin((() => {
|
|
76911
|
+
DYNAMIC_TOOL_SCHEMA_VARIANT = "dynamic_tool_schema";
|
|
76912
|
+
LOADABLE_TOOLS_TRIGGER = "loadable-tools";
|
|
76913
|
+
TOOLS_ADDED_BLOCK = /<tools_added>\n?([\s\S]*?)\n?<\/tools_added>/g;
|
|
76914
|
+
TOOLS_REMOVED_BLOCK = /<tools_removed>\n?([\s\S]*?)\n?<\/tools_removed>/g;
|
|
76915
|
+
}));
|
|
76916
|
+
//#endregion
|
|
76788
76917
|
//#region ../../packages/agent-core/src/utils/abort.ts
|
|
76789
76918
|
function abortError$1(message = "Aborted") {
|
|
76790
76919
|
const error = new Error(message);
|
|
@@ -77089,6 +77218,7 @@ function estimateTokensForMessage(message) {
|
|
|
77089
77218
|
total += estimateTokens$1(call.name);
|
|
77090
77219
|
total += estimateTokens$1(JSON.stringify(call.arguments));
|
|
77091
77220
|
}
|
|
77221
|
+
if (message.tools !== void 0) total += estimateTokensForTools(message.tools);
|
|
77092
77222
|
messageTokenEstimateCache.set(message, total);
|
|
77093
77223
|
return total;
|
|
77094
77224
|
}
|
|
@@ -77492,6 +77622,7 @@ var DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS, OVERFLOW_CONTEXT_SAFETY_RATIO, OVE
|
|
|
77492
77622
|
var init_full = __esmMin((() => {
|
|
77493
77623
|
init_errors$8();
|
|
77494
77624
|
init_src$4();
|
|
77625
|
+
init_dynamic_tools();
|
|
77495
77626
|
init_errors$5();
|
|
77496
77627
|
init_retry();
|
|
77497
77628
|
init_todo_list$1();
|
|
@@ -77600,7 +77731,7 @@ var init_full = __esmMin((() => {
|
|
|
77600
77731
|
return this.agent.context.tokenCountWithPending;
|
|
77601
77732
|
}
|
|
77602
77733
|
estimateRequestTokens(messages) {
|
|
77603
|
-
return estimateTokens$1(this.agent.config.systemPrompt) + estimateTokensForTools(this.agent.tools.loopTools) + estimateTokensForMessages(messages);
|
|
77734
|
+
return estimateTokens$1(this.agent.config.systemPrompt) + estimateTokensForTools(this.agent.tools.loopTools.filter((t) => t.deferred !== true)) + estimateTokensForMessages(messages);
|
|
77604
77735
|
}
|
|
77605
77736
|
resetForTurn() {
|
|
77606
77737
|
this.compactionCountInTurn = 0;
|
|
@@ -77665,6 +77796,7 @@ var init_full = __esmMin((() => {
|
|
|
77665
77796
|
this.agent.log.error("failed to refresh system prompt after compaction", { error });
|
|
77666
77797
|
}
|
|
77667
77798
|
await this.agent.injection.injectAfterCompaction();
|
|
77799
|
+
this.lastCompactedTokenCount = this.tokenCountWithPending;
|
|
77668
77800
|
this.markCompleted();
|
|
77669
77801
|
const { contextSummary: _contextSummary, ...eventResult } = result;
|
|
77670
77802
|
this.agent.emitEvent({
|
|
@@ -77689,6 +77821,57 @@ var init_full = __esmMin((() => {
|
|
|
77689
77821
|
buildInstruction(customInstruction) {
|
|
77690
77822
|
return renderPrompt(compaction_instruction_default, { customInstruction: customInstruction?.trim() ?? "" }).trimEnd();
|
|
77691
77823
|
}
|
|
77824
|
+
/**
|
|
77825
|
+
* Keep-all rebuild (Phase 1): after compaction folded the history — and the
|
|
77826
|
+
* dynamic tool schema messages with it — append ONE merged schema message so
|
|
77827
|
+
* the model keeps calling its loaded tools without re-selecting. Schemas are
|
|
77828
|
+
* read from the live registry, never copied from the old history, so a
|
|
77829
|
+
* schema that changed since load self-heals here. Names whose server is
|
|
77830
|
+
* currently disconnected have no registry schema and are not rebuilt (the
|
|
77831
|
+
* model re-selects after reconnect); names that survived into the
|
|
77832
|
+
* post-compaction history (none under today's users+summary rebuild, but
|
|
77833
|
+
* guarded) are not duplicated. The message goes through the normal
|
|
77834
|
+
* injection-origin append, so estimation and records pick it up as usual.
|
|
77835
|
+
*
|
|
77836
|
+
* Budget guard: the rebuilt floor (users + summary + schemas) is the one
|
|
77837
|
+
* part of the post-compaction context that compaction itself can never
|
|
77838
|
+
* shrink — if it lands inside the auto-compaction trigger band, every
|
|
77839
|
+
* following step re-compacts and rebuilds in a loop. Admit schemas (in name
|
|
77840
|
+
* order) only while the projected context stays within HALF the compaction
|
|
77841
|
+
* trigger, so normal turn content still fits before the next compaction;
|
|
77842
|
+
* anything dropped is simply re-selectable on demand, the same degradation
|
|
77843
|
+
* as a disconnected server.
|
|
77844
|
+
*/
|
|
77845
|
+
rebuildDynamicToolSchemas(activeBefore) {
|
|
77846
|
+
if (!this.agent.toolSelectEnabled) return;
|
|
77847
|
+
if (activeBefore.size === 0) return;
|
|
77848
|
+
const surviving = collectLoadedDynamicToolNames(this.agent.context.history);
|
|
77849
|
+
const candidates = [...activeBefore].filter((name) => !surviving.has(name)).toSorted((a, b) => a.localeCompare(b)).map((name) => this.agent.tools.getMcpToolSchema(name)).filter((tool) => tool !== void 0);
|
|
77850
|
+
if (candidates.length === 0) return;
|
|
77851
|
+
const tools = [];
|
|
77852
|
+
let projected = this.tokenCountWithPending;
|
|
77853
|
+
for (const tool of candidates) {
|
|
77854
|
+
const toolTokens = estimateTokensForTools([tool]);
|
|
77855
|
+
if (this.strategy.shouldCompact((projected + toolTokens) * 2)) break;
|
|
77856
|
+
tools.push(tool);
|
|
77857
|
+
projected += toolTokens;
|
|
77858
|
+
}
|
|
77859
|
+
if (tools.length < candidates.length) this.agent.log.info("trimmed dynamic tool schema rebuild to stay clear of the compaction trigger", {
|
|
77860
|
+
kept: tools.length,
|
|
77861
|
+
dropped: candidates.slice(tools.length).map((tool) => tool.name)
|
|
77862
|
+
});
|
|
77863
|
+
if (tools.length === 0) return;
|
|
77864
|
+
this.agent.context.appendMessage({
|
|
77865
|
+
role: "system",
|
|
77866
|
+
content: [],
|
|
77867
|
+
toolCalls: [],
|
|
77868
|
+
tools,
|
|
77869
|
+
origin: {
|
|
77870
|
+
kind: "injection",
|
|
77871
|
+
variant: DYNAMIC_TOOL_SCHEMA_VARIANT
|
|
77872
|
+
}
|
|
77873
|
+
});
|
|
77874
|
+
}
|
|
77692
77875
|
postProcessSummary(summary) {
|
|
77693
77876
|
const todos = this.agent.tools.storeData()["todo"] ?? [];
|
|
77694
77877
|
if (todos.length === 0) return summary;
|
|
@@ -77699,6 +77882,7 @@ var init_full = __esmMin((() => {
|
|
|
77699
77882
|
const startedAt = Date.now();
|
|
77700
77883
|
const originalHistory = [...this.agent.context.history];
|
|
77701
77884
|
const tokensBefore = estimateTokensForMessages(originalHistory);
|
|
77885
|
+
const activeDynamicToolsBefore = new Set(this.agent.tools.loadedDynamicToolNames());
|
|
77702
77886
|
let retryCount = 0;
|
|
77703
77887
|
try {
|
|
77704
77888
|
await this.triggerPreCompactHook(data, tokensBefore, signal);
|
|
@@ -77718,7 +77902,7 @@ var init_full = __esmMin((() => {
|
|
|
77718
77902
|
const delays = retryBackoffDelays(5);
|
|
77719
77903
|
let usage = null;
|
|
77720
77904
|
let summary;
|
|
77721
|
-
let historyForModel = originalHistory;
|
|
77905
|
+
let historyForModel = stripDynamicToolContext(originalHistory);
|
|
77722
77906
|
let droppedCount = 0;
|
|
77723
77907
|
let overflowShrinkCount = 0;
|
|
77724
77908
|
let emptyOrTruncatedShrinkCount = 0;
|
|
@@ -77780,6 +77964,7 @@ var init_full = __esmMin((() => {
|
|
|
77780
77964
|
tokensBefore,
|
|
77781
77965
|
droppedCount: droppedCount === 0 ? void 0 : droppedCount
|
|
77782
77966
|
});
|
|
77967
|
+
this.rebuildDynamicToolSchemas(activeDynamicToolsBefore);
|
|
77783
77968
|
this.agent.telemetry.track("compaction_finished", {
|
|
77784
77969
|
source: data.source,
|
|
77785
77970
|
tokens_before: result.tokensBefore,
|
|
@@ -77795,7 +77980,7 @@ var init_full = __esmMin((() => {
|
|
|
77795
77980
|
output_tokens: usage.output
|
|
77796
77981
|
}
|
|
77797
77982
|
});
|
|
77798
|
-
this.lastCompactedTokenCount =
|
|
77983
|
+
this.lastCompactedTokenCount = this.tokenCountWithPending;
|
|
77799
77984
|
return result;
|
|
77800
77985
|
} catch (error) {
|
|
77801
77986
|
if (isAbortError$3(error)) return void 0;
|
|
@@ -79222,23 +79407,64 @@ function applyKimiEnvThinkingEffort(provider, thinkingEffort, env = process.env)
|
|
|
79222
79407
|
return provider.withExtraBody({ thinking: { effort } });
|
|
79223
79408
|
}
|
|
79224
79409
|
/**
|
|
79225
|
-
*
|
|
79226
|
-
*
|
|
79227
|
-
*
|
|
79228
|
-
*
|
|
79229
|
-
|
|
79410
|
+
* Parse a single keep source (env var or config field). A blank value is
|
|
79411
|
+
* "unspecified" and falls through to the next source; an off-value explicitly
|
|
79412
|
+
* disables Preserved Thinking (short-circuits, no fallback); anything else is
|
|
79413
|
+
* forwarded verbatim (e.g. "all").
|
|
79414
|
+
*/
|
|
79415
|
+
function parseKeepValue(raw) {
|
|
79416
|
+
const trimmed = raw?.trim();
|
|
79417
|
+
if (trimmed === void 0 || trimmed.length === 0) return { specified: false };
|
|
79418
|
+
if (KEEP_OFF_VALUES.has(trimmed.toLowerCase())) return {
|
|
79419
|
+
specified: true,
|
|
79420
|
+
value: void 0
|
|
79421
|
+
};
|
|
79422
|
+
return {
|
|
79423
|
+
specified: true,
|
|
79424
|
+
value: trimmed
|
|
79425
|
+
};
|
|
79426
|
+
}
|
|
79427
|
+
/**
|
|
79428
|
+
* Resolve the Moonshot Preserved Thinking passthrough (`thinking.keep`) with
|
|
79429
|
+
* precedence env (`KIMI_MODEL_THINKING_KEEP`) > config (`thinking.keep`) >
|
|
79430
|
+
* default `"all"`. Only meaningful while thinking is on — otherwise the API
|
|
79431
|
+
* would receive a `thinking.keep` with no accompanying `thinking.type` it
|
|
79432
|
+
* honors. (Compaction uses a raw provider with thinking off, so it correctly
|
|
79433
|
+
* resolves to `undefined`.)
|
|
79230
79434
|
*
|
|
79231
|
-
*
|
|
79435
|
+
* Returns `undefined` when Preserved Thinking should be disabled.
|
|
79436
|
+
*/
|
|
79437
|
+
function resolveThinkingKeep(env, configKeep, thinkingEffort) {
|
|
79438
|
+
if (thinkingEffort === "off") return void 0;
|
|
79439
|
+
const fromEnv = parseKeepValue(env["KIMI_MODEL_THINKING_KEEP"]);
|
|
79440
|
+
if (fromEnv.specified) return fromEnv.value;
|
|
79441
|
+
const fromConfig = parseKeepValue(configKeep);
|
|
79442
|
+
if (fromConfig.specified) return fromConfig.value;
|
|
79443
|
+
return "all";
|
|
79444
|
+
}
|
|
79445
|
+
/**
|
|
79446
|
+
* Apply the Moonshot Preserved Thinking passthrough to a chat provider. See
|
|
79447
|
+
* `resolveThinkingKeep` for precedence. Non-Kimi providers are returned
|
|
79448
|
+
* unchanged.
|
|
79232
79449
|
*/
|
|
79233
|
-
function applyKimiEnvThinkingKeep(provider, thinkingEffort, env = process.env) {
|
|
79450
|
+
function applyKimiEnvThinkingKeep(provider, thinkingEffort, env = process.env, configKeep) {
|
|
79234
79451
|
if (!(provider instanceof KimiChatProvider)) return provider;
|
|
79235
|
-
const keep = env
|
|
79236
|
-
if (keep === void 0
|
|
79452
|
+
const keep = resolveThinkingKeep(env, configKeep, thinkingEffort);
|
|
79453
|
+
if (keep === void 0) return provider;
|
|
79237
79454
|
return provider.withExtraBody({ thinking: { keep } });
|
|
79238
79455
|
}
|
|
79456
|
+
var KEEP_OFF_VALUES;
|
|
79239
79457
|
var init_kimi_env_params = __esmMin((() => {
|
|
79240
79458
|
init_src$4();
|
|
79241
79459
|
init_resolve$1();
|
|
79460
|
+
KEEP_OFF_VALUES = new Set([
|
|
79461
|
+
"0",
|
|
79462
|
+
"false",
|
|
79463
|
+
"no",
|
|
79464
|
+
"off",
|
|
79465
|
+
"none",
|
|
79466
|
+
"null"
|
|
79467
|
+
]);
|
|
79242
79468
|
}));
|
|
79243
79469
|
//#endregion
|
|
79244
79470
|
//#region ../../packages/agent-core/src/agent/config/thinking.ts
|
|
@@ -79364,7 +79590,7 @@ var init_config$3 = __esmMin((() => {
|
|
|
79364
79590
|
return provider;
|
|
79365
79591
|
}
|
|
79366
79592
|
get provider() {
|
|
79367
|
-
return applyKimiEnvThinkingKeep(applyKimiEnvThinkingEffort(applyKimiEnvSamplingParams(createProvider(this.providerConfig).withThinking(this.thinkingEffort)), this.thinkingEffort), this.thinkingEffort);
|
|
79593
|
+
return applyKimiEnvThinkingKeep(applyKimiEnvThinkingEffort(applyKimiEnvSamplingParams(createProvider(this.providerConfig).withThinking(this.thinkingEffort)), this.thinkingEffort), this.thinkingEffort, void 0, this.agent.kimiConfig?.thinking?.keep);
|
|
79368
79594
|
}
|
|
79369
79595
|
get model() {
|
|
79370
79596
|
if (this._modelAlias === void 0) throw new KimiError(ErrorCodes.MODEL_NOT_CONFIGURED, "Model not set");
|
|
@@ -122000,6 +122226,7 @@ function prepareMessageForProjection(message, onAnomaly) {
|
|
|
122000
122226
|
content
|
|
122001
122227
|
};
|
|
122002
122228
|
if (next.role === "tool" && next.content.length === 0) throw new KimiError(ErrorCodes.REQUEST_INVALID, "Tool result message content cannot be empty after removing empty text blocks.", { details: { toolCallId: next.toolCallId } });
|
|
122229
|
+
if (next.tools !== void 0 && next.tools.length > 0) return next;
|
|
122003
122230
|
return next.content.length === 0 && next.toolCalls.length === 0 ? null : next;
|
|
122004
122231
|
}
|
|
122005
122232
|
function canMergeUserMessage(message) {
|
|
@@ -122029,7 +122256,8 @@ function stripContextMetadata(message) {
|
|
|
122029
122256
|
content: message.content.map((p) => ({ ...p })),
|
|
122030
122257
|
toolCalls: message.toolCalls.map((tc) => ({ ...tc })),
|
|
122031
122258
|
toolCallId: message.toolCallId,
|
|
122032
|
-
partial: message.partial
|
|
122259
|
+
partial: message.partial,
|
|
122260
|
+
tools: message.tools?.map((tool) => ({ ...tool }))
|
|
122033
122261
|
};
|
|
122034
122262
|
}
|
|
122035
122263
|
function trimTrailingOpenToolExchange(history) {
|
|
@@ -122120,8 +122348,10 @@ var init_context$2 = __esmMin((() => {
|
|
|
122120
122348
|
init_xml_escape();
|
|
122121
122349
|
init_compaction();
|
|
122122
122350
|
init_projector();
|
|
122351
|
+
init_dynamic_tools();
|
|
122123
122352
|
init_types$8();
|
|
122124
122353
|
init_types$8();
|
|
122354
|
+
init_dynamic_tools();
|
|
122125
122355
|
TOOL_ERROR_STATUS$2 = "<system>ERROR: Tool execution failed.</system>";
|
|
122126
122356
|
TOOL_EMPTY_STATUS$2 = "<system>Tool output is empty.</system>";
|
|
122127
122357
|
TOOL_EMPTY_ERROR_STATUS$2 = "<system>ERROR: Tool execution failed. Tool output is empty.</system>";
|
|
@@ -122259,6 +122489,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
122259
122489
|
this._lastAssistantAt = null;
|
|
122260
122490
|
this.agent.microCompaction.reset();
|
|
122261
122491
|
this.agent.injection.onContextClear();
|
|
122492
|
+
this.agent.tools.onContextCleared();
|
|
122262
122493
|
this.agent.emitStatusUpdated();
|
|
122263
122494
|
}
|
|
122264
122495
|
undo(count) {
|
|
@@ -122375,6 +122606,7 @@ var init_context$2 = __esmMin((() => {
|
|
|
122375
122606
|
this.tokenCountCoveredMessageCount = this._history.length;
|
|
122376
122607
|
this.agent.microCompaction.reset();
|
|
122377
122608
|
this.agent.injection.onContextCompacted();
|
|
122609
|
+
this.agent.tools.onContextCompacted();
|
|
122378
122610
|
this.agent.emitStatusUpdated();
|
|
122379
122611
|
return result;
|
|
122380
122612
|
}
|
|
@@ -122395,8 +122627,9 @@ var init_context$2 = __esmMin((() => {
|
|
|
122395
122627
|
return this._history;
|
|
122396
122628
|
}
|
|
122397
122629
|
project(messages, options) {
|
|
122630
|
+
const shaped = this.agent.toolSelectEnabled ? messages : stripDynamicToolContext(messages);
|
|
122398
122631
|
const anomalies = [];
|
|
122399
|
-
const result = project(this.agent.microCompaction.compact(
|
|
122632
|
+
const result = project(this.agent.microCompaction.compact(shaped), {
|
|
122400
122633
|
...options,
|
|
122401
122634
|
onAnomaly: (anomaly) => {
|
|
122402
122635
|
anomalies.push(anomaly);
|
|
@@ -122555,7 +122788,8 @@ var init_context$2 = __esmMin((() => {
|
|
|
122555
122788
|
type: "function",
|
|
122556
122789
|
id: event.toolCallId,
|
|
122557
122790
|
name: event.name,
|
|
122558
|
-
arguments: event.args === void 0 ? null : JSON.stringify(event.args)
|
|
122791
|
+
arguments: event.args === void 0 ? null : JSON.stringify(event.args),
|
|
122792
|
+
extras: event.extras
|
|
122559
122793
|
});
|
|
122560
122794
|
this.pendingToolResultIds.add(event.toolCallId);
|
|
122561
122795
|
return;
|
|
@@ -124231,6 +124465,37 @@ var init_todo_list = __esmMin((() => {
|
|
|
124231
124465
|
};
|
|
124232
124466
|
}));
|
|
124233
124467
|
//#endregion
|
|
124468
|
+
//#region ../../packages/agent-core/src/agent/injection/tools-diff.ts
|
|
124469
|
+
var ToolsDiffInjector;
|
|
124470
|
+
var init_tools_diff = __esmMin((() => {
|
|
124471
|
+
init_dynamic_tools();
|
|
124472
|
+
ToolsDiffInjector = class {
|
|
124473
|
+
agent;
|
|
124474
|
+
constructor(agent) {
|
|
124475
|
+
this.agent = agent;
|
|
124476
|
+
}
|
|
124477
|
+
/**
|
|
124478
|
+
* Recompute the loadable set, fold the announced set from history, and
|
|
124479
|
+
* append one diff announcement iff they differ. Most turns append nothing,
|
|
124480
|
+
* keeping the prompt cache warm; the first announcement after session start
|
|
124481
|
+
* (or after compaction folded the history) is naturally the full list.
|
|
124482
|
+
*/
|
|
124483
|
+
inject() {
|
|
124484
|
+
if (!this.agent.toolSelectEnabled) return;
|
|
124485
|
+
const loadable = this.agent.tools.loadableDynamicToolNames();
|
|
124486
|
+
const loadableSet = new Set(loadable);
|
|
124487
|
+
const announced = foldAnnouncedToolNames(this.agent.context.history);
|
|
124488
|
+
const added = loadable.filter((name) => !announced.has(name));
|
|
124489
|
+
const removed = [...announced].filter((name) => !loadableSet.has(name)).toSorted((a, b) => a.localeCompare(b));
|
|
124490
|
+
if (added.length === 0 && removed.length === 0) return;
|
|
124491
|
+
this.agent.context.appendSystemReminder(renderLoadableToolsAnnouncement(added, removed), {
|
|
124492
|
+
kind: "system_trigger",
|
|
124493
|
+
name: LOADABLE_TOOLS_TRIGGER
|
|
124494
|
+
});
|
|
124495
|
+
}
|
|
124496
|
+
};
|
|
124497
|
+
}));
|
|
124498
|
+
//#endregion
|
|
124234
124499
|
//#region ../../packages/agent-core/src/agent/injection/manager.ts
|
|
124235
124500
|
var ACTIVE_BACKGROUND_TASK_GUIDANCE, InjectionManager;
|
|
124236
124501
|
var init_manager$1 = __esmMin((() => {
|
|
@@ -124240,11 +124505,13 @@ var init_manager$1 = __esmMin((() => {
|
|
|
124240
124505
|
init_plugin_session_start();
|
|
124241
124506
|
init_plan_mode();
|
|
124242
124507
|
init_todo_list();
|
|
124508
|
+
init_tools_diff();
|
|
124243
124509
|
ACTIVE_BACKGROUND_TASK_GUIDANCE = "The conversation was compacted, so the earlier messages that started these background tasks are gone — but the tasks are still running from before. Do not start duplicates. Use TaskOutput to fetch a task’s result, TaskList to list them, and TaskStop to cancel one.";
|
|
124244
124510
|
InjectionManager = class {
|
|
124245
124511
|
agent;
|
|
124246
124512
|
injectors;
|
|
124247
124513
|
goalInjector;
|
|
124514
|
+
toolsDiffInjector;
|
|
124248
124515
|
constructor(agent) {
|
|
124249
124516
|
this.agent = agent;
|
|
124250
124517
|
this.injectors = [
|
|
@@ -124254,6 +124521,7 @@ var init_manager$1 = __esmMin((() => {
|
|
|
124254
124521
|
new PermissionModeInjector(agent)
|
|
124255
124522
|
];
|
|
124256
124523
|
this.goalInjector = agent.type === "main" ? new GoalInjector(agent) : null;
|
|
124524
|
+
this.toolsDiffInjector = new ToolsDiffInjector(agent);
|
|
124257
124525
|
}
|
|
124258
124526
|
async inject() {
|
|
124259
124527
|
for (const injector of this.injectors) await injector.inject();
|
|
@@ -124266,8 +124534,17 @@ var init_manager$1 = __esmMin((() => {
|
|
|
124266
124534
|
async injectGoal() {
|
|
124267
124535
|
await this.activeGoalInjector()?.inject();
|
|
124268
124536
|
}
|
|
124537
|
+
/**
|
|
124538
|
+
* Appends a loadable-tools diff announcement when the loadable set changed.
|
|
124539
|
+
* Boundary cadence (turn start + post-compaction); no-op when the disclosure
|
|
124540
|
+
* gate is closed or nothing changed.
|
|
124541
|
+
*/
|
|
124542
|
+
injectToolsDiff() {
|
|
124543
|
+
this.toolsDiffInjector.inject();
|
|
124544
|
+
}
|
|
124269
124545
|
async injectAfterCompaction() {
|
|
124270
124546
|
await this.injectGoal();
|
|
124547
|
+
this.injectToolsDiff();
|
|
124271
124548
|
this.injectActiveBackgroundTasks();
|
|
124272
124549
|
await this.inject();
|
|
124273
124550
|
}
|
|
@@ -124396,7 +124673,8 @@ var init_default_tool_approve = __esmMin((() => {
|
|
|
124396
124673
|
"Skill",
|
|
124397
124674
|
"GetGoal",
|
|
124398
124675
|
"SetGoalBudget",
|
|
124399
|
-
"UpdateGoal"
|
|
124676
|
+
"UpdateGoal",
|
|
124677
|
+
"select_tools"
|
|
124400
124678
|
]);
|
|
124401
124679
|
DefaultToolApprovePermissionPolicy = class {
|
|
124402
124680
|
name = "default-tool-approve";
|
|
@@ -134788,7 +135066,7 @@ function preflightToolCall(step, toolCall) {
|
|
|
134788
135066
|
toolCall,
|
|
134789
135067
|
toolName,
|
|
134790
135068
|
args: parsedArgs.data,
|
|
134791
|
-
output: `Tool "${toolName}" not found`
|
|
135069
|
+
output: step.describeMissingTool?.(toolName) ?? `Tool "${toolName}" not found`
|
|
134792
135070
|
};
|
|
134793
135071
|
if (parsedArgs.parseFailed) step.log?.debug("tool args JSON parse failed", {
|
|
134794
135072
|
toolName,
|
|
@@ -135157,7 +135435,8 @@ async function dispatchToolCall(step, call, args, displayFields) {
|
|
|
135157
135435
|
name: toolName,
|
|
135158
135436
|
args,
|
|
135159
135437
|
description: displayFields?.description,
|
|
135160
|
-
display: displayFields?.display
|
|
135438
|
+
display: displayFields?.display,
|
|
135439
|
+
extras: toolCall.extras
|
|
135161
135440
|
});
|
|
135162
135441
|
}
|
|
135163
135442
|
var GRACE_TIMEOUT_MS, TOOL_OUTPUT_EMPTY, TOOL_OUTPUT_NON_TEXT, validators;
|
|
@@ -135185,7 +135464,7 @@ var init_tool_call = __esmMin((() => {
|
|
|
135185
135464
|
* does not lose model usage that was already spent.
|
|
135186
135465
|
*/
|
|
135187
135466
|
async function executeLoopStep(deps) {
|
|
135188
|
-
const { turnId, signal, buildMessages, buildMessagesStrict, dispatchEvent, llm, tools, hooks, log, currentStep, maxRetryAttempts, recordUsage } = deps;
|
|
135467
|
+
const { turnId, signal, buildMessages, buildMessagesStrict, dispatchEvent, llm, tools, buildTools, describeMissingTool, hooks, log, currentStep, maxRetryAttempts, recordUsage } = deps;
|
|
135189
135468
|
if (hooks?.beforeStep !== void 0) {
|
|
135190
135469
|
const beforeStep = await hooks.beforeStep({
|
|
135191
135470
|
turnId,
|
|
@@ -135196,11 +135475,13 @@ async function executeLoopStep(deps) {
|
|
|
135196
135475
|
if (beforeStep?.block === true) throw new Error(beforeStep.reason ?? `Step ${String(currentStep)} was blocked`);
|
|
135197
135476
|
}
|
|
135198
135477
|
signal.throwIfAborted();
|
|
135478
|
+
const stepTools = buildTools !== void 0 ? buildTools() : tools;
|
|
135199
135479
|
const messages = await buildMessages();
|
|
135200
135480
|
signal.throwIfAborted();
|
|
135201
135481
|
const stepUuid = randomUUID();
|
|
135202
135482
|
const step = {
|
|
135203
|
-
tools,
|
|
135483
|
+
tools: stepTools,
|
|
135484
|
+
describeMissingTool,
|
|
135204
135485
|
hooks,
|
|
135205
135486
|
log,
|
|
135206
135487
|
dispatchEvent,
|
|
@@ -135218,7 +135499,7 @@ async function executeLoopStep(deps) {
|
|
|
135218
135499
|
});
|
|
135219
135500
|
const chatParams = {
|
|
135220
135501
|
messages,
|
|
135221
|
-
tools:
|
|
135502
|
+
tools: stepTools ?? [],
|
|
135222
135503
|
signal,
|
|
135223
135504
|
...createChatStreamingCallbacks({
|
|
135224
135505
|
dispatchEvent,
|
|
@@ -135408,7 +135689,7 @@ var init_turn_step = __esmMin((() => {
|
|
|
135408
135689
|
//#endregion
|
|
135409
135690
|
//#region ../../packages/agent-core/src/loop/run-turn.ts
|
|
135410
135691
|
async function runTurn(input) {
|
|
135411
|
-
const { turnId, signal, llm, buildMessages, buildMessagesStrict, dispatchEvent, tools, hooks, log, maxSteps, maxRetryAttempts, recordStepUsage: hostRecordStepUsage } = input;
|
|
135692
|
+
const { turnId, signal, llm, buildMessages, buildMessagesStrict, dispatchEvent, tools, buildTools, describeMissingTool, hooks, log, maxSteps, maxRetryAttempts, recordStepUsage: hostRecordStepUsage } = input;
|
|
135412
135693
|
let usage = emptyUsage();
|
|
135413
135694
|
let steps = 0;
|
|
135414
135695
|
let stopReason = "end_turn";
|
|
@@ -135431,6 +135712,8 @@ async function runTurn(input) {
|
|
|
135431
135712
|
dispatchEvent,
|
|
135432
135713
|
llm,
|
|
135433
135714
|
tools,
|
|
135715
|
+
buildTools,
|
|
135716
|
+
describeMissingTool,
|
|
135434
135717
|
hooks,
|
|
135435
135718
|
log,
|
|
135436
135719
|
currentStep: steps,
|
|
@@ -135452,7 +135735,8 @@ async function runTurn(input) {
|
|
|
135452
135735
|
}
|
|
135453
135736
|
} catch (error) {
|
|
135454
135737
|
if (isAbortError$3(error) || signal.aborted) {
|
|
135455
|
-
|
|
135738
|
+
const interruptReason = isUserCancellation(signal.reason) || isUserCancellation(error) ? "user_cancelled" : "aborted";
|
|
135739
|
+
dispatchEvent(makeInterruptedEvent("aborted", steps, activeStep, void 0, interruptReason));
|
|
135456
135740
|
return {
|
|
135457
135741
|
stopReason: "aborted",
|
|
135458
135742
|
steps,
|
|
@@ -135468,17 +135752,19 @@ async function runTurn(input) {
|
|
|
135468
135752
|
usage
|
|
135469
135753
|
};
|
|
135470
135754
|
}
|
|
135471
|
-
function makeInterruptedEvent(reason, attemptedSteps, activeStep, message) {
|
|
135755
|
+
function makeInterruptedEvent(reason, attemptedSteps, activeStep, message, interruptReason = reason) {
|
|
135472
135756
|
return {
|
|
135473
135757
|
type: "turn.interrupted",
|
|
135474
135758
|
reason,
|
|
135475
135759
|
attemptedSteps,
|
|
135476
135760
|
...activeStep !== void 0 ? { activeStep } : {},
|
|
135477
|
-
...message !== void 0 ? { message } : {}
|
|
135761
|
+
...message !== void 0 ? { message } : {},
|
|
135762
|
+
interruptReason
|
|
135478
135763
|
};
|
|
135479
135764
|
}
|
|
135480
135765
|
var init_run_turn = __esmMin((() => {
|
|
135481
135766
|
init_src$4();
|
|
135767
|
+
init_abort();
|
|
135482
135768
|
init_errors$5();
|
|
135483
135769
|
init_turn_step();
|
|
135484
135770
|
}));
|
|
@@ -143669,10 +143955,30 @@ var init_agent_swarm = __esmMin((() => {
|
|
|
143669
143955
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/ask-user.md?raw
|
|
143670
143956
|
var ask_user_default;
|
|
143671
143957
|
var init_ask_user$1 = __esmMin((() => {
|
|
143672
|
-
ask_user_default = "Use this tool when you need to ask the user questions with structured options during execution. This allows you to:\n1. Collect user preferences or requirements before proceeding\n2. Resolve ambiguous or underspecified instructions\n3. Let the user decide between implementation approaches as you work\n4. Present concrete options when multiple valid directions exist\n\n**When NOT to use:**\n- When you can infer the answer from context — be decisive and proceed\n- Trivial decisions that don't materially affect the outcome\n\nOverusing this tool interrupts the user's flow. Only use it when the user's input genuinely changes your next action.\n\n**Usage notes:**\n- Users always have an \"Other\" option for custom input — don't create one yourself\n- Use multi_select to allow multiple answers to be selected for a question\n- Keep option labels concise (1-5 words), use descriptions for trade-offs and details\n- Each question should have 2-4 meaningful, distinct options\n- You can ask 1-4 questions at a time; group related questions to minimize interruptions\n- If you recommend a specific option, list it first and append \"(Recommended)\" to its label\n- The result is JSON with an `answers` object
|
|
143958
|
+
ask_user_default = "Use this tool when you need to ask the user questions with structured options during execution. This allows you to:\n1. Collect user preferences or requirements before proceeding\n2. Resolve ambiguous or underspecified instructions\n3. Let the user decide between implementation approaches as you work\n4. Present concrete options when multiple valid directions exist\n\n**When NOT to use:**\n- When you can infer the answer from context — be decisive and proceed\n- Trivial decisions that don't materially affect the outcome\n\nOverusing this tool interrupts the user's flow. Only use it when the user's input genuinely changes your next action.\n\n**Usage notes:**\n- Users always have an \"Other\" option for custom input — don't create one yourself\n- Use multi_select to allow multiple answers to be selected for a question\n- Keep option labels concise (1-5 words), use descriptions for trade-offs and details\n- Each question should have 2-4 meaningful, distinct options\n- Question texts must be unique across the call, and option labels must be unique within each question\n- You can ask 1-4 questions at a time; group related questions to minimize interruptions\n- If you recommend a specific option, list it first and append \"(Recommended)\" to its label\n- The result is JSON with an `answers` object keyed by question text; each value is the chosen option's label (comma-separated labels for multi_select, or the user's own words if they picked \"Other\"); if `answers` is empty and a `note` says the user dismissed it, they declined to answer — proceed with your best judgment and do not re-ask the same question\n";
|
|
143673
143959
|
}));
|
|
143674
143960
|
//#endregion
|
|
143675
143961
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/ask-user.ts
|
|
143962
|
+
/**
|
|
143963
|
+
* Answers are keyed by question text with option labels as values, so both
|
|
143964
|
+
* must be unambiguous: question texts unique across the call, option labels
|
|
143965
|
+
* unique within their question. Runtime tool-arg validation is AJV against
|
|
143966
|
+
* the JSON Schema (where zod refinements are unrepresentable), so the
|
|
143967
|
+
* execution path re-runs this check itself.
|
|
143968
|
+
*/
|
|
143969
|
+
function questionUniquenessError(questions) {
|
|
143970
|
+
const texts = /* @__PURE__ */ new Set();
|
|
143971
|
+
for (const q of questions) {
|
|
143972
|
+
if (texts.has(q.question)) return `Invalid questions: duplicate question text ${JSON.stringify(q.question)}. ${QUESTION_UNIQUENESS_MESSAGE} Rephrase the duplicates and call the tool again.`;
|
|
143973
|
+
texts.add(q.question);
|
|
143974
|
+
const labels = /* @__PURE__ */ new Set();
|
|
143975
|
+
for (const option of q.options) {
|
|
143976
|
+
if (labels.has(option.label)) return `Invalid questions: duplicate option label ${JSON.stringify(option.label)} in question ${JSON.stringify(q.question)}. ${QUESTION_UNIQUENESS_MESSAGE} Rephrase the duplicates and call the tool again.`;
|
|
143977
|
+
labels.add(option.label);
|
|
143978
|
+
}
|
|
143979
|
+
}
|
|
143980
|
+
return null;
|
|
143981
|
+
}
|
|
143676
143982
|
function dismissedQuestionResult() {
|
|
143677
143983
|
return {
|
|
143678
143984
|
isError: false,
|
|
@@ -143707,7 +144013,7 @@ function isQuestionResponse(result) {
|
|
|
143707
144013
|
const answers = result.answers;
|
|
143708
144014
|
return typeof answers === "object" && answers !== null && !Array.isArray(answers);
|
|
143709
144015
|
}
|
|
143710
|
-
var QuestionOptionSchema, QuestionItemSchema, AskUserQuestionInputBaseSchema, AskUserQuestionInputSchemaWithBackground, QUESTION_DISMISSED_MESSAGE, QUESTION_UNSUPPORTED_FAILURE_MESSAGE, AskUserQuestionTool;
|
|
144016
|
+
var QuestionOptionSchema, QuestionItemSchema, QUESTION_UNIQUENESS_MESSAGE, AskUserQuestionInputBaseSchema, AskUserQuestionInputSchemaWithBackground, QUESTION_DISMISSED_MESSAGE, QUESTION_UNSUPPORTED_FAILURE_MESSAGE, AskUserQuestionTool;
|
|
143711
144017
|
var init_ask_user = __esmMin((() => {
|
|
143712
144018
|
init_zod$1();
|
|
143713
144019
|
init_background();
|
|
@@ -143716,17 +144022,19 @@ var init_ask_user = __esmMin((() => {
|
|
|
143716
144022
|
init_input_schema();
|
|
143717
144023
|
init_ask_user$1();
|
|
143718
144024
|
QuestionOptionSchema = object({
|
|
143719
|
-
label: string().describe("Concise display text (1-5 words). If recommended, append '(Recommended)'."),
|
|
144025
|
+
label: string().min(1).describe("Concise display text (1-5 words). If recommended, append '(Recommended)'."),
|
|
143720
144026
|
description: string().default("").describe("Brief explanation of trade-offs or implications.")
|
|
143721
144027
|
});
|
|
143722
144028
|
QuestionItemSchema = object({
|
|
143723
|
-
question: string().describe("A specific, actionable question. End with '?'."),
|
|
144029
|
+
question: string().min(1).describe("A specific, actionable question. End with '?'."),
|
|
143724
144030
|
header: string().default("").describe("Short category tag (max 12 chars, e.g. 'Auth', 'Style')."),
|
|
143725
144031
|
options: array(QuestionOptionSchema).min(2).max(4).describe("2-4 meaningful, distinct options. Do NOT include an 'Other' option — the system adds one automatically."),
|
|
143726
144032
|
multi_select: boolean$1().default(false).describe("Whether the user can select multiple options.")
|
|
143727
144033
|
});
|
|
144034
|
+
QUESTION_UNIQUENESS_MESSAGE = "Question texts must be unique across questions, and option labels must be unique within each question.";
|
|
143728
144035
|
AskUserQuestionInputBaseSchema = object({ questions: array(QuestionItemSchema).min(1).max(4).describe("The questions to ask the user (1-4 questions).") });
|
|
143729
|
-
AskUserQuestionInputSchemaWithBackground = AskUserQuestionInputBaseSchema.extend({ background: boolean$1().default(false).describe("Set true to ask in the background and return immediately with a background task_id; you are notified automatically when the user answers — do not poll with TaskOutput while the question is pending.") });
|
|
144036
|
+
AskUserQuestionInputSchemaWithBackground = AskUserQuestionInputBaseSchema.extend({ background: boolean$1().default(false).describe("Set true to ask in the background and return immediately with a background task_id; you are notified automatically when the user answers — do not poll with TaskOutput while the question is pending.") }).refine((data) => questionUniquenessError(data.questions) === null, { message: QUESTION_UNIQUENESS_MESSAGE });
|
|
144037
|
+
AskUserQuestionInputBaseSchema.refine((data) => questionUniquenessError(data.questions) === null, { message: QUESTION_UNIQUENESS_MESSAGE });
|
|
143730
144038
|
QUESTION_DISMISSED_MESSAGE = "User dismissed the question without answering.";
|
|
143731
144039
|
QUESTION_UNSUPPORTED_FAILURE_MESSAGE = "The connected client does not support interactive questions. Do NOT call this tool again. Ask the user directly in your text response instead.";
|
|
143732
144040
|
AskUserQuestionTool = class {
|
|
@@ -143747,6 +144055,11 @@ var init_ask_user = __esmMin((() => {
|
|
|
143747
144055
|
};
|
|
143748
144056
|
}
|
|
143749
144057
|
async execution(args, { toolCallId, signal, turnId }) {
|
|
144058
|
+
const uniquenessError = questionUniquenessError(args.questions);
|
|
144059
|
+
if (uniquenessError !== null) return {
|
|
144060
|
+
isError: true,
|
|
144061
|
+
output: uniquenessError
|
|
144062
|
+
};
|
|
143750
144063
|
if (args.background === true) return this.executeInBackground(args, {
|
|
143751
144064
|
toolCallId,
|
|
143752
144065
|
turnId,
|
|
@@ -150799,6 +151112,12 @@ function toolOutputText(output) {
|
|
|
150799
151112
|
function interruptedStep(event) {
|
|
150800
151113
|
return event.activeStep ?? event.attemptedSteps;
|
|
150801
151114
|
}
|
|
151115
|
+
function telemetryInterruptReason(reason, userCancelled) {
|
|
151116
|
+
if ((reason === "aborted" || reason === "cancelled") && userCancelled) return "user_cancelled";
|
|
151117
|
+
if (reason === "aborted" || reason === "cancelled") return "aborted";
|
|
151118
|
+
if (reason === "failed") return "error";
|
|
151119
|
+
return reason;
|
|
151120
|
+
}
|
|
150802
151121
|
function classifyApiError(error, summary) {
|
|
150803
151122
|
const statusCode = apiStatusCode(error) ?? summaryStatusCode(summary);
|
|
150804
151123
|
if (statusCode !== void 0) {
|
|
@@ -151301,7 +151620,10 @@ var init_turn = __esmMin((() => {
|
|
|
151301
151620
|
if (standalone && this.currentId === turnId && this.agent.goal.getGoal().goal?.status !== "active") this.activeTurn = null;
|
|
151302
151621
|
if (this.agent.swarmMode.shouldAutoExit) this.agent.swarmMode.exit();
|
|
151303
151622
|
if (errorEvent !== void 0) this.agent.emitEvent(errorEvent);
|
|
151304
|
-
if (ended.reason !== "completed")
|
|
151623
|
+
if (ended.reason !== "completed") {
|
|
151624
|
+
const interruptReason = telemetryInterruptReason(ended.reason, isUserCancellation(signal.reason));
|
|
151625
|
+
this.trackTurnInterrupted(turnId, this.currentStepByTurn.get(turnId) ?? this.currentStep, interruptReason);
|
|
151626
|
+
}
|
|
151305
151627
|
this.telemetryModeByTurn.delete(turnId);
|
|
151306
151628
|
this.currentStepByTurn.delete(turnId);
|
|
151307
151629
|
this.interruptedTelemetryTurnIds.delete(turnId);
|
|
@@ -151375,6 +151697,7 @@ var init_turn = __esmMin((() => {
|
|
|
151375
151697
|
const deduper = new ToolCallDeduplicator({ telemetry: this.agent.telemetry });
|
|
151376
151698
|
await this.agent.mcp?.waitForInitialLoad(signal);
|
|
151377
151699
|
await this.agent.injection.injectGoal();
|
|
151700
|
+
this.agent.injection.injectToolsDiff();
|
|
151378
151701
|
while (true) {
|
|
151379
151702
|
signal.throwIfAborted();
|
|
151380
151703
|
const model = this.agent.config.model;
|
|
@@ -151388,7 +151711,8 @@ var init_turn = __esmMin((() => {
|
|
|
151388
151711
|
buildMessages: () => this.agent.context.messages,
|
|
151389
151712
|
buildMessagesStrict: () => this.agent.context.strictMessages,
|
|
151390
151713
|
dispatchEvent: this.buildDispatchEvent(turnId),
|
|
151391
|
-
|
|
151714
|
+
buildTools: () => this.agent.tools.loopTools,
|
|
151715
|
+
describeMissingTool: (name) => this.agent.tools.missingToolMessage(name),
|
|
151392
151716
|
log: this.agent.log,
|
|
151393
151717
|
maxSteps: loopControl?.maxStepsPerTurn,
|
|
151394
151718
|
maxRetryAttempts: loopControl?.maxRetriesPerStep,
|
|
@@ -151560,7 +151884,7 @@ var init_turn = __esmMin((() => {
|
|
|
151560
151884
|
}
|
|
151561
151885
|
if (event.type === "turn.interrupted") {
|
|
151562
151886
|
if (event.reason === "error" && event.activeStep !== void 0) this.stepFailureByTurn.set(turnId, event);
|
|
151563
|
-
this.trackTurnInterrupted(turnId, interruptedStep(event));
|
|
151887
|
+
this.trackTurnInterrupted(turnId, interruptedStep(event), event.interruptReason ?? telemetryInterruptReason(event.reason, false));
|
|
151564
151888
|
return;
|
|
151565
151889
|
}
|
|
151566
151890
|
this.trackToolLifecycle(event, turnId);
|
|
@@ -151621,12 +151945,13 @@ var init_turn = __esmMin((() => {
|
|
|
151621
151945
|
for (const [seenStep, keys] of this.stepToolCallKeys) if (seenStep !== step && keys.has(key)) return true;
|
|
151622
151946
|
return false;
|
|
151623
151947
|
}
|
|
151624
|
-
trackTurnInterrupted(turnId, atStep) {
|
|
151948
|
+
trackTurnInterrupted(turnId, atStep, interruptReason) {
|
|
151625
151949
|
if (this.interruptedTelemetryTurnIds.has(turnId)) return;
|
|
151626
151950
|
this.interruptedTelemetryTurnIds.add(turnId);
|
|
151627
151951
|
this.agent.telemetry.track("turn_interrupted", {
|
|
151628
151952
|
mode: this.telemetryModeByTurn.get(turnId) ?? this.telemetryMode(),
|
|
151629
151953
|
at_step: atStep,
|
|
151954
|
+
interrupt_reason: interruptReason,
|
|
151630
151955
|
...this.requestProtocolProps()
|
|
151631
151956
|
});
|
|
151632
151957
|
}
|
|
@@ -151974,6 +152299,71 @@ var init_exit_plan_mode = __esmMin((() => {
|
|
|
151974
152299
|
};
|
|
151975
152300
|
}));
|
|
151976
152301
|
//#endregion
|
|
152302
|
+
//#region ../../packages/agent-core/src/tools/builtin/select-tools.ts
|
|
152303
|
+
var SELECT_TOOLS_TOOL_NAME, SelectToolsInputSchema, DESCRIPTION, SelectToolsTool;
|
|
152304
|
+
var init_select_tools = __esmMin((() => {
|
|
152305
|
+
init_zod$1();
|
|
152306
|
+
init_dynamic_tools();
|
|
152307
|
+
init_input_schema();
|
|
152308
|
+
SELECT_TOOLS_TOOL_NAME = "select_tools";
|
|
152309
|
+
SelectToolsInputSchema = object({ names: array(string()).min(1).describe("Exact tool names to load, taken from the latest announced tool list.") }).strict();
|
|
152310
|
+
DESCRIPTION = "Load one or more tools by name so you can call them. All available tool names are listed in the <tools_added>/<tools_removed> announcements in the system context — fold them in order to get the current list. Pass the exact name(s) you need; their full definitions become available immediately, so you can call them directly in your next tool call.";
|
|
152311
|
+
SelectToolsTool = class {
|
|
152312
|
+
agent;
|
|
152313
|
+
name = SELECT_TOOLS_TOOL_NAME;
|
|
152314
|
+
description = DESCRIPTION;
|
|
152315
|
+
parameters = toInputJsonSchema(SelectToolsInputSchema);
|
|
152316
|
+
constructor(agent) {
|
|
152317
|
+
this.agent = agent;
|
|
152318
|
+
}
|
|
152319
|
+
resolveExecution(args) {
|
|
152320
|
+
return {
|
|
152321
|
+
description: `Loading ${args.names.join(", ")}`,
|
|
152322
|
+
approvalRule: this.name,
|
|
152323
|
+
execute: async () => {
|
|
152324
|
+
if (!this.agent.toolSelectEnabled) return {
|
|
152325
|
+
output: "select_tools is not available for the current model.",
|
|
152326
|
+
isError: true
|
|
152327
|
+
};
|
|
152328
|
+
const manager = this.agent.tools;
|
|
152329
|
+
const loadable = new Set(manager.loadableDynamicToolNames());
|
|
152330
|
+
const loaded = manager.loadedDynamicToolNames();
|
|
152331
|
+
const toLoad = [];
|
|
152332
|
+
const alreadyAvailable = [];
|
|
152333
|
+
const unknown = [];
|
|
152334
|
+
for (const name of new Set(args.names)) if (loaded.has(name)) alreadyAvailable.push(name);
|
|
152335
|
+
else if (loadable.has(name)) toLoad.push(name);
|
|
152336
|
+
else unknown.push(name);
|
|
152337
|
+
if (toLoad.length > 0) {
|
|
152338
|
+
toLoad.sort((a, b) => a.localeCompare(b));
|
|
152339
|
+
const tools = toLoad.map((name) => manager.getMcpToolSchema(name)).filter((tool) => tool !== void 0);
|
|
152340
|
+
this.agent.context.appendMessage({
|
|
152341
|
+
role: "system",
|
|
152342
|
+
content: [],
|
|
152343
|
+
toolCalls: [],
|
|
152344
|
+
tools,
|
|
152345
|
+
origin: {
|
|
152346
|
+
kind: "injection",
|
|
152347
|
+
variant: DYNAMIC_TOOL_SCHEMA_VARIANT
|
|
152348
|
+
}
|
|
152349
|
+
});
|
|
152350
|
+
manager.markDynamicToolsLoaded(toLoad);
|
|
152351
|
+
}
|
|
152352
|
+
const lines = [];
|
|
152353
|
+
if (toLoad.length > 0) lines.push(`Loaded: ${toLoad.join(", ")}`);
|
|
152354
|
+
if (alreadyAvailable.length > 0) lines.push(`Already available: ${alreadyAvailable.join(", ")}`);
|
|
152355
|
+
for (const name of unknown) lines.push(`Unknown tool: ${name}. Pick from the latest announced tools list.`);
|
|
152356
|
+
const isError = toLoad.length === 0 && alreadyAvailable.length === 0;
|
|
152357
|
+
return isError ? {
|
|
152358
|
+
output: lines.join("\n"),
|
|
152359
|
+
isError
|
|
152360
|
+
} : { output: lines.join("\n") };
|
|
152361
|
+
}
|
|
152362
|
+
};
|
|
152363
|
+
}
|
|
152364
|
+
};
|
|
152365
|
+
}));
|
|
152366
|
+
//#endregion
|
|
151977
152367
|
//#region ../../packages/agent-core/src/tools/builtin/shell/bash.md?raw
|
|
151978
152368
|
var bash_default;
|
|
151979
152369
|
var init_bash$1 = __esmMin((() => {
|
|
@@ -152464,6 +152854,7 @@ var init_builtin = __esmMin((() => {
|
|
|
152464
152854
|
init_update_goal();
|
|
152465
152855
|
init_enter_plan_mode();
|
|
152466
152856
|
init_exit_plan_mode();
|
|
152857
|
+
init_select_tools();
|
|
152467
152858
|
init_bash();
|
|
152468
152859
|
init_todo_list$1();
|
|
152469
152860
|
init_fetch_url();
|
|
@@ -152478,6 +152869,7 @@ var import_picomatch, SHELL_FOREGROUND_TIMEOUT_S, ToolManager;
|
|
|
152478
152869
|
var init_tool$1 = __esmMin((() => {
|
|
152479
152870
|
init_dist$4();
|
|
152480
152871
|
import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
|
|
152872
|
+
init_dynamic_tools();
|
|
152481
152873
|
init_errors$8();
|
|
152482
152874
|
init_auth_tool();
|
|
152483
152875
|
init_output();
|
|
@@ -152498,6 +152890,14 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152498
152890
|
enabledTools = /* @__PURE__ */ new Set();
|
|
152499
152891
|
/** Glob patterns (e.g. `mcp__*`, `mcp__github__*`) gating which MCP tools the profile exposes. */
|
|
152500
152892
|
mcpAccessPatterns = [];
|
|
152893
|
+
/**
|
|
152894
|
+
* Defer-window lead for the loaded-tools ledger: names marked loaded whose
|
|
152895
|
+
* schema message may still sit in the context's deferred queue (an open tool
|
|
152896
|
+
* exchange). The history itself is the source of truth —
|
|
152897
|
+
* `loadedDynamicToolNames()` unions this set with a history scan — so
|
|
152898
|
+
* undo/compaction/resume never need to roll this back.
|
|
152899
|
+
*/
|
|
152900
|
+
pendingLoadedDynamicTools = /* @__PURE__ */ new Set();
|
|
152501
152901
|
store = {};
|
|
152502
152902
|
mcpToolStatusUnsubscribe;
|
|
152503
152903
|
/** Abort controllers for in-flight `!` shell commands, keyed by commandId so
|
|
@@ -152818,11 +153218,93 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152818
153218
|
isMcpToolEnabled(name) {
|
|
152819
153219
|
return this.mcpAccessPatterns.some((pattern) => import_picomatch.default.isMatch(name, pattern));
|
|
152820
153220
|
}
|
|
153221
|
+
/**
|
|
153222
|
+
* Whether MCP tools are disclosed progressively: kept out of the top-level
|
|
153223
|
+
* `tools[]` and loaded on demand via select_tools. Reads the agent's single
|
|
153224
|
+
* three-gate decision point.
|
|
153225
|
+
*/
|
|
153226
|
+
get progressiveDisclosure() {
|
|
153227
|
+
return this.agent.toolSelectEnabled;
|
|
153228
|
+
}
|
|
153229
|
+
/**
|
|
153230
|
+
* Names the model may select right now: registered MCP tools that pass the
|
|
153231
|
+
* profile's `mcp__*` access patterns, sorted for byte-stable announcements.
|
|
153232
|
+
* In disclosure mode the patterns keep their permission-filter role but stop
|
|
153233
|
+
* feeding the top-level `tools[]`.
|
|
153234
|
+
*/
|
|
153235
|
+
loadableDynamicToolNames() {
|
|
153236
|
+
return [...this.mcpTools.keys()].filter((name) => this.isMcpToolEnabled(name)).toSorted((a, b) => a.localeCompare(b));
|
|
153237
|
+
}
|
|
153238
|
+
/**
|
|
153239
|
+
* The loaded-tools ledger: every name whose full definition has been
|
|
153240
|
+
* delivered to the conversation via a `tools`-carrying message, plus the
|
|
153241
|
+
* defer-window pending set. History is the single source of truth, so the
|
|
153242
|
+
* ledger survives resume (records replay rebuilds the history), keeps its
|
|
153243
|
+
* state across undo (schema messages have `injection` origin and are not
|
|
153244
|
+
* undone), and self-heals after compaction (the rebuild message re-carries
|
|
153245
|
+
* the schemas).
|
|
153246
|
+
*/
|
|
153247
|
+
loadedDynamicToolNames() {
|
|
153248
|
+
const names = collectLoadedDynamicToolNames(this.agent.context.history);
|
|
153249
|
+
for (const name of this.pendingLoadedDynamicTools) names.add(name);
|
|
153250
|
+
return names;
|
|
153251
|
+
}
|
|
153252
|
+
/** Mark names loaded ahead of their schema message landing in history. */
|
|
153253
|
+
markDynamicToolsLoaded(names) {
|
|
153254
|
+
for (const name of names) this.pendingLoadedDynamicTools.add(name);
|
|
153255
|
+
}
|
|
153256
|
+
/**
|
|
153257
|
+
* Context was cleared (`/clear`): every schema message is gone, so the
|
|
153258
|
+
* defer-window lead must not keep reporting its names as loaded — a stale
|
|
153259
|
+
* entry would make select_tools answer "Already available" for a tool whose
|
|
153260
|
+
* definition the model can no longer see.
|
|
153261
|
+
*/
|
|
153262
|
+
onContextCleared() {
|
|
153263
|
+
this.pendingLoadedDynamicTools.clear();
|
|
153264
|
+
}
|
|
153265
|
+
/**
|
|
153266
|
+
* Compaction rebuilt the history: from here on the keep-all rebuild message
|
|
153267
|
+
* (which may have trimmed or skipped schemas — budget guard, disconnected
|
|
153268
|
+
* servers) is the sole truth about what is still loaded. A pending entry
|
|
153269
|
+
* surviving past this boundary would report a schema the context no longer
|
|
153270
|
+
* carries as loaded, and re-selecting it would wrongly answer
|
|
153271
|
+
* "Already available" instead of injecting.
|
|
153272
|
+
*/
|
|
153273
|
+
onContextCompacted() {
|
|
153274
|
+
this.pendingLoadedDynamicTools.clear();
|
|
153275
|
+
}
|
|
153276
|
+
/**
|
|
153277
|
+
* Plain schema snapshot of a registered MCP tool, read from the live
|
|
153278
|
+
* registry (never from history) at injection time.
|
|
153279
|
+
*/
|
|
153280
|
+
getMcpToolSchema(name) {
|
|
153281
|
+
const entry = this.mcpTools.get(name);
|
|
153282
|
+
if (entry === void 0) return void 0;
|
|
153283
|
+
return {
|
|
153284
|
+
name: entry.tool.name,
|
|
153285
|
+
description: entry.tool.description,
|
|
153286
|
+
parameters: entry.tool.parameters
|
|
153287
|
+
};
|
|
153288
|
+
}
|
|
153289
|
+
/**
|
|
153290
|
+
* Disclosure-mode wording for a tool-call preflight miss. A loaded tool
|
|
153291
|
+
* whose server dropped is a different situation from a never-announced name;
|
|
153292
|
+
* telling them apart stops the model from re-selecting a disconnected tool
|
|
153293
|
+
* in a loop or treating a transient disconnect as a permanent removal.
|
|
153294
|
+
*/
|
|
153295
|
+
missingToolMessage(name) {
|
|
153296
|
+
if (!this.progressiveDisclosure) return void 0;
|
|
153297
|
+
if (!isMcpToolName(name)) return void 0;
|
|
153298
|
+
const registered = this.mcpTools.has(name) && this.isMcpToolEnabled(name);
|
|
153299
|
+
const loaded = this.loadedDynamicToolNames().has(name);
|
|
153300
|
+
if (registered && !loaded) return `Tool "${name}" is available but not loaded. Call select_tools with ["${name}"] first, then call the tool.`;
|
|
153301
|
+
if (!registered && loaded) return `Tool "${name}" was loaded but its MCP server is currently disconnected. It may become available again when the server reconnects; do not retry immediately.`;
|
|
153302
|
+
}
|
|
152821
153303
|
*toolInfos() {
|
|
152822
153304
|
for (const tool of this.builtinTools.values()) yield {
|
|
152823
153305
|
name: tool.name,
|
|
152824
153306
|
description: tool.description,
|
|
152825
|
-
active: this.enabledTools.has(tool.name),
|
|
153307
|
+
active: this.enabledTools.has(tool.name) || tool.name === "select_tools" && this.agent.toolSelectEnabled,
|
|
152826
153308
|
source: "builtin"
|
|
152827
153309
|
};
|
|
152828
153310
|
for (const tool of this.userTools.values()) yield {
|
|
@@ -152863,6 +153345,7 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152863
153345
|
(modelCapabilities.image_in || modelCapabilities.video_in) && new ReadMediaFileTool(kaos, workspace, modelCapabilities, videoUploader),
|
|
152864
153346
|
new EnterPlanModeTool(this.agent),
|
|
152865
153347
|
new ExitPlanModeTool(this.agent),
|
|
153348
|
+
new SelectToolsTool(this.agent),
|
|
152866
153349
|
goalToolsEnabled && new CreateGoalTool(this.agent),
|
|
152867
153350
|
goalToolsEnabled && new GetGoalTool(this.agent),
|
|
152868
153351
|
goalToolsEnabled && new SetGoalBudgetTool(this.agent),
|
|
@@ -152941,9 +153424,24 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152941
153424
|
}
|
|
152942
153425
|
get loopTools() {
|
|
152943
153426
|
if (this.loopToolsOverride !== void 0) return this.loopToolsOverride;
|
|
152944
|
-
const
|
|
153427
|
+
const disclosure = this.progressiveDisclosure;
|
|
153428
|
+
const enabledMcpNames = [...this.mcpTools.keys()].filter((name) => this.isMcpToolEnabled(name));
|
|
153429
|
+
const loadedSet = disclosure ? this.loadedDynamicToolNames() : void 0;
|
|
153430
|
+
const mcpNames = loadedSet === void 0 ? enabledMcpNames : enabledMcpNames.filter((name) => loadedSet.has(name));
|
|
153431
|
+
const selectToolsName = disclosure ? [SELECT_TOOLS_TOOL_NAME] : [];
|
|
152945
153432
|
const hideGoalMutationTools = this.agent.goal.getGoal().goal === null;
|
|
152946
|
-
return uniq([
|
|
153433
|
+
return uniq([
|
|
153434
|
+
...this.enabledTools,
|
|
153435
|
+
...selectToolsName,
|
|
153436
|
+
...mcpNames
|
|
153437
|
+
]).toSorted((a, b) => a.localeCompare(b)).filter((name) => !(hideGoalMutationTools && (name === "SetGoalBudget" || name === "UpdateGoal"))).filter((name) => disclosure || name !== "select_tools").map((name) => {
|
|
153438
|
+
const tool = this.userTools.get(name) ?? this.mcpTools.get(name)?.tool ?? this.builtinTools.get(name);
|
|
153439
|
+
if (tool === void 0) return void 0;
|
|
153440
|
+
return disclosure && this.mcpTools.has(name) ? {
|
|
153441
|
+
...tool,
|
|
153442
|
+
deferred: true
|
|
153443
|
+
} : tool;
|
|
153444
|
+
}).filter((tool) => !!tool);
|
|
152947
153445
|
}
|
|
152948
153446
|
};
|
|
152949
153447
|
}));
|
|
@@ -153245,18 +153743,19 @@ var init_llm_request_logger = __esmMin((() => {
|
|
|
153245
153743
|
logRequest(input) {
|
|
153246
153744
|
const { provider, modelAlias, systemPrompt, tools, messages, fields } = input;
|
|
153247
153745
|
const requestLogFields = fields ?? {};
|
|
153746
|
+
const wireTools = tools.filter((tool) => tool.deferred !== true);
|
|
153248
153747
|
const config = {
|
|
153249
153748
|
provider: provider.name,
|
|
153250
153749
|
model: provider.modelName,
|
|
153251
153750
|
modelAlias,
|
|
153252
153751
|
thinkingEffort: provider.thinkingEffort ?? void 0,
|
|
153253
153752
|
systemPromptChars: systemPrompt.length,
|
|
153254
|
-
toolCount:
|
|
153753
|
+
toolCount: wireTools.length
|
|
153255
153754
|
};
|
|
153256
153755
|
const signature = JSON.stringify({
|
|
153257
153756
|
...config,
|
|
153258
153757
|
systemPromptHash: fingerprint(systemPrompt),
|
|
153259
|
-
toolsHash: fingerprint(JSON.stringify(toolSignature(
|
|
153758
|
+
toolsHash: fingerprint(JSON.stringify(toolSignature(wireTools)))
|
|
153260
153759
|
});
|
|
153261
153760
|
if (signature !== this.lastConfigLogSignature) {
|
|
153262
153761
|
this.lastConfigLogSignature = signature;
|
|
@@ -153420,6 +153919,20 @@ var init_agent = __esmMin((() => {
|
|
|
153420
153919
|
this.additionalDirs = normalizeAdditionalDirs(additionalDirs);
|
|
153421
153920
|
if (this.config.hasProvider) this.tools.initializeBuiltinTools();
|
|
153422
153921
|
}
|
|
153922
|
+
/**
|
|
153923
|
+
* Single decision point for select_tools progressive disclosure. All three
|
|
153924
|
+
* gates must be open: the model declares the `select_tools` capability, the
|
|
153925
|
+
* model declares `tool_use` (a model without tool use registering
|
|
153926
|
+
* select_tools is a contradiction), and the `tool-select` experimental flag
|
|
153927
|
+
* is on. Every consumer — top-level tools[] convergence, select_tools
|
|
153928
|
+
* registration, manifest announcements, projection shaping — reads this
|
|
153929
|
+
* instead of re-deriving the conditions, so degradation is lossless: any
|
|
153930
|
+
* closed gate reproduces the inline behavior byte-for-byte.
|
|
153931
|
+
*/
|
|
153932
|
+
get toolSelectEnabled() {
|
|
153933
|
+
const capability = this.config.modelCapabilities;
|
|
153934
|
+
return capability.select_tools === true && capability.tool_use && this.experimentalFlags.enabled("tool-select");
|
|
153935
|
+
}
|
|
153423
153936
|
get generate() {
|
|
153424
153937
|
return async (provider, systemPrompt, tools, history, callbacks, options) => {
|
|
153425
153938
|
const { requestLogFields, generateOptions } = splitGenerateOptions(options);
|
|
@@ -183817,6 +184330,597 @@ var init_mcp$1 = __esmMin((() => {
|
|
|
183817
184330
|
init_types$2();
|
|
183818
184331
|
}));
|
|
183819
184332
|
//#endregion
|
|
184333
|
+
//#region ../../packages/agent-core/src/session/store/session-index.ts
|
|
184334
|
+
function sessionIndexPath(homeDir) {
|
|
184335
|
+
return join$4(homeDir, "session_index.jsonl");
|
|
184336
|
+
}
|
|
184337
|
+
async function appendSessionIndexEntry(homeDir, entry) {
|
|
184338
|
+
const indexPath = sessionIndexPath(homeDir);
|
|
184339
|
+
const line = `${JSON.stringify(entry)}\n`;
|
|
184340
|
+
const next = (appendQueues.get(homeDir) ?? Promise.resolve()).then(async () => {
|
|
184341
|
+
await mkdir(dirname$3(indexPath), {
|
|
184342
|
+
recursive: true,
|
|
184343
|
+
mode: 448
|
|
184344
|
+
});
|
|
184345
|
+
await appendFile(indexPath, line, "utf-8");
|
|
184346
|
+
});
|
|
184347
|
+
appendQueues.set(homeDir, next.then(() => void 0, () => void 0));
|
|
184348
|
+
return next;
|
|
184349
|
+
}
|
|
184350
|
+
async function readSessionIndex$1(homeDir, sessionsDir) {
|
|
184351
|
+
let raw;
|
|
184352
|
+
try {
|
|
184353
|
+
raw = await readFile(sessionIndexPath(homeDir), "utf-8");
|
|
184354
|
+
} catch {
|
|
184355
|
+
return /* @__PURE__ */ new Map();
|
|
184356
|
+
}
|
|
184357
|
+
const result = /* @__PURE__ */ new Map();
|
|
184358
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
184359
|
+
const trimmed = line.trim();
|
|
184360
|
+
if (trimmed === "") continue;
|
|
184361
|
+
const entry = parseIndexLine$1(trimmed);
|
|
184362
|
+
if (entry === void 0) continue;
|
|
184363
|
+
const sessionDir = resolve$2(entry.sessionDir);
|
|
184364
|
+
if (!isAbsolute$2(entry.sessionDir)) continue;
|
|
184365
|
+
if (!isPathInside$1(sessionsDir, sessionDir)) continue;
|
|
184366
|
+
if (basename$2(sessionDir) !== entry.sessionId) continue;
|
|
184367
|
+
result.set(entry.sessionId, {
|
|
184368
|
+
sessionId: entry.sessionId,
|
|
184369
|
+
sessionDir,
|
|
184370
|
+
workDir: entry.workDir
|
|
184371
|
+
});
|
|
184372
|
+
}
|
|
184373
|
+
return result;
|
|
184374
|
+
}
|
|
184375
|
+
function parseIndexLine$1(line) {
|
|
184376
|
+
try {
|
|
184377
|
+
const parsed = JSON.parse(line);
|
|
184378
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
184379
|
+
const entry = parsed;
|
|
184380
|
+
if (typeof entry.sessionId !== "string" || typeof entry.sessionDir !== "string" || typeof entry.workDir !== "string") return;
|
|
184381
|
+
return {
|
|
184382
|
+
sessionId: entry.sessionId,
|
|
184383
|
+
sessionDir: entry.sessionDir,
|
|
184384
|
+
workDir: entry.workDir
|
|
184385
|
+
};
|
|
184386
|
+
} catch {
|
|
184387
|
+
return;
|
|
184388
|
+
}
|
|
184389
|
+
}
|
|
184390
|
+
function isPathInside$1(parent, child) {
|
|
184391
|
+
const rel = relative$1(resolve$2(parent), resolve$2(child));
|
|
184392
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute$2(rel);
|
|
184393
|
+
}
|
|
184394
|
+
var appendQueues;
|
|
184395
|
+
var init_session_index = __esmMin((() => {
|
|
184396
|
+
init_dist$7();
|
|
184397
|
+
appendQueues = /* @__PURE__ */ new Map();
|
|
184398
|
+
}));
|
|
184399
|
+
//#endregion
|
|
184400
|
+
//#region ../../packages/agent-core/src/utils/workdir-slug.ts
|
|
184401
|
+
function slugifyWorkDirName(name) {
|
|
184402
|
+
const slug = name.toLowerCase().replaceAll(/[^a-z0-9._-]+/g, "-").replaceAll(/^-+|-+$/g, "").slice(0, MAX_WORKDIR_SLUG_LENGTH).replaceAll(/^-+|-+$/g, "");
|
|
184403
|
+
return slug === "" || slug === "." || slug === ".." ? "workspace" : slug;
|
|
184404
|
+
}
|
|
184405
|
+
var MAX_WORKDIR_SLUG_LENGTH;
|
|
184406
|
+
var init_workdir_slug = __esmMin((() => {
|
|
184407
|
+
MAX_WORKDIR_SLUG_LENGTH = 40;
|
|
184408
|
+
}));
|
|
184409
|
+
//#endregion
|
|
184410
|
+
//#region ../../packages/agent-core/src/session/store/workdir-key.ts
|
|
184411
|
+
function normalizeWorkDir(workDir) {
|
|
184412
|
+
return resolve$2(workDir);
|
|
184413
|
+
}
|
|
184414
|
+
function encodeWorkDirKey(workDir) {
|
|
184415
|
+
const normalized = normalizeWorkDir(workDir);
|
|
184416
|
+
return `${WORKDIR_KEY_PREFIX}${slugifyWorkDirName(basename$2(normalized))}_${createHash("sha256").update(normalized).digest("hex").slice(0, HASH_LENGTH)}`;
|
|
184417
|
+
}
|
|
184418
|
+
var WORKDIR_KEY_PREFIX, HASH_LENGTH;
|
|
184419
|
+
var init_workdir_key = __esmMin((() => {
|
|
184420
|
+
init_dist$7();
|
|
184421
|
+
init_workdir_slug();
|
|
184422
|
+
WORKDIR_KEY_PREFIX = "wd_";
|
|
184423
|
+
HASH_LENGTH = 12;
|
|
184424
|
+
}));
|
|
184425
|
+
//#endregion
|
|
184426
|
+
//#region ../../packages/agent-core/src/session/store/session-store.ts
|
|
184427
|
+
function metadataFromState(state) {
|
|
184428
|
+
if (state === void 0 || state.custom === void 0) return void 0;
|
|
184429
|
+
return state.custom;
|
|
184430
|
+
}
|
|
184431
|
+
function forkCustomMetadata(source, metadata) {
|
|
184432
|
+
return {
|
|
184433
|
+
...customMetadataWithoutGoal(source),
|
|
184434
|
+
...customMetadataWithoutGoal(metadata)
|
|
184435
|
+
};
|
|
184436
|
+
}
|
|
184437
|
+
async function dropForkedSessionFiles(sessionDir) {
|
|
184438
|
+
await Promise.all(FORKED_SESSION_DROPPED_FILES.map((fileName) => rm(join$4(sessionDir, fileName), { force: true })));
|
|
184439
|
+
}
|
|
184440
|
+
async function appendForkedMarkers(state) {
|
|
184441
|
+
const record = {
|
|
184442
|
+
type: "forked",
|
|
184443
|
+
time: Date.now()
|
|
184444
|
+
};
|
|
184445
|
+
const agents = state["agents"];
|
|
184446
|
+
if (!isRecord$11(agents)) return;
|
|
184447
|
+
const paths = /* @__PURE__ */ new Set();
|
|
184448
|
+
for (const agentMeta of Object.values(agents)) {
|
|
184449
|
+
if (!isRecord$11(agentMeta)) continue;
|
|
184450
|
+
const homedir = agentMeta["homedir"];
|
|
184451
|
+
if (typeof homedir !== "string") continue;
|
|
184452
|
+
paths.add(join$4(homedir, "wire.jsonl"));
|
|
184453
|
+
}
|
|
184454
|
+
await Promise.all([...paths].map(async (path) => {
|
|
184455
|
+
const persistence = new FileSystemAgentRecordPersistence(path);
|
|
184456
|
+
persistence.append(record);
|
|
184457
|
+
await persistence.flush();
|
|
184458
|
+
}));
|
|
184459
|
+
}
|
|
184460
|
+
function customMetadataWithoutGoal(value) {
|
|
184461
|
+
if (!isRecord$11(value)) return {};
|
|
184462
|
+
const custom = {};
|
|
184463
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
184464
|
+
if (key === "goal") continue;
|
|
184465
|
+
custom[key] = entry;
|
|
184466
|
+
}
|
|
184467
|
+
return custom;
|
|
184468
|
+
}
|
|
184469
|
+
async function latestAgentWireMtime(sessionDir) {
|
|
184470
|
+
const agentsDir = join$4(sessionDir, "agents");
|
|
184471
|
+
let entries;
|
|
184472
|
+
try {
|
|
184473
|
+
entries = await readdir$1(agentsDir, { withFileTypes: true });
|
|
184474
|
+
} catch {
|
|
184475
|
+
return;
|
|
184476
|
+
}
|
|
184477
|
+
let latest = 0;
|
|
184478
|
+
for (const entry of entries) {
|
|
184479
|
+
if (!entry.isDirectory()) continue;
|
|
184480
|
+
const wireInfo = await statIfExists(join$4(agentsDir, entry.name, "wire.jsonl"));
|
|
184481
|
+
latest = Math.max(latest, wireInfo?.mtimeMs ?? 0);
|
|
184482
|
+
}
|
|
184483
|
+
return latest > 0 ? latest : void 0;
|
|
184484
|
+
}
|
|
184485
|
+
function titleFromState(state) {
|
|
184486
|
+
if (state === void 0) return void 0;
|
|
184487
|
+
if (typeof state.isCustomTitle === "boolean" && typeof state.title === "string") return state.title;
|
|
184488
|
+
if (typeof state.customTitle === "string") return state.customTitle;
|
|
184489
|
+
return typeof state.title === "string" ? state.title : void 0;
|
|
184490
|
+
}
|
|
184491
|
+
async function readOptionalState(sessionDir) {
|
|
184492
|
+
try {
|
|
184493
|
+
const parsed = JSON.parse(await readFile(join$4(sessionDir, "state.json"), "utf-8"));
|
|
184494
|
+
const result = SessionSummaryStateSchema.safeParse(parsed);
|
|
184495
|
+
return result.success ? result.data : void 0;
|
|
184496
|
+
} catch {
|
|
184497
|
+
return;
|
|
184498
|
+
}
|
|
184499
|
+
}
|
|
184500
|
+
function normalizeRequiredWorkDir(workDir) {
|
|
184501
|
+
if (workDir.trim() === "") throw new KimiError(ErrorCodes.REQUEST_WORK_DIR_REQUIRED, "listSessions requires workDir");
|
|
184502
|
+
return normalizeWorkDir(workDir);
|
|
184503
|
+
}
|
|
184504
|
+
function normalizeOptionalSessionId$1(sessionId) {
|
|
184505
|
+
return sessionId === void 0 ? void 0 : sessionId.trim();
|
|
184506
|
+
}
|
|
184507
|
+
function normalizeForkTitle(title, fallback) {
|
|
184508
|
+
if (title !== void 0) {
|
|
184509
|
+
const normalized = title.trim();
|
|
184510
|
+
if (normalized.length === 0) throw new KimiError(ErrorCodes.SESSION_TITLE_EMPTY, "Session title cannot be empty");
|
|
184511
|
+
return normalized;
|
|
184512
|
+
}
|
|
184513
|
+
return typeof fallback === "string" && fallback.trim().length > 0 ? fallback : "New Session";
|
|
184514
|
+
}
|
|
184515
|
+
function rewriteAgentHomedirs(value, sourceDir, targetDir) {
|
|
184516
|
+
if (!isRecord$11(value)) return {};
|
|
184517
|
+
const agents = {};
|
|
184518
|
+
for (const [agentId, agentMeta] of Object.entries(value)) {
|
|
184519
|
+
if (!isRecord$11(agentMeta)) {
|
|
184520
|
+
agents[agentId] = agentMeta;
|
|
184521
|
+
continue;
|
|
184522
|
+
}
|
|
184523
|
+
const homedir = agentMeta["homedir"];
|
|
184524
|
+
agents[agentId] = {
|
|
184525
|
+
...agentMeta,
|
|
184526
|
+
homedir: typeof homedir === "string" ? remapSessionPath(homedir, sourceDir, targetDir) : homedir
|
|
184527
|
+
};
|
|
184528
|
+
}
|
|
184529
|
+
return agents;
|
|
184530
|
+
}
|
|
184531
|
+
function remapSessionPath(value, sourceDir, targetDir) {
|
|
184532
|
+
const rel = relative$1(sourceDir, value);
|
|
184533
|
+
if (rel === "") return targetDir;
|
|
184534
|
+
if (rel.startsWith("..") || isAbsolute$2(rel)) return value;
|
|
184535
|
+
return join$4(targetDir, rel);
|
|
184536
|
+
}
|
|
184537
|
+
function isRecord$11(value) {
|
|
184538
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
184539
|
+
}
|
|
184540
|
+
async function statIfExists(path) {
|
|
184541
|
+
try {
|
|
184542
|
+
return await stat$2(path);
|
|
184543
|
+
} catch {
|
|
184544
|
+
return;
|
|
184545
|
+
}
|
|
184546
|
+
}
|
|
184547
|
+
async function isDirectory(path) {
|
|
184548
|
+
try {
|
|
184549
|
+
return (await stat$2(path)).isDirectory();
|
|
184550
|
+
} catch {
|
|
184551
|
+
return false;
|
|
184552
|
+
}
|
|
184553
|
+
}
|
|
184554
|
+
function timestampOrFallback(value, fallback) {
|
|
184555
|
+
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
184556
|
+
}
|
|
184557
|
+
function assertSafeSessionId(id) {
|
|
184558
|
+
if (isSafeSessionId(id)) return;
|
|
184559
|
+
throw new KimiError(ErrorCodes.SESSION_ID_INVALID, "Session id contains unsupported path characters");
|
|
184560
|
+
}
|
|
184561
|
+
function isSafeSessionId(id) {
|
|
184562
|
+
return /^[A-Za-z0-9._-]+$/.test(id) && id !== "." && id !== "..";
|
|
184563
|
+
}
|
|
184564
|
+
function compareSessionSummary(a, b) {
|
|
184565
|
+
if (a.updatedAt !== b.updatedAt) return b.updatedAt - a.updatedAt;
|
|
184566
|
+
if (a.createdAt !== b.createdAt) return b.createdAt - a.createdAt;
|
|
184567
|
+
if (a.id < b.id) return -1;
|
|
184568
|
+
if (a.id > b.id) return 1;
|
|
184569
|
+
return 0;
|
|
184570
|
+
}
|
|
184571
|
+
var SessionSummaryStateSchema, FORKED_SESSION_DROPPED_FILES, SessionStore;
|
|
184572
|
+
var init_session_store$1 = __esmMin((() => {
|
|
184573
|
+
init_dist$7();
|
|
184574
|
+
init_zod$1();
|
|
184575
|
+
init_errors$8();
|
|
184576
|
+
init_session_index();
|
|
184577
|
+
init_workdir_key();
|
|
184578
|
+
init_records();
|
|
184579
|
+
SessionSummaryStateSchema = object({
|
|
184580
|
+
archived: boolean$1().optional(),
|
|
184581
|
+
customTitle: string().optional(),
|
|
184582
|
+
isCustomTitle: boolean$1().optional(),
|
|
184583
|
+
lastPrompt: string().optional(),
|
|
184584
|
+
title: string().optional(),
|
|
184585
|
+
workDir: string().optional(),
|
|
184586
|
+
custom: record(string(), unknown()).optional()
|
|
184587
|
+
});
|
|
184588
|
+
FORKED_SESSION_DROPPED_FILES = ["upcoming-goals.json"];
|
|
184589
|
+
SessionStore = class {
|
|
184590
|
+
homeDir;
|
|
184591
|
+
sessionsDir;
|
|
184592
|
+
constructor(homeDir, _options = {}) {
|
|
184593
|
+
this.homeDir = homeDir;
|
|
184594
|
+
this.sessionsDir = join$4(homeDir, "sessions");
|
|
184595
|
+
}
|
|
184596
|
+
sessionDirFor(input) {
|
|
184597
|
+
assertSafeSessionId(input.id);
|
|
184598
|
+
return join$4(this.sessionsDir, encodeWorkDirKey(normalizeWorkDir(input.workDir)), input.id);
|
|
184599
|
+
}
|
|
184600
|
+
async create(input) {
|
|
184601
|
+
assertSafeSessionId(input.id);
|
|
184602
|
+
const workDir = normalizeWorkDir(input.workDir);
|
|
184603
|
+
if (await this.findSessionEntry(input.id) !== void 0) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.id}" already exists`);
|
|
184604
|
+
const dir = this.sessionDirFor({
|
|
184605
|
+
id: input.id,
|
|
184606
|
+
workDir
|
|
184607
|
+
});
|
|
184608
|
+
if (await isDirectory(dir)) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.id}" already exists`);
|
|
184609
|
+
await mkdir(dir, {
|
|
184610
|
+
recursive: true,
|
|
184611
|
+
mode: 448
|
|
184612
|
+
});
|
|
184613
|
+
await appendSessionIndexEntry(this.homeDir, {
|
|
184614
|
+
sessionId: input.id,
|
|
184615
|
+
sessionDir: dir,
|
|
184616
|
+
workDir
|
|
184617
|
+
});
|
|
184618
|
+
return this.summaryFromDir(input.id, dir, workDir);
|
|
184619
|
+
}
|
|
184620
|
+
async fork(input) {
|
|
184621
|
+
const source = await this.findExistingSessionEntry(input.sourceId);
|
|
184622
|
+
assertSafeSessionId(input.targetId);
|
|
184623
|
+
if (await this.findSessionEntry(input.targetId) !== void 0) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.targetId}" already exists`);
|
|
184624
|
+
const targetDir = this.sessionDirFor({
|
|
184625
|
+
id: input.targetId,
|
|
184626
|
+
workDir: source.workDir
|
|
184627
|
+
});
|
|
184628
|
+
if (await isDirectory(targetDir)) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.targetId}" already exists`);
|
|
184629
|
+
await mkdir(dirname$3(targetDir), {
|
|
184630
|
+
recursive: true,
|
|
184631
|
+
mode: 448
|
|
184632
|
+
});
|
|
184633
|
+
try {
|
|
184634
|
+
await cp(source.sessionDir, targetDir, {
|
|
184635
|
+
recursive: true,
|
|
184636
|
+
force: false,
|
|
184637
|
+
errorOnExist: true
|
|
184638
|
+
});
|
|
184639
|
+
await dropForkedSessionFiles(targetDir);
|
|
184640
|
+
await appendForkedMarkers(await this.writeForkedState(input, source.sessionDir, source.workDir, targetDir));
|
|
184641
|
+
const summary = await this.summaryFromDir(input.targetId, targetDir, source.workDir);
|
|
184642
|
+
await appendSessionIndexEntry(this.homeDir, {
|
|
184643
|
+
sessionId: input.targetId,
|
|
184644
|
+
sessionDir: targetDir,
|
|
184645
|
+
workDir: source.workDir
|
|
184646
|
+
});
|
|
184647
|
+
return summary;
|
|
184648
|
+
} catch (error) {
|
|
184649
|
+
await rm(targetDir, {
|
|
184650
|
+
recursive: true,
|
|
184651
|
+
force: true
|
|
184652
|
+
}).catch(() => {});
|
|
184653
|
+
throw error;
|
|
184654
|
+
}
|
|
184655
|
+
}
|
|
184656
|
+
async get(id) {
|
|
184657
|
+
const entry = await this.findExistingSessionEntry(id);
|
|
184658
|
+
return this.summaryFromDir(id, entry.sessionDir, entry.workDir);
|
|
184659
|
+
}
|
|
184660
|
+
async rename(id, title) {
|
|
184661
|
+
const normalized = title.trim();
|
|
184662
|
+
if (normalized.length === 0) throw new KimiError(ErrorCodes.SESSION_TITLE_EMPTY, "Session title cannot be empty");
|
|
184663
|
+
const statePath = join$4((await this.findExistingSessionEntry(id)).sessionDir, "state.json");
|
|
184664
|
+
let parsed;
|
|
184665
|
+
try {
|
|
184666
|
+
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
184667
|
+
} catch (error) {
|
|
184668
|
+
throw new KimiError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${id}" state.json was not found`, { cause: error });
|
|
184669
|
+
}
|
|
184670
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new KimiError(ErrorCodes.SESSION_STATE_INVALID, `Session "${id}" state.json is invalid`);
|
|
184671
|
+
const next = {
|
|
184672
|
+
...parsed,
|
|
184673
|
+
title: normalized,
|
|
184674
|
+
isCustomTitle: true
|
|
184675
|
+
};
|
|
184676
|
+
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
184677
|
+
}
|
|
184678
|
+
async archive(id) {
|
|
184679
|
+
const entry = await this.findExistingSessionEntry(id);
|
|
184680
|
+
const statePath = join$4(entry.sessionDir, "state.json");
|
|
184681
|
+
let parsed;
|
|
184682
|
+
try {
|
|
184683
|
+
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
184684
|
+
} catch (error) {
|
|
184685
|
+
throw new KimiError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${id}" state.json was not found`, { cause: error });
|
|
184686
|
+
}
|
|
184687
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new KimiError(ErrorCodes.SESSION_STATE_INVALID, `Session "${id}" state.json is invalid`);
|
|
184688
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
184689
|
+
const next = {
|
|
184690
|
+
...parsed,
|
|
184691
|
+
archived: true,
|
|
184692
|
+
updatedAt: now
|
|
184693
|
+
};
|
|
184694
|
+
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
184695
|
+
return this.summaryFromDir(id, entry.sessionDir, entry.workDir);
|
|
184696
|
+
}
|
|
184697
|
+
async list(options = {}) {
|
|
184698
|
+
const workDir = options.workDir === void 0 ? void 0 : normalizeRequiredWorkDir(options.workDir);
|
|
184699
|
+
const sessionId = normalizeOptionalSessionId$1(options.sessionId);
|
|
184700
|
+
const includeArchive = options.includeArchive === true;
|
|
184701
|
+
if (workDir !== void 0) {
|
|
184702
|
+
if (sessionId !== void 0) {
|
|
184703
|
+
const local = await this.summaryFromWorkDirSession(sessionId, workDir, includeArchive);
|
|
184704
|
+
if (local !== void 0) return [local];
|
|
184705
|
+
return this.listSessionId(sessionId, includeArchive);
|
|
184706
|
+
}
|
|
184707
|
+
return this.listWorkDir(workDir, includeArchive);
|
|
184708
|
+
}
|
|
184709
|
+
if (sessionId !== void 0) return this.listSessionId(sessionId, includeArchive);
|
|
184710
|
+
return this.listAll(includeArchive);
|
|
184711
|
+
}
|
|
184712
|
+
/**
|
|
184713
|
+
* Rebuild the global session index from the session directories on disk.
|
|
184714
|
+
*
|
|
184715
|
+
* The bucket directory name is a one-way hash of the workDir, so the workDir
|
|
184716
|
+
* can only be recovered from each session's self-describing `state.json`
|
|
184717
|
+
* (`workDir`, falling back to `custom.cwd` for older sessions). Sessions that
|
|
184718
|
+
* record no workDir, or whose recorded workDir does not match the bucket they
|
|
184719
|
+
* live in, are left untouched rather than writing a misleading entry.
|
|
184720
|
+
*
|
|
184721
|
+
* The index is append-only and `readSessionIndex` lets later lines override
|
|
184722
|
+
* earlier ones for the same id, so appending a corrected line both adds
|
|
184723
|
+
* missing entries and repairs stale ones. Best-effort: never throws.
|
|
184724
|
+
*/
|
|
184725
|
+
async reindex() {
|
|
184726
|
+
const index = await readSessionIndex$1(this.homeDir, this.sessionsDir);
|
|
184727
|
+
let bucketEntries;
|
|
184728
|
+
try {
|
|
184729
|
+
bucketEntries = await readdir$1(this.sessionsDir, { withFileTypes: true });
|
|
184730
|
+
} catch {
|
|
184731
|
+
return {
|
|
184732
|
+
scanned: 0,
|
|
184733
|
+
added: 0,
|
|
184734
|
+
repaired: 0
|
|
184735
|
+
};
|
|
184736
|
+
}
|
|
184737
|
+
let scanned = 0;
|
|
184738
|
+
let added = 0;
|
|
184739
|
+
let repaired = 0;
|
|
184740
|
+
for (const bucket of bucketEntries) {
|
|
184741
|
+
if (!bucket.isDirectory()) continue;
|
|
184742
|
+
const bucketDir = join$4(this.sessionsDir, bucket.name);
|
|
184743
|
+
let sessionEntries;
|
|
184744
|
+
try {
|
|
184745
|
+
sessionEntries = await readdir$1(bucketDir, { withFileTypes: true });
|
|
184746
|
+
} catch {
|
|
184747
|
+
continue;
|
|
184748
|
+
}
|
|
184749
|
+
for (const entry of sessionEntries) {
|
|
184750
|
+
if (!entry.isDirectory()) continue;
|
|
184751
|
+
const id = entry.name;
|
|
184752
|
+
if (!isSafeSessionId(id)) continue;
|
|
184753
|
+
const sessionDir = join$4(bucketDir, id);
|
|
184754
|
+
const workDir = await this.recoverWorkDir(sessionDir);
|
|
184755
|
+
if (workDir === void 0) continue;
|
|
184756
|
+
scanned++;
|
|
184757
|
+
let expectedDir;
|
|
184758
|
+
try {
|
|
184759
|
+
expectedDir = this.sessionDirFor({
|
|
184760
|
+
id,
|
|
184761
|
+
workDir
|
|
184762
|
+
});
|
|
184763
|
+
} catch {
|
|
184764
|
+
continue;
|
|
184765
|
+
}
|
|
184766
|
+
if (resolve$2(sessionDir) !== resolve$2(expectedDir)) continue;
|
|
184767
|
+
const existing = index.get(id);
|
|
184768
|
+
if (existing !== void 0 && resolve$2(existing.sessionDir) === resolve$2(sessionDir) && existing.workDir === workDir) continue;
|
|
184769
|
+
await appendSessionIndexEntry(this.homeDir, {
|
|
184770
|
+
sessionId: id,
|
|
184771
|
+
sessionDir,
|
|
184772
|
+
workDir
|
|
184773
|
+
});
|
|
184774
|
+
index.set(id, {
|
|
184775
|
+
sessionId: id,
|
|
184776
|
+
sessionDir,
|
|
184777
|
+
workDir
|
|
184778
|
+
});
|
|
184779
|
+
if (existing === void 0) added++;
|
|
184780
|
+
else repaired++;
|
|
184781
|
+
}
|
|
184782
|
+
}
|
|
184783
|
+
return {
|
|
184784
|
+
scanned,
|
|
184785
|
+
added,
|
|
184786
|
+
repaired
|
|
184787
|
+
};
|
|
184788
|
+
}
|
|
184789
|
+
async recoverWorkDir(sessionDir) {
|
|
184790
|
+
const state = await readOptionalState(sessionDir);
|
|
184791
|
+
if (state?.workDir !== void 0) try {
|
|
184792
|
+
return normalizeWorkDir(state.workDir);
|
|
184793
|
+
} catch {
|
|
184794
|
+
return;
|
|
184795
|
+
}
|
|
184796
|
+
const legacyCwd = state?.custom?.["cwd"];
|
|
184797
|
+
if (typeof legacyCwd === "string" && legacyCwd.length > 0) try {
|
|
184798
|
+
return normalizeWorkDir(legacyCwd);
|
|
184799
|
+
} catch {
|
|
184800
|
+
return;
|
|
184801
|
+
}
|
|
184802
|
+
}
|
|
184803
|
+
async listWorkDir(workDir, includeArchive) {
|
|
184804
|
+
const bucketDir = join$4(this.sessionsDir, encodeWorkDirKey(workDir));
|
|
184805
|
+
let entries;
|
|
184806
|
+
try {
|
|
184807
|
+
entries = await readdir$1(bucketDir, { withFileTypes: true });
|
|
184808
|
+
} catch {
|
|
184809
|
+
return [];
|
|
184810
|
+
}
|
|
184811
|
+
const sessions = [];
|
|
184812
|
+
for (const entry of entries) {
|
|
184813
|
+
if (!entry.isDirectory()) continue;
|
|
184814
|
+
const id = entry.name;
|
|
184815
|
+
if (!isSafeSessionId(id)) continue;
|
|
184816
|
+
const dir = join$4(bucketDir, id);
|
|
184817
|
+
const summary = await this.summaryFromDir(id, dir, workDir);
|
|
184818
|
+
if (!includeArchive && summary.archived === true) continue;
|
|
184819
|
+
sessions.push(summary);
|
|
184820
|
+
}
|
|
184821
|
+
sessions.sort(compareSessionSummary);
|
|
184822
|
+
return sessions;
|
|
184823
|
+
}
|
|
184824
|
+
async listSessionId(sessionId, includeArchive) {
|
|
184825
|
+
try {
|
|
184826
|
+
const summary = await this.get(sessionId);
|
|
184827
|
+
if (!includeArchive && summary.archived === true) return [];
|
|
184828
|
+
return [summary];
|
|
184829
|
+
} catch (error) {
|
|
184830
|
+
if (error instanceof KimiError && error.code === ErrorCodes.SESSION_NOT_FOUND) return [];
|
|
184831
|
+
throw error;
|
|
184832
|
+
}
|
|
184833
|
+
}
|
|
184834
|
+
async listAll(includeArchive) {
|
|
184835
|
+
const index = await readSessionIndex$1(this.homeDir, this.sessionsDir);
|
|
184836
|
+
const sessions = [];
|
|
184837
|
+
for (const entry of index.values()) {
|
|
184838
|
+
if (!await isDirectory(entry.sessionDir)) continue;
|
|
184839
|
+
const summary = await this.summaryFromDir(entry.sessionId, entry.sessionDir, entry.workDir);
|
|
184840
|
+
if (!includeArchive && summary.archived === true) continue;
|
|
184841
|
+
sessions.push(summary);
|
|
184842
|
+
}
|
|
184843
|
+
sessions.sort(compareSessionSummary);
|
|
184844
|
+
return sessions;
|
|
184845
|
+
}
|
|
184846
|
+
async summaryFromWorkDirSession(sessionId, workDir, includeArchive) {
|
|
184847
|
+
if (!isSafeSessionId(sessionId)) return void 0;
|
|
184848
|
+
const sessionDir = this.sessionDirFor({
|
|
184849
|
+
id: sessionId,
|
|
184850
|
+
workDir
|
|
184851
|
+
});
|
|
184852
|
+
if (!await isDirectory(sessionDir)) return void 0;
|
|
184853
|
+
const summary = await this.summaryFromDir(sessionId, sessionDir, workDir);
|
|
184854
|
+
if (!includeArchive && summary.archived === true) return void 0;
|
|
184855
|
+
return summary;
|
|
184856
|
+
}
|
|
184857
|
+
async assertDirectory(id) {
|
|
184858
|
+
return (await this.findExistingSessionEntry(id)).sessionDir;
|
|
184859
|
+
}
|
|
184860
|
+
async findSessionEntry(id) {
|
|
184861
|
+
if (!isSafeSessionId(id)) return void 0;
|
|
184862
|
+
return (await readSessionIndex$1(this.homeDir, this.sessionsDir)).get(id);
|
|
184863
|
+
}
|
|
184864
|
+
async findExistingSessionEntry(id) {
|
|
184865
|
+
const entry = await this.findSessionEntry(id);
|
|
184866
|
+
if (entry !== void 0 && await isDirectory(entry.sessionDir)) return entry;
|
|
184867
|
+
throw new KimiError(ErrorCodes.SESSION_NOT_FOUND, `Session "${id}" was not found`, { details: { sessionId: id } });
|
|
184868
|
+
}
|
|
184869
|
+
async writeForkedState(input, sourceDir, sourceWorkDir, targetDir) {
|
|
184870
|
+
const statePath = join$4(targetDir, "state.json");
|
|
184871
|
+
let parsed;
|
|
184872
|
+
try {
|
|
184873
|
+
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
184874
|
+
} catch (error) {
|
|
184875
|
+
throw new KimiError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${input.sourceId}" state.json was not found`, { cause: error });
|
|
184876
|
+
}
|
|
184877
|
+
if (!isRecord$11(parsed)) throw new KimiError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
|
|
184878
|
+
const title = normalizeForkTitle(input.title, parsed["title"]);
|
|
184879
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
184880
|
+
const next = {
|
|
184881
|
+
...parsed,
|
|
184882
|
+
createdAt: now,
|
|
184883
|
+
updatedAt: now,
|
|
184884
|
+
workDir: sourceWorkDir,
|
|
184885
|
+
title,
|
|
184886
|
+
isCustomTitle: input.title === void 0 ? parsed["isCustomTitle"] === true : true,
|
|
184887
|
+
forkedFrom: input.sourceId,
|
|
184888
|
+
agents: rewriteAgentHomedirs(parsed["agents"], sourceDir, targetDir),
|
|
184889
|
+
custom: forkCustomMetadata(parsed["custom"], input.metadata)
|
|
184890
|
+
};
|
|
184891
|
+
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
184892
|
+
return next;
|
|
184893
|
+
}
|
|
184894
|
+
async summaryFromDir(id, sessionDir, workDir) {
|
|
184895
|
+
const dirStat = await stat$2(sessionDir);
|
|
184896
|
+
const state = await readOptionalState(sessionDir);
|
|
184897
|
+
const [stateInfo, wireInfo, agentsWireMtime] = await Promise.all([
|
|
184898
|
+
statIfExists(join$4(sessionDir, "state.json")),
|
|
184899
|
+
statIfExists(join$4(sessionDir, "wire.jsonl")),
|
|
184900
|
+
latestAgentWireMtime(sessionDir)
|
|
184901
|
+
]);
|
|
184902
|
+
return {
|
|
184903
|
+
id,
|
|
184904
|
+
workDir: state?.workDir ?? workDir,
|
|
184905
|
+
sessionDir,
|
|
184906
|
+
createdAt: timestampOrFallback(dirStat.birthtimeMs, dirStat.ctimeMs),
|
|
184907
|
+
updatedAt: Math.max(dirStat.mtimeMs, stateInfo?.mtimeMs ?? 0, wireInfo?.mtimeMs ?? 0, agentsWireMtime ?? 0),
|
|
184908
|
+
archived: state?.archived === true,
|
|
184909
|
+
title: titleFromState(state),
|
|
184910
|
+
lastPrompt: state?.lastPrompt,
|
|
184911
|
+
metadata: metadataFromState(state)
|
|
184912
|
+
};
|
|
184913
|
+
}
|
|
184914
|
+
};
|
|
184915
|
+
}));
|
|
184916
|
+
//#endregion
|
|
184917
|
+
//#region ../../packages/agent-core/src/session/store/index.ts
|
|
184918
|
+
var init_store$1 = __esmMin((() => {
|
|
184919
|
+
init_session_store$1();
|
|
184920
|
+
init_session_index();
|
|
184921
|
+
init_workdir_key();
|
|
184922
|
+
}));
|
|
184923
|
+
//#endregion
|
|
183820
184924
|
//#region ../../packages/agent-core/src/session/index.ts
|
|
183821
184925
|
async function waitForSettlementOrTimeout(promise, timeoutMs) {
|
|
183822
184926
|
let timeout;
|
|
@@ -183859,6 +184963,7 @@ var init_session$1 = __esmMin((() => {
|
|
|
183859
184963
|
init_flags();
|
|
183860
184964
|
init_abort();
|
|
183861
184965
|
init_subagent_host();
|
|
184966
|
+
init_store$1();
|
|
183862
184967
|
BACKGROUND_KEEP_ALIVE_ON_EXIT_ENV = "KIMI_CODE_BACKGROUND_KEEP_ALIVE_ON_EXIT";
|
|
183863
184968
|
ACTIVE_TURN_CLOSE_TIMEOUT_MS = 8e3;
|
|
183864
184969
|
Session$1 = class {
|
|
@@ -184993,7 +186098,7 @@ async function writeInstalled(kimiHomeDir, data) {
|
|
|
184993
186098
|
await rename(tmp, final);
|
|
184994
186099
|
}
|
|
184995
186100
|
var INSTALLED_REL, EMPTY;
|
|
184996
|
-
var init_store
|
|
186101
|
+
var init_store = __esmMin((() => {
|
|
184997
186102
|
INSTALLED_REL = path.join("plugins", "installed.json");
|
|
184998
186103
|
EMPTY = {
|
|
184999
186104
|
version: 1,
|
|
@@ -185488,7 +186593,7 @@ var init_manager = __esmMin((() => {
|
|
|
185488
186593
|
init_archive();
|
|
185489
186594
|
init_github_resolver();
|
|
185490
186595
|
init_manifest$1();
|
|
185491
|
-
init_store
|
|
186596
|
+
init_store();
|
|
185492
186597
|
init_source();
|
|
185493
186598
|
init_types$1();
|
|
185494
186599
|
KIMI_NODE_FALLBACK_SUBCOMMAND = "__plugin_run_node";
|
|
@@ -185766,7 +186871,7 @@ var init_manager = __esmMin((() => {
|
|
|
185766
186871
|
var init_plugin$1 = __esmMin((() => {
|
|
185767
186872
|
init_types$1();
|
|
185768
186873
|
init_manifest$1();
|
|
185769
|
-
init_store
|
|
186874
|
+
init_store();
|
|
185770
186875
|
init_manager();
|
|
185771
186876
|
init_source();
|
|
185772
186877
|
init_archive();
|
|
@@ -200316,7 +201421,7 @@ function tokenFromWire(wire) {
|
|
|
200316
201421
|
var init_types = __esmMin((() => {}));
|
|
200317
201422
|
//#endregion
|
|
200318
201423
|
//#region ../../packages/oauth/src/utils.ts
|
|
200319
|
-
function isRecord$
|
|
201424
|
+
function isRecord$10(value) {
|
|
200320
201425
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
200321
201426
|
}
|
|
200322
201427
|
var init_utils = __esmMin((() => {}));
|
|
@@ -200372,7 +201477,7 @@ var init_storage = __esmMin((() => {
|
|
|
200372
201477
|
} catch {
|
|
200373
201478
|
return;
|
|
200374
201479
|
}
|
|
200375
|
-
if (!isRecord$
|
|
201480
|
+
if (!isRecord$10(parsed)) return void 0;
|
|
200376
201481
|
return tokenFromWire(parsed);
|
|
200377
201482
|
}
|
|
200378
201483
|
async save(name, token) {
|
|
@@ -200426,7 +201531,7 @@ function extractApiErrorMessage(value) {
|
|
|
200426
201531
|
}
|
|
200427
201532
|
return;
|
|
200428
201533
|
}
|
|
200429
|
-
if (!isRecord$
|
|
201534
|
+
if (!isRecord$10(value)) return void 0;
|
|
200430
201535
|
for (const key of DIRECT_ERROR_KEYS) {
|
|
200431
201536
|
const message = stringField$3(value, key);
|
|
200432
201537
|
if (message !== void 0) return message;
|
|
@@ -200434,7 +201539,7 @@ function extractApiErrorMessage(value) {
|
|
|
200434
201539
|
const error = value["error"];
|
|
200435
201540
|
const errorString = nonEmptyString$2(error);
|
|
200436
201541
|
if (errorString !== void 0) return errorString;
|
|
200437
|
-
if (isRecord$
|
|
201542
|
+
if (isRecord$10(error)) for (const key of NESTED_ERROR_KEYS) {
|
|
200438
201543
|
const message = stringField$3(error, key);
|
|
200439
201544
|
if (message !== void 0) return message;
|
|
200440
201545
|
}
|
|
@@ -200524,7 +201629,7 @@ async function postForm(url, params, deviceHeaders, options) {
|
|
|
200524
201629
|
let data = {};
|
|
200525
201630
|
try {
|
|
200526
201631
|
const parsed = await response.json();
|
|
200527
|
-
if (isRecord$
|
|
201632
|
+
if (isRecord$10(parsed)) data = parsed;
|
|
200528
201633
|
} catch {}
|
|
200529
201634
|
return {
|
|
200530
201635
|
status,
|
|
@@ -202397,9 +203502,9 @@ function parseManagedUsagePayload(payload) {
|
|
|
202397
203502
|
const item = rawLimits[idx];
|
|
202398
203503
|
if (!item || typeof item !== "object") continue;
|
|
202399
203504
|
const detailRaw = item["detail"];
|
|
202400
|
-
const detail = isRecord$
|
|
203505
|
+
const detail = isRecord$10(detailRaw) ? detailRaw : item;
|
|
202401
203506
|
const windowRaw = item["window"];
|
|
202402
|
-
const row = toUsageRow(detail, limitLabel(item, detail, isRecord$
|
|
203507
|
+
const row = toUsageRow(detail, limitLabel(item, detail, isRecord$10(windowRaw) ? windowRaw : {}, idx));
|
|
202403
203508
|
if (row !== null) limits.push(row);
|
|
202404
203509
|
}
|
|
202405
203510
|
return {
|
|
@@ -202408,7 +203513,7 @@ function parseManagedUsagePayload(payload) {
|
|
|
202408
203513
|
};
|
|
202409
203514
|
}
|
|
202410
203515
|
function toUsageRow(raw, defaultLabel) {
|
|
202411
|
-
if (!isRecord$
|
|
203516
|
+
if (!isRecord$10(raw)) return null;
|
|
202412
203517
|
const limit = toInt(raw["limit"]);
|
|
202413
203518
|
let used = toInt(raw["used"]);
|
|
202414
203519
|
if (used === null) {
|
|
@@ -202561,8 +203666,8 @@ function userExtras(existing, remoteOwnedFields) {
|
|
|
202561
203666
|
return out;
|
|
202562
203667
|
}
|
|
202563
203668
|
function mergeRefreshedModelAlias(existing, remote, remoteOwnedFields) {
|
|
202564
|
-
const current = isRecord$
|
|
202565
|
-
const overrides = cloneOverrides(isRecord$
|
|
203669
|
+
const current = isRecord$10(existing) ? existing : {};
|
|
203670
|
+
const overrides = cloneOverrides(isRecord$10(current["overrides"]) ? current["overrides"] : void 0);
|
|
202566
203671
|
return {
|
|
202567
203672
|
...userExtras(current, remoteOwnedFields),
|
|
202568
203673
|
...remote,
|
|
@@ -202742,7 +203847,7 @@ function resolveKimiCodeLoginAuth(options) {
|
|
|
202742
203847
|
};
|
|
202743
203848
|
}
|
|
202744
203849
|
function toModelInfo$1(item) {
|
|
202745
|
-
if (!isRecord$
|
|
203850
|
+
if (!isRecord$10(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
|
|
202746
203851
|
const contextLength = Number(item["context_length"]);
|
|
202747
203852
|
if (!Number.isInteger(contextLength) || contextLength <= 0) throw new Error(`Kimi Code model "${item["id"]}" must include a positive context_length.`);
|
|
202748
203853
|
const displayName = item["display_name"];
|
|
@@ -202813,7 +203918,7 @@ async function fetchManagedKimiCodeModels(options) {
|
|
|
202813
203918
|
throw new Error(message);
|
|
202814
203919
|
}
|
|
202815
203920
|
const payload = await response.json();
|
|
202816
|
-
if (!isRecord$
|
|
203921
|
+
if (!isRecord$10(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${baseUrl}.`);
|
|
202817
203922
|
return payload["data"].map((item) => toModelInfo$1(item)).filter((item) => item !== void 0);
|
|
202818
203923
|
}
|
|
202819
203924
|
function applyManagedKimiCodeConfig(config, options) {
|
|
@@ -202836,11 +203941,11 @@ function applyManagedKimiCodeConfig(config, options) {
|
|
|
202836
203941
|
oauth
|
|
202837
203942
|
};
|
|
202838
203943
|
const upstreamKeys = new Set(options.models.map((m) => managedModelKey(m.id)));
|
|
202839
|
-
for (const [key, model] of Object.entries(existingModels)) if (isRecord$
|
|
203944
|
+
for (const [key, model] of Object.entries(existingModels)) if (isRecord$10(model) && model["provider"] === "managed:kimi-code" && !upstreamKeys.has(key)) delete existingModels[key];
|
|
202840
203945
|
for (const model of options.models) {
|
|
202841
203946
|
const capabilities = capabilitiesForModel$1(model);
|
|
202842
203947
|
const key = managedModelKey(model.id);
|
|
202843
|
-
const existing = isRecord$
|
|
203948
|
+
const existing = isRecord$10(existingModels[key]) ? existingModels[key] : {};
|
|
202844
203949
|
const supportsAdaptiveThinking = model.protocol === "anthropic" && (capabilities?.includes("thinking") === true || capabilities?.includes("always_thinking") === true);
|
|
202845
203950
|
existingModels[key] = mergeRefreshedModelAlias(existing, {
|
|
202846
203951
|
provider: KIMI_CODE_PROVIDER_NAME$1,
|
|
@@ -202883,7 +203988,7 @@ function applyManagedKimiCodeLogoutConfig(config) {
|
|
|
202883
203988
|
let removedDefaultModel = false;
|
|
202884
203989
|
const existingModels = config.models ?? {};
|
|
202885
203990
|
for (const [key, model] of Object.entries(existingModels)) {
|
|
202886
|
-
if (!isRecord$
|
|
203991
|
+
if (!isRecord$10(model) || model["provider"] !== "managed:kimi-code") continue;
|
|
202887
203992
|
delete existingModels[key];
|
|
202888
203993
|
if (config.defaultModel === key) removedDefaultModel = true;
|
|
202889
203994
|
}
|
|
@@ -202922,7 +204027,7 @@ function selectDefaultModel(config, models, options) {
|
|
|
202922
204027
|
function canPreserveDefaultModel(existingModels, defaultModel, managedModels) {
|
|
202923
204028
|
if (managedModels.has(defaultModel)) return true;
|
|
202924
204029
|
const existing = existingModels[defaultModel];
|
|
202925
|
-
return isRecord$
|
|
204030
|
+
return isRecord$10(existing) && existing["provider"] !== "managed:kimi-code";
|
|
202926
204031
|
}
|
|
202927
204032
|
function assertPositiveContextLength(model) {
|
|
202928
204033
|
if (!Number.isInteger(model.contextLength) || model.contextLength <= 0) throw new Error(`Kimi Code model "${model.id}" must include a positive context_length.`);
|
|
@@ -203162,7 +204267,7 @@ function isOpenPlatformId(id) {
|
|
|
203162
204267
|
return OPEN_PLATFORMS.some((p) => p.id === id);
|
|
203163
204268
|
}
|
|
203164
204269
|
function toModelInfo(item) {
|
|
203165
|
-
if (!isRecord$
|
|
204270
|
+
if (!isRecord$10(item) || typeof item["id"] !== "string" || item["id"].length === 0) return;
|
|
203166
204271
|
const contextLength = Number(item["context_length"]);
|
|
203167
204272
|
if (!Number.isInteger(contextLength) || contextLength <= 0) throw new Error(`Model "${item["id"]}" must include a positive context_length.`);
|
|
203168
204273
|
const displayName = item["display_name"];
|
|
@@ -203213,7 +204318,7 @@ async function fetchOpenPlatformModels(platform, apiKey, fetchImpl = fetch, sign
|
|
|
203213
204318
|
});
|
|
203214
204319
|
if (!res.ok) throw new OpenPlatformApiError(await readApiErrorMessage(res, `Failed to list models (HTTP ${res.status}).`), res.status);
|
|
203215
204320
|
const payload = await res.json();
|
|
203216
|
-
if (!isRecord$
|
|
204321
|
+
if (!isRecord$10(payload) || !Array.isArray(payload["data"])) throw new Error(`Unexpected models response for ${platform.baseUrl}.`);
|
|
203217
204322
|
return payload["data"].map((item) => toModelInfo(item)).filter((item) => item !== void 0);
|
|
203218
204323
|
}
|
|
203219
204324
|
function filterModelsByPrefix(models, platform) {
|
|
@@ -203231,10 +204336,10 @@ function applyOpenPlatformConfig(config, options) {
|
|
|
203231
204336
|
};
|
|
203232
204337
|
const existingModels = config.models ?? {};
|
|
203233
204338
|
const upstreamKeys = new Set(options.models.map((m) => `${providerKey}/${m.id}`));
|
|
203234
|
-
for (const [key, model] of Object.entries(existingModels)) if (isRecord$
|
|
204339
|
+
for (const [key, model] of Object.entries(existingModels)) if (isRecord$10(model) && model["provider"] === providerKey && !upstreamKeys.has(key)) delete existingModels[key];
|
|
203235
204340
|
for (const model of options.models) {
|
|
203236
204341
|
const aliasKey = `${providerKey}/${model.id}`;
|
|
203237
|
-
existingModels[aliasKey] = mergeRefreshedModelAlias(isRecord$
|
|
204342
|
+
existingModels[aliasKey] = mergeRefreshedModelAlias(isRecord$10(existingModels[aliasKey]) ? existingModels[aliasKey] : {}, {
|
|
203238
204343
|
provider: providerKey,
|
|
203239
204344
|
model: model.id,
|
|
203240
204345
|
maxContextSize: model.contextLength,
|
|
@@ -203300,14 +204405,14 @@ function toStringArrayOrUndefined(value) {
|
|
|
203300
204405
|
return out;
|
|
203301
204406
|
}
|
|
203302
204407
|
function toModelEntry(value) {
|
|
203303
|
-
if (!isRecord$
|
|
204408
|
+
if (!isRecord$10(value)) return void 0;
|
|
203304
204409
|
const id = value["id"];
|
|
203305
204410
|
if (typeof id !== "string" || id.length === 0) return void 0;
|
|
203306
204411
|
const entry = { id };
|
|
203307
204412
|
const name = value["name"];
|
|
203308
204413
|
if (typeof name === "string" && name.length > 0) entry.name = name;
|
|
203309
204414
|
const limit = value["limit"];
|
|
203310
|
-
if (isRecord$
|
|
204415
|
+
if (isRecord$10(limit)) {
|
|
203311
204416
|
const context = limit["context"];
|
|
203312
204417
|
const output = limit["output"];
|
|
203313
204418
|
const parsedLimit = {};
|
|
@@ -203318,7 +204423,7 @@ function toModelEntry(value) {
|
|
|
203318
204423
|
if (typeof value["tool_call"] === "boolean") entry.tool_call = value["tool_call"];
|
|
203319
204424
|
if (typeof value["reasoning"] === "boolean") entry.reasoning = value["reasoning"];
|
|
203320
204425
|
const modalities = value["modalities"];
|
|
203321
|
-
if (isRecord$
|
|
204426
|
+
if (isRecord$10(modalities)) {
|
|
203322
204427
|
const input = toStringArrayOrUndefined(modalities["input"]);
|
|
203323
204428
|
const output = toStringArrayOrUndefined(modalities["output"]);
|
|
203324
204429
|
if (input !== void 0 || output !== void 0) entry.modalities = {
|
|
@@ -203329,7 +204434,7 @@ function toModelEntry(value) {
|
|
|
203329
204434
|
return entry;
|
|
203330
204435
|
}
|
|
203331
204436
|
function toProviderEntry(value) {
|
|
203332
|
-
if (!isRecord$
|
|
204437
|
+
if (!isRecord$10(value)) return void 0;
|
|
203333
204438
|
const id = value["id"];
|
|
203334
204439
|
const name = value["name"];
|
|
203335
204440
|
const api = value["api"];
|
|
@@ -203339,7 +204444,7 @@ function toProviderEntry(value) {
|
|
|
203339
204444
|
if (typeof name !== "string" || name.length === 0) return void 0;
|
|
203340
204445
|
if (typeof api !== "string" || api.length === 0) return void 0;
|
|
203341
204446
|
if (!isAllowedProviderType(type)) return void 0;
|
|
203342
|
-
if (!isRecord$
|
|
204447
|
+
if (!isRecord$10(models)) return void 0;
|
|
203343
204448
|
const parsedModels = {};
|
|
203344
204449
|
for (const [key, raw] of Object.entries(models)) {
|
|
203345
204450
|
const modelEntry = toModelEntry(raw);
|
|
@@ -203369,7 +204474,7 @@ async function fetchCustomRegistry(source, fetchImpl = fetch, signal) {
|
|
|
203369
204474
|
const response = await fetchImpl(source.url, init);
|
|
203370
204475
|
if (!response.ok) throw new CustomRegistryApiError(await readApiErrorMessage(response, `Failed to fetch custom registry at ${source.url} (HTTP ${response.status}).`), response.status);
|
|
203371
204476
|
const payload = await response.json();
|
|
203372
|
-
if (!isRecord$
|
|
204477
|
+
if (!isRecord$10(payload)) throw new Error(`Unexpected custom registry response at ${source.url}: expected a JSON object keyed by provider id.`);
|
|
203373
204478
|
const out = {};
|
|
203374
204479
|
for (const [key, raw] of Object.entries(payload)) {
|
|
203375
204480
|
const entry = toProviderEntry(raw);
|
|
@@ -203429,13 +204534,13 @@ function applyCustomRegistryProvider(config, entry, source) {
|
|
|
203429
204534
|
};
|
|
203430
204535
|
const existingModels = config.models ?? {};
|
|
203431
204536
|
const upstreamKeys = new Set(Object.keys(entry.models).map((modelKey) => `${providerKey}/${modelKey}`));
|
|
203432
|
-
for (const [key, alias] of Object.entries(existingModels)) if (isRecord$
|
|
204537
|
+
for (const [key, alias] of Object.entries(existingModels)) if (isRecord$10(alias) && alias["provider"] === providerKey && !upstreamKeys.has(key)) delete existingModels[key];
|
|
203433
204538
|
for (const [modelKey, model] of Object.entries(entry.models)) {
|
|
203434
204539
|
const aliasKey = `${providerKey}/${modelKey}`;
|
|
203435
204540
|
const maxContextSize = resolveMaxContextSize(model);
|
|
203436
204541
|
const capabilities = resolveCapabilities(model);
|
|
203437
204542
|
const displayName = typeof model.name === "string" && model.name.length > 0 ? model.name : model.id;
|
|
203438
|
-
existingModels[aliasKey] = mergeRefreshedModelAlias(isRecord$
|
|
204543
|
+
existingModels[aliasKey] = mergeRefreshedModelAlias(isRecord$10(existingModels[aliasKey]) ? existingModels[aliasKey] : {}, {
|
|
203439
204544
|
provider: providerKey,
|
|
203440
204545
|
model: model.id,
|
|
203441
204546
|
maxContextSize,
|
|
@@ -203455,7 +204560,7 @@ function removeCustomRegistryProvider(config, providerId) {
|
|
|
203455
204560
|
let removedDefault = false;
|
|
203456
204561
|
const existingModels = config.models ?? {};
|
|
203457
204562
|
for (const [key, alias] of Object.entries(existingModels)) {
|
|
203458
|
-
if (!isRecord$
|
|
204563
|
+
if (!isRecord$10(alias) || alias["provider"] !== providerId) continue;
|
|
203459
204564
|
delete existingModels[key];
|
|
203460
204565
|
if (config.defaultModel === key) removedDefault = true;
|
|
203461
204566
|
}
|
|
@@ -203487,9 +204592,9 @@ function applyCustomRegistryEntries(config, entries, source) {
|
|
|
203487
204592
|
const surviving = new Set(Object.values(entries).map((entry) => entry.id));
|
|
203488
204593
|
for (const [providerId, provider] of Object.entries(config.providers)) {
|
|
203489
204594
|
if (surviving.has(providerId)) continue;
|
|
203490
|
-
if (!isRecord$
|
|
204595
|
+
if (!isRecord$10(provider)) continue;
|
|
203491
204596
|
const existingSource = provider["source"];
|
|
203492
|
-
if (isRecord$
|
|
204597
|
+
if (isRecord$10(existingSource) && existingSource["kind"] === "apiJson" && existingSource["url"] === source.url) removeCustomRegistryProvider(config, providerId);
|
|
203493
204598
|
}
|
|
203494
204599
|
for (const entry of Object.values(entries)) {
|
|
203495
204600
|
if (entry.id in config.providers) removeCustomRegistryProvider(config, entry.id);
|
|
@@ -204187,7 +205292,8 @@ function resolveModelCapabilities(alias, provider) {
|
|
|
204187
205292
|
audio_in: declared.has("audio_in") || detected.audio_in,
|
|
204188
205293
|
thinking: declared.has("thinking") || declared.has("always_thinking") || detected.thinking,
|
|
204189
205294
|
tool_use: declared.has("tool_use") || detected.tool_use,
|
|
204190
|
-
max_context_tokens: alias.maxContextSize
|
|
205295
|
+
max_context_tokens: alias.maxContextSize,
|
|
205296
|
+
select_tools: declared.has("select_tools") || detected.select_tools === true
|
|
204191
205297
|
};
|
|
204192
205298
|
}
|
|
204193
205299
|
function toKosongProviderConfig(provider, model, modelProtocol, kimiRequestHeaders, maxOutputSize, reasoningKey, promptCacheKey, adaptiveThinking, betaApi, supportEfforts) {
|
|
@@ -204691,498 +205797,6 @@ var init_rpc$1 = __esmMin((() => {
|
|
|
204691
205797
|
};
|
|
204692
205798
|
}));
|
|
204693
205799
|
//#endregion
|
|
204694
|
-
//#region ../../packages/agent-core/src/session/store/session-index.ts
|
|
204695
|
-
function sessionIndexPath(homeDir) {
|
|
204696
|
-
return join$4(homeDir, "session_index.jsonl");
|
|
204697
|
-
}
|
|
204698
|
-
async function appendSessionIndexEntry(homeDir, entry) {
|
|
204699
|
-
const indexPath = sessionIndexPath(homeDir);
|
|
204700
|
-
await mkdir(dirname$3(indexPath), {
|
|
204701
|
-
recursive: true,
|
|
204702
|
-
mode: 448
|
|
204703
|
-
});
|
|
204704
|
-
await appendFile(indexPath, `${JSON.stringify(entry)}\n`, "utf-8");
|
|
204705
|
-
}
|
|
204706
|
-
async function readSessionIndex$1(homeDir, sessionsDir) {
|
|
204707
|
-
let raw;
|
|
204708
|
-
try {
|
|
204709
|
-
raw = await readFile(sessionIndexPath(homeDir), "utf-8");
|
|
204710
|
-
} catch {
|
|
204711
|
-
return /* @__PURE__ */ new Map();
|
|
204712
|
-
}
|
|
204713
|
-
const result = /* @__PURE__ */ new Map();
|
|
204714
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
204715
|
-
const trimmed = line.trim();
|
|
204716
|
-
if (trimmed === "") continue;
|
|
204717
|
-
const entry = parseIndexLine(trimmed);
|
|
204718
|
-
if (entry === void 0) continue;
|
|
204719
|
-
const sessionDir = resolve$2(entry.sessionDir);
|
|
204720
|
-
if (!isAbsolute$2(entry.sessionDir)) continue;
|
|
204721
|
-
if (!isAbsolute$2(entry.workDir)) continue;
|
|
204722
|
-
if (!isPathInside(sessionsDir, sessionDir)) continue;
|
|
204723
|
-
if (basename$2(sessionDir) !== entry.sessionId) continue;
|
|
204724
|
-
result.set(entry.sessionId, {
|
|
204725
|
-
sessionId: entry.sessionId,
|
|
204726
|
-
sessionDir,
|
|
204727
|
-
workDir: resolve$2(entry.workDir)
|
|
204728
|
-
});
|
|
204729
|
-
}
|
|
204730
|
-
return result;
|
|
204731
|
-
}
|
|
204732
|
-
function parseIndexLine(line) {
|
|
204733
|
-
try {
|
|
204734
|
-
const parsed = JSON.parse(line);
|
|
204735
|
-
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
204736
|
-
const entry = parsed;
|
|
204737
|
-
if (typeof entry.sessionId !== "string" || typeof entry.sessionDir !== "string" || typeof entry.workDir !== "string") return;
|
|
204738
|
-
return {
|
|
204739
|
-
sessionId: entry.sessionId,
|
|
204740
|
-
sessionDir: entry.sessionDir,
|
|
204741
|
-
workDir: entry.workDir
|
|
204742
|
-
};
|
|
204743
|
-
} catch {
|
|
204744
|
-
return;
|
|
204745
|
-
}
|
|
204746
|
-
}
|
|
204747
|
-
function isPathInside(parent, child) {
|
|
204748
|
-
const rel = relative$1(resolve$2(parent), resolve$2(child));
|
|
204749
|
-
return rel !== "" && !rel.startsWith("..") && !isAbsolute$2(rel);
|
|
204750
|
-
}
|
|
204751
|
-
var init_session_index = __esmMin((() => {
|
|
204752
|
-
init_dist$7();
|
|
204753
|
-
}));
|
|
204754
|
-
//#endregion
|
|
204755
|
-
//#region ../../packages/agent-core/src/utils/workdir-slug.ts
|
|
204756
|
-
function slugifyWorkDirName(name) {
|
|
204757
|
-
const slug = name.toLowerCase().replaceAll(/[^a-z0-9._-]+/g, "-").replaceAll(/^-+|-+$/g, "").slice(0, MAX_WORKDIR_SLUG_LENGTH).replaceAll(/^-+|-+$/g, "");
|
|
204758
|
-
return slug === "" || slug === "." || slug === ".." ? "workspace" : slug;
|
|
204759
|
-
}
|
|
204760
|
-
var MAX_WORKDIR_SLUG_LENGTH;
|
|
204761
|
-
var init_workdir_slug = __esmMin((() => {
|
|
204762
|
-
MAX_WORKDIR_SLUG_LENGTH = 40;
|
|
204763
|
-
}));
|
|
204764
|
-
//#endregion
|
|
204765
|
-
//#region ../../packages/agent-core/src/session/store/workdir-key.ts
|
|
204766
|
-
function normalizeWorkDir(workDir) {
|
|
204767
|
-
return resolve$2(workDir);
|
|
204768
|
-
}
|
|
204769
|
-
function encodeWorkDirKey(workDir) {
|
|
204770
|
-
const normalized = normalizeWorkDir(workDir);
|
|
204771
|
-
return `${WORKDIR_KEY_PREFIX}${slugifyWorkDirName(basename$2(normalized))}_${createHash("sha256").update(normalized).digest("hex").slice(0, HASH_LENGTH)}`;
|
|
204772
|
-
}
|
|
204773
|
-
var WORKDIR_KEY_PREFIX, HASH_LENGTH;
|
|
204774
|
-
var init_workdir_key = __esmMin((() => {
|
|
204775
|
-
init_dist$7();
|
|
204776
|
-
init_workdir_slug();
|
|
204777
|
-
WORKDIR_KEY_PREFIX = "wd_";
|
|
204778
|
-
HASH_LENGTH = 12;
|
|
204779
|
-
}));
|
|
204780
|
-
//#endregion
|
|
204781
|
-
//#region ../../packages/agent-core/src/session/store/session-store.ts
|
|
204782
|
-
function metadataFromState(state) {
|
|
204783
|
-
if (state === void 0 || state.custom === void 0) return void 0;
|
|
204784
|
-
return state.custom;
|
|
204785
|
-
}
|
|
204786
|
-
function forkCustomMetadata(source, metadata) {
|
|
204787
|
-
return {
|
|
204788
|
-
...customMetadataWithoutGoal(source),
|
|
204789
|
-
...customMetadataWithoutGoal(metadata)
|
|
204790
|
-
};
|
|
204791
|
-
}
|
|
204792
|
-
async function dropForkedSessionFiles(sessionDir) {
|
|
204793
|
-
await Promise.all(FORKED_SESSION_DROPPED_FILES.map((fileName) => rm(join$4(sessionDir, fileName), { force: true })));
|
|
204794
|
-
}
|
|
204795
|
-
async function appendForkedMarkers(state) {
|
|
204796
|
-
const record = {
|
|
204797
|
-
type: "forked",
|
|
204798
|
-
time: Date.now()
|
|
204799
|
-
};
|
|
204800
|
-
const agents = state["agents"];
|
|
204801
|
-
if (!isRecord$10(agents)) return;
|
|
204802
|
-
const paths = /* @__PURE__ */ new Set();
|
|
204803
|
-
for (const agentMeta of Object.values(agents)) {
|
|
204804
|
-
if (!isRecord$10(agentMeta)) continue;
|
|
204805
|
-
const homedir = agentMeta["homedir"];
|
|
204806
|
-
if (typeof homedir !== "string") continue;
|
|
204807
|
-
paths.add(join$4(homedir, "wire.jsonl"));
|
|
204808
|
-
}
|
|
204809
|
-
await Promise.all([...paths].map(async (path) => {
|
|
204810
|
-
const persistence = new FileSystemAgentRecordPersistence(path);
|
|
204811
|
-
persistence.append(record);
|
|
204812
|
-
await persistence.flush();
|
|
204813
|
-
}));
|
|
204814
|
-
}
|
|
204815
|
-
function customMetadataWithoutGoal(value) {
|
|
204816
|
-
if (!isRecord$10(value)) return {};
|
|
204817
|
-
const custom = {};
|
|
204818
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
204819
|
-
if (key === "goal") continue;
|
|
204820
|
-
custom[key] = entry;
|
|
204821
|
-
}
|
|
204822
|
-
return custom;
|
|
204823
|
-
}
|
|
204824
|
-
async function latestAgentWireMtime(sessionDir) {
|
|
204825
|
-
const agentsDir = join$4(sessionDir, "agents");
|
|
204826
|
-
let entries;
|
|
204827
|
-
try {
|
|
204828
|
-
entries = await readdir$1(agentsDir, { withFileTypes: true });
|
|
204829
|
-
} catch {
|
|
204830
|
-
return;
|
|
204831
|
-
}
|
|
204832
|
-
let latest = 0;
|
|
204833
|
-
for (const entry of entries) {
|
|
204834
|
-
if (!entry.isDirectory()) continue;
|
|
204835
|
-
const wireInfo = await statIfExists(join$4(agentsDir, entry.name, "wire.jsonl"));
|
|
204836
|
-
latest = Math.max(latest, wireInfo?.mtimeMs ?? 0);
|
|
204837
|
-
}
|
|
204838
|
-
return latest > 0 ? latest : void 0;
|
|
204839
|
-
}
|
|
204840
|
-
function titleFromState(state) {
|
|
204841
|
-
if (state === void 0) return void 0;
|
|
204842
|
-
if (typeof state.isCustomTitle === "boolean" && typeof state.title === "string") return state.title;
|
|
204843
|
-
if (typeof state.customTitle === "string") return state.customTitle;
|
|
204844
|
-
return typeof state.title === "string" ? state.title : void 0;
|
|
204845
|
-
}
|
|
204846
|
-
async function readOptionalState(sessionDir) {
|
|
204847
|
-
try {
|
|
204848
|
-
const parsed = JSON.parse(await readFile(join$4(sessionDir, "state.json"), "utf-8"));
|
|
204849
|
-
const result = SessionSummaryStateSchema.safeParse(parsed);
|
|
204850
|
-
return result.success ? result.data : void 0;
|
|
204851
|
-
} catch {
|
|
204852
|
-
return;
|
|
204853
|
-
}
|
|
204854
|
-
}
|
|
204855
|
-
function normalizeRequiredWorkDir(workDir) {
|
|
204856
|
-
if (workDir.trim() === "") throw new KimiError(ErrorCodes.REQUEST_WORK_DIR_REQUIRED, "listSessions requires workDir");
|
|
204857
|
-
return normalizeWorkDir(workDir);
|
|
204858
|
-
}
|
|
204859
|
-
function normalizeOptionalSessionId$1(sessionId) {
|
|
204860
|
-
return sessionId === void 0 ? void 0 : sessionId.trim();
|
|
204861
|
-
}
|
|
204862
|
-
function normalizeForkTitle(title, fallback) {
|
|
204863
|
-
if (title !== void 0) {
|
|
204864
|
-
const normalized = title.trim();
|
|
204865
|
-
if (normalized.length === 0) throw new KimiError(ErrorCodes.SESSION_TITLE_EMPTY, "Session title cannot be empty");
|
|
204866
|
-
return normalized;
|
|
204867
|
-
}
|
|
204868
|
-
return typeof fallback === "string" && fallback.trim().length > 0 ? fallback : "New Session";
|
|
204869
|
-
}
|
|
204870
|
-
function rewriteAgentHomedirs(value, sourceDir, targetDir) {
|
|
204871
|
-
if (!isRecord$10(value)) return {};
|
|
204872
|
-
const agents = {};
|
|
204873
|
-
for (const [agentId, agentMeta] of Object.entries(value)) {
|
|
204874
|
-
if (!isRecord$10(agentMeta)) {
|
|
204875
|
-
agents[agentId] = agentMeta;
|
|
204876
|
-
continue;
|
|
204877
|
-
}
|
|
204878
|
-
const homedir = agentMeta["homedir"];
|
|
204879
|
-
agents[agentId] = {
|
|
204880
|
-
...agentMeta,
|
|
204881
|
-
homedir: typeof homedir === "string" ? remapSessionPath(homedir, sourceDir, targetDir) : homedir
|
|
204882
|
-
};
|
|
204883
|
-
}
|
|
204884
|
-
return agents;
|
|
204885
|
-
}
|
|
204886
|
-
function remapSessionPath(value, sourceDir, targetDir) {
|
|
204887
|
-
const rel = relative$1(sourceDir, value);
|
|
204888
|
-
if (rel === "") return targetDir;
|
|
204889
|
-
if (rel.startsWith("..") || isAbsolute$2(rel)) return value;
|
|
204890
|
-
return join$4(targetDir, rel);
|
|
204891
|
-
}
|
|
204892
|
-
function isRecord$10(value) {
|
|
204893
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
204894
|
-
}
|
|
204895
|
-
async function statIfExists(path) {
|
|
204896
|
-
try {
|
|
204897
|
-
return await stat$2(path);
|
|
204898
|
-
} catch {
|
|
204899
|
-
return;
|
|
204900
|
-
}
|
|
204901
|
-
}
|
|
204902
|
-
async function isDirectory(path) {
|
|
204903
|
-
try {
|
|
204904
|
-
return (await stat$2(path)).isDirectory();
|
|
204905
|
-
} catch {
|
|
204906
|
-
return false;
|
|
204907
|
-
}
|
|
204908
|
-
}
|
|
204909
|
-
function timestampOrFallback(value, fallback) {
|
|
204910
|
-
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
204911
|
-
}
|
|
204912
|
-
function assertSafeSessionId(id) {
|
|
204913
|
-
if (isSafeSessionId(id)) return;
|
|
204914
|
-
throw new KimiError(ErrorCodes.SESSION_ID_INVALID, "Session id contains unsupported path characters");
|
|
204915
|
-
}
|
|
204916
|
-
function isSafeSessionId(id) {
|
|
204917
|
-
return /^[A-Za-z0-9._-]+$/.test(id) && id !== "." && id !== "..";
|
|
204918
|
-
}
|
|
204919
|
-
function compareSessionSummary(a, b) {
|
|
204920
|
-
if (a.updatedAt !== b.updatedAt) return b.updatedAt - a.updatedAt;
|
|
204921
|
-
if (a.createdAt !== b.createdAt) return b.createdAt - a.createdAt;
|
|
204922
|
-
if (a.id < b.id) return -1;
|
|
204923
|
-
if (a.id > b.id) return 1;
|
|
204924
|
-
return 0;
|
|
204925
|
-
}
|
|
204926
|
-
var SessionSummaryStateSchema, FORKED_SESSION_DROPPED_FILES, SessionStore;
|
|
204927
|
-
var init_session_store$1 = __esmMin((() => {
|
|
204928
|
-
init_dist$7();
|
|
204929
|
-
init_zod$1();
|
|
204930
|
-
init_errors$8();
|
|
204931
|
-
init_session_index();
|
|
204932
|
-
init_workdir_key();
|
|
204933
|
-
init_records();
|
|
204934
|
-
SessionSummaryStateSchema = object({
|
|
204935
|
-
archived: boolean$1().optional(),
|
|
204936
|
-
customTitle: string().optional(),
|
|
204937
|
-
isCustomTitle: boolean$1().optional(),
|
|
204938
|
-
lastPrompt: string().optional(),
|
|
204939
|
-
title: string().optional(),
|
|
204940
|
-
custom: record(string(), unknown()).optional()
|
|
204941
|
-
});
|
|
204942
|
-
FORKED_SESSION_DROPPED_FILES = ["upcoming-goals.json"];
|
|
204943
|
-
SessionStore = class {
|
|
204944
|
-
homeDir;
|
|
204945
|
-
sessionsDir;
|
|
204946
|
-
constructor(homeDir, _options = {}) {
|
|
204947
|
-
this.homeDir = homeDir;
|
|
204948
|
-
this.sessionsDir = join$4(homeDir, "sessions");
|
|
204949
|
-
}
|
|
204950
|
-
sessionDirFor(input) {
|
|
204951
|
-
assertSafeSessionId(input.id);
|
|
204952
|
-
return join$4(this.sessionsDir, encodeWorkDirKey(normalizeWorkDir(input.workDir)), input.id);
|
|
204953
|
-
}
|
|
204954
|
-
async create(input) {
|
|
204955
|
-
assertSafeSessionId(input.id);
|
|
204956
|
-
const workDir = normalizeWorkDir(input.workDir);
|
|
204957
|
-
if (await this.findSessionEntry(input.id) !== void 0) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.id}" already exists`);
|
|
204958
|
-
const dir = this.sessionDirFor({
|
|
204959
|
-
id: input.id,
|
|
204960
|
-
workDir
|
|
204961
|
-
});
|
|
204962
|
-
if (await isDirectory(dir)) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.id}" already exists`);
|
|
204963
|
-
await mkdir(dir, {
|
|
204964
|
-
recursive: true,
|
|
204965
|
-
mode: 448
|
|
204966
|
-
});
|
|
204967
|
-
await appendSessionIndexEntry(this.homeDir, {
|
|
204968
|
-
sessionId: input.id,
|
|
204969
|
-
sessionDir: dir,
|
|
204970
|
-
workDir
|
|
204971
|
-
});
|
|
204972
|
-
return this.summaryFromDir(input.id, dir, workDir);
|
|
204973
|
-
}
|
|
204974
|
-
async fork(input) {
|
|
204975
|
-
const source = await this.findExistingSessionEntry(input.sourceId);
|
|
204976
|
-
assertSafeSessionId(input.targetId);
|
|
204977
|
-
if (await this.findSessionEntry(input.targetId) !== void 0) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.targetId}" already exists`);
|
|
204978
|
-
const targetDir = this.sessionDirFor({
|
|
204979
|
-
id: input.targetId,
|
|
204980
|
-
workDir: source.workDir
|
|
204981
|
-
});
|
|
204982
|
-
if (await isDirectory(targetDir)) throw new KimiError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.targetId}" already exists`);
|
|
204983
|
-
await mkdir(dirname$3(targetDir), {
|
|
204984
|
-
recursive: true,
|
|
204985
|
-
mode: 448
|
|
204986
|
-
});
|
|
204987
|
-
try {
|
|
204988
|
-
await cp(source.sessionDir, targetDir, {
|
|
204989
|
-
recursive: true,
|
|
204990
|
-
force: false,
|
|
204991
|
-
errorOnExist: true
|
|
204992
|
-
});
|
|
204993
|
-
await dropForkedSessionFiles(targetDir);
|
|
204994
|
-
await appendForkedMarkers(await this.writeForkedState(input, source.sessionDir, targetDir));
|
|
204995
|
-
const summary = await this.summaryFromDir(input.targetId, targetDir, source.workDir);
|
|
204996
|
-
await appendSessionIndexEntry(this.homeDir, {
|
|
204997
|
-
sessionId: input.targetId,
|
|
204998
|
-
sessionDir: targetDir,
|
|
204999
|
-
workDir: source.workDir
|
|
205000
|
-
});
|
|
205001
|
-
return summary;
|
|
205002
|
-
} catch (error) {
|
|
205003
|
-
await rm(targetDir, {
|
|
205004
|
-
recursive: true,
|
|
205005
|
-
force: true
|
|
205006
|
-
}).catch(() => {});
|
|
205007
|
-
throw error;
|
|
205008
|
-
}
|
|
205009
|
-
}
|
|
205010
|
-
async get(id) {
|
|
205011
|
-
const entry = await this.findExistingSessionEntry(id);
|
|
205012
|
-
return this.summaryFromDir(id, entry.sessionDir, entry.workDir);
|
|
205013
|
-
}
|
|
205014
|
-
async rename(id, title) {
|
|
205015
|
-
const normalized = title.trim();
|
|
205016
|
-
if (normalized.length === 0) throw new KimiError(ErrorCodes.SESSION_TITLE_EMPTY, "Session title cannot be empty");
|
|
205017
|
-
const statePath = join$4((await this.findExistingSessionEntry(id)).sessionDir, "state.json");
|
|
205018
|
-
let parsed;
|
|
205019
|
-
try {
|
|
205020
|
-
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
205021
|
-
} catch (error) {
|
|
205022
|
-
throw new KimiError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${id}" state.json was not found`, { cause: error });
|
|
205023
|
-
}
|
|
205024
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new KimiError(ErrorCodes.SESSION_STATE_INVALID, `Session "${id}" state.json is invalid`);
|
|
205025
|
-
const next = {
|
|
205026
|
-
...parsed,
|
|
205027
|
-
title: normalized,
|
|
205028
|
-
isCustomTitle: true
|
|
205029
|
-
};
|
|
205030
|
-
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
205031
|
-
}
|
|
205032
|
-
async archive(id) {
|
|
205033
|
-
const entry = await this.findExistingSessionEntry(id);
|
|
205034
|
-
const statePath = join$4(entry.sessionDir, "state.json");
|
|
205035
|
-
let parsed;
|
|
205036
|
-
try {
|
|
205037
|
-
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
205038
|
-
} catch (error) {
|
|
205039
|
-
throw new KimiError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${id}" state.json was not found`, { cause: error });
|
|
205040
|
-
}
|
|
205041
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new KimiError(ErrorCodes.SESSION_STATE_INVALID, `Session "${id}" state.json is invalid`);
|
|
205042
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
205043
|
-
const next = {
|
|
205044
|
-
...parsed,
|
|
205045
|
-
archived: true,
|
|
205046
|
-
updatedAt: now
|
|
205047
|
-
};
|
|
205048
|
-
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
205049
|
-
return this.summaryFromDir(id, entry.sessionDir, entry.workDir);
|
|
205050
|
-
}
|
|
205051
|
-
async list(options = {}) {
|
|
205052
|
-
const workDir = options.workDir === void 0 ? void 0 : normalizeRequiredWorkDir(options.workDir);
|
|
205053
|
-
const sessionId = normalizeOptionalSessionId$1(options.sessionId);
|
|
205054
|
-
const includeArchive = options.includeArchive === true;
|
|
205055
|
-
if (workDir !== void 0) {
|
|
205056
|
-
if (sessionId !== void 0) {
|
|
205057
|
-
const local = await this.summaryFromWorkDirSession(sessionId, workDir, includeArchive);
|
|
205058
|
-
if (local !== void 0) return [local];
|
|
205059
|
-
return this.listSessionId(sessionId, includeArchive);
|
|
205060
|
-
}
|
|
205061
|
-
return this.listWorkDir(workDir, includeArchive);
|
|
205062
|
-
}
|
|
205063
|
-
if (sessionId !== void 0) return this.listSessionId(sessionId, includeArchive);
|
|
205064
|
-
return this.listAll(includeArchive);
|
|
205065
|
-
}
|
|
205066
|
-
async listWorkDir(workDir, includeArchive) {
|
|
205067
|
-
const bucketDir = join$4(this.sessionsDir, encodeWorkDirKey(workDir));
|
|
205068
|
-
let entries;
|
|
205069
|
-
try {
|
|
205070
|
-
entries = await readdir$1(bucketDir, { withFileTypes: true });
|
|
205071
|
-
} catch {
|
|
205072
|
-
return [];
|
|
205073
|
-
}
|
|
205074
|
-
const sessions = [];
|
|
205075
|
-
for (const entry of entries) {
|
|
205076
|
-
if (!entry.isDirectory()) continue;
|
|
205077
|
-
const id = entry.name;
|
|
205078
|
-
if (!isSafeSessionId(id)) continue;
|
|
205079
|
-
const dir = join$4(bucketDir, id);
|
|
205080
|
-
const summary = await this.summaryFromDir(id, dir, workDir);
|
|
205081
|
-
if (!includeArchive && summary.archived === true) continue;
|
|
205082
|
-
sessions.push(summary);
|
|
205083
|
-
}
|
|
205084
|
-
sessions.sort(compareSessionSummary);
|
|
205085
|
-
return sessions;
|
|
205086
|
-
}
|
|
205087
|
-
async listSessionId(sessionId, includeArchive) {
|
|
205088
|
-
try {
|
|
205089
|
-
const summary = await this.get(sessionId);
|
|
205090
|
-
if (!includeArchive && summary.archived === true) return [];
|
|
205091
|
-
return [summary];
|
|
205092
|
-
} catch (error) {
|
|
205093
|
-
if (error instanceof KimiError && error.code === ErrorCodes.SESSION_NOT_FOUND) return [];
|
|
205094
|
-
throw error;
|
|
205095
|
-
}
|
|
205096
|
-
}
|
|
205097
|
-
async listAll(includeArchive) {
|
|
205098
|
-
const index = await readSessionIndex$1(this.homeDir, this.sessionsDir);
|
|
205099
|
-
const sessions = [];
|
|
205100
|
-
for (const entry of index.values()) {
|
|
205101
|
-
if (!await isDirectory(entry.sessionDir)) continue;
|
|
205102
|
-
const summary = await this.summaryFromDir(entry.sessionId, entry.sessionDir, entry.workDir);
|
|
205103
|
-
if (!includeArchive && summary.archived === true) continue;
|
|
205104
|
-
sessions.push(summary);
|
|
205105
|
-
}
|
|
205106
|
-
sessions.sort(compareSessionSummary);
|
|
205107
|
-
return sessions;
|
|
205108
|
-
}
|
|
205109
|
-
async summaryFromWorkDirSession(sessionId, workDir, includeArchive) {
|
|
205110
|
-
if (!isSafeSessionId(sessionId)) return void 0;
|
|
205111
|
-
const sessionDir = this.sessionDirFor({
|
|
205112
|
-
id: sessionId,
|
|
205113
|
-
workDir
|
|
205114
|
-
});
|
|
205115
|
-
if (!await isDirectory(sessionDir)) return void 0;
|
|
205116
|
-
const summary = await this.summaryFromDir(sessionId, sessionDir, workDir);
|
|
205117
|
-
if (!includeArchive && summary.archived === true) return void 0;
|
|
205118
|
-
return summary;
|
|
205119
|
-
}
|
|
205120
|
-
async assertDirectory(id) {
|
|
205121
|
-
return (await this.findExistingSessionEntry(id)).sessionDir;
|
|
205122
|
-
}
|
|
205123
|
-
async findSessionEntry(id) {
|
|
205124
|
-
if (!isSafeSessionId(id)) return void 0;
|
|
205125
|
-
return (await readSessionIndex$1(this.homeDir, this.sessionsDir)).get(id);
|
|
205126
|
-
}
|
|
205127
|
-
async findExistingSessionEntry(id) {
|
|
205128
|
-
const entry = await this.findSessionEntry(id);
|
|
205129
|
-
if (entry !== void 0 && await isDirectory(entry.sessionDir)) return entry;
|
|
205130
|
-
throw new KimiError(ErrorCodes.SESSION_NOT_FOUND, `Session "${id}" was not found`, { details: { sessionId: id } });
|
|
205131
|
-
}
|
|
205132
|
-
async writeForkedState(input, sourceDir, targetDir) {
|
|
205133
|
-
const statePath = join$4(targetDir, "state.json");
|
|
205134
|
-
let parsed;
|
|
205135
|
-
try {
|
|
205136
|
-
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
205137
|
-
} catch (error) {
|
|
205138
|
-
throw new KimiError(ErrorCodes.SESSION_STATE_NOT_FOUND, `Session "${input.sourceId}" state.json was not found`, { cause: error });
|
|
205139
|
-
}
|
|
205140
|
-
if (!isRecord$10(parsed)) throw new KimiError(ErrorCodes.SESSION_STATE_INVALID, `Session "${input.sourceId}" state.json is invalid`);
|
|
205141
|
-
const title = normalizeForkTitle(input.title, parsed["title"]);
|
|
205142
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
205143
|
-
const next = {
|
|
205144
|
-
...parsed,
|
|
205145
|
-
createdAt: now,
|
|
205146
|
-
updatedAt: now,
|
|
205147
|
-
title,
|
|
205148
|
-
isCustomTitle: input.title === void 0 ? parsed["isCustomTitle"] === true : true,
|
|
205149
|
-
forkedFrom: input.sourceId,
|
|
205150
|
-
agents: rewriteAgentHomedirs(parsed["agents"], sourceDir, targetDir),
|
|
205151
|
-
custom: forkCustomMetadata(parsed["custom"], input.metadata)
|
|
205152
|
-
};
|
|
205153
|
-
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
205154
|
-
return next;
|
|
205155
|
-
}
|
|
205156
|
-
async summaryFromDir(id, sessionDir, workDir) {
|
|
205157
|
-
const dirStat = await stat$2(sessionDir);
|
|
205158
|
-
const state = await readOptionalState(sessionDir);
|
|
205159
|
-
const [stateInfo, wireInfo, agentsWireMtime] = await Promise.all([
|
|
205160
|
-
statIfExists(join$4(sessionDir, "state.json")),
|
|
205161
|
-
statIfExists(join$4(sessionDir, "wire.jsonl")),
|
|
205162
|
-
latestAgentWireMtime(sessionDir)
|
|
205163
|
-
]);
|
|
205164
|
-
return {
|
|
205165
|
-
id,
|
|
205166
|
-
workDir,
|
|
205167
|
-
sessionDir,
|
|
205168
|
-
createdAt: timestampOrFallback(dirStat.birthtimeMs, dirStat.ctimeMs),
|
|
205169
|
-
updatedAt: Math.max(dirStat.mtimeMs, stateInfo?.mtimeMs ?? 0, wireInfo?.mtimeMs ?? 0, agentsWireMtime ?? 0),
|
|
205170
|
-
archived: state?.archived === true,
|
|
205171
|
-
title: titleFromState(state),
|
|
205172
|
-
lastPrompt: state?.lastPrompt,
|
|
205173
|
-
metadata: metadataFromState(state)
|
|
205174
|
-
};
|
|
205175
|
-
}
|
|
205176
|
-
};
|
|
205177
|
-
}));
|
|
205178
|
-
//#endregion
|
|
205179
|
-
//#region ../../packages/agent-core/src/session/store/index.ts
|
|
205180
|
-
var init_store = __esmMin((() => {
|
|
205181
|
-
init_session_store$1();
|
|
205182
|
-
init_session_index();
|
|
205183
|
-
init_workdir_key();
|
|
205184
|
-
}));
|
|
205185
|
-
//#endregion
|
|
205186
205800
|
//#region ../../packages/kaos/src/errors.ts
|
|
205187
205801
|
var KaosError, KaosFileExistsError, KaosShellNotFoundError;
|
|
205188
205802
|
var init_errors$1 = __esmMin((() => {
|
|
@@ -206432,9 +207046,10 @@ var init_core_impl = __esmMin((() => {
|
|
|
206432
207046
|
init_mcp$1();
|
|
206433
207047
|
init_session$1();
|
|
206434
207048
|
init_export();
|
|
207049
|
+
init_skill$4();
|
|
206435
207050
|
init_provider_manager();
|
|
206436
207051
|
init_rpc$1();
|
|
206437
|
-
init_store();
|
|
207052
|
+
init_store$1();
|
|
206438
207053
|
init_telemetry();
|
|
206439
207054
|
init_types$3();
|
|
206440
207055
|
init_src$1();
|
|
@@ -206559,6 +207174,7 @@ var init_core_impl = __esmMin((() => {
|
|
|
206559
207174
|
...session.metadata,
|
|
206560
207175
|
createdAt: new Date(summary.createdAt).toISOString(),
|
|
206561
207176
|
updatedAt: new Date(summary.updatedAt).toISOString(),
|
|
207177
|
+
workDir,
|
|
206562
207178
|
...summary.title !== void 0 ? {
|
|
206563
207179
|
title: summary.title,
|
|
206564
207180
|
isCustomTitle: true
|
|
@@ -206857,6 +207473,34 @@ var init_core_impl = __esmMin((() => {
|
|
|
206857
207473
|
listSkills({ sessionId, ...payload }) {
|
|
206858
207474
|
return this.sessionApi(sessionId).listSkills(payload);
|
|
206859
207475
|
}
|
|
207476
|
+
/**
|
|
207477
|
+
* List the skills available for a workspace working directory without
|
|
207478
|
+
* requiring a session. Mirrors `Session.loadSkills` exactly (same roots,
|
|
207479
|
+
* same discovery order, same built-ins) so the result matches what a new
|
|
207480
|
+
* session created in `workDir` would see. Used to populate the composer
|
|
207481
|
+
* skill menu before a session exists.
|
|
207482
|
+
*/
|
|
207483
|
+
async listWorkspaceSkills({ workDir }) {
|
|
207484
|
+
const cwd = requiredWorkDir("listWorkspaceSkills", workDir);
|
|
207485
|
+
await this.pluginsReady;
|
|
207486
|
+
const skills = this.resolveSessionSkillConfig(this.reloadProviderManager());
|
|
207487
|
+
const roots = await resolveSkillRoots({
|
|
207488
|
+
paths: {
|
|
207489
|
+
userHomeDir: skills.userHomeDir ?? this.userHomeDir,
|
|
207490
|
+
brandHomeDir: skills.brandHomeDir ?? this.homeDir,
|
|
207491
|
+
workDir: cwd
|
|
207492
|
+
},
|
|
207493
|
+
explicitDirs: skills.explicitDirs,
|
|
207494
|
+
extraDirs: skills.extraDirs,
|
|
207495
|
+
pluginSkillRoots: skills.pluginSkillRoots,
|
|
207496
|
+
mergeAllAvailableSkills: skills.mergeAllAvailableSkills,
|
|
207497
|
+
builtinDir: skills.builtinDir
|
|
207498
|
+
});
|
|
207499
|
+
const registry = new SessionSkillRegistry({});
|
|
207500
|
+
await registry.loadRoots(roots);
|
|
207501
|
+
registerBuiltinSkills(registry);
|
|
207502
|
+
return registry.listSkills().map(summarizeSkill);
|
|
207503
|
+
}
|
|
206860
207504
|
listPluginCommands({ sessionId, ...payload }) {
|
|
206861
207505
|
return this.sessionApi(sessionId).listPluginCommands(payload);
|
|
206862
207506
|
}
|
|
@@ -208407,30 +209051,53 @@ function toBrokerRequest(req, params) {
|
|
|
208407
209051
|
* Protocol REST response body → in-process SDK `QuestionResponse` (with
|
|
208408
209052
|
* `answers` flattened to `Record<string, string | true>`).
|
|
208409
209053
|
*
|
|
208410
|
-
*
|
|
208411
|
-
*
|
|
208412
|
-
*
|
|
209054
|
+
* The wire keeps synthesized ids (`q_<idx>` / `opt_<q>_<o>`) so clients can
|
|
209055
|
+
* answer unambiguously, but the flattened record is what the ask-user tool
|
|
209056
|
+
* feeds back to the model — so ids are translated back to text here using
|
|
209057
|
+
* the original broker `request`:
|
|
209058
|
+
* - key → the question's text (falls back to the raw qid
|
|
209059
|
+
* when the request is unavailable or the qid is
|
|
209060
|
+
* unknown — stale client, defensive)
|
|
209061
|
+
* - single → option label
|
|
209062
|
+
* - multi → labels.join(', ')
|
|
208413
209063
|
* - other → text
|
|
208414
|
-
* - multi_with_other → [...
|
|
209064
|
+
* - multi_with_other → [...labels, other_text].join(', ')
|
|
208415
209065
|
* - skipped → OMIT entry
|
|
209066
|
+
*
|
|
209067
|
+
* Multi-select joins use `', '` to match what the TUI reverse-RPC path
|
|
209068
|
+
* already emits, so the model sees one format regardless of which client
|
|
209069
|
+
* answered.
|
|
209070
|
+
*
|
|
209071
|
+
* Unknown qids and option ids — including ids that belong to a DIFFERENT
|
|
209072
|
+
* question than the one being answered — are kept verbatim rather than
|
|
209073
|
+
* resolved or dropped: translating a cross-question id would hand the model
|
|
209074
|
+
* a plausible-looking label that was never offered for that question, while
|
|
209075
|
+
* the raw id stays diagnosable.
|
|
208416
209076
|
*/
|
|
208417
|
-
function toAgentCoreResponse(resp) {
|
|
209077
|
+
function toAgentCoreResponse(resp, request) {
|
|
209078
|
+
const itemsById = /* @__PURE__ */ new Map();
|
|
209079
|
+
for (const item of request?.questions ?? []) itemsById.set(item.id, item);
|
|
208418
209080
|
const flattened = {};
|
|
208419
|
-
for (const [qid, ans] of Object.entries(resp.answers))
|
|
208420
|
-
|
|
208421
|
-
|
|
208422
|
-
|
|
208423
|
-
|
|
208424
|
-
|
|
208425
|
-
|
|
208426
|
-
|
|
208427
|
-
|
|
208428
|
-
|
|
208429
|
-
|
|
208430
|
-
|
|
208431
|
-
|
|
208432
|
-
|
|
208433
|
-
|
|
209081
|
+
for (const [qid, ans] of Object.entries(resp.answers)) {
|
|
209082
|
+
const item = itemsById.get(qid);
|
|
209083
|
+
const key = item?.question ?? qid;
|
|
209084
|
+
const optionText = (id) => item?.options.find((o) => o.id === id)?.label ?? id;
|
|
209085
|
+
switch (ans.kind) {
|
|
209086
|
+
case "single":
|
|
209087
|
+
flattened[key] = optionText(ans.option_id);
|
|
209088
|
+
break;
|
|
209089
|
+
case "multi":
|
|
209090
|
+
flattened[key] = ans.option_ids.map(optionText).join(", ");
|
|
209091
|
+
break;
|
|
209092
|
+
case "other":
|
|
209093
|
+
flattened[key] = ans.text;
|
|
209094
|
+
break;
|
|
209095
|
+
case "multi_with_other":
|
|
209096
|
+
flattened[key] = [...ans.option_ids.map(optionText), ans.other_text].join(", ");
|
|
209097
|
+
break;
|
|
209098
|
+
case "skipped": break;
|
|
209099
|
+
default:
|
|
209100
|
+
}
|
|
208434
209101
|
}
|
|
208435
209102
|
const out = { answers: flattened };
|
|
208436
209103
|
if (resp.method !== void 0) {
|
|
@@ -209087,7 +209754,7 @@ function toProtocolSession(summary, meta) {
|
|
|
209087
209754
|
var ISessionService, SessionUndoUnavailableError, SessionNotFoundError;
|
|
209088
209755
|
var init_session = __esmMin((() => {
|
|
209089
209756
|
init_di();
|
|
209090
|
-
init_store();
|
|
209757
|
+
init_store$1();
|
|
209091
209758
|
init_src$3();
|
|
209092
209759
|
ISessionService = createDecorator("sessionService");
|
|
209093
209760
|
SessionUndoUnavailableError = class extends Error {
|
|
@@ -212483,7 +213150,7 @@ var WORKSPACE_REGISTRY_FILE, WORKSPACE_REGISTRY_VERSION, WorkspaceRegistryServic
|
|
|
212483
213150
|
var init_workspaceRegistryService = __esmMin((() => {
|
|
212484
213151
|
init_dist$7();
|
|
212485
213152
|
init_di();
|
|
212486
|
-
init_store();
|
|
213153
|
+
init_store$1();
|
|
212487
213154
|
init_session_index();
|
|
212488
213155
|
init_environment();
|
|
212489
213156
|
init_event();
|
|
@@ -215595,6 +216262,9 @@ var init_skillService = __esmMin((() => {
|
|
|
215595
216262
|
await this._requireLoadedSession(sessionId);
|
|
215596
216263
|
return (await this.core.rpc.listSkills({ sessionId })).map(toProtocolSkill);
|
|
215597
216264
|
}
|
|
216265
|
+
async listForWorkDir(workDir) {
|
|
216266
|
+
return (await this.core.rpc.listWorkspaceSkills({ workDir })).map(toProtocolSkill);
|
|
216267
|
+
}
|
|
215598
216268
|
async activate(sessionId, skillName, args) {
|
|
215599
216269
|
await this._requireLoadedSession(sessionId);
|
|
215600
216270
|
try {
|
|
@@ -217590,6 +218260,7 @@ function capabilityToStrings(capability) {
|
|
|
217590
218260
|
if (capability.audio_in) caps.push("audio_in");
|
|
217591
218261
|
if (capability.thinking) caps.push("thinking");
|
|
217592
218262
|
if (capability.tool_use) caps.push("tool_use");
|
|
218263
|
+
if (capability.select_tools === true) caps.push("select_tools");
|
|
217593
218264
|
return caps.length > 0 ? caps : void 0;
|
|
217594
218265
|
}
|
|
217595
218266
|
/** Builds a kimi-code model alias from a normalized catalog model. */
|
|
@@ -217648,6 +218319,7 @@ const MAX_QUEUE_SIZE = 1e3;
|
|
|
217648
218319
|
var TelemetryClient = class {
|
|
217649
218320
|
queue = [];
|
|
217650
218321
|
sink = null;
|
|
218322
|
+
systemMetricsCollector = null;
|
|
217651
218323
|
deviceId = null;
|
|
217652
218324
|
sessionId = null;
|
|
217653
218325
|
disabled = false;
|
|
@@ -217658,6 +218330,10 @@ var TelemetryClient = class {
|
|
|
217658
218330
|
withContext(input) {
|
|
217659
218331
|
return new ScopedTelemetryClient(this, input);
|
|
217660
218332
|
}
|
|
218333
|
+
setSystemMetricsCollector(collector) {
|
|
218334
|
+
if (this.systemMetricsCollector !== null && this.systemMetricsCollector !== collector) this.systemMetricsCollector.stop();
|
|
218335
|
+
this.systemMetricsCollector = collector;
|
|
218336
|
+
}
|
|
217661
218337
|
attachSink(sink) {
|
|
217662
218338
|
if (this.sink !== null && this.sink !== sink) {
|
|
217663
218339
|
this.sink.stopPeriodicFlush();
|
|
@@ -217675,6 +218351,8 @@ var TelemetryClient = class {
|
|
|
217675
218351
|
disable() {
|
|
217676
218352
|
this.disabled = true;
|
|
217677
218353
|
this.queue = [];
|
|
218354
|
+
this.systemMetricsCollector?.stop();
|
|
218355
|
+
this.systemMetricsCollector = null;
|
|
217678
218356
|
if (this.sink !== null) {
|
|
217679
218357
|
this.sink.stopPeriodicFlush();
|
|
217680
218358
|
this.sink.clearBuffer();
|
|
@@ -217718,6 +218396,8 @@ var TelemetryClient = class {
|
|
|
217718
218396
|
this.sink?.flushSync();
|
|
217719
218397
|
}
|
|
217720
218398
|
async shutdown(options = {}) {
|
|
218399
|
+
this.systemMetricsCollector?.stop();
|
|
218400
|
+
this.systemMetricsCollector = null;
|
|
217721
218401
|
const sink = this.sink;
|
|
217722
218402
|
if (sink === null) return;
|
|
217723
218403
|
sink.stopPeriodicFlush();
|
|
@@ -217740,6 +218420,8 @@ var TelemetryClient = class {
|
|
|
217740
218420
|
}
|
|
217741
218421
|
resetForTests() {
|
|
217742
218422
|
this.sink?.stopPeriodicFlush();
|
|
218423
|
+
this.systemMetricsCollector?.stop();
|
|
218424
|
+
this.systemMetricsCollector = null;
|
|
217743
218425
|
this.queue = [];
|
|
217744
218426
|
this.sink = null;
|
|
217745
218427
|
this.deviceId = null;
|
|
@@ -217761,6 +218443,9 @@ var ScopedTelemetryClient = class ScopedTelemetryClient extends TelemetryClient
|
|
|
217761
218443
|
withContext(input) {
|
|
217762
218444
|
return new ScopedTelemetryClient(this.parent, mergeContext(this.context, input));
|
|
217763
218445
|
}
|
|
218446
|
+
setSystemMetricsCollector(collector) {
|
|
218447
|
+
this.parent.setSystemMetricsCollector(collector);
|
|
218448
|
+
}
|
|
217764
218449
|
attachSink(sink) {
|
|
217765
218450
|
this.parent.attachSink(sink);
|
|
217766
218451
|
}
|
|
@@ -217908,6 +218593,88 @@ function setPrimitive(target, key, value) {
|
|
|
217908
218593
|
if (typeof value === "string" && value.length === 0) return;
|
|
217909
218594
|
target[key] = value;
|
|
217910
218595
|
}
|
|
218596
|
+
//#endregion
|
|
218597
|
+
//#region ../../packages/telemetry/src/systemMetrics.ts
|
|
218598
|
+
const DEFAULT_INTERVAL_MS = 3e4;
|
|
218599
|
+
const DEFAULT_WARMUP_SAMPLE_MS = 1500;
|
|
218600
|
+
const SYSTEM_METRICS_EVENT = "system_metrics";
|
|
218601
|
+
var SystemMetricsCollector = class {
|
|
218602
|
+
client;
|
|
218603
|
+
intervalMs;
|
|
218604
|
+
warmupSampleMs;
|
|
218605
|
+
intervalTimer = null;
|
|
218606
|
+
warmupTimer = null;
|
|
218607
|
+
previousCpuUsage = process.cpuUsage();
|
|
218608
|
+
previousHrtime = process.hrtime.bigint();
|
|
218609
|
+
processStartedAtSeconds = Math.floor(Date.now() / 1e3 - process.uptime());
|
|
218610
|
+
constructor(options) {
|
|
218611
|
+
this.client = options.client;
|
|
218612
|
+
this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
|
|
218613
|
+
this.warmupSampleMs = options.warmupSampleMs === void 0 ? DEFAULT_WARMUP_SAMPLE_MS : options.warmupSampleMs;
|
|
218614
|
+
}
|
|
218615
|
+
start() {
|
|
218616
|
+
if (this.intervalTimer !== null) return;
|
|
218617
|
+
if (this.warmupSampleMs !== null && this.warmupSampleMs > 0) {
|
|
218618
|
+
this.warmupTimer = setTimeout(() => {
|
|
218619
|
+
this.warmupTimer = null;
|
|
218620
|
+
this.sampleSafely();
|
|
218621
|
+
}, this.warmupSampleMs);
|
|
218622
|
+
this.warmupTimer.unref?.();
|
|
218623
|
+
}
|
|
218624
|
+
this.intervalTimer = setInterval(() => {
|
|
218625
|
+
this.sampleSafely();
|
|
218626
|
+
}, this.intervalMs);
|
|
218627
|
+
this.intervalTimer.unref?.();
|
|
218628
|
+
}
|
|
218629
|
+
stop() {
|
|
218630
|
+
if (this.warmupTimer !== null) {
|
|
218631
|
+
clearTimeout(this.warmupTimer);
|
|
218632
|
+
this.warmupTimer = null;
|
|
218633
|
+
}
|
|
218634
|
+
if (this.intervalTimer !== null) {
|
|
218635
|
+
clearInterval(this.intervalTimer);
|
|
218636
|
+
this.intervalTimer = null;
|
|
218637
|
+
}
|
|
218638
|
+
}
|
|
218639
|
+
sampleSafely() {
|
|
218640
|
+
try {
|
|
218641
|
+
this.sample();
|
|
218642
|
+
} catch {
|
|
218643
|
+
this.stop();
|
|
218644
|
+
}
|
|
218645
|
+
}
|
|
218646
|
+
sample() {
|
|
218647
|
+
const now = process.hrtime.bigint();
|
|
218648
|
+
const elapsedUs = Number(now - this.previousHrtime) / 1e3;
|
|
218649
|
+
const cpu = process.cpuUsage(this.previousCpuUsage);
|
|
218650
|
+
this.previousCpuUsage = process.cpuUsage();
|
|
218651
|
+
this.previousHrtime = now;
|
|
218652
|
+
const mem = process.memoryUsage();
|
|
218653
|
+
const constrainedMemory = getConstrainedMemoryBytes();
|
|
218654
|
+
this.client.track(SYSTEM_METRICS_EVENT, {
|
|
218655
|
+
process_started_at: this.processStartedAtSeconds,
|
|
218656
|
+
process_uptime_ms: Math.round(process.uptime() * 1e3),
|
|
218657
|
+
rss_bytes: mem.rss,
|
|
218658
|
+
heap_used_bytes: mem.heapUsed,
|
|
218659
|
+
heap_total_bytes: mem.heapTotal,
|
|
218660
|
+
external_bytes: mem.external,
|
|
218661
|
+
array_buffers_bytes: mem.arrayBuffers,
|
|
218662
|
+
constrained_memory_bytes: constrainedMemory,
|
|
218663
|
+
cpu_user_us: cpu.user,
|
|
218664
|
+
cpu_system_us: cpu.system,
|
|
218665
|
+
cpu_elapsed_us: Math.round(elapsedUs),
|
|
218666
|
+
load_avg_1m: loadavg()[0],
|
|
218667
|
+
free_mem_bytes: freemem(),
|
|
218668
|
+
total_mem_bytes: totalmem(),
|
|
218669
|
+
cpu_count: cpus().length
|
|
218670
|
+
});
|
|
218671
|
+
}
|
|
218672
|
+
};
|
|
218673
|
+
function getConstrainedMemoryBytes() {
|
|
218674
|
+
if (typeof process.constrainedMemory !== "function") return void 0;
|
|
218675
|
+
const value = process.constrainedMemory();
|
|
218676
|
+
return Number.isFinite(value) ? value : void 0;
|
|
218677
|
+
}
|
|
217911
218678
|
const SERVER_EVENT_PREFIX = "kfc_";
|
|
217912
218679
|
const USER_ID_PREFIX = "kfc_device_id_";
|
|
217913
218680
|
const RETRY_BACKOFFS_MS = [
|
|
@@ -218206,6 +218973,9 @@ function initializeTelemetry(options) {
|
|
|
218206
218973
|
});
|
|
218207
218974
|
client.attachSink(sink);
|
|
218208
218975
|
sink.startPeriodicFlush();
|
|
218976
|
+
const systemMetricsCollector = new SystemMetricsCollector({ client });
|
|
218977
|
+
client.setSystemMetricsCollector(systemMetricsCollector);
|
|
218978
|
+
systemMetricsCollector.start();
|
|
218209
218979
|
sink.retryDiskEvents().catch(() => {});
|
|
218210
218980
|
}
|
|
218211
218981
|
//#endregion
|
|
@@ -218602,7 +219372,7 @@ async function classifySessionDir(sessionDir) {
|
|
|
218602
219372
|
}
|
|
218603
219373
|
//#endregion
|
|
218604
219374
|
//#region ../../packages/migration-legacy/src/sessions/workdir-bucket.ts
|
|
218605
|
-
init_store();
|
|
219375
|
+
init_store$1();
|
|
218606
219376
|
/**
|
|
218607
219377
|
* Bucket directory name `wd_<slug>_<hash12>` for a workdir path.
|
|
218608
219378
|
*
|
|
@@ -220229,10 +220999,12 @@ async function walkDirectoryWithFd(baseDir, fdPath, query, maxResults, signal) {
|
|
|
220229
220999
|
var CombinedAutocompleteProvider = class {
|
|
220230
221000
|
commands;
|
|
220231
221001
|
basePath;
|
|
221002
|
+
additionalBasePaths;
|
|
220232
221003
|
fdPath;
|
|
220233
|
-
constructor(commands = [], basePath, fdPath = null) {
|
|
221004
|
+
constructor(commands = [], basePath, fdPath = null, additionalBasePaths = []) {
|
|
220234
221005
|
this.commands = commands;
|
|
220235
221006
|
this.basePath = basePath;
|
|
221007
|
+
this.additionalBasePaths = additionalBasePaths.map((p) => toDisplayPath(p));
|
|
220236
221008
|
this.fdPath = fdPath;
|
|
220237
221009
|
}
|
|
220238
221010
|
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
@@ -220379,25 +221151,41 @@ var CombinedAutocompleteProvider = class {
|
|
|
220379
221151
|
} else if (path === "~") return homedir();
|
|
220380
221152
|
return path;
|
|
220381
221153
|
}
|
|
221154
|
+
searchRoots() {
|
|
221155
|
+
const seen = /* @__PURE__ */ new Set();
|
|
221156
|
+
const roots = [];
|
|
221157
|
+
for (const root of [this.basePath, ...this.additionalBasePaths]) {
|
|
221158
|
+
const key = toDisplayPath(root);
|
|
221159
|
+
if (seen.has(key)) continue;
|
|
221160
|
+
seen.add(key);
|
|
221161
|
+
roots.push(root);
|
|
221162
|
+
}
|
|
221163
|
+
return roots;
|
|
221164
|
+
}
|
|
220382
221165
|
resolveScopedFuzzyQuery(rawQuery) {
|
|
220383
221166
|
const normalizedQuery = toDisplayPath(rawQuery);
|
|
220384
221167
|
const slashIndex = normalizedQuery.lastIndexOf("/");
|
|
220385
221168
|
if (slashIndex === -1) return null;
|
|
220386
221169
|
const displayBase = normalizedQuery.slice(0, slashIndex + 1);
|
|
220387
221170
|
const query = normalizedQuery.slice(slashIndex + 1);
|
|
220388
|
-
|
|
220389
|
-
|
|
220390
|
-
|
|
220391
|
-
|
|
220392
|
-
|
|
220393
|
-
|
|
220394
|
-
|
|
220395
|
-
return
|
|
221171
|
+
if (displayBase.startsWith("~/") || displayBase.startsWith("/")) {
|
|
221172
|
+
const baseDir = displayBase.startsWith("~/") ? this.expandHomePath(displayBase) : displayBase;
|
|
221173
|
+
try {
|
|
221174
|
+
if (!statSync$1(baseDir).isDirectory()) return null;
|
|
221175
|
+
} catch {
|
|
221176
|
+
return null;
|
|
221177
|
+
}
|
|
221178
|
+
return {
|
|
221179
|
+
kind: "absolute",
|
|
221180
|
+
baseDir,
|
|
221181
|
+
displayBase,
|
|
221182
|
+
query
|
|
221183
|
+
};
|
|
220396
221184
|
}
|
|
220397
221185
|
return {
|
|
220398
|
-
|
|
220399
|
-
|
|
220400
|
-
|
|
221186
|
+
kind: "relative",
|
|
221187
|
+
displayBase,
|
|
221188
|
+
query
|
|
220401
221189
|
};
|
|
220402
221190
|
}
|
|
220403
221191
|
scopedPathForDisplay(displayBase, relativePath) {
|
|
@@ -220487,32 +221275,90 @@ var CombinedAutocompleteProvider = class {
|
|
|
220487
221275
|
return score;
|
|
220488
221276
|
}
|
|
220489
221277
|
async getFuzzyFileSuggestions(query, options) {
|
|
220490
|
-
|
|
221278
|
+
const fdPath = this.fdPath;
|
|
221279
|
+
if (!fdPath || options.signal.aborted) return [];
|
|
220491
221280
|
try {
|
|
220492
|
-
const
|
|
220493
|
-
const
|
|
220494
|
-
const
|
|
220495
|
-
|
|
221281
|
+
const scoped = this.resolveScopedFuzzyQuery(query);
|
|
221282
|
+
const targets = [];
|
|
221283
|
+
const pushFullPathTarget = (root) => {
|
|
221284
|
+
targets.push({
|
|
221285
|
+
baseDir: root,
|
|
221286
|
+
pathRoot: root,
|
|
221287
|
+
displayBase: "",
|
|
221288
|
+
fdQuery: query,
|
|
221289
|
+
isAdditional: root !== this.basePath,
|
|
221290
|
+
absolute: false
|
|
221291
|
+
});
|
|
221292
|
+
};
|
|
221293
|
+
if (scoped?.kind === "absolute") targets.push({
|
|
221294
|
+
baseDir: scoped.baseDir,
|
|
221295
|
+
pathRoot: scoped.baseDir,
|
|
221296
|
+
displayBase: scoped.displayBase,
|
|
221297
|
+
fdQuery: scoped.query,
|
|
221298
|
+
isAdditional: false,
|
|
221299
|
+
absolute: true
|
|
221300
|
+
});
|
|
221301
|
+
else if (scoped?.kind === "relative") for (const root of this.searchRoots()) {
|
|
221302
|
+
const baseDir = join$1(root, scoped.displayBase);
|
|
221303
|
+
let isDir = false;
|
|
221304
|
+
try {
|
|
221305
|
+
isDir = statSync$1(baseDir).isDirectory();
|
|
221306
|
+
} catch {
|
|
221307
|
+
isDir = false;
|
|
221308
|
+
}
|
|
221309
|
+
if (isDir) targets.push({
|
|
221310
|
+
baseDir,
|
|
221311
|
+
pathRoot: root,
|
|
221312
|
+
displayBase: scoped.displayBase,
|
|
221313
|
+
fdQuery: scoped.query,
|
|
221314
|
+
isAdditional: root !== this.basePath,
|
|
221315
|
+
absolute: false
|
|
221316
|
+
});
|
|
221317
|
+
else pushFullPathTarget(root);
|
|
221318
|
+
}
|
|
221319
|
+
else for (const root of this.searchRoots()) pushFullPathTarget(root);
|
|
221320
|
+
if (targets.length === 0) return [];
|
|
221321
|
+
const perRoot = await Promise.all(targets.map(async (target) => {
|
|
221322
|
+
return (await walkDirectoryWithFd(target.baseDir, fdPath, target.fdQuery, 100, options.signal)).map((entry) => ({
|
|
221323
|
+
entry,
|
|
221324
|
+
target
|
|
221325
|
+
}));
|
|
221326
|
+
}));
|
|
220496
221327
|
if (options.signal.aborted) return [];
|
|
220497
|
-
const
|
|
220498
|
-
|
|
220499
|
-
score
|
|
220500
|
-
|
|
220501
|
-
|
|
220502
|
-
|
|
221328
|
+
const bestByAbs = /* @__PURE__ */ new Map();
|
|
221329
|
+
for (const group of perRoot) for (const { entry, target } of group) {
|
|
221330
|
+
const score = target.fdQuery ? this.scoreEntry(entry.path, target.fdQuery, entry.isDirectory) : 1;
|
|
221331
|
+
if (score <= 0) continue;
|
|
221332
|
+
const pathWithoutSlash = entry.isDirectory ? entry.path.slice(0, -1) : entry.path;
|
|
221333
|
+
const absPath = target.absolute ? toDisplayPath(join$1(target.displayBase, pathWithoutSlash)) : toDisplayPath(join$1(target.pathRoot, target.displayBase, pathWithoutSlash));
|
|
221334
|
+
const existing = bestByAbs.get(absPath);
|
|
221335
|
+
if (!existing || score > existing.score) bestByAbs.set(absPath, {
|
|
221336
|
+
path: entry.path,
|
|
221337
|
+
isDirectory: entry.isDirectory,
|
|
221338
|
+
score,
|
|
221339
|
+
target,
|
|
221340
|
+
absPath
|
|
221341
|
+
});
|
|
221342
|
+
}
|
|
221343
|
+
const scored = [...bestByAbs.values()];
|
|
221344
|
+
scored.sort((a, b) => b.score - a.score);
|
|
221345
|
+
const topEntries = scored.slice(0, 20);
|
|
220503
221346
|
const suggestions = [];
|
|
220504
|
-
for (const
|
|
220505
|
-
const pathWithoutSlash = isDirectory ?
|
|
220506
|
-
const displayPath = scopedQuery ? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash) : pathWithoutSlash;
|
|
221347
|
+
for (const item of topEntries) {
|
|
221348
|
+
const pathWithoutSlash = item.isDirectory ? item.path.slice(0, -1) : item.path;
|
|
220507
221349
|
const entryName = basename$1(pathWithoutSlash);
|
|
220508
|
-
|
|
220509
|
-
|
|
221350
|
+
let displayPath;
|
|
221351
|
+
if (item.target.absolute) displayPath = this.scopedPathForDisplay(item.target.displayBase, pathWithoutSlash);
|
|
221352
|
+
else if (item.target.isAdditional) displayPath = item.absPath;
|
|
221353
|
+
else displayPath = item.target.displayBase ? this.scopedPathForDisplay(item.target.displayBase, pathWithoutSlash) : pathWithoutSlash;
|
|
221354
|
+
const value = buildCompletionValue(item.isDirectory ? `${displayPath}/` : displayPath, {
|
|
221355
|
+
isDirectory: item.isDirectory,
|
|
220510
221356
|
isAtPrefix: true,
|
|
220511
221357
|
isQuotedPrefix: options.isQuotedPrefix
|
|
220512
221358
|
});
|
|
220513
221359
|
suggestions.push({
|
|
220514
221360
|
value,
|
|
220515
|
-
label: entryName + (isDirectory ? "/" : ""),
|
|
221361
|
+
label: entryName + (item.isDirectory ? "/" : ""),
|
|
220516
221362
|
description: displayPath
|
|
220517
221363
|
});
|
|
220518
221364
|
}
|
|
@@ -241057,6 +241903,7 @@ function initializeCliTelemetry(options) {
|
|
|
241057
241903
|
version: options.version,
|
|
241058
241904
|
uiMode: options.uiMode,
|
|
241059
241905
|
model: options.model ?? options.config.defaultModel,
|
|
241906
|
+
sessionId: options.sessionId,
|
|
241060
241907
|
getAccessToken: async () => await options.harness.auth.getCachedAccessToken("managed:kimi-code") ?? null
|
|
241061
241908
|
});
|
|
241062
241909
|
if (options.bootstrap.firstLaunch) options.harness.track("first_launch");
|
|
@@ -275394,6 +276241,15 @@ let QuestionService = class QuestionService extends Disposable {
|
|
|
275394
276241
|
isPending(questionId) {
|
|
275395
276242
|
return this._pending.has(questionId);
|
|
275396
276243
|
}
|
|
276244
|
+
/**
|
|
276245
|
+
* Protocol request for a still-pending question. The resolve route needs it
|
|
276246
|
+
* to translate wire ids back to question text / option labels before the
|
|
276247
|
+
* response reaches the SDK; must be read BEFORE `resolve()` settles (and
|
|
276248
|
+
* thereby drops) the pending entry.
|
|
276249
|
+
*/
|
|
276250
|
+
getPendingRequest(questionId) {
|
|
276251
|
+
return this._pending.get(questionId)?.protocolRequest;
|
|
276252
|
+
}
|
|
275397
276253
|
listPending(sessionId) {
|
|
275398
276254
|
return Array.from(this._pending.values()).filter((p) => p.sessionId === sessionId).map((p) => p.protocolRequest);
|
|
275399
276255
|
}
|
|
@@ -275536,7 +276392,7 @@ function registerQuestionsRoutes(app, ix) {
|
|
|
275536
276392
|
return;
|
|
275537
276393
|
}
|
|
275538
276394
|
const body = bodyParse.data;
|
|
275539
|
-
const inProc = toAgentCoreResponse(body);
|
|
276395
|
+
const inProc = toAgentCoreResponse(body, broker.getPendingRequest(questionId));
|
|
275540
276396
|
broker.resolve(questionId, inProc);
|
|
275541
276397
|
broker.markResolved(questionId);
|
|
275542
276398
|
const result = {
|
|
@@ -275548,6 +276404,69 @@ function registerQuestionsRoutes(app, ix) {
|
|
|
275548
276404
|
app.post(route.path, route.options, route.handler);
|
|
275549
276405
|
}
|
|
275550
276406
|
//#endregion
|
|
276407
|
+
//#region ../../packages/server/src/lib/sessionArchive.ts
|
|
276408
|
+
init_src();
|
|
276409
|
+
async function restoreArchivedSession(homeDir, sessionId) {
|
|
276410
|
+
const sessionDir = await findSessionDir$1(homeDir, sessionId);
|
|
276411
|
+
if (sessionDir === void 0) throw new SessionNotFoundError(sessionId);
|
|
276412
|
+
const statePath = join(sessionDir, "state.json");
|
|
276413
|
+
let parsed;
|
|
276414
|
+
try {
|
|
276415
|
+
parsed = JSON.parse(await readFile(statePath, "utf-8"));
|
|
276416
|
+
} catch {
|
|
276417
|
+
throw new SessionNotFoundError(sessionId);
|
|
276418
|
+
}
|
|
276419
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new SessionNotFoundError(sessionId);
|
|
276420
|
+
const next = {
|
|
276421
|
+
...parsed,
|
|
276422
|
+
archived: false,
|
|
276423
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
276424
|
+
};
|
|
276425
|
+
await writeFile$1(statePath, `${JSON.stringify(next, null, 2)}\n`, "utf-8");
|
|
276426
|
+
}
|
|
276427
|
+
async function findSessionDir$1(homeDir, sessionId) {
|
|
276428
|
+
const indexPath = join(homeDir, "session_index.jsonl");
|
|
276429
|
+
let raw;
|
|
276430
|
+
try {
|
|
276431
|
+
raw = await readFile(indexPath, "utf-8");
|
|
276432
|
+
} catch {
|
|
276433
|
+
return;
|
|
276434
|
+
}
|
|
276435
|
+
const sessionsDir = join(homeDir, "sessions");
|
|
276436
|
+
let found;
|
|
276437
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
276438
|
+
const trimmed = line.trim();
|
|
276439
|
+
if (trimmed === "") continue;
|
|
276440
|
+
const entry = parseIndexLine(trimmed);
|
|
276441
|
+
if (entry === void 0 || entry.sessionId !== sessionId) continue;
|
|
276442
|
+
const sessionDir = resolve(entry.sessionDir);
|
|
276443
|
+
if (!isAbsolute(entry.sessionDir)) continue;
|
|
276444
|
+
if (!isPathInside(sessionsDir, sessionDir)) continue;
|
|
276445
|
+
if (basename(sessionDir) !== entry.sessionId) continue;
|
|
276446
|
+
found = sessionDir;
|
|
276447
|
+
}
|
|
276448
|
+
return found;
|
|
276449
|
+
}
|
|
276450
|
+
function parseIndexLine(line) {
|
|
276451
|
+
try {
|
|
276452
|
+
const parsed = JSON.parse(line);
|
|
276453
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
276454
|
+
const entry = parsed;
|
|
276455
|
+
if (typeof entry.sessionId !== "string" || typeof entry.sessionDir !== "string" || typeof entry.workDir !== "string") return;
|
|
276456
|
+
return {
|
|
276457
|
+
sessionId: entry.sessionId,
|
|
276458
|
+
sessionDir: entry.sessionDir,
|
|
276459
|
+
workDir: entry.workDir
|
|
276460
|
+
};
|
|
276461
|
+
} catch {
|
|
276462
|
+
return;
|
|
276463
|
+
}
|
|
276464
|
+
}
|
|
276465
|
+
function isPathInside(parent, child) {
|
|
276466
|
+
const rel = relative(resolve(parent), resolve(child));
|
|
276467
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
|
|
276468
|
+
}
|
|
276469
|
+
//#endregion
|
|
275551
276470
|
//#region ../../packages/server/src/routes/sessions.ts
|
|
275552
276471
|
init_src$3();
|
|
275553
276472
|
init_src();
|
|
@@ -275564,6 +276483,7 @@ const sessionsListQueryCoercion = object({
|
|
|
275564
276483
|
status: sessionStatusSchema.optional(),
|
|
275565
276484
|
include_archive: booleanQueryParam,
|
|
275566
276485
|
exclude_empty: booleanQueryParam,
|
|
276486
|
+
archived_only: booleanQueryParam,
|
|
275567
276487
|
workspace_id: workspaceIdSchema.optional()
|
|
275568
276488
|
}).superRefine((value, ctx) => {
|
|
275569
276489
|
if (value.before_id !== void 0 && value.after_id !== void 0) ctx.addIssue({
|
|
@@ -275572,6 +276492,12 @@ const sessionsListQueryCoercion = object({
|
|
|
275572
276492
|
path: ["before_id"],
|
|
275573
276493
|
params: { code: ErrorCode$1.VALIDATION_FAILED }
|
|
275574
276494
|
});
|
|
276495
|
+
if (value.archived_only === true && value.include_archive === true) ctx.addIssue({
|
|
276496
|
+
code: "custom",
|
|
276497
|
+
message: "archived_only and include_archive are mutually exclusive",
|
|
276498
|
+
path: ["archived_only"],
|
|
276499
|
+
params: { code: ErrorCode$1.VALIDATION_FAILED }
|
|
276500
|
+
});
|
|
275575
276501
|
});
|
|
275576
276502
|
const sessionChildrenListQueryCoercion = object({
|
|
275577
276503
|
before_id: string().min(1).optional(),
|
|
@@ -275615,6 +276541,47 @@ function headerString(headers, key) {
|
|
|
275615
276541
|
const trimmed = raw.trim();
|
|
275616
276542
|
return trimmed.length === 0 ? void 0 : trimmed;
|
|
275617
276543
|
}
|
|
276544
|
+
const DEFAULT_SESSION_LIST_PAGE_SIZE = 20;
|
|
276545
|
+
const MAX_SESSION_LIST_PAGE_SIZE = 100;
|
|
276546
|
+
function normalizeSessionListPageSize(cursor) {
|
|
276547
|
+
const requested = cursor.page_size ?? DEFAULT_SESSION_LIST_PAGE_SIZE;
|
|
276548
|
+
return Math.min(Math.max(requested, 1), MAX_SESSION_LIST_PAGE_SIZE);
|
|
276549
|
+
}
|
|
276550
|
+
async function listSessionsWithRouteFilter(fetchPage, baseQuery, cursor, predicate) {
|
|
276551
|
+
const targetSize = normalizeSessionListPageSize(cursor);
|
|
276552
|
+
const forward = cursor.after_id !== void 0 && cursor.before_id === void 0;
|
|
276553
|
+
const matches = [];
|
|
276554
|
+
let beforeId = forward ? void 0 : cursor.before_id;
|
|
276555
|
+
let afterId = forward ? cursor.after_id : void 0;
|
|
276556
|
+
let coreHasMore = true;
|
|
276557
|
+
while (matches.length <= targetSize && coreHasMore) {
|
|
276558
|
+
const page = await fetchPage({
|
|
276559
|
+
...baseQuery,
|
|
276560
|
+
before_id: beforeId,
|
|
276561
|
+
after_id: afterId,
|
|
276562
|
+
page_size: MAX_SESSION_LIST_PAGE_SIZE
|
|
276563
|
+
});
|
|
276564
|
+
if (page.items.length === 0) break;
|
|
276565
|
+
let hitPivot = false;
|
|
276566
|
+
for (const session of page.items) {
|
|
276567
|
+
if (forward && session.id === afterId) {
|
|
276568
|
+
hitPivot = true;
|
|
276569
|
+
break;
|
|
276570
|
+
}
|
|
276571
|
+
if (predicate(session)) matches.push(session);
|
|
276572
|
+
}
|
|
276573
|
+
coreHasMore = page.has_more && !hitPivot;
|
|
276574
|
+
if (!coreHasMore) break;
|
|
276575
|
+
const nextBeforeId = page.items[page.items.length - 1]?.id;
|
|
276576
|
+
if (nextBeforeId === void 0 || nextBeforeId === beforeId) break;
|
|
276577
|
+
beforeId = nextBeforeId;
|
|
276578
|
+
afterId = void 0;
|
|
276579
|
+
}
|
|
276580
|
+
return {
|
|
276581
|
+
items: matches.slice(0, targetSize),
|
|
276582
|
+
has_more: matches.length > targetSize
|
|
276583
|
+
};
|
|
276584
|
+
}
|
|
275618
276585
|
function registerSessionsRoutes(app, ix) {
|
|
275619
276586
|
const createRoute = defineRoute({
|
|
275620
276587
|
method: "POST",
|
|
@@ -275694,15 +276661,12 @@ function registerSessionsRoutes(app, ix) {
|
|
|
275694
276661
|
}, async (req, reply) => {
|
|
275695
276662
|
try {
|
|
275696
276663
|
const raw = req.query;
|
|
275697
|
-
const
|
|
275698
|
-
|
|
275699
|
-
|
|
275700
|
-
|
|
275701
|
-
status: raw.status,
|
|
275702
|
-
includeArchive: raw.include_archive,
|
|
276664
|
+
const archivedOnly = raw.archived_only === true;
|
|
276665
|
+
const status = raw.status;
|
|
276666
|
+
let baseQuery = {
|
|
276667
|
+
includeArchive: archivedOnly ? true : raw.include_archive,
|
|
275703
276668
|
excludeEmpty: raw.exclude_empty
|
|
275704
276669
|
};
|
|
275705
|
-
let query;
|
|
275706
276670
|
if (raw.workspace_id !== void 0) {
|
|
275707
276671
|
const registry = ix.invokeFunction((a) => a.get(IWorkspaceRegistry));
|
|
275708
276672
|
let root;
|
|
@@ -275715,12 +276679,23 @@ function registerSessionsRoutes(app, ix) {
|
|
|
275715
276679
|
}
|
|
275716
276680
|
throw err;
|
|
275717
276681
|
}
|
|
275718
|
-
|
|
276682
|
+
baseQuery = {
|
|
275719
276683
|
...baseQuery,
|
|
275720
276684
|
workDir: root
|
|
275721
276685
|
};
|
|
275722
|
-
}
|
|
275723
|
-
|
|
276686
|
+
}
|
|
276687
|
+
if (archivedOnly) {
|
|
276688
|
+
const page = await listSessionsWithRouteFilter((query) => ix.invokeFunction((a) => a.get(ISessionService).list(query)), baseQuery, raw, (session) => session.archived === true && (status === void 0 || session.status === status));
|
|
276689
|
+
reply.send(okEnvelope(page, req.id));
|
|
276690
|
+
return;
|
|
276691
|
+
}
|
|
276692
|
+
const page = await ix.invokeFunction((a) => a.get(ISessionService).list({
|
|
276693
|
+
...baseQuery,
|
|
276694
|
+
before_id: raw.before_id,
|
|
276695
|
+
after_id: raw.after_id,
|
|
276696
|
+
page_size: raw.page_size,
|
|
276697
|
+
status
|
|
276698
|
+
}));
|
|
275724
276699
|
reply.send(okEnvelope(page, req.id));
|
|
275725
276700
|
} catch (err) {
|
|
275726
276701
|
sendMappedError$6(reply, req.id, err);
|
|
@@ -275836,7 +276811,8 @@ function registerSessionsRoutes(app, ix) {
|
|
|
275836
276811
|
"undo",
|
|
275837
276812
|
"abort",
|
|
275838
276813
|
"btw",
|
|
275839
|
-
"archive"
|
|
276814
|
+
"archive",
|
|
276815
|
+
"restore"
|
|
275840
276816
|
],
|
|
275841
276817
|
resourceLabel: "session"
|
|
275842
276818
|
});
|
|
@@ -275875,6 +276851,13 @@ function registerSessionsRoutes(app, ix) {
|
|
|
275875
276851
|
reply.send(okEnvelope(result, req.id));
|
|
275876
276852
|
return;
|
|
275877
276853
|
}
|
|
276854
|
+
if (parsed.action === "restore") {
|
|
276855
|
+
const homeDir = ix.invokeFunction((a) => a.get(IEnvironmentService)).homeDir;
|
|
276856
|
+
await restoreArchivedSession(homeDir, parsed.id);
|
|
276857
|
+
const session = await ix.invokeFunction((a) => a.get(ISessionService).get(parsed.id));
|
|
276858
|
+
reply.send(okEnvelope(session, req.id));
|
|
276859
|
+
return;
|
|
276860
|
+
}
|
|
275878
276861
|
const body = undoSessionRequestSchema.parse(req.body);
|
|
275879
276862
|
const result = await ix.invokeFunction((a) => a.get(ISessionService).undo(parsed.id, body));
|
|
275880
276863
|
reply.send(okEnvelope(result, req.id));
|
|
@@ -276073,6 +277056,29 @@ function registerSkillsRoutes(app, ix) {
|
|
|
276073
277056
|
}
|
|
276074
277057
|
});
|
|
276075
277058
|
app.get(listSkillsRoute.path, listSkillsRoute.options, listSkillsRoute.handler);
|
|
277059
|
+
const listWorkspaceSkillsRoute = defineRoute({
|
|
277060
|
+
method: "GET",
|
|
277061
|
+
path: "/workspaces/{workspace_id}/skills",
|
|
277062
|
+
params: workspaceIdParamSchema,
|
|
277063
|
+
success: { data: listSkillsResponseSchema },
|
|
277064
|
+
errors: { [ErrorCode$1.WORKSPACE_NOT_FOUND]: {} },
|
|
277065
|
+
description: "List the skills available to a workspace (no session required)",
|
|
277066
|
+
tags: ["skills"],
|
|
277067
|
+
operationId: "listWorkspaceSkills"
|
|
277068
|
+
}, async (req, reply) => {
|
|
277069
|
+
try {
|
|
277070
|
+
const { workspace_id } = req.params;
|
|
277071
|
+
const skills = await ix.invokeFunction((a) => {
|
|
277072
|
+
const registry = a.get(IWorkspaceRegistry);
|
|
277073
|
+
const skillService = a.get(ISkillService);
|
|
277074
|
+
return registry.resolveRoot(workspace_id).then((workDir) => skillService.listForWorkDir(workDir));
|
|
277075
|
+
});
|
|
277076
|
+
reply.send(okEnvelope({ skills }, req.id));
|
|
277077
|
+
} catch (err) {
|
|
277078
|
+
sendMappedError$5(reply, req.id, err);
|
|
277079
|
+
}
|
|
277080
|
+
});
|
|
277081
|
+
app.get(listWorkspaceSkillsRoute.path, listWorkspaceSkillsRoute.options, listWorkspaceSkillsRoute.handler);
|
|
276076
277082
|
const activateSkillRoute = defineRoute({
|
|
276077
277083
|
method: "POST",
|
|
276078
277084
|
path: "/sessions/{session_id}/skills/{tail}",
|
|
@@ -276119,6 +277125,10 @@ function registerSkillsRoutes(app, ix) {
|
|
|
276119
277125
|
* Map a thrown error to the right envelope. See module header for the table.
|
|
276120
277126
|
*/
|
|
276121
277127
|
function sendMappedError$5(reply, requestId, err) {
|
|
277128
|
+
if (err instanceof WorkspaceNotFoundError) {
|
|
277129
|
+
reply.send(errEnvelope(ErrorCode$1.WORKSPACE_NOT_FOUND, err.message, requestId));
|
|
277130
|
+
return;
|
|
277131
|
+
}
|
|
276122
277132
|
if (err instanceof SessionNotFoundError) {
|
|
276123
277133
|
reply.send(errEnvelope(ErrorCode$1.SESSION_NOT_FOUND, err.message, requestId));
|
|
276124
277134
|
return;
|
|
@@ -276217,7 +277227,7 @@ function loadSnapshotConfig(env = process.env) {
|
|
|
276217
277227
|
* `turn.started` events fired before the first snapshot request.
|
|
276218
277228
|
*/
|
|
276219
277229
|
init_src();
|
|
276220
|
-
init_store();
|
|
277230
|
+
init_store$1();
|
|
276221
277231
|
init_decorateParam();
|
|
276222
277232
|
init_decorate();
|
|
276223
277233
|
const MAIN_AGENT_ID$1 = "main";
|
|
@@ -287643,6 +288653,12 @@ async function startServer(opts) {
|
|
|
287643
288653
|
configPath: opts.coreProcessOptions?.configPath
|
|
287644
288654
|
})
|
|
287645
288655
|
};
|
|
288656
|
+
try {
|
|
288657
|
+
const stats = await new SessionStore(envService.homeDir).reindex();
|
|
288658
|
+
pinoLogger.info(stats, "session index rebuilt");
|
|
288659
|
+
} catch (error) {
|
|
288660
|
+
pinoLogger.warn({ err: String(error) }, "session index rebuild failed (best-effort)");
|
|
288661
|
+
}
|
|
287646
288662
|
const tokenStore = await createTokenStore(envService.homeDir);
|
|
287647
288663
|
const passwordHash = await resolvePasswordHash(process.env);
|
|
287648
288664
|
const defaultAuth = createAuthTokenService({
|
|
@@ -302394,6 +303410,7 @@ const BLINK_INTERVAL = 500;
|
|
|
302394
303410
|
var CompactionComponent = class extends Container {
|
|
302395
303411
|
ui;
|
|
302396
303412
|
headerText;
|
|
303413
|
+
instructionText;
|
|
302397
303414
|
instruction;
|
|
302398
303415
|
tip;
|
|
302399
303416
|
blinkOn = true;
|
|
@@ -302402,6 +303419,9 @@ var CompactionComponent = class extends Container {
|
|
|
302402
303419
|
canceled = false;
|
|
302403
303420
|
tokensBefore;
|
|
302404
303421
|
tokensAfter;
|
|
303422
|
+
summary;
|
|
303423
|
+
summaryText;
|
|
303424
|
+
expanded = false;
|
|
302405
303425
|
constructor(ui, instruction, tip) {
|
|
302406
303426
|
super();
|
|
302407
303427
|
this.ui = ui;
|
|
@@ -302414,23 +303434,35 @@ var CompactionComponent = class extends Container {
|
|
|
302414
303434
|
this.startBlink();
|
|
302415
303435
|
}
|
|
302416
303436
|
addInstructionChild() {
|
|
302417
|
-
if (this.instruction !== void 0)
|
|
303437
|
+
if (this.instruction !== void 0) {
|
|
303438
|
+
this.instructionText = new Text(currentTheme.dim(` ${this.instruction}`), 0, 0);
|
|
303439
|
+
this.addChild(this.instructionText);
|
|
303440
|
+
}
|
|
303441
|
+
}
|
|
303442
|
+
removeInstructionChild() {
|
|
303443
|
+
if (this.instructionText === void 0) return;
|
|
303444
|
+
const index = this.children.indexOf(this.instructionText);
|
|
303445
|
+
if (index !== -1) this.children.splice(index, 1);
|
|
303446
|
+
this.instructionText = void 0;
|
|
302418
303447
|
}
|
|
302419
303448
|
invalidate() {
|
|
302420
303449
|
this.headerText.setText(this.buildHeader());
|
|
302421
|
-
|
|
302422
|
-
|
|
302423
|
-
|
|
302424
|
-
|
|
303450
|
+
const expanded = this.expanded;
|
|
303451
|
+
this.removeInstructionChild();
|
|
303452
|
+
if (expanded) this.removeSummaryChild();
|
|
303453
|
+
this.addInstructionChild();
|
|
303454
|
+
if (expanded) this.addSummaryChild();
|
|
302425
303455
|
super.invalidate();
|
|
302426
303456
|
}
|
|
302427
|
-
markDone(tokensBefore, tokensAfter) {
|
|
303457
|
+
markDone(tokensBefore, tokensAfter, summary) {
|
|
302428
303458
|
if (this.done || this.canceled) return;
|
|
302429
303459
|
this.done = true;
|
|
302430
303460
|
this.tokensBefore = tokensBefore;
|
|
302431
303461
|
this.tokensAfter = tokensAfter;
|
|
303462
|
+
this.summary = summary;
|
|
302432
303463
|
this.stopBlink();
|
|
302433
303464
|
this.headerText.setText(this.buildHeader());
|
|
303465
|
+
if (this.expanded) this.addSummaryChild();
|
|
302434
303466
|
this.ui?.requestRender();
|
|
302435
303467
|
}
|
|
302436
303468
|
markCanceled() {
|
|
@@ -302440,11 +303472,31 @@ var CompactionComponent = class extends Container {
|
|
|
302440
303472
|
this.headerText.setText(this.buildHeader());
|
|
302441
303473
|
this.ui?.requestRender();
|
|
302442
303474
|
}
|
|
303475
|
+
setExpanded(expanded) {
|
|
303476
|
+
if (this.expanded === expanded) return;
|
|
303477
|
+
this.expanded = expanded;
|
|
303478
|
+
if (expanded) this.addSummaryChild();
|
|
303479
|
+
else this.removeSummaryChild();
|
|
303480
|
+
this.headerText.setText(this.buildHeader());
|
|
303481
|
+
this.ui?.requestRender();
|
|
303482
|
+
}
|
|
303483
|
+
addSummaryChild() {
|
|
303484
|
+
if (this.summaryText !== void 0 || this.summary === void 0 || this.summary.length === 0) return;
|
|
303485
|
+
const indentedSummary = this.summary.split("\n").map((line) => ` ${line}`).join("\n");
|
|
303486
|
+
this.summaryText = new Text(currentTheme.dim(indentedSummary), 0, 0);
|
|
303487
|
+
this.addChild(this.summaryText);
|
|
303488
|
+
}
|
|
303489
|
+
removeSummaryChild() {
|
|
303490
|
+
if (this.summaryText === void 0) return;
|
|
303491
|
+
const index = this.children.indexOf(this.summaryText);
|
|
303492
|
+
if (index !== -1) this.children.splice(index, 1);
|
|
303493
|
+
this.summaryText = void 0;
|
|
303494
|
+
}
|
|
302443
303495
|
dispose() {
|
|
302444
303496
|
this.stopBlink();
|
|
302445
303497
|
}
|
|
302446
303498
|
buildHeader() {
|
|
302447
|
-
if (this.done) return `${currentTheme.fg("success", STATUS_BULLET)}${currentTheme.boldFg("success", "Compaction complete")}${this.tokensBefore !== void 0 && this.tokensAfter !== void 0 ? currentTheme.dim(` (${String(this.tokensBefore)} → ${String(this.tokensAfter)} tokens)`) : ""}`;
|
|
303499
|
+
if (this.done) return `${currentTheme.fg("success", STATUS_BULLET)}${currentTheme.boldFg("success", "Compaction complete")}${this.tokensBefore !== void 0 && this.tokensAfter !== void 0 ? currentTheme.dim(` (${String(this.tokensBefore)} → ${String(this.tokensAfter)} tokens)`) : ""}${this.summary !== void 0 && this.summary.length > 0 ? currentTheme.dim(` (Ctrl-O to ${this.expanded ? "hide" : "show"} compaction summary)`) : ""}`;
|
|
302448
303500
|
if (this.canceled) return `${currentTheme.fg("warning", STATUS_BULLET)}${currentTheme.boldFg("warning", "Compaction cancelled")}`;
|
|
302449
303501
|
return `${this.blinkOn ? currentTheme.fg("text", STATUS_BULLET) : " "}${currentTheme.boldFg("primary", "Compacting context...")}${this.tip ? currentTheme.fg("textDim", ` · Tip: ${this.tip}`) : ""}`;
|
|
302450
303502
|
}
|
|
@@ -364019,27 +365071,6 @@ function computeDiffLines(oldText, newText, oldStart = 1, newStart = 1, isIncomp
|
|
|
364019
365071
|
}
|
|
364020
365072
|
return result;
|
|
364021
365073
|
}
|
|
364022
|
-
function renderDiffLines(oldText, newText, path, isIncomplete = false, oldStart, newStart, maxLines) {
|
|
364023
|
-
const s = makeDiffStyles();
|
|
364024
|
-
const changedLines = computeDiffLines(oldText, newText, oldStart ?? 1, newStart ?? 1, isIncomplete).filter((l) => l.kind !== "context");
|
|
364025
|
-
const added = changedLines.filter((l) => l.kind === "add").length;
|
|
364026
|
-
const removed = changedLines.filter((l) => l.kind === "delete").length;
|
|
364027
|
-
const output = [];
|
|
364028
|
-
let header = "";
|
|
364029
|
-
if (added > 0) header += s.addBold(`+${String(added)} `);
|
|
364030
|
-
if (removed > 0) header += s.delBold(`-${String(removed)} `);
|
|
364031
|
-
header += path;
|
|
364032
|
-
output.push(header);
|
|
364033
|
-
const shown = maxLines !== void 0 && maxLines >= 0 && changedLines.length > maxLines ? changedLines.slice(0, maxLines) : changedLines;
|
|
364034
|
-
for (const line of shown) {
|
|
364035
|
-
const marker = line.kind === "add" ? "+" : "-";
|
|
364036
|
-
const color = line.kind === "add" ? s.add : s.del;
|
|
364037
|
-
output.push(s.gutter(String(line.lineNum).padStart(4) + " ") + color(marker + " " + line.code));
|
|
364038
|
-
}
|
|
364039
|
-
const hidden = changedLines.length - shown.length;
|
|
364040
|
-
if (hidden > 0) output.push(s.meta(` … ${String(hidden)} more change${hidden > 1 ? "s" : ""} hidden (ctrl+o to expand)`));
|
|
364041
|
-
return output;
|
|
364042
|
-
}
|
|
364043
365074
|
function buildClusters(diffLines, contextLines) {
|
|
364044
365075
|
const changeIndices = [];
|
|
364045
365076
|
let added = 0;
|
|
@@ -364103,7 +365134,7 @@ function renderDiffLinesClustered(oldText, newText, path, opts = {}) {
|
|
|
364103
365134
|
const s = makeDiffStyles();
|
|
364104
365135
|
const contextLines = opts.contextLines ?? 3;
|
|
364105
365136
|
const maxLines = opts.maxLines;
|
|
364106
|
-
const diffLines = computeDiffLines(oldText, newText, 1, 1, opts.isIncomplete ?? false);
|
|
365137
|
+
const diffLines = computeDiffLines(oldText, newText, opts.oldStart ?? 1, opts.newStart ?? 1, opts.isIncomplete ?? false);
|
|
364107
365138
|
const { clusters, changedCount, addedCount, removedCount } = buildClusters(diffLines, contextLines);
|
|
364108
365139
|
const output = [];
|
|
364109
365140
|
let header = "";
|
|
@@ -364282,7 +365313,8 @@ var TruncatedOutputComponent = class {
|
|
|
364282
365313
|
this.expandHint = options.expandHint ?? true;
|
|
364283
365314
|
this.tail = options.tail ?? false;
|
|
364284
365315
|
const cleaned = trimTrailingEmptyLines(output.split("\n")).join("\n");
|
|
364285
|
-
|
|
365316
|
+
const successColor = options.color ?? "textDim";
|
|
365317
|
+
this.textComponent = new Text(options.isError ? currentTheme.fg("error", cleaned) : currentTheme.fg(successColor, cleaned), this.indent, 0);
|
|
364286
365318
|
}
|
|
364287
365319
|
invalidate() {
|
|
364288
365320
|
this.textComponent.invalidate();
|
|
@@ -364325,8 +365357,8 @@ var ShellExecutionComponent = class extends Container {
|
|
|
364325
365357
|
const allLines = command.split("\n");
|
|
364326
365358
|
const lines = previewLines === void 0 ? allLines : allLines.slice(0, previewLines);
|
|
364327
365359
|
for (const [i, line] of lines.entries()) {
|
|
364328
|
-
const
|
|
364329
|
-
this.addChild(new Text(
|
|
365360
|
+
const text = i === 0 ? currentTheme.fg("shellMode", "$ ") + currentTheme.dim(line) : ` ${currentTheme.dim(line)}`;
|
|
365361
|
+
this.addChild(new Text(text, 2, 0));
|
|
364330
365362
|
}
|
|
364331
365363
|
}
|
|
364332
365364
|
addResultPreview(result, expanded, previewLines, tailOutput, expandHint) {
|
|
@@ -364336,16 +365368,14 @@ var ShellExecutionComponent = class extends Container {
|
|
|
364336
365368
|
isError: result.is_error ?? false,
|
|
364337
365369
|
maxLines: previewLines,
|
|
364338
365370
|
tail: tailOutput,
|
|
364339
|
-
expandHint
|
|
365371
|
+
expandHint,
|
|
365372
|
+
color: "textMuted"
|
|
364340
365373
|
}));
|
|
364341
365374
|
}
|
|
364342
365375
|
};
|
|
364343
|
-
const shellExecutionResultRenderer = (
|
|
364344
|
-
command: typeof toolCall.args["command"] === "string" ? toolCall.args["command"] : "",
|
|
365376
|
+
const shellExecutionResultRenderer = (_toolCall, result, ctx) => [new ShellExecutionComponent({
|
|
364345
365377
|
result,
|
|
364346
|
-
expanded: ctx.expanded
|
|
364347
|
-
showCommand: ctx.expanded,
|
|
364348
|
-
commandPreviewLines: void 0
|
|
365378
|
+
expanded: ctx.expanded
|
|
364349
365379
|
})];
|
|
364350
365380
|
//#endregion
|
|
364351
365381
|
//#region src/tui/components/messages/tool-renderers/goal.ts
|
|
@@ -365727,6 +366757,13 @@ var ToolCallComponent = class ToolCallComponent extends Container {
|
|
|
365727
366757
|
const tone = isError ? "error" : "primary";
|
|
365728
366758
|
return `${bullet}${currentTheme.boldFg(tone, label)}`;
|
|
365729
366759
|
}
|
|
366760
|
+
if (toolCall.name === "Bash") {
|
|
366761
|
+
if (isTruncated) return `${bullet}${currentTheme.fg("error", "Truncated")} ${currentTheme.boldFg("primary", "Bash")}`;
|
|
366762
|
+
const label = isFinished ? "Ran a command" : "Running a command";
|
|
366763
|
+
const tone = isError ? "error" : "primary";
|
|
366764
|
+
const chipStr = isFinished && result !== void 0 ? this.buildHeaderChip(result) : "";
|
|
366765
|
+
return `${bullet}${currentTheme.boldFg(tone, label)}${chipStr}`;
|
|
366766
|
+
}
|
|
365730
366767
|
const goalHeader = buildGoalToolHeader({
|
|
365731
366768
|
toolCall,
|
|
365732
366769
|
result,
|
|
@@ -366038,7 +367075,7 @@ var ToolCallComponent = class ToolCallComponent extends Container {
|
|
|
366038
367075
|
this.buildStreamingPreview(this.toolCall.streamingArguments);
|
|
366039
367076
|
return;
|
|
366040
367077
|
}
|
|
366041
|
-
const shouldCap =
|
|
367078
|
+
const shouldCap = !this.expanded;
|
|
366042
367079
|
if (name === "Write") {
|
|
366043
367080
|
const content = str(this.toolCall.args["content"]);
|
|
366044
367081
|
if (content.length === 0) return;
|
|
@@ -366060,7 +367097,7 @@ var ToolCallComponent = class ToolCallComponent extends Container {
|
|
|
366060
367097
|
...shouldCap ? { maxLines: 10 } : {}
|
|
366061
367098
|
});
|
|
366062
367099
|
for (const line of lines) this.addChild(new Text(line, 2, 0));
|
|
366063
|
-
} else if (name === "Bash"
|
|
367100
|
+
} else if (name === "Bash") {
|
|
366064
367101
|
const command = str(this.toolCall.args["command"]);
|
|
366065
367102
|
if (command.length === 0) return;
|
|
366066
367103
|
this.addChild(new ShellExecutionComponent({
|
|
@@ -366111,7 +367148,7 @@ var ToolCallComponent = class ToolCallComponent extends Container {
|
|
|
366111
367148
|
this.addChild(new ShellExecutionComponent({
|
|
366112
367149
|
command: cmd,
|
|
366113
367150
|
showCommand: true,
|
|
366114
|
-
commandPreviewLines: 10
|
|
367151
|
+
commandPreviewLines: this.expanded ? void 0 : 10
|
|
366115
367152
|
}));
|
|
366116
367153
|
}
|
|
366117
367154
|
}
|
|
@@ -367121,7 +368158,8 @@ async function runPrompt(opts, version, io = {}) {
|
|
|
367121
368158
|
config,
|
|
367122
368159
|
version,
|
|
367123
368160
|
uiMode: PROMPT_UI_MODE,
|
|
367124
|
-
model: telemetryModel
|
|
368161
|
+
model: telemetryModel,
|
|
368162
|
+
sessionId: session.id
|
|
367125
368163
|
});
|
|
367126
368164
|
setCrashPhase("runtime");
|
|
367127
368165
|
const outputFormat = opts.outputFormat ?? "text";
|
|
@@ -369524,7 +370562,11 @@ function buildBody(block) {
|
|
|
369524
370562
|
return buildFileContentBody(block);
|
|
369525
370563
|
}
|
|
369526
370564
|
function buildDiffBody(block) {
|
|
369527
|
-
const [header = "", ...rest] =
|
|
370565
|
+
const [header = "", ...rest] = renderDiffLinesClustered(block.old_text, block.new_text, block.path, {
|
|
370566
|
+
contextLines: 3,
|
|
370567
|
+
oldStart: block.old_start ?? 1,
|
|
370568
|
+
newStart: block.new_start ?? 1
|
|
370569
|
+
});
|
|
369528
370570
|
return {
|
|
369529
370571
|
lines: rest,
|
|
369530
370572
|
title: stripLeadingSpace(header)
|
|
@@ -369563,7 +370605,7 @@ const DEFAULT_KEYBOARD_SHORTCUTS = [
|
|
|
369563
370605
|
},
|
|
369564
370606
|
{
|
|
369565
370607
|
keys: "Ctrl-O",
|
|
369566
|
-
description: "Toggle tool output expansion"
|
|
370608
|
+
description: "Toggle tool output / compaction summary expansion"
|
|
369567
370609
|
},
|
|
369568
370610
|
{
|
|
369569
370611
|
keys: "Ctrl-T",
|
|
@@ -370511,13 +371553,13 @@ const MAX_FALLBACK_SUGGESTIONS = 50;
|
|
|
370511
371553
|
/**
|
|
370512
371554
|
* Kimi wrapper around pi-tui's combined autocomplete provider.
|
|
370513
371555
|
*
|
|
370514
|
-
* File / folder mention behavior uses pi-tui's fd-backed provider
|
|
370515
|
-
* available
|
|
370516
|
-
*
|
|
370517
|
-
*
|
|
370518
|
-
*
|
|
370519
|
-
* readdir-backed path completer. This
|
|
370520
|
-
* slash-command guards.
|
|
371556
|
+
* File / folder mention behavior uses pi-tui's fd-backed provider whenever fd
|
|
371557
|
+
* is available, fanning out across the working directory and any additional
|
|
371558
|
+
* roots so `@` completion pushes the query down to fd instead of enumerating
|
|
371559
|
+
* every file. A small filesystem fallback is used only while managed fd is
|
|
371560
|
+
* downloading, when it is unavailable, or if fd fails to spawn. Ordinary path
|
|
371561
|
+
* completion is still handled by pi-tui's readdir-backed path completer. This
|
|
371562
|
+
* wrapper also keeps Kimi-specific slash-command guards.
|
|
370521
371563
|
*/
|
|
370522
371564
|
var FileMentionProvider = class {
|
|
370523
371565
|
slashCommands;
|
|
@@ -370540,14 +371582,14 @@ var FileMentionProvider = class {
|
|
|
370540
371582
|
name: alias
|
|
370541
371583
|
});
|
|
370542
371584
|
}
|
|
370543
|
-
this.inner = new CombinedAutocompleteProvider(expanded, workDir, fdPath);
|
|
371585
|
+
this.inner = new CombinedAutocompleteProvider(expanded, workDir, fdPath, this.additionalDirs);
|
|
370544
371586
|
}
|
|
370545
371587
|
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
370546
371588
|
const currentLine = lines[cursorLine] ?? "";
|
|
370547
371589
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
370548
371590
|
const atPrefix = extractAtPrefix(textBeforeCursor);
|
|
370549
371591
|
if (atPrefix !== null) {
|
|
370550
|
-
if (this.fdPath === null || this.
|
|
371592
|
+
if (this.fdPath === null || !isExecutableFd(this.fdPath)) return getFsMentionSuggestions(this.workDir, this.additionalDirs, atPrefix, options.signal);
|
|
370551
371593
|
try {
|
|
370552
371594
|
return await this.inner.getSuggestions(lines, cursorLine, cursorCol, options);
|
|
370553
371595
|
} catch {
|
|
@@ -370625,6 +371667,15 @@ function extractAtPrefix(text) {
|
|
|
370625
371667
|
if (text[tokenStart] !== "@") return null;
|
|
370626
371668
|
return text.slice(tokenStart);
|
|
370627
371669
|
}
|
|
371670
|
+
function isExecutableFd(fdPath) {
|
|
371671
|
+
if (!fdPath.includes("/") && !fdPath.includes("\\")) return true;
|
|
371672
|
+
try {
|
|
371673
|
+
accessSync(fdPath, constants.X_OK);
|
|
371674
|
+
return true;
|
|
371675
|
+
} catch {
|
|
371676
|
+
return false;
|
|
371677
|
+
}
|
|
371678
|
+
}
|
|
370628
371679
|
/**
|
|
370629
371680
|
* Match the `/add-dir` directory completer, which skips every entry whose name
|
|
370630
371681
|
* starts with `.` (see registry.ts). pi-tui's path completer sets `label` to
|
|
@@ -374222,7 +375273,7 @@ var SessionEventHandler = class {
|
|
|
374222
375273
|
this.host.streamingUI.beginCompaction(event.instruction);
|
|
374223
375274
|
}
|
|
374224
375275
|
handleCompactionEnd(event, sendQueued) {
|
|
374225
|
-
this.host.streamingUI.endCompaction(event.result.tokensBefore, event.result.tokensAfter);
|
|
375276
|
+
this.host.streamingUI.endCompaction(event.result.tokensBefore, event.result.tokensAfter, event.result.summary);
|
|
374226
375277
|
this.finishCompaction(sendQueued);
|
|
374227
375278
|
}
|
|
374228
375279
|
handleCompactionCancel(_event, sendQueued) {
|
|
@@ -374859,6 +375910,7 @@ var SessionReplayRenderer = class {
|
|
|
374859
375910
|
this.host.appendTranscriptEntry({
|
|
374860
375911
|
...replayEntry(context, "status", "Compaction complete", "plain"),
|
|
374861
375912
|
compactionData: {
|
|
375913
|
+
summary: record.result.summary,
|
|
374862
375914
|
tokensBefore: record.result.tokensBefore,
|
|
374863
375915
|
tokensAfter: record.result.tokensAfter,
|
|
374864
375916
|
instruction: record.instruction
|
|
@@ -375670,12 +376722,13 @@ var StreamingUIController = class {
|
|
|
375670
376722
|
const block = new CompactionComponent(state.ui, instruction, currentWorkingTip()?.text);
|
|
375671
376723
|
this._activeCompactionBlock = block;
|
|
375672
376724
|
state.transcriptContainer.addChild(block);
|
|
376725
|
+
if (state.toolOutputExpanded) block.setExpanded(true);
|
|
375673
376726
|
state.ui.requestRender();
|
|
375674
376727
|
}
|
|
375675
|
-
endCompaction(tokensBefore, tokensAfter) {
|
|
376728
|
+
endCompaction(tokensBefore, tokensAfter, summary) {
|
|
375676
376729
|
const block = this._activeCompactionBlock;
|
|
375677
376730
|
if (block === void 0) return;
|
|
375678
|
-
block.markDone(tokensBefore, tokensAfter);
|
|
376731
|
+
block.markDone(tokensBefore, tokensAfter, summary);
|
|
375679
376732
|
this._activeCompactionBlock = void 0;
|
|
375680
376733
|
this.host.state.ui.requestRender();
|
|
375681
376734
|
}
|
|
@@ -377658,6 +378711,7 @@ var CustomEditor = class extends Editor {
|
|
|
377658
378711
|
consumingPaste = false;
|
|
377659
378712
|
consumeBuffer = "";
|
|
377660
378713
|
argumentHints = /* @__PURE__ */ new Map();
|
|
378714
|
+
autocompleteWasShowing = false;
|
|
377661
378715
|
setArgumentHints(hints) {
|
|
377662
378716
|
this.argumentHints = hints;
|
|
377663
378717
|
}
|
|
@@ -377713,7 +378767,20 @@ var CustomEditor = class extends Editor {
|
|
|
377713
378767
|
cancelAutocompleteActivity() {
|
|
377714
378768
|
this.cancelAutocomplete();
|
|
377715
378769
|
}
|
|
378770
|
+
requestFullRenderOnAutocompleteClose() {
|
|
378771
|
+
if (isInsideTmux()) return;
|
|
378772
|
+
const { columns, rows } = this.tui.terminal;
|
|
378773
|
+
if (this.tui.render(columns).length < rows) return;
|
|
378774
|
+
this.tui.requestRender(true);
|
|
378775
|
+
}
|
|
378776
|
+
trackAutocompleteCloseForFullRender() {
|
|
378777
|
+
const showing = this.isShowingAutocomplete();
|
|
378778
|
+
const closed = this.autocompleteWasShowing && !showing;
|
|
378779
|
+
this.autocompleteWasShowing = showing;
|
|
378780
|
+
if (closed) queueMicrotask(() => this.requestFullRenderOnAutocompleteClose());
|
|
378781
|
+
}
|
|
377716
378782
|
render(width) {
|
|
378783
|
+
this.trackAutocompleteCloseForFullRender();
|
|
377717
378784
|
const lines = super.render(width);
|
|
377718
378785
|
if (lines.length < 3) return lines;
|
|
377719
378786
|
const firstContentIdx = 1;
|
|
@@ -379675,7 +380742,10 @@ var KimiTUI = class {
|
|
|
379675
380742
|
const data = entry.compactionData;
|
|
379676
380743
|
const block = new CompactionComponent(this.state.ui, data.instruction);
|
|
379677
380744
|
if (data.result === "cancelled") block.markCanceled();
|
|
379678
|
-
else
|
|
380745
|
+
else {
|
|
380746
|
+
block.markDone(data.tokensBefore, data.tokensAfter, data.summary);
|
|
380747
|
+
if (this.state.toolOutputExpanded) block.setExpanded(true);
|
|
380748
|
+
}
|
|
379679
380749
|
return block;
|
|
379680
380750
|
}
|
|
379681
380751
|
switch (entry.kind) {
|
|
@@ -380251,7 +381321,9 @@ var KimiTUI = class {
|
|
|
380251
381321
|
this.state.editorContainer.clear();
|
|
380252
381322
|
this.state.editorContainer.addChild(this.state.editor);
|
|
380253
381323
|
this.state.ui.setFocus(this.state.editor);
|
|
380254
|
-
this.state.
|
|
381324
|
+
const { columns, rows } = this.state.terminal;
|
|
381325
|
+
const overflowsViewport = this.state.ui.render(columns).length >= rows;
|
|
381326
|
+
this.state.ui.requestRender(!this.state.terminalState.insideTmux && overflowsViewport);
|
|
380255
381327
|
}
|
|
380256
381328
|
restoreInputText(text) {
|
|
380257
381329
|
this.restoreEditor();
|