@moonshot-ai/kimi-code 0.20.2 → 0.20.3
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 +1144 -1052
- package/dist-web/assets/{CodeBlockNode-Cj5GCBwy.js → CodeBlockNode-QzsUDFhj.js} +1 -1
- package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-BZQYvYGg.js → CodeBlockShell.vue_vue_type_style_index_0_lang-COQWnG7I.js} +1 -1
- package/dist-web/assets/{Tooltip-FXn3ewBz.js → Tooltip-DjdYJu5x.js} +1 -1
- package/dist-web/assets/{arc---yONsFG.js → arc-BgPs0rMd.js} +1 -1
- package/dist-web/assets/{architectureDiagram-3BPJPVTR-Cu5NFSbj.js → architectureDiagram-3BPJPVTR-D0xfzSKA.js} +1 -1
- package/dist-web/assets/{blockDiagram-GPEHLZMM-eAkllecr.js → blockDiagram-GPEHLZMM-jtPOGuGl.js} +1 -1
- package/dist-web/assets/{c4Diagram-AAUBKEIU-BcJyf2yX.js → c4Diagram-AAUBKEIU-BPIjsoUA.js} +1 -1
- package/dist-web/assets/channel-DnBCccMg.js +1 -0
- package/dist-web/assets/{chunk-2J33WTMH-DzpuDCg4.js → chunk-2J33WTMH-ChbTHkcK.js} +1 -1
- package/dist-web/assets/{chunk-4BX2VUAB-DPF55Xbc.js → chunk-4BX2VUAB-br1aQrtt.js} +1 -1
- package/dist-web/assets/{chunk-55IACEB6-Ct2k4oQF.js → chunk-55IACEB6-CoLSy_-M.js} +1 -1
- package/dist-web/assets/{chunk-727SXJPM-DcWnL_ZJ.js → chunk-727SXJPM-Ch73eH6y.js} +1 -1
- package/dist-web/assets/{chunk-AQP2D5EJ-2N1ZTMho.js → chunk-AQP2D5EJ-7Y0GIirZ.js} +1 -1
- package/dist-web/assets/{chunk-FMBD7UC4-jNBVe-u1.js → chunk-FMBD7UC4-D7IRCdHF.js} +1 -1
- package/dist-web/assets/{chunk-ND2GUHAM-BTBgmjVQ.js → chunk-ND2GUHAM-WfKpgeWa.js} +1 -1
- package/dist-web/assets/{chunk-QZHKN3VN-xUCxw3pg.js → chunk-QZHKN3VN-BgQBqGri.js} +1 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-DezksBKS.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-DezksBKS.js +1 -0
- package/dist-web/assets/{cose-bilkent-S5V4N54A-ByEZXDA-.js → cose-bilkent-S5V4N54A-Du7Q4b9R.js} +1 -1
- package/dist-web/assets/{dagre-BM42HDAG-BSfstE2-.js → dagre-BM42HDAG-BBLoya79.js} +1 -1
- package/dist-web/assets/{diagram-2AECGRRQ-CpI86-tI.js → diagram-2AECGRRQ-kByHrOvZ.js} +1 -1
- package/dist-web/assets/{diagram-5GNKFQAL-B4WYOJbp.js → diagram-5GNKFQAL-Dnkgbduh.js} +1 -1
- package/dist-web/assets/{diagram-KO2AKTUF-dmm87H0J.js → diagram-KO2AKTUF-CKfrJMO5.js} +1 -1
- package/dist-web/assets/{diagram-LMA3HP47-CAFHWRvJ.js → diagram-LMA3HP47-D3GoTx0o.js} +1 -1
- package/dist-web/assets/{diagram-OG6HWLK6-CvbELbqm.js → diagram-OG6HWLK6-B057HNTB.js} +1 -1
- package/dist-web/assets/{erDiagram-TEJ5UH35-BATGAYdA.js → erDiagram-TEJ5UH35-CMFH1-0F.js} +1 -1
- package/dist-web/assets/{flowDiagram-I6XJVG4X-BjHCXPMa.js → flowDiagram-I6XJVG4X-Ue7D_If3.js} +1 -1
- package/dist-web/assets/{ganttDiagram-6RSMTGT7-DyP4c3YT.js → ganttDiagram-6RSMTGT7-C3vvEQsr.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-PVQCEYII-NzukZ15I.js → gitGraphDiagram-PVQCEYII-D-L62M3k.js} +1 -1
- package/dist-web/assets/index-BOozFshs.js +284 -0
- package/dist-web/assets/{index-D4Er4P8I.js → index-DRCzCVsJ.js} +1 -1
- package/dist-web/assets/{index-Cfg9noDi.js → index-YYCI79IV.js} +2 -2
- package/dist-web/assets/{index-BYnLiw5r.css → index-gP3qbaq1.css} +1 -1
- package/dist-web/assets/{index10-C4yIRdle.js → index10-C0e1uOHF.js} +1 -1
- package/dist-web/assets/{index11-CqNiMTbJ.js → index11-qzoItZ5X.js} +2 -2
- package/dist-web/assets/{index5-DKdkj0GC.js → index5-BD3g_HrT.js} +1 -1
- package/dist-web/assets/{index6-DsK3MiZT.js → index6-BsyLzjzN.js} +1 -1
- package/dist-web/assets/{index7-DHshPD9x.js → index7-BU9c3C-0.js} +1 -1
- package/dist-web/assets/{index8-CeUCBmKU.js → index8-DC4X3Xlc.js} +2 -2
- package/dist-web/assets/{infoDiagram-5YYISTIA-6n_F_-MA.js → infoDiagram-5YYISTIA-DuKrZwyg.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-CoaeNeqj.js → ishikawaDiagram-YF4QCWOH-DvYYK586.js} +1 -1
- package/dist-web/assets/{journeyDiagram-JHISSGLW-Bi-m1_1y.js → journeyDiagram-JHISSGLW-CijMU22u.js} +1 -1
- package/dist-web/assets/{kanban-definition-UN3LZRKU-DHxtNMaD.js → kanban-definition-UN3LZRKU-BmaUhICc.js} +1 -1
- package/dist-web/assets/{linear-CgHyf5UH.js → linear-C5DmXyYK.js} +1 -1
- package/dist-web/assets/{mermaid.core-CtXm064v.js → mermaid.core-CxStNiKR.js} +4 -4
- package/dist-web/assets/{mindmap-definition-RKZ34NQL-ClpCUmIA.js → mindmap-definition-RKZ34NQL-CH1ykt4a.js} +1 -1
- package/dist-web/assets/{pieDiagram-4H26LBE5-DvYtw1Bp.js → pieDiagram-4H26LBE5-D812Mhsu.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-W4KKPZXB-Dle7c6-0.js → quadrantDiagram-W4KKPZXB-WyDSXdZ7.js} +1 -1
- package/dist-web/assets/{requirementDiagram-4Y6WPE33--X5AnAhp.js → requirementDiagram-4Y6WPE33-CzaQOU4P.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-5OEKKPKP-BUszdT9f.js → sankeyDiagram-5OEKKPKP-D2mgS_7C.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-3UESZ5HK-CDwqGrfV.js → sequenceDiagram-3UESZ5HK-CuoLev25.js} +1 -1
- package/dist-web/assets/{stateDiagram-AJRCARHV-Kmd6YXse.js → stateDiagram-AJRCARHV-BoTsuaL9.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-8LYkXLp8.js +1 -0
- package/dist-web/assets/{timeline-definition-PNZ67QCA-o-RAswWS.js → timeline-definition-PNZ67QCA-DkLWuglL.js} +1 -1
- package/dist-web/assets/{vennDiagram-CIIHVFJN-DljQ_s6w.js → vennDiagram-CIIHVFJN-DYjvU6dg.js} +1 -1
- package/dist-web/assets/{vue.runtime.esm-bundler-BP7sjueK.js → vue.runtime.esm-bundler-C_eIrEdV.js} +1 -1
- package/dist-web/assets/{wardley-L42UT6IY-CW9wuVhK.js → wardley-L42UT6IY-DSIStv05.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-YWT4CUSO-Bh0wtRMV.js → wardleyDiagram-YWT4CUSO-DSPJWT6D.js} +1 -1
- package/dist-web/assets/{xychartDiagram-2RQKCTM6-BAjJ0sMH.js → xychartDiagram-2RQKCTM6-C0OPS_b1.js} +1 -1
- package/dist-web/index.html +3 -3
- package/package.json +3 -3
- package/dist-web/assets/channel-BTxFVrej.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-B47dzfoS.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-B47dzfoS.js +0 -1
- package/dist-web/assets/index-CCjot4qV.js +0 -284
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-CvgWdsVg.js +0 -1
package/dist/main.mjs
CHANGED
|
@@ -54411,7 +54411,7 @@ function toKimiErrorPayload(error) {
|
|
|
54411
54411
|
const code = error.statusCode === 429 ? ErrorCodes.PROVIDER_RATE_LIMIT : error.statusCode === 401 ? ErrorCodes.PROVIDER_AUTH_ERROR : ErrorCodes.PROVIDER_API_ERROR;
|
|
54412
54412
|
return {
|
|
54413
54413
|
code,
|
|
54414
|
-
message: error.message,
|
|
54414
|
+
message: sanitizeStatusErrorMessage(error.message),
|
|
54415
54415
|
name: error.name,
|
|
54416
54416
|
details: {
|
|
54417
54417
|
statusCode: error.statusCode,
|
|
@@ -54455,6 +54455,19 @@ function toKimiErrorPayload(error) {
|
|
|
54455
54455
|
};
|
|
54456
54456
|
}
|
|
54457
54457
|
/**
|
|
54458
|
+
* Provider status errors occasionally carry an HTML body instead of a
|
|
54459
|
+
* structured message (for example, nginx returning
|
|
54460
|
+
* "413 <html><head><title>413 Request Entity Too Large</title>...</html>").
|
|
54461
|
+
* Extract the `<title>` when present so the wire message is human readable,
|
|
54462
|
+
* and strip carriage returns so the text renders cleanly in terminals — a
|
|
54463
|
+
* trailing `\r` combined with line-end padding would otherwise overwrite
|
|
54464
|
+
* the whole line. The original HTML remains available in logs and `details`.
|
|
54465
|
+
*/
|
|
54466
|
+
function sanitizeStatusErrorMessage(message) {
|
|
54467
|
+
const extracted = /<title[^>]*>([\s\S]*?)<\/title>/i.exec(message)?.[1]?.trim();
|
|
54468
|
+
return (extracted !== void 0 && extracted.length > 0 ? extracted : message).replaceAll("\r", "");
|
|
54469
|
+
}
|
|
54470
|
+
/**
|
|
54458
54471
|
* Rehydrate a KimiErrorPayload into a KimiError. Used by SDK boundary code
|
|
54459
54472
|
* receiving errors over RPC to re-surface them with a real class so
|
|
54460
54473
|
* in-process consumers can still use `instanceof`.
|
|
@@ -60771,6 +60784,12 @@ const BackgroundConfigSchema = object({
|
|
|
60771
60784
|
killGracePeriodMs: number$1().int().min(0).optional(),
|
|
60772
60785
|
printWaitCeilingS: number$1().int().min(1).optional()
|
|
60773
60786
|
});
|
|
60787
|
+
const ModelCatalogConfigSchema = object({
|
|
60788
|
+
/** Interval (ms) between automatic provider-model refreshes. `0` disables. */
|
|
60789
|
+
refreshIntervalMs: number$1().int().min(0).optional(),
|
|
60790
|
+
/** Refresh once shortly after the daemon starts. */
|
|
60791
|
+
refreshOnStart: boolean$1().optional()
|
|
60792
|
+
});
|
|
60774
60793
|
const ExperimentalConfigSchema = record(string(), boolean$1());
|
|
60775
60794
|
const HookDefSchema = object({
|
|
60776
60795
|
event: _enum(HOOK_EVENT_TYPES),
|
|
@@ -60851,6 +60870,7 @@ const KimiConfigSchema = object({
|
|
|
60851
60870
|
extraSkillDirs: array(string()).optional(),
|
|
60852
60871
|
loopControl: LoopControlSchema.optional(),
|
|
60853
60872
|
background: BackgroundConfigSchema.optional(),
|
|
60873
|
+
modelCatalog: ModelCatalogConfigSchema.optional(),
|
|
60854
60874
|
experimental: ExperimentalConfigSchema.optional(),
|
|
60855
60875
|
telemetry: boolean$1().optional(),
|
|
60856
60876
|
raw: record(string(), unknown()).optional()
|
|
@@ -60861,6 +60881,7 @@ const ThinkingConfigPatchSchema = ThinkingConfigSchema.partial();
|
|
|
60861
60881
|
const PermissionConfigPatchSchema = PermissionConfigSchema.partial();
|
|
60862
60882
|
const LoopControlPatchSchema = LoopControlSchema.partial();
|
|
60863
60883
|
const BackgroundConfigPatchSchema = BackgroundConfigSchema.partial();
|
|
60884
|
+
const ModelCatalogConfigPatchSchema = ModelCatalogConfigSchema.partial();
|
|
60864
60885
|
const ExperimentalConfigPatchSchema = ExperimentalConfigSchema;
|
|
60865
60886
|
const MoonshotServiceConfigPatchSchema = MoonshotServiceConfigSchema.partial();
|
|
60866
60887
|
const ServicesConfigPatchSchema = object({
|
|
@@ -60885,6 +60906,7 @@ const KimiConfigPatchSchema = object({
|
|
|
60885
60906
|
extraSkillDirs: array(string()).optional(),
|
|
60886
60907
|
loopControl: LoopControlPatchSchema.optional(),
|
|
60887
60908
|
background: BackgroundConfigPatchSchema.optional(),
|
|
60909
|
+
modelCatalog: ModelCatalogConfigPatchSchema.optional(),
|
|
60888
60910
|
experimental: ExperimentalConfigPatchSchema.optional(),
|
|
60889
60911
|
telemetry: boolean$1().optional()
|
|
60890
60912
|
}).strict();
|
|
@@ -72070,28 +72092,31 @@ var FullCompaction = class {
|
|
|
72070
72092
|
tokensAfter
|
|
72071
72093
|
};
|
|
72072
72094
|
this.agent.telemetry.track("compaction_finished", {
|
|
72073
|
-
|
|
72074
|
-
|
|
72095
|
+
source: data.source,
|
|
72096
|
+
tokens_before: result.tokensBefore,
|
|
72097
|
+
tokens_after: result.tokensAfter,
|
|
72075
72098
|
duration_ms: Date.now() - startedAt,
|
|
72076
|
-
|
|
72077
|
-
retryCount,
|
|
72099
|
+
compacted_count: result.compactedCount,
|
|
72100
|
+
retry_count: retryCount,
|
|
72078
72101
|
round,
|
|
72079
|
-
|
|
72080
|
-
...usage
|
|
72081
|
-
|
|
72102
|
+
thinking_level: this.agent.config.thinkingLevel,
|
|
72103
|
+
...usage === null ? {} : {
|
|
72104
|
+
input_tokens: inputTotal(usage),
|
|
72105
|
+
output_tokens: usage.output
|
|
72106
|
+
}
|
|
72082
72107
|
});
|
|
72083
72108
|
this.agent.context.applyCompaction(result);
|
|
72084
72109
|
return result;
|
|
72085
72110
|
} catch (error) {
|
|
72086
72111
|
if (isAbortError$3(error)) return;
|
|
72087
72112
|
this.agent.telemetry.track("compaction_failed", {
|
|
72088
|
-
|
|
72089
|
-
tokensBefore,
|
|
72113
|
+
source: data.source,
|
|
72114
|
+
tokens_before: tokensBefore,
|
|
72090
72115
|
duration_ms: Date.now() - startedAt,
|
|
72091
72116
|
round,
|
|
72092
|
-
retryCount,
|
|
72093
|
-
|
|
72094
|
-
|
|
72117
|
+
retry_count: retryCount,
|
|
72118
|
+
thinking_level: this.agent.config.thinkingLevel,
|
|
72119
|
+
error_type: error instanceof Error ? error.name : "Unknown"
|
|
72095
72120
|
});
|
|
72096
72121
|
if (isKimiError(error) && error.code === ErrorCodes.AUTH_LOGIN_REQUIRED) throw error;
|
|
72097
72122
|
throw new KimiError(ErrorCodes.COMPACTION_FAILED, String(error), { cause: error });
|
|
@@ -72179,15 +72204,21 @@ var MicroCompaction = class {
|
|
|
72179
72204
|
const tokensBefore = rawContextTokens - previousEffect.truncatedToolResultTokensBefore + previousEffect.truncatedToolResultTokensAfter;
|
|
72180
72205
|
const tokensAfter = rawContextTokens - effect.truncatedToolResultTokensBefore + effect.truncatedToolResultTokensAfter;
|
|
72181
72206
|
this.agent.telemetry.track("micro_compaction_finished", {
|
|
72182
|
-
|
|
72183
|
-
|
|
72184
|
-
|
|
72185
|
-
|
|
72207
|
+
keep_recent_messages: config.keepRecentMessages,
|
|
72208
|
+
min_content_tokens: config.minContentTokens,
|
|
72209
|
+
cache_missed_threshold_ms: config.cacheMissedThresholdMs,
|
|
72210
|
+
truncated_marker: config.truncatedMarker,
|
|
72211
|
+
min_context_usage_ratio: config.minContextUsageRatio,
|
|
72212
|
+
truncated_tool_result_count: effect.truncatedToolResultCount,
|
|
72213
|
+
truncated_tool_result_tokens_before: effect.truncatedToolResultTokensBefore,
|
|
72214
|
+
truncated_tool_result_tokens_after: effect.truncatedToolResultTokensAfter,
|
|
72215
|
+
tokens_before: tokensBefore,
|
|
72216
|
+
tokens_after: tokensAfter,
|
|
72186
72217
|
previous_cutoff: previousCutoff,
|
|
72187
72218
|
cutoff: nextCutoff,
|
|
72188
72219
|
message_count: history.length,
|
|
72189
72220
|
cache_age_ms: cacheAgeMs,
|
|
72190
|
-
|
|
72221
|
+
thinking_level: this.agent.config.thinkingLevel
|
|
72191
72222
|
});
|
|
72192
72223
|
}
|
|
72193
72224
|
}
|
|
@@ -89424,6 +89455,29 @@ function validateToolArgs(validator, args) {
|
|
|
89424
89455
|
return errors.map((error) => formatValidationError(error)).join("; ");
|
|
89425
89456
|
}
|
|
89426
89457
|
//#endregion
|
|
89458
|
+
//#region ../../packages/agent-core/src/loop/tool-args-parse.ts
|
|
89459
|
+
function parseToolCallArguments$1(raw) {
|
|
89460
|
+
if (raw === null || raw.length === 0) return {
|
|
89461
|
+
success: true,
|
|
89462
|
+
data: {},
|
|
89463
|
+
parseFailed: false
|
|
89464
|
+
};
|
|
89465
|
+
try {
|
|
89466
|
+
return {
|
|
89467
|
+
success: true,
|
|
89468
|
+
data: JSON.parse(raw),
|
|
89469
|
+
parseFailed: false
|
|
89470
|
+
};
|
|
89471
|
+
} catch (error) {
|
|
89472
|
+
return {
|
|
89473
|
+
success: true,
|
|
89474
|
+
data: {},
|
|
89475
|
+
parseFailed: true,
|
|
89476
|
+
error: errorMessage$5(error)
|
|
89477
|
+
};
|
|
89478
|
+
}
|
|
89479
|
+
}
|
|
89480
|
+
//#endregion
|
|
89427
89481
|
//#region ../../packages/agent-core/src/loop/tool-scheduler.ts
|
|
89428
89482
|
/**
|
|
89429
89483
|
* Stateful execution scheduler for tool calls in one model step.
|
|
@@ -89504,7 +89558,7 @@ async function runToolCallBatch(step, response) {
|
|
|
89504
89558
|
...step,
|
|
89505
89559
|
toolCalls: response.toolCalls
|
|
89506
89560
|
};
|
|
89507
|
-
const calls = response.toolCalls.map((toolCall) => preflightToolCall(step
|
|
89561
|
+
const calls = response.toolCalls.map((toolCall) => preflightToolCall(step, toolCall));
|
|
89508
89562
|
const scheduler = new ToolScheduler();
|
|
89509
89563
|
const pendingResults = [];
|
|
89510
89564
|
let stopTurn = false;
|
|
@@ -89541,25 +89595,23 @@ async function runToolCallBatch(step, response) {
|
|
|
89541
89595
|
* Provider-order validation pass. It does not run hooks, spawn tools, or write
|
|
89542
89596
|
* events. Validator compilation may populate the local cache.
|
|
89543
89597
|
*/
|
|
89544
|
-
function preflightToolCall(
|
|
89598
|
+
function preflightToolCall(step, toolCall) {
|
|
89545
89599
|
const toolName = toolCall.name;
|
|
89546
89600
|
const parsedArgs = parseToolCallArguments$1(toolCall.arguments);
|
|
89547
|
-
const
|
|
89548
|
-
const tool = tools?.find((candidate) => candidate.name === toolName);
|
|
89601
|
+
const tool = step.tools?.find((candidate) => candidate.name === toolName);
|
|
89549
89602
|
if (tool === void 0) return {
|
|
89550
89603
|
kind: "rejected",
|
|
89551
89604
|
toolCall,
|
|
89552
89605
|
toolName,
|
|
89553
|
-
args,
|
|
89606
|
+
args: parsedArgs.data,
|
|
89554
89607
|
output: `Tool "${toolName}" not found`
|
|
89555
89608
|
};
|
|
89556
|
-
if (
|
|
89557
|
-
kind: "rejected",
|
|
89558
|
-
toolCall,
|
|
89609
|
+
if (parsedArgs.parseFailed) step.log?.debug("tool args JSON parse failed", {
|
|
89559
89610
|
toolName,
|
|
89560
|
-
|
|
89561
|
-
|
|
89562
|
-
|
|
89611
|
+
toolCallId: toolCall.id,
|
|
89612
|
+
rawLength: toolCall.arguments?.length ?? 0,
|
|
89613
|
+
error: parsedArgs.error
|
|
89614
|
+
});
|
|
89563
89615
|
const validationError = validateExecutableToolArgs(tool, parsedArgs.data);
|
|
89564
89616
|
if (validationError !== null) return {
|
|
89565
89617
|
kind: "rejected",
|
|
@@ -89576,23 +89628,6 @@ function preflightToolCall(tools, toolCall) {
|
|
|
89576
89628
|
args: parsedArgs.data
|
|
89577
89629
|
};
|
|
89578
89630
|
}
|
|
89579
|
-
function parseToolCallArguments$1(raw) {
|
|
89580
|
-
if (raw === null || raw.length === 0) return {
|
|
89581
|
-
success: true,
|
|
89582
|
-
data: {}
|
|
89583
|
-
};
|
|
89584
|
-
try {
|
|
89585
|
-
return {
|
|
89586
|
-
success: true,
|
|
89587
|
-
data: JSON.parse(raw)
|
|
89588
|
-
};
|
|
89589
|
-
} catch (error) {
|
|
89590
|
-
return {
|
|
89591
|
-
success: false,
|
|
89592
|
-
error: errorMessage$5(error)
|
|
89593
|
-
};
|
|
89594
|
-
}
|
|
89595
|
-
}
|
|
89596
89631
|
function validateExecutableToolArgs(tool, args) {
|
|
89597
89632
|
let validator = validators.get(tool);
|
|
89598
89633
|
if (validator === void 0) try {
|
|
@@ -90972,6 +91007,39 @@ const patchConfigRequestSchema = object({
|
|
|
90972
91007
|
telemetry: boolean$1().optional()
|
|
90973
91008
|
});
|
|
90974
91009
|
//#endregion
|
|
91010
|
+
//#region ../../packages/protocol/src/modelCatalog.ts
|
|
91011
|
+
const modelCatalogItemSchema = object({
|
|
91012
|
+
provider: string().min(1),
|
|
91013
|
+
model: string().min(1),
|
|
91014
|
+
display_name: string().min(1).optional(),
|
|
91015
|
+
max_context_size: number$1().int().min(1),
|
|
91016
|
+
capabilities: array(string()).optional()
|
|
91017
|
+
});
|
|
91018
|
+
const providerCatalogStatusSchema = _enum([
|
|
91019
|
+
"connected",
|
|
91020
|
+
"error",
|
|
91021
|
+
"unconfigured"
|
|
91022
|
+
]);
|
|
91023
|
+
const providerCatalogItemSchema = object({
|
|
91024
|
+
id: string().min(1),
|
|
91025
|
+
type: string().min(1),
|
|
91026
|
+
base_url: string().min(1).optional(),
|
|
91027
|
+
default_model: string().min(1).optional(),
|
|
91028
|
+
has_api_key: boolean$1(),
|
|
91029
|
+
status: providerCatalogStatusSchema,
|
|
91030
|
+
models: array(string().min(1)).optional()
|
|
91031
|
+
});
|
|
91032
|
+
const providerRefreshChangeSchema = object({
|
|
91033
|
+
provider_id: string().min(1),
|
|
91034
|
+
provider_name: string().min(1),
|
|
91035
|
+
added: number$1().int().min(0),
|
|
91036
|
+
removed: number$1().int().min(0)
|
|
91037
|
+
});
|
|
91038
|
+
const providerRefreshFailureSchema = object({
|
|
91039
|
+
provider: string().min(1),
|
|
91040
|
+
reason: string().min(1)
|
|
91041
|
+
});
|
|
91042
|
+
//#endregion
|
|
90975
91043
|
//#region ../../packages/protocol/src/events.ts
|
|
90976
91044
|
const MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE = "mcp.oauth.authorization_url";
|
|
90977
91045
|
const tokenUsageSchema = object({
|
|
@@ -91298,6 +91366,12 @@ object({
|
|
|
91298
91366
|
changedFields: array(string()),
|
|
91299
91367
|
config: configResponseSchema
|
|
91300
91368
|
});
|
|
91369
|
+
const modelCatalogChangedEventSchema = object({
|
|
91370
|
+
type: literal("event.model_catalog.changed"),
|
|
91371
|
+
changed: array(providerRefreshChangeSchema),
|
|
91372
|
+
unchanged: array(string().min(1)),
|
|
91373
|
+
failed: array(providerRefreshFailureSchema)
|
|
91374
|
+
});
|
|
91301
91375
|
const goalUpdatedEventSchema = object({
|
|
91302
91376
|
type: literal("goal.updated"),
|
|
91303
91377
|
snapshot: goalSnapshotSchema.nullable(),
|
|
@@ -91530,6 +91604,7 @@ const eventSchema = discriminatedUnion("type", [
|
|
|
91530
91604
|
workspaceUpdatedEventSchema,
|
|
91531
91605
|
workspaceDeletedEventSchema,
|
|
91532
91606
|
sessionStatusChangedEventSchema,
|
|
91607
|
+
modelCatalogChangedEventSchema,
|
|
91533
91608
|
goalUpdatedEventSchema,
|
|
91534
91609
|
skillActivatedEventSchema,
|
|
91535
91610
|
turnStartedEventSchema,
|
|
@@ -92329,39 +92404,6 @@ const fileMetaSchema = object({
|
|
|
92329
92404
|
expires_at: isoDateTimeSchema.optional()
|
|
92330
92405
|
});
|
|
92331
92406
|
//#endregion
|
|
92332
|
-
//#region ../../packages/protocol/src/modelCatalog.ts
|
|
92333
|
-
const modelCatalogItemSchema = object({
|
|
92334
|
-
provider: string().min(1),
|
|
92335
|
-
model: string().min(1),
|
|
92336
|
-
display_name: string().min(1).optional(),
|
|
92337
|
-
max_context_size: number$1().int().min(1),
|
|
92338
|
-
capabilities: array(string()).optional()
|
|
92339
|
-
});
|
|
92340
|
-
const providerCatalogStatusSchema = _enum([
|
|
92341
|
-
"connected",
|
|
92342
|
-
"error",
|
|
92343
|
-
"unconfigured"
|
|
92344
|
-
]);
|
|
92345
|
-
const providerCatalogItemSchema = object({
|
|
92346
|
-
id: string().min(1),
|
|
92347
|
-
type: string().min(1),
|
|
92348
|
-
base_url: string().min(1).optional(),
|
|
92349
|
-
default_model: string().min(1).optional(),
|
|
92350
|
-
has_api_key: boolean$1(),
|
|
92351
|
-
status: providerCatalogStatusSchema,
|
|
92352
|
-
models: array(string().min(1)).optional()
|
|
92353
|
-
});
|
|
92354
|
-
const providerRefreshChangeSchema = object({
|
|
92355
|
-
provider_id: string().min(1),
|
|
92356
|
-
provider_name: string().min(1),
|
|
92357
|
-
added: number$1().int().min(0),
|
|
92358
|
-
removed: number$1().int().min(0)
|
|
92359
|
-
});
|
|
92360
|
-
const providerRefreshFailureSchema = object({
|
|
92361
|
-
provider: string().min(1),
|
|
92362
|
-
reason: string().min(1)
|
|
92363
|
-
});
|
|
92364
|
-
//#endregion
|
|
92365
92407
|
//#region ../../packages/protocol/src/rest/fs.ts
|
|
92366
92408
|
/**
|
|
92367
92409
|
* POST /v1/sessions/{sid}/fs:list
|
|
@@ -93024,7 +93066,12 @@ const setDefaultModelResponseSchema = object({
|
|
|
93024
93066
|
default_model: string().min(1),
|
|
93025
93067
|
model: modelCatalogItemSchema
|
|
93026
93068
|
});
|
|
93027
|
-
|
|
93069
|
+
object({
|
|
93070
|
+
changed: array(providerRefreshChangeSchema),
|
|
93071
|
+
unchanged: array(string().min(1)),
|
|
93072
|
+
failed: array(providerRefreshFailureSchema)
|
|
93073
|
+
});
|
|
93074
|
+
const refreshProviderModelsResponseSchema = object({
|
|
93028
93075
|
changed: array(providerRefreshChangeSchema),
|
|
93029
93076
|
unchanged: array(string().min(1)),
|
|
93030
93077
|
failed: array(providerRefreshFailureSchema)
|
|
@@ -97246,7 +97293,7 @@ var agent_default$1 = "name: agent\ndescription: Default Kimi Code agent\n\nsyst
|
|
|
97246
97293
|
var coder_default = "extends: agent\nname: coder\npromptVars:\n roleAdditional: |\n You are now running as a subagent. All the `user` messages are sent by the main agent. The main agent cannot see your context, it can only see your last message when you finish the task. You must treat the parent agent as your caller. Do not directly ask the end user questions. If something is unclear, explain the ambiguity in your final summary to the parent agent.\nwhenToUse: |\n Use this agent for non-trivial software engineering work that may require reading files, editing code, running commands, and returning a compact but technically complete summary to the parent agent.\ntools:\n - Bash\n - Read\n - ReadMediaFile\n - Glob\n - Grep\n - Write\n - Edit\n - WebSearch\n - FetchURL\n - mcp__*\n";
|
|
97247
97294
|
//#endregion
|
|
97248
97295
|
//#region ../../packages/agent-core/src/profile/default/explore.yaml?raw
|
|
97249
|
-
var explore_default = "extends: agent\nname: explore\npromptVars:\n roleAdditional: |\n You are now running as a subagent. All the `user` messages are sent by the main agent. The main agent cannot see your context, it can only see your last message when you finish the task. You must treat the parent agent as your caller. Do not directly ask the end user questions. If something is unclear, explain the ambiguity in your final summary to the parent agent.\n\n You are a codebase exploration specialist. Your role is EXCLUSIVELY to search, read, and analyze existing code and resources. You do NOT have access to file editing tools.\n\n Your strengths:\n - Rapidly finding files using glob patterns\n - Searching code and text with powerful regex patterns\n - Reading and analyzing file contents\n - Running read-only shell commands (git log, git diff, ls, find, etc.)\n\n Guidelines:\n - Use Glob for broad file pattern matching. Prefer
|
|
97296
|
+
var explore_default = "extends: agent\nname: explore\npromptVars:\n roleAdditional: |\n You are now running as a subagent. All the `user` messages are sent by the main agent. The main agent cannot see your context, it can only see your last message when you finish the task. You must treat the parent agent as your caller. Do not directly ask the end user questions. If something is unclear, explain the ambiguity in your final summary to the parent agent.\n\n You are a codebase exploration specialist. Your role is EXCLUSIVELY to search, read, and analyze existing code and resources. You do NOT have access to file editing tools.\n\n Your strengths:\n - Rapidly finding files using glob patterns\n - Searching code and text with powerful regex patterns\n - Reading and analyzing file contents\n - Running read-only shell commands (git log, git diff, ls, find, etc.)\n\n Guidelines:\n - Use Glob for broad file pattern matching. Prefer patterns with a literal anchor (extension or subdirectory); pure wildcards like `*` or `**/*` are allowed but usually truncate at the match cap.\n - Use Grep for searching file contents with regex\n - Use Read when you know the specific file path\n - Use Bash ONLY for read-only operations (ls, git status, git log, git diff, find)\n - NEVER use Bash for any file creation or modification commands\n - Adapt your search depth based on the thoroughness level specified by the caller\n - Wherever possible, spawn multiple parallel tool calls for grepping and reading files to maximize speed\n\n If the prompt includes a <git-context> block, use it to orient yourself about the repository state before starting your investigation.\n\n You are meant to be a fast agent. Complete the search request efficiently and report your findings clearly in a structured format.\nwhenToUse: |\n Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (e.g. \"src/**/*.yaml\"), search code for keywords (e.g. \"database connection\"), or answer questions about the codebase (e.g. \"how does the auth module work?\"). When calling this agent, specify the desired thoroughness level: \"quick\" for basic searches, \"medium\" for moderate exploration, or \"thorough\" for comprehensive analysis across multiple locations and naming conventions. Use this agent for any read-only exploration that will clearly require more than 3 search queries. Prefer launching multiple explore agents concurrently when investigating independent questions.\ntools:\n - Bash\n - Read\n - ReadMediaFile\n - Glob\n - Grep\n - WebSearch\n - FetchURL\n";
|
|
97250
97297
|
//#endregion
|
|
97251
97298
|
//#region ../../packages/agent-core/src/profile/default/init.md?raw
|
|
97252
97299
|
var init_default = "You are a software engineering expert with many years of programming experience. Please explore the current project directory to understand the project's architecture and main details.\n\nTask requirements:\n1. Analyze the project structure and identify key configuration files (such as pyproject.toml, package.json, Cargo.toml, etc.).\n2. Understand the project's technology stack, build process and runtime architecture.\n3. Identify how the code is organized and main module divisions.\n4. Discover project-specific development conventions, testing strategies, and deployment processes.\n\nAfter the exploration, you should do a thorough summary of your findings and overwrite it into `AGENTS.md` file in the project root. You need to refer to what is already in the file when you do so.\n\nFor your information, `AGENTS.md` is a file intended to be read by AI coding agents. Expect the reader of this file know nothing about the project.\n\nYou should compose this file according to the actual project content. Do not make any assumptions or generalizations. Ensure the information is accurate and useful. You must use the natural language that is mainly used in the project's comments and documentation.\n\nPopular sections that people usually write in `AGENTS.md` are:\n\n- Project overview\n- Build and test commands\n- Code style guidelines\n- Testing instructions\n- Security considerations\n";
|
|
@@ -99664,278 +99711,6 @@ var EditTool = class {
|
|
|
99664
99711
|
}
|
|
99665
99712
|
};
|
|
99666
99713
|
//#endregion
|
|
99667
|
-
//#region ../../packages/agent-core/src/tools/builtin/file/glob.md?raw
|
|
99668
|
-
var glob_default = "Find files (and optionally directories) by glob pattern, sorted by modification time (most recent first).\n\nGood patterns:\n- `*.ts` — files in the current directory matching an extension\n- `src/**/*.ts` — recursive walk with a subdirectory anchor and extension\n- `**/*.py` — recursive walk from the search root for an extension\n- `*.{ts,tsx}` — brace expansion is supported; expanded into `*.ts` and `*.tsx` before walking\n- `{src,test}/**/*.ts` — cartesian brace expansion is supported too\n\nPrefer a pattern with a literal anchor (a file extension or subdirectory) up front; a bare `**/*` walks until it truncates at the match cap. Results are capped at the first 100 matching paths (walk order, not global modification-time order). If a search would return more, a truncation marker is appended with the count of matches seen so far. Refine the pattern (extension, subdirectory) when 100 is not enough, or call again with a narrower anchor.\n\nLarge-directory caveat — avoid recursing into dependency / build output even with an anchor:\n- `node_modules/**/*.js`, `.venv/**/*.py`, `__pycache__/**`, `target/**` all match technically but\n typically produce thousands of results that truncate at the match cap and waste the caller context.\n Prefer specific subpaths like `node_modules/react/src/**/*.js`.\n";
|
|
99669
|
-
//#endregion
|
|
99670
|
-
//#region ../../packages/agent-core/src/tools/builtin/file/glob.ts
|
|
99671
|
-
const GlobInputSchema = object({
|
|
99672
|
-
pattern: string().describe("Glob pattern to match files/directories."),
|
|
99673
|
-
path: string().optional().describe("Absolute path to the directory to search in. Defaults to the current working directory."),
|
|
99674
|
-
include_dirs: boolean$1().default(true).optional().describe("Whether to include directories in results. Defaults to true. Set false to return only files.")
|
|
99675
|
-
});
|
|
99676
|
-
/**
|
|
99677
|
-
* Hard upper bound on the number of sub-patterns a single brace expansion
|
|
99678
|
-
* is allowed to produce. Generous enough for the common LLM patterns
|
|
99679
|
-
* (`*.{ts,tsx,js,jsx,mjs,cjs}` etc.) while still keeping pathological
|
|
99680
|
-
* cartesian inputs like `{a,b}{c,d}{e,f}{g,h}{i,j}{k,l}` (= 64) from
|
|
99681
|
-
* fanning out unboundedly. Beyond this we fall through with the original
|
|
99682
|
-
* pattern unexpanded — kaos would then treat the braces as literals and
|
|
99683
|
-
* match zero, which is the right "obvious failure" signal for a pattern
|
|
99684
|
-
* the model probably did not mean.
|
|
99685
|
-
*/
|
|
99686
|
-
const MAX_BRACE_EXPANSIONS = 64;
|
|
99687
|
-
/**
|
|
99688
|
-
* Path-shape hint appended to the tool description only on a Windows
|
|
99689
|
-
* (`win32` path class) backend. The `path` argument accepts both native
|
|
99690
|
-
* Windows paths and POSIX-style paths, but matched paths come back in
|
|
99691
|
-
* Windows backslash form — a command run through Bash must convert them
|
|
99692
|
-
* to forward slashes first. Injected conditionally so non-Windows
|
|
99693
|
-
* sessions are not shown a hint that does not apply to them.
|
|
99694
|
-
*/
|
|
99695
|
-
const WINDOWS_PATH_HINT = "\n\nWindows note: the `path` argument accepts both Windows paths (e.g. `C:\\Users\\foo`) and POSIX-style paths (e.g. `/c/Users/foo`). Matched paths are returned in Windows backslash form; convert them to forward slashes before using them in a Bash command.";
|
|
99696
|
-
const S_IFMT$2 = 61440;
|
|
99697
|
-
const S_IFDIR$1 = 16384;
|
|
99698
|
-
/**
|
|
99699
|
-
* Tool-level description shown to the LLM at tool declaration time.
|
|
99700
|
-
* Tells the model — before any round-trip — which patterns are accepted,
|
|
99701
|
-
* how brace expansion is handled, and which directories are too large to
|
|
99702
|
-
* recurse into. On a Windows backend the description also carries
|
|
99703
|
-
* `WINDOWS_PATH_HINT` (path-shape guidance).
|
|
99704
|
-
*/
|
|
99705
|
-
var GlobTool = class {
|
|
99706
|
-
kaos;
|
|
99707
|
-
workspace;
|
|
99708
|
-
name = "Glob";
|
|
99709
|
-
description;
|
|
99710
|
-
parameters = toInputJsonSchema(GlobInputSchema);
|
|
99711
|
-
constructor(kaos, workspace) {
|
|
99712
|
-
this.kaos = kaos;
|
|
99713
|
-
this.workspace = workspace;
|
|
99714
|
-
this.description = this.kaos.pathClass() === "win32" ? glob_default + WINDOWS_PATH_HINT : glob_default;
|
|
99715
|
-
}
|
|
99716
|
-
resolveExecution(args) {
|
|
99717
|
-
let path;
|
|
99718
|
-
if (args.path !== void 0) path = resolvePathAccessPath(args.path, {
|
|
99719
|
-
kaos: this.kaos,
|
|
99720
|
-
workspace: this.workspace,
|
|
99721
|
-
operation: "search",
|
|
99722
|
-
policy: {
|
|
99723
|
-
guardMode: "absolute-outside-allowed",
|
|
99724
|
-
checkSensitive: false
|
|
99725
|
-
}
|
|
99726
|
-
});
|
|
99727
|
-
const searchRoots = [path ?? this.workspace.workspaceDir];
|
|
99728
|
-
const detailParts = [];
|
|
99729
|
-
detailParts.push(`pattern: ${args.pattern}`);
|
|
99730
|
-
if (args.path !== void 0) detailParts.push(`path: ${args.path}`);
|
|
99731
|
-
if (args.include_dirs === false) detailParts.push("include_dirs: false");
|
|
99732
|
-
return {
|
|
99733
|
-
accesses: ToolAccesses.searchTree(searchRoots[0]),
|
|
99734
|
-
description: `Searching ${args.pattern}`,
|
|
99735
|
-
display: {
|
|
99736
|
-
kind: "file_io",
|
|
99737
|
-
operation: "glob",
|
|
99738
|
-
path: searchRoots[0],
|
|
99739
|
-
detail: detailParts.join(", ")
|
|
99740
|
-
},
|
|
99741
|
-
approvalRule: literalRulePattern(this.name, args.pattern),
|
|
99742
|
-
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.pattern),
|
|
99743
|
-
execute: () => this.execution(args, searchRoots)
|
|
99744
|
-
};
|
|
99745
|
-
}
|
|
99746
|
-
async execution(args, searchRoots) {
|
|
99747
|
-
const subPatterns = expandBraces(args.pattern).map((p) => hasGlobEscape(p) ? p : normalize$1(p));
|
|
99748
|
-
const includeDirs = args.include_dirs ?? true;
|
|
99749
|
-
for (const root of searchRoots) try {
|
|
99750
|
-
const iter = this.kaos.iterdir(root);
|
|
99751
|
-
await iter.next();
|
|
99752
|
-
if (typeof iter.return === "function") await iter.return(void 0);
|
|
99753
|
-
} catch (error) {
|
|
99754
|
-
if (error !== null && typeof error === "object" && "code" in error) {
|
|
99755
|
-
const code = error.code;
|
|
99756
|
-
if (code === "ENOENT") return {
|
|
99757
|
-
isError: true,
|
|
99758
|
-
output: `${root} does not exist`
|
|
99759
|
-
};
|
|
99760
|
-
if (code === "ENOTDIR") return {
|
|
99761
|
-
isError: true,
|
|
99762
|
-
output: `${root} is not a directory`
|
|
99763
|
-
};
|
|
99764
|
-
}
|
|
99765
|
-
}
|
|
99766
|
-
try {
|
|
99767
|
-
const seen = /* @__PURE__ */ new Set();
|
|
99768
|
-
const entries = [];
|
|
99769
|
-
const YIELD_SAFETY_CAP = 200 * subPatterns.length;
|
|
99770
|
-
let yielded = 0;
|
|
99771
|
-
let truncated = false;
|
|
99772
|
-
outer: for (const root of searchRoots) for (const subPattern of subPatterns) for await (const filePath of this.kaos.glob(root, subPattern)) {
|
|
99773
|
-
yielded++;
|
|
99774
|
-
if (yielded >= YIELD_SAFETY_CAP) {
|
|
99775
|
-
truncated = true;
|
|
99776
|
-
break outer;
|
|
99777
|
-
}
|
|
99778
|
-
if (seen.has(filePath)) continue;
|
|
99779
|
-
if (entries.length >= 100) {
|
|
99780
|
-
truncated = true;
|
|
99781
|
-
break outer;
|
|
99782
|
-
}
|
|
99783
|
-
seen.add(filePath);
|
|
99784
|
-
let mtime = 0;
|
|
99785
|
-
let isDir = false;
|
|
99786
|
-
try {
|
|
99787
|
-
const st = await this.kaos.stat(filePath);
|
|
99788
|
-
mtime = st.stMtime ?? 0;
|
|
99789
|
-
isDir = (st.stMode & S_IFMT$2) === S_IFDIR$1;
|
|
99790
|
-
} catch {}
|
|
99791
|
-
if (!includeDirs && isDir) continue;
|
|
99792
|
-
entries.push({
|
|
99793
|
-
path: filePath,
|
|
99794
|
-
mtime
|
|
99795
|
-
});
|
|
99796
|
-
}
|
|
99797
|
-
entries.sort((a, b) => b.mtime - a.mtime);
|
|
99798
|
-
const paths = entries.map((e) => e.path);
|
|
99799
|
-
const pathClass = this.kaos.pathClass();
|
|
99800
|
-
const relBase = searchRoots[0] ?? this.workspace.workspaceDir;
|
|
99801
|
-
const shouldRelativize = isWithinDirectory(relBase, this.workspace.workspaceDir, pathClass);
|
|
99802
|
-
const displayLines = paths.map((p) => shouldRelativize ? relativizeIfUnder$1(p, relBase, pathClass) : p);
|
|
99803
|
-
if (entries.length === 0 && !truncated) return { output: "No matches found" };
|
|
99804
|
-
const lines = [];
|
|
99805
|
-
if (truncated) {
|
|
99806
|
-
lines.push(`[Truncated at ${String(100)} matches — ${String(seen.size)} matched so far, use a more specific pattern]`);
|
|
99807
|
-
lines.push(`Only the first ${String(100)} matches are returned.`);
|
|
99808
|
-
}
|
|
99809
|
-
lines.push(...displayLines);
|
|
99810
|
-
if (!truncated && entries.length === 100) lines.push(`Found ${String(entries.length)} matches`);
|
|
99811
|
-
return { output: lines.join("\n") };
|
|
99812
|
-
} catch (error) {
|
|
99813
|
-
if (error !== null && typeof error === "object" && "code" in error) {
|
|
99814
|
-
const code = error.code;
|
|
99815
|
-
const path = searchRoots[0] ?? this.workspace.workspaceDir;
|
|
99816
|
-
if (code === "ENOENT") return {
|
|
99817
|
-
isError: true,
|
|
99818
|
-
output: `${path} does not exist`
|
|
99819
|
-
};
|
|
99820
|
-
if (code === "ENOTDIR") return {
|
|
99821
|
-
isError: true,
|
|
99822
|
-
output: `${path} is not a directory`
|
|
99823
|
-
};
|
|
99824
|
-
}
|
|
99825
|
-
return {
|
|
99826
|
-
isError: true,
|
|
99827
|
-
output: error instanceof Error ? error.message : String(error)
|
|
99828
|
-
};
|
|
99829
|
-
}
|
|
99830
|
-
}
|
|
99831
|
-
};
|
|
99832
|
-
/**
|
|
99833
|
-
* If `candidate` is under `base`, return the portion after `base/`.
|
|
99834
|
-
* Otherwise return `candidate` unchanged (absolute). Both arguments
|
|
99835
|
-
* should be canonical absolute paths.
|
|
99836
|
-
*/
|
|
99837
|
-
function relativizeIfUnder$1(candidate, base, pathClass) {
|
|
99838
|
-
const normCandidate = normalize$1(candidate);
|
|
99839
|
-
const normBase = normalize$1(base);
|
|
99840
|
-
const comparableCandidate = pathClass === "win32" ? normCandidate.toLowerCase() : normCandidate;
|
|
99841
|
-
const comparableBase = pathClass === "win32" ? normBase.toLowerCase() : normBase;
|
|
99842
|
-
if (comparableCandidate === comparableBase) return ".";
|
|
99843
|
-
const prefix = comparableBase.endsWith("/") ? comparableBase : comparableBase + "/";
|
|
99844
|
-
if (comparableCandidate.startsWith(prefix)) return normCandidate.slice(prefix.length);
|
|
99845
|
-
return normCandidate;
|
|
99846
|
-
}
|
|
99847
|
-
/**
|
|
99848
|
-
* Expand brace alternations (`{a,b,c}`, `{src,test}/**`) into a flat list
|
|
99849
|
-
* of sub-patterns. Recursive — handles cartesian products (`{a,b}/{c,d}.ts`
|
|
99850
|
-
* → 4 patterns) and one or more levels of nesting (`{a,{b,c}}.ts`).
|
|
99851
|
-
*
|
|
99852
|
-
* Falls through with the original pattern as a single-element list when:
|
|
99853
|
-
* - the pattern contains no `{...}` group at all;
|
|
99854
|
-
* - the pattern contains `{...}` groups but none have a top-level comma
|
|
99855
|
-
* (e.g. `{abc}` — bash treats those as literal);
|
|
99856
|
-
* - braces are unbalanced (a stray `{` with no matching `}`, etc.);
|
|
99857
|
-
* - expansion would produce more than `MAX_BRACE_EXPANSIONS` patterns —
|
|
99858
|
-
* pathological cartesian inputs (`{a,b}{c,d}{e,f}{g,h}{i,j}{k,l,m}`
|
|
99859
|
-
* ≥ 192) bail out rather than fan out unboundedly.
|
|
99860
|
-
*
|
|
99861
|
-
* Backslash-escaped braces (`\{`, `\}`) are treated as literals and skip
|
|
99862
|
-
* the structural recognition so a user can opt out of expansion.
|
|
99863
|
-
*/
|
|
99864
|
-
function expandBraces(pattern) {
|
|
99865
|
-
const out = [];
|
|
99866
|
-
if (!expandInto(pattern, out, MAX_BRACE_EXPANSIONS)) return [pattern];
|
|
99867
|
-
return out;
|
|
99868
|
-
}
|
|
99869
|
-
function hasGlobEscape(pattern) {
|
|
99870
|
-
return /\\[{}[\]*?,]/.test(pattern);
|
|
99871
|
-
}
|
|
99872
|
-
function expandInto(pattern, out, cap) {
|
|
99873
|
-
let depth = 0;
|
|
99874
|
-
let start = -1;
|
|
99875
|
-
for (let i = 0; i < pattern.length; i++) {
|
|
99876
|
-
const ch = pattern[i];
|
|
99877
|
-
if (ch === "\\" && i + 1 < pattern.length) {
|
|
99878
|
-
i++;
|
|
99879
|
-
continue;
|
|
99880
|
-
}
|
|
99881
|
-
if (ch === "{") {
|
|
99882
|
-
if (depth === 0) start = i;
|
|
99883
|
-
depth++;
|
|
99884
|
-
continue;
|
|
99885
|
-
}
|
|
99886
|
-
if (ch === "}") {
|
|
99887
|
-
if (depth === 0) return pushLiteral(pattern, out, cap);
|
|
99888
|
-
depth--;
|
|
99889
|
-
if (depth === 0 && start !== -1) {
|
|
99890
|
-
const parts = splitTopLevelCommas(pattern.slice(start + 1, i));
|
|
99891
|
-
if (parts.length < 2) {
|
|
99892
|
-
start = -1;
|
|
99893
|
-
continue;
|
|
99894
|
-
}
|
|
99895
|
-
const prefix = pattern.slice(0, start);
|
|
99896
|
-
const suffix = pattern.slice(i + 1);
|
|
99897
|
-
for (const part of parts) {
|
|
99898
|
-
if (out.length >= cap) return false;
|
|
99899
|
-
if (!expandInto(prefix + part + suffix, out, cap)) return false;
|
|
99900
|
-
}
|
|
99901
|
-
return true;
|
|
99902
|
-
}
|
|
99903
|
-
}
|
|
99904
|
-
}
|
|
99905
|
-
if (depth !== 0) return pushLiteral(pattern, out, cap);
|
|
99906
|
-
return pushLiteral(pattern, out, cap);
|
|
99907
|
-
}
|
|
99908
|
-
function pushLiteral(pattern, out, cap) {
|
|
99909
|
-
if (out.length >= cap) return false;
|
|
99910
|
-
out.push(pattern);
|
|
99911
|
-
return true;
|
|
99912
|
-
}
|
|
99913
|
-
/**
|
|
99914
|
-
* Split on commas that sit at brace depth zero. Used by `expandBraces`
|
|
99915
|
-
* to slice a `{a,{b,c},d}` group into `["a", "{b,c}", "d"]` rather than
|
|
99916
|
-
* `["a", "{b", "c}", "d"]`.
|
|
99917
|
-
*/
|
|
99918
|
-
function splitTopLevelCommas(s) {
|
|
99919
|
-
const parts = [];
|
|
99920
|
-
let depth = 0;
|
|
99921
|
-
let last = 0;
|
|
99922
|
-
for (let i = 0; i < s.length; i++) {
|
|
99923
|
-
const ch = s[i];
|
|
99924
|
-
if (ch === "\\" && i + 1 < s.length) {
|
|
99925
|
-
i++;
|
|
99926
|
-
continue;
|
|
99927
|
-
}
|
|
99928
|
-
if (ch === "{") depth++;
|
|
99929
|
-
else if (ch === "}") depth--;
|
|
99930
|
-
else if (ch === "," && depth === 0) {
|
|
99931
|
-
parts.push(s.slice(last, i));
|
|
99932
|
-
last = i + 1;
|
|
99933
|
-
}
|
|
99934
|
-
}
|
|
99935
|
-
parts.push(s.slice(last));
|
|
99936
|
-
return parts;
|
|
99937
|
-
}
|
|
99938
|
-
//#endregion
|
|
99939
99714
|
//#region ../../node_modules/.pnpm/tar@7.5.13/node_modules/tar/dist/esm/index.min.js
|
|
99940
99715
|
var kr = Object.defineProperty;
|
|
99941
99716
|
var vr = (s, t) => {
|
|
@@ -104310,6 +104085,386 @@ function rgUnavailableMessage(cause) {
|
|
|
104310
104085
|
Error: ${cause instanceof Error ? cause.message : typeof cause === "string" ? cause : "unknown error"}\n\nFix options:\n macOS: brew install ripgrep\n Ubuntu: sudo apt-get install ripgrep\n Other: https://github.com/BurntSushi/ripgrep#installation\n\nAlternatively, drop a static rg binary at ${join$4(getShareDir(), "bin", rgBinaryName())}`;
|
|
104311
104086
|
}
|
|
104312
104087
|
//#endregion
|
|
104088
|
+
//#region ../../packages/agent-core/src/tools/support/stream.ts
|
|
104089
|
+
function isPrematureCloseError(error) {
|
|
104090
|
+
return error instanceof Error && error.code === "ERR_STREAM_PREMATURE_CLOSE";
|
|
104091
|
+
}
|
|
104092
|
+
//#endregion
|
|
104093
|
+
//#region ../../packages/agent-core/src/tools/support/run-rg.ts
|
|
104094
|
+
const DEFAULT_TIMEOUT_MS$1 = 2e4;
|
|
104095
|
+
const MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
|
|
104096
|
+
const VCS_DIRECTORIES_TO_EXCLUDE = [
|
|
104097
|
+
".git",
|
|
104098
|
+
".svn",
|
|
104099
|
+
".hg",
|
|
104100
|
+
".bzr",
|
|
104101
|
+
".jj",
|
|
104102
|
+
".sl"
|
|
104103
|
+
];
|
|
104104
|
+
const SENSITIVE_GLOBS_TO_EXCLUDE = [
|
|
104105
|
+
"**/.env",
|
|
104106
|
+
...[
|
|
104107
|
+
"id_rsa",
|
|
104108
|
+
"id_ed25519",
|
|
104109
|
+
"id_ecdsa"
|
|
104110
|
+
].flatMap((name) => [
|
|
104111
|
+
`**/${name}`,
|
|
104112
|
+
`**/${name}[-_]*`,
|
|
104113
|
+
...SENSITIVE_DOT_VARIANT_SUFFIXES.map((suffix) => `**/${name}${suffix}`)
|
|
104114
|
+
]),
|
|
104115
|
+
"**/.aws/credentials",
|
|
104116
|
+
"**/.aws/credentials/**",
|
|
104117
|
+
"**/.gcp/credentials",
|
|
104118
|
+
"**/.gcp/credentials/**"
|
|
104119
|
+
];
|
|
104120
|
+
async function disposeProcess$1(proc) {
|
|
104121
|
+
try {
|
|
104122
|
+
await proc.dispose();
|
|
104123
|
+
} catch {}
|
|
104124
|
+
}
|
|
104125
|
+
async function runRipgrepOnce(kaos, rgArgs, signal, options = {}) {
|
|
104126
|
+
const abortedMessage = options.abortedMessage ?? "Aborted";
|
|
104127
|
+
if (signal.aborted) return {
|
|
104128
|
+
kind: "tool-error",
|
|
104129
|
+
result: {
|
|
104130
|
+
isError: true,
|
|
104131
|
+
output: abortedMessage
|
|
104132
|
+
}
|
|
104133
|
+
};
|
|
104134
|
+
let proc;
|
|
104135
|
+
try {
|
|
104136
|
+
proc = await kaos.exec(...rgArgs);
|
|
104137
|
+
} catch (error) {
|
|
104138
|
+
return {
|
|
104139
|
+
kind: "tool-error",
|
|
104140
|
+
result: {
|
|
104141
|
+
isError: true,
|
|
104142
|
+
output: error instanceof Error && "code" in error && error.code === "ENOENT" ? rgUnavailableMessage(error) : error instanceof Error ? error.message : String(error)
|
|
104143
|
+
}
|
|
104144
|
+
};
|
|
104145
|
+
}
|
|
104146
|
+
try {
|
|
104147
|
+
proc.stdin.end();
|
|
104148
|
+
} catch {}
|
|
104149
|
+
let timedOut = false;
|
|
104150
|
+
let aborted = false;
|
|
104151
|
+
let killed = false;
|
|
104152
|
+
const killProc = async () => {
|
|
104153
|
+
if (killed) return;
|
|
104154
|
+
killed = true;
|
|
104155
|
+
try {
|
|
104156
|
+
await proc.kill("SIGTERM");
|
|
104157
|
+
} catch {}
|
|
104158
|
+
const exited = proc.wait().then(() => true).catch(() => true);
|
|
104159
|
+
if (!await Promise.race([exited, new Promise((resolve) => {
|
|
104160
|
+
setTimeout(() => {
|
|
104161
|
+
resolve(false);
|
|
104162
|
+
}, 5e3);
|
|
104163
|
+
})]) && proc.exitCode === null) try {
|
|
104164
|
+
await proc.kill("SIGKILL");
|
|
104165
|
+
} catch {}
|
|
104166
|
+
await disposeProcess$1(proc);
|
|
104167
|
+
};
|
|
104168
|
+
const onAbort = () => {
|
|
104169
|
+
aborted = true;
|
|
104170
|
+
killProc();
|
|
104171
|
+
};
|
|
104172
|
+
signal.addEventListener("abort", onAbort);
|
|
104173
|
+
if (signal.aborted) onAbort();
|
|
104174
|
+
const timeoutHandle = setTimeout(() => {
|
|
104175
|
+
timedOut = true;
|
|
104176
|
+
killProc();
|
|
104177
|
+
}, DEFAULT_TIMEOUT_MS$1);
|
|
104178
|
+
let exitCode = 0;
|
|
104179
|
+
let stdoutText = "";
|
|
104180
|
+
let stderrText = "";
|
|
104181
|
+
let bufferTruncated = false;
|
|
104182
|
+
let stderrTruncated = false;
|
|
104183
|
+
try {
|
|
104184
|
+
const isTerminating = () => timedOut || aborted || killed;
|
|
104185
|
+
const [stdoutResult, stderrResult, code] = await Promise.all([
|
|
104186
|
+
readStreamWithCap(proc.stdout, MAX_OUTPUT_BYTES, isTerminating),
|
|
104187
|
+
readStreamWithCap(proc.stderr, MAX_OUTPUT_BYTES, isTerminating),
|
|
104188
|
+
proc.wait()
|
|
104189
|
+
]);
|
|
104190
|
+
stdoutText = stdoutResult.text;
|
|
104191
|
+
stderrText = stderrResult.text;
|
|
104192
|
+
bufferTruncated = stdoutResult.truncated;
|
|
104193
|
+
stderrTruncated = stderrResult.truncated;
|
|
104194
|
+
exitCode = code;
|
|
104195
|
+
} catch (error) {
|
|
104196
|
+
if (isPrematureCloseError(error) && (timedOut || aborted || killed)) {} else return {
|
|
104197
|
+
kind: "tool-error",
|
|
104198
|
+
result: {
|
|
104199
|
+
isError: true,
|
|
104200
|
+
output: error instanceof Error ? error.message : String(error)
|
|
104201
|
+
}
|
|
104202
|
+
};
|
|
104203
|
+
} finally {
|
|
104204
|
+
clearTimeout(timeoutHandle);
|
|
104205
|
+
signal.removeEventListener("abort", onAbort);
|
|
104206
|
+
await disposeProcess$1(proc);
|
|
104207
|
+
}
|
|
104208
|
+
if (aborted) return {
|
|
104209
|
+
kind: "tool-error",
|
|
104210
|
+
result: {
|
|
104211
|
+
isError: true,
|
|
104212
|
+
output: abortedMessage
|
|
104213
|
+
}
|
|
104214
|
+
};
|
|
104215
|
+
return {
|
|
104216
|
+
kind: "result",
|
|
104217
|
+
exitCode,
|
|
104218
|
+
stdoutText,
|
|
104219
|
+
stderrText,
|
|
104220
|
+
bufferTruncated,
|
|
104221
|
+
stderrTruncated,
|
|
104222
|
+
timedOut
|
|
104223
|
+
};
|
|
104224
|
+
}
|
|
104225
|
+
function shouldRetryRipgrepEagain(result) {
|
|
104226
|
+
return result.exitCode !== 0 && result.exitCode !== 1 && !result.timedOut && isEagainRipgrepError(result.stderrText);
|
|
104227
|
+
}
|
|
104228
|
+
function isEagainRipgrepError(stderr) {
|
|
104229
|
+
return stderr.includes("os error 11") || stderr.includes("Resource temporarily unavailable");
|
|
104230
|
+
}
|
|
104231
|
+
async function readStreamWithCap(stream, maxBytes, suppressPrematureClose) {
|
|
104232
|
+
const chunks = [];
|
|
104233
|
+
let total = 0;
|
|
104234
|
+
let truncated = false;
|
|
104235
|
+
try {
|
|
104236
|
+
for await (const chunk of stream) {
|
|
104237
|
+
const buf = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
104238
|
+
if (truncated) continue;
|
|
104239
|
+
if (total + buf.length > maxBytes) {
|
|
104240
|
+
const remaining = maxBytes - total;
|
|
104241
|
+
if (remaining > 0) chunks.push(buf.subarray(0, remaining));
|
|
104242
|
+
total = maxBytes;
|
|
104243
|
+
truncated = true;
|
|
104244
|
+
continue;
|
|
104245
|
+
}
|
|
104246
|
+
chunks.push(buf);
|
|
104247
|
+
total += buf.length;
|
|
104248
|
+
}
|
|
104249
|
+
} catch (error) {
|
|
104250
|
+
if (!isPrematureCloseError(error) || suppressPrematureClose?.() !== true) throw error;
|
|
104251
|
+
}
|
|
104252
|
+
return {
|
|
104253
|
+
text: Buffer.concat(chunks).toString("utf8"),
|
|
104254
|
+
truncated
|
|
104255
|
+
};
|
|
104256
|
+
}
|
|
104257
|
+
//#endregion
|
|
104258
|
+
//#region ../../packages/agent-core/src/tools/builtin/file/glob.md?raw
|
|
104259
|
+
var glob_default = "Find files by glob pattern, sorted by modification time (most recent first).\n\nPowered by ripgrep. Respects `.gitignore`, `.ignore`, and `.rgignore` by default — set `include_ignored` to also match ignored files (e.g. build outputs, `node_modules`). Sensitive files (such as `.env`) are always filtered out.\n\nGood patterns:\n- `*.ts` — all files matching an extension, at any depth below the search root (a bare pattern without `/` matches recursively)\n- `src/*.ts` — files directly inside `src/` (one level, not recursive)\n- `src/**/*.ts` — recursive walk with a subdirectory anchor and extension\n- `**/*.py` — recursive walk from the search root for an extension\n- `*.{ts,tsx}` — brace expansion is supported\n- `{src,test}/**/*.ts` — cartesian brace expansion is supported too\n\nResults are capped at the first 100 matching paths. If a search would return more, a truncation marker is appended. Refine the pattern (extension, subdirectory) when 100 is not enough, or call again with a narrower anchor.\n\nLarge-directory caveat — avoid recursing into dependency / build output even with an anchor, especially when `include_ignored` is set:\n- `node_modules/**/*.js`, `.venv/**/*.py`, `__pycache__/**`, `target/**` can produce thousands of results that truncate at the match cap and waste context. Prefer specific subpaths like `node_modules/react/src/**/*.js`.\n";
|
|
104260
|
+
//#endregion
|
|
104261
|
+
//#region ../../packages/agent-core/src/tools/builtin/file/glob.ts
|
|
104262
|
+
const GlobInputSchema = object({
|
|
104263
|
+
pattern: string().describe("Glob pattern to match files."),
|
|
104264
|
+
path: string().optional().describe("Absolute path to the directory to search in. Defaults to the current working directory."),
|
|
104265
|
+
include_ignored: boolean$1().optional().describe("Also match files excluded by ignore files such as `.gitignore`, `.ignore`, and `.rgignore` (for example `node_modules` or build outputs). Sensitive files (such as `.env`) remain filtered out for safety. Defaults to false."),
|
|
104266
|
+
include_dirs: boolean$1().optional().describe("Deprecated and ignored. Results are always files-only — directories are never listed. Accepted only so older calls that still pass this flag are not rejected by parameter validation.")
|
|
104267
|
+
});
|
|
104268
|
+
/**
|
|
104269
|
+
* Path-shape hint appended to the tool description only on a Windows
|
|
104270
|
+
* (`win32` path class) backend. The `path` argument accepts both native
|
|
104271
|
+
* Windows paths and POSIX-style paths, but matched paths come back in
|
|
104272
|
+
* Windows backslash form — a command run through Bash must convert them
|
|
104273
|
+
* to forward slashes first. Injected conditionally so non-Windows
|
|
104274
|
+
* sessions are not shown a hint that does not apply to them.
|
|
104275
|
+
*/
|
|
104276
|
+
const WINDOWS_PATH_HINT = "\n\nWindows note: the `path` argument accepts both Windows paths (e.g. `C:\\Users\\foo`) and POSIX-style paths (e.g. `/c/Users/foo`). Matched paths are returned in Windows backslash form; convert them to forward slashes before using them in a Bash command.";
|
|
104277
|
+
const S_IFMT$2 = 61440;
|
|
104278
|
+
const S_IFDIR$1 = 16384;
|
|
104279
|
+
/**
|
|
104280
|
+
* Tool-level description shown to the LLM at tool declaration time.
|
|
104281
|
+
* Tells the model — before any round-trip — which patterns are accepted,
|
|
104282
|
+
* how brace expansion is handled, and which directories are too large to
|
|
104283
|
+
* recurse into. On a Windows backend the description also carries
|
|
104284
|
+
* `WINDOWS_PATH_HINT` (path-shape guidance).
|
|
104285
|
+
*/
|
|
104286
|
+
var GlobTool = class {
|
|
104287
|
+
kaos;
|
|
104288
|
+
workspace;
|
|
104289
|
+
name = "Glob";
|
|
104290
|
+
description;
|
|
104291
|
+
parameters = toInputJsonSchema(GlobInputSchema);
|
|
104292
|
+
telemetry;
|
|
104293
|
+
constructor(kaos, workspace, telemetry = noopTelemetryClient) {
|
|
104294
|
+
this.kaos = kaos;
|
|
104295
|
+
this.workspace = workspace;
|
|
104296
|
+
this.telemetry = telemetry;
|
|
104297
|
+
this.description = this.kaos.pathClass() === "win32" ? glob_default + WINDOWS_PATH_HINT : glob_default;
|
|
104298
|
+
}
|
|
104299
|
+
resolveExecution(args) {
|
|
104300
|
+
let path;
|
|
104301
|
+
if (args.path !== void 0) path = resolvePathAccessPath(args.path, {
|
|
104302
|
+
kaos: this.kaos,
|
|
104303
|
+
workspace: this.workspace,
|
|
104304
|
+
operation: "search",
|
|
104305
|
+
policy: {
|
|
104306
|
+
guardMode: "absolute-outside-allowed",
|
|
104307
|
+
checkSensitive: false
|
|
104308
|
+
}
|
|
104309
|
+
});
|
|
104310
|
+
const searchRoots = [path ?? this.workspace.workspaceDir];
|
|
104311
|
+
const detailParts = [`pattern: ${args.pattern}`];
|
|
104312
|
+
if (args.path !== void 0) detailParts.push(`path: ${args.path}`);
|
|
104313
|
+
if (args.include_ignored === true) detailParts.push("include_ignored: true");
|
|
104314
|
+
return {
|
|
104315
|
+
accesses: ToolAccesses.searchTree(searchRoots[0]),
|
|
104316
|
+
description: `Searching ${args.pattern}`,
|
|
104317
|
+
display: {
|
|
104318
|
+
kind: "file_io",
|
|
104319
|
+
operation: "glob",
|
|
104320
|
+
path: searchRoots[0],
|
|
104321
|
+
detail: detailParts.join(", ")
|
|
104322
|
+
},
|
|
104323
|
+
approvalRule: literalRulePattern(this.name, args.pattern),
|
|
104324
|
+
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.pattern),
|
|
104325
|
+
execute: ({ signal }) => this.execution(args, signal, searchRoots)
|
|
104326
|
+
};
|
|
104327
|
+
}
|
|
104328
|
+
async execution(args, signal, searchRoots) {
|
|
104329
|
+
const searchRoot = searchRoots[0] ?? this.workspace.workspaceDir;
|
|
104330
|
+
try {
|
|
104331
|
+
if (((await this.kaos.stat(searchRoot)).stMode & S_IFMT$2) !== S_IFDIR$1) return {
|
|
104332
|
+
isError: true,
|
|
104333
|
+
output: `${searchRoot} is not a directory`
|
|
104334
|
+
};
|
|
104335
|
+
} catch (error) {
|
|
104336
|
+
if (errorCode(error) === "ENOENT") return {
|
|
104337
|
+
isError: true,
|
|
104338
|
+
output: `${searchRoot} does not exist`
|
|
104339
|
+
};
|
|
104340
|
+
return {
|
|
104341
|
+
isError: true,
|
|
104342
|
+
output: error instanceof Error ? error.message : String(error)
|
|
104343
|
+
};
|
|
104344
|
+
}
|
|
104345
|
+
let rgPath;
|
|
104346
|
+
try {
|
|
104347
|
+
const resolution = await ensureRgPath({ signal });
|
|
104348
|
+
rgPath = resolution.path;
|
|
104349
|
+
if (resolution.source !== "system-path") this.telemetry.track("glob_tool_rg_fallback", {
|
|
104350
|
+
source: resolution.source,
|
|
104351
|
+
outcome: "resolved"
|
|
104352
|
+
});
|
|
104353
|
+
} catch (error) {
|
|
104354
|
+
if (isAbortError$3(error)) return {
|
|
104355
|
+
isError: true,
|
|
104356
|
+
output: "Glob aborted"
|
|
104357
|
+
};
|
|
104358
|
+
this.telemetry.track("glob_tool_rg_fallback", { outcome: "failed" });
|
|
104359
|
+
return {
|
|
104360
|
+
isError: true,
|
|
104361
|
+
output: rgUnavailableMessage(error)
|
|
104362
|
+
};
|
|
104363
|
+
}
|
|
104364
|
+
const execKaos = this.kaos.withCwd(searchRoot);
|
|
104365
|
+
let runResult = await runRipgrepOnce(execKaos, buildRgArgs$1(rgPath, args), signal, { abortedMessage: "Glob aborted" });
|
|
104366
|
+
if (runResult.kind === "tool-error") return runResult.result;
|
|
104367
|
+
if (shouldRetryRipgrepEagain(runResult)) {
|
|
104368
|
+
runResult = await runRipgrepOnce(execKaos, buildRgArgs$1(rgPath, args, true), signal, { abortedMessage: "Glob aborted" });
|
|
104369
|
+
if (runResult.kind === "tool-error") return runResult.result;
|
|
104370
|
+
}
|
|
104371
|
+
const { exitCode, stdoutText, stderrText, bufferTruncated, timedOut } = runResult;
|
|
104372
|
+
let traversalWarning;
|
|
104373
|
+
if (exitCode !== 0 && exitCode !== 1 && !timedOut) {
|
|
104374
|
+
if (splitCompletePaths(stdoutText, true).length === 0) return {
|
|
104375
|
+
isError: true,
|
|
104376
|
+
output: formatGlobError(searchRoot, stderrText)
|
|
104377
|
+
};
|
|
104378
|
+
traversalWarning = formatGlobWarning(stderrText);
|
|
104379
|
+
}
|
|
104380
|
+
if (signal.aborted) return {
|
|
104381
|
+
isError: true,
|
|
104382
|
+
output: "Glob aborted"
|
|
104383
|
+
};
|
|
104384
|
+
const rawPaths = splitCompletePaths(stdoutText, bufferTruncated || timedOut).map((p) => resolve$2(searchRoot, p));
|
|
104385
|
+
const kept = [];
|
|
104386
|
+
let filteredSensitive = 0;
|
|
104387
|
+
for (const p of rawPaths) if (isSensitiveFile(p)) filteredSensitive++;
|
|
104388
|
+
else kept.push(p);
|
|
104389
|
+
const truncated = kept.length > 100;
|
|
104390
|
+
const limited = truncated ? kept.slice(0, 100) : kept;
|
|
104391
|
+
if (limited.length === 0 && !timedOut) {
|
|
104392
|
+
if (filteredSensitive > 0) return { output: `No non-sensitive matches found (${String(filteredSensitive)} sensitive file(s) filtered).` };
|
|
104393
|
+
return { output: "No matches found" };
|
|
104394
|
+
}
|
|
104395
|
+
const pathClass = this.kaos.pathClass();
|
|
104396
|
+
const shouldRelativize = isWithinDirectory(searchRoot, this.workspace.workspaceDir, pathClass);
|
|
104397
|
+
const displayLines = limited.map((p) => shouldRelativize ? relativizeIfUnder$1(p, searchRoot, pathClass) : p);
|
|
104398
|
+
const lines = [];
|
|
104399
|
+
if (timedOut) lines.push(`Glob timed out after ${String(DEFAULT_TIMEOUT_MS$1 / 1e3)}s; partial results returned.`);
|
|
104400
|
+
if (bufferTruncated) lines.push(`[stdout truncated at ${String(MAX_OUTPUT_BYTES)} bytes; results may be incomplete — use a more specific pattern]`);
|
|
104401
|
+
if (traversalWarning !== void 0) lines.push(traversalWarning);
|
|
104402
|
+
if (truncated) {
|
|
104403
|
+
lines.push(`[Truncated at ${String(100)} matches — use a more specific pattern]`);
|
|
104404
|
+
lines.push(`Only the first ${String(100)} matches are returned.`);
|
|
104405
|
+
}
|
|
104406
|
+
lines.push(...displayLines);
|
|
104407
|
+
if (filteredSensitive > 0) lines.push(`Filtered ${String(filteredSensitive)} sensitive file(s).`);
|
|
104408
|
+
if (!truncated && limited.length === 100) lines.push(`Found ${String(limited.length)} matches`);
|
|
104409
|
+
return { output: lines.join("\n") };
|
|
104410
|
+
}
|
|
104411
|
+
};
|
|
104412
|
+
function buildRgArgs$1(rgPath, args, singleThreaded = false) {
|
|
104413
|
+
const cmd = [rgPath];
|
|
104414
|
+
if (singleThreaded) cmd.push("-j", "1");
|
|
104415
|
+
cmd.push("--files", "--hidden", "--sortr=modified");
|
|
104416
|
+
for (const dir of VCS_DIRECTORIES_TO_EXCLUDE) cmd.push("--glob", `!${dir}`);
|
|
104417
|
+
cmd.push("--glob", args.pattern);
|
|
104418
|
+
for (const glob of SENSITIVE_GLOBS_TO_EXCLUDE) cmd.push("--glob", `!${glob}`);
|
|
104419
|
+
if (args.include_ignored) cmd.push("--no-ignore");
|
|
104420
|
+
cmd.push(".");
|
|
104421
|
+
return cmd;
|
|
104422
|
+
}
|
|
104423
|
+
function formatGlobError(searchRoot, stderr) {
|
|
104424
|
+
const trimmed = stderr.trim();
|
|
104425
|
+
if (/no such file or directory/i.test(trimmed)) return `${searchRoot} does not exist`;
|
|
104426
|
+
return trimmed.length > 0 ? `Glob failed: ${trimmed}` : "Glob failed";
|
|
104427
|
+
}
|
|
104428
|
+
function formatGlobWarning(stderr) {
|
|
104429
|
+
const trimmed = stderr.trim();
|
|
104430
|
+
return trimmed.length > 0 ? `Glob completed with warnings; some directories could not be read: ${trimmed}` : "Glob completed with warnings; some directories could not be read.";
|
|
104431
|
+
}
|
|
104432
|
+
function errorCode(error) {
|
|
104433
|
+
if (error !== null && typeof error === "object" && "code" in error) {
|
|
104434
|
+
const code = error.code;
|
|
104435
|
+
return typeof code === "string" ? code : void 0;
|
|
104436
|
+
}
|
|
104437
|
+
}
|
|
104438
|
+
/**
|
|
104439
|
+
* Split `rg --files` stdout into complete paths. When the run was capped or
|
|
104440
|
+
* timed out (`truncatedOutput`), a path cut mid-write lacks its terminating
|
|
104441
|
+
* newline; drop that trailing fragment so it is never surfaced as a match.
|
|
104442
|
+
* Complete output always ends in `\n`, so the split is lossless in that case.
|
|
104443
|
+
*/
|
|
104444
|
+
function splitCompletePaths(stdoutText, truncatedOutput) {
|
|
104445
|
+
let text = stdoutText;
|
|
104446
|
+
if (truncatedOutput && !text.endsWith("\n")) {
|
|
104447
|
+
const lastNewline = text.lastIndexOf("\n");
|
|
104448
|
+
text = lastNewline >= 0 ? text.slice(0, lastNewline + 1) : "";
|
|
104449
|
+
}
|
|
104450
|
+
return text.split("\n").filter((p) => p.length > 0);
|
|
104451
|
+
}
|
|
104452
|
+
/**
|
|
104453
|
+
* If `candidate` is under `base`, return the portion after `base/`.
|
|
104454
|
+
* Otherwise return `candidate` unchanged (absolute). Both arguments
|
|
104455
|
+
* should be canonical absolute paths.
|
|
104456
|
+
*/
|
|
104457
|
+
function relativizeIfUnder$1(candidate, base, pathClass) {
|
|
104458
|
+
const normCandidate = normalize$1(candidate);
|
|
104459
|
+
const normBase = normalize$1(base);
|
|
104460
|
+
const comparableCandidate = pathClass === "win32" ? normCandidate.toLowerCase() : normCandidate;
|
|
104461
|
+
const comparableBase = pathClass === "win32" ? normBase.toLowerCase() : normBase;
|
|
104462
|
+
if (comparableCandidate === comparableBase) return ".";
|
|
104463
|
+
const prefix = comparableBase.endsWith("/") ? comparableBase : comparableBase + "/";
|
|
104464
|
+
if (comparableCandidate.startsWith(prefix)) return normCandidate.slice(prefix.length);
|
|
104465
|
+
return normCandidate;
|
|
104466
|
+
}
|
|
104467
|
+
//#endregion
|
|
104313
104468
|
//#region ../../packages/agent-core/src/tools/support/result-builder.ts
|
|
104314
104469
|
const DEFAULT_MAX_CHARS = 5e4;
|
|
104315
104470
|
const DEFAULT_MAX_LINE_LENGTH = 2e3;
|
|
@@ -104394,11 +104549,6 @@ var ToolResultBuilder = class {
|
|
|
104394
104549
|
}
|
|
104395
104550
|
};
|
|
104396
104551
|
//#endregion
|
|
104397
|
-
//#region ../../packages/agent-core/src/tools/support/stream.ts
|
|
104398
|
-
function isPrematureCloseError(error) {
|
|
104399
|
-
return error instanceof Error && error.code === "ERR_STREAM_PREMATURE_CLOSE";
|
|
104400
|
-
}
|
|
104401
|
-
//#endregion
|
|
104402
104552
|
//#region ../../packages/agent-core/src/tools/builtin/file/grep.md?raw
|
|
104403
104553
|
var grep_default = "Search file contents using regular expressions (powered by ripgrep).\n\nUse Grep when the task is to find unknown content or unknown file locations. Do not use shell `grep` or `rg` directly; this tool applies workspace path policy, output limits, and sensitive-file filtering.\nALWAYS use Grep tool instead of running `grep` or `rg` from a shell — direct shell calls bypass workspace policy, output limits, and sensitive-file filtering.\nIf you already know a concrete file path and need to inspect its contents, use Read directly instead.\n\nWrite patterns in ripgrep regex syntax, which differs from POSIX `grep` syntax. For example, braces are special, so escape them as `\\{` to match a literal `{`.\n\nHidden files (dotfiles such as `.gitlab-ci.yml` or `.eslintrc.json`) are searched by default. To also search files excluded by `.gitignore` (such as `node_modules` or build outputs), set `include_ignored` to `true`. Sensitive files (such as `.env`) are always skipped for safety, even when `include_ignored` is `true`.\n";
|
|
104404
104554
|
//#endregion
|
|
@@ -104436,41 +104586,9 @@ object({
|
|
|
104436
104586
|
numMatches: number$1().int().nonnegative().optional(),
|
|
104437
104587
|
appliedLimit: number$1().int().nonnegative().optional()
|
|
104438
104588
|
});
|
|
104439
|
-
const DEFAULT_TIMEOUT_MS$1 = 2e4;
|
|
104440
|
-
const SIGTERM_GRACE_MS = 5e3;
|
|
104441
|
-
const MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
|
|
104442
|
-
async function disposeProcess$1(proc) {
|
|
104443
|
-
try {
|
|
104444
|
-
await proc.dispose();
|
|
104445
|
-
} catch {}
|
|
104446
|
-
}
|
|
104447
104589
|
const RG_MAX_COLUMNS = 500;
|
|
104448
104590
|
const DEFAULT_HEAD_LIMIT = 250;
|
|
104449
104591
|
const MTIME_STAT_CONCURRENCY = 32;
|
|
104450
|
-
const VCS_DIRECTORIES_TO_EXCLUDE = [
|
|
104451
|
-
".git",
|
|
104452
|
-
".svn",
|
|
104453
|
-
".hg",
|
|
104454
|
-
".bzr",
|
|
104455
|
-
".jj",
|
|
104456
|
-
".sl"
|
|
104457
|
-
];
|
|
104458
|
-
const SENSITIVE_GLOBS_TO_EXCLUDE = [
|
|
104459
|
-
"**/.env",
|
|
104460
|
-
...[
|
|
104461
|
-
"id_rsa",
|
|
104462
|
-
"id_ed25519",
|
|
104463
|
-
"id_ecdsa"
|
|
104464
|
-
].flatMap((name) => [
|
|
104465
|
-
`**/${name}`,
|
|
104466
|
-
`**/${name}[-_]*`,
|
|
104467
|
-
...SENSITIVE_DOT_VARIANT_SUFFIXES.map((suffix) => `**/${name}${suffix}`)
|
|
104468
|
-
]),
|
|
104469
|
-
"**/.aws/credentials",
|
|
104470
|
-
"**/.aws/credentials/**",
|
|
104471
|
-
"**/.gcp/credentials",
|
|
104472
|
-
"**/.gcp/credentials/**"
|
|
104473
|
-
];
|
|
104474
104592
|
const CONTENT_LINE_RE = /^(.*?)([:-])(\d+)\2/;
|
|
104475
104593
|
var GrepTool = class {
|
|
104476
104594
|
kaos;
|
|
@@ -104478,9 +104596,11 @@ var GrepTool = class {
|
|
|
104478
104596
|
name = "Grep";
|
|
104479
104597
|
description = grep_default;
|
|
104480
104598
|
parameters = toInputJsonSchema(GrepInputSchema);
|
|
104481
|
-
|
|
104599
|
+
telemetry;
|
|
104600
|
+
constructor(kaos, workspace, telemetry = noopTelemetryClient) {
|
|
104482
104601
|
this.kaos = kaos;
|
|
104483
104602
|
this.workspace = workspace;
|
|
104603
|
+
this.telemetry = telemetry;
|
|
104484
104604
|
}
|
|
104485
104605
|
resolveExecution(args) {
|
|
104486
104606
|
let path;
|
|
@@ -104516,21 +104636,27 @@ var GrepTool = class {
|
|
|
104516
104636
|
const pathClass = this.kaos.pathClass();
|
|
104517
104637
|
let rgPath;
|
|
104518
104638
|
try {
|
|
104519
|
-
|
|
104639
|
+
const resolution = await ensureRgPath({ signal });
|
|
104640
|
+
rgPath = resolution.path;
|
|
104641
|
+
if (resolution.source !== "system-path") this.telemetry.track("grep_tool_rg_fallback", {
|
|
104642
|
+
source: resolution.source,
|
|
104643
|
+
outcome: "resolved"
|
|
104644
|
+
});
|
|
104520
104645
|
} catch (error) {
|
|
104521
104646
|
if (isAbortError$3(error)) return {
|
|
104522
104647
|
isError: true,
|
|
104523
104648
|
output: "Grep aborted"
|
|
104524
104649
|
};
|
|
104650
|
+
this.telemetry.track("grep_tool_rg_fallback", { outcome: "failed" });
|
|
104525
104651
|
return {
|
|
104526
104652
|
isError: true,
|
|
104527
104653
|
output: rgUnavailableMessage(error)
|
|
104528
104654
|
};
|
|
104529
104655
|
}
|
|
104530
|
-
let runResult = await runRipgrepOnce(this.kaos, buildRgArgs(rgPath, args, searchPaths), signal);
|
|
104656
|
+
let runResult = await runRipgrepOnce(this.kaos, buildRgArgs(rgPath, args, searchPaths), signal, { abortedMessage: "Grep aborted" });
|
|
104531
104657
|
if (runResult.kind === "tool-error") return runResult.result;
|
|
104532
104658
|
if (shouldRetryRipgrepEagain(runResult)) {
|
|
104533
|
-
runResult = await runRipgrepOnce(this.kaos, buildRgArgs(rgPath, args, searchPaths, true), signal);
|
|
104659
|
+
runResult = await runRipgrepOnce(this.kaos, buildRgArgs(rgPath, args, searchPaths, true), signal, { abortedMessage: "Grep aborted" });
|
|
104534
104660
|
if (runResult.kind === "tool-error") return runResult.result;
|
|
104535
104661
|
}
|
|
104536
104662
|
const { exitCode, stderrText, bufferTruncated, stderrTruncated, timedOut } = runResult;
|
|
@@ -104605,111 +104731,6 @@ var GrepAbortedError = class extends Error {
|
|
|
104605
104731
|
this.name = "GrepAbortedError";
|
|
104606
104732
|
}
|
|
104607
104733
|
};
|
|
104608
|
-
async function runRipgrepOnce(kaos, rgArgs, signal) {
|
|
104609
|
-
if (signal.aborted) return {
|
|
104610
|
-
kind: "tool-error",
|
|
104611
|
-
result: {
|
|
104612
|
-
isError: true,
|
|
104613
|
-
output: "Grep aborted"
|
|
104614
|
-
}
|
|
104615
|
-
};
|
|
104616
|
-
let proc;
|
|
104617
|
-
try {
|
|
104618
|
-
proc = await kaos.exec(...rgArgs);
|
|
104619
|
-
} catch (error) {
|
|
104620
|
-
return {
|
|
104621
|
-
kind: "tool-error",
|
|
104622
|
-
result: {
|
|
104623
|
-
isError: true,
|
|
104624
|
-
output: error instanceof Error && "code" in error && error.code === "ENOENT" ? rgUnavailableMessage(error) : error instanceof Error ? error.message : String(error)
|
|
104625
|
-
}
|
|
104626
|
-
};
|
|
104627
|
-
}
|
|
104628
|
-
try {
|
|
104629
|
-
proc.stdin.end();
|
|
104630
|
-
} catch {}
|
|
104631
|
-
let timedOut = false;
|
|
104632
|
-
let aborted = false;
|
|
104633
|
-
let killed = false;
|
|
104634
|
-
const killProc = async () => {
|
|
104635
|
-
if (killed) return;
|
|
104636
|
-
killed = true;
|
|
104637
|
-
try {
|
|
104638
|
-
await proc.kill("SIGTERM");
|
|
104639
|
-
} catch {}
|
|
104640
|
-
const exited = proc.wait().then(() => true).catch(() => true);
|
|
104641
|
-
if (!await Promise.race([exited, new Promise((resolve) => {
|
|
104642
|
-
setTimeout(() => {
|
|
104643
|
-
resolve(false);
|
|
104644
|
-
}, SIGTERM_GRACE_MS);
|
|
104645
|
-
})]) && proc.exitCode === null) try {
|
|
104646
|
-
await proc.kill("SIGKILL");
|
|
104647
|
-
} catch {}
|
|
104648
|
-
await disposeProcess$1(proc);
|
|
104649
|
-
};
|
|
104650
|
-
const onAbort = () => {
|
|
104651
|
-
aborted = true;
|
|
104652
|
-
killProc();
|
|
104653
|
-
};
|
|
104654
|
-
signal.addEventListener("abort", onAbort);
|
|
104655
|
-
if (signal.aborted) onAbort();
|
|
104656
|
-
const timeoutHandle = setTimeout(() => {
|
|
104657
|
-
timedOut = true;
|
|
104658
|
-
killProc();
|
|
104659
|
-
}, DEFAULT_TIMEOUT_MS$1);
|
|
104660
|
-
let exitCode = 0;
|
|
104661
|
-
let stdoutText = "";
|
|
104662
|
-
let stderrText = "";
|
|
104663
|
-
let bufferTruncated = false;
|
|
104664
|
-
let stderrTruncated = false;
|
|
104665
|
-
try {
|
|
104666
|
-
const isTerminating = () => timedOut || aborted || killed;
|
|
104667
|
-
const [stdoutResult, stderrResult, code] = await Promise.all([
|
|
104668
|
-
readStreamWithCap(proc.stdout, MAX_OUTPUT_BYTES, isTerminating),
|
|
104669
|
-
readStreamWithCap(proc.stderr, MAX_OUTPUT_BYTES, isTerminating),
|
|
104670
|
-
proc.wait()
|
|
104671
|
-
]);
|
|
104672
|
-
stdoutText = stdoutResult.text;
|
|
104673
|
-
stderrText = stderrResult.text;
|
|
104674
|
-
bufferTruncated = stdoutResult.truncated;
|
|
104675
|
-
stderrTruncated = stderrResult.truncated;
|
|
104676
|
-
exitCode = code;
|
|
104677
|
-
} catch (error) {
|
|
104678
|
-
if (isPrematureCloseError(error) && (timedOut || aborted || killed)) {} else return {
|
|
104679
|
-
kind: "tool-error",
|
|
104680
|
-
result: {
|
|
104681
|
-
isError: true,
|
|
104682
|
-
output: error instanceof Error ? error.message : String(error)
|
|
104683
|
-
}
|
|
104684
|
-
};
|
|
104685
|
-
} finally {
|
|
104686
|
-
clearTimeout(timeoutHandle);
|
|
104687
|
-
signal.removeEventListener("abort", onAbort);
|
|
104688
|
-
await disposeProcess$1(proc);
|
|
104689
|
-
}
|
|
104690
|
-
if (aborted) return {
|
|
104691
|
-
kind: "tool-error",
|
|
104692
|
-
result: {
|
|
104693
|
-
isError: true,
|
|
104694
|
-
output: "Grep aborted"
|
|
104695
|
-
}
|
|
104696
|
-
};
|
|
104697
|
-
return {
|
|
104698
|
-
kind: "result",
|
|
104699
|
-
exitCode,
|
|
104700
|
-
stdoutText,
|
|
104701
|
-
stderrText,
|
|
104702
|
-
bufferTruncated,
|
|
104703
|
-
stderrTruncated,
|
|
104704
|
-
timedOut
|
|
104705
|
-
};
|
|
104706
|
-
}
|
|
104707
|
-
function shouldRetryRipgrepEagain(result) {
|
|
104708
|
-
return result.exitCode !== 0 && result.exitCode !== 1 && !result.timedOut && isEagainRipgrepError(result.stderrText);
|
|
104709
|
-
}
|
|
104710
|
-
function isEagainRipgrepError(stderr) {
|
|
104711
|
-
return stderr.includes("os error 11") || stderr.includes("Resource temporarily unavailable");
|
|
104712
|
-
}
|
|
104713
104734
|
async function sortFilesWithMatchesByMtime(lines, kaos, signal) {
|
|
104714
104735
|
const entries = await mapWithConcurrency(lines, MTIME_STAT_CONCURRENCY, signal, async (line, index) => {
|
|
104715
104736
|
const path = line.kind === "record" ? line.filePath : line.kind === "legacy" ? line.text : void 0;
|
|
@@ -104986,32 +105007,6 @@ function countPayloadFromLegacyLine(line) {
|
|
|
104986
105007
|
const idx = line.lastIndexOf(":");
|
|
104987
105008
|
return idx > 0 ? line.slice(idx + 1) : void 0;
|
|
104988
105009
|
}
|
|
104989
|
-
async function readStreamWithCap(stream, maxBytes, suppressPrematureClose) {
|
|
104990
|
-
const chunks = [];
|
|
104991
|
-
let total = 0;
|
|
104992
|
-
let truncated = false;
|
|
104993
|
-
try {
|
|
104994
|
-
for await (const chunk of stream) {
|
|
104995
|
-
const buf = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
104996
|
-
if (truncated) continue;
|
|
104997
|
-
if (total + buf.length > maxBytes) {
|
|
104998
|
-
const remaining = maxBytes - total;
|
|
104999
|
-
if (remaining > 0) chunks.push(buf.subarray(0, remaining));
|
|
105000
|
-
total = maxBytes;
|
|
105001
|
-
truncated = true;
|
|
105002
|
-
continue;
|
|
105003
|
-
}
|
|
105004
|
-
chunks.push(buf);
|
|
105005
|
-
total += buf.length;
|
|
105006
|
-
}
|
|
105007
|
-
} catch (error) {
|
|
105008
|
-
if (!isPrematureCloseError(error) || suppressPrematureClose?.() !== true) throw error;
|
|
105009
|
-
}
|
|
105010
|
-
return {
|
|
105011
|
-
text: Buffer.concat(chunks).toString("utf8"),
|
|
105012
|
-
truncated
|
|
105013
|
-
};
|
|
105014
|
-
}
|
|
105015
105010
|
const IMAGE_MIME_BY_SUFFIX = Object.freeze({
|
|
105016
105011
|
".png": "image/png",
|
|
105017
105012
|
".jpg": "image/jpeg",
|
|
@@ -108540,8 +108535,8 @@ var ToolManager = class {
|
|
|
108540
108535
|
new ReadTool(kaos, workspace),
|
|
108541
108536
|
new WriteTool(kaos, workspace),
|
|
108542
108537
|
new EditTool(kaos, workspace),
|
|
108543
|
-
new GrepTool(kaos, workspace),
|
|
108544
|
-
new GlobTool(kaos, workspace),
|
|
108538
|
+
new GrepTool(kaos, workspace, this.agent.telemetry),
|
|
108539
|
+
new GlobTool(kaos, workspace, this.agent.telemetry),
|
|
108545
108540
|
new BashTool(kaos, cwd, background, { allowBackground }),
|
|
108546
108541
|
(modelCapabilities.image_in || modelCapabilities.video_in) && new ReadMediaFileTool(kaos, workspace, modelCapabilities, videoUploader),
|
|
108547
108542
|
new EnterPlanModeTool(this.agent),
|
|
@@ -108603,7 +108598,7 @@ var ToolManager = class {
|
|
|
108603
108598
|
...base,
|
|
108604
108599
|
outcome: "error",
|
|
108605
108600
|
duration_ms: Date.now() - startedAt,
|
|
108606
|
-
|
|
108601
|
+
error_type: error instanceof Error ? error.name : "Unknown"
|
|
108607
108602
|
});
|
|
108608
108603
|
throw error;
|
|
108609
108604
|
}
|
|
@@ -158254,6 +158249,382 @@ function normalizeOAuthHost(oauthHost) {
|
|
|
158254
158249
|
return oauthHost.trim().replace(/\/+$/, "");
|
|
158255
158250
|
}
|
|
158256
158251
|
//#endregion
|
|
158252
|
+
//#region ../../packages/oauth/src/refreshProviderModels.ts
|
|
158253
|
+
function readProvider(config, providerId) {
|
|
158254
|
+
const provider = config.providers[providerId];
|
|
158255
|
+
if (provider === void 0) return void 0;
|
|
158256
|
+
return provider;
|
|
158257
|
+
}
|
|
158258
|
+
function readModel(config, alias) {
|
|
158259
|
+
const model = config.models?.[alias];
|
|
158260
|
+
if (model === void 0) return void 0;
|
|
158261
|
+
return model;
|
|
158262
|
+
}
|
|
158263
|
+
function readCustomRegistrySource$1(provider) {
|
|
158264
|
+
const source = provider.source;
|
|
158265
|
+
if (typeof source !== "object" || source === null) return void 0;
|
|
158266
|
+
const candidate = source;
|
|
158267
|
+
if (candidate["kind"] !== "apiJson") return void 0;
|
|
158268
|
+
const url = candidate["url"];
|
|
158269
|
+
const apiKey = candidate["apiKey"];
|
|
158270
|
+
if (typeof url !== "string" || url.length === 0) return void 0;
|
|
158271
|
+
if (typeof apiKey !== "string") return void 0;
|
|
158272
|
+
return {
|
|
158273
|
+
kind: "apiJson",
|
|
158274
|
+
url,
|
|
158275
|
+
apiKey
|
|
158276
|
+
};
|
|
158277
|
+
}
|
|
158278
|
+
function customRegistrySourceKey(source) {
|
|
158279
|
+
return JSON.stringify([source.url]);
|
|
158280
|
+
}
|
|
158281
|
+
function customRegistrySourceCredentialKey(source) {
|
|
158282
|
+
return JSON.stringify([source.url, source.apiKey]);
|
|
158283
|
+
}
|
|
158284
|
+
async function fetchCustomRegistryFromSources(sources) {
|
|
158285
|
+
let lastError;
|
|
158286
|
+
for (const source of sources) try {
|
|
158287
|
+
return {
|
|
158288
|
+
entries: await fetchCustomRegistry(source),
|
|
158289
|
+
source
|
|
158290
|
+
};
|
|
158291
|
+
} catch (error) {
|
|
158292
|
+
lastError = error;
|
|
158293
|
+
}
|
|
158294
|
+
if (lastError instanceof Error) throw lastError;
|
|
158295
|
+
if (typeof lastError === "string") throw new Error(lastError);
|
|
158296
|
+
throw new Error("No custom registry sources configured.");
|
|
158297
|
+
}
|
|
158298
|
+
function collectModelIdsForAliases(config, aliasKeys) {
|
|
158299
|
+
const ids = /* @__PURE__ */ new Set();
|
|
158300
|
+
for (const aliasKey of aliasKeys) {
|
|
158301
|
+
const alias = readModel(config, aliasKey);
|
|
158302
|
+
if (alias !== void 0 && alias.model.length > 0) ids.add(alias.model);
|
|
158303
|
+
}
|
|
158304
|
+
return ids;
|
|
158305
|
+
}
|
|
158306
|
+
function providerAliasKeys(config, providerId) {
|
|
158307
|
+
const keys = /* @__PURE__ */ new Set();
|
|
158308
|
+
for (const [alias, raw] of Object.entries(config.models ?? {})) if (raw.provider === providerId) keys.add(alias);
|
|
158309
|
+
return keys;
|
|
158310
|
+
}
|
|
158311
|
+
function generatedProviderAliasKeys(config, providerId, aliasPrefix) {
|
|
158312
|
+
const keys = /* @__PURE__ */ new Set();
|
|
158313
|
+
for (const [alias, raw] of Object.entries(config.models ?? {})) if (raw.provider === providerId && alias.startsWith(aliasPrefix)) keys.add(alias);
|
|
158314
|
+
return keys;
|
|
158315
|
+
}
|
|
158316
|
+
function computeChanges(oldIds, newIds) {
|
|
158317
|
+
let added = 0;
|
|
158318
|
+
for (const id of newIds) if (!oldIds.has(id)) added++;
|
|
158319
|
+
let removed = 0;
|
|
158320
|
+
for (const id of oldIds) if (!newIds.has(id)) removed++;
|
|
158321
|
+
return {
|
|
158322
|
+
added,
|
|
158323
|
+
removed
|
|
158324
|
+
};
|
|
158325
|
+
}
|
|
158326
|
+
function providerModelSnapshot(config, providerId, aliasKeys) {
|
|
158327
|
+
const snapshots = [];
|
|
158328
|
+
for (const alias of aliasKeys) {
|
|
158329
|
+
const model = readModel(config, alias);
|
|
158330
|
+
if (model === void 0 || model.provider !== providerId) continue;
|
|
158331
|
+
snapshots.push({
|
|
158332
|
+
alias,
|
|
158333
|
+
model: {
|
|
158334
|
+
...model,
|
|
158335
|
+
capabilities: model.capabilities === void 0 ? void 0 : model.capabilities.toSorted()
|
|
158336
|
+
}
|
|
158337
|
+
});
|
|
158338
|
+
}
|
|
158339
|
+
snapshots.sort((a, b) => a.alias.localeCompare(b.alias));
|
|
158340
|
+
return JSON.stringify(snapshots);
|
|
158341
|
+
}
|
|
158342
|
+
function providerModelsEqual(config, nextConfig, providerId, aliasKeys) {
|
|
158343
|
+
return providerModelSnapshot(config, providerId, aliasKeys) === providerModelSnapshot(nextConfig, providerId, aliasKeys);
|
|
158344
|
+
}
|
|
158345
|
+
function providerConfigSnapshot(config, providerId) {
|
|
158346
|
+
return JSON.stringify(config.providers[providerId] ?? null);
|
|
158347
|
+
}
|
|
158348
|
+
function providerConfigEqual(config, nextConfig, providerId) {
|
|
158349
|
+
return providerConfigSnapshot(config, providerId) === providerConfigSnapshot(nextConfig, providerId);
|
|
158350
|
+
}
|
|
158351
|
+
function providerRefreshAliasKeys(config, nextConfig, providerId, aliasPrefix) {
|
|
158352
|
+
const keys = generatedProviderAliasKeys(config, providerId, aliasPrefix);
|
|
158353
|
+
for (const key of providerAliasKeys(nextConfig, providerId)) keys.add(key);
|
|
158354
|
+
return keys;
|
|
158355
|
+
}
|
|
158356
|
+
function preserveUserProviderAliases(config, providerId, refreshedAliasKeys) {
|
|
158357
|
+
const preserved = {};
|
|
158358
|
+
for (const [alias, raw] of Object.entries(config.models ?? {})) {
|
|
158359
|
+
const model = raw;
|
|
158360
|
+
if (model.provider !== providerId || refreshedAliasKeys.has(alias)) continue;
|
|
158361
|
+
preserved[alias] = structuredClone(model);
|
|
158362
|
+
}
|
|
158363
|
+
return preserved;
|
|
158364
|
+
}
|
|
158365
|
+
function restoreProviderAliases(config, aliases) {
|
|
158366
|
+
if (Object.keys(aliases).length === 0) return;
|
|
158367
|
+
config.models = {
|
|
158368
|
+
...config.models,
|
|
158369
|
+
...aliases
|
|
158370
|
+
};
|
|
158371
|
+
}
|
|
158372
|
+
function restoreDefaultSelection(config, defaultModel, defaultThinking) {
|
|
158373
|
+
if (defaultModel === void 0 || readModel(config, defaultModel) === void 0) return;
|
|
158374
|
+
config.defaultModel = defaultModel;
|
|
158375
|
+
config.defaultThinking = (readModel(config, defaultModel)?.capabilities ?? []).includes("always_thinking") ? true : defaultThinking;
|
|
158376
|
+
}
|
|
158377
|
+
function clampDanglingDefault(config) {
|
|
158378
|
+
if (config.defaultModel !== void 0 && readModel(config, config.defaultModel) === void 0) {
|
|
158379
|
+
config.defaultModel = void 0;
|
|
158380
|
+
config.defaultThinking = void 0;
|
|
158381
|
+
}
|
|
158382
|
+
}
|
|
158383
|
+
function clearDefaultThinkingWhenDefaultRemoved(config, previousDefaultModel) {
|
|
158384
|
+
if (previousDefaultModel !== void 0 && config.defaultModel === void 0) config.defaultThinking = void 0;
|
|
158385
|
+
}
|
|
158386
|
+
function pickDefaultModel(config, providerId, models) {
|
|
158387
|
+
const firstModel = models[0];
|
|
158388
|
+
if (firstModel === void 0) return "";
|
|
158389
|
+
const existingDefault = config.defaultModel;
|
|
158390
|
+
if (existingDefault !== void 0) {
|
|
158391
|
+
const alias = readModel(config, existingDefault);
|
|
158392
|
+
if (alias !== void 0 && alias.provider === providerId) {
|
|
158393
|
+
const stillAvailable = models.find((m) => m.id === alias.model);
|
|
158394
|
+
if (stillAvailable !== void 0) return stillAvailable.id;
|
|
158395
|
+
}
|
|
158396
|
+
}
|
|
158397
|
+
return firstModel.id;
|
|
158398
|
+
}
|
|
158399
|
+
/**
|
|
158400
|
+
* Refresh remote model metadata for the configured providers and persist any
|
|
158401
|
+
* changes through the host. Handles three provider kinds, in order:
|
|
158402
|
+
*
|
|
158403
|
+
* 1. Managed Kimi Code (OAuth) — `GET /models` against the runtime endpoint.
|
|
158404
|
+
* 2. Open platforms (moonshot-cn, moonshot-ai, …) — platform catalog fetch.
|
|
158405
|
+
* 3. Custom registries (models.dev-style, keyed by `provider.source`).
|
|
158406
|
+
*
|
|
158407
|
+
* Each branch diffs old vs new and only writes when something actually changed
|
|
158408
|
+
* (`removeProvider` then `setConfig`). Failures are collected per-provider and
|
|
158409
|
+
* never abort the whole refresh. Pass `providerId` to scope the refresh to a
|
|
158410
|
+
* single provider; pass `scope: 'oauth'` to refresh only the managed provider.
|
|
158411
|
+
*/
|
|
158412
|
+
async function refreshProviderModels(host, options = {}) {
|
|
158413
|
+
const changed = [];
|
|
158414
|
+
const unchanged = [];
|
|
158415
|
+
const failed = [];
|
|
158416
|
+
const scope = options.scope ?? "all";
|
|
158417
|
+
const targetId = options.providerId;
|
|
158418
|
+
let config = await host.getConfig();
|
|
158419
|
+
const managedProvider = readProvider(config, KIMI_CODE_PROVIDER_NAME$1);
|
|
158420
|
+
if ((targetId === void 0 || targetId === "managed:kimi-code") && managedProvider !== void 0 && managedProvider.type === "kimi" && managedProvider.oauth !== void 0) try {
|
|
158421
|
+
const auth = resolveKimiCodeRuntimeAuth({
|
|
158422
|
+
configuredBaseUrl: managedProvider.baseUrl,
|
|
158423
|
+
configuredOAuthRef: managedProvider.oauth
|
|
158424
|
+
});
|
|
158425
|
+
const models = await fetchManagedKimiCodeModels({
|
|
158426
|
+
accessToken: await host.resolveOAuthToken(KIMI_CODE_PROVIDER_NAME$1, auth.oauthRef),
|
|
158427
|
+
baseUrl: auth.baseUrl
|
|
158428
|
+
});
|
|
158429
|
+
if (models.length > 0) {
|
|
158430
|
+
const next = structuredClone(config);
|
|
158431
|
+
applyManagedKimiCodeConfig(next, {
|
|
158432
|
+
models,
|
|
158433
|
+
baseUrl: auth.baseUrl,
|
|
158434
|
+
oauthKey: auth.oauthRef.key,
|
|
158435
|
+
oauthHost: auth.oauthRef.oauthHost,
|
|
158436
|
+
preserveDefaultModel: true
|
|
158437
|
+
});
|
|
158438
|
+
const refreshedAliasKeys = providerRefreshAliasKeys(config, next, KIMI_CODE_PROVIDER_NAME$1, `${KIMI_CODE_PLATFORM_ID}/`);
|
|
158439
|
+
restoreProviderAliases(next, preserveUserProviderAliases(config, KIMI_CODE_PROVIDER_NAME$1, refreshedAliasKeys));
|
|
158440
|
+
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
|
|
158441
|
+
clampDanglingDefault(next);
|
|
158442
|
+
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
|
|
158443
|
+
if (providerModelsEqual(config, next, "managed:kimi-code", refreshedAliasKeys)) unchanged.push(KIMI_CODE_PROVIDER_NAME$1);
|
|
158444
|
+
else {
|
|
158445
|
+
const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
|
|
158446
|
+
await host.removeProvider(KIMI_CODE_PROVIDER_NAME$1);
|
|
158447
|
+
config = await host.setConfig({
|
|
158448
|
+
providers: next.providers,
|
|
158449
|
+
models: next.models,
|
|
158450
|
+
defaultModel: next.defaultModel,
|
|
158451
|
+
defaultThinking: next.defaultThinking
|
|
158452
|
+
});
|
|
158453
|
+
changed.push({
|
|
158454
|
+
providerId: KIMI_CODE_PROVIDER_NAME$1,
|
|
158455
|
+
providerName: "Kimi Code",
|
|
158456
|
+
added,
|
|
158457
|
+
removed
|
|
158458
|
+
});
|
|
158459
|
+
}
|
|
158460
|
+
}
|
|
158461
|
+
} catch (error) {
|
|
158462
|
+
failed.push({
|
|
158463
|
+
provider: KIMI_CODE_PROVIDER_NAME$1,
|
|
158464
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
158465
|
+
});
|
|
158466
|
+
}
|
|
158467
|
+
if (scope === "oauth" || targetId === "managed:kimi-code") return {
|
|
158468
|
+
changed,
|
|
158469
|
+
unchanged,
|
|
158470
|
+
failed
|
|
158471
|
+
};
|
|
158472
|
+
const openPlatformIds = Object.keys(config.providers).filter((id) => isOpenPlatformId(id));
|
|
158473
|
+
for (const providerId of openPlatformIds) {
|
|
158474
|
+
if (targetId !== void 0 && targetId !== providerId) continue;
|
|
158475
|
+
const platform = getOpenPlatformById(providerId);
|
|
158476
|
+
if (platform === void 0) continue;
|
|
158477
|
+
const providerConfig = readProvider(config, providerId);
|
|
158478
|
+
if (providerConfig === void 0) continue;
|
|
158479
|
+
const apiKey = providerConfig.apiKey;
|
|
158480
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) continue;
|
|
158481
|
+
try {
|
|
158482
|
+
let models = await fetchOpenPlatformModels(platform, apiKey);
|
|
158483
|
+
models = filterModelsByPrefix(models, platform);
|
|
158484
|
+
if (models.length === 0) continue;
|
|
158485
|
+
const selectedModelId = pickDefaultModel(config, providerId, models);
|
|
158486
|
+
const selectedModel = models.find((m) => m.id === selectedModelId);
|
|
158487
|
+
if (selectedModel === void 0) continue;
|
|
158488
|
+
const next = structuredClone(config);
|
|
158489
|
+
applyOpenPlatformConfig(next, {
|
|
158490
|
+
platform,
|
|
158491
|
+
models,
|
|
158492
|
+
selectedModel,
|
|
158493
|
+
thinking: false,
|
|
158494
|
+
apiKey
|
|
158495
|
+
});
|
|
158496
|
+
const refreshedAliasKeys = providerRefreshAliasKeys(config, next, providerId, `${providerId}/`);
|
|
158497
|
+
restoreProviderAliases(next, preserveUserProviderAliases(config, providerId, refreshedAliasKeys));
|
|
158498
|
+
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
|
|
158499
|
+
clampDanglingDefault(next);
|
|
158500
|
+
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
|
|
158501
|
+
if (providerModelsEqual(config, next, providerId, refreshedAliasKeys)) unchanged.push(providerId);
|
|
158502
|
+
else {
|
|
158503
|
+
const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
|
|
158504
|
+
await host.removeProvider(providerId);
|
|
158505
|
+
config = await host.setConfig({
|
|
158506
|
+
providers: next.providers,
|
|
158507
|
+
models: next.models,
|
|
158508
|
+
defaultModel: next.defaultModel,
|
|
158509
|
+
defaultThinking: next.defaultThinking
|
|
158510
|
+
});
|
|
158511
|
+
changed.push({
|
|
158512
|
+
providerId,
|
|
158513
|
+
providerName: platform.name,
|
|
158514
|
+
added,
|
|
158515
|
+
removed
|
|
158516
|
+
});
|
|
158517
|
+
}
|
|
158518
|
+
} catch (error) {
|
|
158519
|
+
failed.push({
|
|
158520
|
+
provider: providerId,
|
|
158521
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
158522
|
+
});
|
|
158523
|
+
}
|
|
158524
|
+
}
|
|
158525
|
+
const customSources = /* @__PURE__ */ new Map();
|
|
158526
|
+
for (const providerId of Object.keys(config.providers)) {
|
|
158527
|
+
if (providerId === "managed:kimi-code") continue;
|
|
158528
|
+
if (isOpenPlatformId(providerId)) continue;
|
|
158529
|
+
const provider = readProvider(config, providerId);
|
|
158530
|
+
if (provider === void 0) continue;
|
|
158531
|
+
const source = readCustomRegistrySource$1(provider);
|
|
158532
|
+
if (source === void 0) continue;
|
|
158533
|
+
const key = customRegistrySourceKey(source);
|
|
158534
|
+
const sourceKey = customRegistrySourceCredentialKey(source);
|
|
158535
|
+
const entry = customSources.get(key);
|
|
158536
|
+
if (entry !== void 0) {
|
|
158537
|
+
if (!entry.sourceKeys.has(sourceKey)) {
|
|
158538
|
+
entry.sources.push(source);
|
|
158539
|
+
entry.sourceKeys.add(sourceKey);
|
|
158540
|
+
}
|
|
158541
|
+
entry.providerIds.push(providerId);
|
|
158542
|
+
} else customSources.set(key, {
|
|
158543
|
+
sources: [source],
|
|
158544
|
+
sourceKeys: new Set([sourceKey]),
|
|
158545
|
+
providerIds: [providerId]
|
|
158546
|
+
});
|
|
158547
|
+
}
|
|
158548
|
+
for (const { sources, providerIds } of customSources.values()) {
|
|
158549
|
+
if (targetId !== void 0 && !providerIds.includes(targetId)) continue;
|
|
158550
|
+
try {
|
|
158551
|
+
const { entries, source } = await fetchCustomRegistryFromSources(sources);
|
|
158552
|
+
const next = structuredClone(config);
|
|
158553
|
+
const changedProviders = [];
|
|
158554
|
+
const providersToRemoveBeforeSet = /* @__PURE__ */ new Set();
|
|
158555
|
+
let hasUnreportedConfigChange = false;
|
|
158556
|
+
const remoteEntries = Object.values(entries);
|
|
158557
|
+
const remoteEntriesByProviderId = new Map(remoteEntries.map((entry) => [entry.id, entry]));
|
|
158558
|
+
const providerIdsToSync = new Set(providerIds);
|
|
158559
|
+
if (targetId === void 0) for (const entry of remoteEntries) providerIdsToSync.add(entry.id);
|
|
158560
|
+
for (const providerId of providerIdsToSync) {
|
|
158561
|
+
if (targetId !== void 0 && providerId !== targetId) continue;
|
|
158562
|
+
const entry = remoteEntriesByProviderId.get(providerId);
|
|
158563
|
+
if (entry === void 0) {
|
|
158564
|
+
const oldIds = collectModelIdsForAliases(config, providerAliasKeys(config, providerId));
|
|
158565
|
+
removeCustomRegistryProvider(next, providerId);
|
|
158566
|
+
changedProviders.push({
|
|
158567
|
+
providerId,
|
|
158568
|
+
providerName: providerId,
|
|
158569
|
+
added: 0,
|
|
158570
|
+
removed: oldIds.size
|
|
158571
|
+
});
|
|
158572
|
+
providersToRemoveBeforeSet.add(providerId);
|
|
158573
|
+
continue;
|
|
158574
|
+
}
|
|
158575
|
+
const existed = config.providers[providerId] !== void 0;
|
|
158576
|
+
applyCustomRegistryProvider(next, entry, source);
|
|
158577
|
+
const refreshedAliasKeys = providerRefreshAliasKeys(config, next, providerId, `${providerId}/`);
|
|
158578
|
+
if (existed) restoreProviderAliases(next, preserveUserProviderAliases(config, providerId, refreshedAliasKeys));
|
|
158579
|
+
if (existed && providerModelsEqual(config, next, providerId, refreshedAliasKeys) && providerConfigEqual(config, next, providerId)) unchanged.push(providerId);
|
|
158580
|
+
else if (existed && providerModelsEqual(config, next, providerId, refreshedAliasKeys)) {
|
|
158581
|
+
unchanged.push(providerId);
|
|
158582
|
+
providersToRemoveBeforeSet.add(providerId);
|
|
158583
|
+
hasUnreportedConfigChange = true;
|
|
158584
|
+
} else {
|
|
158585
|
+
const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
|
|
158586
|
+
changedProviders.push({
|
|
158587
|
+
providerId,
|
|
158588
|
+
providerName: entry.name || providerId,
|
|
158589
|
+
added,
|
|
158590
|
+
removed
|
|
158591
|
+
});
|
|
158592
|
+
if (existed) providersToRemoveBeforeSet.add(providerId);
|
|
158593
|
+
}
|
|
158594
|
+
}
|
|
158595
|
+
if (changedProviders.length > 0 || hasUnreportedConfigChange) {
|
|
158596
|
+
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
|
|
158597
|
+
clampDanglingDefault(next);
|
|
158598
|
+
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
|
|
158599
|
+
for (const providerId of providersToRemoveBeforeSet) await host.removeProvider(providerId);
|
|
158600
|
+
config = await host.setConfig({
|
|
158601
|
+
providers: next.providers,
|
|
158602
|
+
models: next.models,
|
|
158603
|
+
defaultModel: next.defaultModel,
|
|
158604
|
+
defaultThinking: next.defaultThinking
|
|
158605
|
+
});
|
|
158606
|
+
for (const change of changedProviders) changed.push({
|
|
158607
|
+
providerId: change.providerId,
|
|
158608
|
+
providerName: change.providerName,
|
|
158609
|
+
added: change.added,
|
|
158610
|
+
removed: change.removed
|
|
158611
|
+
});
|
|
158612
|
+
}
|
|
158613
|
+
} catch (error) {
|
|
158614
|
+
const reportedIds = targetId !== void 0 ? [targetId] : providerIds;
|
|
158615
|
+
for (const providerId of reportedIds) failed.push({
|
|
158616
|
+
provider: providerId,
|
|
158617
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
158618
|
+
});
|
|
158619
|
+
}
|
|
158620
|
+
}
|
|
158621
|
+
return {
|
|
158622
|
+
changed,
|
|
158623
|
+
unchanged,
|
|
158624
|
+
failed
|
|
158625
|
+
};
|
|
158626
|
+
}
|
|
158627
|
+
//#endregion
|
|
158257
158628
|
//#region ../../packages/agent-core/src/session/provider-manager.ts
|
|
158258
158629
|
var ProviderManager = class {
|
|
158259
158630
|
options;
|
|
@@ -160889,16 +161260,12 @@ function telemetryErrorReason(error) {
|
|
|
160889
161260
|
}
|
|
160890
161261
|
function clientTelemetryProperties(client) {
|
|
160891
161262
|
if (client === void 0) return {};
|
|
160892
|
-
|
|
160893
|
-
|
|
160894
|
-
|
|
160895
|
-
|
|
160896
|
-
|
|
160897
|
-
|
|
160898
|
-
}
|
|
160899
|
-
function addNonEmpty(target, key, value) {
|
|
160900
|
-
const trimmed = value?.trim();
|
|
160901
|
-
if (trimmed !== void 0 && trimmed.length > 0) target[key] = trimmed;
|
|
161263
|
+
return {
|
|
161264
|
+
client_id: client.id ?? null,
|
|
161265
|
+
client_name: client.name ?? null,
|
|
161266
|
+
client_version: client.version ?? null,
|
|
161267
|
+
ui_mode: client.uiMode ?? null
|
|
161268
|
+
};
|
|
160902
161269
|
}
|
|
160903
161270
|
async function resumeSessionResult(summary, session, warning) {
|
|
160904
161271
|
const api = new SessionAPIImpl(session);
|
|
@@ -163600,10 +163967,12 @@ let FsSearchService = class FsSearchService extends Disposable {
|
|
|
163600
163967
|
gitignoreCache = /* @__PURE__ */ new Map();
|
|
163601
163968
|
rgPath = void 0;
|
|
163602
163969
|
rgMissingWarned = false;
|
|
163603
|
-
|
|
163970
|
+
telemetry;
|
|
163971
|
+
constructor(telemetry, sessions, logger) {
|
|
163604
163972
|
super();
|
|
163605
163973
|
this.sessions = sessions;
|
|
163606
163974
|
this.logger = logger;
|
|
163975
|
+
this.telemetry = telemetry;
|
|
163607
163976
|
}
|
|
163608
163977
|
dispose() {
|
|
163609
163978
|
this.gitignoreCache.clear();
|
|
@@ -163650,6 +164019,7 @@ let FsSearchService = class FsSearchService extends Disposable {
|
|
|
163650
164019
|
try {
|
|
163651
164020
|
const rg = await this.probeRg();
|
|
163652
164021
|
if (rg !== null) return await this.grepWithRg(rg, realCwd, req, abortController.signal, startedAt);
|
|
164022
|
+
this.telemetry.track("fs_grep_node_fallback", { reason: "rg_missing" });
|
|
163653
164023
|
return await this.grepWithNode(realCwd, req, abortController.signal, startedAt);
|
|
163654
164024
|
} finally {
|
|
163655
164025
|
clearTimeout(timeoutHandle);
|
|
@@ -163920,7 +164290,7 @@ let FsSearchService = class FsSearchService extends Disposable {
|
|
|
163920
164290
|
return ig;
|
|
163921
164291
|
}
|
|
163922
164292
|
};
|
|
163923
|
-
FsSearchService = __decorate([__decorateParam(
|
|
164293
|
+
FsSearchService = __decorate([__decorateParam(1, ISessionService), __decorateParam(2, ILogService)], FsSearchService);
|
|
163924
164294
|
function computeFuzzyScore(name, queryLower) {
|
|
163925
164295
|
if (queryLower.length === 0) return 0;
|
|
163926
164296
|
const nameLower = name.toLowerCase();
|
|
@@ -164034,7 +164404,7 @@ async function whichBinary(name) {
|
|
|
164034
164404
|
}
|
|
164035
164405
|
return null;
|
|
164036
164406
|
}
|
|
164037
|
-
registerSingleton(IFsSearchService, FsSearchService,
|
|
164407
|
+
registerSingleton(IFsSearchService, new SyncDescriptor(FsSearchService, [noopTelemetryClient], true));
|
|
164038
164408
|
//#endregion
|
|
164039
164409
|
//#region ../../packages/agent-core/src/services/fs/fsGit.ts
|
|
164040
164410
|
var FsGitUnavailableError = class extends Error {
|
|
@@ -167252,15 +167622,20 @@ function globalDefaultForProvider(config, providerId) {
|
|
|
167252
167622
|
var _ModelCatalogService;
|
|
167253
167623
|
let ModelCatalogService = _ModelCatalogService = class ModelCatalogService extends Disposable {
|
|
167254
167624
|
core;
|
|
167625
|
+
eventService;
|
|
167255
167626
|
_serviceBrand;
|
|
167256
167627
|
_authFacade;
|
|
167257
|
-
|
|
167628
|
+
/** Serializes refresh runs so a scheduled refresh and a manual one (or two
|
|
167629
|
+
* manual ones with different options) never race on writing config.toml. */
|
|
167630
|
+
_refreshChain = Promise.resolve();
|
|
167631
|
+
constructor(env, core, eventService) {
|
|
167258
167632
|
super();
|
|
167259
167633
|
this.core = core;
|
|
167634
|
+
this.eventService = eventService;
|
|
167260
167635
|
this._authFacade = createManagedAuthFacade(env);
|
|
167261
167636
|
}
|
|
167262
|
-
static _createForTest(env, core, authFacade) {
|
|
167263
|
-
const service = new _ModelCatalogService(env, core);
|
|
167637
|
+
static _createForTest(env, core, authFacade, eventService = noopEventService) {
|
|
167638
|
+
const service = new _ModelCatalogService(env, core, eventService);
|
|
167264
167639
|
service._authFacade = authFacade;
|
|
167265
167640
|
return service;
|
|
167266
167641
|
}
|
|
@@ -167289,74 +167664,44 @@ let ModelCatalogService = _ModelCatalogService = class ModelCatalogService exten
|
|
|
167289
167664
|
};
|
|
167290
167665
|
}
|
|
167291
167666
|
async refreshOAuthProviderModels() {
|
|
167292
|
-
|
|
167293
|
-
|
|
167294
|
-
|
|
167295
|
-
const
|
|
167296
|
-
|
|
167297
|
-
|
|
167298
|
-
|
|
167299
|
-
|
|
167300
|
-
|
|
167301
|
-
|
|
167302
|
-
try {
|
|
167303
|
-
const auth = resolveKimiCodeRuntimeAuth({
|
|
167304
|
-
configuredBaseUrl: provider.baseUrl,
|
|
167305
|
-
configuredOAuthRef: provider.oauth
|
|
167306
|
-
});
|
|
167307
|
-
const tokenProvider = this._authFacade.resolveOAuthTokenProvider(KIMI_CODE_PROVIDER_NAME$1, auth.oauthRef);
|
|
167308
|
-
if (tokenProvider === void 0) throw new Error("OAuth token provider is not configured.");
|
|
167309
|
-
const models = await fetchManagedKimiCodeModels({
|
|
167310
|
-
accessToken: await tokenProvider.getAccessToken(),
|
|
167311
|
-
baseUrl: auth.baseUrl,
|
|
167312
|
-
headers: this.core.kimiRequestHeaders
|
|
167313
|
-
});
|
|
167314
|
-
if (models.length === 0) return {
|
|
167315
|
-
changed,
|
|
167316
|
-
unchanged,
|
|
167317
|
-
failed
|
|
167318
|
-
};
|
|
167319
|
-
const next = structuredClone(config);
|
|
167320
|
-
applyManagedKimiCodeConfig(next, {
|
|
167321
|
-
models,
|
|
167322
|
-
baseUrl: auth.baseUrl,
|
|
167323
|
-
oauthKey: auth.oauthRef.key,
|
|
167324
|
-
oauthHost: auth.oauthRef.oauthHost,
|
|
167325
|
-
preserveDefaultModel: true
|
|
167326
|
-
});
|
|
167327
|
-
const refreshedAliasKeys = providerRefreshAliasKeys$1(config, next, KIMI_CODE_PROVIDER_NAME$1, `${KIMI_CODE_PLATFORM_ID}/`);
|
|
167328
|
-
restoreProviderAliases$1(next, preserveUserProviderAliases$1(config, KIMI_CODE_PROVIDER_NAME$1, refreshedAliasKeys));
|
|
167329
|
-
restoreDefaultSelection$1(next, config.defaultModel, config.defaultThinking);
|
|
167330
|
-
clampDanglingDefault$1(next);
|
|
167331
|
-
if (providerModelsEqual$1(config, next, "managed:kimi-code", refreshedAliasKeys)) unchanged.push(KIMI_CODE_PROVIDER_NAME$1);
|
|
167332
|
-
else {
|
|
167333
|
-
const { added, removed } = computeChanges$1(collectModelIdsForAliases$1(config, refreshedAliasKeys), collectModelIdsForAliases$1(next, refreshedAliasKeys));
|
|
167334
|
-
await this.core.rpc.removeKimiProvider({ providerId: KIMI_CODE_PROVIDER_NAME$1 });
|
|
167335
|
-
await this.core.rpc.setKimiConfig({
|
|
167336
|
-
providers: next.providers,
|
|
167337
|
-
models: next.models,
|
|
167338
|
-
defaultModel: next.defaultModel,
|
|
167339
|
-
defaultThinking: next.defaultThinking
|
|
167340
|
-
});
|
|
167341
|
-
changed.push({
|
|
167342
|
-
provider_id: KIMI_CODE_PROVIDER_NAME$1,
|
|
167343
|
-
provider_name: "Kimi Code",
|
|
167344
|
-
added,
|
|
167345
|
-
removed
|
|
167346
|
-
});
|
|
167347
|
-
}
|
|
167348
|
-
} catch (err) {
|
|
167349
|
-
failed.push({
|
|
167350
|
-
provider: KIMI_CODE_PROVIDER_NAME$1,
|
|
167351
|
-
reason: err instanceof Error ? err.message : String(err)
|
|
167352
|
-
});
|
|
167667
|
+
return this.refreshProviderModels({ scope: "oauth" });
|
|
167668
|
+
}
|
|
167669
|
+
refreshProviderModels(options = {}) {
|
|
167670
|
+
const run = this._refreshChain.then(() => this._doRefreshProviderModels(options));
|
|
167671
|
+
this._refreshChain = run.then(() => void 0, () => void 0);
|
|
167672
|
+
return run;
|
|
167673
|
+
}
|
|
167674
|
+
async _doRefreshProviderModels(options) {
|
|
167675
|
+
if (options.providerId !== void 0) {
|
|
167676
|
+
if ((await this._readConfig()).providers?.[options.providerId] === void 0) throw new ProviderNotFoundError(options.providerId);
|
|
167353
167677
|
}
|
|
167678
|
+
const response = mapRefreshResult(await refreshProviderModels(this._buildRefreshHost(), {
|
|
167679
|
+
scope: options.scope,
|
|
167680
|
+
providerId: options.providerId
|
|
167681
|
+
}));
|
|
167682
|
+
if (response.changed.length > 0) this.eventService.publish({
|
|
167683
|
+
type: "event.model_catalog.changed",
|
|
167684
|
+
agentId: "main",
|
|
167685
|
+
sessionId: "__global__",
|
|
167686
|
+
changed: response.changed,
|
|
167687
|
+
unchanged: response.unchanged,
|
|
167688
|
+
failed: response.failed
|
|
167689
|
+
});
|
|
167690
|
+
return response;
|
|
167691
|
+
}
|
|
167692
|
+
_buildRefreshHost() {
|
|
167354
167693
|
return {
|
|
167355
|
-
|
|
167356
|
-
|
|
167357
|
-
|
|
167694
|
+
getConfig: () => this._readConfig(),
|
|
167695
|
+
removeProvider: (providerId) => this.core.rpc.removeKimiProvider({ providerId }),
|
|
167696
|
+
setConfig: (patch) => this.core.rpc.setKimiConfig(patch),
|
|
167697
|
+
resolveOAuthToken: (providerName, oauthRef) => this._resolveOAuthToken(providerName, oauthRef)
|
|
167358
167698
|
};
|
|
167359
167699
|
}
|
|
167700
|
+
async _resolveOAuthToken(providerName, oauthRef) {
|
|
167701
|
+
const tokenProvider = this._authFacade.resolveOAuthTokenProvider(providerName, oauthRef);
|
|
167702
|
+
if (tokenProvider === void 0) throw new Error("OAuth token provider is not configured.");
|
|
167703
|
+
return tokenProvider.getAccessToken();
|
|
167704
|
+
}
|
|
167360
167705
|
async _readConfig() {
|
|
167361
167706
|
return this.core.rpc.getKimiConfig({ reload: true });
|
|
167362
167707
|
}
|
|
@@ -167375,7 +167720,26 @@ let ModelCatalogService = _ModelCatalogService = class ModelCatalogService exten
|
|
|
167375
167720
|
}
|
|
167376
167721
|
}
|
|
167377
167722
|
};
|
|
167378
|
-
ModelCatalogService = _ModelCatalogService = __decorate([
|
|
167723
|
+
ModelCatalogService = _ModelCatalogService = __decorate([
|
|
167724
|
+
__decorateParam(0, IEnvironmentService),
|
|
167725
|
+
__decorateParam(1, ICoreProcessService),
|
|
167726
|
+
__decorateParam(2, IEventService)
|
|
167727
|
+
], ModelCatalogService);
|
|
167728
|
+
function mapRefreshResult(result) {
|
|
167729
|
+
return {
|
|
167730
|
+
changed: result.changed.map((change) => ({
|
|
167731
|
+
provider_id: change.providerId,
|
|
167732
|
+
provider_name: change.providerName,
|
|
167733
|
+
added: change.added,
|
|
167734
|
+
removed: change.removed
|
|
167735
|
+
})),
|
|
167736
|
+
unchanged: [...result.unchanged],
|
|
167737
|
+
failed: result.failed.map((failure) => ({
|
|
167738
|
+
provider: failure.provider,
|
|
167739
|
+
reason: failure.reason
|
|
167740
|
+
}))
|
|
167741
|
+
};
|
|
167742
|
+
}
|
|
167379
167743
|
function hasConfiguredApiKey(provider) {
|
|
167380
167744
|
if (nonEmpty$1(provider.apiKey) !== void 0) return true;
|
|
167381
167745
|
switch (provider.type) {
|
|
@@ -167388,89 +167752,16 @@ function hasConfiguredApiKey(provider) {
|
|
|
167388
167752
|
}
|
|
167389
167753
|
return false;
|
|
167390
167754
|
}
|
|
167391
|
-
function collectModelIdsForAliases$1(config, aliasKeys) {
|
|
167392
|
-
const ids = /* @__PURE__ */ new Set();
|
|
167393
|
-
for (const aliasKey of aliasKeys) {
|
|
167394
|
-
const alias = config.models?.[aliasKey];
|
|
167395
|
-
if (alias !== void 0 && alias.model.length > 0) ids.add(alias.model);
|
|
167396
|
-
}
|
|
167397
|
-
return ids;
|
|
167398
|
-
}
|
|
167399
|
-
function providerAliasKeys$1(config, providerId) {
|
|
167400
|
-
const keys = /* @__PURE__ */ new Set();
|
|
167401
|
-
for (const [alias, model] of Object.entries(config.models ?? {})) if (model.provider === providerId) keys.add(alias);
|
|
167402
|
-
return keys;
|
|
167403
|
-
}
|
|
167404
|
-
function generatedProviderAliasKeys$1(config, providerId, aliasPrefix) {
|
|
167405
|
-
const keys = /* @__PURE__ */ new Set();
|
|
167406
|
-
for (const [alias, model] of Object.entries(config.models ?? {})) if (model.provider === providerId && alias.startsWith(aliasPrefix)) keys.add(alias);
|
|
167407
|
-
return keys;
|
|
167408
|
-
}
|
|
167409
|
-
function computeChanges$1(oldIds, newIds) {
|
|
167410
|
-
let added = 0;
|
|
167411
|
-
for (const id of newIds) if (!oldIds.has(id)) added++;
|
|
167412
|
-
let removed = 0;
|
|
167413
|
-
for (const id of oldIds) if (!newIds.has(id)) removed++;
|
|
167414
|
-
return {
|
|
167415
|
-
added,
|
|
167416
|
-
removed
|
|
167417
|
-
};
|
|
167418
|
-
}
|
|
167419
|
-
function providerModelsEqual$1(config, nextConfig, providerId, aliasKeys) {
|
|
167420
|
-
return providerModelSnapshot$1(config, providerId, aliasKeys) === providerModelSnapshot$1(nextConfig, providerId, aliasKeys);
|
|
167421
|
-
}
|
|
167422
|
-
function providerModelSnapshot$1(config, providerId, aliasKeys) {
|
|
167423
|
-
const snapshots = [];
|
|
167424
|
-
for (const alias of aliasKeys) {
|
|
167425
|
-
const model = config.models?.[alias];
|
|
167426
|
-
if (model === void 0 || model.provider !== providerId) continue;
|
|
167427
|
-
snapshots.push({
|
|
167428
|
-
alias,
|
|
167429
|
-
model: {
|
|
167430
|
-
...model,
|
|
167431
|
-
capabilities: model.capabilities === void 0 ? void 0 : model.capabilities.toSorted()
|
|
167432
|
-
}
|
|
167433
|
-
});
|
|
167434
|
-
}
|
|
167435
|
-
snapshots.sort((a, b) => a.alias.localeCompare(b.alias));
|
|
167436
|
-
return JSON.stringify(snapshots);
|
|
167437
|
-
}
|
|
167438
|
-
function providerRefreshAliasKeys$1(config, nextConfig, providerId, aliasPrefix) {
|
|
167439
|
-
const keys = generatedProviderAliasKeys$1(config, providerId, aliasPrefix);
|
|
167440
|
-
for (const key of providerAliasKeys$1(nextConfig, providerId)) keys.add(key);
|
|
167441
|
-
return keys;
|
|
167442
|
-
}
|
|
167443
|
-
function preserveUserProviderAliases$1(config, providerId, refreshedAliasKeys) {
|
|
167444
|
-
const preserved = {};
|
|
167445
|
-
for (const [alias, model] of Object.entries(config.models ?? {})) {
|
|
167446
|
-
if (model.provider !== providerId || refreshedAliasKeys.has(alias)) continue;
|
|
167447
|
-
preserved[alias] = structuredClone(model);
|
|
167448
|
-
}
|
|
167449
|
-
return preserved;
|
|
167450
|
-
}
|
|
167451
|
-
function restoreProviderAliases$1(config, aliases) {
|
|
167452
|
-
if (Object.keys(aliases).length === 0) return;
|
|
167453
|
-
config.models = {
|
|
167454
|
-
...config.models,
|
|
167455
|
-
...aliases
|
|
167456
|
-
};
|
|
167457
|
-
}
|
|
167458
|
-
function restoreDefaultSelection$1(config, defaultModel, defaultThinking) {
|
|
167459
|
-
if (defaultModel === void 0 || config.models?.[defaultModel] === void 0) return;
|
|
167460
|
-
config.defaultModel = defaultModel;
|
|
167461
|
-
config.defaultThinking = (config.models[defaultModel]?.capabilities ?? []).includes("always_thinking") ? true : defaultThinking;
|
|
167462
|
-
}
|
|
167463
|
-
function clampDanglingDefault$1(config) {
|
|
167464
|
-
if (config.defaultModel !== void 0 && config.models?.[config.defaultModel] === void 0) {
|
|
167465
|
-
config.defaultModel = void 0;
|
|
167466
|
-
config.defaultThinking = void 0;
|
|
167467
|
-
}
|
|
167468
|
-
}
|
|
167469
167755
|
function nonEmpty$1(value) {
|
|
167470
167756
|
if (value === void 0) return void 0;
|
|
167471
167757
|
const trimmed = value.trim();
|
|
167472
167758
|
return trimmed.length === 0 ? void 0 : trimmed;
|
|
167473
167759
|
}
|
|
167760
|
+
const noopEventService = {
|
|
167761
|
+
_serviceBrand: void 0,
|
|
167762
|
+
onDidPublish: () => ({ dispose: () => void 0 }),
|
|
167763
|
+
publish: () => void 0
|
|
167764
|
+
};
|
|
167474
167765
|
registerSingleton(IModelCatalogService, ModelCatalogService, 1);
|
|
167475
167766
|
//#endregion
|
|
167476
167767
|
//#region ../../packages/agent-core/src/services/config/config.ts
|
|
@@ -170793,6 +171084,7 @@ var KimiHarness = class {
|
|
|
170793
171084
|
withTelemetryContext$1(this.telemetry, { sessionId: eventSessionId }).track("session_started", {
|
|
170794
171085
|
...this.sessionStartedProperties,
|
|
170795
171086
|
...sessionScoped,
|
|
171087
|
+
client_id: null,
|
|
170796
171088
|
client_name: this.identity?.userAgentProduct ?? null,
|
|
170797
171089
|
client_version: this.identity?.version ?? null,
|
|
170798
171090
|
ui_mode: this.uiMode,
|
|
@@ -193111,7 +193403,7 @@ var AcpSession = class {
|
|
|
193111
193403
|
}
|
|
193112
193404
|
}));
|
|
193113
193405
|
if (answer === null) this.emitTelemetry("question_dismissed");
|
|
193114
|
-
else this.emitTelemetry("question_answered");
|
|
193406
|
+
else this.emitTelemetry("question_answered", { answered: Object.keys(answer).length });
|
|
193115
193407
|
return answer;
|
|
193116
193408
|
} catch (err) {
|
|
193117
193409
|
log.warn("acp: requestPermission (question) failed; dismissing", {
|
|
@@ -194959,7 +195251,7 @@ async function handleProviderAdd$1(deps, url, opts) {
|
|
|
194959
195251
|
const addedProviderIds = [];
|
|
194960
195252
|
let modelCount = 0;
|
|
194961
195253
|
for (const entry of entryList) {
|
|
194962
|
-
applyCustomRegistryProvider(asManaged
|
|
195254
|
+
applyCustomRegistryProvider(asManaged(config), entry, source);
|
|
194963
195255
|
addedProviderIds.push(entry.id);
|
|
194964
195256
|
modelCount += Object.keys(entry.models).length;
|
|
194965
195257
|
}
|
|
@@ -195201,7 +195493,7 @@ function resolveApiKey(flag, env) {
|
|
|
195201
195493
|
const fromEnv = env["KIMI_REGISTRY_API_KEY"];
|
|
195202
195494
|
if (typeof fromEnv === "string" && fromEnv.length > 0) return fromEnv;
|
|
195203
195495
|
}
|
|
195204
|
-
function asManaged
|
|
195496
|
+
function asManaged(config) {
|
|
195205
195497
|
return config;
|
|
195206
195498
|
}
|
|
195207
195499
|
function providerSourceLabel(provider) {
|
|
@@ -224670,7 +224962,7 @@ function extractSessionId(event) {
|
|
|
224670
224962
|
if (typeof snake === "string" && snake.length > 0) return snake;
|
|
224671
224963
|
}
|
|
224672
224964
|
function isGlobalSessionEvent(type) {
|
|
224673
|
-
return type === "event.session.created" || type === "event.session.status_changed" || type === "session.meta.updated" || type === "event.config.changed" || type === "event.workspace.created" || type === "event.workspace.updated" || type === "event.workspace.deleted";
|
|
224965
|
+
return type === "event.session.created" || type === "event.session.status_changed" || type === "session.meta.updated" || type === "event.config.changed" || type === "event.model_catalog.changed" || type === "event.workspace.created" || type === "event.workspace.updated" || type === "event.workspace.deleted";
|
|
224674
224966
|
}
|
|
224675
224967
|
/** Session ids are ULID-ish, but never trust an id used as a path segment. */
|
|
224676
224968
|
function sanitizeFileName(sid) {
|
|
@@ -228304,6 +228596,8 @@ function parseActionSuffix(opts) {
|
|
|
228304
228596
|
//#region ../../packages/server/src/routes/modelCatalog.ts
|
|
228305
228597
|
const providerIdParamSchema = object({ provider_id: string().min(1) });
|
|
228306
228598
|
const modelActionTailParamSchema = object({ tail: string().min(1) });
|
|
228599
|
+
const providerActionTailParamSchema = object({ tail: string().min(1) });
|
|
228600
|
+
const providerCollectionActionParamSchema = object({ action: string().min(1) });
|
|
228307
228601
|
function registerModelCatalogRoutes(app, ix) {
|
|
228308
228602
|
const listModelsRoute = defineRoute({
|
|
228309
228603
|
method: "GET",
|
|
@@ -228359,18 +228653,63 @@ function registerModelCatalogRoutes(app, ix) {
|
|
|
228359
228653
|
reply.send(okEnvelope({ items }, req.id));
|
|
228360
228654
|
});
|
|
228361
228655
|
app.get(listProvidersRoute.path, listProvidersRoute.options, listProvidersRoute.handler);
|
|
228362
|
-
const
|
|
228656
|
+
const refreshProvidersRoute = defineRoute({
|
|
228363
228657
|
method: "POST",
|
|
228364
|
-
path: "/providers:
|
|
228365
|
-
|
|
228366
|
-
|
|
228658
|
+
path: "/providers:action",
|
|
228659
|
+
params: providerCollectionActionParamSchema,
|
|
228660
|
+
success: { data: refreshProviderModelsResponseSchema },
|
|
228661
|
+
errors: { [ErrorCode$1.VALIDATION_FAILED]: {} },
|
|
228662
|
+
description: "Refresh provider model metadata. Use `:refresh` for all providers or `:refresh_oauth` for OAuth-backed providers only.",
|
|
228367
228663
|
tags: ["providers"],
|
|
228368
|
-
operationId: "
|
|
228664
|
+
operationId: "refreshProviders"
|
|
228369
228665
|
}, async (req, reply) => {
|
|
228370
|
-
const
|
|
228371
|
-
|
|
228666
|
+
const raw = req.params.action;
|
|
228667
|
+
const action = raw.startsWith(":") ? raw.slice(1) : raw;
|
|
228668
|
+
if (action === "refresh_oauth") {
|
|
228669
|
+
const result = await ix.invokeFunction((a) => a.get(IModelCatalogService).refreshOAuthProviderModels());
|
|
228670
|
+
reply.send(okEnvelope(result, req.id));
|
|
228671
|
+
return;
|
|
228672
|
+
}
|
|
228673
|
+
if (action === "refresh") {
|
|
228674
|
+
const result = await ix.invokeFunction((a) => a.get(IModelCatalogService).refreshProviderModels({ scope: "all" }));
|
|
228675
|
+
reply.send(okEnvelope(result, req.id));
|
|
228676
|
+
return;
|
|
228677
|
+
}
|
|
228678
|
+
reply.send(errEnvelope(ErrorCode$1.VALIDATION_FAILED, `unsupported action: ${raw}`, req.id));
|
|
228372
228679
|
});
|
|
228373
|
-
app.post(
|
|
228680
|
+
app.post(refreshProvidersRoute.path, refreshProvidersRoute.options, refreshProvidersRoute.handler);
|
|
228681
|
+
const refreshProviderRoute = defineRoute({
|
|
228682
|
+
method: "POST",
|
|
228683
|
+
path: "/providers/{tail}",
|
|
228684
|
+
params: providerActionTailParamSchema,
|
|
228685
|
+
success: { data: refreshProviderModelsResponseSchema },
|
|
228686
|
+
errors: {
|
|
228687
|
+
[ErrorCode$1.VALIDATION_FAILED]: {},
|
|
228688
|
+
[ErrorCode$1.PROVIDER_NOT_FOUND]: {}
|
|
228689
|
+
},
|
|
228690
|
+
description: "Refresh model metadata for a single provider",
|
|
228691
|
+
tags: ["providers"],
|
|
228692
|
+
operationId: "refreshProvider"
|
|
228693
|
+
}, async (req, reply) => {
|
|
228694
|
+
try {
|
|
228695
|
+
const { tail } = req.params;
|
|
228696
|
+
const parsed = parseActionSuffix({
|
|
228697
|
+
tail,
|
|
228698
|
+
allowedActions: ["refresh"],
|
|
228699
|
+
resourceLabel: "provider"
|
|
228700
|
+
});
|
|
228701
|
+
if (parsed.kind !== "action") {
|
|
228702
|
+
const message = parsed.kind === "invalid" ? parsed.reason : `unsupported action: ${tail}`;
|
|
228703
|
+
reply.send(errEnvelope(ErrorCode$1.VALIDATION_FAILED, message, req.id));
|
|
228704
|
+
return;
|
|
228705
|
+
}
|
|
228706
|
+
const result = await ix.invokeFunction((a) => a.get(IModelCatalogService).refreshProviderModels({ providerId: parsed.id }));
|
|
228707
|
+
reply.send(okEnvelope(result, req.id));
|
|
228708
|
+
} catch (err) {
|
|
228709
|
+
sendMappedError$8(reply, req.id, err);
|
|
228710
|
+
}
|
|
228711
|
+
});
|
|
228712
|
+
app.post(refreshProviderRoute.path, refreshProviderRoute.options, refreshProviderRoute.handler);
|
|
228374
228713
|
const getProviderRoute = defineRoute({
|
|
228375
228714
|
method: "GET",
|
|
228376
228715
|
path: "/providers/{provider_id}",
|
|
@@ -230639,13 +230978,100 @@ function registerHealthRoute(apiV1) {
|
|
|
230639
230978
|
});
|
|
230640
230979
|
}
|
|
230641
230980
|
//#endregion
|
|
230981
|
+
//#region ../../packages/server/src/services/modelCatalog/modelCatalogRefreshScheduler.ts
|
|
230982
|
+
/**
|
|
230983
|
+
* Periodic background refresh of provider model metadata for a long-lived
|
|
230984
|
+
* daemon. The original CLI refreshed `/models` at startup; once the server
|
|
230985
|
+
* became a daemon that started once and ran for days, the on-disk catalog went
|
|
230986
|
+
* stale. This scheduler restores "stays fresh" behavior: it refreshes once on
|
|
230987
|
+
* start and then on a configurable interval, delegating the actual work to
|
|
230988
|
+
* `IModelCatalogService.refreshProviderModels` (which serializes concurrent
|
|
230989
|
+
* runs, persists changes, and publishes `event.model_catalog.changed`).
|
|
230990
|
+
*
|
|
230991
|
+
* This is a server-local service (only the daemon is long-lived); the CLI uses
|
|
230992
|
+
* the same underlying refresh orchestrator but triggers it on demand.
|
|
230993
|
+
*/
|
|
230994
|
+
const DEFAULT_REFRESH_INTERVAL_MS = 360 * 60 * 1e3;
|
|
230995
|
+
const INTERVAL_ENV = "KIMI_CODE_MODEL_CATALOG_REFRESH_INTERVAL_MS";
|
|
230996
|
+
const REFRESH_ON_START_ENV = "KIMI_CODE_MODEL_CATALOG_REFRESH_ON_START";
|
|
230997
|
+
const IModelCatalogRefreshScheduler = createDecorator("modelCatalogRefreshScheduler");
|
|
230998
|
+
let ModelCatalogRefreshScheduler = class ModelCatalogRefreshScheduler extends Disposable {
|
|
230999
|
+
modelCatalog;
|
|
231000
|
+
core;
|
|
231001
|
+
logger;
|
|
231002
|
+
_serviceBrand;
|
|
231003
|
+
_timer;
|
|
231004
|
+
_started = false;
|
|
231005
|
+
constructor(modelCatalog, core, logger) {
|
|
231006
|
+
super();
|
|
231007
|
+
this.modelCatalog = modelCatalog;
|
|
231008
|
+
this.core = core;
|
|
231009
|
+
this.logger = logger;
|
|
231010
|
+
}
|
|
231011
|
+
async start() {
|
|
231012
|
+
if (this._started) return;
|
|
231013
|
+
this._started = true;
|
|
231014
|
+
const config = await this.core.rpc.getKimiConfig({ reload: true });
|
|
231015
|
+
const intervalMs = resolveIntervalMs(config.modelCatalog?.refreshIntervalMs);
|
|
231016
|
+
if (resolveRefreshOnStart(config.modelCatalog?.refreshOnStart)) this._refresh("startup");
|
|
231017
|
+
if (intervalMs > 0) {
|
|
231018
|
+
this._timer = setInterval(() => void this._refresh("interval"), intervalMs);
|
|
231019
|
+
this._timer.unref?.();
|
|
231020
|
+
this.logger.info({ intervalMs }, "provider-model catalog auto-refresh enabled");
|
|
231021
|
+
}
|
|
231022
|
+
}
|
|
231023
|
+
async _refresh(trigger) {
|
|
231024
|
+
try {
|
|
231025
|
+
const result = await this.modelCatalog.refreshProviderModels({ scope: "all" });
|
|
231026
|
+
if (result.failed.length > 0) this.logger.warn({
|
|
231027
|
+
trigger,
|
|
231028
|
+
failed: result.failed
|
|
231029
|
+
}, "provider-model catalog refresh completed with failures");
|
|
231030
|
+
} catch (error) {
|
|
231031
|
+
this.logger.warn({
|
|
231032
|
+
trigger,
|
|
231033
|
+
err: error instanceof Error ? error.message : String(error)
|
|
231034
|
+
}, "provider-model catalog refresh failed");
|
|
231035
|
+
}
|
|
231036
|
+
}
|
|
231037
|
+
dispose() {
|
|
231038
|
+
if (this._timer !== void 0) {
|
|
231039
|
+
clearInterval(this._timer);
|
|
231040
|
+
this._timer = void 0;
|
|
231041
|
+
}
|
|
231042
|
+
super.dispose();
|
|
231043
|
+
}
|
|
231044
|
+
};
|
|
231045
|
+
ModelCatalogRefreshScheduler = __decorate([
|
|
231046
|
+
__decorateParam(0, IModelCatalogService),
|
|
231047
|
+
__decorateParam(1, ICoreProcessService),
|
|
231048
|
+
__decorateParam(2, ILogService)
|
|
231049
|
+
], ModelCatalogRefreshScheduler);
|
|
231050
|
+
function resolveIntervalMs(configValue) {
|
|
231051
|
+
const raw = process.env[INTERVAL_ENV];
|
|
231052
|
+
if (raw !== void 0 && raw.trim().length > 0) {
|
|
231053
|
+
const parsed = Number(raw);
|
|
231054
|
+
if (Number.isFinite(parsed) && parsed >= 0) return parsed;
|
|
231055
|
+
}
|
|
231056
|
+
return configValue ?? DEFAULT_REFRESH_INTERVAL_MS;
|
|
231057
|
+
}
|
|
231058
|
+
function resolveRefreshOnStart(configValue) {
|
|
231059
|
+
const raw = process.env[REFRESH_ON_START_ENV];
|
|
231060
|
+
if (raw !== void 0 && raw.trim().length > 0) {
|
|
231061
|
+
const normalized = raw.trim().toLowerCase();
|
|
231062
|
+
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
231063
|
+
}
|
|
231064
|
+
return configValue ?? true;
|
|
231065
|
+
}
|
|
231066
|
+
//#endregion
|
|
230642
231067
|
//#region ../../packages/server/src/services/serviceCollection.ts
|
|
230643
231068
|
function createServerServiceCollection(input) {
|
|
230644
231069
|
const { server, app, pinoLogger, envService } = input;
|
|
230645
231070
|
const snapshotConfig = loadSnapshotConfig();
|
|
230646
|
-
const services = new ServiceCollection(...getSingletonServiceDescriptors(), [IConnectionRegistry, new SyncDescriptor(ConnectionRegistry, [], false)], [ISessionClientsService, new SyncDescriptor(SessionClientsService, [], false)], [IWSBroadcastService, new SyncDescriptor(WSBroadcastService, [], false)], [IApprovalService, new SyncDescriptor(ApprovalService, [], false)], [IQuestionService, new SyncDescriptor(QuestionService, [], false)]);
|
|
231071
|
+
const services = new ServiceCollection(...getSingletonServiceDescriptors(), [IConnectionRegistry, new SyncDescriptor(ConnectionRegistry, [], false)], [ISessionClientsService, new SyncDescriptor(SessionClientsService, [], false)], [IWSBroadcastService, new SyncDescriptor(WSBroadcastService, [], false)], [IModelCatalogRefreshScheduler, new SyncDescriptor(ModelCatalogRefreshScheduler, [], false)], [IApprovalService, new SyncDescriptor(ApprovalService, [], false)], [IQuestionService, new SyncDescriptor(QuestionService, [], false)]);
|
|
230647
231072
|
if (snapshotConfig.mode !== "legacy") services.set(ISnapshotService, new SyncDescriptor(SnapshotService, [], false));
|
|
230648
231073
|
services.set(ILogService, new PinoLogger(pinoLogger));
|
|
231074
|
+
services.set(IFsSearchService, new SyncDescriptor(FsSearchService, [server.coreProcessOptions?.telemetry ?? noopTelemetryClient], true));
|
|
230649
231075
|
services.set(IRestGateway, new FastifyRestGateway(app));
|
|
230650
231076
|
services.set(IEnvironmentService, envService);
|
|
230651
231077
|
services.set(IWSGateway, new SyncDescriptor(WSGateway, [server.wsGatewayOptions ?? {}], false));
|
|
@@ -241163,6 +241589,7 @@ async function startServer(opts) {
|
|
|
241163
241589
|
a.get(IAuthSummaryService);
|
|
241164
241590
|
a.get(IOAuthService);
|
|
241165
241591
|
a.get(IModelCatalogService);
|
|
241592
|
+
a.get(IModelCatalogRefreshScheduler).start().catch((err) => log.error({ err }, "failed to start provider-model refresh scheduler"));
|
|
241166
241593
|
const promptService = a.get(IPromptService);
|
|
241167
241594
|
const terminalService = a.get(ITerminalService);
|
|
241168
241595
|
wsGw.setAbortHandler({
|
|
@@ -242570,10 +242997,7 @@ async function runServerInProcess(options, mode, onReady) {
|
|
|
242570
242997
|
} : void 0
|
|
242571
242998
|
}
|
|
242572
242999
|
});
|
|
242573
|
-
track("server_started", {
|
|
242574
|
-
ui_mode: "web",
|
|
242575
|
-
daemon: mode.daemon
|
|
242576
|
-
});
|
|
243000
|
+
track("server_started", { daemon: mode.daemon });
|
|
242577
243001
|
process.once("SIGINT", () => {
|
|
242578
243002
|
shutdown("SIGINT");
|
|
242579
243003
|
});
|
|
@@ -248274,6 +248698,7 @@ async function handleKimiCodeOAuthLogin(host) {
|
|
|
248274
248698
|
}
|
|
248275
248699
|
host.track("login", {
|
|
248276
248700
|
provider: DEFAULT_OAUTH_PROVIDER_NAME,
|
|
248701
|
+
method: "oauth",
|
|
248277
248702
|
already_logged_in: alreadyLoggedIn
|
|
248278
248703
|
});
|
|
248279
248704
|
if (alreadyLoggedIn) host.showStatus("Already logged in. Model configuration refreshed.");
|
|
@@ -253414,7 +253839,7 @@ var CustomRegistryImportDialogComponent = class extends Container {
|
|
|
253414
253839
|
const ADD_ROW_LABEL = "[ Add New Platform ]";
|
|
253415
253840
|
const PAGE_SIZE = 8;
|
|
253416
253841
|
const HEADER_HINT = "↑↓ navigate · D delete · Esc cancel";
|
|
253417
|
-
function readCustomRegistrySource
|
|
253842
|
+
function readCustomRegistrySource(provider) {
|
|
253418
253843
|
if (typeof provider !== "object" || provider === null) return void 0;
|
|
253419
253844
|
const source = provider.source;
|
|
253420
253845
|
if (typeof source !== "object" || source === null) return void 0;
|
|
@@ -253469,7 +253894,7 @@ function buildRows(opts) {
|
|
|
253469
253894
|
continue;
|
|
253470
253895
|
}
|
|
253471
253896
|
const baseUrl = typeof cfg === "object" && cfg !== null && "baseUrl" in cfg && typeof cfg.baseUrl === "string" ? cfg.baseUrl : void 0;
|
|
253472
|
-
const customSource = readCustomRegistrySource
|
|
253897
|
+
const customSource = readCustomRegistrySource(cfg);
|
|
253473
253898
|
if (customSource !== void 0) {
|
|
253474
253899
|
const key = `${customSource.url}${customSource.apiKey}`;
|
|
253475
253900
|
const existingIdx = customRegistryIndex.get(key);
|
|
@@ -317103,7 +317528,7 @@ function extractKeyArgument(toolName, args, workspaceDir) {
|
|
|
317103
317528
|
let summary = pattern;
|
|
317104
317529
|
const path = args["path"];
|
|
317105
317530
|
if (typeof path === "string" && path.length > 0) summary += ` · ${makeWorkspaceRelativePath(path, workspaceDir)}`;
|
|
317106
|
-
if (args["
|
|
317531
|
+
if (args["include_ignored"] === true) summary += " · include ignored";
|
|
317107
317532
|
return truncateArgValue("pattern", summary);
|
|
317108
317533
|
}
|
|
317109
317534
|
const candidates = keyMap[toolName] ?? Object.keys(args);
|
|
@@ -323020,7 +323445,7 @@ var StatusMessageComponent = class extends Container {
|
|
|
323020
323445
|
super.invalidate();
|
|
323021
323446
|
}
|
|
323022
323447
|
renderText() {
|
|
323023
|
-
return (this.color === void 0 ? currentTheme.fg("textDim", this.content) : currentTheme.fg(this.color, this.content)).split("\n").map((line) => ` ${line}`).join("\n");
|
|
323448
|
+
return (this.color === void 0 ? currentTheme.fg("textDim", this.content) : currentTheme.fg(this.color, this.content)).replaceAll("\r", "").split("\n").map((line) => ` ${line}`).join("\n");
|
|
323024
323449
|
}
|
|
323025
323450
|
};
|
|
323026
323451
|
var NoticeMessageComponent = class extends Container {
|
|
@@ -323128,349 +323553,18 @@ var QueuePaneComponent = class extends Container {
|
|
|
323128
323553
|
};
|
|
323129
323554
|
//#endregion
|
|
323130
323555
|
//#region src/tui/utils/refresh-providers.ts
|
|
323131
|
-
|
|
323132
|
-
|
|
323133
|
-
|
|
323134
|
-
|
|
323135
|
-
|
|
323136
|
-
const url = candidate["url"];
|
|
323137
|
-
const apiKey = candidate["apiKey"];
|
|
323138
|
-
if (typeof url !== "string" || url.length === 0) return void 0;
|
|
323139
|
-
if (typeof apiKey !== "string") return void 0;
|
|
323140
|
-
return {
|
|
323141
|
-
kind: "apiJson",
|
|
323142
|
-
url,
|
|
323143
|
-
apiKey
|
|
323144
|
-
};
|
|
323145
|
-
}
|
|
323146
|
-
function customRegistrySourceKey(source) {
|
|
323147
|
-
return JSON.stringify([source.url]);
|
|
323148
|
-
}
|
|
323149
|
-
function customRegistrySourceCredentialKey(source) {
|
|
323150
|
-
return JSON.stringify([source.url, source.apiKey]);
|
|
323151
|
-
}
|
|
323152
|
-
async function fetchCustomRegistryFromSources(sources) {
|
|
323153
|
-
let lastError;
|
|
323154
|
-
for (const source of sources) try {
|
|
323155
|
-
return {
|
|
323156
|
-
entries: await fetchCustomRegistry(source),
|
|
323157
|
-
source
|
|
323158
|
-
};
|
|
323159
|
-
} catch (error) {
|
|
323160
|
-
lastError = error;
|
|
323161
|
-
}
|
|
323162
|
-
if (lastError instanceof Error) throw lastError;
|
|
323163
|
-
if (typeof lastError === "string") throw new Error(lastError);
|
|
323164
|
-
throw new Error("No custom registry sources configured.");
|
|
323165
|
-
}
|
|
323166
|
-
function asManaged(config) {
|
|
323167
|
-
return config;
|
|
323168
|
-
}
|
|
323169
|
-
function collectModelIdsForAliases(config, aliasKeys) {
|
|
323170
|
-
const ids = /* @__PURE__ */ new Set();
|
|
323171
|
-
for (const aliasKey of aliasKeys) {
|
|
323172
|
-
const alias = config.models?.[aliasKey];
|
|
323173
|
-
if (alias !== void 0 && alias.model.length > 0) ids.add(alias.model);
|
|
323174
|
-
}
|
|
323175
|
-
return ids;
|
|
323176
|
-
}
|
|
323177
|
-
function providerAliasKeys(config, providerId) {
|
|
323178
|
-
const keys = /* @__PURE__ */ new Set();
|
|
323179
|
-
for (const [alias, model] of Object.entries(config.models ?? {})) if (model.provider === providerId) keys.add(alias);
|
|
323180
|
-
return keys;
|
|
323181
|
-
}
|
|
323182
|
-
function generatedProviderAliasKeys(config, providerId, aliasPrefix) {
|
|
323183
|
-
const keys = /* @__PURE__ */ new Set();
|
|
323184
|
-
for (const [alias, model] of Object.entries(config.models ?? {})) if (model.provider === providerId && alias.startsWith(aliasPrefix)) keys.add(alias);
|
|
323185
|
-
return keys;
|
|
323186
|
-
}
|
|
323187
|
-
function computeChanges(oldIds, newIds) {
|
|
323188
|
-
let added = 0;
|
|
323189
|
-
for (const id of newIds) if (!oldIds.has(id)) added++;
|
|
323190
|
-
let removed = 0;
|
|
323191
|
-
for (const id of oldIds) if (!newIds.has(id)) removed++;
|
|
323192
|
-
return {
|
|
323193
|
-
added,
|
|
323194
|
-
removed
|
|
323195
|
-
};
|
|
323196
|
-
}
|
|
323197
|
-
function providerModelSnapshot(config, providerId, aliasKeys) {
|
|
323198
|
-
const snapshots = [];
|
|
323199
|
-
for (const alias of aliasKeys) {
|
|
323200
|
-
const model = config.models?.[alias];
|
|
323201
|
-
if (model === void 0 || model.provider !== providerId) continue;
|
|
323202
|
-
snapshots.push({
|
|
323203
|
-
alias,
|
|
323204
|
-
model: {
|
|
323205
|
-
...model,
|
|
323206
|
-
capabilities: model.capabilities === void 0 ? void 0 : model.capabilities.toSorted()
|
|
323207
|
-
}
|
|
323208
|
-
});
|
|
323209
|
-
}
|
|
323210
|
-
snapshots.sort((a, b) => a.alias.localeCompare(b.alias));
|
|
323211
|
-
return JSON.stringify(snapshots);
|
|
323212
|
-
}
|
|
323213
|
-
function providerModelsEqual(config, nextConfig, providerId, aliasKeys) {
|
|
323214
|
-
return providerModelSnapshot(config, providerId, aliasKeys) === providerModelSnapshot(nextConfig, providerId, aliasKeys);
|
|
323215
|
-
}
|
|
323216
|
-
function providerConfigSnapshot(config, providerId) {
|
|
323217
|
-
return JSON.stringify(config.providers[providerId] ?? null);
|
|
323218
|
-
}
|
|
323219
|
-
function providerConfigEqual(config, nextConfig, providerId) {
|
|
323220
|
-
return providerConfigSnapshot(config, providerId) === providerConfigSnapshot(nextConfig, providerId);
|
|
323221
|
-
}
|
|
323222
|
-
function providerRefreshAliasKeys(config, nextConfig, providerId, aliasPrefix) {
|
|
323223
|
-
const keys = generatedProviderAliasKeys(config, providerId, aliasPrefix);
|
|
323224
|
-
for (const key of providerAliasKeys(nextConfig, providerId)) keys.add(key);
|
|
323225
|
-
return keys;
|
|
323226
|
-
}
|
|
323227
|
-
function preserveUserProviderAliases(config, providerId, refreshedAliasKeys) {
|
|
323228
|
-
const preserved = {};
|
|
323229
|
-
for (const [alias, model] of Object.entries(config.models ?? {})) {
|
|
323230
|
-
if (model.provider !== providerId || refreshedAliasKeys.has(alias)) continue;
|
|
323231
|
-
preserved[alias] = structuredClone(model);
|
|
323232
|
-
}
|
|
323233
|
-
return preserved;
|
|
323234
|
-
}
|
|
323235
|
-
function restoreProviderAliases(config, aliases) {
|
|
323236
|
-
if (Object.keys(aliases).length === 0) return;
|
|
323237
|
-
config.models = {
|
|
323238
|
-
...config.models,
|
|
323239
|
-
...aliases
|
|
323240
|
-
};
|
|
323241
|
-
}
|
|
323242
|
-
function restoreDefaultSelection(config, defaultModel, defaultThinking) {
|
|
323243
|
-
if (defaultModel === void 0 || config.models?.[defaultModel] === void 0) return;
|
|
323244
|
-
config.defaultModel = defaultModel;
|
|
323245
|
-
config.defaultThinking = (config.models[defaultModel]?.capabilities ?? []).includes("always_thinking") ? true : defaultThinking;
|
|
323246
|
-
}
|
|
323247
|
-
function clampDanglingDefault(config) {
|
|
323248
|
-
if (config.defaultModel !== void 0 && config.models?.[config.defaultModel] === void 0) {
|
|
323249
|
-
config.defaultModel = void 0;
|
|
323250
|
-
config.defaultThinking = void 0;
|
|
323251
|
-
}
|
|
323252
|
-
}
|
|
323253
|
-
function clearDefaultThinkingWhenDefaultRemoved(config, previousDefaultModel) {
|
|
323254
|
-
if (previousDefaultModel !== void 0 && config.defaultModel === void 0) config.defaultThinking = void 0;
|
|
323255
|
-
}
|
|
323256
|
-
function pickDefaultModel(config, providerId, models) {
|
|
323257
|
-
const firstModel = models[0];
|
|
323258
|
-
if (firstModel === void 0) return "";
|
|
323259
|
-
const existingDefault = config.defaultModel;
|
|
323260
|
-
if (existingDefault !== void 0) {
|
|
323261
|
-
const alias = config.models?.[existingDefault];
|
|
323262
|
-
if (alias !== void 0 && alias.provider === providerId) {
|
|
323263
|
-
const stillAvailable = models.find((m) => m.id === alias.model);
|
|
323264
|
-
if (stillAvailable !== void 0) return stillAvailable.id;
|
|
323265
|
-
}
|
|
323266
|
-
}
|
|
323267
|
-
return firstModel.id;
|
|
323268
|
-
}
|
|
323556
|
+
/**
|
|
323557
|
+
* Refresh remote model metadata for the configured providers. Thin adapter over
|
|
323558
|
+
* the shared `refreshProviderModels` orchestrator in `@moonshot-ai/kimi-code-oauth`
|
|
323559
|
+
* (which is also what the daemon's scheduled/manual refresh uses).
|
|
323560
|
+
*/
|
|
323269
323561
|
async function refreshAllProviderModels(host, options = {}) {
|
|
323270
|
-
|
|
323271
|
-
|
|
323272
|
-
|
|
323273
|
-
|
|
323274
|
-
|
|
323275
|
-
|
|
323276
|
-
if (managedProvider !== void 0 && managedProvider.type === "kimi" && managedProvider.oauth !== void 0) try {
|
|
323277
|
-
const auth = resolveKimiCodeRuntimeAuth({
|
|
323278
|
-
configuredBaseUrl: managedProvider.baseUrl,
|
|
323279
|
-
configuredOAuthRef: managedProvider.oauth
|
|
323280
|
-
});
|
|
323281
|
-
const models = await fetchManagedKimiCodeModels({
|
|
323282
|
-
accessToken: await host.resolveOAuthToken(KIMI_CODE_PROVIDER_NAME$1, auth.oauthRef),
|
|
323283
|
-
baseUrl: auth.baseUrl
|
|
323284
|
-
});
|
|
323285
|
-
if (models.length > 0) {
|
|
323286
|
-
const next = structuredClone(config);
|
|
323287
|
-
applyManagedKimiCodeConfig(asManaged(next), {
|
|
323288
|
-
models,
|
|
323289
|
-
baseUrl: auth.baseUrl,
|
|
323290
|
-
oauthKey: auth.oauthRef.key,
|
|
323291
|
-
oauthHost: auth.oauthRef.oauthHost,
|
|
323292
|
-
preserveDefaultModel: true
|
|
323293
|
-
});
|
|
323294
|
-
const refreshedAliasKeys = providerRefreshAliasKeys(config, next, KIMI_CODE_PROVIDER_NAME$1, `${KIMI_CODE_PLATFORM_ID}/`);
|
|
323295
|
-
restoreProviderAliases(next, preserveUserProviderAliases(config, KIMI_CODE_PROVIDER_NAME$1, refreshedAliasKeys));
|
|
323296
|
-
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
|
|
323297
|
-
clampDanglingDefault(next);
|
|
323298
|
-
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
|
|
323299
|
-
if (providerModelsEqual(config, next, "managed:kimi-code", refreshedAliasKeys)) unchanged.push(KIMI_CODE_PROVIDER_NAME$1);
|
|
323300
|
-
else {
|
|
323301
|
-
const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
|
|
323302
|
-
await host.removeProvider(KIMI_CODE_PROVIDER_NAME$1);
|
|
323303
|
-
config = await host.setConfig({
|
|
323304
|
-
providers: next.providers,
|
|
323305
|
-
models: next.models,
|
|
323306
|
-
defaultModel: next.defaultModel,
|
|
323307
|
-
defaultThinking: next.defaultThinking
|
|
323308
|
-
});
|
|
323309
|
-
changed.push({
|
|
323310
|
-
providerId: KIMI_CODE_PROVIDER_NAME$1,
|
|
323311
|
-
providerName: "Kimi Code",
|
|
323312
|
-
added,
|
|
323313
|
-
removed
|
|
323314
|
-
});
|
|
323315
|
-
}
|
|
323316
|
-
}
|
|
323317
|
-
} catch (error) {
|
|
323318
|
-
failed.push({
|
|
323319
|
-
provider: KIMI_CODE_PROVIDER_NAME$1,
|
|
323320
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
323321
|
-
});
|
|
323322
|
-
}
|
|
323323
|
-
if (scope === "oauth") return {
|
|
323324
|
-
changed,
|
|
323325
|
-
unchanged,
|
|
323326
|
-
failed
|
|
323327
|
-
};
|
|
323328
|
-
const openPlatformIds = Object.keys(config.providers).filter((id) => isOpenPlatformId(id));
|
|
323329
|
-
for (const providerId of openPlatformIds) {
|
|
323330
|
-
const platform = getOpenPlatformById(providerId);
|
|
323331
|
-
if (platform === void 0) continue;
|
|
323332
|
-
const providerConfig = config.providers[providerId];
|
|
323333
|
-
if (providerConfig === void 0) continue;
|
|
323334
|
-
const apiKey = providerConfig.apiKey;
|
|
323335
|
-
if (typeof apiKey !== "string" || apiKey.length === 0) continue;
|
|
323336
|
-
try {
|
|
323337
|
-
let models = await fetchOpenPlatformModels(platform, apiKey);
|
|
323338
|
-
models = filterModelsByPrefix(models, platform);
|
|
323339
|
-
if (models.length === 0) continue;
|
|
323340
|
-
const selectedModelId = pickDefaultModel(config, providerId, models);
|
|
323341
|
-
const selectedModel = models.find((m) => m.id === selectedModelId);
|
|
323342
|
-
if (selectedModel === void 0) continue;
|
|
323343
|
-
const next = structuredClone(config);
|
|
323344
|
-
applyOpenPlatformConfig(asManaged(next), {
|
|
323345
|
-
platform,
|
|
323346
|
-
models,
|
|
323347
|
-
selectedModel,
|
|
323348
|
-
thinking: false,
|
|
323349
|
-
apiKey
|
|
323350
|
-
});
|
|
323351
|
-
const refreshedAliasKeys = providerRefreshAliasKeys(config, next, providerId, `${providerId}/`);
|
|
323352
|
-
restoreProviderAliases(next, preserveUserProviderAliases(config, providerId, refreshedAliasKeys));
|
|
323353
|
-
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
|
|
323354
|
-
clampDanglingDefault(next);
|
|
323355
|
-
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
|
|
323356
|
-
if (providerModelsEqual(config, next, providerId, refreshedAliasKeys)) unchanged.push(providerId);
|
|
323357
|
-
else {
|
|
323358
|
-
const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
|
|
323359
|
-
await host.removeProvider(providerId);
|
|
323360
|
-
config = await host.setConfig({
|
|
323361
|
-
providers: next.providers,
|
|
323362
|
-
models: next.models,
|
|
323363
|
-
defaultModel: next.defaultModel,
|
|
323364
|
-
defaultThinking: next.defaultThinking
|
|
323365
|
-
});
|
|
323366
|
-
changed.push({
|
|
323367
|
-
providerId,
|
|
323368
|
-
providerName: platform.name,
|
|
323369
|
-
added,
|
|
323370
|
-
removed
|
|
323371
|
-
});
|
|
323372
|
-
}
|
|
323373
|
-
} catch (error) {
|
|
323374
|
-
failed.push({
|
|
323375
|
-
provider: providerId,
|
|
323376
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
323377
|
-
});
|
|
323378
|
-
}
|
|
323379
|
-
}
|
|
323380
|
-
const customSources = /* @__PURE__ */ new Map();
|
|
323381
|
-
for (const [providerId, providerConfig] of Object.entries(config.providers)) {
|
|
323382
|
-
if (providerId === "managed:kimi-code") continue;
|
|
323383
|
-
if (isOpenPlatformId(providerId)) continue;
|
|
323384
|
-
const source = readCustomRegistrySource(providerConfig);
|
|
323385
|
-
if (source === void 0) continue;
|
|
323386
|
-
const key = customRegistrySourceKey(source);
|
|
323387
|
-
const sourceKey = customRegistrySourceCredentialKey(source);
|
|
323388
|
-
const entry = customSources.get(key);
|
|
323389
|
-
if (entry !== void 0) {
|
|
323390
|
-
if (!entry.sourceKeys.has(sourceKey)) {
|
|
323391
|
-
entry.sources.push(source);
|
|
323392
|
-
entry.sourceKeys.add(sourceKey);
|
|
323393
|
-
}
|
|
323394
|
-
entry.providerIds.push(providerId);
|
|
323395
|
-
} else customSources.set(key, {
|
|
323396
|
-
sources: [source],
|
|
323397
|
-
sourceKeys: new Set([sourceKey]),
|
|
323398
|
-
providerIds: [providerId]
|
|
323399
|
-
});
|
|
323400
|
-
}
|
|
323401
|
-
for (const { sources, providerIds } of customSources.values()) try {
|
|
323402
|
-
const { entries, source } = await fetchCustomRegistryFromSources(sources);
|
|
323403
|
-
const next = structuredClone(config);
|
|
323404
|
-
const changedProviders = [];
|
|
323405
|
-
const providersToRemoveBeforeSet = /* @__PURE__ */ new Set();
|
|
323406
|
-
let hasUnreportedConfigChange = false;
|
|
323407
|
-
const remoteEntries = Object.values(entries);
|
|
323408
|
-
const remoteEntriesByProviderId = new Map(remoteEntries.map((entry) => [entry.id, entry]));
|
|
323409
|
-
const providerIdsToSync = new Set(providerIds);
|
|
323410
|
-
for (const entry of remoteEntries) providerIdsToSync.add(entry.id);
|
|
323411
|
-
for (const providerId of providerIdsToSync) {
|
|
323412
|
-
const entry = remoteEntriesByProviderId.get(providerId);
|
|
323413
|
-
if (entry === void 0) {
|
|
323414
|
-
const oldIds = collectModelIdsForAliases(config, providerAliasKeys(config, providerId));
|
|
323415
|
-
removeCustomRegistryProvider(asManaged(next), providerId);
|
|
323416
|
-
changedProviders.push({
|
|
323417
|
-
providerId,
|
|
323418
|
-
providerName: providerId,
|
|
323419
|
-
added: 0,
|
|
323420
|
-
removed: oldIds.size
|
|
323421
|
-
});
|
|
323422
|
-
providersToRemoveBeforeSet.add(providerId);
|
|
323423
|
-
continue;
|
|
323424
|
-
}
|
|
323425
|
-
const existed = config.providers[providerId] !== void 0;
|
|
323426
|
-
applyCustomRegistryProvider(asManaged(next), entry, source);
|
|
323427
|
-
const refreshedAliasKeys = providerRefreshAliasKeys(config, next, providerId, `${providerId}/`);
|
|
323428
|
-
if (existed) restoreProviderAliases(next, preserveUserProviderAliases(config, providerId, refreshedAliasKeys));
|
|
323429
|
-
if (existed && providerModelsEqual(config, next, providerId, refreshedAliasKeys) && providerConfigEqual(config, next, providerId)) unchanged.push(providerId);
|
|
323430
|
-
else if (existed && providerModelsEqual(config, next, providerId, refreshedAliasKeys)) {
|
|
323431
|
-
unchanged.push(providerId);
|
|
323432
|
-
providersToRemoveBeforeSet.add(providerId);
|
|
323433
|
-
hasUnreportedConfigChange = true;
|
|
323434
|
-
} else {
|
|
323435
|
-
const { added, removed } = computeChanges(collectModelIdsForAliases(config, refreshedAliasKeys), collectModelIdsForAliases(next, refreshedAliasKeys));
|
|
323436
|
-
changedProviders.push({
|
|
323437
|
-
providerId,
|
|
323438
|
-
providerName: entry.name || providerId,
|
|
323439
|
-
added,
|
|
323440
|
-
removed
|
|
323441
|
-
});
|
|
323442
|
-
if (existed) providersToRemoveBeforeSet.add(providerId);
|
|
323443
|
-
}
|
|
323444
|
-
}
|
|
323445
|
-
if (changedProviders.length > 0 || hasUnreportedConfigChange) {
|
|
323446
|
-
restoreDefaultSelection(next, config.defaultModel, config.defaultThinking);
|
|
323447
|
-
clampDanglingDefault(next);
|
|
323448
|
-
clearDefaultThinkingWhenDefaultRemoved(next, config.defaultModel);
|
|
323449
|
-
for (const providerId of providersToRemoveBeforeSet) await host.removeProvider(providerId);
|
|
323450
|
-
config = await host.setConfig({
|
|
323451
|
-
providers: next.providers,
|
|
323452
|
-
models: next.models,
|
|
323453
|
-
defaultModel: next.defaultModel,
|
|
323454
|
-
defaultThinking: next.defaultThinking
|
|
323455
|
-
});
|
|
323456
|
-
for (const change of changedProviders) changed.push({
|
|
323457
|
-
providerId: change.providerId,
|
|
323458
|
-
providerName: change.providerName,
|
|
323459
|
-
added: change.added,
|
|
323460
|
-
removed: change.removed
|
|
323461
|
-
});
|
|
323462
|
-
}
|
|
323463
|
-
} catch (error) {
|
|
323464
|
-
for (const providerId of providerIds) failed.push({
|
|
323465
|
-
provider: providerId,
|
|
323466
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
323467
|
-
});
|
|
323468
|
-
}
|
|
323469
|
-
return {
|
|
323470
|
-
changed,
|
|
323471
|
-
unchanged,
|
|
323472
|
-
failed
|
|
323473
|
-
};
|
|
323562
|
+
return refreshProviderModels({
|
|
323563
|
+
getConfig: () => host.getConfig(),
|
|
323564
|
+
removeProvider: (providerId) => host.removeProvider(providerId),
|
|
323565
|
+
setConfig: (patch) => host.setConfig(patch),
|
|
323566
|
+
resolveOAuthToken: (providerName, oauthRef) => host.resolveOAuthToken(providerName, oauthRef)
|
|
323567
|
+
}, options);
|
|
323474
323568
|
}
|
|
323475
323569
|
//#endregion
|
|
323476
323570
|
//#region src/tui/controllers/auth-flow.ts
|
|
@@ -333329,8 +333423,6 @@ async function shouldAutoInstallUpdates() {
|
|
|
333329
333423
|
}
|
|
333330
333424
|
function trackUpdatePrompted(track, currentVersion, target, source, decision, rolloutTelemetry) {
|
|
333331
333425
|
trackUpdateEvent(track, "update_prompted", {
|
|
333332
|
-
current: currentVersion,
|
|
333333
|
-
latest: target.version,
|
|
333334
333426
|
current_version: currentVersion,
|
|
333335
333427
|
target_version: target.version,
|
|
333336
333428
|
source,
|