@moonshot-ai/kimi-code 0.23.5 → 0.23.6
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 +756 -556
- package/dist-web/assets/{CodeBlockNode-KR0ZBibg.js → CodeBlockNode-B5sM5iYb.js} +1 -1
- package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-Bl31Ov6p.js → CodeBlockShell.vue_vue_type_style_index_0_lang-DJ0XaWcQ.js} +1 -1
- package/dist-web/assets/DesignSystemView-CrA0fNau.js +13 -0
- package/dist-web/assets/DesignSystemView-prdQJClv.css +1 -0
- package/dist-web/assets/{Tooltip-CXVZw3LD.js → Tooltip-BzkYFuS-.js} +1 -1
- package/dist-web/assets/{arc-D-rA9VJS.js → arc-hZy2ybJx.js} +1 -1
- package/dist-web/assets/{architectureDiagram-3BPJPVTR-DCwhZ0-3.js → architectureDiagram-3BPJPVTR-Dme2VOsk.js} +1 -1
- package/dist-web/assets/{blockDiagram-GPEHLZMM-7zi2-mzu.js → blockDiagram-GPEHLZMM-DPYxkkxc.js} +1 -1
- package/dist-web/assets/{c4Diagram-AAUBKEIU-BUhBYlbI.js → c4Diagram-AAUBKEIU-BaBOqczU.js} +1 -1
- package/dist-web/assets/channel--SU3IV4L.js +1 -0
- package/dist-web/assets/{chunk-2J33WTMH-DXfD8jVe.js → chunk-2J33WTMH-D12pYaz9.js} +1 -1
- package/dist-web/assets/{chunk-4BX2VUAB-RnAXB6Jd.js → chunk-4BX2VUAB-BXPJT0AD.js} +1 -1
- package/dist-web/assets/{chunk-55IACEB6-CzyvmHuE.js → chunk-55IACEB6-BTJjSIMx.js} +1 -1
- package/dist-web/assets/{chunk-727SXJPM-BwBvbidm.js → chunk-727SXJPM-BorazSkv.js} +1 -1
- package/dist-web/assets/{chunk-AQP2D5EJ-DHeLjRn1.js → chunk-AQP2D5EJ-3eB1WiGE.js} +1 -1
- package/dist-web/assets/{chunk-FMBD7UC4-Bm646OfX.js → chunk-FMBD7UC4-BN6eq3TW.js} +1 -1
- package/dist-web/assets/{chunk-ND2GUHAM-D3VSc8VX.js → chunk-ND2GUHAM-CzHkIi39.js} +1 -1
- package/dist-web/assets/{chunk-QZHKN3VN-BvZn7Sbo.js → chunk-QZHKN3VN-CAAkvUsl.js} +1 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-Cev__UDN.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-Cev__UDN.js +1 -0
- package/dist-web/assets/{cose-bilkent-S5V4N54A-DdsbNmIL.js → cose-bilkent-S5V4N54A-CO12pcZF.js} +1 -1
- package/dist-web/assets/{dagre-BM42HDAG--3VOObN-.js → dagre-BM42HDAG-BHHr0pRl.js} +1 -1
- package/dist-web/assets/{diagram-2AECGRRQ-DeWvFgbz.js → diagram-2AECGRRQ-OR0kYM7N.js} +1 -1
- package/dist-web/assets/{diagram-5GNKFQAL-DthtQYgS.js → diagram-5GNKFQAL-BuWjKSqL.js} +1 -1
- package/dist-web/assets/{diagram-KO2AKTUF-Bt4BtRLc.js → diagram-KO2AKTUF-VPe8ZEiS.js} +1 -1
- package/dist-web/assets/{diagram-LMA3HP47-7N499o4j.js → diagram-LMA3HP47-BvTXlHih.js} +1 -1
- package/dist-web/assets/{diagram-OG6HWLK6-Br3CxOQX.js → diagram-OG6HWLK6-goJtZNF9.js} +1 -1
- package/dist-web/assets/{erDiagram-TEJ5UH35-BrhRvGW3.js → erDiagram-TEJ5UH35-DRnuyJ1R.js} +1 -1
- package/dist-web/assets/{flowDiagram-I6XJVG4X-D-u112mz.js → flowDiagram-I6XJVG4X-CWAtDH7Q.js} +1 -1
- package/dist-web/assets/{ganttDiagram-6RSMTGT7-DpXOgY93.js → ganttDiagram-6RSMTGT7-DpNy6QeS.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-PVQCEYII-BzV-RpYW.js → gitGraphDiagram-PVQCEYII-D7ekpdjQ.js} +1 -1
- package/dist-web/assets/{index-DrI3jjno.js → index-BPhahMpb.js} +1 -1
- package/dist-web/assets/index-DZAkQfN3.js +322 -0
- package/dist-web/assets/{index-DEjpFBq9.js → index-De7eXGys.js} +2 -2
- package/dist-web/assets/{index-5DXn785n.css → index-u0HjHtha.css} +1 -1
- package/dist-web/assets/{index10-UVo4gjYR.js → index10-B4kCqL2q.js} +1 -1
- package/dist-web/assets/{index11-m1oYWviR.js → index11-CdYjVQZ3.js} +1 -1
- package/dist-web/assets/{index5-B45mMYRO.js → index5-CuGXaX2S.js} +1 -1
- package/dist-web/assets/{index6-DvvrfRua.js → index6-Bu6r1Fdb.js} +1 -1
- package/dist-web/assets/{index7-BUH5Peml.js → index7-BBWbs1u4.js} +1 -1
- package/dist-web/assets/{index8-1BPQUZEF.js → index8-B1e6fpQC.js} +2 -2
- package/dist-web/assets/{infoDiagram-5YYISTIA-Cu7fADeQ.js → infoDiagram-5YYISTIA-DWJMi_CT.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-CVvnTORb.js → ishikawaDiagram-YF4QCWOH-DKnaDM-v.js} +1 -1
- package/dist-web/assets/{journeyDiagram-JHISSGLW-C-69S6wV.js → journeyDiagram-JHISSGLW-CuTF_v7K.js} +1 -1
- package/dist-web/assets/{kanban-definition-UN3LZRKU-pwEooP5T.js → kanban-definition-UN3LZRKU-7ZkgOrqm.js} +1 -1
- package/dist-web/assets/{linear-BQ3ylJG8.js → linear-BZuIfHuU.js} +1 -1
- package/dist-web/assets/{mermaid.core-DcE0EhAy.js → mermaid.core-BU-yVv7K.js} +4 -4
- package/dist-web/assets/{mindmap-definition-RKZ34NQL-DKQ2AZ3h.js → mindmap-definition-RKZ34NQL-DME_lWCk.js} +1 -1
- package/dist-web/assets/{pieDiagram-4H26LBE5-CHb1kYTj.js → pieDiagram-4H26LBE5-Co1VItYc.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-W4KKPZXB-DzFGGLJt.js → quadrantDiagram-W4KKPZXB-DpswDnET.js} +1 -1
- package/dist-web/assets/{requirementDiagram-4Y6WPE33-Bk-5_Exk.js → requirementDiagram-4Y6WPE33-BeRdWb9K.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-5OEKKPKP-CSxfPrmb.js → sankeyDiagram-5OEKKPKP-_DYbW6pt.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-3UESZ5HK-DHFbmk49.js → sequenceDiagram-3UESZ5HK-DHiijecn.js} +1 -1
- package/dist-web/assets/{stateDiagram-AJRCARHV-DR8SEStc.js → stateDiagram-AJRCARHV-DCZ1rX02.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-Cw0BsNEk.js +1 -0
- package/dist-web/assets/{timeline-definition-PNZ67QCA-O5r5mf9f.js → timeline-definition-PNZ67QCA-CUBRS-qH.js} +1 -1
- package/dist-web/assets/{vennDiagram-CIIHVFJN-BRtD6E2o.js → vennDiagram-CIIHVFJN-C98FTG2Y.js} +1 -1
- package/dist-web/assets/{vue.runtime.esm-bundler-ClW1ucng.js → vue.runtime.esm-bundler-DPzO-Tma.js} +1 -1
- package/dist-web/assets/{wardley-L42UT6IY-BqzYPkrr.js → wardley-L42UT6IY-Bmyzb8p9.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-YWT4CUSO-BXjVelBc.js → wardleyDiagram-YWT4CUSO-CxFNYY1a.js} +1 -1
- package/dist-web/assets/{xychartDiagram-2RQKCTM6-Cc97QEmc.js → xychartDiagram-2RQKCTM6-ySyVEQA-.js} +1 -1
- package/dist-web/index.html +2 -2
- package/package.json +5 -5
- package/dist-web/assets/DesignSystemView-B0VQ8shl.css +0 -1
- package/dist-web/assets/DesignSystemView-DU67euCs.js +0 -13
- package/dist-web/assets/channel-B7bRl8z3.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-CxRebqWF.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-CxRebqWF.js +0 -1
- package/dist-web/assets/index-6oRZtoED.js +0 -322
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-Cp9aas86.js +0 -1
package/dist/main.mjs
CHANGED
|
@@ -1063,7 +1063,7 @@ var init_provider$1 = __esmMin((() => {}));
|
|
|
1063
1063
|
function isUnknownCapability(capability) {
|
|
1064
1064
|
if (capability === UNKNOWN_CAPABILITY) return true;
|
|
1065
1065
|
if (capability[UNKNOWN_CAPABILITY_MARKER] === true) return true;
|
|
1066
|
-
return !capability.image_in && !capability.video_in && !capability.audio_in && !capability.thinking && !capability.tool_use && capability.
|
|
1066
|
+
return !capability.image_in && !capability.video_in && !capability.audio_in && !capability.thinking && !capability.tool_use && capability.dynamically_loaded_tools !== true && capability.max_context_tokens === 0;
|
|
1067
1067
|
}
|
|
1068
1068
|
var UNKNOWN_CAPABILITY_MARKER, UNKNOWN_CAPABILITY;
|
|
1069
1069
|
var init_capability = __esmMin((() => {
|
|
@@ -1075,7 +1075,7 @@ var init_capability = __esmMin((() => {
|
|
|
1075
1075
|
thinking: false,
|
|
1076
1076
|
tool_use: false,
|
|
1077
1077
|
max_context_tokens: 0,
|
|
1078
|
-
|
|
1078
|
+
dynamically_loaded_tools: false
|
|
1079
1079
|
}, UNKNOWN_CAPABILITY_MARKER, { value: true }));
|
|
1080
1080
|
}));
|
|
1081
1081
|
//#endregion
|
|
@@ -55117,7 +55117,7 @@ function catalogModelToCapability(model) {
|
|
|
55117
55117
|
thinking: Boolean(model.reasoning),
|
|
55118
55118
|
tool_use: model.tool_call ?? true,
|
|
55119
55119
|
max_context_tokens: context,
|
|
55120
|
-
|
|
55120
|
+
dynamically_loaded_tools: model.dynamically_loaded_tools === true
|
|
55121
55121
|
}
|
|
55122
55122
|
};
|
|
55123
55123
|
}
|
|
@@ -62007,7 +62007,7 @@ function isValidPermissionPattern(pattern) {
|
|
|
62007
62007
|
return false;
|
|
62008
62008
|
}
|
|
62009
62009
|
}
|
|
62010
|
-
var ProviderTypeSchema, OAuthRefSchema, StringRecordSchema, ProviderConfigSchema, ModelAliasBaseSchema, ModelAliasOverrideSchema, ModelAliasSchema, ThinkingConfigSchema, PermissionModeSchema, PermissionRuleDecisionSchema, PermissionRuleScopeSchema, PermissionRuleSchema, PermissionConfigSchema, LoopControlSchema, BackgroundConfigSchema, ImageConfigSchema, ModelCatalogConfigSchema, ExperimentalConfigSchema, HookDefSchema, MoonshotServiceConfigSchema, ServicesConfigSchema, McpServerCommonFields, McpServerStdioConfigSchema, McpServerHttpConfigSchema, McpServerSseConfigSchema, McpServerConfigDiscriminatedSchema, McpServerConfigSchema, KimiConfigSchema, ProviderConfigPatchSchema, ModelAliasPatchSchema, ThinkingConfigPatchSchema, PermissionConfigPatchSchema, LoopControlPatchSchema, BackgroundConfigPatchSchema, ImageConfigPatchSchema, ModelCatalogConfigPatchSchema, ExperimentalConfigPatchSchema, MoonshotServiceConfigPatchSchema, ServicesConfigPatchSchema, KimiConfigPatchSchema;
|
|
62010
|
+
var ProviderTypeSchema, OAuthRefSchema, StringRecordSchema, ProviderConfigSchema, ModelAliasBaseSchema, ModelAliasOverrideSchema, ModelAliasSchema, ThinkingConfigSchema, PermissionModeSchema, PermissionRuleDecisionSchema, PermissionRuleScopeSchema, PermissionRuleSchema, PermissionConfigSchema, LoopControlSchema, BackgroundConfigSchema, SubagentConfigSchema, ImageConfigSchema, ModelCatalogConfigSchema, ExperimentalConfigSchema, HookDefSchema, MoonshotServiceConfigSchema, ServicesConfigSchema, McpServerCommonFields, McpServerStdioConfigSchema, McpServerHttpConfigSchema, McpServerSseConfigSchema, McpServerConfigDiscriminatedSchema, McpServerConfigSchema, KimiConfigSchema, ProviderConfigPatchSchema, ModelAliasPatchSchema, ThinkingConfigPatchSchema, PermissionConfigPatchSchema, LoopControlPatchSchema, BackgroundConfigPatchSchema, SubagentConfigPatchSchema, ImageConfigPatchSchema, ModelCatalogConfigPatchSchema, ExperimentalConfigPatchSchema, MoonshotServiceConfigPatchSchema, ServicesConfigPatchSchema, KimiConfigPatchSchema;
|
|
62011
62011
|
var init_schema = __esmMin((() => {
|
|
62012
62012
|
init_types$18();
|
|
62013
62013
|
init_matches_rule();
|
|
@@ -62097,8 +62097,15 @@ var init_schema = __esmMin((() => {
|
|
|
62097
62097
|
maxRunningTasks: number$1().int().min(1).optional(),
|
|
62098
62098
|
keepAliveOnExit: boolean$1().optional(),
|
|
62099
62099
|
killGracePeriodMs: number$1().int().min(0).optional(),
|
|
62100
|
-
printWaitCeilingS: number$1().int().min(1).optional()
|
|
62100
|
+
printWaitCeilingS: number$1().int().min(1).optional(),
|
|
62101
|
+
printBackgroundMode: _enum([
|
|
62102
|
+
"exit",
|
|
62103
|
+
"drain",
|
|
62104
|
+
"steer"
|
|
62105
|
+
]).optional(),
|
|
62106
|
+
printMaxTurns: number$1().int().min(1).optional()
|
|
62101
62107
|
});
|
|
62108
|
+
SubagentConfigSchema = object({ timeoutMs: number$1().int().min(1).optional() });
|
|
62102
62109
|
ImageConfigSchema = object({
|
|
62103
62110
|
/**
|
|
62104
62111
|
* Longest-edge ceiling (px) applied when compressing images for the model.
|
|
@@ -62204,6 +62211,7 @@ var init_schema = __esmMin((() => {
|
|
|
62204
62211
|
extraSkillDirs: array(string()).optional(),
|
|
62205
62212
|
loopControl: LoopControlSchema.optional(),
|
|
62206
62213
|
background: BackgroundConfigSchema.optional(),
|
|
62214
|
+
subagent: SubagentConfigSchema.optional(),
|
|
62207
62215
|
image: ImageConfigSchema.optional(),
|
|
62208
62216
|
modelCatalog: ModelCatalogConfigSchema.optional(),
|
|
62209
62217
|
experimental: ExperimentalConfigSchema.optional(),
|
|
@@ -62216,6 +62224,7 @@ var init_schema = __esmMin((() => {
|
|
|
62216
62224
|
PermissionConfigPatchSchema = PermissionConfigSchema.partial();
|
|
62217
62225
|
LoopControlPatchSchema = LoopControlSchema.partial();
|
|
62218
62226
|
BackgroundConfigPatchSchema = BackgroundConfigSchema.partial();
|
|
62227
|
+
SubagentConfigPatchSchema = SubagentConfigSchema.partial();
|
|
62219
62228
|
ImageConfigPatchSchema = ImageConfigSchema.partial();
|
|
62220
62229
|
ModelCatalogConfigPatchSchema = ModelCatalogConfigSchema.partial();
|
|
62221
62230
|
ExperimentalConfigPatchSchema = ExperimentalConfigSchema;
|
|
@@ -62241,6 +62250,7 @@ var init_schema = __esmMin((() => {
|
|
|
62241
62250
|
extraSkillDirs: array(string()).optional(),
|
|
62242
62251
|
loopControl: LoopControlPatchSchema.optional(),
|
|
62243
62252
|
background: BackgroundConfigPatchSchema.optional(),
|
|
62253
|
+
subagent: SubagentConfigPatchSchema.optional(),
|
|
62244
62254
|
image: ImageConfigPatchSchema.optional(),
|
|
62245
62255
|
modelCatalog: ModelCatalogConfigPatchSchema.optional(),
|
|
62246
62256
|
experimental: ExperimentalConfigPatchSchema.optional(),
|
|
@@ -63744,6 +63754,7 @@ function transformTomlData(data) {
|
|
|
63744
63754
|
else if (targetKey === "background" && isPlainObject$2(value)) result[targetKey] = transformPlainObject(value);
|
|
63745
63755
|
else if (targetKey === "image" && isPlainObject$2(value)) result[targetKey] = transformPlainObject(value);
|
|
63746
63756
|
else if (targetKey === "experimental" && isPlainObject$2(value)) result[targetKey] = cloneRecord$2(value);
|
|
63757
|
+
else if (targetKey === "subagent" && isPlainObject$2(value)) result[targetKey] = transformPlainObject(value);
|
|
63747
63758
|
else if (!isPlainObject$2(value)) result[targetKey] = value;
|
|
63748
63759
|
}
|
|
63749
63760
|
return result;
|
|
@@ -63854,6 +63865,7 @@ function configToTomlData(config) {
|
|
|
63854
63865
|
setSection(out, "services", config.services, servicesToToml);
|
|
63855
63866
|
setSection(out, "loop_control", config.loopControl, loopControlToToml);
|
|
63856
63867
|
setSection(out, "background", config.background, backgroundToToml);
|
|
63868
|
+
setSection(out, "subagent", config.subagent, subagentToToml);
|
|
63857
63869
|
setSection(out, "image", config.image, imageToToml);
|
|
63858
63870
|
setSection(out, "experimental", config.experimental, experimentalToToml);
|
|
63859
63871
|
setSection(out, "permission", config.permission, permissionToToml);
|
|
@@ -63945,6 +63957,11 @@ function backgroundToToml(background, rawBackground) {
|
|
|
63945
63957
|
for (const [key, value] of Object.entries(background)) setDefined(out, camelToSnake$3(key), value);
|
|
63946
63958
|
return out;
|
|
63947
63959
|
}
|
|
63960
|
+
function subagentToToml(subagent, rawSubagent) {
|
|
63961
|
+
const out = cloneRecord$2(rawSubagent);
|
|
63962
|
+
for (const [key, value] of Object.entries(subagent)) setDefined(out, camelToSnake$3(key), value);
|
|
63963
|
+
return out;
|
|
63964
|
+
}
|
|
63948
63965
|
function imageToToml(image, rawImage) {
|
|
63949
63966
|
const out = cloneRecord$2(rawImage);
|
|
63950
63967
|
for (const [key, value] of Object.entries(image)) setDefined(out, camelToSnake$3(key), value);
|
|
@@ -68630,7 +68647,7 @@ var init_registry$1 = __esmMin((() => {
|
|
|
68630
68647
|
FLAG_DEFINITIONS = [{
|
|
68631
68648
|
id: "tool-select",
|
|
68632
68649
|
title: "Tool select (progressive tool disclosure)",
|
|
68633
|
-
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
|
|
68650
|
+
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 dynamically loaded tools.",
|
|
68634
68651
|
env: "KIMI_CODE_EXPERIMENTAL_TOOL_SELECT",
|
|
68635
68652
|
default: false,
|
|
68636
68653
|
surface: "core"
|
|
@@ -121218,10 +121235,10 @@ function isLoadableToolsAnnouncement(message) {
|
|
|
121218
121235
|
* Shape a history for a consumer that must not see dynamic-tool protocol
|
|
121219
121236
|
* context: drop the loadable-tools announcements and strip `message.tools`
|
|
121220
121237
|
* (dropping the message entirely when nothing else remains). Two callers:
|
|
121221
|
-
* - projection for a model without the
|
|
121222
|
-
* model switch — the canonical history keeps its shape, only
|
|
121223
|
-
* view changes; announcements would be noise and even
|
|
121224
|
-
* select_tools tool the model does not have);
|
|
121238
|
+
* - projection for a model without the dynamically-loaded-tools capability
|
|
121239
|
+
* (mid-session model switch — the canonical history keeps its shape, only
|
|
121240
|
+
* the outgoing view changes; announcements would be noise and even
|
|
121241
|
+
* reference a select_tools tool the model does not have);
|
|
121225
121242
|
* - the compaction summarizer input (schemas and announcements are protocol
|
|
121226
121243
|
* context, not conversation — summarizing them wastes tokens and risks
|
|
121227
121244
|
* leaking schema text into the summary).
|
|
@@ -123582,6 +123599,21 @@ var init_manager$2 = __esmMin((() => {
|
|
|
123582
123599
|
return this.scheduler.getNextFireForTask(taskId);
|
|
123583
123600
|
}
|
|
123584
123601
|
/**
|
|
123602
|
+
* Enumerate every scheduled task with its post-jitter next fire time.
|
|
123603
|
+
* Unlike the CronList tool (which renders for the model), this returns
|
|
123604
|
+
* structured data for host applications polling for pending work.
|
|
123605
|
+
*/
|
|
123606
|
+
listTaskSnapshots() {
|
|
123607
|
+
return this.store.list().map((task) => ({
|
|
123608
|
+
id: task.id,
|
|
123609
|
+
cron: task.cron,
|
|
123610
|
+
recurring: task.recurring !== false,
|
|
123611
|
+
createdAt: task.createdAt,
|
|
123612
|
+
lastFiredAt: task.lastFiredAt,
|
|
123613
|
+
nextFireAt: this.scheduler.getNextFireForTask(task.id)
|
|
123614
|
+
}));
|
|
123615
|
+
}
|
|
123616
|
+
/**
|
|
123585
123617
|
* Stale judgment.
|
|
123586
123618
|
*
|
|
123587
123619
|
* - `KIMI_CRON_NO_STALE=1` short-circuits to false (bench).
|
|
@@ -144351,479 +144383,6 @@ var init_output = __esmMin((() => {
|
|
|
144351
144383
|
MCP_MAX_BINARY_PART_CHARS = Math.ceil(MCP_MAX_BINARY_PART_BYTES * 4 / 3);
|
|
144352
144384
|
}));
|
|
144353
144385
|
//#endregion
|
|
144354
|
-
//#region ../../packages/agent-core/src/agent/llm-request-logger.ts
|
|
144355
|
-
function splitGenerateOptions(options) {
|
|
144356
|
-
if (options === void 0) return {
|
|
144357
|
-
requestLogFields: void 0,
|
|
144358
|
-
generateOptions: void 0
|
|
144359
|
-
};
|
|
144360
|
-
const { requestLogFields, ...generateOptions } = options;
|
|
144361
|
-
return {
|
|
144362
|
-
requestLogFields,
|
|
144363
|
-
generateOptions
|
|
144364
|
-
};
|
|
144365
|
-
}
|
|
144366
|
-
function toolSignature(tools) {
|
|
144367
|
-
return tools.map(({ name, description, parameters }) => ({
|
|
144368
|
-
name,
|
|
144369
|
-
description,
|
|
144370
|
-
parameters
|
|
144371
|
-
}));
|
|
144372
|
-
}
|
|
144373
|
-
function fingerprint(content) {
|
|
144374
|
-
return createHash("sha256").update(content).digest("hex");
|
|
144375
|
-
}
|
|
144376
|
-
var LlmRequestLogger;
|
|
144377
|
-
var init_llm_request_logger = __esmMin((() => {
|
|
144378
|
-
LlmRequestLogger = class {
|
|
144379
|
-
log;
|
|
144380
|
-
lastConfigLogSignature;
|
|
144381
|
-
constructor(log) {
|
|
144382
|
-
this.log = log;
|
|
144383
|
-
}
|
|
144384
|
-
logRequest(input) {
|
|
144385
|
-
const { provider, modelAlias, systemPrompt, tools, messages, fields } = input;
|
|
144386
|
-
const requestLogFields = fields ?? {};
|
|
144387
|
-
const wireTools = tools.filter((tool) => tool.deferred !== true);
|
|
144388
|
-
const config = {
|
|
144389
|
-
provider: provider.name,
|
|
144390
|
-
model: provider.modelName,
|
|
144391
|
-
modelAlias,
|
|
144392
|
-
thinkingEffort: provider.thinkingEffort ?? void 0,
|
|
144393
|
-
systemPromptChars: systemPrompt.length,
|
|
144394
|
-
toolCount: wireTools.length
|
|
144395
|
-
};
|
|
144396
|
-
const signature = JSON.stringify({
|
|
144397
|
-
...config,
|
|
144398
|
-
systemPromptHash: fingerprint(systemPrompt),
|
|
144399
|
-
toolsHash: fingerprint(JSON.stringify(toolSignature(wireTools)))
|
|
144400
|
-
});
|
|
144401
|
-
if (signature !== this.lastConfigLogSignature) {
|
|
144402
|
-
this.lastConfigLogSignature = signature;
|
|
144403
|
-
this.log.info("llm config", {
|
|
144404
|
-
...requestLogFields,
|
|
144405
|
-
...config
|
|
144406
|
-
});
|
|
144407
|
-
}
|
|
144408
|
-
const partialMessageCount = messages.filter((message) => message.partial === true).length;
|
|
144409
|
-
const requestFields = { ...requestLogFields };
|
|
144410
|
-
if (partialMessageCount > 0) requestFields.partialMessageCount = partialMessageCount;
|
|
144411
|
-
this.log.info("llm request", requestFields);
|
|
144412
|
-
}
|
|
144413
|
-
};
|
|
144414
|
-
}));
|
|
144415
|
-
//#endregion
|
|
144416
|
-
//#region ../../packages/agent-core/src/tools/background/task-output.md?raw
|
|
144417
|
-
var task_output_default;
|
|
144418
|
-
var init_task_output$1 = __esmMin((() => {
|
|
144419
|
-
task_output_default = "Retrieve output from a running or completed background task.\n\nUse this after `Bash(run_in_background=true)` or `Agent(run_in_background=true)` when you need to inspect progress or explicitly wait for completion.\n\nGuidelines:\n- Prefer relying on automatic completion notifications. Use this tool only when you need task output before the automatic notification arrives.\n- Do not use TaskOutput to wait for a result you need before continuing — if your next step depends on the task's result, run that task in the foreground instead. TaskOutput is for a deliberate progress check you will act on without blocking, not a way to sit and wait for a background task you just launched.\n- By default this tool is non-blocking and returns a current status/output snapshot.\n- Use block=true only when you intentionally want to wait for completion or timeout.\n- This tool returns structured task metadata, a fixed-size output preview, and an output_path for the full log.\n- For a terminal task, the metadata also explains why it ended. A shell command that runs to completion reports `status: completed` on a zero exit, or `status: failed` with its non-zero `exit_code` — judge that failure from the `exit_code`, because a plain command failure carries no `stop_reason` and no `terminal_reason`. `terminal_reason` is a categorical label emitted only when the end is not an ordinary exit: `timed_out` when the deadline aborted it, `stopped` when it was explicitly stopped, or `failed` when it errored without producing an exit code; the `stopped` and `failed` cases also carry a human-readable `stop_reason`. A task that finished on its own with a clean exit carries neither `stop_reason` nor `terminal_reason`.\n- The full, never-truncated log is always available at output_path; use the `Read` tool with that path to page through it, whether or not the preview was truncated.\n- This tool works with the generic background task system and should remain the primary read path for future task types, not just bash.\n";
|
|
144420
|
-
}));
|
|
144421
|
-
//#endregion
|
|
144422
|
-
//#region ../../packages/agent-core/src/tools/background/task-output.ts
|
|
144423
|
-
function retrievalStatus(status, block) {
|
|
144424
|
-
if (isBackgroundTaskTerminal(status)) return "success";
|
|
144425
|
-
return block ? "timeout" : "not_ready";
|
|
144426
|
-
}
|
|
144427
|
-
function terminalReason(info) {
|
|
144428
|
-
if (info.status === "timed_out") return "timed_out";
|
|
144429
|
-
if (info.status === "killed" && info.stopReason !== void 0) return "stopped";
|
|
144430
|
-
if (info.status === "failed" && info.stopReason !== void 0) return "failed";
|
|
144431
|
-
}
|
|
144432
|
-
function fullOutputHint(output) {
|
|
144433
|
-
if (!output.fullOutputAvailable || output.outputPath === void 0) return void 0;
|
|
144434
|
-
if (output.truncated) return `Only the last ${String(OUTPUT_PREVIEW_BYTES)} bytes are shown above. Use the Read tool with the output_path to page through the full log (parameters: path, line_offset, n_lines; read about ${String(PAGING_HINT_LINES)} lines per page).`;
|
|
144435
|
-
return `The preview above is the complete output. Use the Read tool with the output_path if you need to re-read the full log later (parameters: path, line_offset, n_lines; read about ${String(PAGING_HINT_LINES)} lines per page).`;
|
|
144436
|
-
}
|
|
144437
|
-
var OUTPUT_PREVIEW_BYTES, PAGING_HINT_LINES, TaskOutputInputSchema, TaskOutputTool;
|
|
144438
|
-
var init_task_output = __esmMin((() => {
|
|
144439
|
-
init_zod$1();
|
|
144440
|
-
init_background();
|
|
144441
|
-
init_input_schema();
|
|
144442
|
-
init_rule_match();
|
|
144443
|
-
init_format();
|
|
144444
|
-
init_task_output$1();
|
|
144445
|
-
OUTPUT_PREVIEW_BYTES = 32 * 1024;
|
|
144446
|
-
PAGING_HINT_LINES = 300;
|
|
144447
|
-
TaskOutputInputSchema = object({
|
|
144448
|
-
task_id: string().describe("The background task ID to inspect."),
|
|
144449
|
-
block: boolean$1().default(false).describe("Whether to wait for the task to finish before returning.").optional(),
|
|
144450
|
-
timeout: number$1().int().min(0).max(3600).default(30).describe("Maximum number of seconds to wait when block=true.").optional()
|
|
144451
|
-
});
|
|
144452
|
-
TaskOutputTool = class {
|
|
144453
|
-
manager;
|
|
144454
|
-
name = "TaskOutput";
|
|
144455
|
-
description = task_output_default;
|
|
144456
|
-
parameters = toInputJsonSchema(TaskOutputInputSchema);
|
|
144457
|
-
constructor(manager) {
|
|
144458
|
-
this.manager = manager;
|
|
144459
|
-
}
|
|
144460
|
-
resolveExecution(args) {
|
|
144461
|
-
return {
|
|
144462
|
-
description: `Reading output of task ${args.task_id}`,
|
|
144463
|
-
approvalRule: this.name,
|
|
144464
|
-
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.task_id),
|
|
144465
|
-
execute: () => this.execute(args)
|
|
144466
|
-
};
|
|
144467
|
-
}
|
|
144468
|
-
async execute(args) {
|
|
144469
|
-
const info = this.manager.getTask(args.task_id);
|
|
144470
|
-
if (!info) return {
|
|
144471
|
-
isError: true,
|
|
144472
|
-
output: `Task not found: ${args.task_id}`
|
|
144473
|
-
};
|
|
144474
|
-
if (args.block && !isBackgroundTaskTerminal(info.status)) await this.manager.wait(args.task_id, (args.timeout ?? 30) * 1e3);
|
|
144475
|
-
const current = this.manager.getTask(args.task_id);
|
|
144476
|
-
if (!current) return {
|
|
144477
|
-
isError: true,
|
|
144478
|
-
output: `Task not found: ${args.task_id}`
|
|
144479
|
-
};
|
|
144480
|
-
const output = await this.manager.getOutputSnapshot(args.task_id, OUTPUT_PREVIEW_BYTES);
|
|
144481
|
-
const lines = [formatPlainObject({
|
|
144482
|
-
retrievalStatus: retrievalStatus(current.status, args.block),
|
|
144483
|
-
...current,
|
|
144484
|
-
outputPath: output.outputPath,
|
|
144485
|
-
terminalReason: terminalReason(current),
|
|
144486
|
-
outputSizeBytes: output.outputSizeBytes,
|
|
144487
|
-
outputPreviewBytes: output.previewBytes,
|
|
144488
|
-
outputTruncated: output.truncated,
|
|
144489
|
-
fullOutputAvailable: output.fullOutputAvailable,
|
|
144490
|
-
fullOutputTool: output.fullOutputAvailable && output.outputPath !== void 0 ? "Read" : void 0,
|
|
144491
|
-
fullOutputHint: fullOutputHint(output)
|
|
144492
|
-
}), ""];
|
|
144493
|
-
if (output.truncated) lines.push(output.fullOutputAvailable && output.outputPath !== void 0 ? `[Truncated. Full output: ${output.outputPath}]` : "[Truncated. No persisted full log is available for this task.]");
|
|
144494
|
-
lines.push("[output]", output.preview || "[no output available]");
|
|
144495
|
-
return {
|
|
144496
|
-
output: lines.join("\n"),
|
|
144497
|
-
isError: false,
|
|
144498
|
-
message: "Task snapshot retrieved."
|
|
144499
|
-
};
|
|
144500
|
-
}
|
|
144501
|
-
};
|
|
144502
|
-
}));
|
|
144503
|
-
//#endregion
|
|
144504
|
-
//#region ../../packages/agent-core/src/tools/background/task-stop.md?raw
|
|
144505
|
-
var task_stop_default;
|
|
144506
|
-
var init_task_stop$1 = __esmMin((() => {
|
|
144507
|
-
task_stop_default = "Stop a running background task.\n\nOnly use this when a task must genuinely be cancelled — for a task that is\nfinishing normally, wait for its completion notification or inspect it with\n`TaskOutput` instead of stopping it.\n\nGuidelines:\n- This is a general-purpose stop capability for any background task. It is not\n a bash-specific kill.\n- Stopping a task is destructive: it may leave partial side effects behind.\n Use it with care.\n- If the task has already finished, this tool simply returns its current\n status.\n";
|
|
144508
|
-
}));
|
|
144509
|
-
//#endregion
|
|
144510
|
-
//#region ../../packages/agent-core/src/tools/background/task-stop.ts
|
|
144511
|
-
function terminalStopReason(reason) {
|
|
144512
|
-
const trimmed = reason?.trim();
|
|
144513
|
-
return trimmed === void 0 || trimmed.length === 0 ? "Task already in terminal state" : trimmed;
|
|
144514
|
-
}
|
|
144515
|
-
var TaskStopInputSchema, TaskStopTool;
|
|
144516
|
-
var init_task_stop = __esmMin((() => {
|
|
144517
|
-
init_zod$1();
|
|
144518
|
-
init_background();
|
|
144519
|
-
init_input_schema();
|
|
144520
|
-
init_rule_match();
|
|
144521
|
-
init_task_stop$1();
|
|
144522
|
-
TaskStopInputSchema = object({
|
|
144523
|
-
task_id: string().describe("The background task ID to stop."),
|
|
144524
|
-
reason: string().default("Stopped by TaskStop").describe("Short reason recorded when the task is stopped.").optional()
|
|
144525
|
-
});
|
|
144526
|
-
TaskStopTool = class {
|
|
144527
|
-
manager;
|
|
144528
|
-
name = "TaskStop";
|
|
144529
|
-
description = task_stop_default;
|
|
144530
|
-
parameters = toInputJsonSchema(TaskStopInputSchema);
|
|
144531
|
-
constructor(manager) {
|
|
144532
|
-
this.manager = manager;
|
|
144533
|
-
}
|
|
144534
|
-
resolveExecution(args) {
|
|
144535
|
-
return {
|
|
144536
|
-
description: `Stopping task ${args.task_id}`,
|
|
144537
|
-
approvalRule: this.name,
|
|
144538
|
-
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.task_id),
|
|
144539
|
-
execute: async () => {
|
|
144540
|
-
const info = this.manager.getTask(args.task_id);
|
|
144541
|
-
if (!info) return {
|
|
144542
|
-
isError: true,
|
|
144543
|
-
output: `Task not found: ${args.task_id}`
|
|
144544
|
-
};
|
|
144545
|
-
const trimmedReason = args.reason?.trim();
|
|
144546
|
-
const reason = trimmedReason === void 0 || trimmedReason.length === 0 ? "Stopped by TaskStop" : trimmedReason;
|
|
144547
|
-
if (isBackgroundTaskTerminal(info.status)) return {
|
|
144548
|
-
output: `task_id: ${info.taskId}\nstatus: ${info.status}\nreason: ${terminalStopReason(info.stopReason)}`,
|
|
144549
|
-
isError: false
|
|
144550
|
-
};
|
|
144551
|
-
await this.manager.suppressTerminalNotification(args.task_id);
|
|
144552
|
-
const result = await this.manager.stop(args.task_id, reason);
|
|
144553
|
-
if (!result) return {
|
|
144554
|
-
isError: true,
|
|
144555
|
-
output: `Failed to stop task: ${args.task_id}`
|
|
144556
|
-
};
|
|
144557
|
-
return {
|
|
144558
|
-
output: `task_id: ${result.taskId}\nstatus: ${result.status}\nreason: ${result.stopReason ?? reason}`,
|
|
144559
|
-
isError: false
|
|
144560
|
-
};
|
|
144561
|
-
}
|
|
144562
|
-
};
|
|
144563
|
-
}
|
|
144564
|
-
};
|
|
144565
|
-
}));
|
|
144566
|
-
//#endregion
|
|
144567
|
-
//#region ../../packages/agent-core/src/tools/cron/time-format.ts
|
|
144568
|
-
/**
|
|
144569
|
-
* Render cron-facing timestamps in local wall time with an explicit
|
|
144570
|
-
* numeric offset. Cron expressions are evaluated in local time, so the
|
|
144571
|
-
* tool output should preserve that mental model while remaining
|
|
144572
|
-
* unambiguous and parseable as ISO 8601.
|
|
144573
|
-
*/
|
|
144574
|
-
function formatLocalIsoWithOffset(ms) {
|
|
144575
|
-
const date = new Date(ms);
|
|
144576
|
-
const offsetMin = -date.getTimezoneOffset();
|
|
144577
|
-
const sign = offsetMin >= 0 ? "+" : "-";
|
|
144578
|
-
const absOffset = Math.abs(offsetMin);
|
|
144579
|
-
const offset = `${sign}${pad(Math.floor(absOffset / 60))}:${pad(absOffset % 60)}`;
|
|
144580
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${String(date.getMilliseconds()).padStart(3, "0")}${offset}`;
|
|
144581
|
-
}
|
|
144582
|
-
function pad(n) {
|
|
144583
|
-
return String(n).padStart(2, "0");
|
|
144584
|
-
}
|
|
144585
|
-
var init_time_format = __esmMin((() => {}));
|
|
144586
|
-
//#endregion
|
|
144587
|
-
//#region ../../packages/agent-core/src/tools/cron/cron-create.md?raw
|
|
144588
|
-
var cron_create_default;
|
|
144589
|
-
var init_cron_create$1 = __esmMin((() => {
|
|
144590
|
-
cron_create_default = "Schedule a prompt to be enqueued at a future time. Use for both recurring schedules and one-shot reminders.\n\nUses standard 5-field cron in the user's local timezone: minute hour day-of-month month day-of-week. `0 9 * * *` means 9am local — no timezone conversion needed.\n\n## One-shot tasks (recurring: false)\n\nFor \"remind me at X\" or \"at <time>, do Y\" requests — fire once then auto-delete.\nPin minute/hour/day-of-month/month to specific values:\n \"remind me at 2:30pm today to check the deploy\" → cron: \"30 14 <today_dom> <today_month> *\", recurring: false\n \"tomorrow morning, run the smoke test\" → cron: \"57 8 <tomorrow_dom> <tomorrow_month> *\", recurring: false\n\nOne-shots are best for near-term reminders. A task only fires while its session is still alive (see Session lifetime below), so favor near times — within hours or a few days — rather than scheduling weeks or months ahead.\n\n## Recurring jobs (recurring: true, the default)\n\nFor \"every N minutes\" / \"every hour\" / \"weekdays at 9am\" requests:\n \"*/5 * * * *\" (every 5 min), \"0 * * * *\" (hourly), \"0 9 * * 1-5\" (weekdays at 9am local)\n\n## Avoid the :00 and :30 minute marks when the task allows it\n\nEvery user who asks for \"9am\" gets `0 9`, and every user who asks for \"hourly\" gets `0 *` — which means requests from across the planet land on the API at the same instant. When the user's request is approximate, pick a minute that is NOT 0 or 30:\n \"every morning around 9\" → \"57 8 * * *\" or \"3 9 * * *\" (not \"0 9 * * *\")\n \"hourly\" → \"7 * * * *\" (not \"0 * * * *\")\n \"in an hour or so, remind me to...\" → pick whatever minute you land on, don't round\n\nOnly use minute 0 or 30 when the user names that exact time and clearly means it (\"at 9:00 sharp\", \"at half past\", coordinating with a meeting). When in doubt, nudge a few minutes early or late — the user will not notice, and the fleet will.\n\n## Coalesce semantics\n\nFires are delivered only while the session is idle: a fire that comes due during an active turn is held and delivered at the next idle moment, never injected mid-turn.\n\nIf the scheduler slept past multiple ideal fire times (laptop closed, long-running turn, etc.), only **one** fire is delivered when it wakes up. The origin carries `coalescedCount` showing how many ideal fires were collapsed into this single delivery. You should treat `coalescedCount > 1` as \"I missed some checks; only the latest state matters\" rather than running the prompt that many times.\n\n## Cron-fire envelope\n\nWhen a cron task fires, the prompt you scheduled is re-injected wrapped in an XML envelope that exposes the fire context:\n\n```\n<cron-fire jobId=\"...\" cron=\"...\" recurring=\"true|false\" coalescedCount=\"N\" stale=\"true|false\">\n<prompt>\nyour original prompt text, verbatim\n</prompt>\n</cron-fire>\n```\n\nThe envelope is parseable. Use `coalescedCount > 1` to know multiple ideal fires were collapsed into a single delivery (treat as \"only the latest state matters\"), and `stale=\"true\"` as a cue that the task is past its 7-day threshold.\n\n## 7-day stale behavior\n\nRecurring tasks that have been alive for more than 7 days fire one\nfinal time with `stale: true` on the envelope, and the system then\nauto-deletes the task. The flag is the model's notice that this is\nthe last delivery. If the schedule is still wanted, call `CronCreate`\nagain with the same `cron` and `prompt` — that resets `createdAt` and\nstarts a fresh 7-day window. One-shot tasks are never marked stale.\n\n## Jitter behavior\n\nAnti-herd jitter is applied deterministically per task id:\n - Recurring: ideal fire time is shifted **forward** by an offset ≤ min(10% of the cron period, 15 minutes). A `*/5 * * * *` task can drift up to 30s; a `0 9 * * *` task can drift up to 15 minutes.\n - One-shot: only when the ideal fire lands on `:00` or `:30` of the hour, the fire is pulled **earlier** by ≤ 90 seconds. Other minutes pass through unchanged.\n\n## One-shot vs recurring — when to pick which\n\nUse `recurring: false` for \"remind me at X\" style requests, single deadlines, \"in N minutes do Y\", and any task that should not repeat. Use `recurring: true` for periodic polling (CI status, build watchers, scheduled reports), workday rituals, and anything the user explicitly described as recurring.\n\n## Session lifetime\n\nCron tasks live in the current kimi CLI session. When you exit, they\nare persisted under the session homedir; the next `kimi resume` of the\nsame session reloads them and the scheduler resumes from each task's\n`createdAt`. Fire times that fell during the offline window are\ncollapsed into a single delivery via `coalescedCount` (and recurring\ntasks past their 7-day window arrive with `stale: true` as their final\ndelivery).\n\nTasks do **not** carry over into a brand-new session — they are scoped\nto the resumed session id, not to the working directory.\n\n## Limits\n\nA session holds at most 50 live cron tasks; creating one beyond that is rejected. (The `prompt` body is also capped — see its parameter description.) Expressions that never fire within the next 5 years (e.g. `0 0 31 2 *`, an impossible date) are rejected at create time.\n\n## Returned fields\n\n`id` (8-hex), `cron` (the normalized expression), `humanSchedule` (English summary), `recurring`,\n`nextFireAt` (local ISO timestamp with numeric offset, or null). `id` is needed by `CronDelete`.\n\n## Tell the user how to cancel or modify\n\nAfter successfully creating a task, proactively tell the user how they can cancel or modify it later. Users have no direct `/cron` command or self-service UI to manage reminders themselves; they must ask the model to make changes (e.g. \"cancel my 9am reminder\" or \"change my daily check to 10am\"). Include the task `id` in your message so the user can reference it.\n";
|
|
144591
|
-
}));
|
|
144592
|
-
//#endregion
|
|
144593
|
-
//#region ../../packages/agent-core/src/tools/cron/cron-create.ts
|
|
144594
|
-
function formatOutput(o) {
|
|
144595
|
-
return [
|
|
144596
|
-
`id: ${o.id}`,
|
|
144597
|
-
`cron: ${o.cron}`,
|
|
144598
|
-
`humanSchedule: ${o.humanSchedule}`,
|
|
144599
|
-
`recurring: ${String(o.recurring)}`,
|
|
144600
|
-
`nextFireAt: ${o.nextFireAt === null ? "null" : formatLocalIsoWithOffset(o.nextFireAt)}`
|
|
144601
|
-
].join("\n");
|
|
144602
|
-
}
|
|
144603
|
-
var MAX_PROMPT_BYTES, ONE_SHOT_MAX_FUTURE_MS, CronCreateInputSchema, CronCreateTool;
|
|
144604
|
-
var init_cron_create = __esmMin((() => {
|
|
144605
|
-
init_zod$1();
|
|
144606
|
-
init_input_schema();
|
|
144607
|
-
init_rule_match();
|
|
144608
|
-
init_cron_expr();
|
|
144609
|
-
init_jitter();
|
|
144610
|
-
init_time_format();
|
|
144611
|
-
init_cron_create$1();
|
|
144612
|
-
MAX_PROMPT_BYTES = 8 * 1024;
|
|
144613
|
-
ONE_SHOT_MAX_FUTURE_MS = 350 * 24 * 60 * 60 * 1e3;
|
|
144614
|
-
CronCreateInputSchema = object({
|
|
144615
|
-
cron: string().describe("5-field cron expression in local time: \"M H DoM Mon DoW\" (e.g. \"*/5 * * * *\" = every 5 minutes; \"30 14 28 2 *\" = Feb 28 at 2:30pm local — a pinned date like this repeats yearly unless you also pass recurring: false)."),
|
|
144616
|
-
prompt: string().min(1).max(MAX_PROMPT_BYTES).describe("The prompt to enqueue at each fire time. Limited to 8 KiB (UTF-8)."),
|
|
144617
|
-
recurring: boolean$1().optional().default(true).describe("true (default) = fire on every cron match until deleted or auto-expired after 7 days. false = fire once at the next match, then auto-delete. Use false for \"remind me at X\" one-shot requests with pinned minute/hour/dom/month.")
|
|
144618
|
-
});
|
|
144619
|
-
CronCreateTool = class {
|
|
144620
|
-
manager;
|
|
144621
|
-
name = "CronCreate";
|
|
144622
|
-
description = cron_create_default;
|
|
144623
|
-
parameters = toInputJsonSchema(CronCreateInputSchema);
|
|
144624
|
-
constructor(manager) {
|
|
144625
|
-
this.manager = manager;
|
|
144626
|
-
}
|
|
144627
|
-
resolveExecution(args) {
|
|
144628
|
-
if (process.env["KIMI_DISABLE_CRON"] === "1") return {
|
|
144629
|
-
isError: true,
|
|
144630
|
-
output: "Cron scheduling is disabled (KIMI_DISABLE_CRON=1)."
|
|
144631
|
-
};
|
|
144632
|
-
const normalizedCron = args.cron.trim().split(/\s+/).join(" ");
|
|
144633
|
-
let parsed;
|
|
144634
|
-
try {
|
|
144635
|
-
parsed = parseCronExpression(normalizedCron);
|
|
144636
|
-
} catch (err) {
|
|
144637
|
-
return {
|
|
144638
|
-
isError: true,
|
|
144639
|
-
output: `Invalid cron expression: ${err instanceof Error ? err.message : String(err)}`
|
|
144640
|
-
};
|
|
144641
|
-
}
|
|
144642
|
-
const nowAtPrepare = this.manager.clocks.wallNow();
|
|
144643
|
-
if (!hasFireWithinYears(parsed, 5, nowAtPrepare)) return {
|
|
144644
|
-
isError: true,
|
|
144645
|
-
output: `Cron expression ${JSON.stringify(normalizedCron)} has no fire within 5 years; refusing to schedule.`
|
|
144646
|
-
};
|
|
144647
|
-
if (this.manager.store.list().length >= 50) return {
|
|
144648
|
-
isError: true,
|
|
144649
|
-
output: `Cron job cap reached (max ${String(50)} per session).`
|
|
144650
|
-
};
|
|
144651
|
-
const byteLen = Buffer.byteLength(args.prompt, "utf8");
|
|
144652
|
-
if (byteLen > MAX_PROMPT_BYTES) return {
|
|
144653
|
-
isError: true,
|
|
144654
|
-
output: `Prompt exceeds ${String(MAX_PROMPT_BYTES)} bytes (got ${String(byteLen)}).`
|
|
144655
|
-
};
|
|
144656
|
-
const recurring = args.recurring !== false;
|
|
144657
|
-
if (!recurring) {
|
|
144658
|
-
const firstFire = computeNextCronRun(parsed, nowAtPrepare);
|
|
144659
|
-
if (firstFire !== null && firstFire - nowAtPrepare > ONE_SHOT_MAX_FUTURE_MS) return {
|
|
144660
|
-
isError: true,
|
|
144661
|
-
output: `One-shot cron ${JSON.stringify(normalizedCron)} would not fire until ${formatLocalIsoWithOffset(firstFire)} (more than a year out). If you meant "today" or a near date, the pinned day/month has already passed this year — pick a future date or use wildcards.`
|
|
144662
|
-
};
|
|
144663
|
-
}
|
|
144664
|
-
return {
|
|
144665
|
-
description: recurring ? `Scheduling cron ${normalizedCron}` : `Scheduling one-shot ${normalizedCron}`,
|
|
144666
|
-
approvalRule: literalRulePattern(this.name, JSON.stringify({
|
|
144667
|
-
cron: normalizedCron,
|
|
144668
|
-
prompt: args.prompt,
|
|
144669
|
-
recurring
|
|
144670
|
-
})),
|
|
144671
|
-
execute: async () => {
|
|
144672
|
-
const nowMs = this.manager.clocks.wallNow();
|
|
144673
|
-
if (this.manager.store.list().length >= 50) return {
|
|
144674
|
-
isError: true,
|
|
144675
|
-
output: `Cron job cap reached (max ${String(50)} per session).`
|
|
144676
|
-
};
|
|
144677
|
-
const task = this.manager.addTask({
|
|
144678
|
-
cron: normalizedCron,
|
|
144679
|
-
prompt: args.prompt,
|
|
144680
|
-
recurring
|
|
144681
|
-
});
|
|
144682
|
-
const ideal = computeNextCronRun(parsed, nowMs);
|
|
144683
|
-
const nextFireAt = ideal === null ? null : recurring ? jitteredNextCronRunMs(task, parsed, ideal) : oneShotJitteredNextCronRunMs(task, ideal);
|
|
144684
|
-
const humanSchedule = cronToHuman(parsed);
|
|
144685
|
-
this.manager.emitScheduled(task);
|
|
144686
|
-
return {
|
|
144687
|
-
output: formatOutput({
|
|
144688
|
-
id: task.id,
|
|
144689
|
-
cron: normalizedCron,
|
|
144690
|
-
humanSchedule,
|
|
144691
|
-
recurring,
|
|
144692
|
-
nextFireAt
|
|
144693
|
-
}),
|
|
144694
|
-
isError: false,
|
|
144695
|
-
message: `Scheduled cron ${task.id}`
|
|
144696
|
-
};
|
|
144697
|
-
}
|
|
144698
|
-
};
|
|
144699
|
-
}
|
|
144700
|
-
};
|
|
144701
|
-
}));
|
|
144702
|
-
//#endregion
|
|
144703
|
-
//#region ../../packages/agent-core/src/tools/cron/cron-delete.md?raw
|
|
144704
|
-
var cron_delete_default;
|
|
144705
|
-
var init_cron_delete$1 = __esmMin((() => {
|
|
144706
|
-
cron_delete_default = "Cancel a scheduled cron job by id.\n\nUse this tool to remove a cron task previously scheduled with\n`CronCreate`. The `id` is the 8-hex value returned by `CronCreate`, or\nshown in the `id:` column of `CronList` — quote it verbatim, no\nprefix.\n\nBehaviour by task kind:\n\n- **Recurring task** (`recurring: true`): stops all future fires\n immediately. The scheduler picks up the deletion on its next tick.\n- **One-shot task** (`recurring: false`): cancels the pending fire if\n it has not happened yet. One-shots that have already fired\n auto-delete themselves, so calling `CronDelete` on a fired one-shot\n returns \"no cron job with id ...\".\n\nNot-found is reported as an error (not a silent no-op) so you can\ncorrect yourself — typically by calling `CronList` to see which ids\nare actually live, rather than re-trying with the same stale id.\n\nRefresh pattern (use when you want a stale recurring schedule to\ncontinue):\n\nStale recurring tasks are auto-deleted by the system after their final\nfire — there is nothing for `CronDelete` to remove at that point. To\nkeep the schedule running, just call `CronCreate` with the same `cron`\nand `prompt`. Use `CronList`'s `prompt` field to recall the original\ntext after a context compaction.\n\n`CronDelete` remains the right call when you want to cancel a task\nthat is still live (recurring not yet stale, or a one-shot still\npending).\n\nGuidelines:\n\n- Users have no direct `/cron` command or self-service UI to delete\n tasks themselves; they must ask the model to cancel a reminder.\n When deleting on behalf of a user, confirm the action and report\n the result plainly.\n- Cron deletion is irreversible — there is no undo. If you delete the\n wrong task, you must re-create it with `CronCreate`.\n- If the model is unsure which id is current (e.g. after a context\n compaction), call `CronList` first rather than guessing.\n";
|
|
144707
|
-
}));
|
|
144708
|
-
//#endregion
|
|
144709
|
-
//#region ../../packages/agent-core/src/tools/cron/cron-delete.ts
|
|
144710
|
-
var ID_PATTERN, CronDeleteInputSchema, CronDeleteTool;
|
|
144711
|
-
var init_cron_delete = __esmMin((() => {
|
|
144712
|
-
init_zod$1();
|
|
144713
|
-
init_input_schema();
|
|
144714
|
-
init_cron_delete$1();
|
|
144715
|
-
ID_PATTERN = /^[0-9a-f]{8}$/;
|
|
144716
|
-
CronDeleteInputSchema = object({ id: string().describe("The 8-hex cron job id returned by CronCreate / CronList.") });
|
|
144717
|
-
CronDeleteTool = class {
|
|
144718
|
-
manager;
|
|
144719
|
-
name = "CronDelete";
|
|
144720
|
-
description = cron_delete_default;
|
|
144721
|
-
parameters = toInputJsonSchema(CronDeleteInputSchema);
|
|
144722
|
-
constructor(manager) {
|
|
144723
|
-
this.manager = manager;
|
|
144724
|
-
}
|
|
144725
|
-
resolveExecution(args) {
|
|
144726
|
-
if (!ID_PATTERN.test(args.id)) return {
|
|
144727
|
-
isError: true,
|
|
144728
|
-
output: `Invalid cron job id ${JSON.stringify(args.id)} — must be 8 lowercase hex characters.`
|
|
144729
|
-
};
|
|
144730
|
-
return {
|
|
144731
|
-
description: `Deleting cron ${args.id}`,
|
|
144732
|
-
approvalRule: this.name,
|
|
144733
|
-
execute: async () => {
|
|
144734
|
-
if (this.manager.removeTasks([args.id]).length === 0) return {
|
|
144735
|
-
isError: true,
|
|
144736
|
-
output: `No cron job with id ${args.id}.`
|
|
144737
|
-
};
|
|
144738
|
-
this.manager.emitDeleted(args.id);
|
|
144739
|
-
return {
|
|
144740
|
-
output: `Deleted cron job ${args.id}.`,
|
|
144741
|
-
isError: false
|
|
144742
|
-
};
|
|
144743
|
-
}
|
|
144744
|
-
};
|
|
144745
|
-
}
|
|
144746
|
-
};
|
|
144747
|
-
}));
|
|
144748
|
-
//#endregion
|
|
144749
|
-
//#region ../../packages/agent-core/src/tools/cron/cron-list.md?raw
|
|
144750
|
-
var cron_list_default;
|
|
144751
|
-
var init_cron_list$1 = __esmMin((() => {
|
|
144752
|
-
cron_list_default = "List all cron jobs currently scheduled in this session.\n\nUse this tool to see every pending cron task — both recurring jobs and\none-shot reminders — that you (or the user) have scheduled with\n`CronCreate`. The output is the entry point for inspecting scheduled\nwork: it returns a stable id, the original cron expression, a human\nrendering, the next post-jitter fire time, the recurring flag, the\ntask's age in days, and a stale indicator.\n\nEach record carries:\n\n- `id` — the 8-hex task id. Pass this to `CronDelete` to remove the\n task, or quote it in user-facing messages when asking for\n confirmation.\n- `cron` — the verbatim 5-field cron expression as scheduled.\n- `humanSchedule` — plain-English rendering (e.g. `every 5 minutes`).\n- `prompt` — the scheduled prompt text, JSON-encoded so embedded\n newlines stay on one line. Truncated to 200 UTF-8 bytes with\n `…(truncated)` if longer. Use this to recall what a task is for\n after a context compaction, and as the source for the\n `CronCreate` refresh ritual.\n- `nextFireAt` — local ISO timestamp with an explicit numeric offset\n for the next fire **after jitter has been applied**. The actual fire\n may land slightly before or after a round `:00` / `:30` minute mark\n due to herd-avoidance jitter; this is the value the scheduler will\n compare against, so it reflects what will really happen. `null` if\n the expression has no fire in the next 5 years (should not happen\n for tasks created through `CronCreate`, which validates).\n- `recurring` — `true` for cadenced jobs, `false` for one-shots.\n- `ageDays` — `(now - createdAt) / day`, two decimal places. Useful\n when deciding whether a long-running cron is still relevant.\n- `stale` — `true` when a recurring task is older than 7 days. The\n system **auto-deletes the task after this fire** to bound session\n lifetime; the `stale: true` flag is the model's notice that this is\n the final delivery. To resume the same schedule, call `CronCreate`\n again with the original `cron` and `prompt` (the `prompt` row above\n carries it for exactly this purpose). One-shots are never marked\n stale — they fire at most once by construction.\n\nGuidelines:\n\n- This tool is read-only and never mutates state, so it is always\n safe to call (including in plan mode).\n- Users cannot directly manage cron tasks themselves; if they want to\n cancel or modify a schedule, route the request through the model\n (i.e. call `CronDelete` or `CronCreate` on their behalf).\n- The empty case returns `cron_jobs: 0\\nNo cron jobs scheduled.`. Cron\n tasks survive a `kimi resume` of the same session but do not bleed\n into new sessions.\n- After a context compaction, or whenever you are unsure which cron\n jobs are live, call this tool to re-enumerate them rather than\n guessing ids from earlier in the conversation.\n- Records are separated by a line containing just `---`, in the\n insertion order they were scheduled.\n";
|
|
144753
|
-
}));
|
|
144754
|
-
//#endregion
|
|
144755
|
-
//#region ../../packages/agent-core/src/tools/cron/cron-list.ts
|
|
144756
|
-
function previewPrompt(prompt) {
|
|
144757
|
-
const buf = Buffer.from(prompt, "utf8");
|
|
144758
|
-
if (buf.byteLength <= PROMPT_PREVIEW_BYTES) return prompt;
|
|
144759
|
-
let end = PROMPT_PREVIEW_BYTES;
|
|
144760
|
-
while (end > 0 && (buf[end] & 192) === 128) end--;
|
|
144761
|
-
return `${buf.subarray(0, end).toString("utf8")}…(truncated)`;
|
|
144762
|
-
}
|
|
144763
|
-
var CronListInputSchema, MS_PER_DAY, PROMPT_PREVIEW_BYTES, CronListTool;
|
|
144764
|
-
var init_cron_list = __esmMin((() => {
|
|
144765
|
-
init_zod$1();
|
|
144766
|
-
init_input_schema();
|
|
144767
|
-
init_cron_expr();
|
|
144768
|
-
init_time_format();
|
|
144769
|
-
init_cron_list$1();
|
|
144770
|
-
CronListInputSchema = object({}).strict();
|
|
144771
|
-
MS_PER_DAY = 1440 * 60 * 1e3;
|
|
144772
|
-
PROMPT_PREVIEW_BYTES = 200;
|
|
144773
|
-
CronListTool = class {
|
|
144774
|
-
manager;
|
|
144775
|
-
name = "CronList";
|
|
144776
|
-
description = cron_list_default;
|
|
144777
|
-
parameters = toInputJsonSchema(CronListInputSchema);
|
|
144778
|
-
constructor(manager) {
|
|
144779
|
-
this.manager = manager;
|
|
144780
|
-
}
|
|
144781
|
-
resolveExecution(_args) {
|
|
144782
|
-
return {
|
|
144783
|
-
description: "Listing scheduled cron jobs",
|
|
144784
|
-
approvalRule: this.name,
|
|
144785
|
-
execute: async () => {
|
|
144786
|
-
const tasks = this.manager.store.list();
|
|
144787
|
-
const nowMs = this.manager.clocks.wallNow();
|
|
144788
|
-
const records = tasks.map((t) => this.renderRecord(t, nowMs));
|
|
144789
|
-
const header = `cron_jobs: ${String(tasks.length)}`;
|
|
144790
|
-
if (records.length === 0) return {
|
|
144791
|
-
output: `${header}\nNo cron jobs scheduled.`,
|
|
144792
|
-
isError: false
|
|
144793
|
-
};
|
|
144794
|
-
return {
|
|
144795
|
-
output: `${header}\n${records.join("\n---\n")}`,
|
|
144796
|
-
isError: false
|
|
144797
|
-
};
|
|
144798
|
-
}
|
|
144799
|
-
};
|
|
144800
|
-
}
|
|
144801
|
-
renderRecord(task, nowMs) {
|
|
144802
|
-
const recurring = task.recurring !== false;
|
|
144803
|
-
const ageMs = nowMs - task.createdAt;
|
|
144804
|
-
const ageDays = Number.isFinite(ageMs) ? ageMs / MS_PER_DAY : 0;
|
|
144805
|
-
const stale = this.manager.isStale(task);
|
|
144806
|
-
let humanSchedule = task.cron;
|
|
144807
|
-
let nextFireAtIso = "null";
|
|
144808
|
-
try {
|
|
144809
|
-
humanSchedule = cronToHuman(parseCronExpression(task.cron));
|
|
144810
|
-
const nextFireMs = this.manager.getNextFireForTask(task.id);
|
|
144811
|
-
if (nextFireMs !== null) nextFireAtIso = formatLocalIsoWithOffset(nextFireMs);
|
|
144812
|
-
} catch {}
|
|
144813
|
-
return [
|
|
144814
|
-
`id: ${task.id}`,
|
|
144815
|
-
`cron: ${task.cron}`,
|
|
144816
|
-
`humanSchedule: ${humanSchedule}`,
|
|
144817
|
-
`prompt: ${JSON.stringify(previewPrompt(task.prompt))}`,
|
|
144818
|
-
`nextFireAt: ${nextFireAtIso}`,
|
|
144819
|
-
`recurring: ${String(recurring)}`,
|
|
144820
|
-
`ageDays: ${ageDays.toFixed(2)}`,
|
|
144821
|
-
`stale: ${String(stale)}`
|
|
144822
|
-
].join("\n");
|
|
144823
|
-
}
|
|
144824
|
-
};
|
|
144825
|
-
}));
|
|
144826
|
-
//#endregion
|
|
144827
144386
|
//#region ../../packages/agent-core/src/agent/permission/policies/deny-all.ts
|
|
144828
144387
|
var DenyAllPermissionPolicy;
|
|
144829
144388
|
var init_deny_all = __esmMin((() => {
|
|
@@ -145483,6 +145042,38 @@ var init_summary_continuation = __esmMin((() => {
|
|
|
145483
145042
|
}));
|
|
145484
145043
|
//#endregion
|
|
145485
145044
|
//#region ../../packages/agent-core/src/session/subagent-host.ts
|
|
145045
|
+
/**
|
|
145046
|
+
* Resolve the effective subagent per-task timeout. Precedence:
|
|
145047
|
+
* `KIMI_SUBAGENT_TIMEOUT_MS` (positive integer ms) → `configMs` →
|
|
145048
|
+
* `DEFAULT_SUBAGENT_TIMEOUT_MS` (30 min). Set a large value to effectively
|
|
145049
|
+
* disable the cap. The value feeds the background-task manager's per-task
|
|
145050
|
+
* timeout, so it governs foreground and background subagents (and AgentSwarm).
|
|
145051
|
+
*/
|
|
145052
|
+
function resolveSubagentTimeoutMs(configMs) {
|
|
145053
|
+
const raw = process.env[SUBAGENT_TIMEOUT_ENV];
|
|
145054
|
+
if (raw !== void 0 && raw.trim().length > 0) {
|
|
145055
|
+
const parsed = Number(raw);
|
|
145056
|
+
if (Number.isInteger(parsed) && parsed >= 1) return parsed;
|
|
145057
|
+
}
|
|
145058
|
+
if (configMs !== void 0 && Number.isInteger(configMs) && configMs >= 1) return configMs;
|
|
145059
|
+
return DEFAULT_SUBAGENT_TIMEOUT_MS;
|
|
145060
|
+
}
|
|
145061
|
+
/** Human-readable duration for the subagent timeout message. */
|
|
145062
|
+
function formatSubagentTimeoutDescription(ms) {
|
|
145063
|
+
if (ms % (3600 * 1e3) === 0) {
|
|
145064
|
+
const h = ms / (3600 * 1e3);
|
|
145065
|
+
return `${h} hour${h === 1 ? "" : "s"}`;
|
|
145066
|
+
}
|
|
145067
|
+
if (ms % (60 * 1e3) === 0) {
|
|
145068
|
+
const m = ms / (60 * 1e3);
|
|
145069
|
+
return `${m} minute${m === 1 ? "" : "s"}`;
|
|
145070
|
+
}
|
|
145071
|
+
if (ms % 1e3 === 0) {
|
|
145072
|
+
const s = ms / 1e3;
|
|
145073
|
+
return `${s} second${s === 1 ? "" : "s"}`;
|
|
145074
|
+
}
|
|
145075
|
+
return `${ms} ms`;
|
|
145076
|
+
}
|
|
145486
145077
|
async function runChildTurnToCompletion(child, signal) {
|
|
145487
145078
|
const completion = await child.turn.waitForCurrentTurn(signal);
|
|
145488
145079
|
const turnEnded = completion.event;
|
|
@@ -145510,7 +145101,7 @@ function shouldSuppressQueuedAttemptFailureEvent(options, error) {
|
|
|
145510
145101
|
if (isProviderRateLimitError(error)) return true;
|
|
145511
145102
|
return isAbortError$3(error) || options.signal.aborted;
|
|
145512
145103
|
}
|
|
145513
|
-
var DEFAULT_SUBAGENT_TIMEOUT_MS,
|
|
145104
|
+
var DEFAULT_SUBAGENT_TIMEOUT_MS, SUBAGENT_TIMEOUT_ENV, SUMMARY_MIN_LENGTH, SUMMARY_CONTINUATION_ATTEMPTS, HOOK_TEXT_PREVIEW_LENGTH, SUBAGENT_MAX_TOKENS_ERROR, TOOL_CALL_DISABLED_MESSAGE, SUBAGENT_PROMPT_ORIGIN, SIDE_QUESTION_SYSTEM_REMINDER, SessionSubagentHost;
|
|
145514
145105
|
var init_subagent_host = __esmMin((() => {
|
|
145515
145106
|
init_src$4();
|
|
145516
145107
|
init_errors$8();
|
|
@@ -145522,8 +145113,8 @@ var init_subagent_host = __esmMin((() => {
|
|
|
145522
145113
|
init_git_context();
|
|
145523
145114
|
init_subagent_batch();
|
|
145524
145115
|
init_summary_continuation();
|
|
145525
|
-
DEFAULT_SUBAGENT_TIMEOUT_MS =
|
|
145526
|
-
|
|
145116
|
+
DEFAULT_SUBAGENT_TIMEOUT_MS = 7200 * 1e3;
|
|
145117
|
+
SUBAGENT_TIMEOUT_ENV = "KIMI_SUBAGENT_TIMEOUT_MS";
|
|
145527
145118
|
SUMMARY_MIN_LENGTH = 200;
|
|
145528
145119
|
SUMMARY_CONTINUATION_ATTEMPTS = 1;
|
|
145529
145120
|
HOOK_TEXT_PREVIEW_LENGTH = 500;
|
|
@@ -145827,6 +145418,479 @@ IMPORTANT:
|
|
|
145827
145418
|
};
|
|
145828
145419
|
}));
|
|
145829
145420
|
//#endregion
|
|
145421
|
+
//#region ../../packages/agent-core/src/agent/llm-request-logger.ts
|
|
145422
|
+
function splitGenerateOptions(options) {
|
|
145423
|
+
if (options === void 0) return {
|
|
145424
|
+
requestLogFields: void 0,
|
|
145425
|
+
generateOptions: void 0
|
|
145426
|
+
};
|
|
145427
|
+
const { requestLogFields, ...generateOptions } = options;
|
|
145428
|
+
return {
|
|
145429
|
+
requestLogFields,
|
|
145430
|
+
generateOptions
|
|
145431
|
+
};
|
|
145432
|
+
}
|
|
145433
|
+
function toolSignature(tools) {
|
|
145434
|
+
return tools.map(({ name, description, parameters }) => ({
|
|
145435
|
+
name,
|
|
145436
|
+
description,
|
|
145437
|
+
parameters
|
|
145438
|
+
}));
|
|
145439
|
+
}
|
|
145440
|
+
function fingerprint(content) {
|
|
145441
|
+
return createHash("sha256").update(content).digest("hex");
|
|
145442
|
+
}
|
|
145443
|
+
var LlmRequestLogger;
|
|
145444
|
+
var init_llm_request_logger = __esmMin((() => {
|
|
145445
|
+
LlmRequestLogger = class {
|
|
145446
|
+
log;
|
|
145447
|
+
lastConfigLogSignature;
|
|
145448
|
+
constructor(log) {
|
|
145449
|
+
this.log = log;
|
|
145450
|
+
}
|
|
145451
|
+
logRequest(input) {
|
|
145452
|
+
const { provider, modelAlias, systemPrompt, tools, messages, fields } = input;
|
|
145453
|
+
const requestLogFields = fields ?? {};
|
|
145454
|
+
const wireTools = tools.filter((tool) => tool.deferred !== true);
|
|
145455
|
+
const config = {
|
|
145456
|
+
provider: provider.name,
|
|
145457
|
+
model: provider.modelName,
|
|
145458
|
+
modelAlias,
|
|
145459
|
+
thinkingEffort: provider.thinkingEffort ?? void 0,
|
|
145460
|
+
systemPromptChars: systemPrompt.length,
|
|
145461
|
+
toolCount: wireTools.length
|
|
145462
|
+
};
|
|
145463
|
+
const signature = JSON.stringify({
|
|
145464
|
+
...config,
|
|
145465
|
+
systemPromptHash: fingerprint(systemPrompt),
|
|
145466
|
+
toolsHash: fingerprint(JSON.stringify(toolSignature(wireTools)))
|
|
145467
|
+
});
|
|
145468
|
+
if (signature !== this.lastConfigLogSignature) {
|
|
145469
|
+
this.lastConfigLogSignature = signature;
|
|
145470
|
+
this.log.info("llm config", {
|
|
145471
|
+
...requestLogFields,
|
|
145472
|
+
...config
|
|
145473
|
+
});
|
|
145474
|
+
}
|
|
145475
|
+
const partialMessageCount = messages.filter((message) => message.partial === true).length;
|
|
145476
|
+
const requestFields = { ...requestLogFields };
|
|
145477
|
+
if (partialMessageCount > 0) requestFields.partialMessageCount = partialMessageCount;
|
|
145478
|
+
this.log.info("llm request", requestFields);
|
|
145479
|
+
}
|
|
145480
|
+
};
|
|
145481
|
+
}));
|
|
145482
|
+
//#endregion
|
|
145483
|
+
//#region ../../packages/agent-core/src/tools/background/task-output.md?raw
|
|
145484
|
+
var task_output_default;
|
|
145485
|
+
var init_task_output$1 = __esmMin((() => {
|
|
145486
|
+
task_output_default = "Retrieve output from a running or completed background task.\n\nUse this after `Bash(run_in_background=true)` or `Agent(run_in_background=true)` when you need to inspect progress or explicitly wait for completion.\n\nGuidelines:\n- Prefer relying on automatic completion notifications. Use this tool only when you need task output before the automatic notification arrives.\n- Do not use TaskOutput to wait for a result you need before continuing — if your next step depends on the task's result, run that task in the foreground instead. TaskOutput is for a deliberate progress check you will act on without blocking, not a way to sit and wait for a background task you just launched.\n- By default this tool is non-blocking and returns a current status/output snapshot.\n- Use block=true only when you intentionally want to wait for completion or timeout.\n- This tool returns structured task metadata, a fixed-size output preview, and an output_path for the full log.\n- For a terminal task, the metadata also explains why it ended. A shell command that runs to completion reports `status: completed` on a zero exit, or `status: failed` with its non-zero `exit_code` — judge that failure from the `exit_code`, because a plain command failure carries no `stop_reason` and no `terminal_reason`. `terminal_reason` is a categorical label emitted only when the end is not an ordinary exit: `timed_out` when the deadline aborted it, `stopped` when it was explicitly stopped, or `failed` when it errored without producing an exit code; the `stopped` and `failed` cases also carry a human-readable `stop_reason`. A task that finished on its own with a clean exit carries neither `stop_reason` nor `terminal_reason`.\n- The full, never-truncated log is always available at output_path; use the `Read` tool with that path to page through it, whether or not the preview was truncated.\n- This tool works with the generic background task system and should remain the primary read path for future task types, not just bash.\n";
|
|
145487
|
+
}));
|
|
145488
|
+
//#endregion
|
|
145489
|
+
//#region ../../packages/agent-core/src/tools/background/task-output.ts
|
|
145490
|
+
function retrievalStatus(status, block) {
|
|
145491
|
+
if (isBackgroundTaskTerminal(status)) return "success";
|
|
145492
|
+
return block ? "timeout" : "not_ready";
|
|
145493
|
+
}
|
|
145494
|
+
function terminalReason(info) {
|
|
145495
|
+
if (info.status === "timed_out") return "timed_out";
|
|
145496
|
+
if (info.status === "killed" && info.stopReason !== void 0) return "stopped";
|
|
145497
|
+
if (info.status === "failed" && info.stopReason !== void 0) return "failed";
|
|
145498
|
+
}
|
|
145499
|
+
function fullOutputHint(output) {
|
|
145500
|
+
if (!output.fullOutputAvailable || output.outputPath === void 0) return void 0;
|
|
145501
|
+
if (output.truncated) return `Only the last ${String(OUTPUT_PREVIEW_BYTES)} bytes are shown above. Use the Read tool with the output_path to page through the full log (parameters: path, line_offset, n_lines; read about ${String(PAGING_HINT_LINES)} lines per page).`;
|
|
145502
|
+
return `The preview above is the complete output. Use the Read tool with the output_path if you need to re-read the full log later (parameters: path, line_offset, n_lines; read about ${String(PAGING_HINT_LINES)} lines per page).`;
|
|
145503
|
+
}
|
|
145504
|
+
var OUTPUT_PREVIEW_BYTES, PAGING_HINT_LINES, TaskOutputInputSchema, TaskOutputTool;
|
|
145505
|
+
var init_task_output = __esmMin((() => {
|
|
145506
|
+
init_zod$1();
|
|
145507
|
+
init_background();
|
|
145508
|
+
init_input_schema();
|
|
145509
|
+
init_rule_match();
|
|
145510
|
+
init_format();
|
|
145511
|
+
init_task_output$1();
|
|
145512
|
+
OUTPUT_PREVIEW_BYTES = 32 * 1024;
|
|
145513
|
+
PAGING_HINT_LINES = 300;
|
|
145514
|
+
TaskOutputInputSchema = object({
|
|
145515
|
+
task_id: string().describe("The background task ID to inspect."),
|
|
145516
|
+
block: boolean$1().default(false).describe("Whether to wait for the task to finish before returning.").optional(),
|
|
145517
|
+
timeout: number$1().int().min(0).max(3600).default(30).describe("Maximum number of seconds to wait when block=true.").optional()
|
|
145518
|
+
});
|
|
145519
|
+
TaskOutputTool = class {
|
|
145520
|
+
manager;
|
|
145521
|
+
name = "TaskOutput";
|
|
145522
|
+
description = task_output_default;
|
|
145523
|
+
parameters = toInputJsonSchema(TaskOutputInputSchema);
|
|
145524
|
+
constructor(manager) {
|
|
145525
|
+
this.manager = manager;
|
|
145526
|
+
}
|
|
145527
|
+
resolveExecution(args) {
|
|
145528
|
+
return {
|
|
145529
|
+
description: `Reading output of task ${args.task_id}`,
|
|
145530
|
+
approvalRule: this.name,
|
|
145531
|
+
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.task_id),
|
|
145532
|
+
execute: () => this.execute(args)
|
|
145533
|
+
};
|
|
145534
|
+
}
|
|
145535
|
+
async execute(args) {
|
|
145536
|
+
const info = this.manager.getTask(args.task_id);
|
|
145537
|
+
if (!info) return {
|
|
145538
|
+
isError: true,
|
|
145539
|
+
output: `Task not found: ${args.task_id}`
|
|
145540
|
+
};
|
|
145541
|
+
if (args.block && !isBackgroundTaskTerminal(info.status)) await this.manager.wait(args.task_id, (args.timeout ?? 30) * 1e3);
|
|
145542
|
+
const current = this.manager.getTask(args.task_id);
|
|
145543
|
+
if (!current) return {
|
|
145544
|
+
isError: true,
|
|
145545
|
+
output: `Task not found: ${args.task_id}`
|
|
145546
|
+
};
|
|
145547
|
+
const output = await this.manager.getOutputSnapshot(args.task_id, OUTPUT_PREVIEW_BYTES);
|
|
145548
|
+
const lines = [formatPlainObject({
|
|
145549
|
+
retrievalStatus: retrievalStatus(current.status, args.block),
|
|
145550
|
+
...current,
|
|
145551
|
+
outputPath: output.outputPath,
|
|
145552
|
+
terminalReason: terminalReason(current),
|
|
145553
|
+
outputSizeBytes: output.outputSizeBytes,
|
|
145554
|
+
outputPreviewBytes: output.previewBytes,
|
|
145555
|
+
outputTruncated: output.truncated,
|
|
145556
|
+
fullOutputAvailable: output.fullOutputAvailable,
|
|
145557
|
+
fullOutputTool: output.fullOutputAvailable && output.outputPath !== void 0 ? "Read" : void 0,
|
|
145558
|
+
fullOutputHint: fullOutputHint(output)
|
|
145559
|
+
}), ""];
|
|
145560
|
+
if (output.truncated) lines.push(output.fullOutputAvailable && output.outputPath !== void 0 ? `[Truncated. Full output: ${output.outputPath}]` : "[Truncated. No persisted full log is available for this task.]");
|
|
145561
|
+
lines.push("[output]", output.preview || "[no output available]");
|
|
145562
|
+
return {
|
|
145563
|
+
output: lines.join("\n"),
|
|
145564
|
+
isError: false,
|
|
145565
|
+
message: "Task snapshot retrieved."
|
|
145566
|
+
};
|
|
145567
|
+
}
|
|
145568
|
+
};
|
|
145569
|
+
}));
|
|
145570
|
+
//#endregion
|
|
145571
|
+
//#region ../../packages/agent-core/src/tools/background/task-stop.md?raw
|
|
145572
|
+
var task_stop_default;
|
|
145573
|
+
var init_task_stop$1 = __esmMin((() => {
|
|
145574
|
+
task_stop_default = "Stop a running background task.\n\nOnly use this when a task must genuinely be cancelled — for a task that is\nfinishing normally, wait for its completion notification or inspect it with\n`TaskOutput` instead of stopping it.\n\nGuidelines:\n- This is a general-purpose stop capability for any background task. It is not\n a bash-specific kill.\n- Stopping a task is destructive: it may leave partial side effects behind.\n Use it with care.\n- If the task has already finished, this tool simply returns its current\n status.\n";
|
|
145575
|
+
}));
|
|
145576
|
+
//#endregion
|
|
145577
|
+
//#region ../../packages/agent-core/src/tools/background/task-stop.ts
|
|
145578
|
+
function terminalStopReason(reason) {
|
|
145579
|
+
const trimmed = reason?.trim();
|
|
145580
|
+
return trimmed === void 0 || trimmed.length === 0 ? "Task already in terminal state" : trimmed;
|
|
145581
|
+
}
|
|
145582
|
+
var TaskStopInputSchema, TaskStopTool;
|
|
145583
|
+
var init_task_stop = __esmMin((() => {
|
|
145584
|
+
init_zod$1();
|
|
145585
|
+
init_background();
|
|
145586
|
+
init_input_schema();
|
|
145587
|
+
init_rule_match();
|
|
145588
|
+
init_task_stop$1();
|
|
145589
|
+
TaskStopInputSchema = object({
|
|
145590
|
+
task_id: string().describe("The background task ID to stop."),
|
|
145591
|
+
reason: string().default("Stopped by TaskStop").describe("Short reason recorded when the task is stopped.").optional()
|
|
145592
|
+
});
|
|
145593
|
+
TaskStopTool = class {
|
|
145594
|
+
manager;
|
|
145595
|
+
name = "TaskStop";
|
|
145596
|
+
description = task_stop_default;
|
|
145597
|
+
parameters = toInputJsonSchema(TaskStopInputSchema);
|
|
145598
|
+
constructor(manager) {
|
|
145599
|
+
this.manager = manager;
|
|
145600
|
+
}
|
|
145601
|
+
resolveExecution(args) {
|
|
145602
|
+
return {
|
|
145603
|
+
description: `Stopping task ${args.task_id}`,
|
|
145604
|
+
approvalRule: this.name,
|
|
145605
|
+
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.task_id),
|
|
145606
|
+
execute: async () => {
|
|
145607
|
+
const info = this.manager.getTask(args.task_id);
|
|
145608
|
+
if (!info) return {
|
|
145609
|
+
isError: true,
|
|
145610
|
+
output: `Task not found: ${args.task_id}`
|
|
145611
|
+
};
|
|
145612
|
+
const trimmedReason = args.reason?.trim();
|
|
145613
|
+
const reason = trimmedReason === void 0 || trimmedReason.length === 0 ? "Stopped by TaskStop" : trimmedReason;
|
|
145614
|
+
if (isBackgroundTaskTerminal(info.status)) return {
|
|
145615
|
+
output: `task_id: ${info.taskId}\nstatus: ${info.status}\nreason: ${terminalStopReason(info.stopReason)}`,
|
|
145616
|
+
isError: false
|
|
145617
|
+
};
|
|
145618
|
+
await this.manager.suppressTerminalNotification(args.task_id);
|
|
145619
|
+
const result = await this.manager.stop(args.task_id, reason);
|
|
145620
|
+
if (!result) return {
|
|
145621
|
+
isError: true,
|
|
145622
|
+
output: `Failed to stop task: ${args.task_id}`
|
|
145623
|
+
};
|
|
145624
|
+
return {
|
|
145625
|
+
output: `task_id: ${result.taskId}\nstatus: ${result.status}\nreason: ${result.stopReason ?? reason}`,
|
|
145626
|
+
isError: false
|
|
145627
|
+
};
|
|
145628
|
+
}
|
|
145629
|
+
};
|
|
145630
|
+
}
|
|
145631
|
+
};
|
|
145632
|
+
}));
|
|
145633
|
+
//#endregion
|
|
145634
|
+
//#region ../../packages/agent-core/src/tools/cron/time-format.ts
|
|
145635
|
+
/**
|
|
145636
|
+
* Render cron-facing timestamps in local wall time with an explicit
|
|
145637
|
+
* numeric offset. Cron expressions are evaluated in local time, so the
|
|
145638
|
+
* tool output should preserve that mental model while remaining
|
|
145639
|
+
* unambiguous and parseable as ISO 8601.
|
|
145640
|
+
*/
|
|
145641
|
+
function formatLocalIsoWithOffset(ms) {
|
|
145642
|
+
const date = new Date(ms);
|
|
145643
|
+
const offsetMin = -date.getTimezoneOffset();
|
|
145644
|
+
const sign = offsetMin >= 0 ? "+" : "-";
|
|
145645
|
+
const absOffset = Math.abs(offsetMin);
|
|
145646
|
+
const offset = `${sign}${pad(Math.floor(absOffset / 60))}:${pad(absOffset % 60)}`;
|
|
145647
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}.${String(date.getMilliseconds()).padStart(3, "0")}${offset}`;
|
|
145648
|
+
}
|
|
145649
|
+
function pad(n) {
|
|
145650
|
+
return String(n).padStart(2, "0");
|
|
145651
|
+
}
|
|
145652
|
+
var init_time_format = __esmMin((() => {}));
|
|
145653
|
+
//#endregion
|
|
145654
|
+
//#region ../../packages/agent-core/src/tools/cron/cron-create.md?raw
|
|
145655
|
+
var cron_create_default;
|
|
145656
|
+
var init_cron_create$1 = __esmMin((() => {
|
|
145657
|
+
cron_create_default = "Schedule a prompt to be enqueued at a future time. Use for both recurring schedules and one-shot reminders.\n\nUses standard 5-field cron in the user's local timezone: minute hour day-of-month month day-of-week. `0 9 * * *` means 9am local — no timezone conversion needed.\n\n## One-shot tasks (recurring: false)\n\nFor \"remind me at X\" or \"at <time>, do Y\" requests — fire once then auto-delete.\nPin minute/hour/day-of-month/month to specific values:\n \"remind me at 2:30pm today to check the deploy\" → cron: \"30 14 <today_dom> <today_month> *\", recurring: false\n \"tomorrow morning, run the smoke test\" → cron: \"57 8 <tomorrow_dom> <tomorrow_month> *\", recurring: false\n\nOne-shots are best for near-term reminders. A task only fires while its session is still alive (see Session lifetime below), so favor near times — within hours or a few days — rather than scheduling weeks or months ahead.\n\n## Recurring jobs (recurring: true, the default)\n\nFor \"every N minutes\" / \"every hour\" / \"weekdays at 9am\" requests:\n \"*/5 * * * *\" (every 5 min), \"0 * * * *\" (hourly), \"0 9 * * 1-5\" (weekdays at 9am local)\n\n## Avoid the :00 and :30 minute marks when the task allows it\n\nEvery user who asks for \"9am\" gets `0 9`, and every user who asks for \"hourly\" gets `0 *` — which means requests from across the planet land on the API at the same instant. When the user's request is approximate, pick a minute that is NOT 0 or 30:\n \"every morning around 9\" → \"57 8 * * *\" or \"3 9 * * *\" (not \"0 9 * * *\")\n \"hourly\" → \"7 * * * *\" (not \"0 * * * *\")\n \"in an hour or so, remind me to...\" → pick whatever minute you land on, don't round\n\nOnly use minute 0 or 30 when the user names that exact time and clearly means it (\"at 9:00 sharp\", \"at half past\", coordinating with a meeting). When in doubt, nudge a few minutes early or late — the user will not notice, and the fleet will.\n\n## Coalesce semantics\n\nFires are delivered only while the session is idle: a fire that comes due during an active turn is held and delivered at the next idle moment, never injected mid-turn.\n\nIf the scheduler slept past multiple ideal fire times (laptop closed, long-running turn, etc.), only **one** fire is delivered when it wakes up. The origin carries `coalescedCount` showing how many ideal fires were collapsed into this single delivery. You should treat `coalescedCount > 1` as \"I missed some checks; only the latest state matters\" rather than running the prompt that many times.\n\n## Cron-fire envelope\n\nWhen a cron task fires, the prompt you scheduled is re-injected wrapped in an XML envelope that exposes the fire context:\n\n```\n<cron-fire jobId=\"...\" cron=\"...\" recurring=\"true|false\" coalescedCount=\"N\" stale=\"true|false\">\n<prompt>\nyour original prompt text, verbatim\n</prompt>\n</cron-fire>\n```\n\nThe envelope is parseable. Use `coalescedCount > 1` to know multiple ideal fires were collapsed into a single delivery (treat as \"only the latest state matters\"), and `stale=\"true\"` as a cue that the task is past its 7-day threshold.\n\n## 7-day stale behavior\n\nRecurring tasks that have been alive for more than 7 days fire one\nfinal time with `stale: true` on the envelope, and the system then\nauto-deletes the task. The flag is the model's notice that this is\nthe last delivery. If the schedule is still wanted, call `CronCreate`\nagain with the same `cron` and `prompt` — that resets `createdAt` and\nstarts a fresh 7-day window. One-shot tasks are never marked stale.\n\n## Jitter behavior\n\nAnti-herd jitter is applied deterministically per task id:\n - Recurring: ideal fire time is shifted **forward** by an offset ≤ min(10% of the cron period, 15 minutes). A `*/5 * * * *` task can drift up to 30s; a `0 9 * * *` task can drift up to 15 minutes.\n - One-shot: only when the ideal fire lands on `:00` or `:30` of the hour, the fire is pulled **earlier** by ≤ 90 seconds. Other minutes pass through unchanged.\n\n## One-shot vs recurring — when to pick which\n\nUse `recurring: false` for \"remind me at X\" style requests, single deadlines, \"in N minutes do Y\", and any task that should not repeat. Use `recurring: true` for periodic polling (CI status, build watchers, scheduled reports), workday rituals, and anything the user explicitly described as recurring.\n\n## Session lifetime\n\nCron tasks live in the current kimi CLI session. When you exit, they\nare persisted under the session homedir; the next `kimi resume` of the\nsame session reloads them and the scheduler resumes from each task's\n`createdAt`. Fire times that fell during the offline window are\ncollapsed into a single delivery via `coalescedCount` (and recurring\ntasks past their 7-day window arrive with `stale: true` as their final\ndelivery).\n\nTasks do **not** carry over into a brand-new session — they are scoped\nto the resumed session id, not to the working directory.\n\n## Limits\n\nA session holds at most 50 live cron tasks; creating one beyond that is rejected. (The `prompt` body is also capped — see its parameter description.) Expressions that never fire within the next 5 years (e.g. `0 0 31 2 *`, an impossible date) are rejected at create time.\n\n## Returned fields\n\n`id` (8-hex), `cron` (the normalized expression), `humanSchedule` (English summary), `recurring`,\n`nextFireAt` (local ISO timestamp with numeric offset, or null). `id` is needed by `CronDelete`.\n\n## Tell the user how to cancel or modify\n\nAfter successfully creating a task, proactively tell the user how they can cancel or modify it later. Users have no direct `/cron` command or self-service UI to manage reminders themselves; they must ask the model to make changes (e.g. \"cancel my 9am reminder\" or \"change my daily check to 10am\"). Include the task `id` in your message so the user can reference it.\n";
|
|
145658
|
+
}));
|
|
145659
|
+
//#endregion
|
|
145660
|
+
//#region ../../packages/agent-core/src/tools/cron/cron-create.ts
|
|
145661
|
+
function formatOutput(o) {
|
|
145662
|
+
return [
|
|
145663
|
+
`id: ${o.id}`,
|
|
145664
|
+
`cron: ${o.cron}`,
|
|
145665
|
+
`humanSchedule: ${o.humanSchedule}`,
|
|
145666
|
+
`recurring: ${String(o.recurring)}`,
|
|
145667
|
+
`nextFireAt: ${o.nextFireAt === null ? "null" : formatLocalIsoWithOffset(o.nextFireAt)}`
|
|
145668
|
+
].join("\n");
|
|
145669
|
+
}
|
|
145670
|
+
var MAX_PROMPT_BYTES, ONE_SHOT_MAX_FUTURE_MS, CronCreateInputSchema, CronCreateTool;
|
|
145671
|
+
var init_cron_create = __esmMin((() => {
|
|
145672
|
+
init_zod$1();
|
|
145673
|
+
init_input_schema();
|
|
145674
|
+
init_rule_match();
|
|
145675
|
+
init_cron_expr();
|
|
145676
|
+
init_jitter();
|
|
145677
|
+
init_time_format();
|
|
145678
|
+
init_cron_create$1();
|
|
145679
|
+
MAX_PROMPT_BYTES = 8 * 1024;
|
|
145680
|
+
ONE_SHOT_MAX_FUTURE_MS = 350 * 24 * 60 * 60 * 1e3;
|
|
145681
|
+
CronCreateInputSchema = object({
|
|
145682
|
+
cron: string().describe("5-field cron expression in local time: \"M H DoM Mon DoW\" (e.g. \"*/5 * * * *\" = every 5 minutes; \"30 14 28 2 *\" = Feb 28 at 2:30pm local — a pinned date like this repeats yearly unless you also pass recurring: false)."),
|
|
145683
|
+
prompt: string().min(1).max(MAX_PROMPT_BYTES).describe("The prompt to enqueue at each fire time. Limited to 8 KiB (UTF-8)."),
|
|
145684
|
+
recurring: boolean$1().optional().default(true).describe("true (default) = fire on every cron match until deleted or auto-expired after 7 days. false = fire once at the next match, then auto-delete. Use false for \"remind me at X\" one-shot requests with pinned minute/hour/dom/month.")
|
|
145685
|
+
});
|
|
145686
|
+
CronCreateTool = class {
|
|
145687
|
+
manager;
|
|
145688
|
+
name = "CronCreate";
|
|
145689
|
+
description = cron_create_default;
|
|
145690
|
+
parameters = toInputJsonSchema(CronCreateInputSchema);
|
|
145691
|
+
constructor(manager) {
|
|
145692
|
+
this.manager = manager;
|
|
145693
|
+
}
|
|
145694
|
+
resolveExecution(args) {
|
|
145695
|
+
if (process.env["KIMI_DISABLE_CRON"] === "1") return {
|
|
145696
|
+
isError: true,
|
|
145697
|
+
output: "Cron scheduling is disabled (KIMI_DISABLE_CRON=1)."
|
|
145698
|
+
};
|
|
145699
|
+
const normalizedCron = args.cron.trim().split(/\s+/).join(" ");
|
|
145700
|
+
let parsed;
|
|
145701
|
+
try {
|
|
145702
|
+
parsed = parseCronExpression(normalizedCron);
|
|
145703
|
+
} catch (err) {
|
|
145704
|
+
return {
|
|
145705
|
+
isError: true,
|
|
145706
|
+
output: `Invalid cron expression: ${err instanceof Error ? err.message : String(err)}`
|
|
145707
|
+
};
|
|
145708
|
+
}
|
|
145709
|
+
const nowAtPrepare = this.manager.clocks.wallNow();
|
|
145710
|
+
if (!hasFireWithinYears(parsed, 5, nowAtPrepare)) return {
|
|
145711
|
+
isError: true,
|
|
145712
|
+
output: `Cron expression ${JSON.stringify(normalizedCron)} has no fire within 5 years; refusing to schedule.`
|
|
145713
|
+
};
|
|
145714
|
+
if (this.manager.store.list().length >= 50) return {
|
|
145715
|
+
isError: true,
|
|
145716
|
+
output: `Cron job cap reached (max ${String(50)} per session).`
|
|
145717
|
+
};
|
|
145718
|
+
const byteLen = Buffer.byteLength(args.prompt, "utf8");
|
|
145719
|
+
if (byteLen > MAX_PROMPT_BYTES) return {
|
|
145720
|
+
isError: true,
|
|
145721
|
+
output: `Prompt exceeds ${String(MAX_PROMPT_BYTES)} bytes (got ${String(byteLen)}).`
|
|
145722
|
+
};
|
|
145723
|
+
const recurring = args.recurring !== false;
|
|
145724
|
+
if (!recurring) {
|
|
145725
|
+
const firstFire = computeNextCronRun(parsed, nowAtPrepare);
|
|
145726
|
+
if (firstFire !== null && firstFire - nowAtPrepare > ONE_SHOT_MAX_FUTURE_MS) return {
|
|
145727
|
+
isError: true,
|
|
145728
|
+
output: `One-shot cron ${JSON.stringify(normalizedCron)} would not fire until ${formatLocalIsoWithOffset(firstFire)} (more than a year out). If you meant "today" or a near date, the pinned day/month has already passed this year — pick a future date or use wildcards.`
|
|
145729
|
+
};
|
|
145730
|
+
}
|
|
145731
|
+
return {
|
|
145732
|
+
description: recurring ? `Scheduling cron ${normalizedCron}` : `Scheduling one-shot ${normalizedCron}`,
|
|
145733
|
+
approvalRule: literalRulePattern(this.name, JSON.stringify({
|
|
145734
|
+
cron: normalizedCron,
|
|
145735
|
+
prompt: args.prompt,
|
|
145736
|
+
recurring
|
|
145737
|
+
})),
|
|
145738
|
+
execute: async () => {
|
|
145739
|
+
const nowMs = this.manager.clocks.wallNow();
|
|
145740
|
+
if (this.manager.store.list().length >= 50) return {
|
|
145741
|
+
isError: true,
|
|
145742
|
+
output: `Cron job cap reached (max ${String(50)} per session).`
|
|
145743
|
+
};
|
|
145744
|
+
const task = this.manager.addTask({
|
|
145745
|
+
cron: normalizedCron,
|
|
145746
|
+
prompt: args.prompt,
|
|
145747
|
+
recurring
|
|
145748
|
+
});
|
|
145749
|
+
const ideal = computeNextCronRun(parsed, nowMs);
|
|
145750
|
+
const nextFireAt = ideal === null ? null : recurring ? jitteredNextCronRunMs(task, parsed, ideal) : oneShotJitteredNextCronRunMs(task, ideal);
|
|
145751
|
+
const humanSchedule = cronToHuman(parsed);
|
|
145752
|
+
this.manager.emitScheduled(task);
|
|
145753
|
+
return {
|
|
145754
|
+
output: formatOutput({
|
|
145755
|
+
id: task.id,
|
|
145756
|
+
cron: normalizedCron,
|
|
145757
|
+
humanSchedule,
|
|
145758
|
+
recurring,
|
|
145759
|
+
nextFireAt
|
|
145760
|
+
}),
|
|
145761
|
+
isError: false,
|
|
145762
|
+
message: `Scheduled cron ${task.id}`
|
|
145763
|
+
};
|
|
145764
|
+
}
|
|
145765
|
+
};
|
|
145766
|
+
}
|
|
145767
|
+
};
|
|
145768
|
+
}));
|
|
145769
|
+
//#endregion
|
|
145770
|
+
//#region ../../packages/agent-core/src/tools/cron/cron-delete.md?raw
|
|
145771
|
+
var cron_delete_default;
|
|
145772
|
+
var init_cron_delete$1 = __esmMin((() => {
|
|
145773
|
+
cron_delete_default = "Cancel a scheduled cron job by id.\n\nUse this tool to remove a cron task previously scheduled with\n`CronCreate`. The `id` is the 8-hex value returned by `CronCreate`, or\nshown in the `id:` column of `CronList` — quote it verbatim, no\nprefix.\n\nBehaviour by task kind:\n\n- **Recurring task** (`recurring: true`): stops all future fires\n immediately. The scheduler picks up the deletion on its next tick.\n- **One-shot task** (`recurring: false`): cancels the pending fire if\n it has not happened yet. One-shots that have already fired\n auto-delete themselves, so calling `CronDelete` on a fired one-shot\n returns \"no cron job with id ...\".\n\nNot-found is reported as an error (not a silent no-op) so you can\ncorrect yourself — typically by calling `CronList` to see which ids\nare actually live, rather than re-trying with the same stale id.\n\nRefresh pattern (use when you want a stale recurring schedule to\ncontinue):\n\nStale recurring tasks are auto-deleted by the system after their final\nfire — there is nothing for `CronDelete` to remove at that point. To\nkeep the schedule running, just call `CronCreate` with the same `cron`\nand `prompt`. Use `CronList`'s `prompt` field to recall the original\ntext after a context compaction.\n\n`CronDelete` remains the right call when you want to cancel a task\nthat is still live (recurring not yet stale, or a one-shot still\npending).\n\nGuidelines:\n\n- Users have no direct `/cron` command or self-service UI to delete\n tasks themselves; they must ask the model to cancel a reminder.\n When deleting on behalf of a user, confirm the action and report\n the result plainly.\n- Cron deletion is irreversible — there is no undo. If you delete the\n wrong task, you must re-create it with `CronCreate`.\n- If the model is unsure which id is current (e.g. after a context\n compaction), call `CronList` first rather than guessing.\n";
|
|
145774
|
+
}));
|
|
145775
|
+
//#endregion
|
|
145776
|
+
//#region ../../packages/agent-core/src/tools/cron/cron-delete.ts
|
|
145777
|
+
var ID_PATTERN, CronDeleteInputSchema, CronDeleteTool;
|
|
145778
|
+
var init_cron_delete = __esmMin((() => {
|
|
145779
|
+
init_zod$1();
|
|
145780
|
+
init_input_schema();
|
|
145781
|
+
init_cron_delete$1();
|
|
145782
|
+
ID_PATTERN = /^[0-9a-f]{8}$/;
|
|
145783
|
+
CronDeleteInputSchema = object({ id: string().describe("The 8-hex cron job id returned by CronCreate / CronList.") });
|
|
145784
|
+
CronDeleteTool = class {
|
|
145785
|
+
manager;
|
|
145786
|
+
name = "CronDelete";
|
|
145787
|
+
description = cron_delete_default;
|
|
145788
|
+
parameters = toInputJsonSchema(CronDeleteInputSchema);
|
|
145789
|
+
constructor(manager) {
|
|
145790
|
+
this.manager = manager;
|
|
145791
|
+
}
|
|
145792
|
+
resolveExecution(args) {
|
|
145793
|
+
if (!ID_PATTERN.test(args.id)) return {
|
|
145794
|
+
isError: true,
|
|
145795
|
+
output: `Invalid cron job id ${JSON.stringify(args.id)} — must be 8 lowercase hex characters.`
|
|
145796
|
+
};
|
|
145797
|
+
return {
|
|
145798
|
+
description: `Deleting cron ${args.id}`,
|
|
145799
|
+
approvalRule: this.name,
|
|
145800
|
+
execute: async () => {
|
|
145801
|
+
if (this.manager.removeTasks([args.id]).length === 0) return {
|
|
145802
|
+
isError: true,
|
|
145803
|
+
output: `No cron job with id ${args.id}.`
|
|
145804
|
+
};
|
|
145805
|
+
this.manager.emitDeleted(args.id);
|
|
145806
|
+
return {
|
|
145807
|
+
output: `Deleted cron job ${args.id}.`,
|
|
145808
|
+
isError: false
|
|
145809
|
+
};
|
|
145810
|
+
}
|
|
145811
|
+
};
|
|
145812
|
+
}
|
|
145813
|
+
};
|
|
145814
|
+
}));
|
|
145815
|
+
//#endregion
|
|
145816
|
+
//#region ../../packages/agent-core/src/tools/cron/cron-list.md?raw
|
|
145817
|
+
var cron_list_default;
|
|
145818
|
+
var init_cron_list$1 = __esmMin((() => {
|
|
145819
|
+
cron_list_default = "List all cron jobs currently scheduled in this session.\n\nUse this tool to see every pending cron task — both recurring jobs and\none-shot reminders — that you (or the user) have scheduled with\n`CronCreate`. The output is the entry point for inspecting scheduled\nwork: it returns a stable id, the original cron expression, a human\nrendering, the next post-jitter fire time, the recurring flag, the\ntask's age in days, and a stale indicator.\n\nEach record carries:\n\n- `id` — the 8-hex task id. Pass this to `CronDelete` to remove the\n task, or quote it in user-facing messages when asking for\n confirmation.\n- `cron` — the verbatim 5-field cron expression as scheduled.\n- `humanSchedule` — plain-English rendering (e.g. `every 5 minutes`).\n- `prompt` — the scheduled prompt text, JSON-encoded so embedded\n newlines stay on one line. Truncated to 200 UTF-8 bytes with\n `…(truncated)` if longer. Use this to recall what a task is for\n after a context compaction, and as the source for the\n `CronCreate` refresh ritual.\n- `nextFireAt` — local ISO timestamp with an explicit numeric offset\n for the next fire **after jitter has been applied**. The actual fire\n may land slightly before or after a round `:00` / `:30` minute mark\n due to herd-avoidance jitter; this is the value the scheduler will\n compare against, so it reflects what will really happen. `null` if\n the expression has no fire in the next 5 years (should not happen\n for tasks created through `CronCreate`, which validates).\n- `recurring` — `true` for cadenced jobs, `false` for one-shots.\n- `ageDays` — `(now - createdAt) / day`, two decimal places. Useful\n when deciding whether a long-running cron is still relevant.\n- `stale` — `true` when a recurring task is older than 7 days. The\n system **auto-deletes the task after this fire** to bound session\n lifetime; the `stale: true` flag is the model's notice that this is\n the final delivery. To resume the same schedule, call `CronCreate`\n again with the original `cron` and `prompt` (the `prompt` row above\n carries it for exactly this purpose). One-shots are never marked\n stale — they fire at most once by construction.\n\nGuidelines:\n\n- This tool is read-only and never mutates state, so it is always\n safe to call (including in plan mode).\n- Users cannot directly manage cron tasks themselves; if they want to\n cancel or modify a schedule, route the request through the model\n (i.e. call `CronDelete` or `CronCreate` on their behalf).\n- The empty case returns `cron_jobs: 0\\nNo cron jobs scheduled.`. Cron\n tasks survive a `kimi resume` of the same session but do not bleed\n into new sessions.\n- After a context compaction, or whenever you are unsure which cron\n jobs are live, call this tool to re-enumerate them rather than\n guessing ids from earlier in the conversation.\n- Records are separated by a line containing just `---`, in the\n insertion order they were scheduled.\n";
|
|
145820
|
+
}));
|
|
145821
|
+
//#endregion
|
|
145822
|
+
//#region ../../packages/agent-core/src/tools/cron/cron-list.ts
|
|
145823
|
+
function previewPrompt(prompt) {
|
|
145824
|
+
const buf = Buffer.from(prompt, "utf8");
|
|
145825
|
+
if (buf.byteLength <= PROMPT_PREVIEW_BYTES) return prompt;
|
|
145826
|
+
let end = PROMPT_PREVIEW_BYTES;
|
|
145827
|
+
while (end > 0 && (buf[end] & 192) === 128) end--;
|
|
145828
|
+
return `${buf.subarray(0, end).toString("utf8")}…(truncated)`;
|
|
145829
|
+
}
|
|
145830
|
+
var CronListInputSchema, MS_PER_DAY, PROMPT_PREVIEW_BYTES, CronListTool;
|
|
145831
|
+
var init_cron_list = __esmMin((() => {
|
|
145832
|
+
init_zod$1();
|
|
145833
|
+
init_input_schema();
|
|
145834
|
+
init_cron_expr();
|
|
145835
|
+
init_time_format();
|
|
145836
|
+
init_cron_list$1();
|
|
145837
|
+
CronListInputSchema = object({}).strict();
|
|
145838
|
+
MS_PER_DAY = 1440 * 60 * 1e3;
|
|
145839
|
+
PROMPT_PREVIEW_BYTES = 200;
|
|
145840
|
+
CronListTool = class {
|
|
145841
|
+
manager;
|
|
145842
|
+
name = "CronList";
|
|
145843
|
+
description = cron_list_default;
|
|
145844
|
+
parameters = toInputJsonSchema(CronListInputSchema);
|
|
145845
|
+
constructor(manager) {
|
|
145846
|
+
this.manager = manager;
|
|
145847
|
+
}
|
|
145848
|
+
resolveExecution(_args) {
|
|
145849
|
+
return {
|
|
145850
|
+
description: "Listing scheduled cron jobs",
|
|
145851
|
+
approvalRule: this.name,
|
|
145852
|
+
execute: async () => {
|
|
145853
|
+
const tasks = this.manager.store.list();
|
|
145854
|
+
const nowMs = this.manager.clocks.wallNow();
|
|
145855
|
+
const records = tasks.map((t) => this.renderRecord(t, nowMs));
|
|
145856
|
+
const header = `cron_jobs: ${String(tasks.length)}`;
|
|
145857
|
+
if (records.length === 0) return {
|
|
145858
|
+
output: `${header}\nNo cron jobs scheduled.`,
|
|
145859
|
+
isError: false
|
|
145860
|
+
};
|
|
145861
|
+
return {
|
|
145862
|
+
output: `${header}\n${records.join("\n---\n")}`,
|
|
145863
|
+
isError: false
|
|
145864
|
+
};
|
|
145865
|
+
}
|
|
145866
|
+
};
|
|
145867
|
+
}
|
|
145868
|
+
renderRecord(task, nowMs) {
|
|
145869
|
+
const recurring = task.recurring !== false;
|
|
145870
|
+
const ageMs = nowMs - task.createdAt;
|
|
145871
|
+
const ageDays = Number.isFinite(ageMs) ? ageMs / MS_PER_DAY : 0;
|
|
145872
|
+
const stale = this.manager.isStale(task);
|
|
145873
|
+
let humanSchedule = task.cron;
|
|
145874
|
+
let nextFireAtIso = "null";
|
|
145875
|
+
try {
|
|
145876
|
+
humanSchedule = cronToHuman(parseCronExpression(task.cron));
|
|
145877
|
+
const nextFireMs = this.manager.getNextFireForTask(task.id);
|
|
145878
|
+
if (nextFireMs !== null) nextFireAtIso = formatLocalIsoWithOffset(nextFireMs);
|
|
145879
|
+
} catch {}
|
|
145880
|
+
return [
|
|
145881
|
+
`id: ${task.id}`,
|
|
145882
|
+
`cron: ${task.cron}`,
|
|
145883
|
+
`humanSchedule: ${humanSchedule}`,
|
|
145884
|
+
`prompt: ${JSON.stringify(previewPrompt(task.prompt))}`,
|
|
145885
|
+
`nextFireAt: ${nextFireAtIso}`,
|
|
145886
|
+
`recurring: ${String(recurring)}`,
|
|
145887
|
+
`ageDays: ${ageDays.toFixed(2)}`,
|
|
145888
|
+
`stale: ${String(stale)}`
|
|
145889
|
+
].join("\n");
|
|
145890
|
+
}
|
|
145891
|
+
};
|
|
145892
|
+
}));
|
|
145893
|
+
//#endregion
|
|
145830
145894
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/agent-background-disabled.md?raw
|
|
145831
145895
|
var agent_background_disabled_default;
|
|
145832
145896
|
var init_agent_background_disabled = __esmMin((() => {
|
|
@@ -145944,6 +146008,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
145944
146008
|
this.backgroundManager = backgroundManager;
|
|
145945
146009
|
const log = options?.log;
|
|
145946
146010
|
this.allowBackground = options?.allowBackground ?? true;
|
|
146011
|
+
this.subagentTimeoutMs = options?.subagentTimeoutMs;
|
|
145947
146012
|
const typeLines = buildSubagentDescriptions(subagents);
|
|
145948
146013
|
const baseDescription = `${agent_default}\n\n${this.allowBackground ? agent_background_enabled_default : agent_background_disabled_default}`;
|
|
145949
146014
|
this.description = typeLines ? `${baseDescription}\n\nAvailable agent types (pass via subagent_type):\n${typeLines}` : baseDescription;
|
|
@@ -145951,6 +146016,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
145951
146016
|
}
|
|
145952
146017
|
log;
|
|
145953
146018
|
allowBackground;
|
|
146019
|
+
subagentTimeoutMs;
|
|
145954
146020
|
async resolveExecution(args) {
|
|
145955
146021
|
let profileName = args.subagent_type?.length ? args.subagent_type : "coder";
|
|
145956
146022
|
const resumeAgentId = args.resume?.trim();
|
|
@@ -146018,7 +146084,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
146018
146084
|
try {
|
|
146019
146085
|
taskId = this.backgroundManager.registerTask(new AgentBackgroundTask(handle, args.description, this.subagentHost, controller), {
|
|
146020
146086
|
detached: runInBackground,
|
|
146021
|
-
timeoutMs:
|
|
146087
|
+
timeoutMs: this.subagentTimeoutMs ?? 72e5,
|
|
146022
146088
|
signal: runInBackground ? void 0 : signal
|
|
146023
146089
|
});
|
|
146024
146090
|
signal.removeEventListener("abort", abortBeforeRegister);
|
|
@@ -146052,7 +146118,7 @@ var init_agent$1 = __esmMin((() => {
|
|
|
146052
146118
|
if (info?.status === "completed") return { output: formatForegroundAgentSuccess(handle, await this.backgroundManager.readOutput(taskId)) };
|
|
146053
146119
|
const timedOut = info?.status === "timed_out";
|
|
146054
146120
|
return {
|
|
146055
|
-
output: formatForegroundAgentFailure(handle, timedOut ? `Agent timed out after ${
|
|
146121
|
+
output: formatForegroundAgentFailure(handle, timedOut ? `Agent timed out after ${formatSubagentTimeoutDescription(this.subagentTimeoutMs ?? 72e5)}.` : info?.stopReason === "Interrupted by user" ? USER_INTERRUPTED_SUBAGENT_MESSAGE : info?.stopReason !== void 0 ? info.stopReason : "The subagent was stopped before it finished.", timedOut),
|
|
146056
146122
|
isError: true
|
|
146057
146123
|
};
|
|
146058
146124
|
}
|
|
@@ -146166,12 +146232,14 @@ var init_agent_swarm = __esmMin((() => {
|
|
|
146166
146232
|
AgentSwarmTool = class {
|
|
146167
146233
|
subagentHost;
|
|
146168
146234
|
swarmMode;
|
|
146235
|
+
subagentTimeoutMs;
|
|
146169
146236
|
name = "AgentSwarm";
|
|
146170
146237
|
description = agent_swarm_default;
|
|
146171
146238
|
parameters = toInputJsonSchema(AgentSwarmToolInputSchema);
|
|
146172
|
-
constructor(subagentHost, swarmMode) {
|
|
146239
|
+
constructor(subagentHost, swarmMode, subagentTimeoutMs) {
|
|
146173
146240
|
this.subagentHost = subagentHost;
|
|
146174
146241
|
this.swarmMode = swarmMode;
|
|
146242
|
+
this.subagentTimeoutMs = subagentTimeoutMs;
|
|
146175
146243
|
}
|
|
146176
146244
|
resolveExecution(args) {
|
|
146177
146245
|
const agentCount = (args.items?.length ?? 0) + Object.keys(args.resume_agent_ids ?? {}).length;
|
|
@@ -146212,7 +146280,7 @@ var init_agent_swarm = __esmMin((() => {
|
|
|
146212
146280
|
runInBackground: false,
|
|
146213
146281
|
swarmItem: spec.item,
|
|
146214
146282
|
signal,
|
|
146215
|
-
timeout:
|
|
146283
|
+
timeout: this.subagentTimeoutMs ?? 72e5
|
|
146216
146284
|
};
|
|
146217
146285
|
if (spec.kind === "resume") return {
|
|
146218
146286
|
...common,
|
|
@@ -146235,7 +146303,7 @@ var init_agent_swarm = __esmMin((() => {
|
|
|
146235
146303
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/ask-user.md?raw
|
|
146236
146304
|
var ask_user_default;
|
|
146237
146305
|
var init_ask_user$1 = __esmMin((() => {
|
|
146238
|
-
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
|
|
146306
|
+
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 chose not to answer — do not treat this as selecting the recommended option; decide based on context and do not re-ask the same question\n";
|
|
146239
146307
|
}));
|
|
146240
146308
|
//#endregion
|
|
146241
146309
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/ask-user.ts
|
|
@@ -153945,6 +154013,7 @@ var init_tool$1 = __esmMin((() => {
|
|
|
153945
154013
|
init_output();
|
|
153946
154014
|
init_tool_naming();
|
|
153947
154015
|
init_profile();
|
|
154016
|
+
init_subagent_host();
|
|
153948
154017
|
init_skill$4();
|
|
153949
154018
|
init_llm_request_logger();
|
|
153950
154019
|
init_builtin();
|
|
@@ -154501,9 +154570,10 @@ var init_tool$1 = __esmMin((() => {
|
|
|
154501
154570
|
this.agent.skills?.registry.listInvocableSkills().length && new SkillTool(this.agent),
|
|
154502
154571
|
this.agent.subagentHost && new AgentTool(this.agent.subagentHost, background, DEFAULT_AGENT_PROFILES["agent"]?.subagents, {
|
|
154503
154572
|
allowBackground,
|
|
154504
|
-
log: this.agent.log
|
|
154573
|
+
log: this.agent.log,
|
|
154574
|
+
subagentTimeoutMs: resolveSubagentTimeoutMs(this.agent.kimiConfig?.subagent?.timeoutMs)
|
|
154505
154575
|
}),
|
|
154506
|
-
this.agent.subagentHost && new AgentSwarmTool(this.agent.subagentHost, this.agent.swarmMode),
|
|
154576
|
+
this.agent.subagentHost && new AgentSwarmTool(this.agent.subagentHost, this.agent.swarmMode, resolveSubagentTimeoutMs(this.agent.kimiConfig?.subagent?.timeoutMs)),
|
|
154507
154577
|
toolServices?.webSearcher && new WebSearchTool(toolServices.webSearcher),
|
|
154508
154578
|
toolServices?.urlFetcher && new FetchURLTool(toolServices.urlFetcher)
|
|
154509
154579
|
].filter((tool) => !!tool).map((tool) => [tool.name, tool]));
|
|
@@ -156368,17 +156438,18 @@ var init_agent = __esmMin((() => {
|
|
|
156368
156438
|
}
|
|
156369
156439
|
/**
|
|
156370
156440
|
* Single decision point for select_tools progressive disclosure. All three
|
|
156371
|
-
* gates must be open: the model
|
|
156372
|
-
*
|
|
156373
|
-
*
|
|
156374
|
-
*
|
|
156375
|
-
*
|
|
156376
|
-
*
|
|
156377
|
-
*
|
|
156441
|
+
* gates must be open: the model has the `dynamically_loaded_tools`
|
|
156442
|
+
* capability (message-level tool declarations), the model declares
|
|
156443
|
+
* `tool_use` (a model without tool use loading tools dynamically is a
|
|
156444
|
+
* contradiction), and the `tool-select` experimental flag is on. Every
|
|
156445
|
+
* consumer — top-level tools[] convergence, select_tools registration,
|
|
156446
|
+
* manifest announcements, projection shaping — reads this instead of
|
|
156447
|
+
* re-deriving the conditions, so degradation is lossless: any closed gate
|
|
156448
|
+
* reproduces the inline behavior byte-for-byte.
|
|
156378
156449
|
*/
|
|
156379
156450
|
get toolSelectEnabled() {
|
|
156380
156451
|
const capability = this.config.modelCapabilities;
|
|
156381
|
-
return capability.
|
|
156452
|
+
return capability.dynamically_loaded_tools === true && capability.tool_use && this.experimentalFlags.enabled("tool-select");
|
|
156382
156453
|
}
|
|
156383
156454
|
get generate() {
|
|
156384
156455
|
return async (provider, systemPrompt, tools, history, callbacks, options) => {
|
|
@@ -156610,6 +156681,7 @@ var init_agent = __esmMin((() => {
|
|
|
156610
156681
|
pauseGoal: () => this.goal.pauseGoal(),
|
|
156611
156682
|
resumeGoal: () => this.goal.resumeGoal(),
|
|
156612
156683
|
cancelGoal: () => this.goal.cancelGoal(),
|
|
156684
|
+
getCronTasks: () => ({ tasks: this.cron?.listTaskSnapshots() ?? [] }),
|
|
156613
156685
|
getBackgroundOutput: (payload) => this.background.readOutput(payload.taskId, payload.tail),
|
|
156614
156686
|
getContext: () => this.context.data(),
|
|
156615
156687
|
getConfig: () => this.config.data(),
|
|
@@ -187461,6 +187533,8 @@ var init_session$1 = __esmMin((() => {
|
|
|
187461
187533
|
};
|
|
187462
187534
|
writeMetadataPromise = Promise.resolve();
|
|
187463
187535
|
agentsMdWarning;
|
|
187536
|
+
printSteerDeadline;
|
|
187537
|
+
printSteerTurns = 0;
|
|
187464
187538
|
constructor(options) {
|
|
187465
187539
|
this.options = options;
|
|
187466
187540
|
this.logHandle = options.id === void 0 ? void 0 : getRootLogger().attachSession({
|
|
@@ -187647,23 +187721,18 @@ var init_session$1 = __esmMin((() => {
|
|
|
187647
187721
|
* Wait for all still-running background tasks (across every agent) to reach a
|
|
187648
187722
|
* terminal state before a `kimi -p` (print) run exits.
|
|
187649
187723
|
*
|
|
187650
|
-
*
|
|
187651
|
-
*
|
|
187652
|
-
*
|
|
187653
|
-
*
|
|
187724
|
+
* Only runs when the resolved print background mode is `'drain'` (see
|
|
187725
|
+
* `resolvePrintBackgroundMode`): `print_background_mode = "drain"`, or the
|
|
187726
|
+
* legacy `keep_alive_on_exit = true` fallback. In every other mode it returns
|
|
187727
|
+
* immediately. The wait is bounded by `background.print_wait_ceiling_s`
|
|
187728
|
+
* (default 3600s) so a wedged task cannot keep the process alive forever.
|
|
187654
187729
|
*
|
|
187655
187730
|
* Terminal notifications are suppressed for each task while we wait, so a task
|
|
187656
187731
|
* completing cannot `turn.steer` the (already finished) main agent into launching
|
|
187657
|
-
* a new turn.
|
|
187732
|
+
* a new turn. (This is exactly what `'steer'` mode avoids by never calling here.)
|
|
187658
187733
|
*/
|
|
187659
187734
|
async waitForBackgroundTasksOnPrint() {
|
|
187660
|
-
if (
|
|
187661
|
-
env: process.env,
|
|
187662
|
-
envKey: BACKGROUND_KEEP_ALIVE_ON_EXIT_ENV,
|
|
187663
|
-
configValue: this.options.background?.keepAliveOnExit,
|
|
187664
|
-
defaultValue: false,
|
|
187665
|
-
parseEnv: parseBooleanEnv
|
|
187666
|
-
})) return;
|
|
187735
|
+
if (this.resolvePrintBackgroundMode() !== "drain") return;
|
|
187667
187736
|
const timeoutMs = (this.options.background?.printWaitCeilingS ?? 3600) * 1e3;
|
|
187668
187737
|
const deadline = Date.now() + timeoutMs;
|
|
187669
187738
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -187699,6 +187768,67 @@ var init_session$1 = __esmMin((() => {
|
|
|
187699
187768
|
});
|
|
187700
187769
|
}
|
|
187701
187770
|
}
|
|
187771
|
+
/**
|
|
187772
|
+
* Resolve the effective print-mode (`kimi -p`) background-task policy.
|
|
187773
|
+
*
|
|
187774
|
+
* `background.print_background_mode` is authoritative when set. Otherwise we
|
|
187775
|
+
* fall back to the legacy `background.keep_alive_on_exit` mapping so existing
|
|
187776
|
+
* configs keep their behavior: `keep_alive_on_exit = true` ⇒ `'drain'`
|
|
187777
|
+
* (suppress + drain background tasks before exit), otherwise `'exit'`.
|
|
187778
|
+
*/
|
|
187779
|
+
resolvePrintBackgroundMode() {
|
|
187780
|
+
const configured = this.options.background?.printBackgroundMode;
|
|
187781
|
+
if (configured !== void 0) return configured;
|
|
187782
|
+
return resolveConfigValue({
|
|
187783
|
+
env: process.env,
|
|
187784
|
+
envKey: BACKGROUND_KEEP_ALIVE_ON_EXIT_ENV,
|
|
187785
|
+
configValue: this.options.background?.keepAliveOnExit,
|
|
187786
|
+
defaultValue: false,
|
|
187787
|
+
parseEnv: parseBooleanEnv
|
|
187788
|
+
}) ? "drain" : "exit";
|
|
187789
|
+
}
|
|
187790
|
+
countActiveBackgroundTasks() {
|
|
187791
|
+
let count = 0;
|
|
187792
|
+
for (const agent of this.readyAgents()) count += agent.background.list(true).length;
|
|
187793
|
+
return count;
|
|
187794
|
+
}
|
|
187795
|
+
/**
|
|
187796
|
+
* Decide what the `kimi -p` driver should do after the main agent's turn ends
|
|
187797
|
+
* with `reason === 'completed'`. Returns `'finish'` when the run may exit, or
|
|
187798
|
+
* `'continue'` when the driver must stay alive so a background-task completion
|
|
187799
|
+
* can `turn.steer` the main agent into a new turn.
|
|
187800
|
+
*
|
|
187801
|
+
* - 'exit' : finish immediately (default).
|
|
187802
|
+
* - 'drain' : suppress + drain background tasks, then finish (legacy
|
|
187803
|
+
* `keep_alive_on_exit = true` behavior).
|
|
187804
|
+
* - 'steer' : while background tasks are still pending, return 'continue' so
|
|
187805
|
+
* completions steer new main turns; finish once quiescent, or when
|
|
187806
|
+
* the wall-clock ceiling (`print_wait_ceiling_s`) or the turn cap
|
|
187807
|
+
* (`print_max_turns`) is reached.
|
|
187808
|
+
*/
|
|
187809
|
+
async handlePrintMainTurnCompleted() {
|
|
187810
|
+
const mode = this.resolvePrintBackgroundMode();
|
|
187811
|
+
if (mode === "exit") return "finish";
|
|
187812
|
+
if (mode === "drain") {
|
|
187813
|
+
await this.waitForBackgroundTasksOnPrint();
|
|
187814
|
+
return "finish";
|
|
187815
|
+
}
|
|
187816
|
+
const ceilingS = this.options.background?.printWaitCeilingS ?? 3600;
|
|
187817
|
+
const maxTurns = this.options.background?.printMaxTurns ?? 50;
|
|
187818
|
+
const now = Date.now();
|
|
187819
|
+
this.printSteerDeadline ??= now + ceilingS * 1e3;
|
|
187820
|
+
this.printSteerTurns += 1;
|
|
187821
|
+
if (now >= this.printSteerDeadline) {
|
|
187822
|
+
this.log.warn("print steer ceiling reached, finishing", { ceilingS });
|
|
187823
|
+
return "finish";
|
|
187824
|
+
}
|
|
187825
|
+
if (this.printSteerTurns > maxTurns) {
|
|
187826
|
+
this.log.warn("print steer max turns reached, finishing", { maxTurns });
|
|
187827
|
+
return "finish";
|
|
187828
|
+
}
|
|
187829
|
+
if (this.countActiveBackgroundTasks() > 0) return "continue";
|
|
187830
|
+
return "finish";
|
|
187831
|
+
}
|
|
187702
187832
|
async createAgent(config, options = {}) {
|
|
187703
187833
|
await this.skillsReady;
|
|
187704
187834
|
const type = config.type ?? "main";
|
|
@@ -206200,7 +206330,9 @@ var init_model_alias_merge = __esmMin((() => {
|
|
|
206200
206330
|
"model",
|
|
206201
206331
|
"maxContextSize",
|
|
206202
206332
|
"capabilities",
|
|
206203
|
-
"displayName"
|
|
206333
|
+
"displayName",
|
|
206334
|
+
"supportEfforts",
|
|
206335
|
+
"defaultEffort"
|
|
206204
206336
|
]);
|
|
206205
206337
|
}));
|
|
206206
206338
|
//#endregion
|
|
@@ -206928,6 +207060,10 @@ function toModelEntry(value) {
|
|
|
206928
207060
|
}
|
|
206929
207061
|
if (typeof value["tool_call"] === "boolean") entry.tool_call = value["tool_call"];
|
|
206930
207062
|
if (typeof value["reasoning"] === "boolean") entry.reasoning = value["reasoning"];
|
|
207063
|
+
const supportEfforts = toStringArrayOrUndefined(value["support_efforts"]);
|
|
207064
|
+
if (supportEfforts !== void 0) entry.support_efforts = supportEfforts;
|
|
207065
|
+
const defaultEffort = value["default_effort"];
|
|
207066
|
+
if (typeof defaultEffort === "string" && defaultEffort.length > 0) entry.default_effort = defaultEffort;
|
|
206931
207067
|
const modalities = value["modalities"];
|
|
206932
207068
|
if (isRecord$10(modalities)) {
|
|
206933
207069
|
const input = toStringArrayOrUndefined(modalities["input"]);
|
|
@@ -207001,7 +207137,7 @@ async function fetchCustomRegistry(source, fetchImpl = fetch, signal) {
|
|
|
207001
207137
|
function capabilitiesFromCustomEntry(model) {
|
|
207002
207138
|
const caps = /* @__PURE__ */ new Set();
|
|
207003
207139
|
if (model.tool_call === true) caps.add("tool_use");
|
|
207004
|
-
if (model.reasoning === true) caps.add("thinking");
|
|
207140
|
+
if (model.reasoning === true || (model.support_efforts?.length ?? 0) > 0) caps.add("thinking");
|
|
207005
207141
|
if (model.modalities?.input?.includes("image") === true) caps.add("image_in");
|
|
207006
207142
|
if (model.modalities?.input?.includes("video") === true) caps.add("video_in");
|
|
207007
207143
|
if (model.modalities?.output?.includes("image") === true) caps.add("image_out");
|
|
@@ -207009,7 +207145,7 @@ function capabilitiesFromCustomEntry(model) {
|
|
|
207009
207145
|
return [...caps];
|
|
207010
207146
|
}
|
|
207011
207147
|
function hasRichCapabilityHints(model) {
|
|
207012
|
-
return typeof model.tool_call === "boolean" || typeof model.reasoning === "boolean" || model.modalities !== void 0;
|
|
207148
|
+
return typeof model.tool_call === "boolean" || typeof model.reasoning === "boolean" || model.modalities !== void 0 || model.support_efforts !== void 0;
|
|
207013
207149
|
}
|
|
207014
207150
|
function resolveMaxContextSize(model) {
|
|
207015
207151
|
const context = model.limit?.context;
|
|
@@ -207051,7 +207187,9 @@ function applyCustomRegistryProvider(config, entry, source) {
|
|
|
207051
207187
|
model: model.id,
|
|
207052
207188
|
maxContextSize,
|
|
207053
207189
|
capabilities,
|
|
207054
|
-
displayName
|
|
207190
|
+
displayName,
|
|
207191
|
+
...model.support_efforts !== void 0 ? { supportEfforts: model.support_efforts } : {},
|
|
207192
|
+
...model.default_effort !== void 0 ? { defaultEffort: model.default_effort } : {}
|
|
207055
207193
|
}, CUSTOM_REGISTRY_MODEL_FIELDS);
|
|
207056
207194
|
}
|
|
207057
207195
|
config.models = existingModels;
|
|
@@ -207800,7 +207938,7 @@ function resolveModelCapabilities(alias, provider) {
|
|
|
207800
207938
|
thinking: declared.has("thinking") || declared.has("always_thinking") || detected.thinking,
|
|
207801
207939
|
tool_use: declared.has("tool_use") || detected.tool_use,
|
|
207802
207940
|
max_context_tokens: alias.maxContextSize,
|
|
207803
|
-
|
|
207941
|
+
dynamically_loaded_tools: declared.has("dynamically_loaded_tools") || detected.dynamically_loaded_tools === true
|
|
207804
207942
|
};
|
|
207805
207943
|
}
|
|
207806
207944
|
function toKosongProviderConfig(provider, model, modelProtocol, kimiRequestHeaders, maxOutputSize, reasoningKey, promptCacheKey, adaptiveThinking, betaApi, supportEfforts) {
|
|
@@ -208143,6 +208281,9 @@ var init_rpc$1 = __esmMin((() => {
|
|
|
208143
208281
|
waitForBackgroundTasksOnPrint(_payload) {
|
|
208144
208282
|
return this.session.waitForBackgroundTasksOnPrint();
|
|
208145
208283
|
}
|
|
208284
|
+
handlePrintMainTurnCompleted(_payload) {
|
|
208285
|
+
return this.session.handlePrintMainTurnCompleted();
|
|
208286
|
+
}
|
|
208146
208287
|
addAdditionalDir(payload) {
|
|
208147
208288
|
return this.session.addAdditionalDir(payload.path, payload.persist);
|
|
208148
208289
|
}
|
|
@@ -208245,6 +208386,9 @@ var init_rpc$1 = __esmMin((() => {
|
|
|
208245
208386
|
async cancelGoal({ agentId, ...payload }) {
|
|
208246
208387
|
return (await this.getAgent(agentId)).cancelGoal(payload);
|
|
208247
208388
|
}
|
|
208389
|
+
async getCronTasks({ agentId, ...payload }) {
|
|
208390
|
+
return (await this.getAgent(agentId)).getCronTasks(payload);
|
|
208391
|
+
}
|
|
208248
208392
|
async getBackgroundOutput({ agentId, ...payload }) {
|
|
208249
208393
|
return (await this.getAgent(agentId)).getBackgroundOutput(payload);
|
|
208250
208394
|
}
|
|
@@ -210037,6 +210181,9 @@ var init_core_impl = __esmMin((() => {
|
|
|
210037
210181
|
waitForBackgroundTasksOnPrint({ sessionId, ...payload }) {
|
|
210038
210182
|
return this.sessionApi(sessionId).waitForBackgroundTasksOnPrint(payload);
|
|
210039
210183
|
}
|
|
210184
|
+
handlePrintMainTurnCompleted({ sessionId, ...payload }) {
|
|
210185
|
+
return this.sessionApi(sessionId).handlePrintMainTurnCompleted(payload);
|
|
210186
|
+
}
|
|
210040
210187
|
addAdditionalDir({ sessionId, ...payload }) {
|
|
210041
210188
|
return this.requireSession(sessionId).addAdditionalDir(payload.path, payload.persist);
|
|
210042
210189
|
}
|
|
@@ -210058,6 +210205,9 @@ var init_core_impl = __esmMin((() => {
|
|
|
210058
210205
|
cancelGoal({ sessionId, ...payload }) {
|
|
210059
210206
|
return Promise.resolve(this.sessionApi(sessionId).cancelGoal(payload));
|
|
210060
210207
|
}
|
|
210208
|
+
getCronTasks({ sessionId, ...payload }) {
|
|
210209
|
+
return Promise.resolve(this.sessionApi(sessionId).getCronTasks(payload));
|
|
210210
|
+
}
|
|
210061
210211
|
async installPlugin(payload) {
|
|
210062
210212
|
await this.pluginsReady;
|
|
210063
210213
|
this.assertPluginsLoaded();
|
|
@@ -216811,25 +216961,29 @@ function mapContentPart(part) {
|
|
|
216811
216961
|
* Build the protocol-shaped `Message.content[]` for one ContextMessage.
|
|
216812
216962
|
*
|
|
216813
216963
|
* Order:
|
|
216814
|
-
* 1. For `tool` role: emit a SINGLE `tool_result` part.
|
|
216815
|
-
*
|
|
216816
|
-
*
|
|
216964
|
+
* 1. For `tool` role: emit a SINGLE `tool_result` part. Plain-text results
|
|
216965
|
+
* keep the historical flattened-text output (most tool messages emit a
|
|
216966
|
+
* single text); a result that carries media parts (image/video/audio —
|
|
216967
|
+
* e.g. ReadMediaFile) passes the raw kosong content-part array through
|
|
216968
|
+
* instead, the same shape the live `tool.result` event stream carries,
|
|
216969
|
+
* so REST consumers can still render the media. `is_error` is taken
|
|
216970
|
+
* from `ContextMessage.isError`.
|
|
216817
216971
|
* 2. For other roles: emit each content part mapped per `mapContentPart`,
|
|
216818
216972
|
* THEN append one `tool_use` part per `ToolCall` (assistant only).
|
|
216819
216973
|
*/
|
|
216820
216974
|
function buildProtocolContent(msg) {
|
|
216821
216975
|
if (msg.role === "tool") {
|
|
216822
216976
|
if (msg.toolCallId === void 0) return msg.content.map((p) => mapContentPart(p));
|
|
216823
|
-
const
|
|
216977
|
+
const output = msg.content.some((p) => p.type === "image_url" || p.type === "video_url" || p.type === "audio_url") ? msg.content : msg.content.map((p) => p.type === "text" ? p.text : "").join("");
|
|
216824
216978
|
return [msg.isError === true ? {
|
|
216825
216979
|
type: "tool_result",
|
|
216826
216980
|
tool_call_id: msg.toolCallId,
|
|
216827
|
-
output
|
|
216981
|
+
output,
|
|
216828
216982
|
is_error: true
|
|
216829
216983
|
} : {
|
|
216830
216984
|
type: "tool_result",
|
|
216831
216985
|
tool_call_id: msg.toolCallId,
|
|
216832
|
-
output
|
|
216986
|
+
output
|
|
216833
216987
|
}];
|
|
216834
216988
|
}
|
|
216835
216989
|
const base = msg.content.map((p) => mapContentPart(p));
|
|
@@ -219521,14 +219675,27 @@ var Session = class {
|
|
|
219521
219675
|
/**
|
|
219522
219676
|
* Block until every still-running background task (across all agents in this
|
|
219523
219677
|
* session) reaches a terminal state. Used by `kimi -p` after the main agent's
|
|
219524
|
-
* turn finishes when
|
|
219525
|
-
*
|
|
219526
|
-
*
|
|
219678
|
+
* turn finishes when the resolved print background mode is `'drain'`
|
|
219679
|
+
* (`print_background_mode = "drain"`, or the legacy `keep_alive_on_exit = true`
|
|
219680
|
+
* fallback), so background subagents get a chance to complete before the process
|
|
219681
|
+
* exits. No-op in other modes. Bounded by `background.print_wait_ceiling_s`.
|
|
219527
219682
|
*/
|
|
219528
219683
|
async waitForBackgroundTasksOnPrint() {
|
|
219529
219684
|
this.ensureOpen();
|
|
219530
219685
|
await this.rpc.waitForBackgroundTasksOnPrint({ sessionId: this.id });
|
|
219531
219686
|
}
|
|
219687
|
+
/**
|
|
219688
|
+
* Used by `kimi -p` after the main agent's turn ends with `reason ===
|
|
219689
|
+
* 'completed'`. Returns `'finish'` when the run may exit, or `'continue'` when
|
|
219690
|
+
* the caller must keep the session alive so a background-task completion can
|
|
219691
|
+
* steer the main agent into a new turn. Policy is selected by
|
|
219692
|
+
* `background.print_background_mode` (`'exit' | 'drain' | 'steer'`); when unset
|
|
219693
|
+
* it falls back to the legacy `keep_alive_on_exit` mapping (`true ⇒ 'drain'`).
|
|
219694
|
+
*/
|
|
219695
|
+
async handlePrintMainTurnCompleted() {
|
|
219696
|
+
this.ensureOpen();
|
|
219697
|
+
return this.rpc.handlePrintMainTurnCompleted({ sessionId: this.id });
|
|
219698
|
+
}
|
|
219532
219699
|
async createGoal(input) {
|
|
219533
219700
|
this.ensureOpen();
|
|
219534
219701
|
return this.rpc.createGoal({
|
|
@@ -219552,6 +219719,15 @@ var Session = class {
|
|
|
219552
219719
|
this.ensureOpen();
|
|
219553
219720
|
return this.rpc.cancelGoal({ sessionId: this.id });
|
|
219554
219721
|
}
|
|
219722
|
+
/**
|
|
219723
|
+
* Enumerate the cron tasks scheduled in this session. Hosts running a
|
|
219724
|
+
* bounded session lifetime (e.g. `kimi -p`) poll this to decide whether
|
|
219725
|
+
* pending scheduled work still needs the process alive.
|
|
219726
|
+
*/
|
|
219727
|
+
async getCronTasks() {
|
|
219728
|
+
this.ensureOpen();
|
|
219729
|
+
return this.rpc.getCronTasks({ sessionId: this.id });
|
|
219730
|
+
}
|
|
219555
219731
|
async listMcpServers() {
|
|
219556
219732
|
this.ensureOpen();
|
|
219557
219733
|
return this.rpc.listMcpServers({ sessionId: this.id });
|
|
@@ -220414,6 +220590,9 @@ var SDKRpcClientBase = class {
|
|
|
220414
220590
|
async waitForBackgroundTasksOnPrint(input) {
|
|
220415
220591
|
return (await this.getRpc()).waitForBackgroundTasksOnPrint({ sessionId: input.sessionId });
|
|
220416
220592
|
}
|
|
220593
|
+
async handlePrintMainTurnCompleted(input) {
|
|
220594
|
+
return (await this.getRpc()).handlePrintMainTurnCompleted({ sessionId: input.sessionId });
|
|
220595
|
+
}
|
|
220417
220596
|
async createGoal(input) {
|
|
220418
220597
|
return (await this.getRpc()).createGoal({
|
|
220419
220598
|
sessionId: input.sessionId,
|
|
@@ -220446,6 +220625,12 @@ var SDKRpcClientBase = class {
|
|
|
220446
220625
|
agentId: this.interactiveAgentId
|
|
220447
220626
|
});
|
|
220448
220627
|
}
|
|
220628
|
+
async getCronTasks(input) {
|
|
220629
|
+
return (await this.getRpc()).getCronTasks({
|
|
220630
|
+
sessionId: input.sessionId,
|
|
220631
|
+
agentId: this.interactiveAgentId
|
|
220632
|
+
});
|
|
220633
|
+
}
|
|
220449
220634
|
async listMcpServers(input) {
|
|
220450
220635
|
return (await this.getRpc()).listMcpServers({ sessionId: input.sessionId });
|
|
220451
220636
|
}
|
|
@@ -220774,7 +220959,7 @@ function capabilityToStrings(capability) {
|
|
|
220774
220959
|
if (capability.audio_in) caps.push("audio_in");
|
|
220775
220960
|
if (capability.thinking) caps.push("thinking");
|
|
220776
220961
|
if (capability.tool_use) caps.push("tool_use");
|
|
220777
|
-
if (capability.
|
|
220962
|
+
if (capability.dynamically_loaded_tools === true) caps.push("dynamically_loaded_tools");
|
|
220778
220963
|
return caps.length > 0 ? caps : void 0;
|
|
220779
220964
|
}
|
|
220780
220965
|
/** Builds a kimi-code model alias from a normalized catalog model. */
|
|
@@ -303679,7 +303864,7 @@ const REMOVE_CONFIRM_REMOVE = "remove";
|
|
|
303679
303864
|
const INSTALL_TRUST_EXIT = "exit";
|
|
303680
303865
|
const INSTALL_TRUST_TRUST = "trust";
|
|
303681
303866
|
const ELLIPSIS$6 = "…";
|
|
303682
|
-
const WEB_BRIDGE_URL = "https://www.kimi.com/features/webbridge";
|
|
303867
|
+
const WEB_BRIDGE_URL = "https://www.kimi.com/features/webbridge#local-agent";
|
|
303683
303868
|
const WEB_BRIDGE_ENTRY = {
|
|
303684
303869
|
id: "kimi-webbridge",
|
|
303685
303870
|
displayName: "Kimi WebBridge",
|
|
@@ -370845,7 +371030,7 @@ async function runHeadlessGoal(session, goal, model, outputFormat, stdout, stder
|
|
|
370845
371030
|
if (event.type === "goal.updated" && event.agentId === "main" && event.change?.kind === "completion" && event.snapshot !== null) completedSnapshot = event.snapshot;
|
|
370846
371031
|
});
|
|
370847
371032
|
try {
|
|
370848
|
-
await runPromptTurn(session, goal.objective, outputFormat, stdout, stderr
|
|
371033
|
+
await runPromptTurn(session, goal.objective, outputFormat, stdout, stderr);
|
|
370849
371034
|
} finally {
|
|
370850
371035
|
unsubscribeGoalEvents();
|
|
370851
371036
|
const snapshot = completedSnapshot ?? (await session.getGoal()).goal;
|
|
@@ -370972,17 +371157,26 @@ function signalExitCode(signal) {
|
|
|
370972
371157
|
if (signal === "SIGHUP") return 129;
|
|
370973
371158
|
return 143;
|
|
370974
371159
|
}
|
|
370975
|
-
function runPromptTurn(session, prompt, outputFormat, stdout, stderr
|
|
371160
|
+
function runPromptTurn(session, prompt, outputFormat, stdout, stderr) {
|
|
370976
371161
|
let activeTurnId;
|
|
370977
371162
|
let activeAgentId;
|
|
370978
|
-
let latestStartedTurnId;
|
|
370979
371163
|
const outputWriter = outputFormat === "stream-json" ? new PromptJsonWriter(stdout) : new PromptTranscriptWriter(stdout, stderr);
|
|
370980
371164
|
let settled = false;
|
|
370981
371165
|
let unsubscribe;
|
|
371166
|
+
let keepAliveTimer;
|
|
371167
|
+
const holdEventLoop = () => {
|
|
371168
|
+
keepAliveTimer ??= setInterval(() => {}, 6e4);
|
|
371169
|
+
};
|
|
371170
|
+
const releaseEventLoop = () => {
|
|
371171
|
+
if (keepAliveTimer === void 0) return;
|
|
371172
|
+
clearInterval(keepAliveTimer);
|
|
371173
|
+
keepAliveTimer = void 0;
|
|
371174
|
+
};
|
|
370982
371175
|
return new Promise((resolve, reject) => {
|
|
370983
371176
|
const finish = (error) => {
|
|
370984
371177
|
if (settled) return;
|
|
370985
371178
|
settled = true;
|
|
371179
|
+
releaseEventLoop();
|
|
370986
371180
|
unsubscribe?.();
|
|
370987
371181
|
outputWriter.finish();
|
|
370988
371182
|
if (error !== void 0) {
|
|
@@ -370991,21 +371185,39 @@ function runPromptTurn(session, prompt, outputFormat, stdout, stderr, waitForGoa
|
|
|
370991
371185
|
}
|
|
370992
371186
|
resolve();
|
|
370993
371187
|
};
|
|
371188
|
+
const evaluateRunCompletion = async () => {
|
|
371189
|
+
try {
|
|
371190
|
+
const { goal } = await session.getGoal();
|
|
371191
|
+
if (settled || activeTurnId !== void 0) return;
|
|
371192
|
+
if (goal?.status === "active") {
|
|
371193
|
+
holdEventLoop();
|
|
371194
|
+
return;
|
|
371195
|
+
}
|
|
371196
|
+
const { tasks } = await session.getCronTasks();
|
|
371197
|
+
if (settled || activeTurnId !== void 0) return;
|
|
371198
|
+
if (tasks.some((task) => task.nextFireAt !== null)) {
|
|
371199
|
+
holdEventLoop();
|
|
371200
|
+
return;
|
|
371201
|
+
}
|
|
371202
|
+
await finishCompletedTurn();
|
|
371203
|
+
} catch (error) {
|
|
371204
|
+
finish(error instanceof Error ? error : new Error(String(error)));
|
|
371205
|
+
}
|
|
371206
|
+
};
|
|
370994
371207
|
unsubscribe = session.onEvent((event) => {
|
|
370995
371208
|
if (event.type === "error") {
|
|
370996
371209
|
if (event.agentId !== PROMPT_MAIN_AGENT_ID) return;
|
|
370997
371210
|
finish(/* @__PURE__ */ new Error(`${event.code}: ${event.message}`));
|
|
370998
371211
|
return;
|
|
370999
371212
|
}
|
|
371000
|
-
if (event.type === "turn.started"
|
|
371213
|
+
if (event.type === "turn.started") {
|
|
371001
371214
|
if (event.agentId !== PROMPT_MAIN_AGENT_ID) return;
|
|
371002
371215
|
activeTurnId = event.turnId;
|
|
371003
371216
|
activeAgentId = event.agentId;
|
|
371004
|
-
latestStartedTurnId = event.turnId;
|
|
371005
371217
|
return;
|
|
371006
371218
|
}
|
|
371007
|
-
if (
|
|
371008
|
-
|
|
371219
|
+
if (event.type === "goal.updated" && event.agentId === PROMPT_MAIN_AGENT_ID && activeTurnId === void 0 && event.snapshot !== null && event.snapshot.status !== "active") {
|
|
371220
|
+
evaluateRunCompletion();
|
|
371009
371221
|
return;
|
|
371010
371222
|
}
|
|
371011
371223
|
if (activeTurnId === void 0 || activeAgentId === void 0 || !hasTurnId(event) || event.turnId !== activeTurnId || event.agentId !== activeAgentId) return;
|
|
@@ -371042,23 +371254,9 @@ function runPromptTurn(session, prompt, outputFormat, stdout, stderr, waitForGoa
|
|
|
371042
371254
|
case "turn.ended":
|
|
371043
371255
|
if (event.reason === "completed") {
|
|
371044
371256
|
outputWriter.flushAssistant();
|
|
371045
|
-
|
|
371046
|
-
|
|
371047
|
-
|
|
371048
|
-
activeAgentId = void 0;
|
|
371049
|
-
(async () => {
|
|
371050
|
-
try {
|
|
371051
|
-
const { goal } = await session.getGoal();
|
|
371052
|
-
if (activeTurnId !== void 0 || latestStartedTurnId !== completedTurnId) return;
|
|
371053
|
-
if (goal?.status === "active") return;
|
|
371054
|
-
await finishCompletedTurn();
|
|
371055
|
-
} catch (error) {
|
|
371056
|
-
finish(error instanceof Error ? error : new Error(String(error)));
|
|
371057
|
-
}
|
|
371058
|
-
})();
|
|
371059
|
-
return;
|
|
371060
|
-
}
|
|
371061
|
-
finishCompletedTurn();
|
|
371257
|
+
activeTurnId = void 0;
|
|
371258
|
+
activeAgentId = void 0;
|
|
371259
|
+
evaluateRunCompletion();
|
|
371062
371260
|
return;
|
|
371063
371261
|
}
|
|
371064
371262
|
finish(new Error(formatTurnEndedFailure(event)));
|
|
@@ -371081,7 +371279,6 @@ function runPromptTurn(session, prompt, outputFormat, stdout, stderr, waitForGoa
|
|
|
371081
371279
|
case "subagent.started":
|
|
371082
371280
|
case "subagent.suspended":
|
|
371083
371281
|
case "tool.list.updated":
|
|
371084
|
-
case "turn.started":
|
|
371085
371282
|
case "turn.step.completed":
|
|
371086
371283
|
case "warning": return;
|
|
371087
371284
|
}
|
|
@@ -371092,9 +371289,12 @@ function runPromptTurn(session, prompt, outputFormat, stdout, stderr, waitForGoa
|
|
|
371092
371289
|
async function finishCompletedTurn() {
|
|
371093
371290
|
outputWriter.flushAssistant();
|
|
371094
371291
|
try {
|
|
371095
|
-
await session.
|
|
371292
|
+
if (await session.handlePrintMainTurnCompleted() === "continue") {
|
|
371293
|
+
holdEventLoop();
|
|
371294
|
+
return;
|
|
371295
|
+
}
|
|
371096
371296
|
} catch (error) {
|
|
371097
|
-
log.warn("
|
|
371297
|
+
log.warn("handlePrintMainTurnCompleted failed", { error });
|
|
371098
371298
|
}
|
|
371099
371299
|
finish();
|
|
371100
371300
|
}
|