@eddyskywalker/dsh-chatgpt-subscription 0.60.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +1 -1
- package/lib/client.js.map +1 -1
- package/lib/codemode.js +319 -89
- package/lib/entry-plan-mode-CLRKkgYG.js +1787 -0
- package/lib/{entry-progress-updates-CxQewio9.js → entry-progress-updates-DZ0ZRus4.js} +14 -1
- package/lib/index.js +975 -576
- package/lib/plan-mode.js +2 -779
- package/lib/progress-updates.js +1 -1
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/entry-codemode.d.ts.map +1 -1
- package/lib/types/entry-plan-mode.d.ts +136 -0
- package/lib/types/entry-plan-mode.d.ts.map +1 -1
- package/lib/types/host/agent-preset.d.ts.map +1 -1
- package/lib/types/host/claude/adapter.d.ts +16 -0
- package/lib/types/host/claude/adapter.d.ts.map +1 -1
- package/lib/types/host/claude/client.d.ts +7 -1
- package/lib/types/host/claude/client.d.ts.map +1 -1
- package/lib/types/host/claude/mapper.d.ts +9 -0
- package/lib/types/host/claude/mapper.d.ts.map +1 -1
- package/lib/types/host/claude/types.d.ts +10 -0
- package/lib/types/host/claude/types.d.ts.map +1 -1
- package/lib/types/host/cline-pass/mapper.d.ts.map +1 -1
- package/lib/types/host/codemode/discovery.d.ts.map +1 -1
- package/lib/types/host/codemode/rules.d.ts.map +1 -1
- package/lib/types/host/codemode/transport.d.ts +38 -0
- package/lib/types/host/codemode/transport.d.ts.map +1 -1
- package/lib/types/host/command-code/mapper.d.ts.map +1 -1
- package/lib/types/host/common/orphan-tool-calls.d.ts +48 -0
- package/lib/types/host/common/orphan-tool-calls.d.ts.map +1 -0
- package/lib/types/host/dispatch-execution-guard.d.ts +32 -2
- package/lib/types/host/dispatch-execution-guard.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/mapper-anthropic.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/mapper-openai.d.ts.map +1 -1
- package/lib/types/host/kimi-code/mapper.d.ts.map +1 -1
- package/lib/types/host/minimax-code/mapper.d.ts.map +1 -1
- package/lib/types/host/model-catalog.d.ts +21 -0
- package/lib/types/host/model-catalog.d.ts.map +1 -1
- package/lib/types/host/opendesign/mapper.d.ts.map +1 -1
- package/lib/types/host/opendesign/types.d.ts +7 -2
- package/lib/types/host/opendesign/types.d.ts.map +1 -1
- package/lib/types/host/plan-mode-cache-guard.d.ts.map +1 -1
- package/lib/types/host/progress-updates/nudge.d.ts +13 -1
- package/lib/types/host/progress-updates/nudge.d.ts.map +1 -1
- package/lib/types/host/qoder/mapper.d.ts.map +1 -1
- package/lib/types/host/responses-client.d.ts.map +1 -1
- package/lib/types/host/responses-mapper.d.ts +12 -0
- package/lib/types/host/responses-mapper.d.ts.map +1 -1
- package/lib/types/host/settled-job-guard.d.ts +77 -0
- package/lib/types/host/settled-job-guard.d.ts.map +1 -0
- package/lib/types/host/step-code/mapper.d.ts.map +1 -1
- package/lib/types/host/workbuddy/mapper.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/presets/dispatch/README.md +7 -10
- package/presets/dispatch/agent.cordis.yml +4 -11
package/lib/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as resolveProgressUpdatesSettings, n as attachProgressSettings } from "./entry-progress-updates-
|
|
1
|
+
import { a as resolveProgressUpdatesSettings, n as attachProgressSettings } from "./entry-progress-updates-DZ0ZRus4.js";
|
|
2
2
|
import { attachPlanModePipelineSettings, resolvePlanModePipelineEnabled } from "./plan-mode-pipeline.js";
|
|
3
3
|
import { n as PLUGIN_MESSAGE_SOURCE_KIND, r as normalizeGenerateOptions, t as LlmError$1 } from "./llm-compat-u9mor0uu.js";
|
|
4
4
|
import { DEFAULT_SKIP_PROVIDERS, PRUNER_SERVICE_NAME, resolveSkipProviders, shouldSkipPruningForSession } from "./tool-result-pruner.js";
|
|
5
|
-
import { PLAN_PROJECTION_KEY, createPlanNotice } from "./plan-mode.js";
|
|
5
|
+
import { b as installDispatchExecutionGuard, h as installPlanModeExitReminder, l as PLAN_PROJECTION_KEY, p as createPlanNotice, v as registeredPlanControllerActive, x as resolveDispatchExecutionGuardEnabled } from "./entry-plan-mode-CLRKkgYG.js";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import * as LlmModule from "@deepseek-ai/dsh-llm";
|
|
8
8
|
import { EMPTY_RESPONSE_CODE, HarnessError, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, ToolCallId, attributionHeaders, createUserMessage, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
@@ -808,7 +808,7 @@ const ROUTE_PREFIX$5 = "/api/dsh-chatgpt-subscription";
|
|
|
808
808
|
* `test/responses-client.test.ts` asserts the two agree, so a release that
|
|
809
809
|
* forgets this constant fails the suite instead of shipping quietly.
|
|
810
810
|
*/
|
|
811
|
-
const PLUGIN_VERSION = "0.
|
|
811
|
+
const PLUGIN_VERSION = "0.62.0";
|
|
812
812
|
const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
|
|
813
813
|
const CODEX_API_BASE = "https://chatgpt.com/backend-api/codex";
|
|
814
814
|
const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses`;
|
|
@@ -1193,6 +1193,7 @@ function resolveCodexModel(model, preferences, live) {
|
|
|
1193
1193
|
inputModalities: [...liveEntry?.inputModalities ?? entry.inputModalities],
|
|
1194
1194
|
context: { contextWindow: configuredContextWindow ?? liveEntry?.contextWindow ?? entry.contextWindow },
|
|
1195
1195
|
...outputReservation(configuredContextWindow ?? liveEntry?.contextWindow ?? entry.contextWindow, codexModelMaxTokens(model)),
|
|
1196
|
+
...codexToolUpdateMode() === void 0 ? {} : { toolUpdate: codexToolUpdateMode() },
|
|
1196
1197
|
reasoning: {
|
|
1197
1198
|
efforts: orderReasoningEfforts(efforts, GPT_56_REASONING_EFFORTS).map((effort) => ({
|
|
1198
1199
|
id: ReasoningEffortId(effort),
|
|
@@ -1203,6 +1204,46 @@ function resolveCodexModel(model, preferences, live) {
|
|
|
1203
1204
|
};
|
|
1204
1205
|
}
|
|
1205
1206
|
/**
|
|
1207
|
+
* Whether this line may state a tool change in the history instead of rewriting
|
|
1208
|
+
* the head.
|
|
1209
|
+
*
|
|
1210
|
+
* `in-history` rather than `addition-only`: this wire has an `additional_tools`
|
|
1211
|
+
* item to add a tool but nothing to withdraw one, so a removal has to keep its
|
|
1212
|
+
* declaration and travel as a note. Deleting the declaration would shorten the
|
|
1213
|
+
* head and throw the cached prefix away, which is the cost this mode exists to
|
|
1214
|
+
* avoid.
|
|
1215
|
+
*
|
|
1216
|
+
* `DSH_CODEX_TOOL_UPDATE=0` turns it off for one account without a code change,
|
|
1217
|
+
* the same escape hatch kimi-code carries for its own gate.
|
|
1218
|
+
*
|
|
1219
|
+
* @returns the mode to declare, or undefined when every request must restate the
|
|
1220
|
+
* complete tool list.
|
|
1221
|
+
*/
|
|
1222
|
+
function codexToolUpdateMode() {
|
|
1223
|
+
if (toolUpdateRejected) return void 0;
|
|
1224
|
+
const raw = (process.env.DSH_CODEX_TOOL_UPDATE ?? "").trim().toLowerCase();
|
|
1225
|
+
if (raw !== "" && [
|
|
1226
|
+
"0",
|
|
1227
|
+
"false",
|
|
1228
|
+
"no",
|
|
1229
|
+
"off",
|
|
1230
|
+
"none"
|
|
1231
|
+
].includes(raw)) return void 0;
|
|
1232
|
+
return "in-history";
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Set when a request that carried a tool change was refused with a 400.
|
|
1236
|
+
*
|
|
1237
|
+
* Process-wide and one-way: the failure mode of a stale probe is a lost cache
|
|
1238
|
+
* optimisation, and the failure mode of NOT latching is the same 400 on every
|
|
1239
|
+
* later turn. The asymmetry decides it.
|
|
1240
|
+
*/
|
|
1241
|
+
let toolUpdateRejected = false;
|
|
1242
|
+
/** Record a refusal, so every later request restates the complete tool list. */
|
|
1243
|
+
function disableCodexToolUpdate() {
|
|
1244
|
+
toolUpdateRejected = true;
|
|
1245
|
+
}
|
|
1246
|
+
/**
|
|
1206
1247
|
* Resolve the wire capabilities of one model.
|
|
1207
1248
|
*
|
|
1208
1249
|
* The live listing outranks the shipped table, because the backend is the
|
|
@@ -1753,7 +1794,7 @@ function parseListing(payload) {
|
|
|
1753
1794
|
function parseListingEntry$1(value) {
|
|
1754
1795
|
const record = asRecord$20(value);
|
|
1755
1796
|
if (record === void 0) return [];
|
|
1756
|
-
const id = asString$
|
|
1797
|
+
const id = asString$31(record.slug) ?? asString$31(record.id);
|
|
1757
1798
|
if (id === void 0) return [];
|
|
1758
1799
|
const contextWindow = asNumber$8(record.context_window) ?? asNumber$8(record.contextWindow);
|
|
1759
1800
|
const modalities = parseModalities(record.input_modalities);
|
|
@@ -1762,11 +1803,11 @@ function parseListingEntry$1(value) {
|
|
|
1762
1803
|
const fallback = CODEX_MODEL_CATALOG.find((entry) => entry.id === id);
|
|
1763
1804
|
return [{
|
|
1764
1805
|
id,
|
|
1765
|
-
name: asString$
|
|
1806
|
+
name: asString$31(record.display_name) ?? asString$31(record.displayName) ?? fallback?.name ?? id,
|
|
1766
1807
|
contextWindow: contextWindow !== void 0 && contextWindow > 0 ? contextWindow : null,
|
|
1767
1808
|
inputModalities: modalities ?? (fallback ? [...fallback.inputModalities] : ["text"]),
|
|
1768
1809
|
...efforts !== null ? { reasoningEfforts: efforts } : {},
|
|
1769
|
-
defaultReasoningEffort: asString$
|
|
1810
|
+
defaultReasoningEffort: asString$31(record.default_reasoning_level) ?? fallback?.defaultReasoningEffort ?? null,
|
|
1770
1811
|
...useResponsesLite !== void 0 ? { useResponsesLite } : {}
|
|
1771
1812
|
}];
|
|
1772
1813
|
}
|
|
@@ -1774,7 +1815,7 @@ function parseModalities(value) {
|
|
|
1774
1815
|
if (!Array.isArray(value)) return null;
|
|
1775
1816
|
const out = [];
|
|
1776
1817
|
for (const item of value) {
|
|
1777
|
-
const name = asString$
|
|
1818
|
+
const name = asString$31(item);
|
|
1778
1819
|
if (name === "text" || name === "image") out.push(name);
|
|
1779
1820
|
}
|
|
1780
1821
|
return out.length > 0 ? out : null;
|
|
@@ -1789,7 +1830,7 @@ function parseEfforts(value) {
|
|
|
1789
1830
|
if (!Array.isArray(value)) return null;
|
|
1790
1831
|
const out = [];
|
|
1791
1832
|
for (const item of value) {
|
|
1792
|
-
const effort = asString$
|
|
1833
|
+
const effort = asString$31(item) ?? asString$31(asRecord$20(item)?.effort);
|
|
1793
1834
|
if (effort !== void 0 && !out.includes(effort)) out.push(effort);
|
|
1794
1835
|
}
|
|
1795
1836
|
return out.length > 0 ? out : null;
|
|
@@ -1814,7 +1855,7 @@ function accountKeyFor$1(credentials) {
|
|
|
1814
1855
|
function asRecord$20(value) {
|
|
1815
1856
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1816
1857
|
}
|
|
1817
|
-
function asString$
|
|
1858
|
+
function asString$31(value) {
|
|
1818
1859
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
1819
1860
|
}
|
|
1820
1861
|
function asNumber$8(value) {
|
|
@@ -8178,7 +8219,7 @@ function sanitizeText$9(text) {
|
|
|
8178
8219
|
function isRecord$64(value) {
|
|
8179
8220
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8180
8221
|
}
|
|
8181
|
-
function asString$
|
|
8222
|
+
function asString$30(value) {
|
|
8182
8223
|
return typeof value === "string" ? value : void 0;
|
|
8183
8224
|
}
|
|
8184
8225
|
function safeJsonParse$9(text) {
|
|
@@ -8208,7 +8249,7 @@ function attachmentOf$5(block) {
|
|
|
8208
8249
|
}
|
|
8209
8250
|
function attachmentLabel$6(block) {
|
|
8210
8251
|
const attachment = isRecord$64(block.attachment) ? block.attachment : void 0;
|
|
8211
|
-
return asString$
|
|
8252
|
+
return asString$30(attachment?.name) || asString$30(attachment?.attachmentId);
|
|
8212
8253
|
}
|
|
8213
8254
|
function collectImageRefs$3(content, refs) {
|
|
8214
8255
|
if (!Array.isArray(content)) return;
|
|
@@ -8345,10 +8386,10 @@ function unavailableImageText$6(block) {
|
|
|
8345
8386
|
return `[image unavailable: ${label ? `${label} could not be read` : "the image could not be read"}; ask the user to attach it again if the image is needed]`;
|
|
8346
8387
|
}
|
|
8347
8388
|
function imageBlockToPart(block, images) {
|
|
8348
|
-
let data = asString$
|
|
8389
|
+
let data = asString$30(block.data) || asString$30(block.base64);
|
|
8349
8390
|
const source = isRecord$64(block.source) ? block.source : void 0;
|
|
8350
|
-
if (!data && source) data = asString$
|
|
8351
|
-
let mimeType = asString$
|
|
8391
|
+
if (!data && source) data = asString$30(source.data) || asString$30(source.base64);
|
|
8392
|
+
let mimeType = asString$30(block.mimeType) || asString$30(block.mediaType) || (source ? asString$30(source.mimeType) || asString$30(source.mediaType) : void 0) || "image/png";
|
|
8352
8393
|
if (data?.startsWith("data:")) {
|
|
8353
8394
|
const match = data.match(/^data:([^;,]+);base64,(.*)$/s);
|
|
8354
8395
|
if (match) {
|
|
@@ -8422,7 +8463,7 @@ function replayBlockFor$1(message, index) {
|
|
|
8422
8463
|
}
|
|
8423
8464
|
}
|
|
8424
8465
|
function thoughtSignature(part) {
|
|
8425
|
-
return asString$
|
|
8466
|
+
return asString$30(part?.thoughtSignature) || asString$30(part?.thought_signature) || asString$30(part?.thinkingSignature) || asString$30(part?.textSignature);
|
|
8426
8467
|
}
|
|
8427
8468
|
function replayPart(part) {
|
|
8428
8469
|
const copy = { ...part };
|
|
@@ -8521,7 +8562,7 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
|
|
|
8521
8562
|
if (block.type === "reasoning" && runtimeModel.startsWith("claude-") && (message.source?.kind !== "model" || message.source.provider !== "antigravity" || !("model" in message.source) || message.source.model !== model.id)) continue;
|
|
8522
8563
|
const replay = replayBlockFor$1(message, index);
|
|
8523
8564
|
const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord$64) : [];
|
|
8524
|
-
if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString$
|
|
8565
|
+
if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString$30(part.text) || "").join("") === sanitizeText$9(String(block.text || ""))) {
|
|
8525
8566
|
parts.push(...originalParts.map(replayPart));
|
|
8526
8567
|
continue;
|
|
8527
8568
|
}
|
|
@@ -8542,7 +8583,7 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
|
|
|
8542
8583
|
const toolId = String(block.id || "");
|
|
8543
8584
|
const toolName = String(block.name || "");
|
|
8544
8585
|
const originalCall = originalParts.find((part) => isRecord$64(part.functionCall));
|
|
8545
|
-
const wireId = asString$
|
|
8586
|
+
const wireId = asString$30((isRecord$64(originalCall?.functionCall) ? originalCall.functionCall : void 0)?.id) || (toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(toolId, toolName) : originalCall ? void 0 : toolId || void 0);
|
|
8546
8587
|
toolCalls.set(toolId, {
|
|
8547
8588
|
name: toolName,
|
|
8548
8589
|
id: wireId
|
|
@@ -8787,7 +8828,7 @@ function processStreamLine$4(line, state) {
|
|
|
8787
8828
|
if (!isRecord$64(chunk)) return [];
|
|
8788
8829
|
const responseData = isRecord$64(chunk.response) ? chunk.response : chunk;
|
|
8789
8830
|
const error = isRecord$64(chunk.error) ? chunk.error : isRecord$64(responseData.error) ? responseData.error : void 0;
|
|
8790
|
-
if (error !== void 0) throw new LlmError$1(`Antigravity stream error: ${asString$
|
|
8831
|
+
if (error !== void 0) throw new LlmError$1(`Antigravity stream error: ${asString$30(error.message) ?? "unknown error"}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
|
|
8791
8832
|
const candidates = Array.isArray(responseData.candidates) ? responseData.candidates : [];
|
|
8792
8833
|
const candidate = isRecord$64(candidates[0]) ? candidates[0] : void 0;
|
|
8793
8834
|
const content = isRecord$64(candidate?.content) ? candidate.content : void 0;
|
|
@@ -8853,8 +8894,8 @@ function processStreamLine$4(line, state) {
|
|
|
8853
8894
|
if (isRecord$64(part.functionCall)) {
|
|
8854
8895
|
out.push(...closeCurrentBlock(state));
|
|
8855
8896
|
const fc = part.functionCall;
|
|
8856
|
-
const toolName = asString$
|
|
8857
|
-
const toolId = asString$
|
|
8897
|
+
const toolName = asString$30(fc.name) || "";
|
|
8898
|
+
const toolId = asString$30(fc.id) || sanitizeToolCallId("", toolName);
|
|
8858
8899
|
const argsText = JSON.stringify(isRecord$64(fc.args) ? fc.args : {});
|
|
8859
8900
|
const index = state.blocks.length;
|
|
8860
8901
|
const block = {
|
|
@@ -8892,10 +8933,10 @@ function processStreamLine$4(line, state) {
|
|
|
8892
8933
|
}
|
|
8893
8934
|
collectUsage(chunk.usageMetadata, state);
|
|
8894
8935
|
if (responseData !== chunk) collectUsage(responseData.usageMetadata, state);
|
|
8895
|
-
const finishMessage = asString$
|
|
8936
|
+
const finishMessage = asString$30(candidate?.finishMessage);
|
|
8896
8937
|
if (finishMessage) state.finishMessage = finishMessage;
|
|
8897
|
-
const blockReason = asString$
|
|
8898
|
-
const finishReason = asString$
|
|
8938
|
+
const blockReason = asString$30((isRecord$64(responseData.promptFeedback) ? responseData.promptFeedback : void 0)?.blockReason);
|
|
8939
|
+
const finishReason = asString$30(candidate?.finishReason) || asString$30(responseData.finishReason) || (blockReason ? `PROMPT_BLOCKED:${blockReason}` : void 0);
|
|
8899
8940
|
if (finishReason) {
|
|
8900
8941
|
state.finishReason = finishReason;
|
|
8901
8942
|
out.push(...closeCurrentBlock(state));
|
|
@@ -8970,7 +9011,7 @@ function closeStream$7(state) {
|
|
|
8970
9011
|
function isRecord$63(value) {
|
|
8971
9012
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8972
9013
|
}
|
|
8973
|
-
function asString$
|
|
9014
|
+
function asString$29(value) {
|
|
8974
9015
|
return typeof value === "string" ? value : void 0;
|
|
8975
9016
|
}
|
|
8976
9017
|
/**
|
|
@@ -9031,7 +9072,7 @@ function attachmentOf$4(block) {
|
|
|
9031
9072
|
}
|
|
9032
9073
|
function attachmentLabel$5(block) {
|
|
9033
9074
|
const attachment = isRecord$63(block.attachment) ? block.attachment : void 0;
|
|
9034
|
-
return asString$
|
|
9075
|
+
return asString$29(attachment?.name) || asString$29(attachment?.attachmentId);
|
|
9035
9076
|
}
|
|
9036
9077
|
function collectImageRefs$2(content, refs) {
|
|
9037
9078
|
if (!Array.isArray(content)) return;
|
|
@@ -9065,9 +9106,9 @@ function base64Length$2(bytes) {
|
|
|
9065
9106
|
* has no resolved map behaves exactly as before.
|
|
9066
9107
|
*/
|
|
9067
9108
|
function inlinePayloadOf$1(block) {
|
|
9068
|
-
let data = asString$
|
|
9109
|
+
let data = asString$29(block.data) || asString$29(block.base64);
|
|
9069
9110
|
const source = isRecord$63(block.source) ? block.source : void 0;
|
|
9070
|
-
if (!data && source) data = asString$
|
|
9111
|
+
if (!data && source) data = asString$29(source.data) || asString$29(source.base64);
|
|
9071
9112
|
if (data?.startsWith("data:")) {
|
|
9072
9113
|
const matched = data.match(/^data:([^;,]+);base64,(.*)$/s);
|
|
9073
9114
|
if (matched) data = matched[2] ?? "";
|
|
@@ -9530,10 +9571,10 @@ function unavailableImageText$5(block) {
|
|
|
9530
9571
|
return `[image unavailable: ${label ? `${label} could not be read` : "the image could not be read"}; ask the user to attach it again if the image is needed]`;
|
|
9531
9572
|
}
|
|
9532
9573
|
function imageBlockToInline$3(block, images) {
|
|
9533
|
-
let data = asString$
|
|
9574
|
+
let data = asString$29(block.data) || asString$29(block.base64);
|
|
9534
9575
|
const source = isRecord$63(block.source) ? block.source : void 0;
|
|
9535
|
-
if (!data && source) data = asString$
|
|
9536
|
-
let mediaType = asString$
|
|
9576
|
+
if (!data && source) data = asString$29(source.data) || asString$29(source.base64);
|
|
9577
|
+
let mediaType = asString$29(block.mimeType) || asString$29(block.mediaType) || (source ? asString$29(source.mimeType) || asString$29(source.mediaType) : void 0) || "image/png";
|
|
9537
9578
|
if (data?.startsWith("data:")) {
|
|
9538
9579
|
const matched = data.match(/^data:([^;,]+);base64,(.*)$/s);
|
|
9539
9580
|
if (matched) {
|
|
@@ -13110,6 +13151,21 @@ async function buildResponsesPayload(options, attachments, localRawImages = {},
|
|
|
13110
13151
|
});
|
|
13111
13152
|
continue;
|
|
13112
13153
|
}
|
|
13154
|
+
if (message.role === "developer") {
|
|
13155
|
+
input.push(...toolChangeItems(message, options.tools, wire.idNamespace));
|
|
13156
|
+
const rest = message.content.filter((block) => block.type !== "tool-addition" && block.type !== "tool-removal");
|
|
13157
|
+
if (rest.length > 0) {
|
|
13158
|
+
const content = await mapContent({
|
|
13159
|
+
...message,
|
|
13160
|
+
content: rest
|
|
13161
|
+
}, attachments, options.signal, localRawImages, localImageStats, resolveLocalRawImages);
|
|
13162
|
+
if (content.length > 0) input.push({
|
|
13163
|
+
role: "developer",
|
|
13164
|
+
content
|
|
13165
|
+
});
|
|
13166
|
+
}
|
|
13167
|
+
continue;
|
|
13168
|
+
}
|
|
13113
13169
|
const content = await mapContent(message, attachments, options.signal, localRawImages, localImageStats, resolveLocalRawImages);
|
|
13114
13170
|
if (content.length > 0) input.push({
|
|
13115
13171
|
role: message.role,
|
|
@@ -13120,8 +13176,9 @@ async function buildResponsesPayload(options, attachments, localRawImages = {},
|
|
|
13120
13176
|
offloadOldestInputImages(input);
|
|
13121
13177
|
const instructionText = [...instructionParts, localRawImageInstruction(localImageStats)].filter((value) => Boolean(value)).join("\n\n");
|
|
13122
13178
|
const prefix = [];
|
|
13123
|
-
const
|
|
13124
|
-
|
|
13179
|
+
const allTools = options.tools ?? [];
|
|
13180
|
+
const tools = allTools.filter((tool) => tool.deferLoading !== true);
|
|
13181
|
+
if (useResponsesLite && allTools.length > 0) prefix.push(additionalToolsItem(allTools, wire.idNamespace));
|
|
13125
13182
|
if (instructionText !== "") prefix.push(developerMessageItem(instructionText, wire.idNamespace, useResponsesLite));
|
|
13126
13183
|
input.unshift(...prefix);
|
|
13127
13184
|
const toolDeclarations = tools.length > 0 ? tools.map(toolDeclaration) : void 0;
|
|
@@ -13193,6 +13250,87 @@ function additionalToolsItem(tools, idNamespace) {
|
|
|
13193
13250
|
};
|
|
13194
13251
|
}
|
|
13195
13252
|
/**
|
|
13253
|
+
* The input items one mid-conversation tool change becomes.
|
|
13254
|
+
*
|
|
13255
|
+
* An addition travels as an `additional_tools` item at the point in the history
|
|
13256
|
+
* where it happened. The item carries the full definition, so the head never has
|
|
13257
|
+
* to grow it: everything before this position keeps its cached prefix and the
|
|
13258
|
+
* backend reads the new tool from here onward.
|
|
13259
|
+
*
|
|
13260
|
+
* A removal has no wire form of its own — there is no `tool_removal` item — so
|
|
13261
|
+
* the declaration stays exactly where it is and this note tells the model the
|
|
13262
|
+
* tool is gone. Dropping the declaration instead would shorten the head and
|
|
13263
|
+
* throw the prefix away, which is the cost `in-history` exists to avoid.
|
|
13264
|
+
*
|
|
13265
|
+
* Measured on the subscription backend by
|
|
13266
|
+
* `scripts/probe-codex-tool-updates.probe.ts`: the item is accepted, the model
|
|
13267
|
+
* calls a tool that only ever appeared in it, and a padded prefix stays cached
|
|
13268
|
+
* across the addition.
|
|
13269
|
+
*
|
|
13270
|
+
* @param message - the developer message carrying the change.
|
|
13271
|
+
* @param tools - the active declaration set the change resolves against.
|
|
13272
|
+
* @param idNamespace - the conversation identity, for stable item ids.
|
|
13273
|
+
* @returns the items to append at this position, in order.
|
|
13274
|
+
*/
|
|
13275
|
+
function toolChangeItems(message, tools, idNamespace) {
|
|
13276
|
+
const byName = new Map((tools ?? []).map((tool) => [tool.name, tool]));
|
|
13277
|
+
const added = [];
|
|
13278
|
+
const removed = [];
|
|
13279
|
+
for (const block of message.content) {
|
|
13280
|
+
const name = typeof block["toolName"] === "string" ? block["toolName"] : "";
|
|
13281
|
+
if (name === "") continue;
|
|
13282
|
+
if (block["type"] === "tool-addition") {
|
|
13283
|
+
const tool = byName.get(name);
|
|
13284
|
+
if (tool !== void 0) added.push(toolDeclaration(tool));
|
|
13285
|
+
} else if (block["type"] === "tool-removal") removed.push(name);
|
|
13286
|
+
}
|
|
13287
|
+
const items = [];
|
|
13288
|
+
if (added.length > 0) items.push({
|
|
13289
|
+
type: "additional_tools",
|
|
13290
|
+
id: stableItemId("at", idNamespace, JSON.stringify(added)),
|
|
13291
|
+
role: "developer",
|
|
13292
|
+
tools: added
|
|
13293
|
+
});
|
|
13294
|
+
if (removed.length > 0) {
|
|
13295
|
+
const text = toolRemovalNotice(removed);
|
|
13296
|
+
items.push({
|
|
13297
|
+
type: "message",
|
|
13298
|
+
id: stableItemId("msg", idNamespace, text),
|
|
13299
|
+
role: "developer",
|
|
13300
|
+
content: [{
|
|
13301
|
+
type: "input_text",
|
|
13302
|
+
text
|
|
13303
|
+
}]
|
|
13304
|
+
});
|
|
13305
|
+
}
|
|
13306
|
+
return items;
|
|
13307
|
+
}
|
|
13308
|
+
/**
|
|
13309
|
+
* The same request with every tool change taken back out.
|
|
13310
|
+
*
|
|
13311
|
+
* This is the shape a backend that refuses the update channel gets: the complete
|
|
13312
|
+
* current declaration list at the head, no change messages, no deferred markers.
|
|
13313
|
+
* It is exactly what the line sent before the capability existed, so the fallback
|
|
13314
|
+
* costs a cache miss and nothing else.
|
|
13315
|
+
*
|
|
13316
|
+
* @param options - the request that was refused.
|
|
13317
|
+
* @returns a request the line can always send.
|
|
13318
|
+
*/
|
|
13319
|
+
function withoutCodexToolChanges(options) {
|
|
13320
|
+
const messages = options.messages.filter((message) => !(message.role === "developer" && Array.isArray(message.content) && message.content.some((block) => block.type === "tool-addition" || block.type === "tool-removal")));
|
|
13321
|
+
const tools = options.tools?.map(({ deferLoading: _deferred, ...tool }) => tool);
|
|
13322
|
+
return {
|
|
13323
|
+
...options,
|
|
13324
|
+
messages,
|
|
13325
|
+
...tools === void 0 ? {} : { tools }
|
|
13326
|
+
};
|
|
13327
|
+
}
|
|
13328
|
+
/** How a withdrawn tool is stated to the model, imperatively. */
|
|
13329
|
+
function toolRemovalNotice(names) {
|
|
13330
|
+
const list = names.map((name) => `"${name}"`).join(", ");
|
|
13331
|
+
return names.length === 1 ? `[The tool ${list} is no longer available. Do not call it again: any call will fail.]` : `[The tools ${list} are no longer available. Do not call them again: any call will fail.]`;
|
|
13332
|
+
}
|
|
13333
|
+
/**
|
|
13196
13334
|
* The base instructions as a developer message.
|
|
13197
13335
|
*
|
|
13198
13336
|
* The official client marks the item with the `model.base_instructions` kind, so
|
|
@@ -13579,6 +13717,8 @@ var ResponsesClient = class {
|
|
|
13579
13717
|
const turnKey = turnKeyFor(sessionId);
|
|
13580
13718
|
let currentModel = options.model;
|
|
13581
13719
|
let attemptOptions = options;
|
|
13720
|
+
let strippedToolChanges = false;
|
|
13721
|
+
const statesToolChange = (candidate) => candidate.messages.some((message) => message.role === "developer" && Array.isArray(message.content) && message.content.some((block) => block["type"] === "tool-addition" || block["type"] === "tool-removal"));
|
|
13582
13722
|
let response;
|
|
13583
13723
|
let release;
|
|
13584
13724
|
while (true) {
|
|
@@ -13604,6 +13744,12 @@ var ResponsesClient = class {
|
|
|
13604
13744
|
continue;
|
|
13605
13745
|
}
|
|
13606
13746
|
}
|
|
13747
|
+
if (!strippedToolChanges && statesToolChange(attemptOptions) && error.status === 400) {
|
|
13748
|
+
disableCodexToolUpdate();
|
|
13749
|
+
attemptOptions = withoutCodexToolChanges(attemptOptions);
|
|
13750
|
+
strippedToolChanges = true;
|
|
13751
|
+
continue;
|
|
13752
|
+
}
|
|
13607
13753
|
throw error;
|
|
13608
13754
|
}
|
|
13609
13755
|
}
|
|
@@ -20868,7 +21014,7 @@ function isRecord$61(value) {
|
|
|
20868
21014
|
function asRecord$16(value) {
|
|
20869
21015
|
return isRecord$61(value) ? value : void 0;
|
|
20870
21016
|
}
|
|
20871
|
-
function asString$
|
|
21017
|
+
function asString$28(value) {
|
|
20872
21018
|
if (typeof value === "string" && value.trim() !== "") return value;
|
|
20873
21019
|
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
20874
21020
|
}
|
|
@@ -20881,7 +21027,7 @@ function asNumber$6(value) {
|
|
|
20881
21027
|
}
|
|
20882
21028
|
function firstString$2(record, keys) {
|
|
20883
21029
|
for (const key of keys) {
|
|
20884
|
-
const value = asString$
|
|
21030
|
+
const value = asString$28(record[key]);
|
|
20885
21031
|
if (value !== void 0) return value;
|
|
20886
21032
|
}
|
|
20887
21033
|
}
|
|
@@ -21128,7 +21274,7 @@ function parseCreditBalances(payload, consumed = []) {
|
|
|
21128
21274
|
/** Resolve the plan id the subscription or credits payload reports, when either does. */
|
|
21129
21275
|
function parsePlanId(payloads) {
|
|
21130
21276
|
for (const payload of payloads) {
|
|
21131
|
-
const id = asString$
|
|
21277
|
+
const id = asString$28(deepValue(payload, [
|
|
21132
21278
|
"planId",
|
|
21133
21279
|
"plan_id",
|
|
21134
21280
|
"priceId",
|
|
@@ -21147,7 +21293,7 @@ function parsePlanId(payloads) {
|
|
|
21147
21293
|
*/
|
|
21148
21294
|
function parseSubscriptionStatus(payload) {
|
|
21149
21295
|
const root = asRecord$16(payload) ?? {};
|
|
21150
|
-
return asString$
|
|
21296
|
+
return asString$28(deepValue(asRecord$16(root.data) ?? root, ["status"])) ?? null;
|
|
21151
21297
|
}
|
|
21152
21298
|
/** End of the current billing period, in Unix milliseconds. */
|
|
21153
21299
|
function parseSubscriptionPeriodEnd(payload) {
|
|
@@ -21723,6 +21869,92 @@ function buildModelOptions$2(catalog, enabledModelIds, overrides) {
|
|
|
21723
21869
|
});
|
|
21724
21870
|
}
|
|
21725
21871
|
//#endregion
|
|
21872
|
+
//#region src/host/common/orphan-tool-calls.ts
|
|
21873
|
+
/**
|
|
21874
|
+
* 读一个未知字段为字符串。
|
|
21875
|
+
* @param value - 候选值。
|
|
21876
|
+
* @returns 字符串,或任何其它类型的 undefined。
|
|
21877
|
+
*/
|
|
21878
|
+
function asString$27(value) {
|
|
21879
|
+
return typeof value === "string" ? value : void 0;
|
|
21880
|
+
}
|
|
21881
|
+
/**
|
|
21882
|
+
* 清掉没有配对的工具调用。
|
|
21883
|
+
*
|
|
21884
|
+
* 配对规则只有一条:`tool_use` 必须被**后面第一条** user 轮里的同名 `tool_result` 应答;
|
|
21885
|
+
* 到了下一条 assistant 轮还没被应答,它就是孤儿。反向也一样——`tool_result` 找不到仍在
|
|
21886
|
+
* 等待的同名调用,它就是无主结果(线上报的是「tool call result does not follow tool call」)。
|
|
21887
|
+
*
|
|
21888
|
+
* @param messages - 已折叠过的消息列表。
|
|
21889
|
+
* @param refold - 调用方自己的相邻同角色折叠,清理后需要再折一次。
|
|
21890
|
+
* @returns 配对完整、且没有空消息的消息列表;清理会把整段历史清空时原样返回。
|
|
21891
|
+
*/
|
|
21892
|
+
function cleanOrphanedToolCalls(messages, refold) {
|
|
21893
|
+
const result = [];
|
|
21894
|
+
let pending = [];
|
|
21895
|
+
/**
|
|
21896
|
+
* 丢掉没有被结果应答的调用。
|
|
21897
|
+
* @param answered - 已经被结果应答的 id 集合。
|
|
21898
|
+
*/
|
|
21899
|
+
const dropUnanswered = (answered) => {
|
|
21900
|
+
const byMessage = /* @__PURE__ */ new Map();
|
|
21901
|
+
for (const call of pending) {
|
|
21902
|
+
if (answered.has(call.id)) continue;
|
|
21903
|
+
const indices = byMessage.get(call.messageIndex);
|
|
21904
|
+
if (indices === void 0) byMessage.set(call.messageIndex, [call.blockIndex]);
|
|
21905
|
+
else indices.push(call.blockIndex);
|
|
21906
|
+
}
|
|
21907
|
+
for (const [messageIndex, indices] of byMessage) {
|
|
21908
|
+
const message = result[messageIndex];
|
|
21909
|
+
if (message === void 0) continue;
|
|
21910
|
+
message.content = message.content.filter((_block, index) => !indices.includes(index));
|
|
21911
|
+
}
|
|
21912
|
+
pending = [];
|
|
21913
|
+
};
|
|
21914
|
+
for (const message of messages) {
|
|
21915
|
+
if (message.role === "assistant") {
|
|
21916
|
+
dropUnanswered(/* @__PURE__ */ new Set());
|
|
21917
|
+
const messageIndex = result.length;
|
|
21918
|
+
for (let blockIndex = 0; blockIndex < message.content.length; blockIndex += 1) {
|
|
21919
|
+
const block = message.content[blockIndex];
|
|
21920
|
+
if (block.type !== "tool_use") continue;
|
|
21921
|
+
const id = asString$27(block.id);
|
|
21922
|
+
if (id === void 0) continue;
|
|
21923
|
+
pending.push({
|
|
21924
|
+
messageIndex,
|
|
21925
|
+
blockIndex,
|
|
21926
|
+
id
|
|
21927
|
+
});
|
|
21928
|
+
}
|
|
21929
|
+
result.push({
|
|
21930
|
+
...message,
|
|
21931
|
+
content: [...message.content]
|
|
21932
|
+
});
|
|
21933
|
+
continue;
|
|
21934
|
+
}
|
|
21935
|
+
const answered = /* @__PURE__ */ new Set();
|
|
21936
|
+
const content = [];
|
|
21937
|
+
for (const block of message.content) {
|
|
21938
|
+
if (block.type === "tool_result") {
|
|
21939
|
+
const id = asString$27(block.tool_use_id);
|
|
21940
|
+
if (id === void 0 || !pending.some((call) => call.id === id)) continue;
|
|
21941
|
+
answered.add(id);
|
|
21942
|
+
content.push(block);
|
|
21943
|
+
continue;
|
|
21944
|
+
}
|
|
21945
|
+
content.push(block);
|
|
21946
|
+
}
|
|
21947
|
+
dropUnanswered(answered);
|
|
21948
|
+
result.push({
|
|
21949
|
+
...message,
|
|
21950
|
+
content
|
|
21951
|
+
});
|
|
21952
|
+
}
|
|
21953
|
+
dropUnanswered(/* @__PURE__ */ new Set());
|
|
21954
|
+
const nonEmpty = result.filter((message) => message.content.length > 0);
|
|
21955
|
+
return nonEmpty.length === 0 ? messages : refold(nonEmpty);
|
|
21956
|
+
}
|
|
21957
|
+
//#endregion
|
|
21726
21958
|
//#region src/host/command-code/mapper.ts
|
|
21727
21959
|
/**
|
|
21728
21960
|
* Provider-wire mapping for the two Command Code provider endpoints.
|
|
@@ -22279,7 +22511,7 @@ function anthropicAssistantContent$3(message) {
|
|
|
22279
22511
|
* the Messages wire wants one user turn, so consecutive turns of one role are
|
|
22280
22512
|
* folded together in order.
|
|
22281
22513
|
*/
|
|
22282
|
-
function mergeAnthropicMessages$
|
|
22514
|
+
function mergeAnthropicMessages$4(entries) {
|
|
22283
22515
|
const merged = [];
|
|
22284
22516
|
for (const entry of entries) {
|
|
22285
22517
|
if (entry.content.length === 0) continue;
|
|
@@ -22370,7 +22602,7 @@ function buildAnthropicRequest$1(options, images = NO_RESOLVED_IMAGES$3) {
|
|
|
22370
22602
|
return {
|
|
22371
22603
|
model: options.model,
|
|
22372
22604
|
max_tokens: maxTokens,
|
|
22373
|
-
messages: mergeAnthropicMessages$
|
|
22605
|
+
messages: cleanOrphanedToolCalls(mergeAnthropicMessages$4(entries), mergeAnthropicMessages$4),
|
|
22374
22606
|
...system === void 0 ? {} : { system: anthropicSystemBlocks(system) },
|
|
22375
22607
|
...options.temperature === void 0 || budget !== void 0 ? {} : { temperature: options.temperature },
|
|
22376
22608
|
...options.stop && options.stop.length > 0 ? { stop_sequences: options.stop } : {},
|
|
@@ -22672,6 +22904,23 @@ function applyOpenAIToolDelta$1(entry, state) {
|
|
|
22672
22904
|
const fn = isRecord$60(entry.function) ? entry.function : {};
|
|
22673
22905
|
const out = [];
|
|
22674
22906
|
let call = state.toolCalls.get(wireIndex);
|
|
22907
|
+
const incomingId = asString$26(entry.id);
|
|
22908
|
+
if (call !== void 0 && incomingId !== void 0 && call.id !== `call_${wireIndex}` && incomingId !== call.id) {
|
|
22909
|
+
const closedBlock = {
|
|
22910
|
+
type: "tool-call",
|
|
22911
|
+
id: toToolCallId(call.id),
|
|
22912
|
+
name: call.name,
|
|
22913
|
+
arguments: call.arguments === "" ? "{}" : call.arguments
|
|
22914
|
+
};
|
|
22915
|
+
state.blocks[call.blockIndex] = closedBlock;
|
|
22916
|
+
out.push({
|
|
22917
|
+
type: "block-end",
|
|
22918
|
+
index: call.blockIndex,
|
|
22919
|
+
block: closedBlock
|
|
22920
|
+
});
|
|
22921
|
+
state.toolCalls.delete(wireIndex);
|
|
22922
|
+
call = void 0;
|
|
22923
|
+
}
|
|
22675
22924
|
if (call === void 0) {
|
|
22676
22925
|
out.push(...closeCurrent$6(state));
|
|
22677
22926
|
call = {
|
|
@@ -34457,7 +34706,7 @@ function anthropicAssistantContent$2(message, toolCallIds) {
|
|
|
34457
34706
|
* the Messages wire wants one user turn, so consecutive turns of one role are
|
|
34458
34707
|
* folded together in order.
|
|
34459
34708
|
*/
|
|
34460
|
-
function mergeAnthropicMessages$
|
|
34709
|
+
function mergeAnthropicMessages$3(entries) {
|
|
34461
34710
|
const merged = [];
|
|
34462
34711
|
for (const entry of entries) {
|
|
34463
34712
|
if (entry.content.length === 0) continue;
|
|
@@ -34510,7 +34759,7 @@ function buildAnthropicRequest(options, images = NO_RESOLVED_IMAGES$4, media = {
|
|
|
34510
34759
|
type: CLEAR_THINKING_EDIT,
|
|
34511
34760
|
keep: "all"
|
|
34512
34761
|
}] } : void 0;
|
|
34513
|
-
const messages = mergeAnthropicMessages$
|
|
34762
|
+
const messages = cleanOrphanedToolCalls(mergeAnthropicMessages$3(entries), mergeAnthropicMessages$3);
|
|
34514
34763
|
const lastMessage = messages[messages.length - 1];
|
|
34515
34764
|
if (lastMessage !== void 0 && Array.isArray(lastMessage.content) && lastMessage.content.length > 0) {
|
|
34516
34765
|
const lastBlock = lastMessage.content[lastMessage.content.length - 1];
|
|
@@ -34823,6 +35072,23 @@ function applyOpenAIToolDelta(entry, state) {
|
|
|
34823
35072
|
const fn = isRecord$53(entry.function) ? entry.function : {};
|
|
34824
35073
|
const out = [];
|
|
34825
35074
|
let call = state.toolCalls.get(wireIndex);
|
|
35075
|
+
const incomingId = asString$21(entry.id);
|
|
35076
|
+
if (call !== void 0 && incomingId !== void 0 && call.id !== `call_${wireIndex}` && incomingId !== call.id) {
|
|
35077
|
+
const closedBlock = {
|
|
35078
|
+
type: "tool-call",
|
|
35079
|
+
id: toToolCallId(state.toolCallIds.normalize(call.id)),
|
|
35080
|
+
name: call.name,
|
|
35081
|
+
arguments: call.arguments === "" ? "{}" : call.arguments
|
|
35082
|
+
};
|
|
35083
|
+
state.blocks[call.blockIndex] = closedBlock;
|
|
35084
|
+
out.push({
|
|
35085
|
+
type: "block-end",
|
|
35086
|
+
index: call.blockIndex,
|
|
35087
|
+
block: closedBlock
|
|
35088
|
+
});
|
|
35089
|
+
state.toolCalls.delete(wireIndex);
|
|
35090
|
+
call = void 0;
|
|
35091
|
+
}
|
|
34826
35092
|
if (call === void 0) {
|
|
34827
35093
|
out.push(...closeCurrent$5(state));
|
|
34828
35094
|
call = {
|
|
@@ -36809,7 +37075,7 @@ const KIMI_CODE_REQUEST_IMAGE_MAX_EDGE = 2e3;
|
|
|
36809
37075
|
* @param catalog - live catalog, possibly empty when offline.
|
|
36810
37076
|
* @returns the tool-update mode, or undefined when this route must resend everything.
|
|
36811
37077
|
*/
|
|
36812
|
-
function toolUpdateMode$
|
|
37078
|
+
function toolUpdateMode$2(modelId, catalog) {
|
|
36813
37079
|
if (!dynamicToolsForEntry(modelId, catalog)) return void 0;
|
|
36814
37080
|
if (wireForCatalogEntry(modelId, catalog) !== "openai") return void 0;
|
|
36815
37081
|
const raw = (process.env.DSH_KIMI_CODE_TOOL_UPDATE ?? "").trim().toLowerCase();
|
|
@@ -37212,7 +37478,7 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
37212
37478
|
id: modelId,
|
|
37213
37479
|
name: entry?.name ?? modelId,
|
|
37214
37480
|
inputModalities: inputModalitiesForEntry(modelId, catalog),
|
|
37215
|
-
...toolUpdateMode$
|
|
37481
|
+
...toolUpdateMode$2(modelId, catalog) === void 0 ? {} : { toolUpdate: toolUpdateMode$2(modelId, catalog) },
|
|
37216
37482
|
context: { contextWindow: this.contextWindowFor(modelId, entry, settings.contextWindowOverrides) },
|
|
37217
37483
|
...efforts.length === 0 ? {} : { reasoning: {
|
|
37218
37484
|
efforts: efforts.map((effort) => ({
|
|
@@ -40865,7 +41131,7 @@ function anthropicAssistantContent$1(message, expectedScope) {
|
|
|
40865
41131
|
* Messages wire wants one user turn, so consecutive turns of one role are folded
|
|
40866
41132
|
* together in order.
|
|
40867
41133
|
*/
|
|
40868
|
-
function mergeAnthropicMessages$
|
|
41134
|
+
function mergeAnthropicMessages$2(entries) {
|
|
40869
41135
|
const merged = [];
|
|
40870
41136
|
for (const entry of entries) {
|
|
40871
41137
|
if (entry.content.length === 0) continue;
|
|
@@ -41087,7 +41353,7 @@ function buildMinimaxRequest(options, images = NO_RESOLVED_IMAGES$2, request = {
|
|
|
41087
41353
|
model: options.model,
|
|
41088
41354
|
max_tokens: maxTokens,
|
|
41089
41355
|
stream: true,
|
|
41090
|
-
messages: mergeAnthropicMessages$
|
|
41356
|
+
messages: cleanOrphanedToolCalls(mergeAnthropicMessages$2(entries), mergeAnthropicMessages$2),
|
|
41091
41357
|
...system === void 0 ? {} : { system: caching ? [{
|
|
41092
41358
|
type: "text",
|
|
41093
41359
|
text: system
|
|
@@ -49630,6 +49896,16 @@ function isClaudeCacheTtl$1(value) {
|
|
|
49630
49896
|
* models (`THINKING_BINDING_CONTROLS_BETA`, pushed when `supportsMidConvoEffort`).
|
|
49631
49897
|
*/
|
|
49632
49898
|
const THINKING_BINDING_CONTROLS_BETA = "thinking-binding-controls-2026-08-01";
|
|
49899
|
+
/**
|
|
49900
|
+
* Licenses a mid-conversation `tool_addition` / `tool_removal` block.
|
|
49901
|
+
*
|
|
49902
|
+
* A tool change stated inside a `role: "system"` message is a beta shape: without
|
|
49903
|
+
* this marker the blocks are an unknown content type and the request is refused.
|
|
49904
|
+
* The name carries its own date because the vendor versions the shape, so a
|
|
49905
|
+
* future revision arrives as a new constant rather than as a silent behaviour
|
|
49906
|
+
* change under the old one.
|
|
49907
|
+
*/
|
|
49908
|
+
const INLINE_TOOLS_BETA = "inline-tools-2026-09-15";
|
|
49633
49909
|
/** Anthropic protocol revision sent as `anthropic-version`. */
|
|
49634
49910
|
const ANTHROPIC_VERSION$1 = "2023-06-01";
|
|
49635
49911
|
/**
|
|
@@ -51256,6 +51532,7 @@ function claudeBetas(options = {}) {
|
|
|
51256
51532
|
if (options.thinking === true) betas.push(INTERLEAVED_THINKING_BETA);
|
|
51257
51533
|
if (options.thinkingBinding === true) betas.push(THINKING_BINDING_CONTROLS_BETA);
|
|
51258
51534
|
if (options.cacheTtl === "1h") betas.push(EXTENDED_CACHE_TTL_BETA);
|
|
51535
|
+
if (options.toolChanges === true) betas.push(INLINE_TOOLS_BETA);
|
|
51259
51536
|
return betas;
|
|
51260
51537
|
}
|
|
51261
51538
|
/** The `User-Agent` value this line reports for one surface. */
|
|
@@ -53356,10 +53633,85 @@ function wireTool(tool, names) {
|
|
|
53356
53633
|
return {
|
|
53357
53634
|
name: claudeWireToolName(tool.name, names),
|
|
53358
53635
|
description: tool.description ?? "",
|
|
53359
|
-
input_schema: schema
|
|
53636
|
+
input_schema: schema,
|
|
53637
|
+
...tool.deferLoading === true ? { defer_loading: true } : {}
|
|
53360
53638
|
};
|
|
53361
53639
|
}
|
|
53362
53640
|
/**
|
|
53641
|
+
* The stand-in declaration a request needs when every real tool is deferred.
|
|
53642
|
+
*
|
|
53643
|
+
* The vendor's rule is that at least one tool must stay active: a request whose
|
|
53644
|
+
* declarations are all deferred has no active declaration, and a tool change
|
|
53645
|
+
* stated in that state would move the start of the rendered prompt. Transcribed
|
|
53646
|
+
* from the harness's own anthropic-messages adapter, which inserts the same
|
|
53647
|
+
* placeholder for the same reason.
|
|
53648
|
+
*/
|
|
53649
|
+
const CLAUDE_TOOL_UPDATE_PLACEHOLDER = {
|
|
53650
|
+
name: "tool_update_placeholder",
|
|
53651
|
+
description: "Reserved. Keeps one tool declaration active so a mid-conversation tool change stays in the history. Never call it.",
|
|
53652
|
+
parameters: {
|
|
53653
|
+
type: "object",
|
|
53654
|
+
properties: {}
|
|
53655
|
+
}
|
|
53656
|
+
};
|
|
53657
|
+
/** Whether one message states a tool change this wire can carry. */
|
|
53658
|
+
function claudeMessageStatesToolChange(message) {
|
|
53659
|
+
return Array.isArray(message.content) && message.content.some((block) => isRecord$41(block) && (block.type === "tool-addition" || block.type === "tool-removal"));
|
|
53660
|
+
}
|
|
53661
|
+
/**
|
|
53662
|
+
* The fallback statement of one tool change, for a history position the vendor
|
|
53663
|
+
* will not accept a mid-conversation system message in.
|
|
53664
|
+
*
|
|
53665
|
+
* The declarations are untouched in both shapes: this only tells the model what
|
|
53666
|
+
* changed, and it is deliberately imperative for a removal because the
|
|
53667
|
+
* declaration is still there and could otherwise still be called.
|
|
53668
|
+
*/
|
|
53669
|
+
function claudeToolChangeNote(message) {
|
|
53670
|
+
const added = [];
|
|
53671
|
+
const removed = [];
|
|
53672
|
+
for (const block of message.content) {
|
|
53673
|
+
if (!isRecord$41(block)) continue;
|
|
53674
|
+
const name = typeof block.toolName === "string" ? block.toolName.trim() : "";
|
|
53675
|
+
if (name === "") continue;
|
|
53676
|
+
if (block.type === "tool-addition") added.push(name);
|
|
53677
|
+
else if (block.type === "tool-removal") removed.push(name);
|
|
53678
|
+
}
|
|
53679
|
+
const notes = [];
|
|
53680
|
+
if (added.length > 0) notes.push(`[The tool(s) ${added.map((name) => `"${name}"`).join(", ")} are now available.]`);
|
|
53681
|
+
if (removed.length > 0) notes.push(`[The tool(s) ${removed.map((name) => `"${name}"`).join(", ")} are no longer available. Do not call them again: any call will fail.]`);
|
|
53682
|
+
return notes.join("\n");
|
|
53683
|
+
}
|
|
53684
|
+
/** Whether any message states a tool change that this wire can carry. */
|
|
53685
|
+
function claudeHasToolChanges(options) {
|
|
53686
|
+
return options.messages.some((message) => message.role === "developer" && Array.isArray(message.content) && message.content.some((block) => isRecord$41(block) && (block.type === "tool-addition" || block.type === "tool-removal")));
|
|
53687
|
+
}
|
|
53688
|
+
/**
|
|
53689
|
+
* Whether a BUILT payload carries a `tool_addition` / `tool_removal` block.
|
|
53690
|
+
*
|
|
53691
|
+
* Read off the body rather than from the request, so the beta header and the
|
|
53692
|
+
* blocks it licenses cannot disagree about one request.
|
|
53693
|
+
*/
|
|
53694
|
+
function claudeBodyHasToolChanges(payload) {
|
|
53695
|
+
const messages = payload["messages"];
|
|
53696
|
+
if (!Array.isArray(messages)) return false;
|
|
53697
|
+
return messages.some((message) => {
|
|
53698
|
+
const content = message["content"];
|
|
53699
|
+
return Array.isArray(content) && content.some((block) => block["type"] === "tool_addition" || block["type"] === "tool_removal");
|
|
53700
|
+
});
|
|
53701
|
+
}
|
|
53702
|
+
/**
|
|
53703
|
+
* The wire tool list for one request.
|
|
53704
|
+
*
|
|
53705
|
+
* Deferred declarations travel with `defer_loading` so they stay out of the
|
|
53706
|
+
* prefix. When EVERY declaration is deferred and the history states a change,
|
|
53707
|
+
* one placeholder is prepended: the vendor refuses a tool change on a request
|
|
53708
|
+
* that has no active declaration at all.
|
|
53709
|
+
*/
|
|
53710
|
+
function claudeWireTools(options, names) {
|
|
53711
|
+
const tools = options.tools ?? [];
|
|
53712
|
+
return (tools.length > 0 && tools.every((tool) => tool.deferLoading === true) && claudeHasToolChanges(options) ? [CLAUDE_TOOL_UPDATE_PLACEHOLDER, ...tools] : tools).map((tool) => wireTool(tool, names));
|
|
53713
|
+
}
|
|
53714
|
+
/**
|
|
53363
53715
|
* One system-role turn's blocks.
|
|
53364
53716
|
*
|
|
53365
53717
|
* The vendor documents a mid-conversation system message as carrying "a plain
|
|
@@ -53385,6 +53737,17 @@ function claudeSystemContent(message, images) {
|
|
|
53385
53737
|
continue;
|
|
53386
53738
|
}
|
|
53387
53739
|
if (block.type === "image") blocks.push(imageBlockFor(block, images));
|
|
53740
|
+
if (block.type === "tool-addition" || block.type === "tool-removal") {
|
|
53741
|
+
const name = typeof block.toolName === "string" ? block.toolName.trim() : "";
|
|
53742
|
+
if (name === "") continue;
|
|
53743
|
+
blocks.push({
|
|
53744
|
+
type: block.type === "tool-addition" ? "tool_addition" : "tool_removal",
|
|
53745
|
+
tool: {
|
|
53746
|
+
type: "tool_reference",
|
|
53747
|
+
name: claudeWireToolName(name)
|
|
53748
|
+
}
|
|
53749
|
+
});
|
|
53750
|
+
}
|
|
53388
53751
|
}
|
|
53389
53752
|
return blocks;
|
|
53390
53753
|
}
|
|
@@ -53588,7 +53951,9 @@ function buildClaudeRequestBody(options, images = NO_RESOLVED_IMAGES$1, request
|
|
|
53588
53951
|
const maxTokens = claudeRequestThinks(options.model, effort, catalog) ? adjustMaxTokensForThinking(baseMax, modelMax, level, request.thinkingBudgets).maxTokens : baseMax;
|
|
53589
53952
|
const { thinking, outputConfig } = claudeThinking(options.model, effort, level, maxTokens, request.thinkingBudgets, catalog);
|
|
53590
53953
|
const entries = [];
|
|
53591
|
-
|
|
53954
|
+
const wire = messagesForTheWire(options);
|
|
53955
|
+
for (let index = 0; index < wire.length; index += 1) {
|
|
53956
|
+
const message = wire[index];
|
|
53592
53957
|
if (message.role === "system") {
|
|
53593
53958
|
entries.push({
|
|
53594
53959
|
role: "system",
|
|
@@ -53596,6 +53961,26 @@ function buildClaudeRequestBody(options, images = NO_RESOLVED_IMAGES$1, request
|
|
|
53596
53961
|
});
|
|
53597
53962
|
continue;
|
|
53598
53963
|
}
|
|
53964
|
+
if (message.role === "developer" && claudeMessageStatesToolChange(message)) {
|
|
53965
|
+
const previous = wire[index - 1];
|
|
53966
|
+
const next = wire[index + 1];
|
|
53967
|
+
if (previous !== void 0 && wireRoleOf(previous) === "user" && (next === void 0 || wireRoleOf(next) === "assistant")) {
|
|
53968
|
+
entries.push({
|
|
53969
|
+
role: "system",
|
|
53970
|
+
content: claudeSystemContent(message, images)
|
|
53971
|
+
});
|
|
53972
|
+
continue;
|
|
53973
|
+
}
|
|
53974
|
+
const note = claudeToolChangeNote(message);
|
|
53975
|
+
if (note !== "") entries.push({
|
|
53976
|
+
role: "user",
|
|
53977
|
+
content: [{
|
|
53978
|
+
type: "text",
|
|
53979
|
+
text: note
|
|
53980
|
+
}]
|
|
53981
|
+
});
|
|
53982
|
+
continue;
|
|
53983
|
+
}
|
|
53599
53984
|
if (isToolResultMessage$5(message)) {
|
|
53600
53985
|
entries.push({
|
|
53601
53986
|
role: "user",
|
|
@@ -53617,8 +54002,8 @@ function buildClaudeRequestBody(options, images = NO_RESOLVED_IMAGES$1, request
|
|
|
53617
54002
|
max_tokens: maxTokens,
|
|
53618
54003
|
stream: true,
|
|
53619
54004
|
system: buildClaudeSystemBlocks(options, caching, cacheTtl),
|
|
53620
|
-
messages: mergeClaudeMessages(entries),
|
|
53621
|
-
...options.tools !== void 0 && options.tools.length > 0 ? { tools: options
|
|
54005
|
+
messages: cleanOrphanedToolCalls(mergeClaudeMessages(entries), mergeClaudeMessages),
|
|
54006
|
+
...options.tools !== void 0 && options.tools.length > 0 ? { tools: claudeWireTools(options, names) } : {},
|
|
53622
54007
|
...thinking === void 0 ? {} : { thinking },
|
|
53623
54008
|
...outputConfig === void 0 ? {} : { output_config: outputConfig },
|
|
53624
54009
|
...temperatureAllowed && options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
@@ -55444,6 +55829,33 @@ var ClaudeAccountTokenStore = class {
|
|
|
55444
55829
|
await this.store.saveAccount(credentials, { internalId: this.internalId });
|
|
55445
55830
|
}
|
|
55446
55831
|
};
|
|
55832
|
+
/**
|
|
55833
|
+
* Whether this model may state a tool change in the history.
|
|
55834
|
+
*
|
|
55835
|
+
* Gated on the same capability that licenses a mid-conversation system message,
|
|
55836
|
+
* because that message is what carries the change: a model that folds those
|
|
55837
|
+
* messages back into the top-level `system` field cannot take a tool change
|
|
55838
|
+
* without moving the head, which is the cost the capability exists to avoid.
|
|
55839
|
+
*
|
|
55840
|
+
* `DSH_CLAUDE_TOOL_UPDATE=0` turns it off for one account without a code change,
|
|
55841
|
+
* mirroring the escape hatch kimi-code and the codex line carry.
|
|
55842
|
+
*
|
|
55843
|
+
* @param modelId - exact model id.
|
|
55844
|
+
* @returns the mode to declare, or undefined when every request must restate the
|
|
55845
|
+
* complete tool list.
|
|
55846
|
+
*/
|
|
55847
|
+
function toolUpdateMode$1(modelId) {
|
|
55848
|
+
if (!claudeSupportsMidConversationSystemMessages(modelId)) return void 0;
|
|
55849
|
+
const raw = (process.env.DSH_CLAUDE_TOOL_UPDATE ?? "").trim().toLowerCase();
|
|
55850
|
+
if (raw !== "" && [
|
|
55851
|
+
"0",
|
|
55852
|
+
"false",
|
|
55853
|
+
"no",
|
|
55854
|
+
"off",
|
|
55855
|
+
"none"
|
|
55856
|
+
].includes(raw)) return void 0;
|
|
55857
|
+
return "in-history";
|
|
55858
|
+
}
|
|
55447
55859
|
var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
|
|
55448
55860
|
store;
|
|
55449
55861
|
modelSettings;
|
|
@@ -55559,6 +55971,7 @@ var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
|
|
|
55559
55971
|
inputModalities: entry.supportsImage ? ["text", "image"] : ["text"],
|
|
55560
55972
|
context: { contextWindow: contextWindow || 2e5 },
|
|
55561
55973
|
...outputReservation(contextWindow || 2e5, maxOutputTokensFor(modelId, catalog)),
|
|
55974
|
+
...toolUpdateMode$1(modelId) === void 0 ? {} : { toolUpdate: toolUpdateMode$1(modelId) },
|
|
55562
55975
|
...efforts.length === 0 ? {} : { reasoning: {
|
|
55563
55976
|
efforts: efforts.map((effort) => ({
|
|
55564
55977
|
id: ReasoningEffortId(effort),
|
|
@@ -55657,6 +56070,7 @@ var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
|
|
|
55657
56070
|
model: requestOptions.model,
|
|
55658
56071
|
thinking,
|
|
55659
56072
|
thinkingBinding: claudeBodyBindsThinking(payload),
|
|
56073
|
+
toolChanges: claudeBodyHasToolChanges(payload),
|
|
55660
56074
|
cacheTtl,
|
|
55661
56075
|
method: "POST"
|
|
55662
56076
|
}),
|
|
@@ -59161,7 +59575,7 @@ function safeStringify(value) {
|
|
|
59161
59575
|
* DSH 历史里可能连续两条 user(注入的上下文提示 + 真正的用户轮),而工具结果本身就是
|
|
59162
59576
|
* user 角色消息;Messages 线要的是一个 user 轮,所以同角色的连续轮按顺序折叠。
|
|
59163
59577
|
*/
|
|
59164
|
-
function mergeAnthropicMessages(entries) {
|
|
59578
|
+
function mergeAnthropicMessages$1(entries) {
|
|
59165
59579
|
const merged = [];
|
|
59166
59580
|
for (const entry of entries) {
|
|
59167
59581
|
if (entry.content.length === 0) continue;
|
|
@@ -59310,7 +59724,7 @@ function buildGlmAnthropicRequest(options, request = {}) {
|
|
|
59310
59724
|
}
|
|
59311
59725
|
const system = glmAnthropicSystemBlocks(options);
|
|
59312
59726
|
const maxTokens = options.maxTokens ?? request.defaultMaxTokens ?? 32768;
|
|
59313
|
-
const merged = mergeAnthropicMessages(entries);
|
|
59727
|
+
const merged = cleanOrphanedToolCalls(mergeAnthropicMessages$1(entries), mergeAnthropicMessages$1);
|
|
59314
59728
|
const lastMessageIndex = merged.length - 1;
|
|
59315
59729
|
const messages = lastMessageIndex < 0 ? merged : merged.map((message, index) => index === lastMessageIndex ? {
|
|
59316
59730
|
...message,
|
|
@@ -60637,6 +61051,23 @@ function applyToolDelta$3(entry, state) {
|
|
|
60637
61051
|
const fn = isRecord$37(entry.function) ? entry.function : {};
|
|
60638
61052
|
const out = [];
|
|
60639
61053
|
let call = state.toolCalls.get(wireIndex);
|
|
61054
|
+
const incomingId = asString$14(entry.id);
|
|
61055
|
+
if (call !== void 0 && incomingId !== void 0 && call.id !== `call_${wireIndex}` && incomingId !== call.id) {
|
|
61056
|
+
const closedBlock = {
|
|
61057
|
+
type: "tool-call",
|
|
61058
|
+
id: toToolCallId(call.id),
|
|
61059
|
+
name: call.name,
|
|
61060
|
+
arguments: call.arguments === "" ? "{}" : call.arguments
|
|
61061
|
+
};
|
|
61062
|
+
state.blocks[call.blockIndex] = closedBlock;
|
|
61063
|
+
out.push({
|
|
61064
|
+
type: "block-end",
|
|
61065
|
+
index: call.blockIndex,
|
|
61066
|
+
block: closedBlock
|
|
61067
|
+
});
|
|
61068
|
+
state.toolCalls.delete(wireIndex);
|
|
61069
|
+
call = void 0;
|
|
61070
|
+
}
|
|
60640
61071
|
if (call === void 0) {
|
|
60641
61072
|
out.push(...closeCurrent$3(state));
|
|
60642
61073
|
call = {
|
|
@@ -65470,6 +65901,23 @@ function applyToolDelta$2(entry, state) {
|
|
|
65470
65901
|
const fn = isRecord$33(entry.function) ? entry.function : void 0;
|
|
65471
65902
|
const out = [];
|
|
65472
65903
|
let call = state.toolCalls.get(wireIndex);
|
|
65904
|
+
const incomingId = asString$10(entry.id);
|
|
65905
|
+
if (call !== void 0 && incomingId !== void 0 && call.id !== `call_${wireIndex}` && incomingId !== call.id) {
|
|
65906
|
+
const closedBlock = {
|
|
65907
|
+
type: "tool-call",
|
|
65908
|
+
id: toToolCallId(call.id),
|
|
65909
|
+
name: call.name,
|
|
65910
|
+
arguments: call.arguments === "" ? "{}" : call.arguments
|
|
65911
|
+
};
|
|
65912
|
+
state.blocks[call.blockIndex] = closedBlock;
|
|
65913
|
+
out.push({
|
|
65914
|
+
type: "block-end",
|
|
65915
|
+
index: call.blockIndex,
|
|
65916
|
+
block: closedBlock
|
|
65917
|
+
});
|
|
65918
|
+
state.toolCalls.delete(wireIndex);
|
|
65919
|
+
call = void 0;
|
|
65920
|
+
}
|
|
65473
65921
|
if (call === void 0) {
|
|
65474
65922
|
const opened = openToolCall$1(state, entry, wireIndex);
|
|
65475
65923
|
out.push(...opened.chunks);
|
|
@@ -71734,6 +72182,7 @@ async function* translate(payloads) {
|
|
|
71734
72182
|
if (!isRecord$26(call)) continue;
|
|
71735
72183
|
const index = Number(call.index ?? 0);
|
|
71736
72184
|
let block = toolBlocks.get(index);
|
|
72185
|
+
if (block !== void 0 && typeof call.id === "string" && call.id.length > 0 && block.callId !== void 0 && block.callId.length > 0 && block.callId !== call.id) block = void 0;
|
|
71737
72186
|
if (block === void 0) {
|
|
71738
72187
|
block = open("tool-call");
|
|
71739
72188
|
toolBlocks.set(index, block);
|
|
@@ -71745,7 +72194,7 @@ async function* translate(payloads) {
|
|
|
71745
72194
|
}
|
|
71746
72195
|
const fn = isRecord$26(call.function) ? call.function : {};
|
|
71747
72196
|
block.callId = acceptIdentity$1(block.callId, call.id);
|
|
71748
|
-
block.name = acceptIdentity$1(block.name, fn.name);
|
|
72197
|
+
if (block.name === void 0 || block.name === "") block.name = acceptIdentity$1(block.name, fn.name);
|
|
71749
72198
|
const fragment = typeof fn.arguments === "string" ? fn.arguments : "";
|
|
71750
72199
|
block.text += fragment;
|
|
71751
72200
|
yield {
|
|
@@ -78472,6 +78921,23 @@ function applyToolDelta$1(entry, state) {
|
|
|
78472
78921
|
const fn = isRecord$21(entry.function) ? entry.function : void 0;
|
|
78473
78922
|
const out = [];
|
|
78474
78923
|
let call = state.toolCalls.get(wireIndex);
|
|
78924
|
+
const incomingId = asString$7(entry.id);
|
|
78925
|
+
if (call !== void 0 && incomingId !== void 0 && call.id !== "call_" + wireIndex && incomingId !== call.id) {
|
|
78926
|
+
const closedBlock = {
|
|
78927
|
+
type: "tool-call",
|
|
78928
|
+
id: toToolCallId(call.id),
|
|
78929
|
+
name: call.name,
|
|
78930
|
+
arguments: call.arguments === "" ? "{}" : call.arguments
|
|
78931
|
+
};
|
|
78932
|
+
state.blocks[call.blockIndex] = closedBlock;
|
|
78933
|
+
out.push({
|
|
78934
|
+
type: "block-end",
|
|
78935
|
+
index: call.blockIndex,
|
|
78936
|
+
block: closedBlock
|
|
78937
|
+
});
|
|
78938
|
+
state.toolCalls.delete(wireIndex);
|
|
78939
|
+
call = void 0;
|
|
78940
|
+
}
|
|
78475
78941
|
if (call === void 0) {
|
|
78476
78942
|
const opened = openToolCall(state, entry, wireIndex);
|
|
78477
78943
|
out.push(...opened.chunks);
|
|
@@ -80982,8 +81448,13 @@ const POOL_COOLDOWN_MS$1 = 15 * 6e4;
|
|
|
80982
81448
|
* The subscription's models at release time, keyed by wire id.
|
|
80983
81449
|
*
|
|
80984
81450
|
* Id spellings and prices are transcribed from MODEL_PRICES_URL (fetched
|
|
80985
|
-
* 2026-
|
|
80986
|
-
* per call and are not in it).
|
|
81451
|
+
* 2026-11-07, 41 entries, all chat models — the plan's image models are priced
|
|
81452
|
+
* per call and are not in it). A variant the list prices but no other source
|
|
81453
|
+
* describes separately (`deepseek-v4.1-flash-eco`, `gpt-6.1-terra`, `hy4`,
|
|
81454
|
+
* `kimi-k3.1-pro`, added 2026-11-07) transcribes only its price from that list;
|
|
81455
|
+
* its window, output cap, modalities and ladder are inherited from the sibling
|
|
81456
|
+
* row of the same family, which is the rule `deepseek-v4-flash-vision-exp`
|
|
81457
|
+
* already follows. Display names use the pricing page's spelling
|
|
80987
81458
|
* where that page lists the model (https://open-design.ai/pricing/) and are
|
|
80988
81459
|
* derived from the id otherwise; the live catalog's own name wins once one is
|
|
80989
81460
|
* read. Windows, output caps, modalities and ladders come from the sibling
|
|
@@ -81137,6 +81608,23 @@ const MODEL_CATALOG$1 = Object.freeze({
|
|
|
81137
81608
|
],
|
|
81138
81609
|
defaultEffort: "high"
|
|
81139
81610
|
},
|
|
81611
|
+
"deepseek-v4.1-flash-eco": {
|
|
81612
|
+
name: "DeepSeek V4.1 Flash Eco",
|
|
81613
|
+
pricing: {
|
|
81614
|
+
input: .3,
|
|
81615
|
+
output: 1.2
|
|
81616
|
+
},
|
|
81617
|
+
contextWindow: 1e6,
|
|
81618
|
+
maxTokens: 384e3,
|
|
81619
|
+
input: ["text", "image"],
|
|
81620
|
+
efforts: [
|
|
81621
|
+
"none",
|
|
81622
|
+
"low",
|
|
81623
|
+
"high",
|
|
81624
|
+
"max"
|
|
81625
|
+
],
|
|
81626
|
+
defaultEffort: "high"
|
|
81627
|
+
},
|
|
81140
81628
|
"deepseek-v4-flash": {
|
|
81141
81629
|
name: "DeepSeek V4 Flash",
|
|
81142
81630
|
pricing: {
|
|
@@ -81339,6 +81827,23 @@ const MODEL_CATALOG$1 = Object.freeze({
|
|
|
81339
81827
|
"max"
|
|
81340
81828
|
]
|
|
81341
81829
|
},
|
|
81830
|
+
"gpt-6.1-terra": {
|
|
81831
|
+
name: "GPT-6.1 Terra",
|
|
81832
|
+
pricing: {
|
|
81833
|
+
input: 1,
|
|
81834
|
+
output: 5
|
|
81835
|
+
},
|
|
81836
|
+
contextWindow: 105e4,
|
|
81837
|
+
maxTokens: 128e3,
|
|
81838
|
+
input: ["text", "image"],
|
|
81839
|
+
efforts: [
|
|
81840
|
+
"low",
|
|
81841
|
+
"medium",
|
|
81842
|
+
"high",
|
|
81843
|
+
"xhigh",
|
|
81844
|
+
"max"
|
|
81845
|
+
]
|
|
81846
|
+
},
|
|
81342
81847
|
"gpt-6-astra": {
|
|
81343
81848
|
name: "GPT-6 Astra",
|
|
81344
81849
|
pricing: {
|
|
@@ -81434,6 +81939,20 @@ const MODEL_CATALOG$1 = Object.freeze({
|
|
|
81434
81939
|
"xhigh"
|
|
81435
81940
|
]
|
|
81436
81941
|
},
|
|
81942
|
+
"hy4": {
|
|
81943
|
+
name: "Hunyuan H4",
|
|
81944
|
+
pricing: {
|
|
81945
|
+
input: .417,
|
|
81946
|
+
output: 1.2505
|
|
81947
|
+
},
|
|
81948
|
+
contextWindow: 1048576,
|
|
81949
|
+
input: ["text"],
|
|
81950
|
+
efforts: [
|
|
81951
|
+
"low",
|
|
81952
|
+
"medium",
|
|
81953
|
+
"high"
|
|
81954
|
+
]
|
|
81955
|
+
},
|
|
81437
81956
|
"hy4-preview": {
|
|
81438
81957
|
name: "Hunyuan H4 Preview",
|
|
81439
81958
|
pricing: {
|
|
@@ -81479,6 +81998,21 @@ const MODEL_CATALOG$1 = Object.freeze({
|
|
|
81479
81998
|
"max"
|
|
81480
81999
|
]
|
|
81481
82000
|
},
|
|
82001
|
+
"kimi-k3.1-pro": {
|
|
82002
|
+
name: "Kimi K3.1 Pro",
|
|
82003
|
+
pricing: {
|
|
82004
|
+
input: 2,
|
|
82005
|
+
output: 10
|
|
82006
|
+
},
|
|
82007
|
+
contextWindow: 1048576,
|
|
82008
|
+
maxTokens: 131072,
|
|
82009
|
+
input: ["text", "image"],
|
|
82010
|
+
efforts: [
|
|
82011
|
+
"low",
|
|
82012
|
+
"high",
|
|
82013
|
+
"max"
|
|
82014
|
+
]
|
|
82015
|
+
},
|
|
81482
82016
|
"mimo-v2.6-flash": {
|
|
81483
82017
|
name: "MiMo V2.6 Flash",
|
|
81484
82018
|
pricing: {
|
|
@@ -83690,6 +84224,7 @@ async function* translate$1(payloads) {
|
|
|
83690
84224
|
if (!isRecord$17(call)) continue;
|
|
83691
84225
|
const index = Number(call.index ?? 0);
|
|
83692
84226
|
let block = toolBlocks.get(index);
|
|
84227
|
+
if (block !== void 0 && typeof call.id === "string" && call.id.length > 0 && block.callId !== void 0 && block.callId.length > 0 && block.callId !== call.id) block = void 0;
|
|
83693
84228
|
if (block === void 0) {
|
|
83694
84229
|
block = open("tool-call");
|
|
83695
84230
|
toolBlocks.set(index, block);
|
|
@@ -83701,7 +84236,7 @@ async function* translate$1(payloads) {
|
|
|
83701
84236
|
}
|
|
83702
84237
|
const fn = isRecord$17(call.function) ? call.function : {};
|
|
83703
84238
|
block.callId = acceptIdentity(block.callId, call.id);
|
|
83704
|
-
block.name = acceptIdentity(block.name, fn.name);
|
|
84239
|
+
if (block.name === void 0 || block.name === "") block.name = acceptIdentity(block.name, fn.name);
|
|
83705
84240
|
const fragment = typeof fn.arguments === "string" ? fn.arguments : "";
|
|
83706
84241
|
block.text += fragment;
|
|
83707
84242
|
yield {
|
|
@@ -87228,9 +87763,9 @@ function installToolResultPrunerGuard(ctx, options = {}) {
|
|
|
87228
87763
|
const wrapPruner = (pruner) => {
|
|
87229
87764
|
if (disposed || !isRecord$14(pruner)) return false;
|
|
87230
87765
|
if (alreadyWrapped.has(pruner)) return false;
|
|
87231
|
-
const target = resolveMethodTarget$
|
|
87766
|
+
const target = resolveMethodTarget$4(pruner, "pruneSession");
|
|
87232
87767
|
if (target === void 0) return false;
|
|
87233
|
-
if (alreadyPatched$
|
|
87768
|
+
if (alreadyPatched$4(patchedMethods, target.holder, target.name)) {
|
|
87234
87769
|
alreadyWrapped.add(pruner);
|
|
87235
87770
|
return false;
|
|
87236
87771
|
}
|
|
@@ -87242,11 +87777,11 @@ function installToolResultPrunerGuard(ctx, options = {}) {
|
|
|
87242
87777
|
};
|
|
87243
87778
|
return original.call(this ?? pruner, session);
|
|
87244
87779
|
};
|
|
87245
|
-
if (!installMethod$
|
|
87246
|
-
markPatched$
|
|
87780
|
+
if (!installMethod$4(target, replacement)) return false;
|
|
87781
|
+
markPatched$4(patchedMethods, target.holder, target.name);
|
|
87247
87782
|
alreadyWrapped.add(pruner);
|
|
87248
87783
|
restores.push(() => {
|
|
87249
|
-
restoreMethod$
|
|
87784
|
+
restoreMethod$4(target);
|
|
87250
87785
|
});
|
|
87251
87786
|
return true;
|
|
87252
87787
|
};
|
|
@@ -87466,7 +88001,7 @@ function isRecord$14(value) {
|
|
|
87466
88001
|
* @param name - 方法名。
|
|
87467
88002
|
* @returns 目标;方法不存在时为 `undefined`。
|
|
87468
88003
|
*/
|
|
87469
|
-
function resolveMethodTarget$
|
|
88004
|
+
function resolveMethodTarget$4(service, name) {
|
|
87470
88005
|
if (typeof service !== "object" || service === null) return void 0;
|
|
87471
88006
|
const own = service;
|
|
87472
88007
|
if (Object.prototype.hasOwnProperty.call(own, name)) {
|
|
@@ -87498,7 +88033,7 @@ function resolveMethodTarget$3(service, name) {
|
|
|
87498
88033
|
* @param replacement - 包装实现。
|
|
87499
88034
|
* @returns 是否装上了。
|
|
87500
88035
|
*/
|
|
87501
|
-
function installMethod$
|
|
88036
|
+
function installMethod$4(target, replacement) {
|
|
87502
88037
|
try {
|
|
87503
88038
|
Object.defineProperty(target.holder, target.name, {
|
|
87504
88039
|
value: replacement,
|
|
@@ -87516,7 +88051,7 @@ function installMethod$3(target, replacement) {
|
|
|
87516
88051
|
*
|
|
87517
88052
|
* @param target - 目标。
|
|
87518
88053
|
*/
|
|
87519
|
-
function restoreMethod$
|
|
88054
|
+
function restoreMethod$4(target) {
|
|
87520
88055
|
try {
|
|
87521
88056
|
if (target.descriptor === void 0) Reflect.deleteProperty(target.holder, target.name);
|
|
87522
88057
|
else Object.defineProperty(target.holder, target.name, target.descriptor);
|
|
@@ -87530,7 +88065,7 @@ function restoreMethod$3(target) {
|
|
|
87530
88065
|
* @param name - 方法名。
|
|
87531
88066
|
* @returns 是否已经包过。
|
|
87532
88067
|
*/
|
|
87533
|
-
function alreadyPatched$
|
|
88068
|
+
function alreadyPatched$4(patched, holder, name) {
|
|
87534
88069
|
return patched.get(holder)?.has(name) === true;
|
|
87535
88070
|
}
|
|
87536
88071
|
/**
|
|
@@ -87540,7 +88075,7 @@ function alreadyPatched$3(patched, holder, name) {
|
|
|
87540
88075
|
* @param holder - 方法宿主。
|
|
87541
88076
|
* @param name - 方法名。
|
|
87542
88077
|
*/
|
|
87543
|
-
function markPatched$
|
|
88078
|
+
function markPatched$4(patched, holder, name) {
|
|
87544
88079
|
const names = patched.get(holder);
|
|
87545
88080
|
if (names === void 0) patched.set(holder, /* @__PURE__ */ new Set([name]));
|
|
87546
88081
|
else names.add(name);
|
|
@@ -87555,7 +88090,7 @@ const GLOBAL_KEY$2 = Object.freeze({});
|
|
|
87555
88090
|
* @param service - 服务名。
|
|
87556
88091
|
* @returns 服务实例或 undefined。
|
|
87557
88092
|
*/
|
|
87558
|
-
function serviceOf$
|
|
88093
|
+
function serviceOf$2(ctx, service) {
|
|
87559
88094
|
const read = ctx?.get;
|
|
87560
88095
|
if (typeof read !== "function") return void 0;
|
|
87561
88096
|
try {
|
|
@@ -87577,11 +88112,15 @@ function bucketOf$1(value) {
|
|
|
87577
88112
|
* @param ctx - 宿主上下文。
|
|
87578
88113
|
* @param event - 事件名。
|
|
87579
88114
|
* @param listener - 监听器。
|
|
88115
|
+
* @param options - cordis 订阅选项;省略时按两参数订阅。
|
|
87580
88116
|
* @returns 解绑函数或 undefined。
|
|
87581
88117
|
*/
|
|
87582
|
-
function subscribe$3(ctx, event, listener) {
|
|
88118
|
+
function subscribe$3(ctx, event, listener, options) {
|
|
87583
88119
|
const on = ctx?.on;
|
|
87584
88120
|
if (typeof on !== "function") return void 0;
|
|
88121
|
+
if (options !== void 0) try {
|
|
88122
|
+
return on.call(ctx, event, listener, options);
|
|
88123
|
+
} catch {}
|
|
87585
88124
|
try {
|
|
87586
88125
|
return on.call(ctx, event, listener);
|
|
87587
88126
|
} catch {
|
|
@@ -87674,11 +88213,15 @@ function installPlanModeCacheGuard(ctx) {
|
|
|
87674
88213
|
if (offPreStep !== void 0) restores.push(() => {
|
|
87675
88214
|
offPreStep();
|
|
87676
88215
|
});
|
|
88216
|
+
const offReminder = installPlanModeExitReminder(ctx, { isActive: (agent) => planActiveOfAgent(ctx, agent) });
|
|
88217
|
+
if (offReminder !== void 0) restores.push(() => {
|
|
88218
|
+
offReminder();
|
|
88219
|
+
});
|
|
87677
88220
|
const wrap = (tools) => {
|
|
87678
88221
|
if (tools === void 0) return;
|
|
87679
|
-
const target = resolveMethodTarget$
|
|
88222
|
+
const target = resolveMethodTarget$3(tools, "register");
|
|
87680
88223
|
if (target === void 0) return;
|
|
87681
|
-
if (alreadyPatched$
|
|
88224
|
+
if (alreadyPatched$3(patchedMethods, target.holder, target.name)) return;
|
|
87682
88225
|
const original = target.original;
|
|
87683
88226
|
const wrapped = function(...args) {
|
|
87684
88227
|
const receiver = this ?? tools;
|
|
@@ -87690,16 +88233,16 @@ function installPlanModeCacheGuard(ctx) {
|
|
|
87690
88233
|
}
|
|
87691
88234
|
return original.call(receiver, definition, options);
|
|
87692
88235
|
};
|
|
87693
|
-
if (!installMethod$
|
|
87694
|
-
markPatched$
|
|
88236
|
+
if (!installMethod$3(target, wrapped)) return;
|
|
88237
|
+
markPatched$3(patchedMethods, target.holder, target.name);
|
|
87695
88238
|
restores.push(() => {
|
|
87696
|
-
restoreMethod$
|
|
88239
|
+
restoreMethod$3(target);
|
|
87697
88240
|
});
|
|
87698
88241
|
if (typeof tools.get === "function") try {
|
|
87699
88242
|
if (tools.get("exit_plan_mode") !== void 0) logWarn$1(ctx, "[dsh-chatgpt-subscription] plan-mode cache guard was installed after exit_plan_mode was already registered; this session keeps the conditional admission");
|
|
87700
88243
|
} catch {}
|
|
87701
88244
|
};
|
|
87702
|
-
const tools = serviceOf$
|
|
88245
|
+
const tools = serviceOf$2(ctx, "tools");
|
|
87703
88246
|
if (tools !== void 0) wrap(tools);
|
|
87704
88247
|
else {
|
|
87705
88248
|
const inject = ctx?.inject;
|
|
@@ -87709,7 +88252,7 @@ function installPlanModeCacheGuard(ctx) {
|
|
|
87709
88252
|
inject.call(ctx, ["tools"], (scope) => {
|
|
87710
88253
|
if (wrapped || closed) return;
|
|
87711
88254
|
wrapped = true;
|
|
87712
|
-
wrap(serviceOf$
|
|
88255
|
+
wrap(serviceOf$2(scope, "tools"));
|
|
87713
88256
|
});
|
|
87714
88257
|
} catch {}
|
|
87715
88258
|
}
|
|
@@ -87729,7 +88272,7 @@ function installPlanModeCacheGuard(ctx) {
|
|
|
87729
88272
|
* @returns true / false;读不到时 undefined。
|
|
87730
88273
|
*/
|
|
87731
88274
|
function planActiveOf(ctx, session) {
|
|
87732
|
-
const projections = serviceOf$
|
|
88275
|
+
const projections = serviceOf$2(ctx, "sessionProjections");
|
|
87733
88276
|
if (typeof projections?.stateOf !== "function") return void 0;
|
|
87734
88277
|
try {
|
|
87735
88278
|
const state = projections.stateOf(session, PLAN_PROJECTION_KEY);
|
|
@@ -87739,6 +88282,35 @@ function planActiveOf(ctx, session) {
|
|
|
87739
88282
|
}
|
|
87740
88283
|
}
|
|
87741
88284
|
/**
|
|
88285
|
+
* 读一个 agent 此刻是否在计划模式。
|
|
88286
|
+
*
|
|
88287
|
+
* 三级降级,顺序不可颠倒:
|
|
88288
|
+
*
|
|
88289
|
+
* 1. 进程级登记册({@link registeredPlanControllerActive}):本包的 fork 会把每个
|
|
88290
|
+
* 会话登记进去,**跨 realm 可见**。`ctx.get()` 看不见 `isolate: { planMode: true }`
|
|
88291
|
+
* 的子 realm,而隔离正是宿主守卫最常见的部署(守卫在根作用域、控制器在 preset 里),
|
|
88292
|
+
* 所以这一级必须先问。
|
|
88293
|
+
* 2. 同一作用域里的 `planMode` 服务:本包的 fork 有 `selectedActive`(含未决选择),
|
|
88294
|
+
* 所以 `exit_plan_mode` 刚排队 `{ active: false }`、日志还没落进投影的那一刻不会被
|
|
88295
|
+
* 误判成「还在计划模式」。
|
|
88296
|
+
* 3. plan 投影:内置 preset 挂的是官方服务,它的 `/plan` 只写日志,投影是那边唯一的
|
|
88297
|
+
* 事实来源。
|
|
88298
|
+
* @param ctx - 宿主上下文。
|
|
88299
|
+
* @param agent - 调用方 agent。
|
|
88300
|
+
* @returns true / false;读不到时 undefined。
|
|
88301
|
+
*/
|
|
88302
|
+
function planActiveOfAgent(ctx, agent) {
|
|
88303
|
+
const session = agent?.session;
|
|
88304
|
+
const registered = registeredPlanControllerActive(session);
|
|
88305
|
+
if (registered !== void 0) return registered;
|
|
88306
|
+
const controller = serviceOf$2(ctx, "planMode");
|
|
88307
|
+
if (typeof controller?.selectedActive === "function") try {
|
|
88308
|
+
const active = controller.selectedActive(session);
|
|
88309
|
+
if (typeof active === "boolean") return active;
|
|
88310
|
+
} catch {}
|
|
88311
|
+
return planActiveOf(ctx, session);
|
|
88312
|
+
}
|
|
88313
|
+
/**
|
|
87742
88314
|
* 记一条警告。
|
|
87743
88315
|
* @param ctx - 宿主上下文。
|
|
87744
88316
|
* @param message - 正文。
|
|
@@ -87767,7 +88339,7 @@ function logWarn$1(ctx, message) {
|
|
|
87767
88339
|
* @param name - 方法名。
|
|
87768
88340
|
* @returns 目标;方法不存在时为 `undefined`。
|
|
87769
88341
|
*/
|
|
87770
|
-
function resolveMethodTarget$
|
|
88342
|
+
function resolveMethodTarget$3(service, name) {
|
|
87771
88343
|
if (typeof service !== "object" || service === null) return void 0;
|
|
87772
88344
|
const own = service;
|
|
87773
88345
|
if (Object.prototype.hasOwnProperty.call(own, name)) {
|
|
@@ -87799,7 +88371,7 @@ function resolveMethodTarget$2(service, name) {
|
|
|
87799
88371
|
* @param replacement - 包装实现。
|
|
87800
88372
|
* @returns 是否装上了。
|
|
87801
88373
|
*/
|
|
87802
|
-
function installMethod$
|
|
88374
|
+
function installMethod$3(target, replacement) {
|
|
87803
88375
|
try {
|
|
87804
88376
|
Object.defineProperty(target.holder, target.name, {
|
|
87805
88377
|
value: replacement,
|
|
@@ -87817,7 +88389,7 @@ function installMethod$2(target, replacement) {
|
|
|
87817
88389
|
*
|
|
87818
88390
|
* @param target - 目标。
|
|
87819
88391
|
*/
|
|
87820
|
-
function restoreMethod$
|
|
88392
|
+
function restoreMethod$3(target) {
|
|
87821
88393
|
try {
|
|
87822
88394
|
if (target.descriptor === void 0) Reflect.deleteProperty(target.holder, target.name);
|
|
87823
88395
|
else Object.defineProperty(target.holder, target.name, target.descriptor);
|
|
@@ -87831,7 +88403,7 @@ function restoreMethod$2(target) {
|
|
|
87831
88403
|
* @param name - 方法名。
|
|
87832
88404
|
* @returns 是否已经包过。
|
|
87833
88405
|
*/
|
|
87834
|
-
function alreadyPatched$
|
|
88406
|
+
function alreadyPatched$3(patched, holder, name) {
|
|
87835
88407
|
return patched.get(holder)?.has(name) === true;
|
|
87836
88408
|
}
|
|
87837
88409
|
/**
|
|
@@ -87841,7 +88413,7 @@ function alreadyPatched$2(patched, holder, name) {
|
|
|
87841
88413
|
* @param holder - 方法宿主。
|
|
87842
88414
|
* @param name - 方法名。
|
|
87843
88415
|
*/
|
|
87844
|
-
function markPatched$
|
|
88416
|
+
function markPatched$3(patched, holder, name) {
|
|
87845
88417
|
const names = patched.get(holder);
|
|
87846
88418
|
if (names === void 0) patched.set(holder, /* @__PURE__ */ new Set([name]));
|
|
87847
88419
|
else names.add(name);
|
|
@@ -87963,7 +88535,7 @@ function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
|
87963
88535
|
*/
|
|
87964
88536
|
const toolFingerprint = (tools, scope) => {
|
|
87965
88537
|
if (!isRecord$13(tools)) return "";
|
|
87966
|
-
const target = resolveMethodTarget$
|
|
88538
|
+
const target = resolveMethodTarget$2(tools, "definitions");
|
|
87967
88539
|
if (target === void 0) return "";
|
|
87968
88540
|
let list;
|
|
87969
88541
|
try {
|
|
@@ -87983,9 +88555,9 @@ function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
|
87983
88555
|
const wrapToolsService = (tools) => {
|
|
87984
88556
|
if (disposed || !isRecord$13(tools)) return false;
|
|
87985
88557
|
if (alreadyWrapped.has(tools)) return false;
|
|
87986
|
-
const target = resolveMethodTarget$
|
|
88558
|
+
const target = resolveMethodTarget$2(tools, "definitions");
|
|
87987
88559
|
if (target === void 0) return false;
|
|
87988
|
-
if (alreadyPatched$
|
|
88560
|
+
if (alreadyPatched$2(patchedMethods, target.holder, target.name)) {
|
|
87989
88561
|
alreadyWrapped.add(tools);
|
|
87990
88562
|
return false;
|
|
87991
88563
|
}
|
|
@@ -87998,11 +88570,11 @@ function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
|
87998
88570
|
}
|
|
87999
88571
|
return original.call(receiver, scope, toolSet);
|
|
88000
88572
|
};
|
|
88001
|
-
if (!installMethod$
|
|
88002
|
-
markPatched$
|
|
88573
|
+
if (!installMethod$2(target, replacement)) return false;
|
|
88574
|
+
markPatched$2(patchedMethods, target.holder, target.name);
|
|
88003
88575
|
alreadyWrapped.add(tools);
|
|
88004
88576
|
restores.push(() => {
|
|
88005
|
-
restoreMethod$
|
|
88577
|
+
restoreMethod$2(target);
|
|
88006
88578
|
});
|
|
88007
88579
|
return true;
|
|
88008
88580
|
};
|
|
@@ -88042,7 +88614,7 @@ function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
|
88042
88614
|
};
|
|
88043
88615
|
const offAssemble = subscribe$2(host, "system-prompt/assemble", onAssemble);
|
|
88044
88616
|
if (offAssemble !== void 0) disposers.push(offAssemble);
|
|
88045
|
-
const initialTools = serviceOf(host, "tools");
|
|
88617
|
+
const initialTools = serviceOf$1(host, "tools");
|
|
88046
88618
|
if (initialTools !== void 0) {
|
|
88047
88619
|
currentTools = initialTools;
|
|
88048
88620
|
wrapToolsService(initialTools);
|
|
@@ -88051,7 +88623,7 @@ function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
|
88051
88623
|
if (typeof inject === "function") try {
|
|
88052
88624
|
inject.call(host, ["tools"], (scope) => {
|
|
88053
88625
|
if (disposed) return;
|
|
88054
|
-
const tools = serviceOf(scope, "tools");
|
|
88626
|
+
const tools = serviceOf$1(scope, "tools");
|
|
88055
88627
|
if (tools === void 0) return;
|
|
88056
88628
|
currentTools = tools;
|
|
88057
88629
|
wrapToolsService(tools);
|
|
@@ -88079,7 +88651,7 @@ function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
|
88079
88651
|
* @param service - 服务名。
|
|
88080
88652
|
* @returns 服务实例;读不到时为 `undefined`。
|
|
88081
88653
|
*/
|
|
88082
|
-
function serviceOf(ctx, service) {
|
|
88654
|
+
function serviceOf$1(ctx, service) {
|
|
88083
88655
|
if (!isRecord$13(ctx)) return void 0;
|
|
88084
88656
|
const read = ctx["get"];
|
|
88085
88657
|
if (typeof read !== "function") return void 0;
|
|
@@ -88148,7 +88720,7 @@ function isRecord$13(value) {
|
|
|
88148
88720
|
* @param name - 方法名。
|
|
88149
88721
|
* @returns 目标;方法不存在时为 `undefined`。
|
|
88150
88722
|
*/
|
|
88151
|
-
function resolveMethodTarget$
|
|
88723
|
+
function resolveMethodTarget$2(service, name) {
|
|
88152
88724
|
if (typeof service !== "object" || service === null) return void 0;
|
|
88153
88725
|
const own = service;
|
|
88154
88726
|
if (Object.prototype.hasOwnProperty.call(own, name)) {
|
|
@@ -88180,7 +88752,7 @@ function resolveMethodTarget$1(service, name) {
|
|
|
88180
88752
|
* @param replacement - 包装实现。
|
|
88181
88753
|
* @returns 是否装上了。
|
|
88182
88754
|
*/
|
|
88183
|
-
function installMethod$
|
|
88755
|
+
function installMethod$2(target, replacement) {
|
|
88184
88756
|
try {
|
|
88185
88757
|
Object.defineProperty(target.holder, target.name, {
|
|
88186
88758
|
value: replacement,
|
|
@@ -88198,7 +88770,7 @@ function installMethod$1(target, replacement) {
|
|
|
88198
88770
|
*
|
|
88199
88771
|
* @param target - 目标。
|
|
88200
88772
|
*/
|
|
88201
|
-
function restoreMethod$
|
|
88773
|
+
function restoreMethod$2(target) {
|
|
88202
88774
|
try {
|
|
88203
88775
|
if (target.descriptor === void 0) Reflect.deleteProperty(target.holder, target.name);
|
|
88204
88776
|
else Object.defineProperty(target.holder, target.name, target.descriptor);
|
|
@@ -88212,7 +88784,7 @@ function restoreMethod$1(target) {
|
|
|
88212
88784
|
* @param name - 方法名。
|
|
88213
88785
|
* @returns 是否已经包过。
|
|
88214
88786
|
*/
|
|
88215
|
-
function alreadyPatched$
|
|
88787
|
+
function alreadyPatched$2(patched, holder, name) {
|
|
88216
88788
|
return patched.get(holder)?.has(name) === true;
|
|
88217
88789
|
}
|
|
88218
88790
|
/**
|
|
@@ -88222,12 +88794,245 @@ function alreadyPatched$1(patched, holder, name) {
|
|
|
88222
88794
|
* @param holder - 方法宿主。
|
|
88223
88795
|
* @param name - 方法名。
|
|
88224
88796
|
*/
|
|
88225
|
-
function markPatched$
|
|
88797
|
+
function markPatched$2(patched, holder, name) {
|
|
88226
88798
|
const names = patched.get(holder);
|
|
88227
88799
|
if (names === void 0) patched.set(holder, /* @__PURE__ */ new Set([name]));
|
|
88228
88800
|
else names.add(name);
|
|
88229
88801
|
}
|
|
88230
88802
|
//#endregion
|
|
88803
|
+
//#region src/host/settled-job-guard.ts
|
|
88804
|
+
function isRecord$12(value) {
|
|
88805
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
88806
|
+
}
|
|
88807
|
+
function serviceOf(ctx, name) {
|
|
88808
|
+
const get = ctx?.get;
|
|
88809
|
+
if (typeof get !== "function") return void 0;
|
|
88810
|
+
try {
|
|
88811
|
+
return get.call(ctx, name);
|
|
88812
|
+
} catch {
|
|
88813
|
+
return;
|
|
88814
|
+
}
|
|
88815
|
+
}
|
|
88816
|
+
function isTerminalStatus(value) {
|
|
88817
|
+
return value === "completed" || value === "failed" || value === "killed";
|
|
88818
|
+
}
|
|
88819
|
+
function isUnknownJobError(error, id) {
|
|
88820
|
+
if (!(error instanceof Error)) return false;
|
|
88821
|
+
return error.message === `unknown job ${id}`;
|
|
88822
|
+
}
|
|
88823
|
+
/**
|
|
88824
|
+
* 通过 `agents` 或 `sessions` 服务定位 `caller` 对应的会话对象。
|
|
88825
|
+
*/
|
|
88826
|
+
function resolveCallerSession(ctx, caller) {
|
|
88827
|
+
const agents = serviceOf(ctx, "agents");
|
|
88828
|
+
if (typeof agents?.get === "function") try {
|
|
88829
|
+
const agent = agents.get(caller);
|
|
88830
|
+
if (agent?.session !== void 0 && agent.session !== null) return agent.session;
|
|
88831
|
+
} catch {}
|
|
88832
|
+
const sessions = serviceOf(ctx, "sessions");
|
|
88833
|
+
if (typeof sessions?.get === "function") try {
|
|
88834
|
+
const session = sessions.get(caller);
|
|
88835
|
+
if (session !== void 0 && session !== null) return session;
|
|
88836
|
+
} catch {
|
|
88837
|
+
return;
|
|
88838
|
+
}
|
|
88839
|
+
}
|
|
88840
|
+
/**
|
|
88841
|
+
* 从调用方自己的持久会话日志里倒序查找已落盘的 `job/settled` 记录。
|
|
88842
|
+
*
|
|
88843
|
+
* 严格校验 `owner === caller`:无主或归属其它会话的任务绝不跨会话恢复。
|
|
88844
|
+
*/
|
|
88845
|
+
function findSettledJobInSession(session, jobId, caller) {
|
|
88846
|
+
if (!isRecord$12(session)) return void 0;
|
|
88847
|
+
const snapshot = session["snapshotEvents"];
|
|
88848
|
+
if (typeof snapshot !== "function") return void 0;
|
|
88849
|
+
let events;
|
|
88850
|
+
try {
|
|
88851
|
+
events = snapshot.call(session);
|
|
88852
|
+
} catch {
|
|
88853
|
+
return;
|
|
88854
|
+
}
|
|
88855
|
+
if (!Array.isArray(events)) return void 0;
|
|
88856
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
88857
|
+
const event = events[index];
|
|
88858
|
+
if (!isRecord$12(event) || event["type"] !== "job/settled") continue;
|
|
88859
|
+
const data = event["data"];
|
|
88860
|
+
if (!isRecord$12(data)) continue;
|
|
88861
|
+
if (data["jobId"] !== jobId) continue;
|
|
88862
|
+
if (data["owner"] !== caller) return void 0;
|
|
88863
|
+
const kind = typeof data["kind"] === "string" && data["kind"].length > 0 ? data["kind"] : "job";
|
|
88864
|
+
const label = typeof data["label"] === "string" && data["label"].length > 0 ? data["label"] : jobId;
|
|
88865
|
+
const status = isTerminalStatus(data["status"]) ? data["status"] : "killed";
|
|
88866
|
+
const detail = typeof data["detail"] === "string" && data["detail"].length > 0 ? data["detail"] : void 0;
|
|
88867
|
+
const startedAt = typeof data["startedAt"] === "number" && Number.isFinite(data["startedAt"]) ? data["startedAt"] : 0;
|
|
88868
|
+
const finishedAt = typeof data["finishedAt"] === "number" && Number.isFinite(data["finishedAt"]) ? data["finishedAt"] : void 0;
|
|
88869
|
+
return {
|
|
88870
|
+
id: jobId,
|
|
88871
|
+
kind,
|
|
88872
|
+
label,
|
|
88873
|
+
owner: caller,
|
|
88874
|
+
status,
|
|
88875
|
+
...detail === void 0 ? {} : { detail },
|
|
88876
|
+
startedAt,
|
|
88877
|
+
...finishedAt === void 0 ? {} : { finishedAt },
|
|
88878
|
+
output: {
|
|
88879
|
+
total: 0,
|
|
88880
|
+
earliest: 0
|
|
88881
|
+
}
|
|
88882
|
+
};
|
|
88883
|
+
}
|
|
88884
|
+
}
|
|
88885
|
+
function resolveMethodTarget$1(service, name) {
|
|
88886
|
+
if (typeof service !== "object" || service === null) return void 0;
|
|
88887
|
+
const own = service;
|
|
88888
|
+
if (Object.prototype.hasOwnProperty.call(own, name)) {
|
|
88889
|
+
const original = own[name];
|
|
88890
|
+
if (typeof original !== "function") return void 0;
|
|
88891
|
+
return {
|
|
88892
|
+
holder: own,
|
|
88893
|
+
name,
|
|
88894
|
+
original,
|
|
88895
|
+
descriptor: Object.getOwnPropertyDescriptor(own, name)
|
|
88896
|
+
};
|
|
88897
|
+
}
|
|
88898
|
+
const proto = Object.getPrototypeOf(service);
|
|
88899
|
+
if (proto === null || proto === Object.prototype || proto === Function.prototype) return void 0;
|
|
88900
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, name);
|
|
88901
|
+
if (descriptor === void 0 || typeof descriptor.value !== "function") return void 0;
|
|
88902
|
+
return {
|
|
88903
|
+
holder: proto,
|
|
88904
|
+
name,
|
|
88905
|
+
original: descriptor.value,
|
|
88906
|
+
descriptor
|
|
88907
|
+
};
|
|
88908
|
+
}
|
|
88909
|
+
function installMethod$1(target, replacement) {
|
|
88910
|
+
try {
|
|
88911
|
+
Object.defineProperty(target.holder, target.name, {
|
|
88912
|
+
configurable: target.descriptor?.configurable ?? true,
|
|
88913
|
+
enumerable: target.descriptor?.enumerable ?? false,
|
|
88914
|
+
writable: target.descriptor?.writable ?? true,
|
|
88915
|
+
value: replacement
|
|
88916
|
+
});
|
|
88917
|
+
return true;
|
|
88918
|
+
} catch {
|
|
88919
|
+
return false;
|
|
88920
|
+
}
|
|
88921
|
+
}
|
|
88922
|
+
function restoreMethod$1(target) {
|
|
88923
|
+
try {
|
|
88924
|
+
if (target.descriptor !== void 0) Object.defineProperty(target.holder, target.name, target.descriptor);
|
|
88925
|
+
else delete target.holder[target.name];
|
|
88926
|
+
} catch {}
|
|
88927
|
+
}
|
|
88928
|
+
function alreadyPatched$1(patched, holder, name) {
|
|
88929
|
+
return patched.get(holder)?.has(name) === true;
|
|
88930
|
+
}
|
|
88931
|
+
function markPatched$1(patched, holder, name) {
|
|
88932
|
+
let set = patched.get(holder);
|
|
88933
|
+
if (set === void 0) {
|
|
88934
|
+
set = /* @__PURE__ */ new Set();
|
|
88935
|
+
patched.set(holder, set);
|
|
88936
|
+
}
|
|
88937
|
+
set.add(name);
|
|
88938
|
+
}
|
|
88939
|
+
/**
|
|
88940
|
+
* 安装「已结算后台任务跨回合幂等守卫」。
|
|
88941
|
+
*
|
|
88942
|
+
* @param ctx - 宿主上下文。
|
|
88943
|
+
* @returns 守卫句柄。
|
|
88944
|
+
*/
|
|
88945
|
+
function installSettledJobGuard(ctx) {
|
|
88946
|
+
const restores = [];
|
|
88947
|
+
const patchedMethods = /* @__PURE__ */ new WeakMap();
|
|
88948
|
+
let closed = false;
|
|
88949
|
+
const recoverForCaller = (rawId, rawCaller) => {
|
|
88950
|
+
if (closed) return void 0;
|
|
88951
|
+
if (typeof rawId !== "string" || rawId.length === 0) return void 0;
|
|
88952
|
+
if (typeof rawCaller !== "string" || rawCaller.length === 0) return void 0;
|
|
88953
|
+
return findSettledJobInSession(resolveCallerSession(ctx, rawCaller), rawId, rawCaller);
|
|
88954
|
+
};
|
|
88955
|
+
const patchSync = (jobs, methodName, onRecovered) => {
|
|
88956
|
+
const target = resolveMethodTarget$1(jobs, methodName);
|
|
88957
|
+
if (target === void 0 || alreadyPatched$1(patchedMethods, target.holder, target.name)) return;
|
|
88958
|
+
const original = target.original;
|
|
88959
|
+
const wrapped = function(...args) {
|
|
88960
|
+
const receiver = this ?? jobs;
|
|
88961
|
+
try {
|
|
88962
|
+
return original.call(receiver, ...args);
|
|
88963
|
+
} catch (error) {
|
|
88964
|
+
const id = typeof args[0] === "string" ? args[0] : "";
|
|
88965
|
+
if (id !== "" && isUnknownJobError(error, id)) {
|
|
88966
|
+
const recovered = recoverForCaller(id, args[1]);
|
|
88967
|
+
if (recovered !== void 0) return onRecovered(recovered);
|
|
88968
|
+
}
|
|
88969
|
+
throw error;
|
|
88970
|
+
}
|
|
88971
|
+
};
|
|
88972
|
+
if (!installMethod$1(target, wrapped)) return;
|
|
88973
|
+
markPatched$1(patchedMethods, target.holder, target.name);
|
|
88974
|
+
restores.push(() => {
|
|
88975
|
+
restoreMethod$1(target);
|
|
88976
|
+
});
|
|
88977
|
+
};
|
|
88978
|
+
const patchWait = (jobs) => {
|
|
88979
|
+
const target = resolveMethodTarget$1(jobs, "wait");
|
|
88980
|
+
if (target === void 0 || alreadyPatched$1(patchedMethods, target.holder, target.name)) return;
|
|
88981
|
+
const original = target.original;
|
|
88982
|
+
const wrapped = async function(...args) {
|
|
88983
|
+
const receiver = this ?? jobs;
|
|
88984
|
+
try {
|
|
88985
|
+
return await original.call(receiver, ...args);
|
|
88986
|
+
} catch (error) {
|
|
88987
|
+
const id = typeof args[0] === "string" ? args[0] : "";
|
|
88988
|
+
if (id !== "" && isUnknownJobError(error, id)) {
|
|
88989
|
+
const recovered = recoverForCaller(id, args[2]);
|
|
88990
|
+
if (recovered !== void 0) return recovered;
|
|
88991
|
+
}
|
|
88992
|
+
throw error;
|
|
88993
|
+
}
|
|
88994
|
+
};
|
|
88995
|
+
if (!installMethod$1(target, wrapped)) return;
|
|
88996
|
+
markPatched$1(patchedMethods, target.holder, target.name);
|
|
88997
|
+
restores.push(() => {
|
|
88998
|
+
restoreMethod$1(target);
|
|
88999
|
+
});
|
|
89000
|
+
};
|
|
89001
|
+
const wrap = (jobs) => {
|
|
89002
|
+
if (jobs === void 0) return;
|
|
89003
|
+
patchSync(jobs, "kill", () => "already-finished");
|
|
89004
|
+
patchSync(jobs, "get", (view) => view);
|
|
89005
|
+
patchSync(jobs, "read", (view) => ({
|
|
89006
|
+
chunks: [],
|
|
89007
|
+
lossy: false,
|
|
89008
|
+
job: view
|
|
89009
|
+
}));
|
|
89010
|
+
patchWait(jobs);
|
|
89011
|
+
};
|
|
89012
|
+
const immediate = serviceOf(ctx, "jobs");
|
|
89013
|
+
if (immediate !== void 0) wrap(immediate);
|
|
89014
|
+
else {
|
|
89015
|
+
const inject = ctx?.inject;
|
|
89016
|
+
if (typeof inject === "function") {
|
|
89017
|
+
let wrapped = false;
|
|
89018
|
+
try {
|
|
89019
|
+
inject.call(ctx, ["jobs"], (scope) => {
|
|
89020
|
+
if (wrapped || closed) return;
|
|
89021
|
+
wrapped = true;
|
|
89022
|
+
wrap(serviceOf(scope, "jobs"));
|
|
89023
|
+
});
|
|
89024
|
+
} catch {}
|
|
89025
|
+
}
|
|
89026
|
+
}
|
|
89027
|
+
return { dispose() {
|
|
89028
|
+
if (closed) return;
|
|
89029
|
+
closed = true;
|
|
89030
|
+
for (const restore of restores.splice(0)) try {
|
|
89031
|
+
restore();
|
|
89032
|
+
} catch {}
|
|
89033
|
+
} };
|
|
89034
|
+
}
|
|
89035
|
+
//#endregion
|
|
88231
89036
|
//#region src/host/team-policy-cache-guard.ts
|
|
88232
89037
|
/**
|
|
88233
89038
|
* 「Agent Teams 策略段前缀缓存守卫」—— 把内置 `team:policy` 段从 system 里摘掉,
|
|
@@ -88567,7 +89372,7 @@ const GUARDED_EVENTS = [
|
|
|
88567
89372
|
* @returns 可销毁的句柄。
|
|
88568
89373
|
*/
|
|
88569
89374
|
function installCompactionPolicyGuard(ctx, options = {}) {
|
|
88570
|
-
const host = isRecord$
|
|
89375
|
+
const host = isRecord$11(ctx) ? ctx : void 0;
|
|
88571
89376
|
const provider = options.provider ?? "kimi-code";
|
|
88572
89377
|
const defaults = {
|
|
88573
89378
|
provider,
|
|
@@ -88642,9 +89447,9 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88642
89447
|
* @param source - agent、header 或配置对象。
|
|
88643
89448
|
*/
|
|
88644
89449
|
const observeFrom = (source) => {
|
|
88645
|
-
if (!isRecord$
|
|
89450
|
+
if (!isRecord$11(source)) return;
|
|
88646
89451
|
const session = source["session"];
|
|
88647
|
-
if (isRecord$
|
|
89452
|
+
if (isRecord$11(session)) {
|
|
88648
89453
|
const requestHeader = session["requestHeader"];
|
|
88649
89454
|
if (typeof requestHeader === "function") {
|
|
88650
89455
|
let header;
|
|
@@ -88653,16 +89458,16 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88653
89458
|
} catch {
|
|
88654
89459
|
header = void 0;
|
|
88655
89460
|
}
|
|
88656
|
-
if (isRecord$
|
|
89461
|
+
if (isRecord$11(header)) {
|
|
88657
89462
|
const config = header["config"];
|
|
88658
|
-
if (isRecord$
|
|
89463
|
+
if (isRecord$11(config)) observe(readString(config["provider"]), readString(config["model"]));
|
|
88659
89464
|
}
|
|
88660
89465
|
}
|
|
88661
89466
|
}
|
|
88662
89467
|
const optionsField = source["options"];
|
|
88663
|
-
if (isRecord$
|
|
89468
|
+
if (isRecord$11(optionsField)) observe(readString(optionsField["provider"]), readString(optionsField["model"]));
|
|
88664
89469
|
const config = source["config"];
|
|
88665
|
-
if (isRecord$
|
|
89470
|
+
if (isRecord$11(config)) observe(readString(config["provider"]), readString(config["model"]));
|
|
88666
89471
|
};
|
|
88667
89472
|
/**
|
|
88668
89473
|
* 读一个字符串字段。
|
|
@@ -88692,10 +89497,10 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88692
89497
|
* @returns 是否真的改写了。
|
|
88693
89498
|
*/
|
|
88694
89499
|
const patchEngine = (engine) => {
|
|
88695
|
-
if (disposed || !isRecord$
|
|
89500
|
+
if (disposed || !isRecord$11(engine)) return false;
|
|
88696
89501
|
if (patched.has(engine)) return false;
|
|
88697
89502
|
const config = engine["config"];
|
|
88698
|
-
if (!isRecord$
|
|
89503
|
+
if (!isRecord$11(config)) return false;
|
|
88699
89504
|
const originalPolicies = config["modelPolicies"];
|
|
88700
89505
|
if (!Array.isArray(originalPolicies)) return false;
|
|
88701
89506
|
const originalConfig = config;
|
|
@@ -88765,7 +89570,7 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88765
89570
|
let nextArgs = args;
|
|
88766
89571
|
if (name === "summarize") {
|
|
88767
89572
|
const input = args[0];
|
|
88768
|
-
if (isRecord$
|
|
89573
|
+
if (isRecord$11(input)) {
|
|
88769
89574
|
const messages = input["messages"];
|
|
88770
89575
|
if (Array.isArray(messages)) {
|
|
88771
89576
|
const replaced = replaceCompactionInstruction(messages);
|
|
@@ -88800,12 +89605,12 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88800
89605
|
* @returns 是否改写了新引擎。
|
|
88801
89606
|
*/
|
|
88802
89607
|
const patchStoreEntry = (entry) => {
|
|
88803
|
-
if (!isRecord$
|
|
89608
|
+
if (!isRecord$11(entry)) return false;
|
|
88804
89609
|
const record = entry;
|
|
88805
89610
|
const name = readServiceName(record);
|
|
88806
89611
|
if (name !== void 0 && name !== "compaction") return false;
|
|
88807
89612
|
const value = record.value ?? record.impl;
|
|
88808
|
-
if (isRecord$
|
|
89613
|
+
if (isRecord$11(value)) {
|
|
88809
89614
|
if (patchEngine(value)) return true;
|
|
88810
89615
|
const nested = value["engine"];
|
|
88811
89616
|
if (nested !== void 0) return patchEngine(nested);
|
|
@@ -88820,11 +89625,11 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88820
89625
|
* @returns 本次新改写的引擎数。
|
|
88821
89626
|
*/
|
|
88822
89627
|
const scanStore = (target) => {
|
|
88823
|
-
if (!isRecord$
|
|
89628
|
+
if (!isRecord$11(target)) return 0;
|
|
88824
89629
|
const reflect = target["reflect"];
|
|
88825
|
-
if (!isRecord$
|
|
89630
|
+
if (!isRecord$11(reflect)) return 0;
|
|
88826
89631
|
const store = reflect["store"];
|
|
88827
|
-
if (!isRecord$
|
|
89632
|
+
if (!isRecord$11(store)) return 0;
|
|
88828
89633
|
const services = store;
|
|
88829
89634
|
let count = 0;
|
|
88830
89635
|
for (const key of Object.getOwnPropertySymbols(services)) if (patchStoreEntry(services[key])) count += 1;
|
|
@@ -88838,12 +89643,12 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88838
89643
|
* @returns 是否改写了新引擎。
|
|
88839
89644
|
*/
|
|
88840
89645
|
const patchServiceFrom = (target, name) => {
|
|
88841
|
-
if (!isRecord$
|
|
89646
|
+
if (!isRecord$11(target)) return false;
|
|
88842
89647
|
const get = target["get"];
|
|
88843
89648
|
if (typeof get !== "function") return false;
|
|
88844
89649
|
try {
|
|
88845
89650
|
const service = get.call(target, name);
|
|
88846
|
-
if (!isRecord$
|
|
89651
|
+
if (!isRecord$11(service)) return false;
|
|
88847
89652
|
if (patchEngine(service)) return true;
|
|
88848
89653
|
const nested = service["engine"];
|
|
88849
89654
|
return nested === void 0 ? false : patchEngine(nested);
|
|
@@ -88886,7 +89691,7 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88886
89691
|
try {
|
|
88887
89692
|
for (const arg of args) {
|
|
88888
89693
|
observeFrom(arg);
|
|
88889
|
-
if (isRecord$
|
|
89694
|
+
if (isRecord$11(arg)) observeFrom(arg["agent"]);
|
|
88890
89695
|
}
|
|
88891
89696
|
scanAndPatch();
|
|
88892
89697
|
const agentCtx = findAgentContext(args);
|
|
@@ -88925,9 +89730,9 @@ function installCompactionPolicyGuard(ctx, options = {}) {
|
|
|
88925
89730
|
function readServiceName(record) {
|
|
88926
89731
|
if (typeof record.name === "string") return record.name;
|
|
88927
89732
|
const impl = record.impl;
|
|
88928
|
-
if (isRecord$
|
|
89733
|
+
if (isRecord$11(impl) && typeof impl["name"] === "string") return impl["name"];
|
|
88929
89734
|
const value = record.value;
|
|
88930
|
-
if (isRecord$
|
|
89735
|
+
if (isRecord$11(value) && typeof value["name"] === "string") return value["name"];
|
|
88931
89736
|
}
|
|
88932
89737
|
/**
|
|
88933
89738
|
* 从一次事件派发的参数里找出 agent 的上下文。
|
|
@@ -88939,7 +89744,7 @@ function findAgentContext(args) {
|
|
|
88939
89744
|
for (const arg of args) {
|
|
88940
89745
|
const direct = readContext(arg);
|
|
88941
89746
|
if (direct !== void 0) return direct;
|
|
88942
|
-
if (isRecord$
|
|
89747
|
+
if (isRecord$11(arg)) {
|
|
88943
89748
|
const nested = readContext(arg["agent"]);
|
|
88944
89749
|
if (nested !== void 0) return nested;
|
|
88945
89750
|
}
|
|
@@ -88952,10 +89757,10 @@ function findAgentContext(args) {
|
|
|
88952
89757
|
* @returns 上下文;不像时返回 `undefined`。
|
|
88953
89758
|
*/
|
|
88954
89759
|
function readContext(value) {
|
|
88955
|
-
if (!isRecord$
|
|
89760
|
+
if (!isRecord$11(value)) return void 0;
|
|
88956
89761
|
const ctx = value["ctx"];
|
|
88957
|
-
if (!isRecord$
|
|
88958
|
-
if (typeof ctx["get"] === "function" || isRecord$
|
|
89762
|
+
if (!isRecord$11(ctx)) return void 0;
|
|
89763
|
+
if (typeof ctx["get"] === "function" || isRecord$11(ctx["reflect"])) return ctx;
|
|
88959
89764
|
}
|
|
88960
89765
|
/**
|
|
88961
89766
|
* 订阅一个事件,优先用 `prepend: true`。
|
|
@@ -88995,7 +89800,7 @@ function subscribe(host, event, listener) {
|
|
|
88995
89800
|
* @param value - 任意值。
|
|
88996
89801
|
* @returns 是非 null 的对象时为 `true`。
|
|
88997
89802
|
*/
|
|
88998
|
-
function isRecord$
|
|
89803
|
+
function isRecord$11(value) {
|
|
88999
89804
|
return typeof value === "object" && value !== null;
|
|
89000
89805
|
}
|
|
89001
89806
|
/**
|
|
@@ -89095,449 +89900,6 @@ function markPatched(patched, holder, name) {
|
|
|
89095
89900
|
if (names === void 0) patched.set(holder, /* @__PURE__ */ new Set([name]));
|
|
89096
89901
|
else names.add(name);
|
|
89097
89902
|
}
|
|
89098
|
-
//#endregion
|
|
89099
|
-
//#region src/host/dispatch-execution-guard.ts
|
|
89100
|
-
/**
|
|
89101
|
-
* 「调度执行守卫」——在**执行期**拦住两类越界调用。
|
|
89102
|
-
*
|
|
89103
|
-
* ## 为什么需要它
|
|
89104
|
-
*
|
|
89105
|
-
* 调度模式(dispatch preset)里主控与子代理跑在同一进程、同一套工具注册面上,
|
|
89106
|
-
* 于是有两件事会悄悄坏掉:
|
|
89107
|
-
*
|
|
89108
|
-
* 1. **子代理越权调用主控专用工具**。`ask_user_question`、`exit_plan_mode`、
|
|
89109
|
-
* `create_goal` 这些是**主控的**决定口:让子代理自己问用户、自己进/出计划模式、
|
|
89110
|
-
* 自己建目标,都会把「一个决定」拆成两个决定——子代理问完,用户答了,主控却
|
|
89111
|
-
* 不知道问过什么。子代理本来就该把未决问题**带回**主控,而不是自己去问。
|
|
89112
|
-
* 2. **等待子代理期间空等**。子代理还在跑的时候,主控用 `sleep` 空转,既烧 token
|
|
89113
|
-
* 又错过通知到达的那一刻。正确做法是**结束这一轮**,让内置的子代理完成通知把
|
|
89114
|
-
* 它叫醒(R-W)。
|
|
89115
|
-
*
|
|
89116
|
-
* ## 零 Kimi Code 缓存漂移
|
|
89117
|
-
*
|
|
89118
|
-
* 守卫**只**用 `ctx.tools.guard(exec => …)` 这一条执行期接缝:
|
|
89119
|
-
*
|
|
89120
|
-
* - 不包 `tools.definitions`,不包 `tools.register`,不听
|
|
89121
|
-
* `system-prompt/assemble`——工具声明面(`tools:sdk` 段与顶层工具 schema)
|
|
89122
|
-
* 保持逐字节恒定,Kimi Code 的前缀缓存不会因为这个守卫重建一次。
|
|
89123
|
-
* - 拦截发生在**调用执行时**,模型看到的工具表完全没变,所以「看得见」与
|
|
89124
|
-
* 「叫得动」仍然被拆开:工具照常出现在表里,只是越界的调用被拒。
|
|
89125
|
-
*
|
|
89126
|
-
* ## 判定从哪来
|
|
89127
|
-
*
|
|
89128
|
-
* 两条判定都走**结构探测**,不 import 任何 harness 代次专属的类型:
|
|
89129
|
-
*
|
|
89130
|
-
* - 「你是不是子代理」:先看**持久会话血缘**(`session.header.origin ===
|
|
89131
|
-
* 'subagent'`),再看宿主活着的**存活根**(`agents.roots()`)。两条都是
|
|
89132
|
-
* 读得着的既有事实,不新增任何状态。
|
|
89133
|
-
* - 「你还有没有在跑的子代理」:依次问 `subagents.list` 与 `agents.list`,
|
|
89134
|
-
* 看有没有 `status === 'running'` 的直接子代。
|
|
89135
|
-
*
|
|
89136
|
-
* @module @eddyskywalker/dsh-chatgpt-subscription/host/dispatch-execution-guard
|
|
89137
|
-
*/
|
|
89138
|
-
/**
|
|
89139
|
-
* 子代理**不得**直接调用的主控专用工具。
|
|
89140
|
-
*
|
|
89141
|
-
* 这七个都是「决定口」或「交付口」,不是「干活口」:
|
|
89142
|
-
*
|
|
89143
|
-
* - `ask_user_question` / `exit_plan_mode` / `enter_plan_mode` /
|
|
89144
|
-
* `leave_plan_mode`:计划与提问的决定权在主控;
|
|
89145
|
-
* - `create_goal` / `update_goal`:目标由主控持有;
|
|
89146
|
-
* - `present`:交付口由主控掌握。
|
|
89147
|
-
*
|
|
89148
|
-
* 子代理遇到需要决定的地方,正确动作是**把问题带回主控**,让主控去调这些工具。
|
|
89149
|
-
*/
|
|
89150
|
-
const DEFAULT_DELEGATED_BLOCKED_TOOLS = Object.freeze([
|
|
89151
|
-
"ask_user_question",
|
|
89152
|
-
"exit_plan_mode",
|
|
89153
|
-
"enter_plan_mode",
|
|
89154
|
-
"leave_plan_mode",
|
|
89155
|
-
"create_goal",
|
|
89156
|
-
"update_goal",
|
|
89157
|
-
"present"
|
|
89158
|
-
]);
|
|
89159
|
-
/**
|
|
89160
|
-
* 承载「等待」语义的 shell 工具。
|
|
89161
|
-
*
|
|
89162
|
-
* 这三个是本包与宿主都会用到的 shell 入口:它们的 `command` 参数里可能藏着
|
|
89163
|
-
* `sleep`。空等只在**确实有在跑的子代理**时才是问题(有子代理时应当结束这一
|
|
89164
|
-
* 轮等通知),没有子代理时 `sleep 1` 只是普通命令,不该拦。
|
|
89165
|
-
*/
|
|
89166
|
-
const DEFAULT_SHELL_TOOLS = Object.freeze([
|
|
89167
|
-
"bash",
|
|
89168
|
-
"pwsh",
|
|
89169
|
-
"win_bash"
|
|
89170
|
-
]);
|
|
89171
|
-
/** 一次执行里被判定为「纯等待」的命令形态。 */
|
|
89172
|
-
const SLEEP_COMMAND_PATTERN = /^(?:sleep\s+\d+(?:\.\d+)?[smhd]?|Start-Sleep\s+(?:-(?:Seconds|Milliseconds|s|m)\s+)?\d+(?:\.\d+)?|timeout(?:\.exe)?\s+(?:\/t\s+)?\d+(?:\s+\/nobreak)?|ping(?:\.exe)?\s+-(?:n|c)\s+\d+\s+(?:127\.0\.0\.1|localhost)(?:\s+>|\s*$).*)$/i;
|
|
89173
|
-
/** 无害的空转语句(回显、真、冒号)。 */
|
|
89174
|
-
const NOOP_COMMAND_PATTERN = /^(?:echo\b.*|Write-Host\b.*|Write-Output\b.*|true|:)$/;
|
|
89175
|
-
/** 注释行。 */
|
|
89176
|
-
const COMMENT_COMMAND_PATTERN = /^#/;
|
|
89177
|
-
/**
|
|
89178
|
-
* 读宿主上下文上「直接注入」的 running-child 判定回调。
|
|
89179
|
-
*
|
|
89180
|
-
* 这一步必须**try/catch**:真实 Cordis 的上下文代理对任何没有 inject 的属性直读
|
|
89181
|
-
* 都当场抛 `cannot get property "..." without inject`,一次读失败不该让守卫在
|
|
89182
|
-
* 每次工具调用上抛错。
|
|
89183
|
-
*
|
|
89184
|
-
* @param ctx - 宿主上下文。
|
|
89185
|
-
* @returns 注入的回调;没有时为 undefined。
|
|
89186
|
-
*/
|
|
89187
|
-
function injectedHasRunningChildren(ctx) {
|
|
89188
|
-
if (!isRecord$11(ctx)) return void 0;
|
|
89189
|
-
let injected;
|
|
89190
|
-
try {
|
|
89191
|
-
injected = ctx["hasRunningChildren"];
|
|
89192
|
-
} catch {
|
|
89193
|
-
return;
|
|
89194
|
-
}
|
|
89195
|
-
return typeof injected === "function" ? injected : void 0;
|
|
89196
|
-
}
|
|
89197
|
-
/**
|
|
89198
|
-
* 判断一个值是不是可读的记录对象。
|
|
89199
|
-
*
|
|
89200
|
-
* @param value - 候选值。
|
|
89201
|
-
* @returns 是记录对象时为 true。
|
|
89202
|
-
*/
|
|
89203
|
-
function isRecord$11(value) {
|
|
89204
|
-
return typeof value === "object" && value !== null;
|
|
89205
|
-
}
|
|
89206
|
-
/**
|
|
89207
|
-
* 从宿主上下文里读一个**可选**服务。
|
|
89208
|
-
*
|
|
89209
|
-
* 一律走 `ctx.get()`:没写进 `inject` 的服务名不能当属性读,真实 Cordis 会当场
|
|
89210
|
-
* 抛 `cannot get property "..." without inject`,整个插件降级。读不到就是读不到,
|
|
89211
|
-
* 守卫据此放行,绝不因此让插件挂不上。
|
|
89212
|
-
*
|
|
89213
|
-
* @param ctx - 宿主上下文。
|
|
89214
|
-
* @param name - 服务名。
|
|
89215
|
-
* @returns 服务实例;不存在或读取抛错时为 undefined。
|
|
89216
|
-
*/
|
|
89217
|
-
function readService(ctx, name) {
|
|
89218
|
-
const reader = ctx?.get;
|
|
89219
|
-
if (typeof reader !== "function") return void 0;
|
|
89220
|
-
try {
|
|
89221
|
-
return reader.call(ctx, name);
|
|
89222
|
-
} catch {
|
|
89223
|
-
return;
|
|
89224
|
-
}
|
|
89225
|
-
}
|
|
89226
|
-
/**
|
|
89227
|
-
* 读一个宿主上下文里的工具注册面。
|
|
89228
|
-
*
|
|
89229
|
-
* @param ctx - 宿主上下文。
|
|
89230
|
-
* @returns 带 `guard` 接缝的注册面;没有时为 undefined。
|
|
89231
|
-
*/
|
|
89232
|
-
function toolsOf$2(ctx) {
|
|
89233
|
-
if (!isRecord$11(ctx)) return void 0;
|
|
89234
|
-
let tools;
|
|
89235
|
-
try {
|
|
89236
|
-
tools = ctx["tools"];
|
|
89237
|
-
} catch {
|
|
89238
|
-
tools = void 0;
|
|
89239
|
-
}
|
|
89240
|
-
if (!isRecord$11(tools)) tools = readService(ctx, "tools");
|
|
89241
|
-
return isRecord$11(tools) ? tools : void 0;
|
|
89242
|
-
}
|
|
89243
|
-
/**
|
|
89244
|
-
* 读一条记录的 `id`。
|
|
89245
|
-
*
|
|
89246
|
-
* @param value - 候选记录。
|
|
89247
|
-
* @returns id 字符串;没有时为 undefined。
|
|
89248
|
-
*/
|
|
89249
|
-
function idOf(value) {
|
|
89250
|
-
if (!isRecord$11(value)) return void 0;
|
|
89251
|
-
const id = value["id"];
|
|
89252
|
-
return typeof id === "string" ? id : void 0;
|
|
89253
|
-
}
|
|
89254
|
-
/**
|
|
89255
|
-
* 读一条会话记录头里的 `id`。
|
|
89256
|
-
*
|
|
89257
|
-
* @param agent - 候选 agent。
|
|
89258
|
-
* @returns 会话 id;没有时为 undefined。
|
|
89259
|
-
*/
|
|
89260
|
-
function sessionIdOf$1(agent) {
|
|
89261
|
-
if (!isRecord$11(agent)) return void 0;
|
|
89262
|
-
const session = agent["session"];
|
|
89263
|
-
if (!isRecord$11(session)) return void 0;
|
|
89264
|
-
const header = session["header"];
|
|
89265
|
-
return idOf(header);
|
|
89266
|
-
}
|
|
89267
|
-
/**
|
|
89268
|
-
* 这个调用方是不是**子代理**。
|
|
89269
|
-
*
|
|
89270
|
-
* 判定分两级,先看能独立成立的持久事实,再看宿主当前活着的存活根:
|
|
89271
|
-
*
|
|
89272
|
-
* 1. **持久会话血缘**:`session.header.origin === 'subagent'`。这是子代理会话
|
|
89273
|
-
* 创建时就写下的血缘,跨宿主代次都在,不依赖任何服务是否挂载。
|
|
89274
|
-
* 2. **存活根判定**:宿主提供 `agents.roots()` 时,一个**不在**存活根集合里的
|
|
89275
|
-
* agent 就是别人的孩子。先核对**存活**(`agents.get(id) === agent`):不是
|
|
89276
|
-
* 那个 id 当前登记的存活 agent,说明这个调用方已经过期或已被顶替——判它是不是
|
|
89277
|
-
* 子代理没有意义,放行。
|
|
89278
|
-
*
|
|
89279
|
-
* 宿主没有 `agents` 服务(或老代没有 `roots`)时,判不了就**放行**:把一个
|
|
89280
|
-
* 读不出来的身份当成子代理去拦,会拦掉主控自己的正常调用。
|
|
89281
|
-
*
|
|
89282
|
-
* @param agent - 调用方 agent。
|
|
89283
|
-
* @param ctx - 宿主上下文(可选;用于读 `agents` 服务)。
|
|
89284
|
-
* @returns 是子代理时为 true。
|
|
89285
|
-
*/
|
|
89286
|
-
function isDelegatedCaller(agent, ctx) {
|
|
89287
|
-
if (!isRecord$11(agent)) return false;
|
|
89288
|
-
const session = agent["session"];
|
|
89289
|
-
if (isRecord$11(session)) {
|
|
89290
|
-
const header = session["header"];
|
|
89291
|
-
if (isRecord$11(header) && header["origin"] === "subagent") return true;
|
|
89292
|
-
}
|
|
89293
|
-
const agents = readService(ctx, "agents");
|
|
89294
|
-
if (!isRecord$11(agents)) return false;
|
|
89295
|
-
const roots = rootsOf(agents);
|
|
89296
|
-
if (roots === void 0) return false;
|
|
89297
|
-
const id = idOf(agent);
|
|
89298
|
-
if (typeof id === "string" && typeof agents["get"] === "function") {
|
|
89299
|
-
let live;
|
|
89300
|
-
try {
|
|
89301
|
-
live = agents["get"].call(agents, id);
|
|
89302
|
-
} catch {
|
|
89303
|
-
live = void 0;
|
|
89304
|
-
}
|
|
89305
|
-
if (live !== agent) return false;
|
|
89306
|
-
}
|
|
89307
|
-
return !roots.includes(agent);
|
|
89308
|
-
}
|
|
89309
|
-
/**
|
|
89310
|
-
* 读宿主存活根集合。
|
|
89311
|
-
*
|
|
89312
|
-
* @param agents - `agents` 服务。
|
|
89313
|
-
* @returns 存活根数组;服务没有 `roots` 或读取抛错时为 undefined。
|
|
89314
|
-
*/
|
|
89315
|
-
function rootsOf(agents) {
|
|
89316
|
-
const roots = agents["roots"];
|
|
89317
|
-
if (typeof roots !== "function") return void 0;
|
|
89318
|
-
try {
|
|
89319
|
-
const listed = roots.call(agents);
|
|
89320
|
-
return Array.isArray(listed) ? listed : void 0;
|
|
89321
|
-
} catch {
|
|
89322
|
-
return;
|
|
89323
|
-
}
|
|
89324
|
-
}
|
|
89325
|
-
/**
|
|
89326
|
-
* 判断一条命令是不是**纯等待**。
|
|
89327
|
-
*
|
|
89328
|
-
* 判据:整条命令**按分隔符切开后**,至少有一条是 sleep/wait,而**每一条**都是
|
|
89329
|
-
* sleep/wait 或者无害的空转(回显、真、冒号、注释)。只要有一条在做真事
|
|
89330
|
-
* (`sleep 1 && npm test`、`git status`、`node …`),整条命令就不是纯等待——
|
|
89331
|
-
* 这类命令**必须放行**,否则守卫会拦掉正当的后台工作。
|
|
89332
|
-
*
|
|
89333
|
-
* @param command - 候选命令。
|
|
89334
|
-
* @returns 是纯等待时为 true。
|
|
89335
|
-
*/
|
|
89336
|
-
function isPureSleepCommand(command) {
|
|
89337
|
-
if (typeof command !== "string") return false;
|
|
89338
|
-
const trimmed = command.trim();
|
|
89339
|
-
if (trimmed.length === 0) return false;
|
|
89340
|
-
const statements = trimmed.split(/;|&&|\n/).map((statement) => statement.trim()).filter((statement) => statement.length > 0);
|
|
89341
|
-
if (statements.length === 0) return false;
|
|
89342
|
-
let sawWait = false;
|
|
89343
|
-
for (const statement of statements) {
|
|
89344
|
-
if (SLEEP_COMMAND_PATTERN.test(statement)) {
|
|
89345
|
-
sawWait = true;
|
|
89346
|
-
continue;
|
|
89347
|
-
}
|
|
89348
|
-
if (!isNoopStatement(statement)) return false;
|
|
89349
|
-
}
|
|
89350
|
-
return sawWait;
|
|
89351
|
-
}
|
|
89352
|
-
/**
|
|
89353
|
-
* 判断一条语句是不是无害的空转。
|
|
89354
|
-
*
|
|
89355
|
-
* @param statement - 候选语句。
|
|
89356
|
-
* @returns 是空转时为 true。
|
|
89357
|
-
*/
|
|
89358
|
-
function isNoopStatement(statement) {
|
|
89359
|
-
return NOOP_COMMAND_PATTERN.test(statement) || COMMENT_COMMAND_PATTERN.test(statement);
|
|
89360
|
-
}
|
|
89361
|
-
/**
|
|
89362
|
-
* 这个调用方当前**还有没有在跑的子代理**。
|
|
89363
|
-
*
|
|
89364
|
-
* 两条宿主探测,任何一条给出答案就算数:
|
|
89365
|
-
*
|
|
89366
|
-
* 1. `subagents.list(agent, 'children')`(老代退化成 `subagents.list(agent)`):
|
|
89367
|
-
* 直接子代里有没有 `status === 'running'` 的。
|
|
89368
|
-
* 2. `agents.list()`:活着且 `status === 'running'`、并且 `parent` 就是这个
|
|
89369
|
-
* 调用方的那些 agent。
|
|
89370
|
-
*
|
|
89371
|
-
* 宿主提供 `hasRunningChildren` 回调时以它为准(直接注入口,见
|
|
89372
|
-
* {@link DispatchExecutionGuardOptions.hasRunningChildren})。
|
|
89373
|
-
*
|
|
89374
|
-
* @param agent - 调用方 agent。
|
|
89375
|
-
* @param ctx - 宿主上下文(可选;用于读 `subagents` / `agents` 服务)。
|
|
89376
|
-
* @returns 有在跑的子代理时为 true。
|
|
89377
|
-
*/
|
|
89378
|
-
function hasRunningChildSubagent(agent, ctx) {
|
|
89379
|
-
if (!isRecord$11(agent)) return false;
|
|
89380
|
-
const injected = injectedHasRunningChildren(ctx);
|
|
89381
|
-
if (injected !== void 0) try {
|
|
89382
|
-
return injected(agent) === true;
|
|
89383
|
-
} catch {
|
|
89384
|
-
return false;
|
|
89385
|
-
}
|
|
89386
|
-
const subagents = readService(ctx, "subagents");
|
|
89387
|
-
if (isRecord$11(subagents) && typeof subagents["list"] === "function") {
|
|
89388
|
-
if (entriesOf(callList(subagents["list"], subagents, agent)).some((entry) => entry["status"] === "running")) return true;
|
|
89389
|
-
}
|
|
89390
|
-
const agents = readService(ctx, "agents");
|
|
89391
|
-
if (isRecord$11(agents) && typeof agents["list"] === "function") {
|
|
89392
|
-
const listed = callList(agents["list"], agents, agent, false);
|
|
89393
|
-
const parentIds = /* @__PURE__ */ new Set();
|
|
89394
|
-
const ownId = idOf(agent);
|
|
89395
|
-
if (ownId !== void 0) parentIds.add(ownId);
|
|
89396
|
-
const headerId = sessionIdOf$1(agent);
|
|
89397
|
-
if (headerId !== void 0) parentIds.add(headerId);
|
|
89398
|
-
if (entriesOf(listed).some((entry) => entry["status"] === "running" && typeof entry["parent"] === "string" && parentIds.has(entry["parent"]))) return true;
|
|
89399
|
-
}
|
|
89400
|
-
return false;
|
|
89401
|
-
}
|
|
89402
|
-
/**
|
|
89403
|
-
* 调用一个「列出子代」的宿主方法。
|
|
89404
|
-
*
|
|
89405
|
-
* 先试带 scope 的形态(`list(agent, 'children')`),老代只认 `list(agent)`,
|
|
89406
|
-
* 再老一代的 `agents.list()` 不接参数——三种都试,谁先成功用谁。
|
|
89407
|
-
*
|
|
89408
|
-
* @param fn - 宿主方法。
|
|
89409
|
-
* @param self - 调用宿主。
|
|
89410
|
-
* @param agent - 调用方 agent。
|
|
89411
|
-
* @param scoped - 是否先试带 scope 的形态。
|
|
89412
|
-
* @returns 宿主返回值;全部失败时为 undefined。
|
|
89413
|
-
*/
|
|
89414
|
-
function callList(fn, self, agent, scoped = true) {
|
|
89415
|
-
if (typeof fn !== "function") return void 0;
|
|
89416
|
-
const call = fn;
|
|
89417
|
-
const attempts = scoped ? [
|
|
89418
|
-
[agent, "children"],
|
|
89419
|
-
[agent],
|
|
89420
|
-
[]
|
|
89421
|
-
] : [
|
|
89422
|
-
[],
|
|
89423
|
-
[agent],
|
|
89424
|
-
[agent, "children"]
|
|
89425
|
-
];
|
|
89426
|
-
for (const args of attempts) try {
|
|
89427
|
-
const listed = call.apply(self, args);
|
|
89428
|
-
if (listed !== void 0) return listed;
|
|
89429
|
-
} catch {}
|
|
89430
|
-
}
|
|
89431
|
-
/**
|
|
89432
|
-
* 从宿主返回值里取出「条目数组」。
|
|
89433
|
-
*
|
|
89434
|
-
* 宿主可能直接给数组,也可能给一个包着数组的记录(`children` / `agents`)。
|
|
89435
|
-
*
|
|
89436
|
-
* @param listed - 宿主返回值。
|
|
89437
|
-
* @returns 条目数组;取不到时是空数组。
|
|
89438
|
-
*/
|
|
89439
|
-
function entriesOf(listed) {
|
|
89440
|
-
if (Array.isArray(listed)) return listed.filter(isRecord$11);
|
|
89441
|
-
if (!isRecord$11(listed)) return [];
|
|
89442
|
-
const entries = [];
|
|
89443
|
-
for (const key of [
|
|
89444
|
-
"children",
|
|
89445
|
-
"agents",
|
|
89446
|
-
"entries",
|
|
89447
|
-
"list"
|
|
89448
|
-
]) {
|
|
89449
|
-
const candidate = listed[key];
|
|
89450
|
-
if (!Array.isArray(candidate)) continue;
|
|
89451
|
-
for (const entry of candidate) if (isRecord$11(entry)) entries.push(entry);
|
|
89452
|
-
}
|
|
89453
|
-
return entries;
|
|
89454
|
-
}
|
|
89455
|
-
/**
|
|
89456
|
-
* 解析「调度执行守卫」当前是否启用。
|
|
89457
|
-
*
|
|
89458
|
-
* 沿 volatile 活引用取当前值,所以设置保存后立刻生效。缺省、非法值、读取抛错都
|
|
89459
|
-
* 按**开启**处理:守卫是保护,不是功能开关,读失败不该把保护关掉。
|
|
89460
|
-
*
|
|
89461
|
-
* @param config - 插件配置(活引用或普通值)。
|
|
89462
|
-
* @returns 是否启用。
|
|
89463
|
-
*/
|
|
89464
|
-
function resolveDispatchExecutionGuardEnabled(config) {
|
|
89465
|
-
const field = config?.dispatchExecutionGuard;
|
|
89466
|
-
if (field === void 0 || field === null) return true;
|
|
89467
|
-
if (typeof field === "object" && typeof field.get === "function") try {
|
|
89468
|
-
return field.get() !== false;
|
|
89469
|
-
} catch {
|
|
89470
|
-
return true;
|
|
89471
|
-
}
|
|
89472
|
-
return field !== false;
|
|
89473
|
-
}
|
|
89474
|
-
/**
|
|
89475
|
-
* 子代理越权调用时的拒绝文案。
|
|
89476
|
-
*
|
|
89477
|
-
* 文案要**可执行**:光说「不许调」模型只会换个花样再试一次,所以这里写清楚
|
|
89478
|
-
* 它该做什么——把未决问题带回主控,并带上报告状态。
|
|
89479
|
-
*
|
|
89480
|
-
* @param toolName - 被拦下的工具名。
|
|
89481
|
-
* @returns 拒绝理由。
|
|
89482
|
-
*/
|
|
89483
|
-
function delegatedDenial(toolName) {
|
|
89484
|
-
return `DELEGATED_CALLER: "${toolName}" is a dispatch-level tool and a delegated subagent must not call it directly. Report back to the dispatcher instead: include status: "hand_back" or status: "blocked" and the unresolved question or decision in your report, and let the dispatcher act on it.`;
|
|
89485
|
-
}
|
|
89486
|
-
/**
|
|
89487
|
-
* 子代理还在跑时用 sleep 空等的拒绝文案。
|
|
89488
|
-
*
|
|
89489
|
-
* @returns 拒绝理由。
|
|
89490
|
-
*/
|
|
89491
|
-
function activeChildSleepDenial() {
|
|
89492
|
-
return "ACTIVE_CHILD_SLEEP_FORBIDDEN: a child subagent is still running, so sleeping to wait for it is not allowed. End your turn now and let the built-in subagent completion notification wake you.";
|
|
89493
|
-
}
|
|
89494
|
-
/**
|
|
89495
|
-
* 装一台「调度执行守卫」。
|
|
89496
|
-
*
|
|
89497
|
-
* 只用 `ctx.tools.guard()` 这一条执行期接缝:工具声明面(`tools:sdk` 段与顶层
|
|
89498
|
-
* 工具 schema)一个字节都不改,Kimi Code 的前缀缓存不会因为这个守卫重建。
|
|
89499
|
-
*
|
|
89500
|
-
* @param ctx - 宿主上下文。
|
|
89501
|
-
* @param options - 守卫选项。
|
|
89502
|
-
* @returns 注销守卫的函数;宿主没有 `guard` 接缝时是一个空操作。
|
|
89503
|
-
*/
|
|
89504
|
-
function installDispatchExecutionGuard(ctx, options = {}) {
|
|
89505
|
-
const tools = toolsOf$2(ctx);
|
|
89506
|
-
const register = tools?.guard;
|
|
89507
|
-
if (typeof register !== "function") return () => void 0;
|
|
89508
|
-
const enabled = options.enabled ?? (() => true);
|
|
89509
|
-
const delegatedBlocked = new Set(DEFAULT_DELEGATED_BLOCKED_TOOLS);
|
|
89510
|
-
const shellTools = new Set(DEFAULT_SHELL_TOOLS);
|
|
89511
|
-
const hasRunningChildren = options.hasRunningChildren;
|
|
89512
|
-
const guard = (execution) => {
|
|
89513
|
-
if (!isEnabled(enabled)) return void 0;
|
|
89514
|
-
const toolName = typeof execution?.name === "string" ? execution.name : void 0;
|
|
89515
|
-
if (toolName === void 0) return void 0;
|
|
89516
|
-
const agent = execution?.agent;
|
|
89517
|
-
if (delegatedBlocked.has(toolName) && isDelegatedCaller(agent, ctx)) return delegatedDenial(toolName);
|
|
89518
|
-
if (shellTools.has(toolName)) {
|
|
89519
|
-
const args = isRecord$11(execution?.arguments) ? execution.arguments : void 0;
|
|
89520
|
-
if (!(args?.["run_in_background"] === true) && isPureSleepCommand(args?.["command"])) {
|
|
89521
|
-
if (hasRunningChildren !== void 0 ? hasRunningChildren(agent) === true : hasRunningChildSubagent(agent, ctx)) return activeChildSleepDenial();
|
|
89522
|
-
}
|
|
89523
|
-
}
|
|
89524
|
-
};
|
|
89525
|
-
const dispose = register.call(tools, guard);
|
|
89526
|
-
return typeof dispose === "function" ? dispose : () => void 0;
|
|
89527
|
-
}
|
|
89528
|
-
/**
|
|
89529
|
-
* 读一次开关。读失败按**开启**处理:保护不该因为一次读失败而失效。
|
|
89530
|
-
*
|
|
89531
|
-
* @param enabled - 开关读取函数。
|
|
89532
|
-
* @returns 是否启用。
|
|
89533
|
-
*/
|
|
89534
|
-
function isEnabled(enabled) {
|
|
89535
|
-
try {
|
|
89536
|
-
return enabled() !== false;
|
|
89537
|
-
} catch {
|
|
89538
|
-
return true;
|
|
89539
|
-
}
|
|
89540
|
-
}
|
|
89541
89903
|
const ID_SCHEMA = z.string().min(1).max(64).regex(/^[A-Za-z0-9._:-]+$/);
|
|
89542
89904
|
const TASK_REFERENCE_SCHEMA = z.string().min(1).max(160);
|
|
89543
89905
|
const BOUNDARY_SCHEMA = z.string().min(1).max(120);
|
|
@@ -92883,23 +93245,16 @@ const DISPATCH_PRESET = {
|
|
|
92883
93245
|
name: "@deepseek-ai/dsh-persona",
|
|
92884
93246
|
config: {
|
|
92885
93247
|
suffix: "Your working directory is {{cwd}}.",
|
|
92886
|
-
prefix: `[Role Identification] If your first user message is a task brief (rather than a direct request from the human user), you are a subagent: the coordinator-facing rules in R0,
|
|
93248
|
+
prefix: `[Role Identification] If your first user message is a task brief (rather than a direct request from the human user), you are a subagent: the coordinator-facing rules in R0, R-G, R1, R2, R4, R5, and R-W do not apply to you. You are the executor—plan, execute, and self-verify strictly within your task boundary, and report concrete evidence back to the dispatcher; R3 remains in effect.
|
|
92887
93249
|
- [Standing Subagent Contract] Unless overridden by the brief, every subagent inherits these standing limits: retry attempts at most 3 total per brief; file edits bounded strictly to the declared Boundary module or files; read, search, verification, and test commands unlimited within that boundary; no per-cycle banking (all limits are single-run task totals, and unused allowance is not banked).
|
|
92888
93250
|
- [Subagent Report Protocol] Every subagent completion report states status: ready | hand_back | blocked | failed | dropped, a summary, and evidence (diffs, test commands and outputs, before/after captures for UI). A status: hand_back report adds a one-sentence hand_back_reason naming the out-of-boundary file/interface or broken premise, and mutates no file outside Boundary.
|
|
92889
93251
|
- [Coordinator-Only Tools] ask_user_question, enter_plan_mode, leave_plan_mode, exit_plan_mode, create_goal, update_goal, and present are coordinator-only: a subagent call is hard-blocked at execution time (DELEGATED_CALLER), while declarations remain visible to preserve the provider’s content-prefix cache. Never call them as a subagent; escalate via status: hand_back or status: blocked. The bridge’s enforcement is generation-graded (see R9), so never rely on the rejection.
|
|
92890
93252
|
- [Dispatch Ledger] Call dispatch_ledger {action:"self"} once before your first delegation — it prints the v2 mandate protocol at the tail of its result — and follow that protocol verbatim for every dispatch, report, and steer.
|
|
92891
93253
|
|
|
92892
93254
|
[Coordinator Identity] You are the Lead & Dispatch Agent: converge requirements, plan architecture, select R1 topology (Lead-Core / Hybrid / Fan-out), orchestrate subagents where ROI is positive, and own final acceptance.
|
|
92893
|
-
[Execution Pipeline] R0
|
|
93255
|
+
[Execution Pipeline] R0 Triage -> (L2) R-G Interview -> R9 Plan -> R1 Topology -> (if delegating: R2 Routing -> R5 Brief -> R-W Wait) -> R6 Acceptance.
|
|
92894
93256
|
|
|
92895
|
-
|
|
92896
|
-
A legacy Agent Teams runtime (pre-#7519) registers spawn_teammate and replaces send_message / list_agents / interrupt_agent with team-scoped variants, leaving spawned subagents unreachable. The current runtime only adds a shared task board (team_task_create and its list/get/update siblings) and reuses this mode's tools.
|
|
92897
|
-
Criterion: whether spawn_teammate exists (check via code_run). Never gate on wait_agent, send_message, list_agents, or interrupt_agent: this mode mounts those itself.
|
|
92898
|
-
- Absent -> Write "Orchestration ready: subagent" and proceed to R0. The board tools stay declared whether or not the board is on - frozen declaration, not availability - so confirm with team_task_list before relying on it. When the board is on it is bookkeeping, not a second dispatcher: the dispatch ledger stays the dispatch authority and R5 briefs stay the task contract; publish cross-agent dependencies (blocked_by) and write scopes on one team task per brief, claimed and completed by the child that owns it; never start work because a task is ready, and never reassign a task to skip R6.
|
|
92899
|
-
- Present -> This session runs the legacy runtime and is **not orchestratable**. In order, and nothing else:
|
|
92900
|
-
1. State in one sentence that the legacy runtime shadows the coordination tools and this mode has no degraded path.
|
|
92901
|
-
2. Call ask_user_question once (see R-W) offering: disable the legacy runtime, restart Host, **start a new session**; switch preset; or execute this task directly.
|
|
92902
|
-
3. **Do nothing else** until the user replies: no triage, plan, dispatch, file edits, or workarounds.
|
|
93257
|
+
[Agent Teams Board] A current harness adds exactly one Agent Teams surface beside this mode: the shared task board (team_task_create and its list/get/update siblings). It is bookkeeping, not a second dispatcher. The board tools stay declared whether or not the board is on - frozen declaration, not availability - so confirm with team_task_list before relying on it. When it is on, the dispatch ledger stays the dispatch authority and R5 briefs stay the task contract; publish cross-agent dependencies (blocked_by) and write scopes on one team task per brief, claimed and completed by the child that owns it; never start work because a task is ready, and never reassign a task to skip R6.
|
|
92903
93258
|
|
|
92904
93259
|
## R0 · Complexity Triage (Triage First, Then Choose the Workflow)
|
|
92905
93260
|
Upon receiving a task, determine its tier by semantic impact and uncertainty first, write one line stating "Tier + Rationale", and run the matching workflow:
|
|
@@ -92970,7 +93325,7 @@ Fallback is a task-scoped, non-session-wide exception for delegated briefs: it c
|
|
|
92970
93325
|
|
|
92971
93326
|
## Anti-Patterns (Any Occurrence Is a Violation)
|
|
92972
93327
|
1. Orchestrating or opening Plan Mode for an L0/L1 task, or before the R-G interview has converged (21. Entering Plan Mode for an L0/L1 task, or before the R-G interview has converged; 22. Using leave_plan_mode to bypass exit_plan_mode approval).
|
|
92973
|
-
2. Switching to teammate vocabulary to keep orchestrating
|
|
93328
|
+
2. Switching to teammate vocabulary to keep orchestrating, or Treating the team task board as a substitute for R1 topology, R2 routing, R5 briefs, R6 acceptance, or R-W waiting (R1, R6).
|
|
92974
93329
|
3. Omitting provider/model under [State: Listed], Second-guessing list_subagent_models output by hunting through local config or source files just to check which subagent models are allowed, or Reporting a route as "authorized", or claiming per-task routing is in force, when the session recorded no allowlist (R2).
|
|
92975
93330
|
4. Writing a task brief with a range where a cap belongs ("2–5 files", "a few attempts"), or Asking a subagent to restate its rules as a correctness check (R0, R5).
|
|
92976
93331
|
5. Running sleep, polling loops, or placeholder long commands to wait, Proactively creating a goal at the start of a task, or Ending with a paragraph of prose to wait for user sign-off instead of calling ask_user_question (R-W).
|
|
@@ -99769,6 +100124,23 @@ function applyToolDelta(entry, state) {
|
|
|
99769
100124
|
const fn = isRecord$3(entry.function) ? entry.function : {};
|
|
99770
100125
|
const out = [];
|
|
99771
100126
|
let call = state.toolCalls.get(wireIndex);
|
|
100127
|
+
const incomingId = asString$1(entry.id);
|
|
100128
|
+
if (call !== void 0 && incomingId !== void 0 && call.id !== `call_${wireIndex}` && incomingId !== call.id) {
|
|
100129
|
+
const closedBlock = {
|
|
100130
|
+
type: "tool-call",
|
|
100131
|
+
id: toToolCallId(call.id),
|
|
100132
|
+
name: call.name,
|
|
100133
|
+
arguments: call.arguments === "" ? "{}" : call.arguments
|
|
100134
|
+
};
|
|
100135
|
+
state.blocks[call.blockIndex] = closedBlock;
|
|
100136
|
+
out.push({
|
|
100137
|
+
type: "block-end",
|
|
100138
|
+
index: call.blockIndex,
|
|
100139
|
+
block: closedBlock
|
|
100140
|
+
});
|
|
100141
|
+
state.toolCalls.delete(wireIndex);
|
|
100142
|
+
call = void 0;
|
|
100143
|
+
}
|
|
99772
100144
|
if (call === void 0) {
|
|
99773
100145
|
out.push(...closeCurrent(state));
|
|
99774
100146
|
call = {
|
|
@@ -100138,6 +100510,30 @@ function messagesAssistantContent(message) {
|
|
|
100138
100510
|
return blocks;
|
|
100139
100511
|
}
|
|
100140
100512
|
/**
|
|
100513
|
+
* Merge neighbouring same-role turns.
|
|
100514
|
+
*
|
|
100515
|
+
* DSH history can hold two user messages in a row (an injected context notice
|
|
100516
|
+
* followed by the real turn) and a tool result is itself a user-role message;
|
|
100517
|
+
* the Messages wire wants one user turn, so consecutive turns of one role are
|
|
100518
|
+
* folded together in order.
|
|
100519
|
+
*/
|
|
100520
|
+
function mergeAnthropicMessages(entries) {
|
|
100521
|
+
const merged = [];
|
|
100522
|
+
for (const entry of entries) {
|
|
100523
|
+
if (entry.content.length === 0) continue;
|
|
100524
|
+
const last = merged[merged.length - 1];
|
|
100525
|
+
if (last !== void 0 && last.role === entry.role) {
|
|
100526
|
+
last.content = [...last.content, ...entry.content];
|
|
100527
|
+
continue;
|
|
100528
|
+
}
|
|
100529
|
+
merged.push({
|
|
100530
|
+
role: entry.role,
|
|
100531
|
+
content: [...entry.content]
|
|
100532
|
+
});
|
|
100533
|
+
}
|
|
100534
|
+
return merged;
|
|
100535
|
+
}
|
|
100536
|
+
/**
|
|
100141
100537
|
* Build one `/v1/messages` body.
|
|
100142
100538
|
*
|
|
100143
100539
|
* `stream: true` is mandatory: the adapter reads every response as SSE, and a
|
|
@@ -100155,13 +100551,12 @@ function buildMessagesRequest(options, request = {}) {
|
|
|
100155
100551
|
const role = isToolResultMessage(message) || message.role !== "assistant" ? "user" : "assistant";
|
|
100156
100552
|
const content = role === "user" ? messagesUserContent(message, images) : messagesAssistantContent(message);
|
|
100157
100553
|
if (content.length === 0) continue;
|
|
100158
|
-
|
|
100159
|
-
if (previous !== void 0 && previous.role === role) previous.content.push(...content);
|
|
100160
|
-
else entries.push({
|
|
100554
|
+
entries.push({
|
|
100161
100555
|
role,
|
|
100162
100556
|
content
|
|
100163
100557
|
});
|
|
100164
100558
|
}
|
|
100559
|
+
const messages = cleanOrphanedToolCalls(mergeAnthropicMessages(entries), mergeAnthropicMessages);
|
|
100165
100560
|
const system = leadingSystemTextRaw(options);
|
|
100166
100561
|
const tools = options.tools ?? [];
|
|
100167
100562
|
const effort = request.effort !== void 0 && (request.efforts ?? []).length > 0 ? request.effort : void 0;
|
|
@@ -100170,7 +100565,7 @@ function buildMessagesRequest(options, request = {}) {
|
|
|
100170
100565
|
model: options.model,
|
|
100171
100566
|
max_tokens: maxTokens,
|
|
100172
100567
|
stream: true,
|
|
100173
|
-
messages
|
|
100568
|
+
messages,
|
|
100174
100569
|
...system === void 0 ? {} : { system },
|
|
100175
100570
|
...tools.length > 0 ? { tools: tools.map((tool) => ({
|
|
100176
100571
|
name: tool.name,
|
|
@@ -103920,6 +104315,10 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
103920
104315
|
const guard = installPtcSdkCacheGuard(ctx);
|
|
103921
104316
|
return () => guard.dispose();
|
|
103922
104317
|
}, "dsh-chatgpt-subscription: PTC SDK cache guard");
|
|
104318
|
+
ctx.effect(() => {
|
|
104319
|
+
const guard = installSettledJobGuard(ctx);
|
|
104320
|
+
return () => guard.dispose();
|
|
104321
|
+
}, "dsh-chatgpt-subscription: settled job guard");
|
|
103923
104322
|
ctx.effect(() => {
|
|
103924
104323
|
const guard = installTeamPolicyCacheGuard(ctx, { enabled: () => resolveTeamPolicyCacheGuardEnabled(pluginConfig) });
|
|
103925
104324
|
return () => guard.dispose();
|