@moonshot-ai/kimi-code 0.23.1 → 0.23.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 +427 -206
- package/dist-web/assets/{CodeBlockNode-C3v9L5tu.js → CodeBlockNode-EM_kCY-N.js} +1 -1
- package/dist-web/assets/{CodeBlockShell.vue_vue_type_style_index_0_lang-OER_lgTH.js → CodeBlockShell.vue_vue_type_style_index_0_lang-CRgIOeOQ.js} +1 -1
- package/dist-web/assets/DesignSystemView-CHgJ_72D.css +1 -0
- package/dist-web/assets/DesignSystemView-CcrMrQZg.js +12 -0
- package/dist-web/assets/{Tooltip-C12yteht.js → Tooltip-CzU8Fz35.js} +1 -1
- package/dist-web/assets/{arc-06Rz4VQ-.js → arc-DJW0hKnH.js} +1 -1
- package/dist-web/assets/{architectureDiagram-3BPJPVTR-SukqShtR.js → architectureDiagram-3BPJPVTR-BugvyD1E.js} +1 -1
- package/dist-web/assets/{blockDiagram-GPEHLZMM-BNJEVQuc.js → blockDiagram-GPEHLZMM-CYo-sII1.js} +1 -1
- package/dist-web/assets/{c4Diagram-AAUBKEIU-C9SPPZVL.js → c4Diagram-AAUBKEIU-D5-N6MBf.js} +1 -1
- package/dist-web/assets/channel-CC7oTf8I.js +1 -0
- package/dist-web/assets/{chunk-2J33WTMH-BzX0gLZp.js → chunk-2J33WTMH-B3rIAyxG.js} +1 -1
- package/dist-web/assets/{chunk-4BX2VUAB-2tV0t7rP.js → chunk-4BX2VUAB-BqE5MO-d.js} +1 -1
- package/dist-web/assets/{chunk-55IACEB6-0TgNLC_z.js → chunk-55IACEB6-CLF660V6.js} +1 -1
- package/dist-web/assets/{chunk-727SXJPM-BSFCho5K.js → chunk-727SXJPM-B0BhWK0K.js} +1 -1
- package/dist-web/assets/{chunk-AQP2D5EJ-XiSvZi9j.js → chunk-AQP2D5EJ-DPjMnAJ0.js} +1 -1
- package/dist-web/assets/{chunk-FMBD7UC4-C_jrUP7r.js → chunk-FMBD7UC4-D5PTPUwg.js} +1 -1
- package/dist-web/assets/{chunk-ND2GUHAM-B6mTBYIB.js → chunk-ND2GUHAM-kAaY_4Vl.js} +1 -1
- package/dist-web/assets/{chunk-QZHKN3VN-DSY_ClX7.js → chunk-QZHKN3VN-C9evXZPa.js} +1 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-Khrb0akV.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-Khrb0akV.js +1 -0
- package/dist-web/assets/{cose-bilkent-S5V4N54A-BJEsiRfG.js → cose-bilkent-S5V4N54A-CLouiVVi.js} +1 -1
- package/dist-web/assets/{dagre-BM42HDAG-CBrTyMup.js → dagre-BM42HDAG-DzxOlw1n.js} +1 -1
- package/dist-web/assets/{diagram-2AECGRRQ-C5TmGHID.js → diagram-2AECGRRQ-BByJ2hb_.js} +1 -1
- package/dist-web/assets/{diagram-5GNKFQAL-DNiKwHCr.js → diagram-5GNKFQAL-IRsTcFso.js} +1 -1
- package/dist-web/assets/{diagram-KO2AKTUF-Dd35hxfq.js → diagram-KO2AKTUF-OnKw1-KB.js} +1 -1
- package/dist-web/assets/{diagram-LMA3HP47-WrOo32AA.js → diagram-LMA3HP47-BDxe5igX.js} +1 -1
- package/dist-web/assets/{diagram-OG6HWLK6-DR3kJpcY.js → diagram-OG6HWLK6-C8HfQ_tC.js} +1 -1
- package/dist-web/assets/{erDiagram-TEJ5UH35-BmSLh1fo.js → erDiagram-TEJ5UH35-9GqhMJHB.js} +1 -1
- package/dist-web/assets/{flowDiagram-I6XJVG4X-zQFT0Hxs.js → flowDiagram-I6XJVG4X-BxnUU20J.js} +1 -1
- package/dist-web/assets/{ganttDiagram-6RSMTGT7-CG2RzgSV.js → ganttDiagram-6RSMTGT7-BvvI2pVg.js} +1 -1
- package/dist-web/assets/{gitGraphDiagram-PVQCEYII-FepYh7HV.js → gitGraphDiagram-PVQCEYII-B7iu5op7.js} +1 -1
- package/dist-web/assets/{index-CMuCGyH1.js → index-BCLn8KKh.js} +2 -2
- package/dist-web/assets/{index-BUWl4lsr.js → index-Bi8oHSIr.js} +1 -1
- package/dist-web/assets/{index-_6Mhj8Rj.css → index-D-9xA0Nc.css} +1 -1
- package/dist-web/assets/index-e04Pgjfa.js +290 -0
- package/dist-web/assets/{index10-09ZlQIpo.js → index10-CCuAby3p.js} +1 -1
- package/dist-web/assets/{index11-C8YlETLm.js → index11-Dfvs1Rhd.js} +1 -1
- package/dist-web/assets/{index5-Dvc9jUB7.js → index5-iCBVHj23.js} +1 -1
- package/dist-web/assets/{index6-UocCE6Lj.js → index6-pl4U4MZe.js} +1 -1
- package/dist-web/assets/{index7-E3VgrKiQ.js → index7-DHIAb9rr.js} +1 -1
- package/dist-web/assets/{index8-Bxb-Xjem.js → index8-f7_g7Sdt.js} +2 -2
- package/dist-web/assets/{infoDiagram-5YYISTIA-BbI2KCTX.js → infoDiagram-5YYISTIA-CyYBC3kA.js} +1 -1
- package/dist-web/assets/{ishikawaDiagram-YF4QCWOH-BzZLnVVK.js → ishikawaDiagram-YF4QCWOH-Jlcx9xTb.js} +1 -1
- package/dist-web/assets/{journeyDiagram-JHISSGLW-1f5fa5m5.js → journeyDiagram-JHISSGLW-CL5Yb_5k.js} +1 -1
- package/dist-web/assets/{kanban-definition-UN3LZRKU-BQhnYXtD.js → kanban-definition-UN3LZRKU-BqnauHAF.js} +1 -1
- package/dist-web/assets/{linear-CPygMVCd.js → linear-CMWGjNOi.js} +1 -1
- package/dist-web/assets/{mermaid.core-DzyMX8Ld.js → mermaid.core-KmcIQ1Ur.js} +66 -66
- package/dist-web/assets/{mindmap-definition-RKZ34NQL-B35GhhQo.js → mindmap-definition-RKZ34NQL-CVr19Hb0.js} +1 -1
- package/dist-web/assets/{pieDiagram-4H26LBE5-BxCyeEvP.js → pieDiagram-4H26LBE5-DJkmgpkl.js} +1 -1
- package/dist-web/assets/{quadrantDiagram-W4KKPZXB-C-sg-PQj.js → quadrantDiagram-W4KKPZXB-Q6FJUxUg.js} +1 -1
- package/dist-web/assets/{requirementDiagram-4Y6WPE33-RGkLcART.js → requirementDiagram-4Y6WPE33-CQTp7wfD.js} +1 -1
- package/dist-web/assets/{sankeyDiagram-5OEKKPKP-ZDy9_EXn.js → sankeyDiagram-5OEKKPKP-CyNSPnTi.js} +1 -1
- package/dist-web/assets/{sequenceDiagram-3UESZ5HK-9faAsd9D.js → sequenceDiagram-3UESZ5HK-DoC6yllg.js} +1 -1
- package/dist-web/assets/{stateDiagram-AJRCARHV-JM7V6DDb.js → stateDiagram-AJRCARHV-DJPyh7eE.js} +1 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-D6D0vb-i.js +1 -0
- package/dist-web/assets/{timeline-definition-PNZ67QCA-DBNxjfbt.js → timeline-definition-PNZ67QCA-C3cofncr.js} +1 -1
- package/dist-web/assets/{vennDiagram-CIIHVFJN-DHTh4JLY.js → vennDiagram-CIIHVFJN-D9J8WcHA.js} +1 -1
- package/dist-web/assets/{vue.runtime.esm-bundler-Cuefls6q.js → vue.runtime.esm-bundler-C14m1nnd.js} +1 -1
- package/dist-web/assets/{wardley-L42UT6IY-D70FWw9B.js → wardley-L42UT6IY-DkNDXFdt.js} +1 -1
- package/dist-web/assets/{wardleyDiagram-YWT4CUSO-BPHoDdFV.js → wardleyDiagram-YWT4CUSO-BHgVdx4X.js} +1 -1
- package/dist-web/assets/{xychartDiagram-2RQKCTM6-U3-Pc0An.js → xychartDiagram-2RQKCTM6-eziUIMuM.js} +1 -1
- package/dist-web/index.html +2 -2
- package/package.json +5 -5
- package/dist-web/assets/DesignSystemView-Bm5-sKT3.js +0 -12
- package/dist-web/assets/DesignSystemView-CxzrbiS1.css +0 -1
- package/dist-web/assets/channel-8SRtyypN.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-BICc9PAJ.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-BICc9PAJ.js +0 -1
- package/dist-web/assets/index-BCQoQ7Uo.js +0 -292
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-B_V1QY7S.js +0 -1
package/dist/main.mjs
CHANGED
|
@@ -9285,6 +9285,16 @@ function normalizeAnthropicStopReason(raw) {
|
|
|
9285
9285
|
};
|
|
9286
9286
|
}
|
|
9287
9287
|
}
|
|
9288
|
+
function applyResponseFormat$1(kwargs, format) {
|
|
9289
|
+
if (format === void 0) return;
|
|
9290
|
+
if (format.type === "json_object") throw new ChatProviderError("Anthropic provider requires a JSON schema for structured response output.");
|
|
9291
|
+
const outputConfig = kwargs["output_config"] !== void 0 && kwargs["output_config"] !== null ? { ...kwargs["output_config"] } : {};
|
|
9292
|
+
outputConfig["format"] = {
|
|
9293
|
+
type: "json_schema",
|
|
9294
|
+
schema: format.jsonSchema.schema
|
|
9295
|
+
};
|
|
9296
|
+
kwargs["output_config"] = outputConfig;
|
|
9297
|
+
}
|
|
9288
9298
|
/**
|
|
9289
9299
|
* Extract Claude family + version from a model id.
|
|
9290
9300
|
*
|
|
@@ -9927,6 +9937,7 @@ var init_anthropic = __esmMin((() => {
|
|
|
9927
9937
|
const thinking = this._generationKwargs.thinking;
|
|
9928
9938
|
if (thinking !== void 0 && !(thinking.type === "disabled" && isFableModel(this._model))) kwargs["thinking"] = thinking;
|
|
9929
9939
|
if (this._generationKwargs.output_config !== void 0) kwargs["output_config"] = this._generationKwargs.output_config;
|
|
9940
|
+
applyResponseFormat$1(kwargs, options?.responseFormat);
|
|
9930
9941
|
if (this._generationKwargs.contextManagement !== void 0) kwargs["context_management"] = this._generationKwargs.contextManagement;
|
|
9931
9942
|
const betas = this._generationKwargs.betaFeatures ?? [];
|
|
9932
9943
|
const extraHeaders = {};
|
|
@@ -44858,6 +44869,13 @@ function toolToGoogleGenAI(tool) {
|
|
|
44858
44869
|
parametersJsonSchema: tool.parameters
|
|
44859
44870
|
}] };
|
|
44860
44871
|
}
|
|
44872
|
+
function applyResponseFormat(config, format) {
|
|
44873
|
+
if (format === void 0) return;
|
|
44874
|
+
config["responseMimeType"] = "application/json";
|
|
44875
|
+
delete config["responseSchema"];
|
|
44876
|
+
delete config["responseJsonSchema"];
|
|
44877
|
+
if (format.type === "json_schema") config["responseJsonSchema"] = format.jsonSchema.schema;
|
|
44878
|
+
}
|
|
44861
44879
|
function toolCallIdToName(toolCallId, toolNameById) {
|
|
44862
44880
|
const name = toolNameById.get(toolCallId);
|
|
44863
44881
|
if (name !== void 0) return name;
|
|
@@ -45299,6 +45317,7 @@ var init_google_genai = __esmMin((() => {
|
|
|
45299
45317
|
systemInstruction: systemPrompt,
|
|
45300
45318
|
...tools.length > 0 ? { tools: tools.map((t) => toolToGoogleGenAI(t)) } : {}
|
|
45301
45319
|
};
|
|
45320
|
+
applyResponseFormat(config, options?.responseFormat);
|
|
45302
45321
|
try {
|
|
45303
45322
|
const models = this._createClient(options?.auth).models;
|
|
45304
45323
|
const params = {
|
|
@@ -53516,6 +53535,18 @@ function convertTool$1(tool) {
|
|
|
53516
53535
|
}
|
|
53517
53536
|
};
|
|
53518
53537
|
}
|
|
53538
|
+
function responseFormatToOpenAI$1(format) {
|
|
53539
|
+
if (format.type === "json_object") return { type: "json_object" };
|
|
53540
|
+
return {
|
|
53541
|
+
type: "json_schema",
|
|
53542
|
+
json_schema: {
|
|
53543
|
+
name: format.jsonSchema.name,
|
|
53544
|
+
schema: format.jsonSchema.schema,
|
|
53545
|
+
strict: format.jsonSchema.strict,
|
|
53546
|
+
description: format.jsonSchema.description
|
|
53547
|
+
}
|
|
53548
|
+
};
|
|
53549
|
+
}
|
|
53519
53550
|
/**
|
|
53520
53551
|
* Extract usage from a streaming chunk. Moonshot may place usage in
|
|
53521
53552
|
* `choices[0].usage` in addition to the top-level `usage` field.
|
|
@@ -53717,6 +53748,7 @@ var init_kimi = __esmMin((() => {
|
|
|
53717
53748
|
...requestKwargs,
|
|
53718
53749
|
...extraBody
|
|
53719
53750
|
};
|
|
53751
|
+
if (options?.responseFormat !== void 0) createParams["response_format"] = responseFormatToOpenAI$1(options.responseFormat);
|
|
53720
53752
|
if (tools.length > 0) createParams["tools"] = tools.map((t) => convertTool$1(t));
|
|
53721
53753
|
if (this._stream) createParams["stream_options"] = { include_usage: true };
|
|
53722
53754
|
try {
|
|
@@ -53798,6 +53830,18 @@ var init_kimi = __esmMin((() => {
|
|
|
53798
53830
|
}));
|
|
53799
53831
|
//#endregion
|
|
53800
53832
|
//#region ../../packages/kosong/src/providers/openai-legacy.ts
|
|
53833
|
+
function responseFormatToOpenAI(format) {
|
|
53834
|
+
if (format.type === "json_object") return { type: "json_object" };
|
|
53835
|
+
return {
|
|
53836
|
+
type: "json_schema",
|
|
53837
|
+
json_schema: {
|
|
53838
|
+
name: format.jsonSchema.name,
|
|
53839
|
+
schema: format.jsonSchema.schema,
|
|
53840
|
+
strict: format.jsonSchema.strict,
|
|
53841
|
+
description: format.jsonSchema.description
|
|
53842
|
+
}
|
|
53843
|
+
};
|
|
53844
|
+
}
|
|
53801
53845
|
function extractReasoningContent(source, explicitKey) {
|
|
53802
53846
|
if (typeof source !== "object" || source === null) return void 0;
|
|
53803
53847
|
const record = source;
|
|
@@ -54070,6 +54114,7 @@ var init_openai_legacy = __esmMin((() => {
|
|
|
54070
54114
|
stream: this._stream,
|
|
54071
54115
|
...kwargs
|
|
54072
54116
|
};
|
|
54117
|
+
if (options?.responseFormat !== void 0) createParams["response_format"] = responseFormatToOpenAI(options.responseFormat);
|
|
54073
54118
|
if (tools.length > 0) createParams["tools"] = tools.map((t) => toolToOpenAI(t));
|
|
54074
54119
|
if (this._stream) createParams["stream_options"] = { include_usage: true };
|
|
54075
54120
|
if (reasoningEffort !== void 0) createParams["reasoning_effort"] = reasoningEffort;
|
|
@@ -54295,6 +54340,16 @@ function formatResponsesFailedResponse(response) {
|
|
|
54295
54340
|
const reason = incompleteDetails === void 0 ? void 0 : readStringField$1(incompleteDetails, "reason");
|
|
54296
54341
|
return reason === void 0 ? "Unknown error (no error details in response)" : `incomplete: ${reason}`;
|
|
54297
54342
|
}
|
|
54343
|
+
function responseFormatToResponsesText(format) {
|
|
54344
|
+
if (format.type === "json_object") return { format: { type: "json_object" } };
|
|
54345
|
+
return { format: {
|
|
54346
|
+
type: "json_schema",
|
|
54347
|
+
name: format.jsonSchema.name,
|
|
54348
|
+
schema: format.jsonSchema.schema,
|
|
54349
|
+
strict: format.jsonSchema.strict,
|
|
54350
|
+
description: format.jsonSchema.description
|
|
54351
|
+
} };
|
|
54352
|
+
}
|
|
54298
54353
|
function contentPartsToInputItems(parts) {
|
|
54299
54354
|
const items = [];
|
|
54300
54355
|
for (const part of parts) switch (part.type) {
|
|
@@ -54814,6 +54869,10 @@ var init_openai_responses = __esmMin((() => {
|
|
|
54814
54869
|
...kwargs
|
|
54815
54870
|
};
|
|
54816
54871
|
if (systemPrompt) createParams["instructions"] = systemPrompt;
|
|
54872
|
+
if (options?.responseFormat !== void 0) createParams["text"] = {
|
|
54873
|
+
...asRawObject(createParams["text"]),
|
|
54874
|
+
...responseFormatToResponsesText(options.responseFormat)
|
|
54875
|
+
};
|
|
54817
54876
|
if (!("responses" in client) || typeof client.responses?.create !== "function") throw new Error("OpenAI SDK version does not support Responses API. Upgrade to >=4.x with responses support.");
|
|
54818
54877
|
options?.onRequestSent?.();
|
|
54819
54878
|
return new OpenAIResponsesStreamedMessage(await client.responses.create(createParams, options?.signal ? { signal: options.signal } : void 0), this._stream);
|
|
@@ -77871,57 +77930,6 @@ var init_full = __esmMin((() => {
|
|
|
77871
77930
|
buildInstruction(customInstruction) {
|
|
77872
77931
|
return renderPrompt(compaction_instruction_default, { customInstruction: customInstruction?.trim() ?? "" }).trimEnd();
|
|
77873
77932
|
}
|
|
77874
|
-
/**
|
|
77875
|
-
* Keep-all rebuild (Phase 1): after compaction folded the history — and the
|
|
77876
|
-
* dynamic tool schema messages with it — append ONE merged schema message so
|
|
77877
|
-
* the model keeps calling its loaded tools without re-selecting. Schemas are
|
|
77878
|
-
* read from the live registry, never copied from the old history, so a
|
|
77879
|
-
* schema that changed since load self-heals here. Names whose server is
|
|
77880
|
-
* currently disconnected have no registry schema and are not rebuilt (the
|
|
77881
|
-
* model re-selects after reconnect); names that survived into the
|
|
77882
|
-
* post-compaction history (none under today's users+summary rebuild, but
|
|
77883
|
-
* guarded) are not duplicated. The message goes through the normal
|
|
77884
|
-
* injection-origin append, so estimation and records pick it up as usual.
|
|
77885
|
-
*
|
|
77886
|
-
* Budget guard: the rebuilt floor (users + summary + schemas) is the one
|
|
77887
|
-
* part of the post-compaction context that compaction itself can never
|
|
77888
|
-
* shrink — if it lands inside the auto-compaction trigger band, every
|
|
77889
|
-
* following step re-compacts and rebuilds in a loop. Admit schemas (in name
|
|
77890
|
-
* order) only while the projected context stays within HALF the compaction
|
|
77891
|
-
* trigger, so normal turn content still fits before the next compaction;
|
|
77892
|
-
* anything dropped is simply re-selectable on demand, the same degradation
|
|
77893
|
-
* as a disconnected server.
|
|
77894
|
-
*/
|
|
77895
|
-
rebuildDynamicToolSchemas(activeBefore) {
|
|
77896
|
-
if (!this.agent.toolSelectEnabled) return;
|
|
77897
|
-
if (activeBefore.size === 0) return;
|
|
77898
|
-
const surviving = collectLoadedDynamicToolNames(this.agent.context.history);
|
|
77899
|
-
const candidates = [...activeBefore].filter((name) => !surviving.has(name)).toSorted((a, b) => a.localeCompare(b)).map((name) => this.agent.tools.getMcpToolSchema(name)).filter((tool) => tool !== void 0);
|
|
77900
|
-
if (candidates.length === 0) return;
|
|
77901
|
-
const tools = [];
|
|
77902
|
-
let projected = this.tokenCountWithPending;
|
|
77903
|
-
for (const tool of candidates) {
|
|
77904
|
-
const toolTokens = estimateTokensForTools([tool]);
|
|
77905
|
-
if (this.strategy.shouldCompact((projected + toolTokens) * 2)) break;
|
|
77906
|
-
tools.push(tool);
|
|
77907
|
-
projected += toolTokens;
|
|
77908
|
-
}
|
|
77909
|
-
if (tools.length < candidates.length) this.agent.log.info("trimmed dynamic tool schema rebuild to stay clear of the compaction trigger", {
|
|
77910
|
-
kept: tools.length,
|
|
77911
|
-
dropped: candidates.slice(tools.length).map((tool) => tool.name)
|
|
77912
|
-
});
|
|
77913
|
-
if (tools.length === 0) return;
|
|
77914
|
-
this.agent.context.appendMessage({
|
|
77915
|
-
role: "system",
|
|
77916
|
-
content: [],
|
|
77917
|
-
toolCalls: [],
|
|
77918
|
-
tools,
|
|
77919
|
-
origin: {
|
|
77920
|
-
kind: "injection",
|
|
77921
|
-
variant: DYNAMIC_TOOL_SCHEMA_VARIANT
|
|
77922
|
-
}
|
|
77923
|
-
});
|
|
77924
|
-
}
|
|
77925
77933
|
postProcessSummary(summary) {
|
|
77926
77934
|
const todos = this.agent.tools.storeData()["todo"] ?? [];
|
|
77927
77935
|
if (todos.length === 0) return summary;
|
|
@@ -77932,7 +77940,6 @@ var init_full = __esmMin((() => {
|
|
|
77932
77940
|
const startedAt = Date.now();
|
|
77933
77941
|
const originalHistory = [...this.agent.context.history];
|
|
77934
77942
|
const tokensBefore = estimateTokensForMessages(originalHistory);
|
|
77935
|
-
const activeDynamicToolsBefore = new Set(this.agent.tools.loadedDynamicToolNames());
|
|
77936
77943
|
let retryCount = 0;
|
|
77937
77944
|
try {
|
|
77938
77945
|
await this.triggerPreCompactHook(data, tokensBefore, signal);
|
|
@@ -78021,7 +78028,6 @@ var init_full = __esmMin((() => {
|
|
|
78021
78028
|
tokensBefore,
|
|
78022
78029
|
droppedCount: droppedCount === 0 ? void 0 : droppedCount
|
|
78023
78030
|
});
|
|
78024
|
-
this.rebuildDynamicToolSchemas(activeDynamicToolsBefore);
|
|
78025
78031
|
this.agent.telemetry.track("compaction_finished", {
|
|
78026
78032
|
source: data.source,
|
|
78027
78033
|
tokens_before: result.tokensBefore,
|
|
@@ -78050,7 +78056,7 @@ var init_full = __esmMin((() => {
|
|
|
78050
78056
|
thinking_effort: this.agent.config.thinkingEffort,
|
|
78051
78057
|
error_type: error instanceof Error ? error.name : "Unknown"
|
|
78052
78058
|
});
|
|
78053
|
-
if (isKimiError(error) && error.code === ErrorCodes.AUTH_LOGIN_REQUIRED) throw error;
|
|
78059
|
+
if (isKimiError(error) && (error.code === ErrorCodes.AUTH_LOGIN_REQUIRED || error.code === ErrorCodes.PROVIDER_AUTH_ERROR)) throw error;
|
|
78054
78060
|
throw new KimiError(ErrorCodes.COMPACTION_FAILED, String(error), { cause: error });
|
|
78055
78061
|
}
|
|
78056
78062
|
}
|
|
@@ -79838,6 +79844,11 @@ function sniffMediaFromMagic(data) {
|
|
|
79838
79844
|
* after the `WEBP` tag, or the first JPEG SOFn segment). Returns `null`
|
|
79839
79845
|
* for formats whose dimensions are not locatable from that region, or
|
|
79840
79846
|
* when the supplied buffer is too short to cover it.
|
|
79847
|
+
*
|
|
79848
|
+
* JPEG dimensions are reported in DISPLAY space: an EXIF Orientation of
|
|
79849
|
+
* 5-8 transposes the image at decode time, so the SOF width/height are
|
|
79850
|
+
* swapped to match what decoders (and this codebase's crop regions and
|
|
79851
|
+
* compression captions) actually operate in.
|
|
79841
79852
|
*/
|
|
79842
79853
|
function sniffImageDimensions(data) {
|
|
79843
79854
|
const buf = toBuffer$2(data);
|
|
@@ -79881,6 +79892,7 @@ function sniffImageDimensions(data) {
|
|
|
79881
79892
|
};
|
|
79882
79893
|
}
|
|
79883
79894
|
if (startsWith(buf, [255, 216])) {
|
|
79895
|
+
let orientation = null;
|
|
79884
79896
|
let offset = 2;
|
|
79885
79897
|
while (offset + 9 < buf.length) {
|
|
79886
79898
|
if (buf[offset] !== 255) {
|
|
@@ -79888,21 +79900,60 @@ function sniffImageDimensions(data) {
|
|
|
79888
79900
|
continue;
|
|
79889
79901
|
}
|
|
79890
79902
|
const marker = buf[offset + 1];
|
|
79891
|
-
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204)
|
|
79892
|
-
height
|
|
79893
|
-
width
|
|
79894
|
-
|
|
79903
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
|
|
79904
|
+
const height = buf.readUInt16BE(offset + 5);
|
|
79905
|
+
const width = buf.readUInt16BE(offset + 7);
|
|
79906
|
+
return orientation !== null && orientation >= 5 ? {
|
|
79907
|
+
width: height,
|
|
79908
|
+
height: width,
|
|
79909
|
+
transposed: true
|
|
79910
|
+
} : {
|
|
79911
|
+
width,
|
|
79912
|
+
height
|
|
79913
|
+
};
|
|
79914
|
+
}
|
|
79895
79915
|
if (marker === 216 || marker === 217 || marker >= 208 && marker <= 215) {
|
|
79896
79916
|
offset += 2;
|
|
79897
79917
|
continue;
|
|
79898
79918
|
}
|
|
79899
79919
|
const segmentLength = buf.readUInt16BE(offset + 2);
|
|
79900
79920
|
if (segmentLength < 2) break;
|
|
79921
|
+
if (marker === 225 && orientation === null) orientation = readExifOrientation(buf, offset + 4, offset + 2 + segmentLength);
|
|
79901
79922
|
offset += 2 + segmentLength;
|
|
79902
79923
|
}
|
|
79903
79924
|
}
|
|
79904
79925
|
return null;
|
|
79905
79926
|
}
|
|
79927
|
+
/**
|
|
79928
|
+
* Read the Orientation tag (0x0112) out of a JPEG APP1 payload spanning
|
|
79929
|
+
* [`start`, `end`). Returns 1-8, or `null` when the payload is not EXIF,
|
|
79930
|
+
* is truncated, or carries no valid orientation. Only IFD0 is examined —
|
|
79931
|
+
* that is where the tag lives; nothing here follows nested IFDs.
|
|
79932
|
+
*/
|
|
79933
|
+
function readExifOrientation(buf, start, end) {
|
|
79934
|
+
const boundedEnd = Math.min(end, buf.length);
|
|
79935
|
+
if (start + 6 > boundedEnd || buf.toString("latin1", start, start + 6) !== "Exif\0\0") return null;
|
|
79936
|
+
const tiff = start + 6;
|
|
79937
|
+
if (tiff + 8 > boundedEnd) return null;
|
|
79938
|
+
const byteOrder = buf.toString("latin1", tiff, tiff + 2);
|
|
79939
|
+
const le = byteOrder === "II";
|
|
79940
|
+
if (!le && byteOrder !== "MM") return null;
|
|
79941
|
+
const u16 = (offset) => le ? buf.readUInt16LE(offset) : buf.readUInt16BE(offset);
|
|
79942
|
+
const u32 = (offset) => le ? buf.readUInt32LE(offset) : buf.readUInt32BE(offset);
|
|
79943
|
+
if (u16(tiff + 2) !== 42) return null;
|
|
79944
|
+
const ifd = tiff + u32(tiff + 4);
|
|
79945
|
+
if (ifd + 2 > boundedEnd) return null;
|
|
79946
|
+
const entryCount = u16(ifd);
|
|
79947
|
+
for (let i = 0; i < entryCount; i += 1) {
|
|
79948
|
+
const entry = ifd + 2 + i * 12;
|
|
79949
|
+
if (entry + 12 > boundedEnd) return null;
|
|
79950
|
+
if (u16(entry) === 274) {
|
|
79951
|
+
const value = u16(entry + 8);
|
|
79952
|
+
return value >= 1 && value <= 8 ? value : null;
|
|
79953
|
+
}
|
|
79954
|
+
}
|
|
79955
|
+
return null;
|
|
79956
|
+
}
|
|
79906
79957
|
function getSuffix(path) {
|
|
79907
79958
|
const idx = path.lastIndexOf(".");
|
|
79908
79959
|
if (idx === -1) return "";
|
|
@@ -121696,7 +121747,8 @@ var init_esm$13 = __esmMin((() => {
|
|
|
121696
121747
|
* `changed: false`.
|
|
121697
121748
|
*/
|
|
121698
121749
|
async function compressImageForModel(bytes, mimeType, options = {}) {
|
|
121699
|
-
const
|
|
121750
|
+
const startedAt = Date.now();
|
|
121751
|
+
const maxEdge = options.maxEdge ?? 3e3;
|
|
121700
121752
|
const byteBudget = options.byteBudget ?? 3932160;
|
|
121701
121753
|
const maxDecodeBytes = options.maxDecodeBytes ?? MAX_DECODE_BYTES;
|
|
121702
121754
|
const normalizedMime = normalizeMime(mimeType);
|
|
@@ -121712,38 +121764,50 @@ async function compressImageForModel(bytes, mimeType, options = {}) {
|
|
|
121712
121764
|
originalByteLength: bytes.length,
|
|
121713
121765
|
finalByteLength: bytes.length
|
|
121714
121766
|
});
|
|
121715
|
-
|
|
121716
|
-
|
|
121767
|
+
const finish = (outcome, result) => {
|
|
121768
|
+
reportCompressEvent(options.telemetry, {
|
|
121769
|
+
outcome,
|
|
121770
|
+
startedAt,
|
|
121771
|
+
inputMime: normalizedMime,
|
|
121772
|
+
exifTransposed: dims?.transposed === true,
|
|
121773
|
+
result
|
|
121774
|
+
});
|
|
121775
|
+
return result;
|
|
121776
|
+
};
|
|
121777
|
+
if (bytes.length === 0) return finish("passthrough_unsupported", passthrough());
|
|
121778
|
+
if (!RECODABLE_MIME.has(normalizedMime)) return finish("passthrough_unsupported", passthrough());
|
|
121717
121779
|
const longestEdge = dims ? Math.max(dims.width, dims.height) : 0;
|
|
121718
|
-
if (bytes.length <= byteBudget && (longestEdge > 0 && longestEdge <= maxEdge || longestEdge === 0)) return passthrough();
|
|
121719
|
-
if (dims && dims.width * dims.height > MAX_DECODE_PIXELS) return passthrough();
|
|
121720
|
-
if (bytes.length > maxDecodeBytes) return passthrough();
|
|
121780
|
+
if (bytes.length <= byteBudget && (longestEdge > 0 && longestEdge <= maxEdge || longestEdge === 0)) return finish("passthrough_fast", passthrough());
|
|
121781
|
+
if (dims && dims.width * dims.height > MAX_DECODE_PIXELS) return finish("passthrough_guard", passthrough());
|
|
121782
|
+
if (bytes.length > maxDecodeBytes) return finish("passthrough_guard", passthrough());
|
|
121721
121783
|
try {
|
|
121722
121784
|
const { Jimp } = await Promise.resolve().then(() => (init_esm$13(), esm_exports$3));
|
|
121723
121785
|
const image = await Jimp.fromBuffer(Buffer.from(bytes));
|
|
121724
121786
|
const sourceIsPng = normalizedMime === "image/png";
|
|
121787
|
+
const decodedWidth = image.width;
|
|
121788
|
+
const decodedHeight = image.height;
|
|
121725
121789
|
fitWithinEdge(image, maxEdge);
|
|
121726
121790
|
const encoded = await encodeWithinBudget(image, {
|
|
121727
121791
|
sourceIsPng,
|
|
121728
121792
|
byteBudget,
|
|
121729
|
-
|
|
121793
|
+
fallbackEdges: FALLBACK_EDGES_PX
|
|
121730
121794
|
});
|
|
121731
|
-
const originalPixels =
|
|
121795
|
+
const originalPixels = decodedWidth * decodedHeight;
|
|
121732
121796
|
const finalPixels = encoded.width * encoded.height;
|
|
121733
|
-
if (!(encoded.data.length < bytes.length) && !(
|
|
121734
|
-
return {
|
|
121797
|
+
if (!(encoded.data.length < bytes.length) && !(finalPixels < originalPixels)) return finish("passthrough_unhelpful", passthrough());
|
|
121798
|
+
return finish("compressed", {
|
|
121735
121799
|
data: encoded.data,
|
|
121736
121800
|
mimeType: encoded.mimeType,
|
|
121737
121801
|
width: encoded.width,
|
|
121738
121802
|
height: encoded.height,
|
|
121739
|
-
originalWidth:
|
|
121740
|
-
originalHeight:
|
|
121803
|
+
originalWidth: decodedWidth,
|
|
121804
|
+
originalHeight: decodedHeight,
|
|
121741
121805
|
changed: true,
|
|
121742
121806
|
originalByteLength: bytes.length,
|
|
121743
121807
|
finalByteLength: encoded.data.length
|
|
121744
|
-
};
|
|
121808
|
+
});
|
|
121745
121809
|
} catch {
|
|
121746
|
-
return passthrough();
|
|
121810
|
+
return finish("passthrough_error", passthrough());
|
|
121747
121811
|
}
|
|
121748
121812
|
}
|
|
121749
121813
|
/**
|
|
@@ -121752,24 +121816,35 @@ async function compressImageForModel(bytes, mimeType, options = {}) {
|
|
|
121752
121816
|
* returns the original base64 unchanged on any failure.
|
|
121753
121817
|
*/
|
|
121754
121818
|
async function compressBase64ForModel(base64, mimeType, options = {}) {
|
|
121819
|
+
const startedAt = Date.now();
|
|
121755
121820
|
const maxDecodeBytes = options.maxDecodeBytes ?? MAX_DECODE_BYTES;
|
|
121756
121821
|
const approxBytes = Math.floor(base64.length * 3 / 4);
|
|
121757
|
-
if (approxBytes > maxDecodeBytes)
|
|
121758
|
-
|
|
121759
|
-
|
|
121760
|
-
|
|
121761
|
-
|
|
121762
|
-
|
|
121763
|
-
|
|
121764
|
-
|
|
121765
|
-
|
|
121766
|
-
|
|
121767
|
-
|
|
121822
|
+
if (approxBytes > maxDecodeBytes) {
|
|
121823
|
+
const result = {
|
|
121824
|
+
base64,
|
|
121825
|
+
mimeType,
|
|
121826
|
+
width: 0,
|
|
121827
|
+
height: 0,
|
|
121828
|
+
originalWidth: 0,
|
|
121829
|
+
originalHeight: 0,
|
|
121830
|
+
changed: false,
|
|
121831
|
+
originalByteLength: approxBytes,
|
|
121832
|
+
finalByteLength: approxBytes
|
|
121833
|
+
};
|
|
121834
|
+
reportCompressEvent(options.telemetry, {
|
|
121835
|
+
outcome: "passthrough_guard",
|
|
121836
|
+
startedAt,
|
|
121837
|
+
inputMime: normalizeMime(mimeType),
|
|
121838
|
+
exifTransposed: false,
|
|
121839
|
+
result
|
|
121840
|
+
});
|
|
121841
|
+
return result;
|
|
121842
|
+
}
|
|
121768
121843
|
let bytes;
|
|
121769
121844
|
try {
|
|
121770
121845
|
bytes = Buffer.from(base64, "base64");
|
|
121771
121846
|
} catch {
|
|
121772
|
-
|
|
121847
|
+
const result = {
|
|
121773
121848
|
base64,
|
|
121774
121849
|
mimeType,
|
|
121775
121850
|
width: 0,
|
|
@@ -121780,6 +121855,14 @@ async function compressBase64ForModel(base64, mimeType, options = {}) {
|
|
|
121780
121855
|
originalByteLength: 0,
|
|
121781
121856
|
finalByteLength: 0
|
|
121782
121857
|
};
|
|
121858
|
+
reportCompressEvent(options.telemetry, {
|
|
121859
|
+
outcome: "passthrough_error",
|
|
121860
|
+
startedAt,
|
|
121861
|
+
inputMime: normalizeMime(mimeType),
|
|
121862
|
+
exifTransposed: false,
|
|
121863
|
+
result
|
|
121864
|
+
});
|
|
121865
|
+
return result;
|
|
121783
121866
|
}
|
|
121784
121867
|
const result = await compressImageForModel(bytes, mimeType, options);
|
|
121785
121868
|
if (!result.changed) return {
|
|
@@ -121884,36 +121967,41 @@ async function compressImageContentParts(parts, options = {}) {
|
|
|
121884
121967
|
* larger than the edge cap is therefore delivered at native resolution.
|
|
121885
121968
|
*/
|
|
121886
121969
|
async function cropImageForModel(bytes, mimeType, region, options = {}) {
|
|
121887
|
-
const
|
|
121970
|
+
const startedAt = Date.now();
|
|
121971
|
+
const maxEdge = options.maxEdge ?? 3e3;
|
|
121888
121972
|
const byteBudget = options.byteBudget ?? 3932160;
|
|
121889
121973
|
const maxDecodeBytes = options.maxDecodeBytes ?? MAX_DECODE_BYTES;
|
|
121890
121974
|
const normalizedMime = normalizeMime(mimeType);
|
|
121891
|
-
|
|
121892
|
-
|
|
121893
|
-
|
|
121975
|
+
const fail = (errorKind, error) => {
|
|
121976
|
+
reportCropEvent(options.telemetry, {
|
|
121977
|
+
startedAt,
|
|
121978
|
+
ok: false,
|
|
121979
|
+
errorKind
|
|
121980
|
+
});
|
|
121981
|
+
return {
|
|
121982
|
+
ok: false,
|
|
121983
|
+
error
|
|
121984
|
+
};
|
|
121894
121985
|
};
|
|
121895
|
-
|
|
121896
|
-
|
|
121897
|
-
|
|
121986
|
+
const succeed = (result) => {
|
|
121987
|
+
reportCropEvent(options.telemetry, {
|
|
121988
|
+
startedAt,
|
|
121989
|
+
ok: true,
|
|
121990
|
+
result
|
|
121991
|
+
});
|
|
121992
|
+
return result;
|
|
121898
121993
|
};
|
|
121994
|
+
if (bytes.length === 0) return fail("empty", "The image is empty.");
|
|
121995
|
+
if (!RECODABLE_MIME.has(normalizedMime)) return fail("unsupported_format", `Cropping is only supported for PNG and JPEG images; got ${mimeType}.`);
|
|
121899
121996
|
if (![
|
|
121900
121997
|
region.x,
|
|
121901
121998
|
region.y,
|
|
121902
121999
|
region.width,
|
|
121903
122000
|
region.height
|
|
121904
|
-
].every((value) => Number.isFinite(value))) return {
|
|
121905
|
-
ok: false,
|
|
121906
|
-
error: `Region coordinates must be finite numbers; got x=${String(region.x)}, y=${String(region.y)}, width=${String(region.width)}, height=${String(region.height)}.`
|
|
121907
|
-
};
|
|
122001
|
+
].every((value) => Number.isFinite(value))) return fail("region_invalid", `Region coordinates must be finite numbers; got x=${String(region.x)}, y=${String(region.y)}, width=${String(region.width)}, height=${String(region.height)}.`);
|
|
121908
122002
|
const dims = sniffImageDimensions(bytes);
|
|
121909
|
-
if (dims && dims.width * dims.height > MAX_DECODE_PIXELS) return {
|
|
121910
|
-
|
|
121911
|
-
error: `The image (${String(dims.width)}x${String(dims.height)} pixels) is too large to decode for cropping.`
|
|
121912
|
-
};
|
|
121913
|
-
if (bytes.length > maxDecodeBytes) return {
|
|
121914
|
-
ok: false,
|
|
121915
|
-
error: "The image is too large to decode for cropping."
|
|
121916
|
-
};
|
|
122003
|
+
if (dims && dims.width * dims.height > MAX_DECODE_PIXELS) return fail("too_large", `The image (${String(dims.width)}x${String(dims.height)} pixels) is too large to decode for cropping.`);
|
|
122004
|
+
if (bytes.length > maxDecodeBytes) return fail("too_large", "The image is too large to decode for cropping.");
|
|
121917
122005
|
try {
|
|
121918
122006
|
const { Jimp } = await Promise.resolve().then(() => (init_esm$13(), esm_exports$3));
|
|
121919
122007
|
const image = await Jimp.fromBuffer(Buffer.from(bytes));
|
|
@@ -121921,10 +122009,7 @@ async function cropImageForModel(bytes, mimeType, region, options = {}) {
|
|
|
121921
122009
|
const originalHeight = image.height;
|
|
121922
122010
|
const x = Math.floor(region.x);
|
|
121923
122011
|
const y = Math.floor(region.y);
|
|
121924
|
-
if (x < 0 || y < 0 || x >= originalWidth || y >= originalHeight || region.width < 1 || region.height < 1) return {
|
|
121925
|
-
ok: false,
|
|
121926
|
-
error: `Region (x=${String(region.x)}, y=${String(region.y)}, width=${String(region.width)}, height=${String(region.height)}) lies outside the ${String(originalWidth)}x${String(originalHeight)} image.`
|
|
121927
|
-
};
|
|
122012
|
+
if (x < 0 || y < 0 || x >= originalWidth || y >= originalHeight || region.width < 1 || region.height < 1) return fail("out_of_bounds", `Region (x=${String(region.x)}, y=${String(region.y)}, width=${String(region.width)}, height=${String(region.height)}) lies outside the ${String(originalWidth)}x${String(originalHeight)} image.`);
|
|
121928
122013
|
const w = Math.min(Math.floor(region.width), originalWidth - x);
|
|
121929
122014
|
const h = Math.min(Math.floor(region.height), originalHeight - y);
|
|
121930
122015
|
const applied = {
|
|
@@ -121942,11 +122027,8 @@ async function cropImageForModel(bytes, mimeType, region, options = {}) {
|
|
|
121942
122027
|
const sourceIsPng = normalizedMime === "image/png";
|
|
121943
122028
|
if (options.skipResize === true) {
|
|
121944
122029
|
const buffer = sourceIsPng ? await image.getBuffer("image/png", { deflateLevel: 9 }) : await image.getBuffer("image/jpeg", { quality: 90 });
|
|
121945
|
-
if (buffer.length > byteBudget) return {
|
|
121946
|
-
|
|
121947
|
-
error: `The cropped region encodes to ${String(buffer.length)} bytes (${formatByteSize$2(buffer.length)}), over the ${String(byteBudget)}-byte (${formatByteSize$2(byteBudget)}) per-image limit. Choose a smaller region, or allow downscaling.`
|
|
121948
|
-
};
|
|
121949
|
-
return {
|
|
122030
|
+
if (buffer.length > byteBudget) return fail("budget", `The cropped region encodes to ${String(buffer.length)} bytes (${formatByteSize$2(buffer.length)}), over the ${String(byteBudget)}-byte (${formatByteSize$2(byteBudget)}) per-image limit. Choose a smaller region, or allow downscaling.`);
|
|
122031
|
+
return succeed({
|
|
121950
122032
|
ok: true,
|
|
121951
122033
|
data: new Uint8Array(buffer),
|
|
121952
122034
|
mimeType: sourceIsPng ? "image/png" : "image/jpeg",
|
|
@@ -121958,15 +122040,15 @@ async function cropImageForModel(bytes, mimeType, region, options = {}) {
|
|
|
121958
122040
|
resized: false,
|
|
121959
122041
|
originalByteLength: bytes.length,
|
|
121960
122042
|
finalByteLength: buffer.length
|
|
121961
|
-
};
|
|
122043
|
+
});
|
|
121962
122044
|
}
|
|
121963
122045
|
fitWithinEdge(image, maxEdge);
|
|
121964
122046
|
const encoded = await encodeWithinBudget(image, {
|
|
121965
122047
|
sourceIsPng,
|
|
121966
122048
|
byteBudget,
|
|
121967
|
-
|
|
122049
|
+
fallbackEdges: FALLBACK_EDGES_PX
|
|
121968
122050
|
});
|
|
121969
|
-
return {
|
|
122051
|
+
return succeed({
|
|
121970
122052
|
ok: true,
|
|
121971
122053
|
data: new Uint8Array(encoded.data),
|
|
121972
122054
|
mimeType: encoded.mimeType,
|
|
@@ -121978,12 +122060,9 @@ async function cropImageForModel(bytes, mimeType, region, options = {}) {
|
|
|
121978
122060
|
resized: encoded.width !== w || encoded.height !== h,
|
|
121979
122061
|
originalByteLength: bytes.length,
|
|
121980
122062
|
finalByteLength: encoded.data.length
|
|
121981
|
-
};
|
|
122063
|
+
});
|
|
121982
122064
|
} catch (error) {
|
|
121983
|
-
return {
|
|
121984
|
-
ok: false,
|
|
121985
|
-
error: `Failed to decode the image for cropping: ${error instanceof Error ? error.message : String(error)}`
|
|
121986
|
-
};
|
|
122065
|
+
return fail("decode_failed", `Failed to decode the image for cropping: ${error instanceof Error ? error.message : String(error)}`);
|
|
121987
122066
|
}
|
|
121988
122067
|
}
|
|
121989
122068
|
/**
|
|
@@ -122056,14 +122135,17 @@ function parseImageDataUrl$1(url) {
|
|
|
122056
122135
|
* Strategy — prefer the source format so a downscaled screenshot stays lossless
|
|
122057
122136
|
* PNG (preserving text and transparency), and only fall back to lossy JPEG when
|
|
122058
122137
|
* PNG cannot meet the byte budget:
|
|
122059
|
-
* - PNG source: PNG at the fitted size →
|
|
122060
|
-
*
|
|
122138
|
+
* - PNG source: PNG at the fitted size → smaller PNG rescales, stepping down
|
|
122139
|
+
* the fallback edges → JPEG ladder.
|
|
122140
|
+
* - JPEG source: the full quality ladder at the fitted size, then again at
|
|
122141
|
+
* each fallback edge — a smaller rescale must not skip the high-quality
|
|
122142
|
+
* rungs its extra pixels just paid for.
|
|
122061
122143
|
*
|
|
122062
122144
|
* Always returns the smallest buffer it produced, even if no attempt met the
|
|
122063
122145
|
* budget — the caller still gates on whether it actually helped.
|
|
122064
122146
|
*/
|
|
122065
122147
|
async function encodeWithinBudget(image, opts) {
|
|
122066
|
-
const { sourceIsPng, byteBudget,
|
|
122148
|
+
const { sourceIsPng, byteBudget, fallbackEdges } = opts;
|
|
122067
122149
|
let smallest = null;
|
|
122068
122150
|
const consider = (data, mimeType) => {
|
|
122069
122151
|
const candidate = {
|
|
@@ -122079,7 +122161,8 @@ async function encodeWithinBudget(image, opts) {
|
|
|
122079
122161
|
const png = await image.getBuffer("image/png", { deflateLevel: 9 });
|
|
122080
122162
|
if (png.length <= byteBudget) return consider(png, "image/png");
|
|
122081
122163
|
consider(png, "image/png");
|
|
122082
|
-
|
|
122164
|
+
for (const edge of fallbackEdges) {
|
|
122165
|
+
if (!fitWithinEdge(image, edge)) continue;
|
|
122083
122166
|
const smallerPng = await image.getBuffer("image/png", { deflateLevel: 9 });
|
|
122084
122167
|
if (smallerPng.length <= byteBudget) return consider(smallerPng, "image/png");
|
|
122085
122168
|
consider(smallerPng, "image/png");
|
|
@@ -122096,12 +122179,26 @@ async function encodeWithinBudget(image, opts) {
|
|
|
122096
122179
|
if (jpeg.length <= byteBudget) return consider(jpeg, "image/jpeg");
|
|
122097
122180
|
consider(jpeg, "image/jpeg");
|
|
122098
122181
|
}
|
|
122099
|
-
|
|
122182
|
+
for (const edge of fallbackEdges) {
|
|
122183
|
+
if (!fitWithinEdge(image, edge)) continue;
|
|
122184
|
+
for (const quality of JPEG_QUALITY_STEPS) {
|
|
122185
|
+
const jpeg = await image.getBuffer("image/jpeg", { quality });
|
|
122186
|
+
if (jpeg.length <= byteBudget) return consider(jpeg, "image/jpeg");
|
|
122187
|
+
consider(jpeg, "image/jpeg");
|
|
122188
|
+
}
|
|
122189
|
+
}
|
|
122100
122190
|
return smallest;
|
|
122101
122191
|
}
|
|
122102
122192
|
/**
|
|
122103
122193
|
* Scale `image` so its longest edge is at most `edge`, preserving aspect
|
|
122104
122194
|
* ratio. No-op (returns false) when the image already fits.
|
|
122195
|
+
*
|
|
122196
|
+
* Deliberately passes no `mode`: without one, jimp's default resizer
|
|
122197
|
+
* downscales with a full-coverage area average (every source pixel
|
|
122198
|
+
* contributes to the output), which does not alias. The named
|
|
122199
|
+
* ResizeStrategy modes (BILINEAR, BICUBIC, …) switch to point-sampled
|
|
122200
|
+
* interpolation that skips source pixels beyond ~2x reduction and produces
|
|
122201
|
+
* moiré on text and fine patterns — do not "upgrade" this call to one.
|
|
122105
122202
|
*/
|
|
122106
122203
|
function fitWithinEdge(image, edge) {
|
|
122107
122204
|
const longest = Math.max(image.width, image.height);
|
|
@@ -122117,7 +122214,53 @@ function normalizeMime(mimeType) {
|
|
|
122117
122214
|
const lower = mimeType.trim().toLowerCase();
|
|
122118
122215
|
return lower === "image/jpg" ? "image/jpeg" : lower;
|
|
122119
122216
|
}
|
|
122120
|
-
|
|
122217
|
+
/**
|
|
122218
|
+
* Emit the `image_compress` event. Properties are all numeric/enum — never
|
|
122219
|
+
* paths or content — and a throwing client is swallowed so telemetry can
|
|
122220
|
+
* never affect the compression result.
|
|
122221
|
+
*/
|
|
122222
|
+
function reportCompressEvent(telemetry, input) {
|
|
122223
|
+
if (telemetry === void 0) return;
|
|
122224
|
+
try {
|
|
122225
|
+
telemetry.client.track("image_compress", {
|
|
122226
|
+
source: telemetry.source,
|
|
122227
|
+
outcome: input.outcome,
|
|
122228
|
+
input_mime: input.inputMime,
|
|
122229
|
+
output_mime: normalizeMime(input.result.mimeType),
|
|
122230
|
+
original_bytes: input.result.originalByteLength,
|
|
122231
|
+
final_bytes: input.result.finalByteLength,
|
|
122232
|
+
original_width: input.result.originalWidth,
|
|
122233
|
+
original_height: input.result.originalHeight,
|
|
122234
|
+
final_width: input.result.width,
|
|
122235
|
+
final_height: input.result.height,
|
|
122236
|
+
exif_transposed: input.exifTransposed,
|
|
122237
|
+
duration_ms: Date.now() - input.startedAt
|
|
122238
|
+
});
|
|
122239
|
+
} catch {}
|
|
122240
|
+
}
|
|
122241
|
+
/**
|
|
122242
|
+
* Emit the `image_crop` event. Reports the region as a share of the original
|
|
122243
|
+
* pixel area rather than raw coordinates.
|
|
122244
|
+
*/
|
|
122245
|
+
function reportCropEvent(telemetry, input) {
|
|
122246
|
+
if (telemetry === void 0) return;
|
|
122247
|
+
try {
|
|
122248
|
+
const { result } = input;
|
|
122249
|
+
const originalPixels = result === void 0 ? 0 : result.originalWidth * result.originalHeight;
|
|
122250
|
+
telemetry.client.track("image_crop", {
|
|
122251
|
+
source: telemetry.source,
|
|
122252
|
+
ok: input.ok,
|
|
122253
|
+
error_kind: input.errorKind,
|
|
122254
|
+
resized: result?.resized,
|
|
122255
|
+
original_width: result?.originalWidth,
|
|
122256
|
+
original_height: result?.originalHeight,
|
|
122257
|
+
region_area_ratio: result === void 0 || originalPixels === 0 ? void 0 : result.region.width * result.region.height / originalPixels,
|
|
122258
|
+
final_bytes: result?.finalByteLength,
|
|
122259
|
+
duration_ms: Date.now() - input.startedAt
|
|
122260
|
+
});
|
|
122261
|
+
} catch {}
|
|
122262
|
+
}
|
|
122263
|
+
var IMAGE_BYTE_BUDGET, JPEG_QUALITY_STEPS, FALLBACK_EDGES_PX, MAX_DECODE_PIXELS, MAX_DECODE_BYTES, RECODABLE_MIME, CAPTION_OPENING, CAPTION_PATTERN;
|
|
122121
122264
|
var init_image_compress = __esmMin((() => {
|
|
122122
122265
|
init_file_type$1();
|
|
122123
122266
|
IMAGE_BYTE_BUDGET = 3.75 * 1024 * 1024;
|
|
@@ -122127,7 +122270,7 @@ var init_image_compress = __esmMin((() => {
|
|
|
122127
122270
|
40,
|
|
122128
122271
|
20
|
|
122129
122272
|
];
|
|
122130
|
-
|
|
122273
|
+
FALLBACK_EDGES_PX = [2e3, 1e3];
|
|
122131
122274
|
MAX_DECODE_PIXELS = 1e8;
|
|
122132
122275
|
MAX_DECODE_BYTES = 64 * 1024 * 1024;
|
|
122133
122276
|
RECODABLE_MIME = new Set(["image/png", "image/jpeg"]);
|
|
@@ -123396,19 +123539,26 @@ var init_goal$1 = __esmMin((() => {
|
|
|
123396
123539
|
}));
|
|
123397
123540
|
//#endregion
|
|
123398
123541
|
//#region ../../packages/agent-core/src/session/hooks/runner.ts
|
|
123542
|
+
function buildHookSpawnOptions(options) {
|
|
123543
|
+
return {
|
|
123544
|
+
shell: true,
|
|
123545
|
+
cwd: options.cwd,
|
|
123546
|
+
stdio: "pipe",
|
|
123547
|
+
detached: process.platform !== "win32",
|
|
123548
|
+
windowsHide: true,
|
|
123549
|
+
env: options.env ? {
|
|
123550
|
+
...process.env,
|
|
123551
|
+
...options.env
|
|
123552
|
+
} : void 0
|
|
123553
|
+
};
|
|
123554
|
+
}
|
|
123399
123555
|
async function runHook(command, input, options) {
|
|
123400
123556
|
let child;
|
|
123401
123557
|
try {
|
|
123402
|
-
child = spawn$1(command, {
|
|
123403
|
-
shell: true,
|
|
123558
|
+
child = spawn$1(command, buildHookSpawnOptions({
|
|
123404
123559
|
cwd: options.cwd,
|
|
123405
|
-
|
|
123406
|
-
|
|
123407
|
-
env: options.env ? {
|
|
123408
|
-
...process.env,
|
|
123409
|
-
...options.env
|
|
123410
|
-
} : void 0
|
|
123411
|
-
});
|
|
123560
|
+
env: options.env
|
|
123561
|
+
}));
|
|
123412
123562
|
} catch (error) {
|
|
123413
123563
|
return allowResult({ stderr: errorMessage$4(error) });
|
|
123414
123564
|
}
|
|
@@ -124229,7 +124379,7 @@ function buildGoalReminder(goal) {
|
|
|
124229
124379
|
lines.push("");
|
|
124230
124380
|
lines.push("Before doing any goal work, check the objective and latest request for a clear hard budget limit. If one is present and the current goal does not already record that limit, call SetGoalBudget first. Do not invent budgets. If a requested budget is not reasonable, do not set it; tell the user it is not reasonable.");
|
|
124231
124381
|
lines.push("");
|
|
124232
|
-
lines.push("Goal mode is iterative. Keep the self-audit brief each turn. Do not explore unrelated interpretations once the goal can be decided. If the objective is simple, already answered, impossible, unsafe, or contradictory, do not run another goal turn. Explain briefly if useful, then call UpdateGoal with `complete` or `blocked` in the same turn. Otherwise, choose one bounded, useful slice of work toward the objective. Do not try to finish a broad goal in one turn unless the whole goal is genuinely small. Most goal turns should not call UpdateGoal: after completing a useful slice, if material work remains, end the turn normally without calling UpdateGoal so the runtime can continue the goal in the next turn. Call UpdateGoal with `complete` only when all required work is done, any stated validation has passed, and there is no useful next action. Do not mark complete after only producing a plan, summary, first pass, or partial result.
|
|
124382
|
+
lines.push("Goal mode is iterative. Keep the self-audit brief each turn. Do not explore unrelated interpretations once the goal can be decided. If the objective is simple, already answered, impossible, unsafe, or contradictory, do not run another goal turn. Explain briefly if useful, then call UpdateGoal with `complete` or `blocked` in the same turn. Otherwise, choose one bounded, useful slice of work toward the objective. Do not try to finish a broad goal in one turn unless the whole goal is genuinely small. Most goal turns should not call UpdateGoal: after completing a useful slice, if material work remains, end the turn normally without calling UpdateGoal so the runtime can continue the goal in the next turn. Call UpdateGoal with `complete` only when all required work is done, any stated validation has passed, and there is no useful next action. Completion audit: before calling `complete`, verify the current state against the actual objective and every explicit requirement. Treat weak or indirect evidence as not complete. Do not mark complete after only producing a plan, summary, first pass, or partial result. Do not mark complete merely because a budget is nearly exhausted or you want to stop. Blocked audit: do not call UpdateGoal with `blocked` the first time you hit a blocker. Use `blocked` only for a genuine impasse: an external condition, required user input, missing credentials or permissions, or a persistent technical failure. For those non-terminal blockers, the same blocking condition must repeat for at least 3 consecutive goal turns before you call `blocked`, counting the original/user-triggered turn and automatic continuations. If a previously blocked goal is resumed, treat the resumed run as a fresh blocked audit. Exception: if the objective itself is impossible, unsafe, or contradictory, call UpdateGoal with `blocked` in the same turn; do not run more goal turns just to satisfy the audit. Do not use `blocked` because the work is large, hard, slow, uncertain, incomplete, still needs validation, would benefit from clarification, or needs more goal turns. Once the 3-turn threshold is met and you cannot make meaningful progress without user input or an external-state change, call UpdateGoal with `blocked`; do not keep reporting the blocker while leaving the goal active.");
|
|
124233
124383
|
return lines.join("\n");
|
|
124234
124384
|
}
|
|
124235
124385
|
/** Highest budget-usage fraction across the set hard budgets (turns/tokens/time). */
|
|
@@ -142142,7 +142292,13 @@ async function mcpResultToExecutableOutput(result, qualifiedToolName, options =
|
|
|
142142
142292
|
if (part !== null) converted.push(part);
|
|
142143
142293
|
}
|
|
142144
142294
|
const budgeted = applyTextBudget(wrapMediaOnly(converted, qualifiedToolName));
|
|
142145
|
-
const compressed = await compressImageContentParts(budgeted.parts, {
|
|
142295
|
+
const compressed = await compressImageContentParts(budgeted.parts, {
|
|
142296
|
+
telemetry: options.telemetry === void 0 ? void 0 : {
|
|
142297
|
+
client: options.telemetry,
|
|
142298
|
+
source: "mcp_tool_result"
|
|
142299
|
+
},
|
|
142300
|
+
annotate: { persistOriginal: (bytes, mimeType) => persistOriginalImage(bytes, mimeType, options.originalsDir === void 0 ? {} : { dir: options.originalsDir }) }
|
|
142301
|
+
});
|
|
142146
142302
|
const capped = applyBinaryPartCap(compressed.parts);
|
|
142147
142303
|
const truncated = budgeted.truncated || capped.truncated;
|
|
142148
142304
|
return {
|
|
@@ -150452,7 +150608,8 @@ var init_read_media = __esmMin((() => {
|
|
|
150452
150608
|
name = "ReadMediaFile";
|
|
150453
150609
|
description;
|
|
150454
150610
|
parameters = toInputJsonSchema(ReadMediaFileInputSchema);
|
|
150455
|
-
|
|
150611
|
+
compressTelemetry;
|
|
150612
|
+
constructor(kaos, workspace, capabilities, videoUploader, telemetry) {
|
|
150456
150613
|
this.kaos = kaos;
|
|
150457
150614
|
this.workspace = workspace;
|
|
150458
150615
|
this.capabilities = capabilities;
|
|
@@ -150463,6 +150620,10 @@ var init_read_media = __esmMin((() => {
|
|
|
150463
150620
|
throw skip;
|
|
150464
150621
|
}
|
|
150465
150622
|
this.description = buildDescription(capabilities);
|
|
150623
|
+
this.compressTelemetry = telemetry === void 0 ? void 0 : {
|
|
150624
|
+
client: telemetry,
|
|
150625
|
+
source: "read_media"
|
|
150626
|
+
};
|
|
150466
150627
|
}
|
|
150467
150628
|
resolveExecution(args) {
|
|
150468
150629
|
const path = resolvePathAccessPath(args.path, {
|
|
@@ -150528,7 +150689,10 @@ var init_read_media = __esmMin((() => {
|
|
|
150528
150689
|
let mediaPart;
|
|
150529
150690
|
let delivery;
|
|
150530
150691
|
if (fileType.kind === "image") if (args.region !== void 0) {
|
|
150531
|
-
const outcome = await cropImageForModel(data, fileType.mimeType, args.region, {
|
|
150692
|
+
const outcome = await cropImageForModel(data, fileType.mimeType, args.region, {
|
|
150693
|
+
skipResize: args.full_resolution === true,
|
|
150694
|
+
telemetry: this.compressTelemetry
|
|
150695
|
+
});
|
|
150532
150696
|
if (!outcome.ok) return {
|
|
150533
150697
|
isError: true,
|
|
150534
150698
|
output: `Cannot read region from "${args.path}": ${outcome.error}`
|
|
@@ -150547,7 +150711,7 @@ var init_read_media = __esmMin((() => {
|
|
|
150547
150711
|
region: outcome.region,
|
|
150548
150712
|
resized: outcome.resized
|
|
150549
150713
|
};
|
|
150550
|
-
dimensions
|
|
150714
|
+
dimensions = {
|
|
150551
150715
|
width: outcome.originalWidth,
|
|
150552
150716
|
height: outcome.originalHeight
|
|
150553
150717
|
};
|
|
@@ -150569,7 +150733,7 @@ var init_read_media = __esmMin((() => {
|
|
|
150569
150733
|
mimeType: fileType.mimeType
|
|
150570
150734
|
};
|
|
150571
150735
|
} else {
|
|
150572
|
-
const compressed = await compressImageForModel(data, fileType.mimeType);
|
|
150736
|
+
const compressed = await compressImageForModel(data, fileType.mimeType, { telemetry: this.compressTelemetry });
|
|
150573
150737
|
const base64 = Buffer.from(compressed.data).toString("base64");
|
|
150574
150738
|
mediaPart = {
|
|
150575
150739
|
type: "image_url",
|
|
@@ -150582,6 +150746,10 @@ var init_read_media = __esmMin((() => {
|
|
|
150582
150746
|
byteLength: compressed.finalByteLength,
|
|
150583
150747
|
mimeType: compressed.mimeType
|
|
150584
150748
|
};
|
|
150749
|
+
if (compressed.changed) dimensions = {
|
|
150750
|
+
width: compressed.originalWidth,
|
|
150751
|
+
height: compressed.originalHeight
|
|
150752
|
+
};
|
|
150585
150753
|
}
|
|
150586
150754
|
else if (this.videoUploader !== void 0) mediaPart = await this.videoUploader({
|
|
150587
150755
|
data,
|
|
@@ -151012,10 +151180,13 @@ var init_outcome_prompts = __esmMin((() => {}));
|
|
|
151012
151180
|
//#region ../../packages/agent-core/src/tools/builtin/goal/update-goal.md?raw
|
|
151013
151181
|
var update_goal_default;
|
|
151014
151182
|
var init_update_goal$1 = __esmMin((() => {
|
|
151015
|
-
update_goal_default = "Set the status of the current goal. This is how you resume,
|
|
151183
|
+
update_goal_default = "Set the status of the current goal. This is how you resume, complete, or block an autonomous goal.\n\n- `active` — resume a paused or blocked goal when the user explicitly asks you to work on that goal.\n- `complete` — the objective is satisfied and any stated validation has passed. The goal ends and a completion summary is recorded. Before using this, verify the current state against the actual objective and every explicit requirement. Treat weak or indirect evidence as not complete. Do not use `complete` merely because a budget is nearly exhausted or you want to stop.\n- `blocked` — a genuine impasse prevents useful progress: an external condition, required user input, missing credentials or permissions, a persistent technical failure, or an impossible, unsafe, or contradictory objective. For non-terminal blockers, do not use `blocked` the first time you hit the blocker. The same blocking condition must repeat for at least 3 consecutive goal turns before you call `blocked`, counting the original/user-triggered turn and automatic continuations. If a previously blocked goal is resumed, treat the resumed run as a fresh blocked audit. If the objective itself is impossible, unsafe, or contradictory, call `blocked` in the same turn instead of running more goal turns. Do not use `blocked` because the work is large, hard, slow, uncertain, incomplete, still needs validation, would benefit from clarification, or needs more goal turns. Once the 3-turn threshold is met and you cannot make meaningful progress without user input or an external-state change, call `blocked` instead of leaving the goal active.\n\nMost active goal turns should not call this tool. If you complete one useful slice of work and material work remains, end the turn normally without calling UpdateGoal; the runtime will prompt you to continue in the next goal turn. Call `complete` only when all required work is done, any stated validation has passed, and there is no useful next action. Do not call `complete` after only producing a plan, summary, first pass, or partial result. Call `blocked` only after the blocked audit threshold is met. If you call `blocked`, you will be prompted to explain the blocker in your next message. Setting the status is the machine-readable signal; the completion summary or blocker explanation is yours to write in the following message.\n";
|
|
151016
151184
|
}));
|
|
151017
151185
|
//#endregion
|
|
151018
151186
|
//#region ../../packages/agent-core/src/tools/builtin/goal/update-goal.ts
|
|
151187
|
+
function isUpdateGoalStatus(status) {
|
|
151188
|
+
return status === "active" || status === "complete" || status === "blocked";
|
|
151189
|
+
}
|
|
151019
151190
|
var UpdateGoalToolInputSchema, UpdateGoalTool;
|
|
151020
151191
|
var init_update_goal = __esmMin((() => {
|
|
151021
151192
|
init_zod$1();
|
|
@@ -151025,9 +151196,8 @@ var init_update_goal = __esmMin((() => {
|
|
|
151025
151196
|
UpdateGoalToolInputSchema = object({ status: _enum([
|
|
151026
151197
|
"active",
|
|
151027
151198
|
"complete",
|
|
151028
|
-
"paused",
|
|
151029
151199
|
"blocked"
|
|
151030
|
-
]).describe("The lifecycle status to set for the current goal.") }).strict();
|
|
151200
|
+
]).describe("The lifecycle status to set for the current goal. Use `blocked` for impossible, unsafe, or contradictory objectives, or after the same non-terminal blocking condition repeats for at least 3 consecutive goal turns.") }).strict();
|
|
151031
151201
|
UpdateGoalTool = class {
|
|
151032
151202
|
agent;
|
|
151033
151203
|
name = "UpdateGoal";
|
|
@@ -151037,20 +151207,25 @@ var init_update_goal = __esmMin((() => {
|
|
|
151037
151207
|
this.agent = agent;
|
|
151038
151208
|
}
|
|
151039
151209
|
resolveExecution(args) {
|
|
151210
|
+
if (!isUpdateGoalStatus(args.status)) return {
|
|
151211
|
+
isError: true,
|
|
151212
|
+
output: "Invalid goal status. Use `active`, `complete`, or `blocked`."
|
|
151213
|
+
};
|
|
151214
|
+
const status = args.status;
|
|
151040
151215
|
const goal = this.agent.goal;
|
|
151041
151216
|
const currentGoal = goal.getGoal().goal;
|
|
151042
151217
|
const goalIsActive = currentGoal?.status === "active";
|
|
151043
151218
|
return {
|
|
151044
|
-
description: `Setting goal status: ${
|
|
151045
|
-
stopBatchAfterThis:
|
|
151219
|
+
description: `Setting goal status: ${status}`,
|
|
151220
|
+
stopBatchAfterThis: status !== "active" && goalIsActive,
|
|
151046
151221
|
approvalRule: this.name,
|
|
151047
151222
|
execute: async () => {
|
|
151048
|
-
if (
|
|
151223
|
+
if (status === "active") {
|
|
151049
151224
|
if (currentGoal === null) return { output: "Goal not resumed: no current goal." };
|
|
151050
151225
|
await goal.resumeGoal({}, "model");
|
|
151051
151226
|
return { output: "Goal resumed." };
|
|
151052
151227
|
}
|
|
151053
|
-
if (
|
|
151228
|
+
if (status === "complete") {
|
|
151054
151229
|
const completed = await goal.markComplete({}, "model");
|
|
151055
151230
|
if (completed === null) return { output: "Goal not completed: no active goal." };
|
|
151056
151231
|
return {
|
|
@@ -151058,7 +151233,7 @@ var init_update_goal = __esmMin((() => {
|
|
|
151058
151233
|
stopTurn: true
|
|
151059
151234
|
};
|
|
151060
151235
|
}
|
|
151061
|
-
if (
|
|
151236
|
+
if (status === "blocked") {
|
|
151062
151237
|
const blocked = await goal.markBlocked({}, "model");
|
|
151063
151238
|
if (blocked === null) return { output: "Goal not blocked: no active goal." };
|
|
151064
151239
|
return {
|
|
@@ -151066,11 +151241,9 @@ var init_update_goal = __esmMin((() => {
|
|
|
151066
151241
|
stopTurn: true
|
|
151067
151242
|
};
|
|
151068
151243
|
}
|
|
151069
|
-
if (currentGoal === null) return { output: "Goal not paused: no current goal." };
|
|
151070
|
-
await goal.pauseGoal({}, "model");
|
|
151071
151244
|
return {
|
|
151072
|
-
|
|
151073
|
-
|
|
151245
|
+
isError: true,
|
|
151246
|
+
output: "Invalid goal status. Use `active`, `complete`, or `blocked`."
|
|
151074
151247
|
};
|
|
151075
151248
|
}
|
|
151076
151249
|
};
|
|
@@ -152107,7 +152280,10 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152107
152280
|
return {
|
|
152108
152281
|
approvalRule: qualified,
|
|
152109
152282
|
execute: async (context) => {
|
|
152110
|
-
return mcpResultToExecutableOutput(await client.callTool(tool.name, args ?? {}, context.signal), qualified, {
|
|
152283
|
+
return mcpResultToExecutableOutput(await client.callTool(tool.name, args ?? {}, context.signal), qualified, {
|
|
152284
|
+
originalsDir: this.agent.mediaOriginalsDir,
|
|
152285
|
+
telemetry: this.agent.telemetry
|
|
152286
|
+
});
|
|
152111
152287
|
}
|
|
152112
152288
|
};
|
|
152113
152289
|
}
|
|
@@ -152292,8 +152468,8 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152292
152468
|
* defer-window pending set. History is the single source of truth, so the
|
|
152293
152469
|
* ledger survives resume (records replay rebuilds the history), keeps its
|
|
152294
152470
|
* state across undo (schema messages have `injection` origin and are not
|
|
152295
|
-
* undone), and
|
|
152296
|
-
* the
|
|
152471
|
+
* undone), and empties at compaction (schema messages are discarded with
|
|
152472
|
+
* the folded history — the model re-selects what it still needs).
|
|
152297
152473
|
*/
|
|
152298
152474
|
loadedDynamicToolNames() {
|
|
152299
152475
|
const names = collectLoadedDynamicToolNames(this.agent.context.history);
|
|
@@ -152314,12 +152490,11 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152314
152490
|
this.pendingLoadedDynamicTools.clear();
|
|
152315
152491
|
}
|
|
152316
152492
|
/**
|
|
152317
|
-
* Compaction rebuilt the history
|
|
152318
|
-
*
|
|
152319
|
-
*
|
|
152320
|
-
*
|
|
152321
|
-
*
|
|
152322
|
-
* "Already available" instead of injecting.
|
|
152493
|
+
* Compaction rebuilt the history and discarded every loaded schema with it
|
|
152494
|
+
* — the loaded set is empty from here on. A pending entry surviving past
|
|
152495
|
+
* this boundary would report a schema the context no longer carries as
|
|
152496
|
+
* loaded, and re-selecting it would wrongly answer "Already available"
|
|
152497
|
+
* instead of injecting.
|
|
152323
152498
|
*/
|
|
152324
152499
|
onContextCompacted() {
|
|
152325
152500
|
this.pendingLoadedDynamicTools.clear();
|
|
@@ -152393,7 +152568,7 @@ var init_tool$1 = __esmMin((() => {
|
|
|
152393
152568
|
new GrepTool(kaos, workspace, this.agent.telemetry),
|
|
152394
152569
|
new GlobTool(kaos, workspace, this.agent.telemetry),
|
|
152395
152570
|
new BashTool(kaos, cwd, background, { allowBackground }),
|
|
152396
|
-
(modelCapabilities.image_in || modelCapabilities.video_in) && new ReadMediaFileTool(kaos, workspace, modelCapabilities, videoUploader),
|
|
152571
|
+
(modelCapabilities.image_in || modelCapabilities.video_in) && new ReadMediaFileTool(kaos, workspace, modelCapabilities, videoUploader, this.agent.telemetry),
|
|
152397
152572
|
new EnterPlanModeTool(this.agent),
|
|
152398
152573
|
new ExitPlanModeTool(this.agent),
|
|
152399
152574
|
new SelectToolsTool(this.agent),
|
|
@@ -153011,15 +153186,23 @@ var init_turn = __esmMin((() => {
|
|
|
153011
153186
|
"useful slice, if material work remains, end the turn normally without calling UpdateGoal so",
|
|
153012
153187
|
"the runtime can continue the goal in the next turn. Call UpdateGoal with `complete` only when",
|
|
153013
153188
|
"all required work is done, any stated validation has passed, and there is no useful next",
|
|
153014
|
-
"action.
|
|
153015
|
-
"
|
|
153016
|
-
"
|
|
153017
|
-
"
|
|
153018
|
-
"
|
|
153019
|
-
"
|
|
153020
|
-
"
|
|
153021
|
-
"
|
|
153022
|
-
"
|
|
153189
|
+
"action. Completion audit: before calling `complete`, verify the current state against the",
|
|
153190
|
+
"actual objective and every explicit requirement. Treat weak or indirect evidence as not",
|
|
153191
|
+
"complete. Do not mark complete after only producing a plan, summary, first pass, or partial",
|
|
153192
|
+
"result. Do not mark complete merely because a budget is nearly exhausted or you want to stop.",
|
|
153193
|
+
"Blocked audit: do not call UpdateGoal with `blocked` the first time you hit a blocker. Use",
|
|
153194
|
+
"`blocked` only for a genuine impasse: an external condition, required user input, missing",
|
|
153195
|
+
"credentials or permissions, or a persistent technical failure. For those non-terminal",
|
|
153196
|
+
"blockers, the same blocking condition must repeat for at least 3 consecutive goal turns before",
|
|
153197
|
+
"you call `blocked`, counting the original/user-triggered turn and automatic continuations.",
|
|
153198
|
+
"If a previously blocked goal is resumed, treat the resumed run as a fresh blocked audit.",
|
|
153199
|
+
"Exception: if the objective itself is impossible, unsafe, or contradictory, call UpdateGoal",
|
|
153200
|
+
"with `blocked` in the same turn; do not run more goal turns just to satisfy the audit. Do not",
|
|
153201
|
+
"use `blocked` because the work is large, hard, slow, uncertain, incomplete, still needs",
|
|
153202
|
+
"validation, would benefit from clarification, or needs more goal turns. Once the 3-turn",
|
|
153203
|
+
"threshold is met and you cannot make meaningful progress without user input or an",
|
|
153204
|
+
"external-state change, call UpdateGoal with `blocked`; do not keep reporting the blocker while",
|
|
153205
|
+
"leaving the goal active. Do not ask the user for input unless a real blocker prevents progress."
|
|
153023
153206
|
].join(" ");
|
|
153024
153207
|
TurnFlow = class {
|
|
153025
153208
|
agent;
|
|
@@ -153212,10 +153395,16 @@ var init_turn = __esmMin((() => {
|
|
|
153212
153395
|
try {
|
|
153213
153396
|
if (this.agent.goal.getGoal().goal?.status === "active") return await this.driveGoal(firstTurnId, input, origin, signal);
|
|
153214
153397
|
const end = await this.runOneTurn(firstTurnId, input, origin, signal, true);
|
|
153215
|
-
if (this.agent.goal.getGoal().goal?.status === "active" && end.event.reason !== "cancelled" && end.event.reason !== "failed" && end.event.reason !== "filtered")
|
|
153216
|
-
|
|
153217
|
-
|
|
153218
|
-
|
|
153398
|
+
if (this.agent.goal.getGoal().goal?.status === "active" && end.event.reason !== "cancelled" && end.event.reason !== "failed" && end.event.reason !== "filtered") {
|
|
153399
|
+
if ((await this.agent.goal.incrementTurn())?.budget.overBudget === true) {
|
|
153400
|
+
await this.agent.goal.markBlocked({ reason: "A configured budget was reached" });
|
|
153401
|
+
return end;
|
|
153402
|
+
}
|
|
153403
|
+
return await this.driveGoal(this.allocateTurnId(), [{
|
|
153404
|
+
type: "text",
|
|
153405
|
+
text: GOAL_CONTINUATION_PROMPT
|
|
153406
|
+
}], GOAL_CONTINUATION_ORIGIN, signal);
|
|
153407
|
+
}
|
|
153219
153408
|
return end;
|
|
153220
153409
|
} finally {
|
|
153221
153410
|
if (ownsActiveTurn()) this.activeTurn = null;
|
|
@@ -153225,8 +153414,8 @@ var init_turn = __esmMin((() => {
|
|
|
153225
153414
|
* Drives an active goal as a sequence of ordinary turns — the autonomous
|
|
153226
153415
|
* equivalent of the user repeatedly typing "continue". Each iteration runs one
|
|
153227
153416
|
* full turn, then reads the goal status the model set via `UpdateGoal`:
|
|
153228
|
-
* `complete` (the record is cleared) / `blocked`
|
|
153229
|
-
*
|
|
153417
|
+
* `complete` (the record is cleared) / `blocked` stop the loop; `active`
|
|
153418
|
+
* (the model didn't decide) re-injects the goal reminder and runs the
|
|
153230
153419
|
* next continuation turn. Aborted or failed turns pause the goal. Goal-state
|
|
153231
153420
|
* blockers, such as explicit `UpdateGoal('blocked')`, prompt-hook blocks, and
|
|
153232
153421
|
* budget limits, block it (all resumable). Returns the final turn's result.
|
|
@@ -205862,13 +206051,16 @@ var init_provider_manager = __esmMin((() => {
|
|
|
205862
206051
|
return await request(auth);
|
|
205863
206052
|
} catch (error) {
|
|
205864
206053
|
if (!(error instanceof APIStatusError) || error.statusCode !== 401) throw error;
|
|
205865
|
-
if (refreshed)
|
|
205866
|
-
|
|
205867
|
-
|
|
205868
|
-
|
|
205869
|
-
|
|
205870
|
-
|
|
205871
|
-
|
|
206054
|
+
if (refreshed) {
|
|
206055
|
+
const reason = error.message.replaceAll("\r", "");
|
|
206056
|
+
throw new KimiError(ErrorCodes.PROVIDER_AUTH_ERROR, reason.length > 0 ? reason : "OAuth provider credentials were rejected.", {
|
|
206057
|
+
cause: error,
|
|
206058
|
+
details: {
|
|
206059
|
+
statusCode: error.statusCode,
|
|
206060
|
+
requestId: error.requestId
|
|
206061
|
+
}
|
|
206062
|
+
});
|
|
206063
|
+
}
|
|
205872
206064
|
auth = await fetchAuth(true);
|
|
205873
206065
|
}
|
|
205874
206066
|
};
|
|
@@ -209492,6 +209684,7 @@ var _CoreProcessService, CoreProcessService;
|
|
|
209492
209684
|
var init_coreProcessService = __esmMin((() => {
|
|
209493
209685
|
init_rpc();
|
|
209494
209686
|
init_di();
|
|
209687
|
+
init_telemetry();
|
|
209495
209688
|
init_src$2();
|
|
209496
209689
|
init_managedAuth();
|
|
209497
209690
|
init_coreProcessClient();
|
|
@@ -209513,6 +209706,7 @@ var init_coreProcessService = __esmMin((() => {
|
|
|
209513
209706
|
*/
|
|
209514
209707
|
rpc;
|
|
209515
209708
|
kimiRequestHeaders;
|
|
209709
|
+
telemetry;
|
|
209516
209710
|
/**
|
|
209517
209711
|
* The in-process `KimiCore` instance. Kept private so daemon-side code can't
|
|
209518
209712
|
* grab it and bypass the peer-service indirection.
|
|
@@ -209535,6 +209729,7 @@ var init_coreProcessService = __esmMin((() => {
|
|
|
209535
209729
|
const [coreRpc, sdkRpc] = createRPC();
|
|
209536
209730
|
const resolveOAuthTokenProvider = options.resolveOAuthTokenProvider ?? _CoreProcessService._defaultOAuthTokenResolver(env.homeDir, env.configPath);
|
|
209537
209731
|
this.kimiRequestHeaders = options.kimiRequestHeaders ?? _CoreProcessService._defaultKimiRequestHeaders(env.homeDir, options.identity);
|
|
209732
|
+
this.telemetry = options.telemetry ?? noopTelemetryClient;
|
|
209538
209733
|
const appVersion = options.appVersion ?? options.identity?.version;
|
|
209539
209734
|
this._core = new KimiCore(coreRpc, {
|
|
209540
209735
|
...options,
|
|
@@ -218643,8 +218838,12 @@ function applyCatalogProvider(config, options) {
|
|
|
218643
218838
|
init_src();
|
|
218644
218839
|
//#endregion
|
|
218645
218840
|
//#region ../../packages/telemetry/src/types.ts
|
|
218841
|
+
const MAX_TELEMETRY_NUMBER_MAGNITUDE = Number.MAX_SAFE_INTEGER;
|
|
218646
218842
|
function isTelemetryPrimitive(value) {
|
|
218647
|
-
return value === null || value === void 0 || typeof value === "boolean" || typeof value === "string" || typeof value === "number" &&
|
|
218843
|
+
return value === null || value === void 0 || typeof value === "boolean" || typeof value === "string" || typeof value === "number" && isTelemetryNumber(value);
|
|
218844
|
+
}
|
|
218845
|
+
function isTelemetryNumber(value) {
|
|
218846
|
+
return Number.isFinite(value) && Math.abs(value) <= MAX_TELEMETRY_NUMBER_MAGNITUDE;
|
|
218648
218847
|
}
|
|
218649
218848
|
//#endregion
|
|
218650
218849
|
//#region ../../packages/telemetry/src/client.ts
|
|
@@ -218928,7 +219127,7 @@ function setPrimitive(target, key, value) {
|
|
|
218928
219127
|
}
|
|
218929
219128
|
//#endregion
|
|
218930
219129
|
//#region ../../packages/telemetry/src/systemMetrics.ts
|
|
218931
|
-
const DEFAULT_INTERVAL_MS =
|
|
219130
|
+
const DEFAULT_INTERVAL_MS = 3e5;
|
|
218932
219131
|
const DEFAULT_WARMUP_SAMPLE_MS = 1500;
|
|
218933
219132
|
const SYSTEM_METRICS_EVENT = "system_metrics";
|
|
218934
219133
|
var SystemMetricsCollector = class {
|
|
@@ -218984,7 +219183,7 @@ var SystemMetricsCollector = class {
|
|
|
218984
219183
|
this.previousHrtime = now;
|
|
218985
219184
|
const mem = process.memoryUsage();
|
|
218986
219185
|
const constrainedMemory = getConstrainedMemoryBytes();
|
|
218987
|
-
|
|
219186
|
+
const properties = {
|
|
218988
219187
|
process_started_at: this.processStartedAtSeconds,
|
|
218989
219188
|
process_uptime_ms: Math.round(process.uptime() * 1e3),
|
|
218990
219189
|
rss_bytes: mem.rss,
|
|
@@ -218992,7 +219191,6 @@ var SystemMetricsCollector = class {
|
|
|
218992
219191
|
heap_total_bytes: mem.heapTotal,
|
|
218993
219192
|
external_bytes: mem.external,
|
|
218994
219193
|
array_buffers_bytes: mem.arrayBuffers,
|
|
218995
|
-
constrained_memory_bytes: constrainedMemory,
|
|
218996
219194
|
cpu_user_us: cpu.user,
|
|
218997
219195
|
cpu_system_us: cpu.system,
|
|
218998
219196
|
cpu_elapsed_us: Math.round(elapsedUs),
|
|
@@ -219000,13 +219198,15 @@ var SystemMetricsCollector = class {
|
|
|
219000
219198
|
free_mem_bytes: freemem(),
|
|
219001
219199
|
total_mem_bytes: totalmem(),
|
|
219002
219200
|
cpu_count: cpus().length
|
|
219003
|
-
}
|
|
219201
|
+
};
|
|
219202
|
+
if (constrainedMemory !== void 0) properties["constrained_memory_bytes"] = constrainedMemory;
|
|
219203
|
+
this.client.track(SYSTEM_METRICS_EVENT, properties);
|
|
219004
219204
|
}
|
|
219005
219205
|
};
|
|
219006
219206
|
function getConstrainedMemoryBytes() {
|
|
219007
219207
|
if (typeof process.constrainedMemory !== "function") return void 0;
|
|
219008
219208
|
const value = process.constrainedMemory();
|
|
219009
|
-
return Number.
|
|
219209
|
+
return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
219010
219210
|
}
|
|
219011
219211
|
const SERVER_EVENT_PREFIX = "kfc_";
|
|
219012
219212
|
const USER_ID_PREFIX = "kfc_device_id_";
|
|
@@ -238571,7 +238771,10 @@ async function compressPromptImageParts(parts, options = {}) {
|
|
|
238571
238771
|
if (part.type === "image_url") {
|
|
238572
238772
|
const parsed = parseImageDataUrl(part.imageUrl.url);
|
|
238573
238773
|
if (parsed !== null) {
|
|
238574
|
-
const result = await compressBase64ForModel(parsed.base64, parsed.mimeType
|
|
238774
|
+
const result = await compressBase64ForModel(parsed.base64, parsed.mimeType, { telemetry: options.telemetry === void 0 ? void 0 : {
|
|
238775
|
+
client: options.telemetry,
|
|
238776
|
+
source: "acp_prompt"
|
|
238777
|
+
} });
|
|
238575
238778
|
if (result.changed) {
|
|
238576
238779
|
const originalPath = await persistOriginalImage(Buffer.from(parsed.base64, "base64"), parsed.mimeType, options.originalsDir === void 0 ? {} : { dir: options.originalsDir });
|
|
238577
238780
|
out.push({
|
|
@@ -240372,7 +240575,11 @@ var AcpSession = class {
|
|
|
240372
240575
|
let parts;
|
|
240373
240576
|
try {
|
|
240374
240577
|
const sessionDir = this.session.summary?.sessionDir;
|
|
240375
|
-
|
|
240578
|
+
const track = this.track;
|
|
240579
|
+
parts = await compressPromptImageParts(acpBlocksToPromptParts(blocks), {
|
|
240580
|
+
originalsDir: sessionDir === void 0 ? void 0 : sessionMediaOriginalsDir(sessionDir),
|
|
240581
|
+
telemetry: track === void 0 ? void 0 : { track: (event, properties) => track(event, properties === void 0 ? void 0 : { ...properties }) }
|
|
240582
|
+
});
|
|
240376
240583
|
} finally {
|
|
240377
240584
|
this.pendingPromptAborts.delete(pending);
|
|
240378
240585
|
}
|
|
@@ -276137,10 +276344,13 @@ function registerPromptsRoutes(app, ix) {
|
|
|
276137
276344
|
const promptService = a.get(IPromptService);
|
|
276138
276345
|
const fileStore = a.get(IFileStore);
|
|
276139
276346
|
const core = a.get(ICoreProcessService);
|
|
276140
|
-
const resolved = await resolvePromptMediaFiles(body, fileStore, join(a.get(IEnvironmentService).homeDir, "cache"), {
|
|
276141
|
-
|
|
276142
|
-
|
|
276143
|
-
|
|
276347
|
+
const resolved = await resolvePromptMediaFiles(body, fileStore, join(a.get(IEnvironmentService).homeDir, "cache"), {
|
|
276348
|
+
telemetry: core.telemetry === void 0 ? void 0 : withTelemetryContext$1(core.telemetry, { sessionId: session_id }),
|
|
276349
|
+
resolveOriginalsDir: async () => {
|
|
276350
|
+
const sessionDir = (await core.rpc.listSessions({ sessionId: session_id }))[0]?.sessionDir;
|
|
276351
|
+
return sessionDir === void 0 ? void 0 : sessionMediaOriginalsDir(sessionDir);
|
|
276352
|
+
}
|
|
276353
|
+
});
|
|
276144
276354
|
return promptService.submit(session_id, resolved);
|
|
276145
276355
|
});
|
|
276146
276356
|
reply.send(okEnvelope(result, req.id));
|
|
@@ -276229,10 +276439,14 @@ async function resolvePromptMediaFiles(body, store, cacheDir, options = {}) {
|
|
|
276229
276439
|
}
|
|
276230
276440
|
return originalsDir;
|
|
276231
276441
|
};
|
|
276442
|
+
const telemetryFor = (source) => options.telemetry === void 0 ? void 0 : {
|
|
276443
|
+
client: options.telemetry,
|
|
276444
|
+
source
|
|
276445
|
+
};
|
|
276232
276446
|
const content = [];
|
|
276233
276447
|
for (const part of body.content) {
|
|
276234
276448
|
if (part.type === "image" && part.source.kind === "base64") {
|
|
276235
|
-
const compressed = await compressBase64ForModel(part.source.data, part.source.media_type);
|
|
276449
|
+
const compressed = await compressBase64ForModel(part.source.data, part.source.media_type, { telemetry: telemetryFor("prompt_inline") });
|
|
276236
276450
|
if (compressed.changed) {
|
|
276237
276451
|
const dir = await resolveOriginalsDir();
|
|
276238
276452
|
const originalPath = await persistOriginalImage(Buffer.from(part.source.data, "base64"), part.source.media_type, dir === void 0 ? {} : { dir });
|
|
@@ -276285,7 +276499,7 @@ async function resolvePromptMediaFiles(body, store, cacheDir, options = {}) {
|
|
|
276285
276499
|
let mediaType = file.meta.media_type;
|
|
276286
276500
|
let bytes = data;
|
|
276287
276501
|
if (part.type === "image") {
|
|
276288
|
-
const compressed = await compressImageForModel(data, mediaType);
|
|
276502
|
+
const compressed = await compressImageForModel(data, mediaType, { telemetry: telemetryFor("prompt_file") });
|
|
276289
276503
|
if (compressed.changed) content.push({
|
|
276290
276504
|
type: "text",
|
|
276291
276505
|
text: buildImageCompressionCaption({
|
|
@@ -368352,7 +368566,11 @@ init_dist$7();
|
|
|
368352
368566
|
*
|
|
368353
368567
|
* Used to bound shutdown so a wedged cleanup step can't keep a completed
|
|
368354
368568
|
* headless run alive, without silently swallowing a cleanup that fails fast. The
|
|
368355
|
-
* timer
|
|
368569
|
+
* timer stays ref'd so a cleanup step that suspends on an unref'd handle (e.g.
|
|
368570
|
+
* telemetry's retry backoff when the network is blocked) can't drain the event
|
|
368571
|
+
* loop and exit 0 before the rejection propagates — the timer keeps the loop
|
|
368572
|
+
* alive until it fires, then gives the rejection a chance to surface. A wedged
|
|
368573
|
+
* cleanup is still bounded by `timeoutMs`, so this can't hang the run forever.
|
|
368356
368574
|
*/
|
|
368357
368575
|
async function raceWithTimeout(promise, timeoutMs) {
|
|
368358
368576
|
let timedOut = false;
|
|
@@ -368366,7 +368584,6 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
368366
368584
|
timedOut = true;
|
|
368367
368585
|
resolve();
|
|
368368
368586
|
}, timeoutMs);
|
|
368369
|
-
timer.unref?.();
|
|
368370
368587
|
});
|
|
368371
368588
|
try {
|
|
368372
368589
|
await Promise.race([guarded, timedOutSignal]);
|
|
@@ -374112,15 +374329,18 @@ var EditorKeyboardController = class {
|
|
|
374112
374329
|
}
|
|
374113
374330
|
const meta = parseImageMeta(media.bytes);
|
|
374114
374331
|
if (meta === null) return false;
|
|
374115
|
-
const compressed = await compressImageForModel(media.bytes, meta.mime
|
|
374332
|
+
const compressed = await compressImageForModel(media.bytes, meta.mime, { telemetry: {
|
|
374333
|
+
client: { track: (event, properties) => this.host.track(event, properties === void 0 ? void 0 : { ...properties }) },
|
|
374334
|
+
source: "tui_paste"
|
|
374335
|
+
} });
|
|
374116
374336
|
const sessionDir = this.host.session?.summary?.sessionDir;
|
|
374117
374337
|
const attachment = compressed.changed ? this.imageStore.addImage(compressed.data, compressed.mimeType, compressed.width, compressed.height, {
|
|
374118
374338
|
path: await persistOriginalImage(media.bytes, meta.mime, sessionDir === void 0 ? {} : { dir: sessionMediaOriginalsDir(sessionDir) }),
|
|
374119
|
-
width:
|
|
374120
|
-
height:
|
|
374339
|
+
width: compressed.originalWidth,
|
|
374340
|
+
height: compressed.originalHeight,
|
|
374121
374341
|
byteLength: media.bytes.length,
|
|
374122
374342
|
mime: meta.mime
|
|
374123
|
-
}) : this.imageStore.addImage(media.bytes, meta.mime, meta.width, meta.height);
|
|
374343
|
+
}) : this.imageStore.addImage(media.bytes, meta.mime, compressed.width || meta.width, compressed.height || meta.height);
|
|
374124
374344
|
this.host.state.editor.insertTextAtCursor?.(`${attachment.placeholder} `);
|
|
374125
374345
|
this.host.state.ui.requestRender();
|
|
374126
374346
|
this.host.track("shortcut_paste", { kind: "image" });
|
|
@@ -383290,6 +383510,7 @@ function main() {
|
|
|
383290
383510
|
handleMainCommand(opts, version).then(async (outcome) => {
|
|
383291
383511
|
if (outcome.headlessCompleted) await finalizeHeadlessRun(process, [process.stdout, process.stderr], () => Number(process.exitCode) || 0);
|
|
383292
383512
|
}).catch(async (error) => {
|
|
383513
|
+
process.exitCode = 1;
|
|
383293
383514
|
const operation = opts.prompt !== void 0 ? "run prompt" : "start shell";
|
|
383294
383515
|
await logStartupFailure(operation, error);
|
|
383295
383516
|
process.stderr.write(formatStartupError(error, { operation }));
|