@eddyskywalker/dsh-chatgpt-subscription 0.51.0 → 0.52.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 +36 -0
- package/lib/client.js.map +1 -1
- package/lib/index.js +2154 -374
- package/lib/tool-result-pruner.js +8 -7
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/entry-tool-result-pruner.d.ts +7 -6
- package/lib/types/entry-tool-result-pruner.d.ts.map +1 -1
- package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
- package/lib/types/host/kimi-code/client.d.ts.map +1 -1
- package/lib/types/host/kimi-code/mapper.d.ts +19 -1
- package/lib/types/host/kimi-code/mapper.d.ts.map +1 -1
- package/lib/types/host/kimi-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/kimi-code/oauth.d.ts +35 -1
- package/lib/types/host/kimi-code/oauth.d.ts.map +1 -1
- package/lib/types/host/kimi-code/repeat-breaker.d.ts +220 -0
- package/lib/types/host/kimi-code/repeat-breaker.d.ts.map +1 -0
- package/lib/types/host/kimi-code/types.d.ts +13 -0
- package/lib/types/host/kimi-code/types.d.ts.map +1 -1
- package/lib/types/host/minimax-code/adapter.d.ts.map +1 -1
- package/lib/types/host/minimax-code/client.d.ts +10 -1
- package/lib/types/host/minimax-code/client.d.ts.map +1 -1
- package/lib/types/host/minimax-code/mapper.d.ts +33 -4
- package/lib/types/host/minimax-code/mapper.d.ts.map +1 -1
- package/lib/types/host/minimax-code/model-catalog.d.ts +9 -2
- package/lib/types/host/minimax-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/minimax-code/runtime-enhancements.d.ts +313 -0
- package/lib/types/host/minimax-code/runtime-enhancements.d.ts.map +1 -0
- package/lib/types/host/minimax-code/types.d.ts +37 -4
- package/lib/types/host/minimax-code/types.d.ts.map +1 -1
- package/lib/types/host/ptc-sdk-cache-guard.d.ts +13 -4
- package/lib/types/host/ptc-sdk-cache-guard.d.ts.map +1 -1
- package/lib/types/host/tool-result-pruner-guard.d.ts +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { DEFAULT_SKIP_PROVIDERS, PRUNER_SERVICE_NAME, resolveSkipProviders, shou
|
|
|
4
4
|
import { PLAN_PROJECTION_KEY, createPlanNotice } from "./plan-mode.js";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import * as LlmModule from "@deepseek-ai/dsh-llm";
|
|
7
|
-
import { EMPTY_RESPONSE_CODE, HarnessError, LlmAdapter, LlmError, LlmError as LlmError$1, ProviderRequestId, ReasoningEffortId, ToolCallId, attributionHeaders, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
7
|
+
import { EMPTY_RESPONSE_CODE, HarnessError, LlmAdapter, LlmError, LlmError as LlmError$1, ProviderRequestId, ReasoningEffortId, ToolCallId, attributionHeaders, createUserMessage, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
8
8
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
import z$1 from "@deepseek-ai/schemastery";
|
|
@@ -146,7 +146,7 @@ const ROUTE_PREFIX$5 = "/api/dsh-chatgpt-subscription";
|
|
|
146
146
|
* `test/responses-client.test.ts` asserts the two agree, so a release that
|
|
147
147
|
* forgets this constant fails the suite instead of shipping quietly.
|
|
148
148
|
*/
|
|
149
|
-
const PLUGIN_VERSION = "0.
|
|
149
|
+
const PLUGIN_VERSION = "0.52.0";
|
|
150
150
|
const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
|
|
151
151
|
const CODEX_API_BASE = "https://chatgpt.com/backend-api/codex";
|
|
152
152
|
const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses`;
|
|
@@ -3453,7 +3453,7 @@ var OAuthService = class {
|
|
|
3453
3453
|
throw new OAuthServiceError("oauth-token-exchange-failed", `The ChatGPT device code could not be issued (${response.status}${detail === null ? "" : `, ${detail}`}).`, response.status);
|
|
3454
3454
|
}
|
|
3455
3455
|
const payload = await response.json().catch(() => null);
|
|
3456
|
-
const record = isRecord$
|
|
3456
|
+
const record = isRecord$68(payload) ? payload : {};
|
|
3457
3457
|
const authId = nonEmptyString$11(record.device_auth_id);
|
|
3458
3458
|
const userCode = nonEmptyString$11(record.user_code) ?? nonEmptyString$11(record.usercode);
|
|
3459
3459
|
if (authId === void 0 || userCode === void 0) throw new OAuthServiceError("oauth-token-exchange-failed", "ChatGPT returned no device code.");
|
|
@@ -3520,7 +3520,7 @@ var OAuthService = class {
|
|
|
3520
3520
|
const detail = deviceErrorIdentifier(payload);
|
|
3521
3521
|
throw new OAuthServiceError("oauth-token-exchange-failed", `The ChatGPT device confirmation was refused (${response.status}${detail === void 0 ? "" : `, ${detail}`}).`, response.status);
|
|
3522
3522
|
}
|
|
3523
|
-
const record = isRecord$
|
|
3523
|
+
const record = isRecord$68(payload) ? payload : {};
|
|
3524
3524
|
const authorizationCode = nonEmptyString$11(record.authorization_code);
|
|
3525
3525
|
const codeVerifier = nonEmptyString$11(record.code_verifier);
|
|
3526
3526
|
if (authorizationCode === void 0 || codeVerifier === void 0) throw new OAuthServiceError("oauth-token-exchange-failed", "ChatGPT confirmed the device code but returned no authorization code.");
|
|
@@ -3867,11 +3867,11 @@ const DEVICE_PENDING_STATUSES = /* @__PURE__ */ new Set([
|
|
|
3867
3867
|
function isPendingDeviceAnswer(response, payload) {
|
|
3868
3868
|
if (response.status === 403 || response.status === 404) return true;
|
|
3869
3869
|
if (!response.ok && response.status !== 400) return false;
|
|
3870
|
-
if (!isRecord$
|
|
3870
|
+
if (!isRecord$68(payload)) return false;
|
|
3871
3871
|
const status = payload.status;
|
|
3872
3872
|
if (typeof status === "string" && DEVICE_PENDING_STATUSES.has(status.toLowerCase())) return true;
|
|
3873
3873
|
const error = payload.error;
|
|
3874
|
-
if (isRecord$
|
|
3874
|
+
if (isRecord$68(error)) {
|
|
3875
3875
|
const code = error.code;
|
|
3876
3876
|
if (typeof code === "string" && DEVICE_PENDING_STATUSES.has(code.toLowerCase())) return true;
|
|
3877
3877
|
}
|
|
@@ -3885,18 +3885,18 @@ function isPendingDeviceAnswer(response, payload) {
|
|
|
3885
3885
|
* wrong.
|
|
3886
3886
|
*/
|
|
3887
3887
|
function deviceErrorIdentifier(payload) {
|
|
3888
|
-
if (!isRecord$
|
|
3888
|
+
if (!isRecord$68(payload)) return void 0;
|
|
3889
3889
|
const candidates = [payload.code];
|
|
3890
3890
|
const error = payload.error;
|
|
3891
3891
|
if (typeof error === "string") candidates.push(error);
|
|
3892
|
-
else if (isRecord$
|
|
3892
|
+
else if (isRecord$68(error)) candidates.push(error.code, error.type);
|
|
3893
3893
|
candidates.push(payload.status);
|
|
3894
3894
|
for (const candidate of candidates) if (typeof candidate === "string" && /^[a-z0-9_.-]{1,64}$/i.test(candidate)) return candidate;
|
|
3895
3895
|
}
|
|
3896
3896
|
function nonEmptyString$11(value) {
|
|
3897
3897
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
3898
3898
|
}
|
|
3899
|
-
function isRecord$
|
|
3899
|
+
function isRecord$68(value) {
|
|
3900
3900
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3901
3901
|
}
|
|
3902
3902
|
async function oauthErrorIdentifier(response) {
|
|
@@ -4079,7 +4079,7 @@ const CODEX_AUTH_CLAIMS_KEY = "https://api.openai.com/auth";
|
|
|
4079
4079
|
* here, and the import has to be repeated afterwards.
|
|
4080
4080
|
*/
|
|
4081
4081
|
const ADOPTED_CODEX_CREDENTIAL_EXPIRED_HINT = "The sign-in imported from the Codex CLI has expired. Sign in again in the Codex CLI, then import it again from this settings card.";
|
|
4082
|
-
function isRecord$
|
|
4082
|
+
function isRecord$67(value) {
|
|
4083
4083
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4084
4084
|
}
|
|
4085
4085
|
/** A trimmed, non-empty string, or nothing. */
|
|
@@ -4181,7 +4181,7 @@ function decodeJwtClaims$1(token) {
|
|
|
4181
4181
|
if (parts.length !== 3) return void 0;
|
|
4182
4182
|
try {
|
|
4183
4183
|
const value = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
|
|
4184
|
-
return isRecord$
|
|
4184
|
+
return isRecord$67(value) ? value : void 0;
|
|
4185
4185
|
} catch {
|
|
4186
4186
|
return;
|
|
4187
4187
|
}
|
|
@@ -4226,10 +4226,10 @@ function expiryFromAccessToken(accessToken) {
|
|
|
4226
4226
|
* the file carries cannot reach the result.
|
|
4227
4227
|
*/
|
|
4228
4228
|
function parseAdoptedCodexCredential(value, sourcePath) {
|
|
4229
|
-
if (!isRecord$
|
|
4229
|
+
if (!isRecord$67(value)) return void 0;
|
|
4230
4230
|
if (value.auth_mode !== "chatgpt") return void 0;
|
|
4231
4231
|
const tokens = value[CODEX_CLI_TOKENS_KEY];
|
|
4232
|
-
if (!isRecord$
|
|
4232
|
+
if (!isRecord$67(tokens)) return void 0;
|
|
4233
4233
|
const accessToken = nonEmptyString$10(tokens.access_token);
|
|
4234
4234
|
if (accessToken === void 0) return void 0;
|
|
4235
4235
|
const refreshToken = nonEmptyString$10(tokens.refresh_token);
|
|
@@ -4248,7 +4248,7 @@ function parseAdoptedCodexCredential(value, sourcePath) {
|
|
|
4248
4248
|
const email = claims === void 0 ? void 0 : nonEmptyString$10(claims.email);
|
|
4249
4249
|
if (email !== void 0) credentials.email = email;
|
|
4250
4250
|
const authClaims = claims === void 0 ? void 0 : claims[CODEX_AUTH_CLAIMS_KEY];
|
|
4251
|
-
const planType = isRecord$
|
|
4251
|
+
const planType = isRecord$67(authClaims) ? nonEmptyString$10(authClaims.chatgpt_plan_type) : void 0;
|
|
4252
4252
|
if (planType !== void 0) credentials.planType = planType;
|
|
4253
4253
|
}
|
|
4254
4254
|
const accountId = nonEmptyString$10(tokens.account_id);
|
|
@@ -5017,13 +5017,13 @@ function webServerOrigin(server) {
|
|
|
5017
5017
|
//#region src/host/common/llm-compat.ts
|
|
5018
5018
|
/** This package's kind in the harness message-source map. */
|
|
5019
5019
|
const PLUGIN_MESSAGE_SOURCE_KIND = "dsh-chatgpt-subscription";
|
|
5020
|
-
function isRecord$
|
|
5020
|
+
function isRecord$66(value) {
|
|
5021
5021
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5022
5022
|
}
|
|
5023
5023
|
/** Read a message body's blocks, keeping every entry that carries a block tag. */
|
|
5024
5024
|
function readBlocks(raw) {
|
|
5025
5025
|
if (!Array.isArray(raw)) return [];
|
|
5026
|
-
return raw.filter((block) => isRecord$
|
|
5026
|
+
return raw.filter((block) => isRecord$66(block) && typeof block.type === "string");
|
|
5027
5027
|
}
|
|
5028
5028
|
/**
|
|
5029
5029
|
* The first value that is a non-empty string.
|
|
@@ -5078,10 +5078,10 @@ function toolCallIdOf(raw, source, embedded) {
|
|
|
5078
5078
|
function normalizeMessages(messages) {
|
|
5079
5079
|
const normalized = [];
|
|
5080
5080
|
for (const raw of messages ?? []) {
|
|
5081
|
-
if (!isRecord$
|
|
5081
|
+
if (!isRecord$66(raw)) continue;
|
|
5082
5082
|
const content = readBlocks(raw.content);
|
|
5083
5083
|
if (raw.role === "tool") {
|
|
5084
|
-
const source = isRecord$
|
|
5084
|
+
const source = isRecord$66(raw.source) ? raw.source : void 0;
|
|
5085
5085
|
const embedded = embeddedToolResult(content);
|
|
5086
5086
|
const callId = toolCallIdOf(raw, source, embedded);
|
|
5087
5087
|
const isError = raw.isError === true || embedded?.isError === true;
|
|
@@ -5105,7 +5105,7 @@ function normalizeMessages(messages) {
|
|
|
5105
5105
|
id: raw.id,
|
|
5106
5106
|
role: typeof raw.role === "string" ? raw.role : "user",
|
|
5107
5107
|
content,
|
|
5108
|
-
...isRecord$
|
|
5108
|
+
...isRecord$66(raw.source) ? { source: raw.source } : {}
|
|
5109
5109
|
});
|
|
5110
5110
|
}
|
|
5111
5111
|
return normalized;
|
|
@@ -6809,7 +6809,7 @@ const schemaFields = /* @__PURE__ */ new Set([
|
|
|
6809
6809
|
"required",
|
|
6810
6810
|
"propertyOrdering"
|
|
6811
6811
|
]);
|
|
6812
|
-
function isRecord$
|
|
6812
|
+
function isRecord$65(value) {
|
|
6813
6813
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6814
6814
|
}
|
|
6815
6815
|
function mergeSchemas(left, right) {
|
|
@@ -6817,7 +6817,7 @@ function mergeSchemas(left, right) {
|
|
|
6817
6817
|
...left,
|
|
6818
6818
|
...right
|
|
6819
6819
|
};
|
|
6820
|
-
if (isRecord$
|
|
6820
|
+
if (isRecord$65(left.properties) && isRecord$65(right.properties)) merged.properties = {
|
|
6821
6821
|
...left.properties,
|
|
6822
6822
|
...right.properties
|
|
6823
6823
|
};
|
|
@@ -6853,9 +6853,9 @@ const mergedTypeKeys = /* @__PURE__ */ new Set([
|
|
|
6853
6853
|
* model with strictly less than the schema it started from.
|
|
6854
6854
|
*/
|
|
6855
6855
|
function describeBranch(branch) {
|
|
6856
|
-
const type = typeof branch.type === "string" ? branch.type : isRecord$
|
|
6856
|
+
const type = typeof branch.type === "string" ? branch.type : isRecord$65(branch.properties) ? "object" : isRecord$65(branch.items) ? "array" : "value";
|
|
6857
6857
|
const details = [];
|
|
6858
|
-
if (isRecord$
|
|
6858
|
+
if (isRecord$65(branch.properties)) {
|
|
6859
6859
|
const names = Object.keys(branch.properties);
|
|
6860
6860
|
if (names.length > 0) details.push(`{${names.join(",")}}`);
|
|
6861
6861
|
}
|
|
@@ -6869,7 +6869,7 @@ function describeBranch(branch) {
|
|
|
6869
6869
|
}
|
|
6870
6870
|
/** How well one branch can stand in for a whole union; a named object shape wins. */
|
|
6871
6871
|
function branchRank(branch) {
|
|
6872
|
-
if (isRecord$
|
|
6872
|
+
if (isRecord$65(branch.properties)) return 3;
|
|
6873
6873
|
if (branch.type === "object") return 2;
|
|
6874
6874
|
if (branch.type === "array") return 1;
|
|
6875
6875
|
return 0;
|
|
@@ -6898,7 +6898,7 @@ function unionShape(branches) {
|
|
|
6898
6898
|
shape: branches[0],
|
|
6899
6899
|
folded: false
|
|
6900
6900
|
};
|
|
6901
|
-
if (new Set(branches.map((branch) => branch.type)).size === 1 && branches.every((branch) => !isRecord$
|
|
6901
|
+
if (new Set(branches.map((branch) => branch.type)).size === 1 && branches.every((branch) => !isRecord$65(branch.properties) && !isRecord$65(branch.items))) {
|
|
6902
6902
|
const shape = { type: branches[0].type };
|
|
6903
6903
|
if (branches.every((branch) => Array.isArray(branch.enum))) {
|
|
6904
6904
|
const values = [...new Set(branches.flatMap((branch) => branch.enum))];
|
|
@@ -6935,7 +6935,7 @@ function foldOwnFields(node) {
|
|
|
6935
6935
|
const out = {};
|
|
6936
6936
|
for (const [key, value] of Object.entries(node)) {
|
|
6937
6937
|
if (key === "anyOf" || key === "oneOf" || key === "allOf") continue;
|
|
6938
|
-
if (key === "properties" && isRecord$
|
|
6938
|
+
if (key === "properties" && isRecord$65(value)) {
|
|
6939
6939
|
out.properties = Object.fromEntries(Object.entries(value).map(([name, child]) => [name, foldSchemaUnions(child)]));
|
|
6940
6940
|
continue;
|
|
6941
6941
|
}
|
|
@@ -6964,15 +6964,15 @@ function foldOwnFields(node) {
|
|
|
6964
6964
|
* argument the model sends anyway fails there, naming the actual problem.
|
|
6965
6965
|
*/
|
|
6966
6966
|
function foldSchemaUnions(node) {
|
|
6967
|
-
if (!isRecord$
|
|
6967
|
+
if (!isRecord$65(node)) return node;
|
|
6968
6968
|
let own = foldOwnFields(node);
|
|
6969
6969
|
if (Array.isArray(node.allOf)) for (const branch of node.allOf) {
|
|
6970
6970
|
const folded = foldSchemaUnions(branch);
|
|
6971
|
-
if (isRecord$
|
|
6971
|
+
if (isRecord$65(folded)) own = mergeSchemas(own, folded);
|
|
6972
6972
|
}
|
|
6973
6973
|
const alternatives = Array.isArray(node.anyOf) ? node.anyOf : Array.isArray(node.oneOf) ? node.oneOf : [];
|
|
6974
6974
|
if (alternatives.length === 0) return own;
|
|
6975
|
-
const branches = alternatives.map((branch) => foldSchemaUnions(branch)).filter(isRecord$
|
|
6975
|
+
const branches = alternatives.map((branch) => foldSchemaUnions(branch)).filter(isRecord$65);
|
|
6976
6976
|
if (branches.length === 0) return own;
|
|
6977
6977
|
const shapes = branches.filter((branch) => branch.type !== "null");
|
|
6978
6978
|
const acceptsNull = branches.some((branch) => branch.type === "null");
|
|
@@ -6988,7 +6988,7 @@ function foldSchemaUnions(node) {
|
|
|
6988
6988
|
return merged;
|
|
6989
6989
|
}
|
|
6990
6990
|
function toAntigravityToolSchema(schema, options = {}) {
|
|
6991
|
-
if (!isRecord$
|
|
6991
|
+
if (!isRecord$65(schema)) return schema;
|
|
6992
6992
|
const root = schema;
|
|
6993
6993
|
function resolveReference(reference) {
|
|
6994
6994
|
let target = root;
|
|
@@ -6996,13 +6996,13 @@ function toAntigravityToolSchema(schema, options = {}) {
|
|
|
6996
6996
|
const path = reference === "#" ? [] : reference.slice(2).split("/");
|
|
6997
6997
|
for (const segment of path) {
|
|
6998
6998
|
const key = segment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
6999
|
-
target = isRecord$
|
|
6999
|
+
target = isRecord$65(target) && Object.hasOwn(target, key) ? target[key] : void 0;
|
|
7000
7000
|
}
|
|
7001
|
-
if (!isRecord$
|
|
7001
|
+
if (!isRecord$65(target)) throw new LlmError(`Antigravity tool schema reference was not found: ${reference}`, "PROVIDER_ERROR");
|
|
7002
7002
|
return target;
|
|
7003
7003
|
}
|
|
7004
7004
|
function convert(node, references) {
|
|
7005
|
-
if (!isRecord$
|
|
7005
|
+
if (!isRecord$65(node)) return {};
|
|
7006
7006
|
let inherited = {};
|
|
7007
7007
|
if (typeof node.$ref === "string") {
|
|
7008
7008
|
if (references.has(node.$ref)) throw new LlmError(`Antigravity tool schema contains a recursive reference: ${node.$ref}`, "PROVIDER_ERROR");
|
|
@@ -7011,8 +7011,8 @@ function toAntigravityToolSchema(schema, options = {}) {
|
|
|
7011
7011
|
if (Array.isArray(node.allOf)) for (const branch of node.allOf) inherited = mergeSchemas(inherited, convert(branch, references));
|
|
7012
7012
|
const out = {};
|
|
7013
7013
|
for (const [key, value] of Object.entries(node)) if (schemaFields.has(key)) out[key] = value;
|
|
7014
|
-
if (isRecord$
|
|
7015
|
-
if (isRecord$
|
|
7014
|
+
if (isRecord$65(node.properties)) out.properties = Object.fromEntries(Object.entries(node.properties).map(([name, child]) => [name, convert(child, references)]));
|
|
7015
|
+
if (isRecord$65(node.items)) out.items = convert(node.items, references);
|
|
7016
7016
|
const alternatives = Array.isArray(node.anyOf) ? node.anyOf : node.oneOf;
|
|
7017
7017
|
if (Array.isArray(alternatives)) out.anyOf = alternatives.map((child) => convert(child, references));
|
|
7018
7018
|
if (Array.isArray(node.type)) {
|
|
@@ -7048,7 +7048,7 @@ let toolCallCounter = 0;
|
|
|
7048
7048
|
function sanitizeText$9(text) {
|
|
7049
7049
|
return text.replace(/\0/g, "");
|
|
7050
7050
|
}
|
|
7051
|
-
function isRecord$
|
|
7051
|
+
function isRecord$64(value) {
|
|
7052
7052
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7053
7053
|
}
|
|
7054
7054
|
function asString$29(value) {
|
|
@@ -7068,25 +7068,25 @@ function toolCallIdNeeded(modelId, runtimeModel) {
|
|
|
7068
7068
|
return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-") || runtimeModel.startsWith("claude-") || runtimeModel.startsWith("gpt-oss-");
|
|
7069
7069
|
}
|
|
7070
7070
|
function parseArguments$1(raw) {
|
|
7071
|
-
if (isRecord$
|
|
7071
|
+
if (isRecord$64(raw)) return raw;
|
|
7072
7072
|
if (raw === void 0 || raw === null || raw === "") return {};
|
|
7073
7073
|
const parsed = typeof raw === "string" ? safeJsonParse$9(raw) : raw;
|
|
7074
|
-
return isRecord$
|
|
7074
|
+
return isRecord$64(parsed) ? parsed : {};
|
|
7075
7075
|
}
|
|
7076
7076
|
const NO_RESOLVED_IMAGES$5 = /* @__PURE__ */ new Map();
|
|
7077
7077
|
function attachmentOf$5(block) {
|
|
7078
7078
|
const attachment = block.attachment;
|
|
7079
|
-
if (!isRecord$
|
|
7079
|
+
if (!isRecord$64(attachment)) return void 0;
|
|
7080
7080
|
return typeof attachment.attachmentId === "string" ? attachment : void 0;
|
|
7081
7081
|
}
|
|
7082
7082
|
function attachmentLabel$6(block) {
|
|
7083
|
-
const attachment = isRecord$
|
|
7083
|
+
const attachment = isRecord$64(block.attachment) ? block.attachment : void 0;
|
|
7084
7084
|
return asString$29(attachment?.name) || asString$29(attachment?.attachmentId);
|
|
7085
7085
|
}
|
|
7086
7086
|
function collectImageRefs$3(content, refs) {
|
|
7087
7087
|
if (!Array.isArray(content)) return;
|
|
7088
7088
|
for (const block of content) {
|
|
7089
|
-
if (!isRecord$
|
|
7089
|
+
if (!isRecord$64(block)) continue;
|
|
7090
7090
|
if (block.type === "image") {
|
|
7091
7091
|
const attachment = attachmentOf$5(block);
|
|
7092
7092
|
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
@@ -7199,7 +7199,7 @@ function requestImageBytes$2(block) {
|
|
|
7199
7199
|
function collectRequestImageBytes$2(content, lengths) {
|
|
7200
7200
|
if (!Array.isArray(content)) return;
|
|
7201
7201
|
for (const block of content) {
|
|
7202
|
-
if (!isRecord$
|
|
7202
|
+
if (!isRecord$64(block)) continue;
|
|
7203
7203
|
if (block.type === "tool-result") {
|
|
7204
7204
|
collectRequestImageBytes$2(block.content, lengths);
|
|
7205
7205
|
continue;
|
|
@@ -7249,7 +7249,7 @@ function offloadOldestRequestImages$3(options) {
|
|
|
7249
7249
|
let replaced = false;
|
|
7250
7250
|
return {
|
|
7251
7251
|
content: content.map((block) => {
|
|
7252
|
-
if (remaining.count === 0 || !isRecord$
|
|
7252
|
+
if (remaining.count === 0 || !isRecord$64(block)) return block;
|
|
7253
7253
|
if (block.type === "image") {
|
|
7254
7254
|
if (requestImageBytes$2(block) === void 0) return block;
|
|
7255
7255
|
remaining.count -= 1;
|
|
@@ -7352,7 +7352,7 @@ function unavailableImageText$6(block) {
|
|
|
7352
7352
|
}
|
|
7353
7353
|
function imageBlockToPart(block, images) {
|
|
7354
7354
|
let data = asString$29(block.data) || asString$29(block.base64);
|
|
7355
|
-
const source = isRecord$
|
|
7355
|
+
const source = isRecord$64(block.source) ? block.source : void 0;
|
|
7356
7356
|
if (!data && source) data = asString$29(source.data) || asString$29(source.base64);
|
|
7357
7357
|
let mimeType = asString$29(block.mimeType) || asString$29(block.mediaType) || (source ? asString$29(source.mimeType) || asString$29(source.mediaType) : void 0) || "image/png";
|
|
7358
7358
|
if (data?.startsWith("data:")) {
|
|
@@ -7377,8 +7377,8 @@ function contentToUserParts(content, images) {
|
|
|
7377
7377
|
if (typeof content === "string") return [{ text: sanitizeText$9(content) }];
|
|
7378
7378
|
if (!Array.isArray(content)) return [];
|
|
7379
7379
|
const parts = [];
|
|
7380
|
-
for (const block of content) if (isRecord$
|
|
7381
|
-
else if (isRecord$
|
|
7380
|
+
for (const block of content) if (isRecord$64(block) && block.type === "text" && typeof block.text === "string") parts.push({ text: sanitizeText$9(block.text) });
|
|
7381
|
+
else if (isRecord$64(block) && block.type === "image") {
|
|
7382
7382
|
const img = imageBlockToPart(block, images);
|
|
7383
7383
|
parts.push(img ?? { text: unavailableImageText$6(block) });
|
|
7384
7384
|
}
|
|
@@ -7393,7 +7393,7 @@ function toolResultImageParts(blocks, images) {
|
|
|
7393
7393
|
if (!Array.isArray(blocks)) return [];
|
|
7394
7394
|
const parts = [];
|
|
7395
7395
|
for (const block of blocks) {
|
|
7396
|
-
if (!isRecord$
|
|
7396
|
+
if (!isRecord$64(block)) continue;
|
|
7397
7397
|
if (block.type === "image") {
|
|
7398
7398
|
parts.push(imageBlockToPart(block, images) ?? { text: unavailableImageText$6(block) });
|
|
7399
7399
|
continue;
|
|
@@ -7405,7 +7405,7 @@ function toolResultImageParts(blocks, images) {
|
|
|
7405
7405
|
function toolResultText$9(blocks) {
|
|
7406
7406
|
if (!Array.isArray(blocks)) return "";
|
|
7407
7407
|
return blocks.map((block) => {
|
|
7408
|
-
if (!isRecord$
|
|
7408
|
+
if (!isRecord$64(block)) return "";
|
|
7409
7409
|
if (block.type === "text" && typeof block.text === "string") return sanitizeText$9(block.text);
|
|
7410
7410
|
if (block.type === "tool-result") return toolResultText$9(block.content);
|
|
7411
7411
|
if (block.type === "image") {
|
|
@@ -7419,9 +7419,9 @@ function replayBlockFor$1(message, index) {
|
|
|
7419
7419
|
const source = message.source;
|
|
7420
7420
|
if (!source || source.kind !== "model" || source.provider !== "antigravity") return void 0;
|
|
7421
7421
|
const state = source.replayState;
|
|
7422
|
-
if (!isRecord$
|
|
7422
|
+
if (!isRecord$64(state)) return void 0;
|
|
7423
7423
|
if (Array.isArray(state.blocks)) return state.blocks[index];
|
|
7424
|
-
const resp = isRecord$
|
|
7424
|
+
const resp = isRecord$64(state.response) ? state.response : void 0;
|
|
7425
7425
|
if (resp) {
|
|
7426
7426
|
if (Array.isArray(resp.outputItems)) return resp.outputItems[index];
|
|
7427
7427
|
if (Array.isArray(resp.blocks)) return resp.blocks[index];
|
|
@@ -7523,10 +7523,10 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
|
|
|
7523
7523
|
if (!Array.isArray(message.content)) return parts;
|
|
7524
7524
|
for (let index = 0; index < message.content.length; index++) {
|
|
7525
7525
|
const block = message.content[index];
|
|
7526
|
-
if (!isRecord$
|
|
7526
|
+
if (!isRecord$64(block)) continue;
|
|
7527
7527
|
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;
|
|
7528
7528
|
const replay = replayBlockFor$1(message, index);
|
|
7529
|
-
const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord$
|
|
7529
|
+
const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord$64) : [];
|
|
7530
7530
|
if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString$29(part.text) || "").join("") === sanitizeText$9(String(block.text || ""))) {
|
|
7531
7531
|
parts.push(...originalParts.map(replayPart));
|
|
7532
7532
|
continue;
|
|
@@ -7547,8 +7547,8 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
|
|
|
7547
7547
|
} else if (block.type === "tool-call") {
|
|
7548
7548
|
const toolId = String(block.id || "");
|
|
7549
7549
|
const toolName = String(block.name || "");
|
|
7550
|
-
const originalCall = originalParts.find((part) => isRecord$
|
|
7551
|
-
const wireId = asString$29((isRecord$
|
|
7550
|
+
const originalCall = originalParts.find((part) => isRecord$64(part.functionCall));
|
|
7551
|
+
const wireId = asString$29((isRecord$64(originalCall?.functionCall) ? originalCall.functionCall : void 0)?.id) || (toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(toolId, toolName) : originalCall ? void 0 : toolId || void 0);
|
|
7552
7552
|
toolCalls.set(toolId, {
|
|
7553
7553
|
name: toolName,
|
|
7554
7554
|
id: wireId
|
|
@@ -7600,7 +7600,7 @@ function convertMessages(options, model, runtimeModel, images = NO_RESOLVED_IMAG
|
|
|
7600
7600
|
continue;
|
|
7601
7601
|
}
|
|
7602
7602
|
const content = Array.isArray(message.content) ? message.content : [];
|
|
7603
|
-
const userParts = contentToUserParts(content.filter((b) => !isRecord$
|
|
7603
|
+
const userParts = contentToUserParts(content.filter((b) => !isRecord$64(b) || b.type !== "tool-result"), images);
|
|
7604
7604
|
if (role === "system") {
|
|
7605
7605
|
if (userParts.length) contents.push({
|
|
7606
7606
|
role: GEMINI_ROLE.user,
|
|
@@ -7612,7 +7612,7 @@ function convertMessages(options, model, runtimeModel, images = NO_RESOLVED_IMAG
|
|
|
7612
7612
|
role: GEMINI_ROLE.user,
|
|
7613
7613
|
parts: userParts
|
|
7614
7614
|
});
|
|
7615
|
-
for (const b of content) if (isRecord$
|
|
7615
|
+
for (const b of content) if (isRecord$64(b) && b.type === "tool-result") pushToolResult(contents, b, toolCalls, model, runtimeModel, images);
|
|
7616
7616
|
}
|
|
7617
7617
|
return contents;
|
|
7618
7618
|
}
|
|
@@ -7760,7 +7760,7 @@ const USAGE_FIELDS = [
|
|
|
7760
7760
|
"totalTokenCount"
|
|
7761
7761
|
];
|
|
7762
7762
|
function collectUsage(value, state) {
|
|
7763
|
-
if (!isRecord$
|
|
7763
|
+
if (!isRecord$64(value)) return;
|
|
7764
7764
|
for (const key of USAGE_FIELDS) {
|
|
7765
7765
|
const count = value[key];
|
|
7766
7766
|
if (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) continue;
|
|
@@ -7790,17 +7790,17 @@ function processStreamLine$4(line, state) {
|
|
|
7790
7790
|
}
|
|
7791
7791
|
if (!json) return [];
|
|
7792
7792
|
const chunk = safeJsonParse$9(json);
|
|
7793
|
-
if (!isRecord$
|
|
7794
|
-
const responseData = isRecord$
|
|
7795
|
-
const error = isRecord$
|
|
7793
|
+
if (!isRecord$64(chunk)) return [];
|
|
7794
|
+
const responseData = isRecord$64(chunk.response) ? chunk.response : chunk;
|
|
7795
|
+
const error = isRecord$64(chunk.error) ? chunk.error : isRecord$64(responseData.error) ? responseData.error : void 0;
|
|
7796
7796
|
if (error !== void 0) throw new LlmError$1(`Antigravity stream error: ${asString$29(error.message) ?? "unknown error"}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
|
|
7797
7797
|
const candidates = Array.isArray(responseData.candidates) ? responseData.candidates : [];
|
|
7798
|
-
const candidate = isRecord$
|
|
7799
|
-
const content = isRecord$
|
|
7798
|
+
const candidate = isRecord$64(candidates[0]) ? candidates[0] : void 0;
|
|
7799
|
+
const content = isRecord$64(candidate?.content) ? candidate.content : void 0;
|
|
7800
7800
|
const parts = Array.isArray(content?.parts) ? content.parts : [];
|
|
7801
7801
|
const out = [];
|
|
7802
7802
|
for (const part of parts) {
|
|
7803
|
-
if (!isRecord$
|
|
7803
|
+
if (!isRecord$64(part)) continue;
|
|
7804
7804
|
if (typeof part.text === "string" && part.text !== "") {
|
|
7805
7805
|
const isThinking = Boolean(part.thought);
|
|
7806
7806
|
const blockType = isThinking ? "reasoning" : "text";
|
|
@@ -7832,7 +7832,7 @@ function processStreamLine$4(line, state) {
|
|
|
7832
7832
|
index: state.currentBlock.index,
|
|
7833
7833
|
text: delta
|
|
7834
7834
|
});
|
|
7835
|
-
} else if (!isRecord$
|
|
7835
|
+
} else if (!isRecord$64(part.functionCall) && thoughtSignature(part)) {
|
|
7836
7836
|
if (state.replayBlocks.length === 0) {
|
|
7837
7837
|
const type = part.thought ? "reasoning" : "text";
|
|
7838
7838
|
state.blocks.push({
|
|
@@ -7856,12 +7856,12 @@ function processStreamLine$4(line, state) {
|
|
|
7856
7856
|
}
|
|
7857
7857
|
state.replayBlocks[state.replayBlocks.length - 1].parts.push(replayPart(part));
|
|
7858
7858
|
}
|
|
7859
|
-
if (isRecord$
|
|
7859
|
+
if (isRecord$64(part.functionCall)) {
|
|
7860
7860
|
out.push(...closeCurrentBlock(state));
|
|
7861
7861
|
const fc = part.functionCall;
|
|
7862
7862
|
const toolName = asString$29(fc.name) || "";
|
|
7863
7863
|
const toolId = asString$29(fc.id) || sanitizeToolCallId("", toolName);
|
|
7864
|
-
const argsText = JSON.stringify(isRecord$
|
|
7864
|
+
const argsText = JSON.stringify(isRecord$64(fc.args) ? fc.args : {});
|
|
7865
7865
|
const index = state.blocks.length;
|
|
7866
7866
|
const block = {
|
|
7867
7867
|
type: "tool-call",
|
|
@@ -7900,7 +7900,7 @@ function processStreamLine$4(line, state) {
|
|
|
7900
7900
|
if (responseData !== chunk) collectUsage(responseData.usageMetadata, state);
|
|
7901
7901
|
const finishMessage = asString$29(candidate?.finishMessage);
|
|
7902
7902
|
if (finishMessage) state.finishMessage = finishMessage;
|
|
7903
|
-
const blockReason = asString$29((isRecord$
|
|
7903
|
+
const blockReason = asString$29((isRecord$64(responseData.promptFeedback) ? responseData.promptFeedback : void 0)?.blockReason);
|
|
7904
7904
|
const finishReason = asString$29(candidate?.finishReason) || asString$29(responseData.finishReason) || (blockReason ? `PROMPT_BLOCKED:${blockReason}` : void 0);
|
|
7905
7905
|
if (finishReason) {
|
|
7906
7906
|
state.finishReason = finishReason;
|
|
@@ -14084,7 +14084,7 @@ async function compactionCandidates(ctx) {
|
|
|
14084
14084
|
};
|
|
14085
14085
|
}))).filter((provider) => provider.models.length > 0) };
|
|
14086
14086
|
}
|
|
14087
|
-
function isRecord$
|
|
14087
|
+
function isRecord$63(value) {
|
|
14088
14088
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14089
14089
|
}
|
|
14090
14090
|
function readPreferencesUpdate(value, current) {
|
|
@@ -14134,7 +14134,7 @@ function readPreferencesUpdate(value, current) {
|
|
|
14134
14134
|
patch.subagentModelsByMainModel = value.subagentModelsByMainModel;
|
|
14135
14135
|
}
|
|
14136
14136
|
if ("contextWindowOverrides" in value) {
|
|
14137
|
-
if (!isRecord$
|
|
14137
|
+
if (!isRecord$63(value.contextWindowOverrides)) throw new PreferenceError("contextWindowOverrides must be an object.");
|
|
14138
14138
|
const overrides = {};
|
|
14139
14139
|
for (const [model, contextWindow] of Object.entries(value.contextWindowOverrides)) {
|
|
14140
14140
|
if (!isCodexModelId(model)) throw new PreferenceError("Unknown Codex model for a context window override.");
|
|
@@ -18634,11 +18634,11 @@ function commandCodeHeaders(apiKey, extra = {}) {
|
|
|
18634
18634
|
function timeoutSignal$5(signal, ms) {
|
|
18635
18635
|
return signal ? AbortSignal.any([signal, AbortSignal.timeout(ms)]) : AbortSignal.timeout(ms);
|
|
18636
18636
|
}
|
|
18637
|
-
function isRecord$
|
|
18637
|
+
function isRecord$62(value) {
|
|
18638
18638
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18639
18639
|
}
|
|
18640
18640
|
function asRecord$16(value) {
|
|
18641
|
-
return isRecord$
|
|
18641
|
+
return isRecord$62(value) ? value : void 0;
|
|
18642
18642
|
}
|
|
18643
18643
|
function asString$28(value) {
|
|
18644
18644
|
if (typeof value === "string" && value.trim() !== "") return value;
|
|
@@ -18682,7 +18682,7 @@ function deepValue(value, keys, depth = 0) {
|
|
|
18682
18682
|
}
|
|
18683
18683
|
return;
|
|
18684
18684
|
}
|
|
18685
|
-
if (!isRecord$
|
|
18685
|
+
if (!isRecord$62(value)) return void 0;
|
|
18686
18686
|
for (const key of keys) if (value[key] !== void 0 && value[key] !== null) return value[key];
|
|
18687
18687
|
for (const nested of Object.values(value)) {
|
|
18688
18688
|
const hit = deepValue(nested, keys, depth + 1);
|
|
@@ -18696,7 +18696,7 @@ function collectRecords(value, keys, depth = 0, out = []) {
|
|
|
18696
18696
|
for (const entry of value) collectRecords(entry, keys, depth + 1, out);
|
|
18697
18697
|
return out;
|
|
18698
18698
|
}
|
|
18699
|
-
if (!isRecord$
|
|
18699
|
+
if (!isRecord$62(value)) return out;
|
|
18700
18700
|
if (keys.some((key) => value[key] !== void 0)) out.push(value);
|
|
18701
18701
|
for (const nested of Object.values(value)) collectRecords(nested, keys, depth + 1, out);
|
|
18702
18702
|
return out;
|
|
@@ -19506,7 +19506,7 @@ function buildModelOptions$2(catalog, enabledModelIds, overrides) {
|
|
|
19506
19506
|
*
|
|
19507
19507
|
* https://commandcode.ai/blog/command-code-provider-api
|
|
19508
19508
|
*/
|
|
19509
|
-
function isRecord$
|
|
19509
|
+
function isRecord$61(value) {
|
|
19510
19510
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19511
19511
|
}
|
|
19512
19512
|
function asString$27(value) {
|
|
@@ -19546,17 +19546,17 @@ const SUPPORTED_IMAGE_MEDIA_TYPES$4 = /* @__PURE__ */ new Set([
|
|
|
19546
19546
|
]);
|
|
19547
19547
|
function attachmentOf$4(block) {
|
|
19548
19548
|
const attachment = block.attachment;
|
|
19549
|
-
if (!isRecord$
|
|
19549
|
+
if (!isRecord$61(attachment)) return void 0;
|
|
19550
19550
|
return typeof attachment.attachmentId === "string" ? attachment : void 0;
|
|
19551
19551
|
}
|
|
19552
19552
|
function attachmentLabel$5(block) {
|
|
19553
|
-
const attachment = isRecord$
|
|
19553
|
+
const attachment = isRecord$61(block.attachment) ? block.attachment : void 0;
|
|
19554
19554
|
return asString$27(attachment?.name) || asString$27(attachment?.attachmentId);
|
|
19555
19555
|
}
|
|
19556
19556
|
function collectImageRefs$2(content, refs) {
|
|
19557
19557
|
if (!Array.isArray(content)) return;
|
|
19558
19558
|
for (const block of content) {
|
|
19559
|
-
if (!isRecord$
|
|
19559
|
+
if (!isRecord$61(block)) continue;
|
|
19560
19560
|
if (block.type === "image") {
|
|
19561
19561
|
const attachment = attachmentOf$4(block);
|
|
19562
19562
|
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
@@ -19577,7 +19577,7 @@ function requestImageBytes$1(block) {
|
|
|
19577
19577
|
function collectRequestImageBytes$1(content, lengths) {
|
|
19578
19578
|
if (!Array.isArray(content)) return;
|
|
19579
19579
|
for (const block of content) {
|
|
19580
|
-
if (!isRecord$
|
|
19580
|
+
if (!isRecord$61(block)) continue;
|
|
19581
19581
|
if (block.type === "tool-result") {
|
|
19582
19582
|
collectRequestImageBytes$1(block.content, lengths);
|
|
19583
19583
|
continue;
|
|
@@ -19613,7 +19613,7 @@ function offloadOldestRequestImages$2(options) {
|
|
|
19613
19613
|
let replaced = false;
|
|
19614
19614
|
return {
|
|
19615
19615
|
content: content.map((block) => {
|
|
19616
|
-
if (remaining.count === 0 || !isRecord$
|
|
19616
|
+
if (remaining.count === 0 || !isRecord$61(block)) return block;
|
|
19617
19617
|
if (block.type === "image") {
|
|
19618
19618
|
if (requestImageBytes$1(block) === void 0) return block;
|
|
19619
19619
|
remaining.count -= 1;
|
|
@@ -19685,7 +19685,7 @@ function unavailableImageText$5(block) {
|
|
|
19685
19685
|
}
|
|
19686
19686
|
function imageBlockToInline$3(block, images) {
|
|
19687
19687
|
let data = asString$27(block.data) || asString$27(block.base64);
|
|
19688
|
-
const source = isRecord$
|
|
19688
|
+
const source = isRecord$61(block.source) ? block.source : void 0;
|
|
19689
19689
|
if (!data && source) data = asString$27(source.data) || asString$27(source.base64);
|
|
19690
19690
|
let mediaType = asString$27(block.mimeType) || asString$27(block.mediaType) || (source ? asString$27(source.mimeType) || asString$27(source.mediaType) : void 0) || "image/png";
|
|
19691
19691
|
if (data?.startsWith("data:")) {
|
|
@@ -19711,7 +19711,7 @@ function textOf$9(content) {
|
|
|
19711
19711
|
if (!Array.isArray(content)) return "";
|
|
19712
19712
|
const parts = [];
|
|
19713
19713
|
for (const block of content) {
|
|
19714
|
-
if (!isRecord$
|
|
19714
|
+
if (!isRecord$61(block)) continue;
|
|
19715
19715
|
if (block.type === "text" && typeof block.text === "string") parts.push(sanitizeText$8(block.text));
|
|
19716
19716
|
else if (block.type === "tool-result") parts.push(textOf$9(block.content));
|
|
19717
19717
|
}
|
|
@@ -19720,7 +19720,7 @@ function textOf$9(content) {
|
|
|
19720
19720
|
function toolResultText$8(blocks) {
|
|
19721
19721
|
if (!Array.isArray(blocks)) return "";
|
|
19722
19722
|
return blocks.map((block) => {
|
|
19723
|
-
if (!isRecord$
|
|
19723
|
+
if (!isRecord$61(block)) return "";
|
|
19724
19724
|
if (block.type === "text" && typeof block.text === "string") return sanitizeText$8(block.text);
|
|
19725
19725
|
if (block.type === "tool-result") return toolResultText$8(block.content);
|
|
19726
19726
|
if (block.type === "image") return `[image: ${attachmentLabel$5(block) ?? "attached image"}]`;
|
|
@@ -19738,7 +19738,7 @@ function toolResultBlocks$2(blocks, images) {
|
|
|
19738
19738
|
const out = [];
|
|
19739
19739
|
let hasImage = false;
|
|
19740
19740
|
for (const block of blocks) {
|
|
19741
|
-
if (!isRecord$
|
|
19741
|
+
if (!isRecord$61(block)) continue;
|
|
19742
19742
|
if (block.type === "text" && typeof block.text === "string") {
|
|
19743
19743
|
out.push({
|
|
19744
19744
|
type: "text",
|
|
@@ -19787,7 +19787,7 @@ function toolResultImageBlocks$5(blocks, images) {
|
|
|
19787
19787
|
if (!Array.isArray(blocks)) return [];
|
|
19788
19788
|
const out = [];
|
|
19789
19789
|
for (const block of blocks) {
|
|
19790
|
-
if (!isRecord$
|
|
19790
|
+
if (!isRecord$61(block)) continue;
|
|
19791
19791
|
if (block.type === "image") {
|
|
19792
19792
|
const inline = imageBlockToInline$3(block, images);
|
|
19793
19793
|
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$4.has(inline.mediaType)) out.push({
|
|
@@ -19831,7 +19831,7 @@ function nonSystemMessages$8(options) {
|
|
|
19831
19831
|
}
|
|
19832
19832
|
/** Drop the JSON-Schema keywords provider gateways reject or ignore. */
|
|
19833
19833
|
function stripMetaSchema$2(schema) {
|
|
19834
|
-
if (!isRecord$
|
|
19834
|
+
if (!isRecord$61(schema)) return {
|
|
19835
19835
|
type: "object",
|
|
19836
19836
|
properties: {}
|
|
19837
19837
|
};
|
|
@@ -19848,7 +19848,7 @@ function openAIUserContent$4(message, images) {
|
|
|
19848
19848
|
const parts = [];
|
|
19849
19849
|
let hasImage = false;
|
|
19850
19850
|
for (const block of message.content) {
|
|
19851
|
-
if (!isRecord$
|
|
19851
|
+
if (!isRecord$61(block)) continue;
|
|
19852
19852
|
if (block.type === "text" && typeof block.text === "string") {
|
|
19853
19853
|
const text = sanitizeText$8(block.text);
|
|
19854
19854
|
if (text !== "") parts.push({
|
|
@@ -19876,7 +19876,7 @@ function openAIAssistantContent$4(message) {
|
|
|
19876
19876
|
const textParts = [];
|
|
19877
19877
|
const toolCalls = [];
|
|
19878
19878
|
for (const block of message.content) {
|
|
19879
|
-
if (!isRecord$
|
|
19879
|
+
if (!isRecord$61(block)) continue;
|
|
19880
19880
|
if (block.type === "text" && typeof block.text === "string") textParts.push(sanitizeText$8(block.text));
|
|
19881
19881
|
else if (block.type === "tool-call" && typeof block.name === "string") toolCalls.push({
|
|
19882
19882
|
id: typeof block.id === "string" && block.id !== "" ? block.id : `call_${toolCalls.length}`,
|
|
@@ -19908,7 +19908,7 @@ function buildOpenAIRequest$1(options, images = NO_RESOLVED_IMAGES$4) {
|
|
|
19908
19908
|
while (index < conversation.length && isToolResultMessage$8(conversation[index])) {
|
|
19909
19909
|
const current = conversation[index];
|
|
19910
19910
|
const block = current.content[0];
|
|
19911
|
-
const callId = isRecord$
|
|
19911
|
+
const callId = isRecord$61(block) && typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
19912
19912
|
messages.push({
|
|
19913
19913
|
role: "tool",
|
|
19914
19914
|
tool_call_id: callId,
|
|
@@ -19969,7 +19969,7 @@ function anthropicUserContent$3(message, images) {
|
|
|
19969
19969
|
if (!Array.isArray(message.content)) return [];
|
|
19970
19970
|
const blocks = [];
|
|
19971
19971
|
for (const block of message.content) {
|
|
19972
|
-
if (!isRecord$
|
|
19972
|
+
if (!isRecord$61(block)) continue;
|
|
19973
19973
|
if (block.type === "text" && typeof block.text === "string") {
|
|
19974
19974
|
const text = sanitizeText$8(block.text);
|
|
19975
19975
|
if (text !== "") blocks.push({
|
|
@@ -20006,7 +20006,7 @@ function anthropicUserContent$3(message, images) {
|
|
|
20006
20006
|
function anthropicAssistantContent$3(message) {
|
|
20007
20007
|
const blocks = [];
|
|
20008
20008
|
for (const block of message.content) {
|
|
20009
|
-
if (!isRecord$
|
|
20009
|
+
if (!isRecord$61(block)) continue;
|
|
20010
20010
|
if (block.type === "text" && typeof block.text === "string") {
|
|
20011
20011
|
const text = sanitizeText$8(block.text);
|
|
20012
20012
|
if (text !== "") blocks.push({
|
|
@@ -20019,7 +20019,7 @@ function anthropicAssistantContent$3(message) {
|
|
|
20019
20019
|
type: "tool_use",
|
|
20020
20020
|
id: typeof block.id === "string" && block.id !== "" ? block.id : `toolu_${blocks.length}`,
|
|
20021
20021
|
name: block.name,
|
|
20022
|
-
input: isRecord$
|
|
20022
|
+
input: isRecord$61(parsed) ? parsed : {}
|
|
20023
20023
|
});
|
|
20024
20024
|
}
|
|
20025
20025
|
}
|
|
@@ -20050,7 +20050,7 @@ function mergeAnthropicMessages$3(entries) {
|
|
|
20050
20050
|
return merged;
|
|
20051
20051
|
}
|
|
20052
20052
|
/** Reasoning budget a thinking-enabled request may spend, given its output cap. */
|
|
20053
|
-
function thinkingBudgetFor
|
|
20053
|
+
function thinkingBudgetFor(effort, maxTokens) {
|
|
20054
20054
|
if (effort === void 0 || effort === "") return void 0;
|
|
20055
20055
|
const requested = anthropicThinkingBudget(effort);
|
|
20056
20056
|
if (requested === void 0 || requested === null) return void 0;
|
|
@@ -20075,7 +20075,7 @@ function buildAnthropicRequest$1(options, images = NO_RESOLVED_IMAGES$4) {
|
|
|
20075
20075
|
}
|
|
20076
20076
|
const system = leadingSystemText$8(options);
|
|
20077
20077
|
const maxTokens = options.maxTokens ?? maxOutputTokensFor$6(options.model);
|
|
20078
|
-
const budget = thinkingBudgetFor
|
|
20078
|
+
const budget = thinkingBudgetFor(wireReasoningEffort(options.reasoningEffort === void 0 ? void 0 : String(options.reasoningEffort)), maxTokens);
|
|
20079
20079
|
return {
|
|
20080
20080
|
model: options.model,
|
|
20081
20081
|
max_tokens: maxTokens,
|
|
@@ -20113,7 +20113,7 @@ function responsesUserContent(message, images) {
|
|
|
20113
20113
|
if (!Array.isArray(message.content)) return [];
|
|
20114
20114
|
const parts = [];
|
|
20115
20115
|
for (const block of message.content) {
|
|
20116
|
-
if (!isRecord$
|
|
20116
|
+
if (!isRecord$61(block)) continue;
|
|
20117
20117
|
if (block.type === "text" && typeof block.text === "string") {
|
|
20118
20118
|
const text = sanitizeText$8(block.text);
|
|
20119
20119
|
if (text !== "") parts.push({
|
|
@@ -20138,7 +20138,7 @@ function responsesToolResultImageBlocks(blocks, images) {
|
|
|
20138
20138
|
if (!Array.isArray(blocks)) return [];
|
|
20139
20139
|
const out = [];
|
|
20140
20140
|
for (const block of blocks) {
|
|
20141
|
-
if (!isRecord$
|
|
20141
|
+
if (!isRecord$61(block)) continue;
|
|
20142
20142
|
if (block.type === "image") {
|
|
20143
20143
|
const inline = imageBlockToInline$3(block, images);
|
|
20144
20144
|
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$4.has(inline.mediaType)) out.push({
|
|
@@ -20165,8 +20165,8 @@ function buildResponsesRequest(options, images = NO_RESOLVED_IMAGES$4) {
|
|
|
20165
20165
|
const imageBlocks = [];
|
|
20166
20166
|
while (index < conversation.length && isToolResultMessage$8(conversation[index])) {
|
|
20167
20167
|
const current = conversation[index];
|
|
20168
|
-
const toolResult = Array.isArray(current.content) ? current.content.find((b) => isRecord$
|
|
20169
|
-
const callId = (isRecord$
|
|
20168
|
+
const toolResult = Array.isArray(current.content) ? current.content.find((b) => isRecord$61(b) && b.type === "tool-result") : void 0;
|
|
20169
|
+
const callId = (isRecord$61(toolResult) && typeof toolResult.toolCallId === "string" ? toolResult.toolCallId : "") || (typeof current.source?.callId === "string" ? current.source.callId : "");
|
|
20170
20170
|
input.push({
|
|
20171
20171
|
type: "function_call_output",
|
|
20172
20172
|
call_id: callId,
|
|
@@ -20189,7 +20189,7 @@ function buildResponsesRequest(options, images = NO_RESOLVED_IMAGES$4) {
|
|
|
20189
20189
|
content
|
|
20190
20190
|
});
|
|
20191
20191
|
for (const call of toolCalls) {
|
|
20192
|
-
const fn = isRecord$
|
|
20192
|
+
const fn = isRecord$61(call.function) ? call.function : void 0;
|
|
20193
20193
|
input.push({
|
|
20194
20194
|
type: "function_call",
|
|
20195
20195
|
call_id: call.id,
|
|
@@ -20312,9 +20312,9 @@ function processOpenAIStreamLine$1(line, state) {
|
|
|
20312
20312
|
}
|
|
20313
20313
|
if (payload === "") return [];
|
|
20314
20314
|
const chunk = safeJsonParse$8(payload);
|
|
20315
|
-
if (!isRecord$
|
|
20315
|
+
if (!isRecord$61(chunk)) return [];
|
|
20316
20316
|
const out = [];
|
|
20317
|
-
if (isRecord$
|
|
20317
|
+
if (isRecord$61(chunk.error)) {
|
|
20318
20318
|
const message = asString$27(chunk.error.message) ?? "unknown error";
|
|
20319
20319
|
state.streamError = {
|
|
20320
20320
|
vocabulary: "openai",
|
|
@@ -20323,20 +20323,20 @@ function processOpenAIStreamLine$1(line, state) {
|
|
|
20323
20323
|
};
|
|
20324
20324
|
throw new LlmError$1(`Command Code stream error: ${message}`, isContextOverflow(chunk.error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
|
|
20325
20325
|
}
|
|
20326
|
-
const usage = isRecord$
|
|
20326
|
+
const usage = isRecord$61(chunk.usage) ? chunk.usage : void 0;
|
|
20327
20327
|
if (usage) {
|
|
20328
20328
|
state.sawUsage = true;
|
|
20329
20329
|
const prompt = numberOr$9(usage.prompt_tokens, 0);
|
|
20330
|
-
const details = isRecord$
|
|
20330
|
+
const details = isRecord$61(usage.prompt_tokens_details) ? usage.prompt_tokens_details : void 0;
|
|
20331
20331
|
const cached = details ? numberOr$9(details.cached_tokens, 0) : 0;
|
|
20332
20332
|
state.inputTokens = Math.max(0, prompt - cached);
|
|
20333
20333
|
state.cacheReadTokens = cached;
|
|
20334
20334
|
state.outputTokens = numberOr$9(usage.completion_tokens, state.outputTokens);
|
|
20335
|
-
if (isRecord$
|
|
20335
|
+
if (isRecord$61(usage.completion_tokens_details)) state.reasoningTokens = numberOr$9(usage.completion_tokens_details.reasoning_tokens, state.reasoningTokens);
|
|
20336
20336
|
}
|
|
20337
20337
|
const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
|
|
20338
|
-
const choice = isRecord$
|
|
20339
|
-
const delta = isRecord$
|
|
20338
|
+
const choice = isRecord$61(choices[0]) ? choices[0] : void 0;
|
|
20339
|
+
const delta = isRecord$61(choice?.delta) ? choice.delta : void 0;
|
|
20340
20340
|
if (delta) {
|
|
20341
20341
|
const reasoning = asString$27(delta.reasoning_content) ?? asString$27(delta.reasoning);
|
|
20342
20342
|
if (reasoning !== void 0 && reasoning !== "") {
|
|
@@ -20364,7 +20364,7 @@ function processOpenAIStreamLine$1(line, state) {
|
|
|
20364
20364
|
}
|
|
20365
20365
|
const toolDeltas = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];
|
|
20366
20366
|
for (const entry of toolDeltas) {
|
|
20367
|
-
if (!isRecord$
|
|
20367
|
+
if (!isRecord$61(entry)) continue;
|
|
20368
20368
|
out.push(...applyOpenAIToolDelta$1(entry, state));
|
|
20369
20369
|
}
|
|
20370
20370
|
}
|
|
@@ -20378,7 +20378,7 @@ function processOpenAIStreamLine$1(line, state) {
|
|
|
20378
20378
|
}
|
|
20379
20379
|
function applyOpenAIToolDelta$1(entry, state) {
|
|
20380
20380
|
const wireIndex = typeof entry.index === "number" ? entry.index : 0;
|
|
20381
|
-
const fn = isRecord$
|
|
20381
|
+
const fn = isRecord$61(entry.function) ? entry.function : {};
|
|
20382
20382
|
const out = [];
|
|
20383
20383
|
let call = state.toolCalls.get(wireIndex);
|
|
20384
20384
|
if (call === void 0) {
|
|
@@ -20436,12 +20436,12 @@ function processAnthropicStreamLine$1(line, state) {
|
|
|
20436
20436
|
const payload = trimmed.slice(5).trim();
|
|
20437
20437
|
if (payload === "" || payload === "[DONE]") return [];
|
|
20438
20438
|
const event = safeJsonParse$8(payload);
|
|
20439
|
-
if (!isRecord$
|
|
20439
|
+
if (!isRecord$61(event)) return [];
|
|
20440
20440
|
const type = asString$27(event.type);
|
|
20441
20441
|
const out = [];
|
|
20442
20442
|
if (type === "message_start") {
|
|
20443
|
-
const message = isRecord$
|
|
20444
|
-
const usage = message && isRecord$
|
|
20443
|
+
const message = isRecord$61(event.message) ? event.message : void 0;
|
|
20444
|
+
const usage = message && isRecord$61(message.usage) ? message.usage : void 0;
|
|
20445
20445
|
if (usage) {
|
|
20446
20446
|
state.sawUsage = true;
|
|
20447
20447
|
state.inputTokens = numberOr$9(usage.input_tokens, 0);
|
|
@@ -20455,7 +20455,7 @@ function processAnthropicStreamLine$1(line, state) {
|
|
|
20455
20455
|
}
|
|
20456
20456
|
if (type === "content_block_start") {
|
|
20457
20457
|
const contentIndex = numberOr$9(event.index, 0);
|
|
20458
|
-
const block = isRecord$
|
|
20458
|
+
const block = isRecord$61(event.content_block) ? event.content_block : {};
|
|
20459
20459
|
const blockType = asString$27(block.type);
|
|
20460
20460
|
out.push(...closeCurrent$6(state));
|
|
20461
20461
|
if (blockType === "tool_use") {
|
|
@@ -20505,7 +20505,7 @@ function processAnthropicStreamLine$1(line, state) {
|
|
|
20505
20505
|
}
|
|
20506
20506
|
if (type === "content_block_delta") {
|
|
20507
20507
|
const contentIndex = numberOr$9(event.index, 0);
|
|
20508
|
-
const delta = isRecord$
|
|
20508
|
+
const delta = isRecord$61(event.delta) ? event.delta : {};
|
|
20509
20509
|
const deltaType = asString$27(delta.type);
|
|
20510
20510
|
if (deltaType === "input_json_delta") {
|
|
20511
20511
|
const pending = state.toolCalls.get(contentIndex);
|
|
@@ -20578,10 +20578,10 @@ function processAnthropicStreamLine$1(line, state) {
|
|
|
20578
20578
|
return out;
|
|
20579
20579
|
}
|
|
20580
20580
|
if (type === "message_delta") {
|
|
20581
|
-
const delta = isRecord$
|
|
20581
|
+
const delta = isRecord$61(event.delta) ? event.delta : void 0;
|
|
20582
20582
|
const stop = delta ? asString$27(delta.stop_reason) : void 0;
|
|
20583
20583
|
if (stop !== void 0 && stop !== "") state.finishReason = stop;
|
|
20584
|
-
const usage = isRecord$
|
|
20584
|
+
const usage = isRecord$61(event.usage) ? event.usage : void 0;
|
|
20585
20585
|
if (usage) {
|
|
20586
20586
|
state.sawUsage = true;
|
|
20587
20587
|
state.outputTokens = numberOr$9(usage.output_tokens, state.outputTokens);
|
|
@@ -20593,7 +20593,7 @@ function processAnthropicStreamLine$1(line, state) {
|
|
|
20593
20593
|
return closeStream$6(state);
|
|
20594
20594
|
}
|
|
20595
20595
|
if (type === "error") {
|
|
20596
|
-
const error = isRecord$
|
|
20596
|
+
const error = isRecord$61(event.error) ? event.error : {};
|
|
20597
20597
|
const message = asString$27(error.message) ?? "unknown error";
|
|
20598
20598
|
state.streamError = {
|
|
20599
20599
|
vocabulary: "anthropic",
|
|
@@ -20639,7 +20639,7 @@ function processResponsesStreamLine(line, state) {
|
|
|
20639
20639
|
} catch {
|
|
20640
20640
|
return [];
|
|
20641
20641
|
}
|
|
20642
|
-
if (!isRecord$
|
|
20642
|
+
if (!isRecord$61(parsed)) return [];
|
|
20643
20643
|
const type = typeof parsed.type === "string" ? parsed.type : "";
|
|
20644
20644
|
if (type === "response.output_text.delta") {
|
|
20645
20645
|
const delta = typeof parsed.delta === "string" ? parsed.delta : "";
|
|
@@ -20666,7 +20666,7 @@ function processResponsesStreamLine(line, state) {
|
|
|
20666
20666
|
}];
|
|
20667
20667
|
}
|
|
20668
20668
|
if (type === "response.output_item.added") {
|
|
20669
|
-
const item = isRecord$
|
|
20669
|
+
const item = isRecord$61(parsed.item) ? parsed.item : null;
|
|
20670
20670
|
if (item === null || item.type !== "function_call") return [];
|
|
20671
20671
|
return startResponsesToolCall(state, parsed, item);
|
|
20672
20672
|
}
|
|
@@ -20690,11 +20690,11 @@ function processResponsesStreamLine(line, state) {
|
|
|
20690
20690
|
return [];
|
|
20691
20691
|
}
|
|
20692
20692
|
if (type === "response.completed" || type === "response.incomplete") {
|
|
20693
|
-
const response = isRecord$
|
|
20693
|
+
const response = isRecord$61(parsed.response) ? parsed.response : null;
|
|
20694
20694
|
if (response !== null) {
|
|
20695
20695
|
if (response.status === "failed") {
|
|
20696
20696
|
state.done = true;
|
|
20697
|
-
const errorObj = isRecord$
|
|
20697
|
+
const errorObj = isRecord$61(response.error) ? response.error : null;
|
|
20698
20698
|
const detail = errorObj && typeof errorObj.message === "string" ? errorObj.message : typeof response.error === "string" ? response.error : "";
|
|
20699
20699
|
state.streamError = {
|
|
20700
20700
|
vocabulary: "responses",
|
|
@@ -20707,7 +20707,7 @@ function processResponsesStreamLine(line, state) {
|
|
|
20707
20707
|
}
|
|
20708
20708
|
state.done = true;
|
|
20709
20709
|
if (type === "response.incomplete") {
|
|
20710
|
-
const details = response && isRecord$
|
|
20710
|
+
const details = response && isRecord$61(response.incomplete_details) ? response.incomplete_details : null;
|
|
20711
20711
|
const reason = details && typeof details.reason === "string" ? details.reason : "";
|
|
20712
20712
|
state.finishReason = reason === "max_output_tokens" || reason === "length" || reason === "max_tokens" ? "length" : reason || "length";
|
|
20713
20713
|
} else state.finishReason = "stop";
|
|
@@ -20715,8 +20715,8 @@ function processResponsesStreamLine(line, state) {
|
|
|
20715
20715
|
}
|
|
20716
20716
|
if (type === "response.failed" || type === "error") {
|
|
20717
20717
|
state.done = true;
|
|
20718
|
-
const errorObj = isRecord$
|
|
20719
|
-
const detail = (typeof parsed.message === "string" ? parsed.message : "") || (errorObj && typeof errorObj.message === "string" ? errorObj.message : "") || (isRecord$
|
|
20718
|
+
const errorObj = isRecord$61(parsed.error) ? parsed.error : isRecord$61(parsed.response) && isRecord$61(parsed.response.error) ? parsed.response.error : null;
|
|
20719
|
+
const detail = (typeof parsed.message === "string" ? parsed.message : "") || (errorObj && typeof errorObj.message === "string" ? errorObj.message : "") || (isRecord$61(parsed.response) && typeof parsed.response.error === "string" ? parsed.response.error : typeof parsed.error === "string" ? parsed.error : "");
|
|
20720
20720
|
state.streamError = {
|
|
20721
20721
|
vocabulary: "responses",
|
|
20722
20722
|
error: errorObj,
|
|
@@ -20804,15 +20804,15 @@ function responsesToolCall(state, key) {
|
|
|
20804
20804
|
for (const call of state.toolCalls.values()) if (call.id === toToolCallId(key)) return call;
|
|
20805
20805
|
}
|
|
20806
20806
|
function readResponsesUsage(response, state) {
|
|
20807
|
-
const usage = isRecord$
|
|
20807
|
+
const usage = isRecord$61(response.usage) ? response.usage : null;
|
|
20808
20808
|
if (usage === null) return;
|
|
20809
|
-
const cached = isRecord$
|
|
20810
|
-
const written = isRecord$
|
|
20809
|
+
const cached = isRecord$61(usage.input_tokens_details) ? numberOrZero(usage.input_tokens_details.cached_tokens) : 0;
|
|
20810
|
+
const written = isRecord$61(usage.input_tokens_details) ? numberOrZero(usage.input_tokens_details.cache_write_tokens) : 0;
|
|
20811
20811
|
state.inputTokens = Math.max(0, numberOrZero(usage.input_tokens) - cached - written);
|
|
20812
20812
|
state.cacheReadTokens = cached;
|
|
20813
20813
|
state.cacheWriteTokens = written;
|
|
20814
20814
|
state.outputTokens = numberOrZero(usage.output_tokens);
|
|
20815
|
-
const outputDetails = isRecord$
|
|
20815
|
+
const outputDetails = isRecord$61(usage.output_tokens_details) ? usage.output_tokens_details : null;
|
|
20816
20816
|
if (outputDetails !== null) state.reasoningTokens = numberOrZero(outputDetails.reasoning_tokens);
|
|
20817
20817
|
state.sawUsage = true;
|
|
20818
20818
|
}
|
|
@@ -20900,7 +20900,7 @@ const ANTHROPIC_IN_BAND_STATUS = {
|
|
|
20900
20900
|
* Anything not recognized keeps the mapper's verdict.
|
|
20901
20901
|
*/
|
|
20902
20902
|
function inBandResponsesCode(error, message) {
|
|
20903
|
-
const fields = isRecord$
|
|
20903
|
+
const fields = isRecord$60(error) ? error : {};
|
|
20904
20904
|
const rawCode = (asString$26(fields.code) ?? asString$26(fields.type) ?? "").toLowerCase();
|
|
20905
20905
|
const text = message.toLowerCase();
|
|
20906
20906
|
if (text.includes("rate limit") || rawCode === "rate_limit" || rawCode === "rate_limit_exceeded") return "RATE_LIMIT";
|
|
@@ -20959,13 +20959,13 @@ function reclassifyInBandResponsesError(thrown, rawError, message, classify) {
|
|
|
20959
20959
|
}
|
|
20960
20960
|
/** The wire `error` object of an in-band event, read defensively. */
|
|
20961
20961
|
function readErrorType(error) {
|
|
20962
|
-
if (!isRecord$
|
|
20962
|
+
if (!isRecord$60(error)) return null;
|
|
20963
20963
|
return typeof error.type === "string" ? error.type : null;
|
|
20964
20964
|
}
|
|
20965
20965
|
function asString$26(value) {
|
|
20966
20966
|
return typeof value === "string" ? value : void 0;
|
|
20967
20967
|
}
|
|
20968
|
-
function isRecord$
|
|
20968
|
+
function isRecord$60(value) {
|
|
20969
20969
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20970
20970
|
}
|
|
20971
20971
|
//#endregion
|
|
@@ -24190,14 +24190,14 @@ const IN_BAND_SERVER = [
|
|
|
24190
24190
|
function isAbort$3(error, signal) {
|
|
24191
24191
|
return signal?.aborted === true || error instanceof Error && error.name === "AbortError";
|
|
24192
24192
|
}
|
|
24193
|
-
function isRecord$
|
|
24193
|
+
function isRecord$59(value) {
|
|
24194
24194
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24195
24195
|
}
|
|
24196
24196
|
function asString$25(value) {
|
|
24197
24197
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
24198
24198
|
}
|
|
24199
24199
|
function attachmentLabel$4(block) {
|
|
24200
|
-
const attachment = isRecord$
|
|
24200
|
+
const attachment = isRecord$59(block.attachment) ? block.attachment : void 0;
|
|
24201
24201
|
return asString$25(attachment?.name) || asString$25(attachment?.attachmentId);
|
|
24202
24202
|
}
|
|
24203
24203
|
function unavailableImageText$4(block) {
|
|
@@ -24233,7 +24233,7 @@ async function processMessageContent(content, model, attachments, signal) {
|
|
|
24233
24233
|
textParts.push(part);
|
|
24234
24234
|
continue;
|
|
24235
24235
|
}
|
|
24236
|
-
if (!isRecord$
|
|
24236
|
+
if (!isRecord$59(part)) continue;
|
|
24237
24237
|
if (part.type === "text") {
|
|
24238
24238
|
if (typeof part.text === "string" && part.text !== "") textParts.push(part.text);
|
|
24239
24239
|
continue;
|
|
@@ -24262,7 +24262,7 @@ async function processMessageContent(content, model, attachments, signal) {
|
|
|
24262
24262
|
continue;
|
|
24263
24263
|
}
|
|
24264
24264
|
const inline = part.source;
|
|
24265
|
-
if (isRecord$
|
|
24265
|
+
if (isRecord$59(inline)) {
|
|
24266
24266
|
const data = inline.data;
|
|
24267
24267
|
if (typeof data === "string" && data !== "") {
|
|
24268
24268
|
images.push(encodeImage(data, asMediaType(inline.mediaType)));
|
|
@@ -24303,7 +24303,7 @@ async function toOllamaRequest(options, attachments, signal, declared) {
|
|
|
24303
24303
|
const toolResultBlocks = message.content.filter((b) => b.type === "tool-result");
|
|
24304
24304
|
if (toolResultBlocks.length > 0) {
|
|
24305
24305
|
for (const block of toolResultBlocks) {
|
|
24306
|
-
const toolCallId = String(block.toolCallId ?? (isRecord$
|
|
24306
|
+
const toolCallId = String(block.toolCallId ?? (isRecord$59(message.source) ? message.source.callId : "") ?? "");
|
|
24307
24307
|
const processed = await processMessageContent(block.content, options.model, attachments, signal);
|
|
24308
24308
|
messages.push({
|
|
24309
24309
|
role: "tool",
|
|
@@ -26394,7 +26394,7 @@ function planRetrievalOutline(text, toolName) {
|
|
|
26394
26394
|
* @returns 读到的元数据;两者都没有时 undefined。
|
|
26395
26395
|
*/
|
|
26396
26396
|
function shellMetadataOf(holder) {
|
|
26397
|
-
const job = isPlainRecord(holder.job) ? holder.job : void 0;
|
|
26397
|
+
const job = isPlainRecord$2(holder.job) ? holder.job : void 0;
|
|
26398
26398
|
let exitCode;
|
|
26399
26399
|
if (typeof holder.exitCode === "number" && Number.isFinite(holder.exitCode)) exitCode = holder.exitCode;
|
|
26400
26400
|
if (exitCode === void 0 && typeof job?.exitCode === "number" && Number.isFinite(job.exitCode)) exitCode = job.exitCode;
|
|
@@ -26499,7 +26499,7 @@ const JSON_ENVELOPE_LOG_KEYS = [
|
|
|
26499
26499
|
/** JSON envelope 其余字段允许占用的最大序列化字符数(防止把含批量源码的混合 envelope 压掉)。 */
|
|
26500
26500
|
const JSON_ENVELOPE_MAX_OTHER_CHARS = 800;
|
|
26501
26501
|
/** 判断一个值是不是普通 JSON 对象(不是数组,也不是 null)。 */
|
|
26502
|
-
function isPlainRecord(value) {
|
|
26502
|
+
function isPlainRecord$2(value) {
|
|
26503
26503
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26504
26504
|
}
|
|
26505
26505
|
/** 重建信封:只把预览写回被替换的键,其余字段原样保留。 */
|
|
@@ -26601,7 +26601,7 @@ function extractJsonEnvelopeLogField(text, toolName) {
|
|
|
26601
26601
|
});
|
|
26602
26602
|
}
|
|
26603
26603
|
for (const [outerKey, outerValue] of Object.entries(record)) {
|
|
26604
|
-
if (!isPlainRecord(outerValue)) continue;
|
|
26604
|
+
if (!isPlainRecord$2(outerValue)) continue;
|
|
26605
26605
|
for (const key of JSON_ENVELOPE_LOG_KEYS) {
|
|
26606
26606
|
const value = outerValue[key];
|
|
26607
26607
|
if (typeof value === "string" && value.length > 0) candidates.push({
|
|
@@ -26691,7 +26691,7 @@ function canonicalGrepMatches(value) {
|
|
|
26691
26691
|
if (!Array.isArray(value) || value.length === 0) return void 0;
|
|
26692
26692
|
const matches = [];
|
|
26693
26693
|
for (const entry of value) {
|
|
26694
|
-
if (!isPlainRecord(entry)) return void 0;
|
|
26694
|
+
if (!isPlainRecord$2(entry)) return void 0;
|
|
26695
26695
|
if (typeof entry.path !== "string") return void 0;
|
|
26696
26696
|
if (!Number.isSafeInteger(entry.lineNumber)) return void 0;
|
|
26697
26697
|
if (typeof entry.line !== "string") return void 0;
|
|
@@ -26705,12 +26705,12 @@ function canonicalGrepMatches(value) {
|
|
|
26705
26705
|
}
|
|
26706
26706
|
/** 规范读取结果。 */
|
|
26707
26707
|
function canonicalReadResult(value) {
|
|
26708
|
-
if (!isPlainRecord(value)) return void 0;
|
|
26708
|
+
if (!isPlainRecord$2(value)) return void 0;
|
|
26709
26709
|
if (typeof value.path !== "string" || value.path.trim() === "") return void 0;
|
|
26710
26710
|
if (!Array.isArray(value.lines) || value.lines.length === 0) return void 0;
|
|
26711
26711
|
const lines = [];
|
|
26712
26712
|
for (const entry of value.lines) {
|
|
26713
|
-
if (!isPlainRecord(entry)) return void 0;
|
|
26713
|
+
if (!isPlainRecord$2(entry)) return void 0;
|
|
26714
26714
|
if (!Number.isSafeInteger(entry.number)) return void 0;
|
|
26715
26715
|
if (typeof entry.text !== "string") return void 0;
|
|
26716
26716
|
lines.push({
|
|
@@ -26735,7 +26735,7 @@ function findGrepBinding(record) {
|
|
|
26735
26735
|
matches: top
|
|
26736
26736
|
};
|
|
26737
26737
|
for (const [outerKey, outerValue] of Object.entries(record)) {
|
|
26738
|
-
if (!isPlainRecord(outerValue)) continue;
|
|
26738
|
+
if (!isPlainRecord$2(outerValue)) continue;
|
|
26739
26739
|
const nested = canonicalGrepMatches(outerValue.matches);
|
|
26740
26740
|
if (nested !== void 0) return {
|
|
26741
26741
|
binding: {
|
|
@@ -26762,7 +26762,7 @@ function findGlobBinding(record) {
|
|
|
26762
26762
|
...typeof record.root === "string" ? { root: record.root } : {}
|
|
26763
26763
|
};
|
|
26764
26764
|
for (const [outerKey, outerValue] of Object.entries(record)) {
|
|
26765
|
-
if (!isPlainRecord(outerValue)) continue;
|
|
26765
|
+
if (!isPlainRecord$2(outerValue)) continue;
|
|
26766
26766
|
const nested = canonicalGlobPaths(outerValue.paths);
|
|
26767
26767
|
if (nested !== void 0) return {
|
|
26768
26768
|
binding: {
|
|
@@ -26940,13 +26940,13 @@ function collectCompositeEntries(record) {
|
|
|
26940
26940
|
for (const [key, value] of Object.entries(record)) {
|
|
26941
26941
|
if (Array.isArray(value)) {
|
|
26942
26942
|
value.forEach((item, index) => {
|
|
26943
|
-
if (isPlainRecord(item)) push(`${key}[${index}]`, item);
|
|
26943
|
+
if (isPlainRecord$2(item)) push(`${key}[${index}]`, item);
|
|
26944
26944
|
});
|
|
26945
26945
|
continue;
|
|
26946
26946
|
}
|
|
26947
|
-
if (!isPlainRecord(value)) continue;
|
|
26947
|
+
if (!isPlainRecord$2(value)) continue;
|
|
26948
26948
|
if (push(key, value)) continue;
|
|
26949
|
-
for (const [subKey, subValue] of Object.entries(value)) if (isPlainRecord(subValue)) push(`${key}.${subKey}`, subValue);
|
|
26949
|
+
for (const [subKey, subValue] of Object.entries(value)) if (isPlainRecord$2(subValue)) push(`${key}.${subKey}`, subValue);
|
|
26950
26950
|
}
|
|
26951
26951
|
return entries;
|
|
26952
26952
|
}
|
|
@@ -27382,7 +27382,7 @@ async function projectToolResult(input) {
|
|
|
27382
27382
|
*
|
|
27383
27383
|
* @module dsh-chatgpt-subscription/request-images
|
|
27384
27384
|
*/
|
|
27385
|
-
function isRecord$
|
|
27385
|
+
function isRecord$58(value) {
|
|
27386
27386
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27387
27387
|
}
|
|
27388
27388
|
function asString$24(value) {
|
|
@@ -27441,17 +27441,17 @@ const SUPPORTED_IMAGE_MEDIA_TYPES$3 = /* @__PURE__ */ new Set([
|
|
|
27441
27441
|
]);
|
|
27442
27442
|
function attachmentOf$3(block) {
|
|
27443
27443
|
const attachment = block.attachment;
|
|
27444
|
-
if (!isRecord$
|
|
27444
|
+
if (!isRecord$58(attachment)) return void 0;
|
|
27445
27445
|
return typeof attachment.attachmentId === "string" ? attachment : void 0;
|
|
27446
27446
|
}
|
|
27447
27447
|
function attachmentLabel$3(block) {
|
|
27448
|
-
const attachment = isRecord$
|
|
27448
|
+
const attachment = isRecord$58(block.attachment) ? block.attachment : void 0;
|
|
27449
27449
|
return asString$24(attachment?.name) || asString$24(attachment?.attachmentId);
|
|
27450
27450
|
}
|
|
27451
27451
|
function collectImageRefs$1(content, refs) {
|
|
27452
27452
|
if (!Array.isArray(content)) return;
|
|
27453
27453
|
for (const block of content) {
|
|
27454
|
-
if (!isRecord$
|
|
27454
|
+
if (!isRecord$58(block)) continue;
|
|
27455
27455
|
if (block.type === "image") {
|
|
27456
27456
|
const attachment = attachmentOf$3(block);
|
|
27457
27457
|
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
@@ -27481,7 +27481,7 @@ function base64Length$1(bytes) {
|
|
|
27481
27481
|
*/
|
|
27482
27482
|
function inlinePayloadOf(block) {
|
|
27483
27483
|
let data = asString$24(block.data) || asString$24(block.base64);
|
|
27484
|
-
const source = isRecord$
|
|
27484
|
+
const source = isRecord$58(block.source) ? block.source : void 0;
|
|
27485
27485
|
if (!data && source) data = asString$24(source.data) || asString$24(source.base64);
|
|
27486
27486
|
if (data?.startsWith("data:")) {
|
|
27487
27487
|
const matched = data.match(/^data:([^;,]+);base64,(.*)$/s);
|
|
@@ -27511,7 +27511,7 @@ function requestImagePayloadLength(block, images) {
|
|
|
27511
27511
|
function collectRequestImagePayloads(content, images, lengths) {
|
|
27512
27512
|
if (!Array.isArray(content)) return;
|
|
27513
27513
|
for (const block of content) {
|
|
27514
|
-
if (!isRecord$
|
|
27514
|
+
if (!isRecord$58(block)) continue;
|
|
27515
27515
|
if (block.type === "image") {
|
|
27516
27516
|
const bytes = requestImagePayloadLength(block, images);
|
|
27517
27517
|
if (bytes !== void 0) lengths.push(bytes);
|
|
@@ -27565,7 +27565,7 @@ function replaceOldestRequestImages(options, count, images) {
|
|
|
27565
27565
|
let replaced = false;
|
|
27566
27566
|
return {
|
|
27567
27567
|
content: content.map((block) => {
|
|
27568
|
-
if (remaining.count === 0 || !isRecord$
|
|
27568
|
+
if (remaining.count === 0 || !isRecord$58(block)) return block;
|
|
27569
27569
|
if (block.type === "image") {
|
|
27570
27570
|
if (requestImagePayloadLength(block, images) === void 0) return block;
|
|
27571
27571
|
remaining.count -= 1;
|
|
@@ -27707,7 +27707,7 @@ function collectImageOccurrences(options, images) {
|
|
|
27707
27707
|
const walk = (content) => {
|
|
27708
27708
|
if (!Array.isArray(content)) return;
|
|
27709
27709
|
for (const block of content) {
|
|
27710
|
-
if (!isRecord$
|
|
27710
|
+
if (!isRecord$58(block)) continue;
|
|
27711
27711
|
if (block.type === "image") {
|
|
27712
27712
|
const bytes = requestImagePayloadLength(block, images);
|
|
27713
27713
|
const key = requestImageKey(block, images);
|
|
@@ -27761,7 +27761,7 @@ function replaceDroppedRequestImages(options, droppedKeys, images) {
|
|
|
27761
27761
|
let replaced = false;
|
|
27762
27762
|
return {
|
|
27763
27763
|
content: content.map((block) => {
|
|
27764
|
-
if (!isRecord$
|
|
27764
|
+
if (!isRecord$58(block)) return block;
|
|
27765
27765
|
if (block.type === "image") {
|
|
27766
27766
|
const key = requestImageKey(block, images);
|
|
27767
27767
|
if (key === void 0 || !droppedKeys.has(key)) return block;
|
|
@@ -27946,7 +27946,7 @@ function unavailableImageText$3(block) {
|
|
|
27946
27946
|
}
|
|
27947
27947
|
function imageBlockToInline$2(block, images) {
|
|
27948
27948
|
let data = asString$24(block.data) || asString$24(block.base64);
|
|
27949
|
-
const source = isRecord$
|
|
27949
|
+
const source = isRecord$58(block.source) ? block.source : void 0;
|
|
27950
27950
|
if (!data && source) data = asString$24(source.data) || asString$24(source.base64);
|
|
27951
27951
|
let mediaType = asString$24(block.mimeType) || asString$24(block.mediaType) || (source ? asString$24(source.mimeType) || asString$24(source.mediaType) : void 0) || "image/png";
|
|
27952
27952
|
if (data?.startsWith("data:")) {
|
|
@@ -27990,7 +27990,7 @@ function imageBlockToInline$2(block, images) {
|
|
|
27990
27990
|
* figure with DSH_KIMI_CODE_MAX_BODY_BYTES. The 256K tier keeps 2 MB, where the
|
|
27991
27991
|
* old ceiling and the window line up.
|
|
27992
27992
|
*/
|
|
27993
|
-
const LONG_CONTEXT_MESSAGE_BODY_BYTES =
|
|
27993
|
+
const LONG_CONTEXT_MESSAGE_BODY_BYTES = 24 * 1024 * 1024;
|
|
27994
27994
|
/**
|
|
27995
27995
|
* The ids the subscription serves today.
|
|
27996
27996
|
*
|
|
@@ -28198,6 +28198,19 @@ const HEADER_MSH_DEVICE_NAME = "x-msh-device-name";
|
|
|
28198
28198
|
const HEADER_MSH_DEVICE_MODEL = "x-msh-device-model";
|
|
28199
28199
|
const HEADER_MSH_OS_VERSION = "x-msh-os-version";
|
|
28200
28200
|
const HEADER_MSH_DEVICE_ID = "x-msh-device-id";
|
|
28201
|
+
/**
|
|
28202
|
+
* Environment variable carrying extra headers for every Kimi Code request.
|
|
28203
|
+
*
|
|
28204
|
+
* The official client reads newline-separated `Name: Value` lines from
|
|
28205
|
+
* `KIMI_CODE_CUSTOM_HEADERS` (it mirrors `ANTHROPIC_CUSTOM_HEADERS`) and
|
|
28206
|
+
* applies them to every outbound request, the `/models` listing included.
|
|
28207
|
+
*
|
|
28208
|
+
* These headers are the LOWEST-precedence layer: the Kimi device identity
|
|
28209
|
+
* headers and the caller's own headers both override them, so a deployment can
|
|
28210
|
+
* add a header for one gateway without being able to weaken the identity the
|
|
28211
|
+
* service attributes usage to.
|
|
28212
|
+
*/
|
|
28213
|
+
const KIMI_CODE_CUSTOM_HEADERS_ENV = "KIMI_CODE_CUSTOM_HEADERS";
|
|
28201
28214
|
/** Version the plugin reports to the managed service's telemetry headers. */
|
|
28202
28215
|
const MSH_VERSION = "1.0.0";
|
|
28203
28216
|
const REFRESH_THRESHOLD_RATIO = .5;
|
|
@@ -29052,6 +29065,51 @@ function asciiHeaderValue(value) {
|
|
|
29052
29065
|
const printable = value.replace(/[^\x20-\x7E]/g, "").trim();
|
|
29053
29066
|
return printable === "" ? void 0 : printable;
|
|
29054
29067
|
}
|
|
29068
|
+
/**
|
|
29069
|
+
* Whether one header name is already set, ignoring case.
|
|
29070
|
+
*
|
|
29071
|
+
* HTTP header names are case-insensitive, so a custom `User-Agent` and the
|
|
29072
|
+
* identity `user-agent` are the same header. Keeping both in the map would
|
|
29073
|
+
* send one header twice with two values, which is exactly how a spoofed user
|
|
29074
|
+
* agent would survive the layer that was supposed to override it.
|
|
29075
|
+
*/
|
|
29076
|
+
function hasHeaderName(headers, name) {
|
|
29077
|
+
const target = name.toLowerCase();
|
|
29078
|
+
return Object.keys(headers).some((key) => key.toLowerCase() === target);
|
|
29079
|
+
}
|
|
29080
|
+
/**
|
|
29081
|
+
* Extra headers the deployment supplies through KIMI_CODE_CUSTOM_HEADERS.
|
|
29082
|
+
*
|
|
29083
|
+
* The format is the official client's: newline-separated `Name: Value` lines,
|
|
29084
|
+
* exactly as `ANTHROPIC_CUSTOM_HEADERS` carries them. A line without a colon
|
|
29085
|
+
* is skipped, and both the name and the value are trimmed. The name keeps the
|
|
29086
|
+
* casing the deployment wrote, because that is the header the deployment
|
|
29087
|
+
* expects to see on the wire.
|
|
29088
|
+
*
|
|
29089
|
+
* The value is filtered through {@link asciiHeaderValue}, so a value with
|
|
29090
|
+
* nothing printable left in it is dropped instead of being sent as an empty
|
|
29091
|
+
* header.
|
|
29092
|
+
*
|
|
29093
|
+
* These headers form the LOWEST-precedence layer: the Kimi device identity
|
|
29094
|
+
* headers and the caller's own headers both override them.
|
|
29095
|
+
*
|
|
29096
|
+
* @param env environment the variable is read from, injectable for tests.
|
|
29097
|
+
*/
|
|
29098
|
+
function parseKimiCodeCustomHeaders(env = process.env) {
|
|
29099
|
+
const raw = env[KIMI_CODE_CUSTOM_HEADERS_ENV]?.trim();
|
|
29100
|
+
if (raw === void 0 || raw === "") return {};
|
|
29101
|
+
const headers = {};
|
|
29102
|
+
for (const line of raw.split("\n")) {
|
|
29103
|
+
const colon = line.indexOf(":");
|
|
29104
|
+
if (colon < 0) continue;
|
|
29105
|
+
const name = line.slice(0, colon).trim();
|
|
29106
|
+
if (name === "") continue;
|
|
29107
|
+
const value = asciiHeaderValue(line.slice(colon + 1));
|
|
29108
|
+
if (value === void 0) continue;
|
|
29109
|
+
headers[name] = value;
|
|
29110
|
+
}
|
|
29111
|
+
return headers;
|
|
29112
|
+
}
|
|
29055
29113
|
/** Best-effort human description of this machine, matching the official client. */
|
|
29056
29114
|
function deviceModel() {
|
|
29057
29115
|
const arch = os.arch();
|
|
@@ -29084,7 +29142,22 @@ async function getDeviceId() {
|
|
|
29084
29142
|
} catch {}
|
|
29085
29143
|
return created;
|
|
29086
29144
|
}
|
|
29087
|
-
/**
|
|
29145
|
+
/**
|
|
29146
|
+
* Identity headers every Kimi Code OAuth and account request carries.
|
|
29147
|
+
*
|
|
29148
|
+
* Three layers, lowest precedence first:
|
|
29149
|
+
*
|
|
29150
|
+
* 1. the deployment's own `KIMI_CODE_CUSTOM_HEADERS`, so a gateway in front of
|
|
29151
|
+
* this route can ask for one extra header without a plugin release;
|
|
29152
|
+
* 2. the Kimi device identity, which the service uses to attribute usage to an
|
|
29153
|
+
* installation;
|
|
29154
|
+
* 3. the caller's own headers, which carry the credentials.
|
|
29155
|
+
*
|
|
29156
|
+
* A header name is matched across the layers without regard to case, so a
|
|
29157
|
+
* custom `User-Agent` cannot sit next to the identity `user-agent` and have
|
|
29158
|
+
* the last value win by accident: the higher layer replaces the lower one
|
|
29159
|
+
* outright instead of adding a second copy of the same header.
|
|
29160
|
+
*/
|
|
29088
29161
|
async function kimiIdentityHeaders(extra = {}) {
|
|
29089
29162
|
const deviceId = await getDeviceId();
|
|
29090
29163
|
const candidates = [
|
|
@@ -29102,6 +29175,10 @@ async function kimiIdentityHeaders(extra = {}) {
|
|
|
29102
29175
|
const safe = asciiHeaderValue(value);
|
|
29103
29176
|
if (safe !== void 0) headers[name] = safe;
|
|
29104
29177
|
}
|
|
29178
|
+
for (const [name, value] of Object.entries(parseKimiCodeCustomHeaders())) {
|
|
29179
|
+
if (hasHeaderName(headers, name) || hasHeaderName(extra, name)) continue;
|
|
29180
|
+
headers[name] = value;
|
|
29181
|
+
}
|
|
29105
29182
|
return {
|
|
29106
29183
|
...headers,
|
|
29107
29184
|
...extra
|
|
@@ -29561,11 +29638,11 @@ const MODELS_PATH$2 = "/models";
|
|
|
29561
29638
|
const USAGES_PATH = "/usages";
|
|
29562
29639
|
/** The service reports money in fixed-point units of 1e-6 cents. */
|
|
29563
29640
|
const FIXED_POINT_CENTS = 1e6;
|
|
29564
|
-
function isRecord$
|
|
29641
|
+
function isRecord$57(value) {
|
|
29565
29642
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29566
29643
|
}
|
|
29567
29644
|
function asRecord$14(value) {
|
|
29568
|
-
return isRecord$
|
|
29645
|
+
return isRecord$57(value) ? value : void 0;
|
|
29569
29646
|
}
|
|
29570
29647
|
function asString$23(value) {
|
|
29571
29648
|
if (typeof value === "string" && value.trim() !== "") return value;
|
|
@@ -29591,6 +29668,19 @@ function firstNumber(record, keys) {
|
|
|
29591
29668
|
if (value !== void 0) return value;
|
|
29592
29669
|
}
|
|
29593
29670
|
}
|
|
29671
|
+
/**
|
|
29672
|
+
* Non-empty strings from one array field.
|
|
29673
|
+
*
|
|
29674
|
+
* The service states its lists as JSON arrays. A field that is not an array, or
|
|
29675
|
+
* an array with nothing usable in it, reads as "the server said nothing" rather
|
|
29676
|
+
* than as an empty list, so the caller can fall back to the other dialect
|
|
29677
|
+
* instead of publishing an empty answer as the server's verdict.
|
|
29678
|
+
*/
|
|
29679
|
+
function asStringList(value) {
|
|
29680
|
+
if (!Array.isArray(value)) return void 0;
|
|
29681
|
+
const entries = value.filter((entry) => typeof entry === "string" && entry.trim() !== "");
|
|
29682
|
+
return entries.length > 0 ? entries : void 0;
|
|
29683
|
+
}
|
|
29594
29684
|
function clamp01$1(value) {
|
|
29595
29685
|
return Math.min(1, Math.max(0, value));
|
|
29596
29686
|
}
|
|
@@ -29698,14 +29788,48 @@ const RETIRED_MODEL_STATUSES = /* @__PURE__ */ new Set([
|
|
|
29698
29788
|
* Read the three-state thinking declaration.
|
|
29699
29789
|
*
|
|
29700
29790
|
* Kept separate from the effort list because it can contradict it: a model may
|
|
29701
|
-
* ship `valid_efforts` that still contain `none` while
|
|
29702
|
-
*
|
|
29703
|
-
*
|
|
29791
|
+
* ship `valid_efforts` that still contain `none` while the declaration says it
|
|
29792
|
+
* can only reason. When both are present the declaration wins, because it is
|
|
29793
|
+
* the field the service introduced to replace the older boolean.
|
|
29794
|
+
*
|
|
29795
|
+
* Two dialects state it. The unified schema nests it under `reasoning`:
|
|
29796
|
+
* `{ "type": "only" | "both" | "none" }`; the older listing states it flat as
|
|
29797
|
+
* `supports_thinking_type`. The unified object is read first, because it is
|
|
29798
|
+
* the newer field and the one that also carries the effort ladder; the flat
|
|
29799
|
+
* field remains the fallback for a server that still speaks the old shape.
|
|
29800
|
+
*
|
|
29801
|
+
* The unified schema spells the non-thinking state `none`; the internal
|
|
29802
|
+
* three-state keeps the legacy `no`.
|
|
29704
29803
|
*/
|
|
29705
29804
|
function parseThinkingType(record) {
|
|
29805
|
+
const reasoning = asRecord$14(record.reasoning);
|
|
29806
|
+
if (reasoning !== void 0) {
|
|
29807
|
+
const rType = asString$23(reasoning.type);
|
|
29808
|
+
if (rType === "only" || rType === "both") return rType;
|
|
29809
|
+
if (rType === "none" || rType === "no") return "no";
|
|
29810
|
+
}
|
|
29706
29811
|
const raw = asString$23(record.supports_thinking_type) ?? asString$23(record.supportsThinkingType);
|
|
29707
29812
|
return raw === "only" || raw === "no" || raw === "both" ? raw : void 0;
|
|
29708
29813
|
}
|
|
29814
|
+
/**
|
|
29815
|
+
* Read one model entry from the live listing.
|
|
29816
|
+
*
|
|
29817
|
+
* The service has published two shapes of the same listing and this parser
|
|
29818
|
+
* reads both:
|
|
29819
|
+
*
|
|
29820
|
+
* - the unified schema, which nests the window under `limit.context`, the
|
|
29821
|
+
* input cap under `limit.input`, the thinking declaration and the effort
|
|
29822
|
+
* ladder under `reasoning`, the accepted media under `modalities.input`
|
|
29823
|
+
* and the message-level tool flag under `tools.dynamic_load`;
|
|
29824
|
+
* - the older flat schema, which states the same facts as
|
|
29825
|
+
* `context_length`, `max_input_tokens`, `supports_thinking_type`,
|
|
29826
|
+
* `think_efforts`, `supports_image_in` / `supports_video_in` and
|
|
29827
|
+
* `supports_dynamic_tools`.
|
|
29828
|
+
*
|
|
29829
|
+
* A field the unified schema carries wins over its flat counterpart, because
|
|
29830
|
+
* that is the shape the service is moving towards; a field only the flat shape
|
|
29831
|
+
* carries is still read, so an older server keeps working.
|
|
29832
|
+
*/
|
|
29709
29833
|
function parseCatalogModel(value) {
|
|
29710
29834
|
const record = asRecord$14(value);
|
|
29711
29835
|
if (record === void 0) return void 0;
|
|
@@ -29713,30 +29837,41 @@ function parseCatalogModel(value) {
|
|
|
29713
29837
|
if (id === void 0) return void 0;
|
|
29714
29838
|
const status = asString$23(record.status)?.toLowerCase();
|
|
29715
29839
|
if (status !== void 0 && RETIRED_MODEL_STATUSES.has(status)) return void 0;
|
|
29716
|
-
const
|
|
29840
|
+
const limits = asRecord$14(record.limit) ?? asRecord$14(record.limits);
|
|
29841
|
+
const contextWindow = firstNumber(record, ["context_length", "contextLength"]) ?? firstNumber(limits ?? {}, ["context"]);
|
|
29717
29842
|
if (contextWindow === void 0 || contextWindow <= 0) return void 0;
|
|
29718
|
-
const declaredInput = firstNumber(
|
|
29843
|
+
const declaredInput = firstNumber(limits ?? {}, ["input"]) ?? firstNumber(record, ["max_input_tokens", "maxInputTokens"]);
|
|
29719
29844
|
const maxInputTokens = declaredInput !== void 0 && declaredInput > 0 && declaredInput < contextWindow ? declaredInput : void 0;
|
|
29720
29845
|
const thinkingType = parseThinkingType(record);
|
|
29846
|
+
const reasoningEffort = asRecord$14(asRecord$14(record.reasoning)?.effort);
|
|
29721
29847
|
const efforts = asRecord$14(record.think_efforts) ?? asRecord$14(record.thinkEfforts);
|
|
29722
|
-
const
|
|
29848
|
+
const usableEfforts = efforts !== void 0 && "support" in efforts && efforts.support !== true ? void 0 : efforts;
|
|
29849
|
+
const validEfforts = asStringList(reasoningEffort?.valid) ?? asStringList(usableEfforts?.valid_efforts) ?? asStringList(usableEfforts?.validEfforts);
|
|
29850
|
+
const rawDefaultEffort = asString$23(reasoningEffort?.default) ?? asString$23(usableEfforts?.default_effort ?? usableEfforts?.defaultEffort);
|
|
29851
|
+
const defaultReasoningEffort = rawDefaultEffort !== void 0 && validEfforts !== void 0 && validEfforts.length > 0 && !validEfforts.includes(rawDefaultEffort) ? void 0 : rawDefaultEffort;
|
|
29852
|
+
const rawModalities = asRecord$14(record.modalities);
|
|
29853
|
+
const modalityInputs = Array.isArray(rawModalities?.input) ? rawModalities.input.filter((entry) => typeof entry === "string") : [];
|
|
29854
|
+
const hasImage = record.supports_image_in === true || record.supportsImageIn === true || modalityInputs.includes("image");
|
|
29855
|
+
const hasVideo = record.supports_video_in === true || record.supportsVideoIn === true || modalityInputs.includes("video");
|
|
29723
29856
|
const modalities = ["text"];
|
|
29724
|
-
if (
|
|
29725
|
-
if (
|
|
29857
|
+
if (hasImage) modalities.push("image");
|
|
29858
|
+
if (hasVideo) modalities.push("video");
|
|
29859
|
+
const toolsObj = asRecord$14(record.tools);
|
|
29860
|
+
const rawDynamicTools = typeof toolsObj?.dynamic_load === "boolean" ? toolsObj.dynamic_load : record.supports_dynamic_tools ?? record.supportsDynamicTools;
|
|
29726
29861
|
const protocol = asString$23(record.protocol);
|
|
29727
29862
|
return {
|
|
29728
29863
|
id,
|
|
29729
29864
|
name: asString$23(record.display_name) ?? asString$23(record.displayName) ?? void 0,
|
|
29730
29865
|
contextWindow,
|
|
29731
|
-
...validEfforts === void 0
|
|
29732
|
-
...
|
|
29866
|
+
...validEfforts === void 0 ? {} : { reasoningEfforts: validEfforts },
|
|
29867
|
+
...defaultReasoningEffort === void 0 ? {} : { defaultReasoningEffort },
|
|
29733
29868
|
inputModalities: modalities,
|
|
29734
29869
|
protocol: protocol === "anthropic" ? "anthropic" : "openai",
|
|
29735
|
-
...
|
|
29870
|
+
...hasVideo ? { supportsVideo: true } : {},
|
|
29736
29871
|
...maxInputTokens === void 0 ? {} : { maxInputTokens },
|
|
29737
29872
|
...thinkingType === void 0 ? {} : { thinkingType },
|
|
29738
29873
|
...typeof (record.supports_tool_use ?? record.supportsToolUse) === "boolean" ? { supportsToolUse: record.supports_tool_use ?? record.supportsToolUse } : {},
|
|
29739
|
-
...typeof
|
|
29874
|
+
...typeof rawDynamicTools === "boolean" ? { supportsDynamicTools: rawDynamicTools } : {}
|
|
29740
29875
|
};
|
|
29741
29876
|
}
|
|
29742
29877
|
/**
|
|
@@ -30622,12 +30757,12 @@ async function testConnection$1(store, options = {}) {
|
|
|
30622
30757
|
*
|
|
30623
30758
|
* @module dsh-chatgpt-subscription/tool-schema
|
|
30624
30759
|
*/
|
|
30625
|
-
function isRecord$
|
|
30760
|
+
function isRecord$56(value) {
|
|
30626
30761
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30627
30762
|
}
|
|
30628
30763
|
function cloneJsonValue(value) {
|
|
30629
30764
|
if (Array.isArray(value)) return value.map(cloneJsonValue);
|
|
30630
|
-
if (isRecord$
|
|
30765
|
+
if (isRecord$56(value)) {
|
|
30631
30766
|
const res = {};
|
|
30632
30767
|
for (const [k, v] of Object.entries(value)) res[k] = cloneJsonValue(v);
|
|
30633
30768
|
return res;
|
|
@@ -30642,7 +30777,7 @@ function resolveLocalJsonPointer(root, ref) {
|
|
|
30642
30777
|
let current = root;
|
|
30643
30778
|
for (const rawPart of ref.slice(2).split("/")) {
|
|
30644
30779
|
const part = rawPart.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
30645
|
-
if (isRecord$
|
|
30780
|
+
if (isRecord$56(current)) {
|
|
30646
30781
|
if (!Object.prototype.hasOwnProperty.call(current, part)) return { found: false };
|
|
30647
30782
|
current = current[part];
|
|
30648
30783
|
} else if (Array.isArray(current)) {
|
|
@@ -30658,7 +30793,7 @@ function resolveLocalJsonPointer(root, ref) {
|
|
|
30658
30793
|
}
|
|
30659
30794
|
function derefNode(node, root, visited) {
|
|
30660
30795
|
if (Array.isArray(node)) return node.map((item) => derefNode(item, root, visited));
|
|
30661
|
-
if (isRecord$
|
|
30796
|
+
if (isRecord$56(node)) {
|
|
30662
30797
|
if (typeof node["$ref"] === "string" && (node["$ref"] === "#" || node["$ref"].startsWith("#/"))) {
|
|
30663
30798
|
const ref = node["$ref"];
|
|
30664
30799
|
if (visited.has(ref)) return node;
|
|
@@ -30667,7 +30802,7 @@ function derefNode(node, root, visited) {
|
|
|
30667
30802
|
visited.add(ref);
|
|
30668
30803
|
const inlined = derefNode(resolved.value, root, visited);
|
|
30669
30804
|
visited.delete(ref);
|
|
30670
|
-
if (isRecord$
|
|
30805
|
+
if (isRecord$56(inlined)) {
|
|
30671
30806
|
const merged = { ...inlined };
|
|
30672
30807
|
for (const [k, v] of Object.entries(node)) {
|
|
30673
30808
|
if (k === "$ref") continue;
|
|
@@ -30687,7 +30822,7 @@ function derefNode(node, root, visited) {
|
|
|
30687
30822
|
}
|
|
30688
30823
|
function hasUnresolvedDefinitionRef(node, bucketKey) {
|
|
30689
30824
|
if (Array.isArray(node)) return node.some((child) => hasUnresolvedDefinitionRef(child, bucketKey));
|
|
30690
|
-
if (isRecord$
|
|
30825
|
+
if (isRecord$56(node)) {
|
|
30691
30826
|
const ref = node["$ref"];
|
|
30692
30827
|
if (typeof ref === "string" && ref.startsWith(`#/${bucketKey}/`)) return true;
|
|
30693
30828
|
for (const [k, v] of Object.entries(node)) {
|
|
@@ -30718,19 +30853,19 @@ function inferTypeFromValues(values) {
|
|
|
30718
30853
|
if (types.size === 1) return types.values().next().value;
|
|
30719
30854
|
}
|
|
30720
30855
|
function normalizeSchemaProperties(node) {
|
|
30721
|
-
if (!isRecord$
|
|
30722
|
-
if (isRecord$
|
|
30723
|
-
for (const propSchema of Object.values(node.properties)) if (isRecord$
|
|
30856
|
+
if (!isRecord$56(node)) return;
|
|
30857
|
+
if (isRecord$56(node.properties)) {
|
|
30858
|
+
for (const propSchema of Object.values(node.properties)) if (isRecord$56(propSchema)) {
|
|
30724
30859
|
if (!propSchema.type && !propSchema.$ref) {
|
|
30725
30860
|
if (Array.isArray(propSchema.enum) && propSchema.enum.length > 0) propSchema.type = inferTypeFromValues(propSchema.enum) ?? "string";
|
|
30726
30861
|
else if (propSchema.const !== void 0) propSchema.type = inferValueType(propSchema.const) ?? "string";
|
|
30727
|
-
else if (isRecord$
|
|
30862
|
+
else if (isRecord$56(propSchema.properties)) propSchema.type = "object";
|
|
30728
30863
|
else if (propSchema.items) propSchema.type = "array";
|
|
30729
30864
|
}
|
|
30730
30865
|
normalizeSchemaProperties(propSchema);
|
|
30731
30866
|
}
|
|
30732
30867
|
}
|
|
30733
|
-
if (isRecord$
|
|
30868
|
+
if (isRecord$56(node.items)) normalizeSchemaProperties(node.items);
|
|
30734
30869
|
else if (Array.isArray(node.items)) for (const item of node.items) normalizeSchemaProperties(item);
|
|
30735
30870
|
}
|
|
30736
30871
|
/**
|
|
@@ -30738,7 +30873,7 @@ function normalizeSchemaProperties(node) {
|
|
|
30738
30873
|
* inlining definitions ($defs/definitions/$ref), and ensuring property types for enums/consts.
|
|
30739
30874
|
*/
|
|
30740
30875
|
function normalizeKimiToolSchema(schema) {
|
|
30741
|
-
if (!isRecord$
|
|
30876
|
+
if (!isRecord$56(schema)) return {
|
|
30742
30877
|
type: "object",
|
|
30743
30878
|
properties: {}
|
|
30744
30879
|
};
|
|
@@ -30756,7 +30891,7 @@ function stripMetaSchema$1(schema) {
|
|
|
30756
30891
|
}
|
|
30757
30892
|
//#endregion
|
|
30758
30893
|
//#region src/host/common/prompt-estimate.ts
|
|
30759
|
-
function isRecord$
|
|
30894
|
+
function isRecord$55(value) {
|
|
30760
30895
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30761
30896
|
}
|
|
30762
30897
|
/** Tool-call arguments as the JSON string a wire carries, whatever shape they arrived in. */
|
|
@@ -30789,7 +30924,7 @@ function estimatedInputTokens(options) {
|
|
|
30789
30924
|
const contentCharacters = (content) => {
|
|
30790
30925
|
if (!Array.isArray(content)) return typeof content === "string" ? content.length : 0;
|
|
30791
30926
|
return content.reduce((total, block) => {
|
|
30792
|
-
if (!isRecord$
|
|
30927
|
+
if (!isRecord$55(block)) return total;
|
|
30793
30928
|
if ((block.type === "text" || block.type === "reasoning") && typeof block.text === "string") return total + block.text.length;
|
|
30794
30929
|
if (block.type === "tool-result") return total + contentCharacters(block.content);
|
|
30795
30930
|
if (block.type === "tool-call") {
|
|
@@ -30890,7 +31025,7 @@ function videoOmissionText$1(reason, label) {
|
|
|
30890
31025
|
}
|
|
30891
31026
|
//#endregion
|
|
30892
31027
|
//#region src/host/common/video-request.ts
|
|
30893
|
-
function isRecord$
|
|
31028
|
+
function isRecord$54(value) {
|
|
30894
31029
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30895
31030
|
}
|
|
30896
31031
|
function asString$22(value) {
|
|
@@ -30898,14 +31033,14 @@ function asString$22(value) {
|
|
|
30898
31033
|
}
|
|
30899
31034
|
function videoAttachmentOf(block) {
|
|
30900
31035
|
const attachment = block.attachment;
|
|
30901
|
-
if (!isRecord$
|
|
31036
|
+
if (!isRecord$54(attachment)) return void 0;
|
|
30902
31037
|
if (typeof attachment.attachmentId !== "string") return void 0;
|
|
30903
31038
|
return attachment;
|
|
30904
31039
|
}
|
|
30905
31040
|
function collectVideoRefs(content, refs) {
|
|
30906
31041
|
if (!Array.isArray(content)) return;
|
|
30907
31042
|
for (const block of content) {
|
|
30908
|
-
if (!isRecord$
|
|
31043
|
+
if (!isRecord$54(block) || block.type !== "video") continue;
|
|
30909
31044
|
const attachment = videoAttachmentOf(block);
|
|
30910
31045
|
if (attachment) refs.set(attachment.attachmentId, attachment);
|
|
30911
31046
|
}
|
|
@@ -30920,7 +31055,7 @@ function requestVideoBytes(block) {
|
|
|
30920
31055
|
function collectRequestVideoBytes(content, lengths) {
|
|
30921
31056
|
if (!Array.isArray(content)) return;
|
|
30922
31057
|
for (const block of content) {
|
|
30923
|
-
if (!isRecord$
|
|
31058
|
+
if (!isRecord$54(block) || block.type !== "video") continue;
|
|
30924
31059
|
const bytes = requestVideoBytes(block);
|
|
30925
31060
|
if (bytes !== void 0) lengths.push(bytes);
|
|
30926
31061
|
}
|
|
@@ -30964,7 +31099,7 @@ function isAbortLike(error, signal) {
|
|
|
30964
31099
|
}
|
|
30965
31100
|
/** True when the request carries any video occurrence at all. */
|
|
30966
31101
|
function requestHasVideo(options) {
|
|
30967
|
-
return options.messages.some((message) => Array.isArray(message.content) && message.content.some((block) => isRecord$
|
|
31102
|
+
return options.messages.some((message) => Array.isArray(message.content) && message.content.some((block) => isRecord$54(block) && block.type === "video"));
|
|
30968
31103
|
}
|
|
30969
31104
|
function omittedVideoText(omit, block) {
|
|
30970
31105
|
return omit("unreadable", videoBlockLabel(block));
|
|
@@ -30999,7 +31134,7 @@ function offloadOldestRequestVideos(options, maxBytes) {
|
|
|
30999
31134
|
if (remaining.count === 0 || !Array.isArray(message.content)) return message;
|
|
31000
31135
|
let replaced = false;
|
|
31001
31136
|
const content = message.content.map((block) => {
|
|
31002
|
-
if (remaining.count === 0 || !isRecord$
|
|
31137
|
+
if (remaining.count === 0 || !isRecord$54(block) || block.type !== "video") return block;
|
|
31003
31138
|
if (requestVideoBytes(block) === void 0) return block;
|
|
31004
31139
|
remaining.count -= 1;
|
|
31005
31140
|
replaced = true;
|
|
@@ -31082,7 +31217,7 @@ function videoBlockToInline(block, videos, videoAccepted, omit) {
|
|
|
31082
31217
|
*
|
|
31083
31218
|
* See https://www.kimi.com/code/docs/en/kimi-code/error-reference.html
|
|
31084
31219
|
*/
|
|
31085
|
-
function isRecord$
|
|
31220
|
+
function isRecord$53(value) {
|
|
31086
31221
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31087
31222
|
}
|
|
31088
31223
|
function asString$21(value) {
|
|
@@ -31192,7 +31327,7 @@ function reasoningDetailFragments(value) {
|
|
|
31192
31327
|
if (!Array.isArray(value)) return [];
|
|
31193
31328
|
const fragments = [];
|
|
31194
31329
|
value.forEach((entry, position) => {
|
|
31195
|
-
if (!isRecord$
|
|
31330
|
+
if (!isRecord$53(entry)) return;
|
|
31196
31331
|
fragments.push(...reasoningDetailElement(entry, position));
|
|
31197
31332
|
});
|
|
31198
31333
|
return fragments;
|
|
@@ -31423,23 +31558,12 @@ function mapReasoningEffort(effort) {
|
|
|
31423
31558
|
default: return;
|
|
31424
31559
|
}
|
|
31425
31560
|
}
|
|
31426
|
-
/**
|
|
31427
|
-
* Thinking-token budget one Anthropic-route level asks for.
|
|
31428
|
-
*
|
|
31429
|
-
* Kimi's Anthropic surface takes the standard `thinking` block, so the budget is
|
|
31430
|
-
* derived from the same three levels the OpenAI surface uses.
|
|
31431
|
-
*/
|
|
31432
|
-
function thinkingBudgetFor(effort, maxTokens) {
|
|
31433
|
-
if (effort === void 0 || effort === "none") return void 0;
|
|
31434
|
-
const budget = Math.min(effort === "low" ? 2048 : effort === "high" ? 8192 : 16384, maxTokens - 1024);
|
|
31435
|
-
return budget >= 1024 ? budget : void 0;
|
|
31436
|
-
}
|
|
31437
31561
|
function textOf$7(content) {
|
|
31438
31562
|
if (typeof content === "string") return sanitizeText$7(content);
|
|
31439
31563
|
if (!Array.isArray(content)) return "";
|
|
31440
31564
|
const parts = [];
|
|
31441
31565
|
for (const block of content) {
|
|
31442
|
-
if (!isRecord$
|
|
31566
|
+
if (!isRecord$53(block)) continue;
|
|
31443
31567
|
if (block.type === "text" && typeof block.text === "string") parts.push(sanitizeText$7(block.text));
|
|
31444
31568
|
else if (block.type === "tool-result") parts.push(textOf$7(block.content));
|
|
31445
31569
|
}
|
|
@@ -31448,7 +31572,7 @@ function textOf$7(content) {
|
|
|
31448
31572
|
function toolResultText$7(blocks) {
|
|
31449
31573
|
if (!Array.isArray(blocks)) return "";
|
|
31450
31574
|
return blocks.map((block) => {
|
|
31451
|
-
if (!isRecord$
|
|
31575
|
+
if (!isRecord$53(block)) return "";
|
|
31452
31576
|
if (block.type === "text" && typeof block.text === "string") return sanitizeText$7(block.text);
|
|
31453
31577
|
if (block.type === "tool-result") return toolResultText$7(block.content);
|
|
31454
31578
|
if (block.type === "image") return `[image: ${attachmentLabel$3(block) ?? "attached image"}]`;
|
|
@@ -31466,7 +31590,7 @@ function toolResultBlocks$1(blocks, images) {
|
|
|
31466
31590
|
const out = [];
|
|
31467
31591
|
let hasImage = false;
|
|
31468
31592
|
for (const block of blocks) {
|
|
31469
|
-
if (!isRecord$
|
|
31593
|
+
if (!isRecord$53(block)) continue;
|
|
31470
31594
|
if (block.type === "text" && typeof block.text === "string") {
|
|
31471
31595
|
out.push({
|
|
31472
31596
|
type: "text",
|
|
@@ -31521,7 +31645,7 @@ function toolResultImageBlocks$4(blocks, images, media = {}) {
|
|
|
31521
31645
|
if (!Array.isArray(blocks)) return [];
|
|
31522
31646
|
const out = [];
|
|
31523
31647
|
for (const block of blocks) {
|
|
31524
|
-
if (!isRecord$
|
|
31648
|
+
if (!isRecord$53(block)) continue;
|
|
31525
31649
|
if (block.type === "image") {
|
|
31526
31650
|
const reference = hostedReference(media.imageReferences, block);
|
|
31527
31651
|
if (reference !== void 0) {
|
|
@@ -31556,7 +31680,7 @@ const HOSTED_FILE_SCHEME = "ms://";
|
|
|
31556
31680
|
* bytes.
|
|
31557
31681
|
*/
|
|
31558
31682
|
function attachmentIdOf(block) {
|
|
31559
|
-
const attachment = isRecord$
|
|
31683
|
+
const attachment = isRecord$53(block.attachment) ? block.attachment : void 0;
|
|
31560
31684
|
const id = attachment === void 0 ? void 0 : asString$21(attachment.attachmentId);
|
|
31561
31685
|
return id === void 0 || id === "" ? void 0 : id;
|
|
31562
31686
|
}
|
|
@@ -31639,12 +31763,12 @@ function readReasoningForm(value) {
|
|
|
31639
31763
|
*/
|
|
31640
31764
|
function reasoningRunsAt(message, blockIndex) {
|
|
31641
31765
|
const state = message.source?.replayState;
|
|
31642
|
-
if (!isRecord$
|
|
31766
|
+
if (!isRecord$53(state) || !Array.isArray(state.blocks)) return void 0;
|
|
31643
31767
|
const entry = state.blocks[blockIndex];
|
|
31644
|
-
if (!isRecord$
|
|
31768
|
+
if (!isRecord$53(entry) || !Array.isArray(entry.reasoning)) return void 0;
|
|
31645
31769
|
const runs = [];
|
|
31646
31770
|
for (const raw of entry.reasoning) {
|
|
31647
|
-
if (!isRecord$
|
|
31771
|
+
if (!isRecord$53(raw)) return void 0;
|
|
31648
31772
|
const key = asString$21(raw.key);
|
|
31649
31773
|
const length = raw.length;
|
|
31650
31774
|
if (key === void 0 || typeof length !== "number" || !Number.isInteger(length) || length < 0) return void 0;
|
|
@@ -31694,7 +31818,7 @@ function replayedReasoning(message, fallbackKey) {
|
|
|
31694
31818
|
};
|
|
31695
31819
|
for (let blockIndex = 0; blockIndex < message.content.length; blockIndex++) {
|
|
31696
31820
|
const block = message.content[blockIndex];
|
|
31697
|
-
if (!isRecord$
|
|
31821
|
+
if (!isRecord$53(block) || block.type !== "reasoning" || typeof block.text !== "string") continue;
|
|
31698
31822
|
const text = sanitizeText$7(block.text);
|
|
31699
31823
|
joined += text;
|
|
31700
31824
|
const runs = reasoningRunsAt(message, blockIndex);
|
|
@@ -31863,7 +31987,7 @@ function openAIUserContent$3(message, images, media = {}) {
|
|
|
31863
31987
|
const parts = [];
|
|
31864
31988
|
let hasRichPart = false;
|
|
31865
31989
|
for (const block of message.content) {
|
|
31866
|
-
if (!isRecord$
|
|
31990
|
+
if (!isRecord$53(block)) continue;
|
|
31867
31991
|
if (block.type === "text" && typeof block.text === "string") {
|
|
31868
31992
|
const text = sanitizeText$7(block.text);
|
|
31869
31993
|
if (text !== "") parts.push({
|
|
@@ -31921,16 +32045,20 @@ function openAIAssistantContent$3(message, toolCallIds, reasoningKey) {
|
|
|
31921
32045
|
const textParts = [];
|
|
31922
32046
|
const toolCalls = [];
|
|
31923
32047
|
for (const block of message.content) {
|
|
31924
|
-
if (!isRecord$
|
|
32048
|
+
if (!isRecord$53(block)) continue;
|
|
31925
32049
|
if (block.type === "text" && typeof block.text === "string") textParts.push(sanitizeText$7(block.text));
|
|
31926
|
-
else if (block.type === "tool-call" && typeof block.name === "string")
|
|
31927
|
-
|
|
31928
|
-
|
|
31929
|
-
|
|
31930
|
-
|
|
31931
|
-
|
|
31932
|
-
|
|
31933
|
-
|
|
32050
|
+
else if (block.type === "tool-call" && typeof block.name === "string") {
|
|
32051
|
+
const call = {
|
|
32052
|
+
id: toolCallIds.normalize(typeof block.id === "string" && block.id !== "" ? block.id : `call_${toolCalls.length}`),
|
|
32053
|
+
type: "function",
|
|
32054
|
+
function: {
|
|
32055
|
+
name: block.name,
|
|
32056
|
+
arguments: toolCallArguments$6(block.arguments)
|
|
32057
|
+
}
|
|
32058
|
+
};
|
|
32059
|
+
if (isRecord$53(block.extras)) call.extras = block.extras;
|
|
32060
|
+
toolCalls.push(call);
|
|
32061
|
+
}
|
|
31934
32062
|
}
|
|
31935
32063
|
return {
|
|
31936
32064
|
content: textParts.join(""),
|
|
@@ -32071,6 +32199,31 @@ function replayedDetailElement(detail) {
|
|
|
32071
32199
|
...index
|
|
32072
32200
|
};
|
|
32073
32201
|
}
|
|
32202
|
+
/**
|
|
32203
|
+
* Put one run of tool results back in the order the assistant declared its
|
|
32204
|
+
* calls in.
|
|
32205
|
+
*
|
|
32206
|
+
* A parallel tool call answers several calls at once, and the service reads
|
|
32207
|
+
* the `tool` messages as the answers to the `tool_calls` that precede them:
|
|
32208
|
+
* a result that arrives in the wrong order is answered against the wrong call.
|
|
32209
|
+
* DSH history can hold the results out of order (a resumed session, a tool
|
|
32210
|
+
* that answered late), so the run is sorted back into the declared order.
|
|
32211
|
+
*
|
|
32212
|
+
* A result whose id belongs to no declared call keeps its relative order
|
|
32213
|
+
* behind the answered ones: it answers something this turn did not declare,
|
|
32214
|
+
* so there is no declared position for it to be sorted into.
|
|
32215
|
+
*/
|
|
32216
|
+
function pairToolExchanges(batch, declaredIds) {
|
|
32217
|
+
if (batch.length < 2 || declaredIds.length < 2) return [...batch];
|
|
32218
|
+
const rank = /* @__PURE__ */ new Map();
|
|
32219
|
+
for (const [position, id] of declaredIds.entries()) if (!rank.has(id)) rank.set(id, position);
|
|
32220
|
+
if (batch.filter((entry) => rank.has(entry.id)).length < 2) return [...batch];
|
|
32221
|
+
return batch.map((entry, position) => ({
|
|
32222
|
+
entry,
|
|
32223
|
+
position,
|
|
32224
|
+
key: rank.get(entry.id) ?? Number.MAX_SAFE_INTEGER
|
|
32225
|
+
})).sort((a, b) => a.key - b.key || a.position - b.position).map((ordered) => ordered.entry);
|
|
32226
|
+
}
|
|
32074
32227
|
/** Build one `/chat/completions` body. */
|
|
32075
32228
|
function buildOpenAIRequest(options, images = NO_RESOLVED_IMAGES$3, preserveThinking = preserveThinkingEnabled(), media = {}) {
|
|
32076
32229
|
const effort = mapReasoningEffort(options.reasoningEffort === void 0 ? void 0 : String(options.reasoningEffort));
|
|
@@ -32082,12 +32235,46 @@ function buildOpenAIRequest(options, images = NO_RESOLVED_IMAGES$3, preserveThin
|
|
|
32082
32235
|
role: "system",
|
|
32083
32236
|
content: system
|
|
32084
32237
|
});
|
|
32238
|
+
const NO_TOOL_RESULT_TEXT = "[no result: the tool call did not complete]";
|
|
32239
|
+
let awaitingToolCallIds = [];
|
|
32240
|
+
let deferredNonToolMessages = [];
|
|
32241
|
+
let pendingToolImages = [];
|
|
32242
|
+
const emitNonTool = (entry) => {
|
|
32243
|
+
if (awaitingToolCallIds.length > 0) deferredNonToolMessages.push(entry);
|
|
32244
|
+
else messages.push(entry);
|
|
32245
|
+
};
|
|
32246
|
+
const flushToolImages = () => {
|
|
32247
|
+
if (pendingToolImages.length === 0) return;
|
|
32248
|
+
const imageContent = pendingToolImages;
|
|
32249
|
+
pendingToolImages = [];
|
|
32250
|
+
emitNonTool({
|
|
32251
|
+
role: "user",
|
|
32252
|
+
content: imageContent
|
|
32253
|
+
});
|
|
32254
|
+
};
|
|
32255
|
+
const flushDeferred = () => {
|
|
32256
|
+
flushToolImages();
|
|
32257
|
+
if (deferredNonToolMessages.length === 0) return;
|
|
32258
|
+
messages.push(...deferredNonToolMessages);
|
|
32259
|
+
deferredNonToolMessages = [];
|
|
32260
|
+
};
|
|
32261
|
+
const settleOpenToolCalls = () => {
|
|
32262
|
+
if (awaitingToolCallIds.length > 0) {
|
|
32263
|
+
for (const id of awaitingToolCallIds) messages.push({
|
|
32264
|
+
role: "tool",
|
|
32265
|
+
tool_call_id: id,
|
|
32266
|
+
content: NO_TOOL_RESULT_TEXT
|
|
32267
|
+
});
|
|
32268
|
+
awaitingToolCallIds = [];
|
|
32269
|
+
}
|
|
32270
|
+
flushDeferred();
|
|
32271
|
+
};
|
|
32085
32272
|
const slots = declarationSlots(options, media);
|
|
32086
32273
|
let slotIndex = 0;
|
|
32087
32274
|
let nonSystemIndex = 0;
|
|
32088
32275
|
const flushSlots = (upTo) => {
|
|
32089
32276
|
while (slotIndex < slots.length && slots[slotIndex].beforeIndex <= upTo) {
|
|
32090
|
-
|
|
32277
|
+
for (const entry of slots[slotIndex].entries) emitNonTool(entry);
|
|
32091
32278
|
slotIndex += 1;
|
|
32092
32279
|
}
|
|
32093
32280
|
};
|
|
@@ -32098,49 +32285,61 @@ function buildOpenAIRequest(options, images = NO_RESOLVED_IMAGES$3, preserveThin
|
|
|
32098
32285
|
flushSlots(nonSystemIndex);
|
|
32099
32286
|
nonSystemIndex += 1;
|
|
32100
32287
|
if (isToolResultMessage$7(message)) {
|
|
32101
|
-
const
|
|
32288
|
+
const batch = [];
|
|
32102
32289
|
while (index < conversation.length && isToolResultMessage$7(conversation[index])) {
|
|
32103
32290
|
const current = conversation[index];
|
|
32104
|
-
|
|
32291
|
+
const block = current.content[0];
|
|
32292
|
+
const rawCallId = isRecord$53(block) && typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
32293
|
+
batch.push({
|
|
32294
|
+
id: toolCallIds.normalize(rawCallId),
|
|
32295
|
+
content: toolResultText$7(current.content),
|
|
32296
|
+
images: toolResultImageBlocks$4(current.content, images, media)
|
|
32297
|
+
});
|
|
32298
|
+
if (index + 1 < conversation.length && isToolResultMessage$7(conversation[index + 1])) {
|
|
32105
32299
|
flushSlots(nonSystemIndex);
|
|
32106
32300
|
nonSystemIndex += 1;
|
|
32301
|
+
index += 1;
|
|
32302
|
+
continue;
|
|
32107
32303
|
}
|
|
32108
|
-
|
|
32109
|
-
|
|
32304
|
+
break;
|
|
32305
|
+
}
|
|
32306
|
+
for (const entry of pairToolExchanges(batch, awaitingToolCallIds)) {
|
|
32110
32307
|
messages.push({
|
|
32111
32308
|
role: "tool",
|
|
32112
|
-
tool_call_id:
|
|
32113
|
-
content:
|
|
32309
|
+
tool_call_id: entry.id,
|
|
32310
|
+
content: entry.content
|
|
32114
32311
|
});
|
|
32115
|
-
|
|
32116
|
-
|
|
32312
|
+
pendingToolImages.push(...entry.images);
|
|
32313
|
+
if (awaitingToolCallIds.length > 0) {
|
|
32314
|
+
awaitingToolCallIds = awaitingToolCallIds.filter((id) => id !== entry.id);
|
|
32315
|
+
if (awaitingToolCallIds.length === 0) flushDeferred();
|
|
32316
|
+
}
|
|
32117
32317
|
}
|
|
32118
|
-
|
|
32119
|
-
if (imageBlocks.length > 0) messages.push({
|
|
32120
|
-
role: "user",
|
|
32121
|
-
content: imageBlocks
|
|
32122
|
-
});
|
|
32318
|
+
if (awaitingToolCallIds.length === 0) flushToolImages();
|
|
32123
32319
|
continue;
|
|
32124
32320
|
}
|
|
32125
32321
|
if (message.role === "assistant") {
|
|
32126
32322
|
const reasoningKey = reasoningDialect.outboundKey();
|
|
32127
32323
|
const { content, toolCalls, reasoning } = openAIAssistantContent$3(message, toolCallIds, reasoningKey);
|
|
32128
32324
|
if (content === "" && toolCalls.length === 0 && reasoning.fields.length === 0 && reasoning.details.length === 0) continue;
|
|
32325
|
+
settleOpenToolCalls();
|
|
32129
32326
|
const entry = { role: "assistant" };
|
|
32130
32327
|
if (content !== "" || toolCalls.length === 0) entry.content = content;
|
|
32131
32328
|
if (toolCalls.length > 0) entry.tool_calls = toolCalls;
|
|
32132
32329
|
if (thinkingOn) applyReplayedReasoning(entry, reasoning, reasoningKey);
|
|
32133
32330
|
messages.push(entry);
|
|
32331
|
+
awaitingToolCallIds = toolCalls.map((call) => typeof call.id === "string" ? call.id : "").filter((id) => id !== "");
|
|
32134
32332
|
continue;
|
|
32135
32333
|
}
|
|
32136
32334
|
const content = openAIUserContent$3(message, images, media);
|
|
32137
32335
|
if (typeof content === "string" && content === "") continue;
|
|
32138
|
-
|
|
32336
|
+
emitNonTool({
|
|
32139
32337
|
role: "user",
|
|
32140
32338
|
content
|
|
32141
32339
|
});
|
|
32142
32340
|
}
|
|
32143
32341
|
flushSlots(nonSystemIndex);
|
|
32342
|
+
settleOpenToolCalls();
|
|
32144
32343
|
const topLevelTools = (options.tools ?? []).filter((tool) => tool.deferLoading !== true);
|
|
32145
32344
|
const maxTokens = options.maxTokens ?? maxOutputTokensFor$5(options.model);
|
|
32146
32345
|
const body = {
|
|
@@ -32210,7 +32409,7 @@ function firstTextOf(content) {
|
|
|
32210
32409
|
}
|
|
32211
32410
|
if (!Array.isArray(content)) return void 0;
|
|
32212
32411
|
for (const block of content) {
|
|
32213
|
-
if (!isRecord$
|
|
32412
|
+
if (!isRecord$53(block)) continue;
|
|
32214
32413
|
if (block.type === "text" && typeof block.text === "string") {
|
|
32215
32414
|
const text = sanitizeText$7(block.text);
|
|
32216
32415
|
if (text !== "") return text;
|
|
@@ -32268,7 +32467,7 @@ function isSideChannelTitleRequest(options) {
|
|
|
32268
32467
|
const tools = options.tools;
|
|
32269
32468
|
const toolLess = tools === void 0 || tools.length === 0;
|
|
32270
32469
|
for (const message of messages) {
|
|
32271
|
-
if (!isRecord$
|
|
32470
|
+
if (!isRecord$53(message)) continue;
|
|
32272
32471
|
if (message.source?.kind === "dsh-session-title-llm") return true;
|
|
32273
32472
|
const text = firstTextOf(message.content);
|
|
32274
32473
|
if (toolLess && text !== void 0 && text.startsWith(TITLE_REQUEST_PROMPT_PREFIX)) return true;
|
|
@@ -32295,15 +32494,70 @@ function promptCacheKey(options) {
|
|
|
32295
32494
|
if (isSideChannelTitleRequest(options)) return void 0;
|
|
32296
32495
|
if (typeof options.sessionId === "string" && options.sessionId.trim() !== "") return `dsh-${options.sessionId.trim()}`;
|
|
32297
32496
|
}
|
|
32298
|
-
|
|
32497
|
+
/**
|
|
32498
|
+
* The Anthropic beta that carries the context-management edit.
|
|
32499
|
+
*
|
|
32500
|
+
* `clear_thinking_20251015` is honoured only on the beta Messages API, so the
|
|
32501
|
+
* beta has to travel WITH the request; the official Kimi Anthropic protocol
|
|
32502
|
+
* asks for it on every thinking request (see the upstream
|
|
32503
|
+
* `kimiAnthropicProtocol`, which returns `betaFeatures: [CONTEXT_MANAGEMENT_BETA]`
|
|
32504
|
+
* for both the enabled and the disabled encoding).
|
|
32505
|
+
*/
|
|
32506
|
+
const CONTEXT_MANAGEMENT_BETA = "context-management-2025-06-27";
|
|
32507
|
+
/**
|
|
32508
|
+
* The Anthropic context edit that clears stale thinking blocks.
|
|
32509
|
+
*
|
|
32510
|
+
* The edit is what "keep the thinking across turns" means on this wire: the
|
|
32511
|
+
* service clears the thinking it has already consumed instead of replaying it,
|
|
32512
|
+
* so a preserved thinking block stays affordable.
|
|
32513
|
+
*/
|
|
32514
|
+
const CLEAR_THINKING_EDIT = "clear_thinking_20251015";
|
|
32515
|
+
/** The cache breakpoint the Anthropic wire marks with. */
|
|
32516
|
+
const ANTHROPIC_CACHE_CONTROL = { type: "ephemeral" };
|
|
32517
|
+
/**
|
|
32518
|
+
* The content block types that accept a cache breakpoint.
|
|
32519
|
+
*
|
|
32520
|
+
* The official provider injects the breakpoint on the last block of the last
|
|
32521
|
+
* message, and only when that block is one of the cacheable kinds; a block
|
|
32522
|
+
* that cannot carry the marker is left alone rather than given a field the
|
|
32523
|
+
* service would reject.
|
|
32524
|
+
*/
|
|
32525
|
+
const ANTHROPIC_CACHEABLE_BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
32526
|
+
"text",
|
|
32527
|
+
"image",
|
|
32528
|
+
"document",
|
|
32529
|
+
"tool_use",
|
|
32530
|
+
"tool_result"
|
|
32531
|
+
]);
|
|
32532
|
+
function anthropicUserContent$2(message, images, toolCallIds, media = {}) {
|
|
32299
32533
|
if (!Array.isArray(message.content)) return [];
|
|
32300
32534
|
const blocks = [];
|
|
32301
32535
|
for (const block of message.content) {
|
|
32302
|
-
if (!isRecord$
|
|
32536
|
+
if (!isRecord$53(block)) continue;
|
|
32303
32537
|
if (block.type === "video") {
|
|
32304
|
-
|
|
32538
|
+
const reference = hostedReference(media.videoReferences, block);
|
|
32539
|
+
if (reference !== void 0) {
|
|
32540
|
+
blocks.push({
|
|
32541
|
+
type: "video",
|
|
32542
|
+
source: {
|
|
32543
|
+
type: "url",
|
|
32544
|
+
url: reference
|
|
32545
|
+
}
|
|
32546
|
+
});
|
|
32547
|
+
continue;
|
|
32548
|
+
}
|
|
32549
|
+
const outcome = videoBlockToInline(block, media.videos ?? /* @__PURE__ */ new Map(), media.videoAccepted === true, videoOmissionText$1);
|
|
32550
|
+
if ("inline" in outcome) blocks.push({
|
|
32551
|
+
type: "video",
|
|
32552
|
+
source: {
|
|
32553
|
+
type: "base64",
|
|
32554
|
+
media_type: outcome.inline.mediaType,
|
|
32555
|
+
data: outcome.inline.data
|
|
32556
|
+
}
|
|
32557
|
+
});
|
|
32558
|
+
else blocks.push({
|
|
32305
32559
|
type: "text",
|
|
32306
|
-
text:
|
|
32560
|
+
text: outcome.omission
|
|
32307
32561
|
});
|
|
32308
32562
|
continue;
|
|
32309
32563
|
}
|
|
@@ -32314,19 +32568,29 @@ function anthropicUserContent$2(message, images, toolCallIds) {
|
|
|
32314
32568
|
text
|
|
32315
32569
|
});
|
|
32316
32570
|
} else if (block.type === "image") {
|
|
32317
|
-
const
|
|
32318
|
-
if (
|
|
32571
|
+
const reference = hostedReference(media.imageReferences, block);
|
|
32572
|
+
if (reference !== void 0) blocks.push({
|
|
32319
32573
|
type: "image",
|
|
32320
32574
|
source: {
|
|
32321
|
-
type: "
|
|
32322
|
-
|
|
32323
|
-
data: inline.data
|
|
32575
|
+
type: "url",
|
|
32576
|
+
url: reference
|
|
32324
32577
|
}
|
|
32325
32578
|
});
|
|
32326
|
-
else
|
|
32327
|
-
|
|
32328
|
-
|
|
32329
|
-
|
|
32579
|
+
else {
|
|
32580
|
+
const inline = imageBlockToInline$2(block, images);
|
|
32581
|
+
if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$3.has(inline.mediaType)) blocks.push({
|
|
32582
|
+
type: "image",
|
|
32583
|
+
source: {
|
|
32584
|
+
type: "base64",
|
|
32585
|
+
media_type: inline.mediaType,
|
|
32586
|
+
data: inline.data
|
|
32587
|
+
}
|
|
32588
|
+
});
|
|
32589
|
+
else blocks.push({
|
|
32590
|
+
type: "text",
|
|
32591
|
+
text: unavailableImageText$3(block)
|
|
32592
|
+
});
|
|
32593
|
+
}
|
|
32330
32594
|
} else if (block.type === "tool-result") {
|
|
32331
32595
|
const callId = typeof block.toolCallId === "string" ? block.toolCallId : "";
|
|
32332
32596
|
const resultBlocks = toolResultBlocks$1(block.content, images);
|
|
@@ -32343,20 +32607,28 @@ function anthropicUserContent$2(message, images, toolCallIds) {
|
|
|
32343
32607
|
function anthropicAssistantContent$2(message, toolCallIds) {
|
|
32344
32608
|
const blocks = [];
|
|
32345
32609
|
for (const block of message.content) {
|
|
32346
|
-
if (!isRecord$
|
|
32610
|
+
if (!isRecord$53(block)) continue;
|
|
32347
32611
|
if (block.type === "text" && typeof block.text === "string") {
|
|
32348
32612
|
const text = sanitizeText$7(block.text);
|
|
32349
32613
|
if (text !== "") blocks.push({
|
|
32350
32614
|
type: "text",
|
|
32351
32615
|
text
|
|
32352
32616
|
});
|
|
32617
|
+
} else if (block.type === "reasoning") {
|
|
32618
|
+
const thinkingText = typeof block.text === "string" ? sanitizeText$7(block.text) : "";
|
|
32619
|
+
const sig = typeof block.signature === "string" && block.signature.trim() !== "" ? block.signature : void 0;
|
|
32620
|
+
if (thinkingText !== "" || sig !== void 0) blocks.push({
|
|
32621
|
+
type: "thinking",
|
|
32622
|
+
thinking: thinkingText,
|
|
32623
|
+
...sig === void 0 ? {} : { signature: sig }
|
|
32624
|
+
});
|
|
32353
32625
|
} else if (block.type === "tool-call" && typeof block.name === "string") {
|
|
32354
32626
|
const parsed = safeJsonParse$7(toolCallArguments$6(block.arguments));
|
|
32355
32627
|
blocks.push({
|
|
32356
32628
|
type: "tool_use",
|
|
32357
32629
|
id: toolCallIds.normalize(typeof block.id === "string" && block.id !== "" ? block.id : `toolu_${blocks.length}`),
|
|
32358
32630
|
name: block.name,
|
|
32359
|
-
input: isRecord$
|
|
32631
|
+
input: isRecord$53(parsed) ? parsed : {}
|
|
32360
32632
|
});
|
|
32361
32633
|
}
|
|
32362
32634
|
}
|
|
@@ -32387,7 +32659,7 @@ function mergeAnthropicMessages$2(entries) {
|
|
|
32387
32659
|
return merged;
|
|
32388
32660
|
}
|
|
32389
32661
|
/** Build one `/v1/messages` body. */
|
|
32390
|
-
function buildAnthropicRequest(options, images = NO_RESOLVED_IMAGES$3, media = {}) {
|
|
32662
|
+
function buildAnthropicRequest(options, images = NO_RESOLVED_IMAGES$3, media = {}, preserveThinking = preserveThinkingEnabled()) {
|
|
32391
32663
|
const toolCallIds = new ToolCallIdNormalizer();
|
|
32392
32664
|
const carriers = options.messages.filter((message) => message.role === "system" && messageToolsOf(message) !== void 0);
|
|
32393
32665
|
const unsentDeclarations = carriers.reduce((total, message) => total + (messageToolsOf(message)?.length ?? 0), 0);
|
|
@@ -32397,13 +32669,13 @@ function buildAnthropicRequest(options, images = NO_RESOLVED_IMAGES$3, media = {
|
|
|
32397
32669
|
if (isToolResultMessage$7(message)) {
|
|
32398
32670
|
entries.push({
|
|
32399
32671
|
role: "user",
|
|
32400
|
-
content: anthropicUserContent$2(message, images, toolCallIds)
|
|
32672
|
+
content: anthropicUserContent$2(message, images, toolCallIds, media)
|
|
32401
32673
|
});
|
|
32402
32674
|
continue;
|
|
32403
32675
|
}
|
|
32404
32676
|
entries.push({
|
|
32405
32677
|
role: message.role === "assistant" ? "assistant" : "user",
|
|
32406
|
-
content: message.role === "assistant" ? anthropicAssistantContent$2(message, toolCallIds) : anthropicUserContent$2(message, images, toolCallIds)
|
|
32678
|
+
content: message.role === "assistant" ? anthropicAssistantContent$2(message, toolCallIds) : anthropicUserContent$2(message, images, toolCallIds, media)
|
|
32407
32679
|
});
|
|
32408
32680
|
}
|
|
32409
32681
|
const systemParts = [
|
|
@@ -32414,31 +32686,54 @@ function buildAnthropicRequest(options, images = NO_RESOLVED_IMAGES$3, media = {
|
|
|
32414
32686
|
const system = systemParts.length === 0 ? void 0 : systemParts.join("\n\n");
|
|
32415
32687
|
const maxTokens = options.maxTokens ?? maxOutputTokensFor$5(options.model);
|
|
32416
32688
|
const effort = mapReasoningEffort(options.reasoningEffort === void 0 ? void 0 : String(options.reasoningEffort));
|
|
32417
|
-
const
|
|
32689
|
+
const thinkingOff = effort === "none";
|
|
32690
|
+
const thinkingField = thinkingOff ? { type: "disabled" } : { type: "enabled" };
|
|
32691
|
+
const outputConfig = !thinkingOff && effort !== void 0 ? { effort } : void 0;
|
|
32692
|
+
const keepThinking = preserveThinking && !thinkingOff;
|
|
32693
|
+
const betas = [CONTEXT_MANAGEMENT_BETA];
|
|
32694
|
+
const contextManagement = keepThinking ? { edits: [{
|
|
32695
|
+
type: CLEAR_THINKING_EDIT,
|
|
32696
|
+
keep: "all"
|
|
32697
|
+
}] } : void 0;
|
|
32698
|
+
const messages = mergeAnthropicMessages$2(entries);
|
|
32699
|
+
const lastMessage = messages[messages.length - 1];
|
|
32700
|
+
if (lastMessage !== void 0 && Array.isArray(lastMessage.content) && lastMessage.content.length > 0) {
|
|
32701
|
+
const lastBlock = lastMessage.content[lastMessage.content.length - 1];
|
|
32702
|
+
if (lastBlock !== void 0 && ANTHROPIC_CACHEABLE_BLOCK_TYPES.has(String(lastBlock.type))) lastBlock.cache_control = { ...ANTHROPIC_CACHE_CONTROL };
|
|
32703
|
+
}
|
|
32704
|
+
const tools = options.tools && options.tools.length > 0 ? options.tools.map((tool) => ({
|
|
32705
|
+
name: tool.name,
|
|
32706
|
+
description: tool.description,
|
|
32707
|
+
input_schema: normalizeKimiToolSchema(tool.parameters)
|
|
32708
|
+
})) : [];
|
|
32709
|
+
if (tools.length > 0) tools[tools.length - 1] = {
|
|
32710
|
+
...tools[tools.length - 1],
|
|
32711
|
+
cache_control: { ...ANTHROPIC_CACHE_CONTROL }
|
|
32712
|
+
};
|
|
32418
32713
|
return {
|
|
32419
32714
|
model: options.model,
|
|
32420
32715
|
max_tokens: maxTokens,
|
|
32421
|
-
messages
|
|
32422
|
-
...system === void 0 ? {} : { system
|
|
32423
|
-
|
|
32716
|
+
messages,
|
|
32717
|
+
...system === void 0 ? {} : { system: [{
|
|
32718
|
+
type: "text",
|
|
32719
|
+
text: system,
|
|
32720
|
+
cache_control: { ...ANTHROPIC_CACHE_CONTROL }
|
|
32721
|
+
}] },
|
|
32722
|
+
...options.temperature === void 0 || !thinkingOff ? {} : { temperature: options.temperature },
|
|
32424
32723
|
...options.stop && options.stop.length > 0 ? { stop_sequences: options.stop } : {},
|
|
32425
|
-
...
|
|
32426
|
-
|
|
32427
|
-
|
|
32428
|
-
|
|
32429
|
-
|
|
32430
|
-
...effort === void 0 ? {} : budget === void 0 ? { thinking: { type: "disabled" } } : { thinking: {
|
|
32431
|
-
type: "enabled",
|
|
32432
|
-
budget_tokens: budget
|
|
32433
|
-
} }
|
|
32724
|
+
...tools.length > 0 ? { tools } : {},
|
|
32725
|
+
thinking: thinkingField,
|
|
32726
|
+
...outputConfig === void 0 ? {} : { output_config: outputConfig },
|
|
32727
|
+
...contextManagement === void 0 ? {} : { context_management: contextManagement },
|
|
32728
|
+
betas
|
|
32434
32729
|
};
|
|
32435
32730
|
}
|
|
32436
32731
|
/** Build the body for whichever endpoint serves `wire`. */
|
|
32437
32732
|
function buildRequest(options, wire, images = NO_RESOLVED_IMAGES$3, preserveThinking = preserveThinkingEnabled(), media = {}) {
|
|
32438
|
-
if (isSideChannelTitleRequest(options)) return wire === "anthropic" ? buildAnthropicRequest(options, images, media) : buildOpenAIRequest(options, images, preserveThinking, media);
|
|
32733
|
+
if (isSideChannelTitleRequest(options)) return wire === "anthropic" ? buildAnthropicRequest(options, images, media, preserveThinking) : buildOpenAIRequest(options, images, preserveThinking, media);
|
|
32439
32734
|
const cause = trackPrefixStability(options);
|
|
32440
32735
|
recordDriftCause(cause === "stable" && (pendingImageOffloads.get(cacheScopeKey(options.sessionId)) ?? 0) > 0 ? "image-offload" : cause, options.sessionId, options);
|
|
32441
|
-
return wire === "anthropic" ? buildAnthropicRequest(options, images, media) : buildOpenAIRequest(options, images, preserveThinking, media);
|
|
32736
|
+
return wire === "anthropic" ? buildAnthropicRequest(options, images, media, preserveThinking) : buildOpenAIRequest(options, images, preserveThinking, media);
|
|
32442
32737
|
}
|
|
32443
32738
|
/**
|
|
32444
32739
|
* Reject a request the service would refuse for its size.
|
|
@@ -32480,7 +32775,7 @@ function walkJson(value, visit) {
|
|
|
32480
32775
|
for (const item of value) walkJson(item, visit);
|
|
32481
32776
|
return;
|
|
32482
32777
|
}
|
|
32483
|
-
if (!isRecord$
|
|
32778
|
+
if (!isRecord$53(value)) return;
|
|
32484
32779
|
visit(value);
|
|
32485
32780
|
for (const nested of Object.values(value)) walkJson(nested, visit);
|
|
32486
32781
|
}
|
|
@@ -32496,12 +32791,12 @@ function requestBodyBreakdown(body, carriesVideo = false) {
|
|
|
32496
32791
|
const totalBytes = Buffer.byteLength(serialized, "utf8");
|
|
32497
32792
|
let imageBytes = 0;
|
|
32498
32793
|
walkJson(body, (node) => {
|
|
32499
|
-
const url = isRecord$
|
|
32794
|
+
const url = isRecord$53(node.image_url) ? asString$21(node.image_url.url) : void 0;
|
|
32500
32795
|
if (url?.startsWith("data:")) {
|
|
32501
32796
|
imageBytes += Buffer.byteLength(url, "utf8");
|
|
32502
32797
|
return;
|
|
32503
32798
|
}
|
|
32504
|
-
const source = isRecord$
|
|
32799
|
+
const source = isRecord$53(node.source) ? node.source : void 0;
|
|
32505
32800
|
if (source && asString$21(source.data) !== void 0 && asString$21(source.media_type) !== void 0) imageBytes += Buffer.byteLength(asString$21(source.data) ?? "", "utf8");
|
|
32506
32801
|
});
|
|
32507
32802
|
const toolSchemaBytes = Buffer.byteLength(JSON.stringify(body.tools ?? []), "utf8");
|
|
@@ -32628,9 +32923,9 @@ function processOpenAIStreamLine(line, state) {
|
|
|
32628
32923
|
}
|
|
32629
32924
|
if (payload === "") return [];
|
|
32630
32925
|
const chunk = safeJsonParse$7(payload);
|
|
32631
|
-
if (!isRecord$
|
|
32926
|
+
if (!isRecord$53(chunk)) return [];
|
|
32632
32927
|
const out = [];
|
|
32633
|
-
const errorPayload = isRecord$
|
|
32928
|
+
const errorPayload = isRecord$53(chunk.error) ? chunk.error : void 0;
|
|
32634
32929
|
if (errorPayload !== void 0) {
|
|
32635
32930
|
const message = asString$21(errorPayload.message) ?? "unknown error";
|
|
32636
32931
|
state.streamError = {
|
|
@@ -32640,22 +32935,22 @@ function processOpenAIStreamLine(line, state) {
|
|
|
32640
32935
|
};
|
|
32641
32936
|
throw new LlmError$1(`Kimi Code stream error: ${message}`, isContextOverflow(errorPayload) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
|
|
32642
32937
|
}
|
|
32643
|
-
const usage = isRecord$
|
|
32938
|
+
const usage = isRecord$53(chunk.usage) ? chunk.usage : void 0;
|
|
32644
32939
|
if (usage) {
|
|
32645
32940
|
state.sawUsage = true;
|
|
32646
32941
|
const prompt = numberOr$8(usage.prompt_tokens, 0);
|
|
32647
|
-
const details = isRecord$
|
|
32942
|
+
const details = isRecord$53(usage.prompt_tokens_details) ? usage.prompt_tokens_details : void 0;
|
|
32648
32943
|
const cached = details ? numberOr$8(details.cached_tokens, 0) : 0;
|
|
32649
32944
|
const written = details ? numberOr$8(details.cache_write_tokens, 0) : 0;
|
|
32650
32945
|
state.inputTokens = Math.max(0, prompt - cached - written);
|
|
32651
32946
|
state.cacheReadTokens = cached;
|
|
32652
32947
|
state.cacheWriteTokens = written;
|
|
32653
32948
|
state.outputTokens = numberOr$8(usage.completion_tokens, state.outputTokens);
|
|
32654
|
-
if (isRecord$
|
|
32949
|
+
if (isRecord$53(usage.completion_tokens_details)) state.reasoningTokens = numberOr$8(usage.completion_tokens_details.reasoning_tokens, state.reasoningTokens);
|
|
32655
32950
|
}
|
|
32656
32951
|
const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
|
|
32657
|
-
const choice = isRecord$
|
|
32658
|
-
const delta = isRecord$
|
|
32952
|
+
const choice = isRecord$53(choices[0]) ? choices[0] : void 0;
|
|
32953
|
+
const delta = isRecord$53(choice?.delta) ? choice.delta : void 0;
|
|
32659
32954
|
if (delta) {
|
|
32660
32955
|
for (const fragment of reasoningDialect.observeAll(delta)) {
|
|
32661
32956
|
const text = sanitizeText$7(fragment.text);
|
|
@@ -32696,7 +32991,7 @@ function processOpenAIStreamLine(line, state) {
|
|
|
32696
32991
|
}
|
|
32697
32992
|
const toolDeltas = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];
|
|
32698
32993
|
for (const entry of toolDeltas) {
|
|
32699
|
-
if (!isRecord$
|
|
32994
|
+
if (!isRecord$53(entry)) continue;
|
|
32700
32995
|
out.push(...applyOpenAIToolDelta(entry, state));
|
|
32701
32996
|
}
|
|
32702
32997
|
}
|
|
@@ -32710,7 +33005,7 @@ function processOpenAIStreamLine(line, state) {
|
|
|
32710
33005
|
}
|
|
32711
33006
|
function applyOpenAIToolDelta(entry, state) {
|
|
32712
33007
|
const wireIndex = typeof entry.index === "number" ? entry.index : 0;
|
|
32713
|
-
const fn = isRecord$
|
|
33008
|
+
const fn = isRecord$53(entry.function) ? entry.function : {};
|
|
32714
33009
|
const out = [];
|
|
32715
33010
|
let call = state.toolCalls.get(wireIndex);
|
|
32716
33011
|
if (call === void 0) {
|
|
@@ -32765,12 +33060,12 @@ function processAnthropicStreamLine(line, state) {
|
|
|
32765
33060
|
const payload = trimmed.slice(5).trim();
|
|
32766
33061
|
if (payload === "" || payload === "[DONE]") return [];
|
|
32767
33062
|
const event = safeJsonParse$7(payload);
|
|
32768
|
-
if (!isRecord$
|
|
33063
|
+
if (!isRecord$53(event)) return [];
|
|
32769
33064
|
const type = asString$21(event.type);
|
|
32770
33065
|
const out = [];
|
|
32771
33066
|
if (type === "message_start") {
|
|
32772
|
-
const message = isRecord$
|
|
32773
|
-
const usage = message && isRecord$
|
|
33067
|
+
const message = isRecord$53(event.message) ? event.message : void 0;
|
|
33068
|
+
const usage = message && isRecord$53(message.usage) ? message.usage : void 0;
|
|
32774
33069
|
if (usage) {
|
|
32775
33070
|
state.sawUsage = true;
|
|
32776
33071
|
state.inputTokens = numberOr$8(usage.input_tokens, 0);
|
|
@@ -32784,7 +33079,7 @@ function processAnthropicStreamLine(line, state) {
|
|
|
32784
33079
|
}
|
|
32785
33080
|
if (type === "content_block_start") {
|
|
32786
33081
|
const contentIndex = numberOr$8(event.index, 0);
|
|
32787
|
-
const block = isRecord$
|
|
33082
|
+
const block = isRecord$53(event.content_block) ? event.content_block : {};
|
|
32788
33083
|
const blockType = asString$21(block.type);
|
|
32789
33084
|
out.push(...closeCurrent$5(state));
|
|
32790
33085
|
if (blockType === "tool_use") {
|
|
@@ -32834,7 +33129,7 @@ function processAnthropicStreamLine(line, state) {
|
|
|
32834
33129
|
}
|
|
32835
33130
|
if (type === "content_block_delta") {
|
|
32836
33131
|
const contentIndex = numberOr$8(event.index, 0);
|
|
32837
|
-
const delta = isRecord$
|
|
33132
|
+
const delta = isRecord$53(event.delta) ? event.delta : {};
|
|
32838
33133
|
const deltaType = asString$21(delta.type);
|
|
32839
33134
|
if (deltaType === "input_json_delta") {
|
|
32840
33135
|
const pending = state.toolCalls.get(contentIndex);
|
|
@@ -32907,10 +33202,10 @@ function processAnthropicStreamLine(line, state) {
|
|
|
32907
33202
|
return out;
|
|
32908
33203
|
}
|
|
32909
33204
|
if (type === "message_delta") {
|
|
32910
|
-
const delta = isRecord$
|
|
33205
|
+
const delta = isRecord$53(event.delta) ? event.delta : void 0;
|
|
32911
33206
|
const stop = delta ? asString$21(delta.stop_reason) : void 0;
|
|
32912
33207
|
if (stop !== void 0 && stop !== "") state.finishReason = stop;
|
|
32913
|
-
const usage = isRecord$
|
|
33208
|
+
const usage = isRecord$53(event.usage) ? event.usage : void 0;
|
|
32914
33209
|
if (usage) {
|
|
32915
33210
|
state.sawUsage = true;
|
|
32916
33211
|
state.outputTokens = numberOr$8(usage.output_tokens, state.outputTokens);
|
|
@@ -32922,7 +33217,7 @@ function processAnthropicStreamLine(line, state) {
|
|
|
32922
33217
|
return closeStream$4(state);
|
|
32923
33218
|
}
|
|
32924
33219
|
if (type === "error") {
|
|
32925
|
-
const error = isRecord$
|
|
33220
|
+
const error = isRecord$53(event.error) ? event.error : {};
|
|
32926
33221
|
const message = asString$21(error.message) ?? "unknown error";
|
|
32927
33222
|
state.streamError = {
|
|
32928
33223
|
vocabulary: "anthropic",
|
|
@@ -33513,7 +33808,7 @@ var SessionCacheStateStore = class {
|
|
|
33513
33808
|
/** Validate one parsed document, dropping entries that do not describe a record. */
|
|
33514
33809
|
function normalizeDocument(value) {
|
|
33515
33810
|
const sessions = {};
|
|
33516
|
-
if (isRecord$
|
|
33811
|
+
if (isRecord$52(value) && isRecord$52(value.sessions)) for (const [key, entry] of Object.entries(value.sessions)) {
|
|
33517
33812
|
const record = normalizeRecord(entry);
|
|
33518
33813
|
if (record !== void 0) sessions[key] = record;
|
|
33519
33814
|
}
|
|
@@ -33523,7 +33818,7 @@ function normalizeDocument(value) {
|
|
|
33523
33818
|
};
|
|
33524
33819
|
}
|
|
33525
33820
|
function normalizeRecord(value) {
|
|
33526
|
-
if (!isRecord$
|
|
33821
|
+
if (!isRecord$52(value)) return void 0;
|
|
33527
33822
|
const lastActiveAt = finite(value.lastActiveAt);
|
|
33528
33823
|
const updatedAt = finite(value.updatedAt);
|
|
33529
33824
|
if (lastActiveAt === void 0 || updatedAt === void 0) return void 0;
|
|
@@ -33611,7 +33906,7 @@ function resolveSessionCacheView(sessionId, memory, durable) {
|
|
|
33611
33906
|
}
|
|
33612
33907
|
/** The process-wide store the adapter writes and the routes read. */
|
|
33613
33908
|
const sessionCacheState = new SessionCacheStateStore();
|
|
33614
|
-
function isRecord$
|
|
33909
|
+
function isRecord$52(value) {
|
|
33615
33910
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33616
33911
|
}
|
|
33617
33912
|
function finite(value) {
|
|
@@ -33781,9 +34076,9 @@ function bodyDigest(raw, token) {
|
|
|
33781
34076
|
const text = raw.trim();
|
|
33782
34077
|
if (text === "") return "";
|
|
33783
34078
|
const parsed = parseJson(text);
|
|
33784
|
-
if (parsed.ok && isRecord$
|
|
34079
|
+
if (parsed.ok && isRecord$51(parsed.value)) {
|
|
33785
34080
|
const root = parsed.value;
|
|
33786
|
-
const nested = isRecord$
|
|
34081
|
+
const nested = isRecord$51(root.error) ? root.error : void 0;
|
|
33787
34082
|
const code = firstString(nested?.code) ?? firstString(root.code) ?? firstString(root.error_code) ?? "";
|
|
33788
34083
|
const message = nested !== void 0 ? firstString(nested.message) ?? firstString(nested.code) ?? "" : typeof root.error === "string" ? root.error : firstString(root.message) ?? firstString(root.detail) ?? "";
|
|
33789
34084
|
const composed = [code === "" ? "" : "code=" + code, message].filter((part) => part !== "").join(" ");
|
|
@@ -33819,7 +34114,7 @@ function normalizeFileId(value) {
|
|
|
33819
34114
|
*/
|
|
33820
34115
|
function readFileId$1(value, depth = 0) {
|
|
33821
34116
|
if (depth > 3) return void 0;
|
|
33822
|
-
if (!isRecord$
|
|
34117
|
+
if (!isRecord$51(value)) return void 0;
|
|
33823
34118
|
const direct = normalizeFileId(value.id);
|
|
33824
34119
|
if (direct !== void 0) return direct;
|
|
33825
34120
|
for (const key of NESTED_ID_KEYS) {
|
|
@@ -33866,7 +34161,7 @@ function mediaFileCacheKey(input) {
|
|
|
33866
34161
|
contentSha256(input.data)
|
|
33867
34162
|
].join("|");
|
|
33868
34163
|
}
|
|
33869
|
-
function isRecord$
|
|
34164
|
+
function isRecord$51(value) {
|
|
33870
34165
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33871
34166
|
}
|
|
33872
34167
|
function firstString(value) {
|
|
@@ -35223,6 +35518,7 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
35223
35518
|
* this request still carries: see {@link mediaAttachmentIdsIn}.
|
|
35224
35519
|
*/
|
|
35225
35520
|
let measured;
|
|
35521
|
+
let sentBuild;
|
|
35226
35522
|
const pool = this.accountPool;
|
|
35227
35523
|
const tried = /* @__PURE__ */ new Set();
|
|
35228
35524
|
let servedByAccountId;
|
|
@@ -35278,11 +35574,13 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
35278
35574
|
accountScope,
|
|
35279
35575
|
signal
|
|
35280
35576
|
});
|
|
35281
|
-
let
|
|
35577
|
+
let finalBuild = uploads === void 0 ? planned.length === 0 ? measured : buildBodyWithinLimit(baseMedia) : buildBodyWithinLimit({
|
|
35282
35578
|
...baseMedia,
|
|
35283
35579
|
imageReferences: uploads.imageReferences,
|
|
35284
35580
|
videoReferences: uploads.videoReferences
|
|
35285
|
-
})
|
|
35581
|
+
});
|
|
35582
|
+
sentBuild = finalBuild;
|
|
35583
|
+
let body = finalBuild.body;
|
|
35286
35584
|
const post = async (payload) => {
|
|
35287
35585
|
try {
|
|
35288
35586
|
return await fetchWithContextBudgetRecovery(fetchFn)(endpoint, {
|
|
@@ -35321,14 +35619,16 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
35321
35619
|
mediaType: item.mediaType,
|
|
35322
35620
|
data: item.data
|
|
35323
35621
|
});
|
|
35324
|
-
let
|
|
35622
|
+
let inlineBuild;
|
|
35325
35623
|
try {
|
|
35326
|
-
|
|
35624
|
+
inlineBuild = buildBodyWithinLimit(baseMedia);
|
|
35327
35625
|
} catch {
|
|
35328
|
-
|
|
35626
|
+
inlineBuild = void 0;
|
|
35329
35627
|
}
|
|
35330
|
-
if (
|
|
35331
|
-
|
|
35628
|
+
if (inlineBuild !== void 0) {
|
|
35629
|
+
finalBuild = inlineBuild;
|
|
35630
|
+
sentBuild = inlineBuild;
|
|
35631
|
+
body = inlineBuild.body;
|
|
35332
35632
|
response = await post(body);
|
|
35333
35633
|
detail = response.ok ? "" : (await response.text().catch(() => "")).slice(0, 2e3);
|
|
35334
35634
|
}
|
|
@@ -35355,11 +35655,11 @@ var KimiCodeAdapter = class extends LlmAdapter {
|
|
|
35355
35655
|
...after === void 0 ? {} : { providerRetryAfterMs: after }
|
|
35356
35656
|
});
|
|
35357
35657
|
}
|
|
35358
|
-
if (
|
|
35359
|
-
const requestImageBytes = requestImagePayloadLengths(
|
|
35658
|
+
if (sentBuild !== void 0 && !sideChannel) {
|
|
35659
|
+
const requestImageBytes = requestImagePayloadLengths(sentBuild.options, images).reduce((sum, bytes) => sum + bytes, 0);
|
|
35360
35660
|
const trimmedKeys = new Set(collectRemainingImageKeys(imageTrimmed, images));
|
|
35361
|
-
const
|
|
35362
|
-
const bodyFitDroppedKeys = [...trimmedKeys].filter((key) => !
|
|
35661
|
+
const sentKeys = new Set(collectRemainingImageKeys(sentBuild.options, images));
|
|
35662
|
+
const bodyFitDroppedKeys = [...trimmedKeys].filter((key) => !sentKeys.has(key));
|
|
35363
35663
|
const allDroppedKeys = /* @__PURE__ */ new Set([...stickyOffload.allDroppedKeys, ...bodyFitDroppedKeys]);
|
|
35364
35664
|
recordSessionImageBudget(options.sessionId, {
|
|
35365
35665
|
allDroppedKeys,
|
|
@@ -36648,7 +36948,7 @@ const KIMI_VIDEO_TOOL_NAME = "kimi_attach_video";
|
|
|
36648
36948
|
* routed provider is this one, which is the same contract `read_image` states
|
|
36649
36949
|
* for a modality the active model does not declare.
|
|
36650
36950
|
*/
|
|
36651
|
-
const KIMI_CODE_PROVIDER$
|
|
36951
|
+
const KIMI_CODE_PROVIDER$2 = "kimi-code";
|
|
36652
36952
|
/**
|
|
36653
36953
|
* Refuse when the session's routed model cannot accept video.
|
|
36654
36954
|
*
|
|
@@ -36662,7 +36962,7 @@ async function assertVideoCapableRoute(ctx, exec, source) {
|
|
|
36662
36962
|
const provider = routed?.provider ?? agent?.options?.provider;
|
|
36663
36963
|
const model = routed?.model ?? agent?.options?.model;
|
|
36664
36964
|
if (provider === void 0 || model === void 0) throw new HarnessError(`cannot attach "${source}": the current model route could not be resolved`, "KIMI_VIDEO_ROUTE_UNRESOLVED");
|
|
36665
|
-
if (provider !== KIMI_CODE_PROVIDER$
|
|
36965
|
+
if (provider !== KIMI_CODE_PROVIDER$2) throw new HarnessError(`cannot attach "${source}": video input is only wired for the ${KIMI_CODE_PROVIDER$2} provider, and this session is routed to "${provider}"`, "KIMI_VIDEO_WRONG_PROVIDER");
|
|
36666
36966
|
const llm = ctx.get("llm");
|
|
36667
36967
|
if (llm === void 0) throw new HarnessError(`cannot attach "${source}": the LLM service is unavailable`, "KIMI_VIDEO_NO_LLM");
|
|
36668
36968
|
const active = await llm.resolveModelInfo(provider, model, exec.signal);
|
|
@@ -36971,6 +37271,18 @@ const MESSAGES_PATH$1 = "/messages";
|
|
|
36971
37271
|
/** Anthropic protocol revision the endpoint documents. */
|
|
36972
37272
|
const ANTHROPIC_VERSION$2 = "2023-06-01";
|
|
36973
37273
|
/**
|
|
37274
|
+
* Beta marker the interleaved-thinking protocol needs.
|
|
37275
|
+
*
|
|
37276
|
+
* The Messages endpoint on this route accepts signed `thinking` blocks and
|
|
37277
|
+
* streams reasoning back in its own channel, and the Anthropic dialect gates
|
|
37278
|
+
* that on the interleaved-thinking beta. The official MiniMax agent sends the
|
|
37279
|
+
* marker on every Messages request (its `model-resolver-helpers.ts`), so a
|
|
37280
|
+
* request without it is shaped differently from the one the service is
|
|
37281
|
+
* documented against - and the replay path on this line has signed thinking
|
|
37282
|
+
* blocks to send.
|
|
37283
|
+
*/
|
|
37284
|
+
const ANTHROPIC_INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
|
|
37285
|
+
/**
|
|
36974
37286
|
* Byte ceiling the guard enforces on one request body.
|
|
36975
37287
|
*
|
|
36976
37288
|
* WHY THIS IS NOT KIMI'S 2 MB FIGURE
|
|
@@ -37059,13 +37371,34 @@ function maxRequestImageBytes(env = process.env) {
|
|
|
37059
37371
|
/**
|
|
37060
37372
|
* Product token this plugin reports.
|
|
37061
37373
|
*
|
|
37062
|
-
*
|
|
37063
|
-
*
|
|
37064
|
-
*
|
|
37065
|
-
* subscription.
|
|
37374
|
+
* This is the plugin's own identity, and it stays honest. MiniMax Code's own
|
|
37375
|
+
* telemetry headers are deliberately NOT forged: this is a third-party client of
|
|
37376
|
+
* the subscription, and claiming to be the official app is both dishonest and,
|
|
37377
|
+
* per the app's own terms, grounds for suspending the subscription.
|
|
37378
|
+
*
|
|
37379
|
+
* The surfaces that carry this token are exactly the first-party ones (the
|
|
37380
|
+
* check-in call, the reset-card call, the usage read), and those are the ones
|
|
37381
|
+
* that must be able to say who is asking. The MODEL request carries
|
|
37382
|
+
* {@link MINIMAX_AGENT_USER_AGENT} instead - a different surface, a different
|
|
37383
|
+
* identifier.
|
|
37066
37384
|
*/
|
|
37067
37385
|
const USER_AGENT$3 = "dsh-chatgpt-subscription (+https://github.com/Aa728848/dsh-chatgpt-subscription)";
|
|
37068
37386
|
/**
|
|
37387
|
+
* Client identifier the managed agent's MODEL requests carry.
|
|
37388
|
+
*
|
|
37389
|
+
* The managed agent classifies a model request by this header, and the official
|
|
37390
|
+
* MiniMax agent sends exactly this value (`model-resolver-helpers.ts:11`, and
|
|
37391
|
+
* the same identifier the Matrix media face uses). A model request that names
|
|
37392
|
+
* something else is shaped differently from the one the service is documented
|
|
37393
|
+
* against - and the model request is the surface that has to speak the
|
|
37394
|
+
* protocol's own identifier.
|
|
37395
|
+
*
|
|
37396
|
+
* It is a separate constant from {@link USER_AGENT} on purpose: the first-party
|
|
37397
|
+
* surfaces keep identifying this plugin honestly, and only the model request
|
|
37398
|
+
* speaks as the agent the endpoint expects.
|
|
37399
|
+
*/
|
|
37400
|
+
const MINIMAX_AGENT_USER_AGENT = "MiniMaxAgent";
|
|
37401
|
+
/**
|
|
37069
37402
|
* How long before expiry a token is replaced.
|
|
37070
37403
|
*
|
|
37071
37404
|
* The measured MiniMax Code access token lives ONE HOUR, not the day an earlier
|
|
@@ -37194,6 +37527,937 @@ function computeMinimaxAuthOwner(credentials, accountId) {
|
|
|
37194
37527
|
return hash.digest("hex").slice(0, 32);
|
|
37195
37528
|
}
|
|
37196
37529
|
//#endregion
|
|
37530
|
+
//#region src/host/minimax-code/runtime-enhancements.ts
|
|
37531
|
+
/** 本模块只对 MiniMax Code 这条线路生效。 */
|
|
37532
|
+
const MINIMAX_CODE_PROVIDER$1 = "minimax-code";
|
|
37533
|
+
/**
|
|
37534
|
+
* 判断一个值是不是普通对象(原型是 `Object.prototype` 或 `null`)。
|
|
37535
|
+
* @param value - 任意值。
|
|
37536
|
+
* @returns 是普通对象时为 true。
|
|
37537
|
+
*/
|
|
37538
|
+
function isPlainRecord$1(value) {
|
|
37539
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
37540
|
+
const prototype = Object.getPrototypeOf(value);
|
|
37541
|
+
return prototype === Object.prototype || prototype === null;
|
|
37542
|
+
}
|
|
37543
|
+
/**
|
|
37544
|
+
* 判断一个值是不是普通对象(不要求原型,数组也算对象)。
|
|
37545
|
+
* @param value - 任意值。
|
|
37546
|
+
* @returns 是对象时为 true。
|
|
37547
|
+
*/
|
|
37548
|
+
function isRecord$50(value) {
|
|
37549
|
+
return typeof value === "object" && value !== null;
|
|
37550
|
+
}
|
|
37551
|
+
/**
|
|
37552
|
+
* 读一个未知字段为非空字符串。
|
|
37553
|
+
* @param value - 候选值。
|
|
37554
|
+
* @returns 字符串,或任何其它类型的 undefined。
|
|
37555
|
+
*/
|
|
37556
|
+
function stringOf$4(value) {
|
|
37557
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
37558
|
+
}
|
|
37559
|
+
/**
|
|
37560
|
+
* 读一次工具调用所属的线路。
|
|
37561
|
+
*
|
|
37562
|
+
* provider 的四个来源按可靠性排序:**请求头快照**(唯一反映「已经真的路由到
|
|
37563
|
+
* 哪个 provider」的那一份)→ **模型选择面**(首步还没有请求头时唯一还能说出
|
|
37564
|
+
* 这一场走哪条线路的地方)→ **agent 选项**(还没发出请求时唯一的意图)→
|
|
37565
|
+
* **agent 自身的 provider 字段**(最后的兜底)。
|
|
37566
|
+
*
|
|
37567
|
+
* 每一处读取都独立 try/catch:任何一处抛错都只是「这一处读不到」,不改变
|
|
37568
|
+
* 其余来源的行为,也不让整次读取失败。
|
|
37569
|
+
*
|
|
37570
|
+
* @param agent - 事件里的调用方 agent。
|
|
37571
|
+
* @returns 线路信息;读不到的字段省略。
|
|
37572
|
+
*/
|
|
37573
|
+
function minimaxSessionRouteOf(agent) {
|
|
37574
|
+
const record = isRecord$50(agent) ? agent : void 0;
|
|
37575
|
+
const session = record?.session;
|
|
37576
|
+
let provider;
|
|
37577
|
+
try {
|
|
37578
|
+
provider = stringOf$4(session?.requestHeader?.()?.config?.provider);
|
|
37579
|
+
} catch {
|
|
37580
|
+
provider = void 0;
|
|
37581
|
+
}
|
|
37582
|
+
if (provider === void 0) try {
|
|
37583
|
+
provider = stringOf$4(record?.model?.current?.()?.provider);
|
|
37584
|
+
} catch {
|
|
37585
|
+
provider = void 0;
|
|
37586
|
+
}
|
|
37587
|
+
if (provider === void 0) provider = stringOf$4(record?.options?.provider);
|
|
37588
|
+
if (provider === void 0) provider = stringOf$4(record?.provider);
|
|
37589
|
+
const sessionId = stringOf$4(session?.header?.id) ?? stringOf$4(record?.id);
|
|
37590
|
+
return {
|
|
37591
|
+
...provider === void 0 ? {} : { provider },
|
|
37592
|
+
...sessionId === void 0 ? {} : { sessionId }
|
|
37593
|
+
};
|
|
37594
|
+
}
|
|
37595
|
+
/**
|
|
37596
|
+
* 判断一次工具调用是不是 MiniMax Code 这条线路上的。
|
|
37597
|
+
* @param agent - 事件里的调用方 agent。
|
|
37598
|
+
* @returns 是 MiniMax Code 时为 true。
|
|
37599
|
+
*/
|
|
37600
|
+
function isMinimaxSession(agent) {
|
|
37601
|
+
return minimaxSessionRouteOf(agent).provider === MINIMAX_CODE_PROVIDER$1;
|
|
37602
|
+
}
|
|
37603
|
+
/** 无损的数字字符串:允许小数、指数、前导负号。 */
|
|
37604
|
+
const NUMERIC_STRING = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/u;
|
|
37605
|
+
/**
|
|
37606
|
+
* 顶层已知的数字字段(没有 schema 时按字段名强转)。
|
|
37607
|
+
*
|
|
37608
|
+
* 这些是本宿主工具面里**本来就该是数字**的字段:模型把它们写成字符串时,
|
|
37609
|
+
* schema 校验会直接失败,而它们强转回来是**无损**的。
|
|
37610
|
+
*/
|
|
37611
|
+
const NUMERIC_TOOL_FIELDS = Object.freeze([
|
|
37612
|
+
"offset",
|
|
37613
|
+
"limit",
|
|
37614
|
+
"timeout",
|
|
37615
|
+
"timeoutMs",
|
|
37616
|
+
"timeout_ms",
|
|
37617
|
+
"line",
|
|
37618
|
+
"delta_x",
|
|
37619
|
+
"delta_y",
|
|
37620
|
+
"x",
|
|
37621
|
+
"y",
|
|
37622
|
+
"ref"
|
|
37623
|
+
]);
|
|
37624
|
+
/**
|
|
37625
|
+
* 顶层已知的布尔字段(没有 schema 时按字段名强转)。
|
|
37626
|
+
*
|
|
37627
|
+
* 只有字面 `"true"` / `"false"` 才转:别的写法(`"1"`、`"yes"`)在布尔
|
|
37628
|
+
* 字段上是**有歧义**的,转过去等于替模型猜了一个开关的状态。
|
|
37629
|
+
*/
|
|
37630
|
+
const BOOLEAN_TOOL_FIELDS = Object.freeze([
|
|
37631
|
+
"replace_all",
|
|
37632
|
+
"wait",
|
|
37633
|
+
"run_in_background",
|
|
37634
|
+
"new_tab",
|
|
37635
|
+
"multi_select"
|
|
37636
|
+
]);
|
|
37637
|
+
/**
|
|
37638
|
+
* 按 schema 强转一个值,并把强转过程记进 `fixes`。
|
|
37639
|
+
*
|
|
37640
|
+
* 只认三种形状:
|
|
37641
|
+
*
|
|
37642
|
+
* - `type: 'array'`:值是单键对象 `{ item: X }` 时拆包(官方 Pi 的
|
|
37643
|
+
* `item_wrapper` 形状),然后按 `items` 递归每个元素;
|
|
37644
|
+
* - `type: 'number' | 'integer'`:值是**无损**数字字符串时转成数字
|
|
37645
|
+
* (`integer` 还要求转出来确实是整数,`"2.5"` 不转);
|
|
37646
|
+
* - `type: 'boolean'`:值是 `"true"` / `"false"` 时转成布尔。
|
|
37647
|
+
*
|
|
37648
|
+
* @param value - 当前值。
|
|
37649
|
+
* @param schema - 这一层的 JSON Schema。
|
|
37650
|
+
* @param fixes - 修复项累加器。
|
|
37651
|
+
* @returns 强转后的值。
|
|
37652
|
+
*/
|
|
37653
|
+
function coerceBySchema(value, schema, fixes) {
|
|
37654
|
+
if (!isRecord$50(schema)) return value;
|
|
37655
|
+
const type = schema["type"];
|
|
37656
|
+
if (type === "array") {
|
|
37657
|
+
let current = value;
|
|
37658
|
+
if (isPlainRecord$1(current) && Object.keys(current).length === 1 && "item" in current) {
|
|
37659
|
+
const inner = current["item"];
|
|
37660
|
+
current = Array.isArray(inner) ? [...inner] : [inner];
|
|
37661
|
+
fixes.push("item_wrapper");
|
|
37662
|
+
}
|
|
37663
|
+
const items = schema["items"];
|
|
37664
|
+
if (Array.isArray(current) && items !== void 0) current = current.map((entry) => coerceBySchema(entry, items, fixes));
|
|
37665
|
+
return current;
|
|
37666
|
+
}
|
|
37667
|
+
if (type === "number" || type === "integer") {
|
|
37668
|
+
if (typeof value === "string" && NUMERIC_STRING.test(value)) {
|
|
37669
|
+
const parsed = Number(value);
|
|
37670
|
+
if (Number.isFinite(parsed) && (type !== "integer" || Number.isInteger(parsed))) {
|
|
37671
|
+
fixes.push("number_string");
|
|
37672
|
+
return parsed;
|
|
37673
|
+
}
|
|
37674
|
+
}
|
|
37675
|
+
return value;
|
|
37676
|
+
}
|
|
37677
|
+
if (type === "boolean") {
|
|
37678
|
+
if (value === "true") {
|
|
37679
|
+
fixes.push("boolean_string");
|
|
37680
|
+
return true;
|
|
37681
|
+
}
|
|
37682
|
+
if (value === "false") {
|
|
37683
|
+
fixes.push("boolean_string");
|
|
37684
|
+
return false;
|
|
37685
|
+
}
|
|
37686
|
+
return value;
|
|
37687
|
+
}
|
|
37688
|
+
if (type === "object") {
|
|
37689
|
+
const properties = schema["properties"];
|
|
37690
|
+
if (!isPlainRecord$1(value) || !isRecord$50(properties)) return value;
|
|
37691
|
+
const next = { ...value };
|
|
37692
|
+
for (const [key, subSchema] of Object.entries(properties)) {
|
|
37693
|
+
if (!(key in next)) continue;
|
|
37694
|
+
next[key] = coerceBySchema(next[key], subSchema, fixes);
|
|
37695
|
+
}
|
|
37696
|
+
return next;
|
|
37697
|
+
}
|
|
37698
|
+
const properties = schema["properties"];
|
|
37699
|
+
if (isPlainRecord$1(value) && isRecord$50(properties)) {
|
|
37700
|
+
const next = { ...value };
|
|
37701
|
+
for (const [key, subSchema] of Object.entries(properties)) {
|
|
37702
|
+
if (!(key in next)) continue;
|
|
37703
|
+
next[key] = coerceBySchema(next[key], subSchema, fixes);
|
|
37704
|
+
}
|
|
37705
|
+
return next;
|
|
37706
|
+
}
|
|
37707
|
+
const items = schema["items"];
|
|
37708
|
+
if (Array.isArray(value) && items !== void 0) return value.map((entry) => coerceBySchema(entry, items, fixes));
|
|
37709
|
+
return value;
|
|
37710
|
+
}
|
|
37711
|
+
/**
|
|
37712
|
+
* 没有 schema 时按字段名做的顶层强转。
|
|
37713
|
+
*
|
|
37714
|
+
* 只动**顶层**的已知字段:嵌套结构没有 schema 就没有依据,猜不得。
|
|
37715
|
+
* @param args - 参数副本。
|
|
37716
|
+
* @param fixes - 修复项累加器。
|
|
37717
|
+
*/
|
|
37718
|
+
function coerceByKnownFields(args, fixes) {
|
|
37719
|
+
for (const field of NUMERIC_TOOL_FIELDS) {
|
|
37720
|
+
const current = args[field];
|
|
37721
|
+
if (typeof current !== "string" || !NUMERIC_STRING.test(current)) continue;
|
|
37722
|
+
const parsed = Number(current);
|
|
37723
|
+
if (!Number.isFinite(parsed)) continue;
|
|
37724
|
+
args[field] = parsed;
|
|
37725
|
+
fixes.push("number_string");
|
|
37726
|
+
}
|
|
37727
|
+
for (const field of BOOLEAN_TOOL_FIELDS) {
|
|
37728
|
+
const current = args[field];
|
|
37729
|
+
if (current === "true") {
|
|
37730
|
+
args[field] = true;
|
|
37731
|
+
fixes.push("boolean_string");
|
|
37732
|
+
} else if (current === "false") {
|
|
37733
|
+
args[field] = false;
|
|
37734
|
+
fixes.push("boolean_string");
|
|
37735
|
+
}
|
|
37736
|
+
}
|
|
37737
|
+
}
|
|
37738
|
+
/**
|
|
37739
|
+
* 修复一次工具调用的参数。
|
|
37740
|
+
*
|
|
37741
|
+
* 三步,顺序固定:
|
|
37742
|
+
*
|
|
37743
|
+
* 1. **`edits` 字符串解析**(官方 `edit-prepare-arguments.ts`):`edits` 是
|
|
37744
|
+
* JSON 字符串时解析回数组。解析失败就**原样留着**,让 schema 校验照常报错
|
|
37745
|
+
* ——在这里猜一个数组比不猜更糟。
|
|
37746
|
+
* 2. **按 schema 强转**(官方 `direct-call-arguments.ts` / `input-validation.ts`):
|
|
37747
|
+
* `item_wrapper` 拆包、数字字符串转数字、布尔字符串转布尔,并递归进
|
|
37748
|
+
* `properties` 与 `items`。
|
|
37749
|
+
* 3. **按字段名强转**:**没有传 schema** 时才做,因为那时唯一的依据就是字段名。
|
|
37750
|
+
*
|
|
37751
|
+
* 入参**不被修改**:返回值是一份新对象。
|
|
37752
|
+
*
|
|
37753
|
+
* @param toolName - 工具名(只用于日志与将来按工具定制规则)。
|
|
37754
|
+
* @param args - 原始参数。
|
|
37755
|
+
* @param schema - 该工具的 JSON Schema(参数面),可选。
|
|
37756
|
+
* @returns 修复后的参数与修复项列表。
|
|
37757
|
+
*/
|
|
37758
|
+
function repairMinimaxToolArguments(toolName, args, schema) {
|
|
37759
|
+
if (!isPlainRecord$1(args)) return {
|
|
37760
|
+
value: args,
|
|
37761
|
+
fixes: []
|
|
37762
|
+
};
|
|
37763
|
+
const fixes = [];
|
|
37764
|
+
const working = { ...args };
|
|
37765
|
+
if (typeof working["edits"] === "string") {
|
|
37766
|
+
const parsed = tryParseJson(working["edits"]);
|
|
37767
|
+
if (Array.isArray(parsed)) {
|
|
37768
|
+
working["edits"] = parsed;
|
|
37769
|
+
fixes.push("edits_json_string");
|
|
37770
|
+
}
|
|
37771
|
+
}
|
|
37772
|
+
if (schema !== void 0) {
|
|
37773
|
+
const coerced = coerceBySchema(working, schema, fixes);
|
|
37774
|
+
if (isPlainRecord$1(coerced)) Object.assign(working, coerced);
|
|
37775
|
+
} else coerceByKnownFields(working, fixes);
|
|
37776
|
+
return {
|
|
37777
|
+
value: working,
|
|
37778
|
+
fixes
|
|
37779
|
+
};
|
|
37780
|
+
}
|
|
37781
|
+
/**
|
|
37782
|
+
* 解析一段 JSON,失败时返回 undefined(不抛)。
|
|
37783
|
+
* @param text - 待解析的文本。
|
|
37784
|
+
* @returns 解析结果,或 undefined。
|
|
37785
|
+
*/
|
|
37786
|
+
function tryParseJson(text) {
|
|
37787
|
+
try {
|
|
37788
|
+
return JSON.parse(text);
|
|
37789
|
+
} catch {
|
|
37790
|
+
return;
|
|
37791
|
+
}
|
|
37792
|
+
}
|
|
37793
|
+
/**
|
|
37794
|
+
* 直接调用需要提醒的工具名。
|
|
37795
|
+
*
|
|
37796
|
+
* 这些是**原生**工具:在 PTC 模式里模型只能直接调 `run_code`,原生工具要
|
|
37797
|
+
* 从 `run_code` 程序里调。
|
|
37798
|
+
*/
|
|
37799
|
+
const DIRECT_CALL_REMINDER_TOOLS = Object.freeze([
|
|
37800
|
+
"read",
|
|
37801
|
+
"edit",
|
|
37802
|
+
"write",
|
|
37803
|
+
"grep",
|
|
37804
|
+
"glob",
|
|
37805
|
+
"win_bash",
|
|
37806
|
+
"bash",
|
|
37807
|
+
"pwsh"
|
|
37808
|
+
]);
|
|
37809
|
+
/**
|
|
37810
|
+
* 各个原生工具在 `run_code` 里的调用示例参数。
|
|
37811
|
+
*
|
|
37812
|
+
* 例子必须**真的能跑**:提醒里给一个跑不通的示例,比不给示例更糟。
|
|
37813
|
+
*/
|
|
37814
|
+
const DIRECT_CALL_EXAMPLE_ARGS = Object.freeze({
|
|
37815
|
+
read: "{ file_path: \"README.md\" }",
|
|
37816
|
+
write: "{ file_path: \"README.md\", content: \"...\" }",
|
|
37817
|
+
edit: "{ file_path: \"README.md\", old_string: \"...\", new_string: \"...\" }",
|
|
37818
|
+
grep: "{ pattern: \"TODO\", path: \".\" }",
|
|
37819
|
+
glob: "{ pattern: \"src/**/*.ts\" }",
|
|
37820
|
+
bash: "{ command: \"ls -la\" }",
|
|
37821
|
+
win_bash: "{ command: \"ls -la\" }",
|
|
37822
|
+
pwsh: "{ command: \"Get-ChildItem\" }"
|
|
37823
|
+
});
|
|
37824
|
+
/**
|
|
37825
|
+
* 造一条 `run_code` 调用示例。
|
|
37826
|
+
* @param toolName - 工具名。
|
|
37827
|
+
* @returns 一句可读的调用示例。
|
|
37828
|
+
*/
|
|
37829
|
+
function directCallExampleOf(toolName) {
|
|
37830
|
+
return `await tools.${toolName}(${DIRECT_CALL_EXAMPLE_ARGS[toolName] ?? "{ ... }"})`;
|
|
37831
|
+
}
|
|
37832
|
+
/**
|
|
37833
|
+
* 渲染 PTC 直调提醒。
|
|
37834
|
+
*
|
|
37835
|
+
* 文案与官方 `direct-call-reminder.ts` 同形:
|
|
37836
|
+
*
|
|
37837
|
+
* ```text
|
|
37838
|
+
* <system-reminder>
|
|
37839
|
+
* Do not call read directly in this turn. Call it inside run_code: await tools.read({ file_path: "README.md" }). Put your next tool calls in one run_code program.
|
|
37840
|
+
* </system-reminder>
|
|
37841
|
+
* ```
|
|
37842
|
+
*
|
|
37843
|
+
* @param toolNames - 被直接调用的工具名。
|
|
37844
|
+
* @returns 提醒正文。
|
|
37845
|
+
*/
|
|
37846
|
+
function renderDirectCallReminder(toolNames) {
|
|
37847
|
+
const names = [...new Set(toolNames.filter((name) => name !== ""))];
|
|
37848
|
+
if (names.length === 0) return [
|
|
37849
|
+
"<system-reminder>",
|
|
37850
|
+
"Do not call tools directly in this turn. Call them inside run_code. Put your next tool calls in one run_code program.",
|
|
37851
|
+
"</system-reminder>"
|
|
37852
|
+
].join("\n");
|
|
37853
|
+
return [
|
|
37854
|
+
"<system-reminder>",
|
|
37855
|
+
`Do not call ${names.join(", ")} directly in this turn. Call ${names.length === 1 ? "it" : "them"} inside run_code: ${names.slice(0, 2).map((name) => directCallExampleOf(name)).join("; ")}. Put your next tool calls in one run_code program.`,
|
|
37856
|
+
"</system-reminder>"
|
|
37857
|
+
].join("\n");
|
|
37858
|
+
}
|
|
37859
|
+
/**
|
|
37860
|
+
* 官方提醒文案的后缀:提醒只对当前这一轮有效。
|
|
37861
|
+
* @returns 后缀正文。
|
|
37862
|
+
*/
|
|
37863
|
+
const TURN_ONLY_SUFFIX = " This is a temporary runtime reminder for the current Turn only, not a user preference or a durable rule; do not save this reminder or generalize it into Memory, Skills, or other persistent instruction files for future Turns or sessions.";
|
|
37864
|
+
/**
|
|
37865
|
+
* 渲染「同一个动作立刻重复」提醒。
|
|
37866
|
+
*
|
|
37867
|
+
* 与官方 `packages/agent-modules/runaway-guard/src/reminder.ts` 逐字一致。
|
|
37868
|
+
* @param occurrences - 连击次数。
|
|
37869
|
+
* @returns 提醒正文。
|
|
37870
|
+
*/
|
|
37871
|
+
function renderExactActionRepeatReminder(occurrences) {
|
|
37872
|
+
return `[runaway guard] The immediately repeated tool action has now occurred ${occurrences} times with the same arguments. Do not repeat it unchanged. Inspect the results already available, then either change strategy with a concrete expected state change, or report the blocker. Repetition alone does not establish that the task is complete or impossible.${TURN_ONLY_SUFFIX}`;
|
|
37873
|
+
}
|
|
37874
|
+
/**
|
|
37875
|
+
* 渲染「同一族错误连续发生」提醒。
|
|
37876
|
+
*
|
|
37877
|
+
* 与官方 `packages/agent-modules/runaway-guard/src/reminder.ts` 逐字一致。
|
|
37878
|
+
* @param occurrences - 连击次数。
|
|
37879
|
+
* @returns 提醒正文。
|
|
37880
|
+
*/
|
|
37881
|
+
function renderSameErrorFamilyReminder(occurrences) {
|
|
37882
|
+
return `[runaway guard] The same tool error family has now occurred ${occurrences} times in a row. Do not retry the same route unchanged. Diagnose the cause, change one controlled variable or switch route. Do not infer that the entire task has failed from this signal.${TURN_ONLY_SUFFIX}`;
|
|
37883
|
+
}
|
|
37884
|
+
/**
|
|
37885
|
+
* 渲染「反复轮询同一个后台任务」提醒。
|
|
37886
|
+
*
|
|
37887
|
+
* 与官方 `packages/agent-modules/runaway-guard/src/reminder.ts` 逐字一致:
|
|
37888
|
+
* 三次读同一个任务时写的是 `Three`,其它次数写数字。
|
|
37889
|
+
* @param occurrences - 连击次数。
|
|
37890
|
+
* @returns 提醒正文。
|
|
37891
|
+
*/
|
|
37892
|
+
function renderPollingRepeatReminder(occurrences) {
|
|
37893
|
+
return [
|
|
37894
|
+
"<system-reminder>",
|
|
37895
|
+
`${occurrences === 3 ? "Three" : String(occurrences)} task_output reads for the same task have returned an unchanged status and output cursor. Avoid repeated polling; you will be notified automatically and this conversation will resume when the background task completes.`,
|
|
37896
|
+
"This reminder applies only to the current Turn. Do not save or generalize it into Memory, Skills, or other persistent instructions.",
|
|
37897
|
+
"</system-reminder>"
|
|
37898
|
+
].join("\n");
|
|
37899
|
+
}
|
|
37900
|
+
/**
|
|
37901
|
+
* 轮询类工具名(后台任务的结果读取)。
|
|
37902
|
+
*
|
|
37903
|
+
* 这两个工具读的是后台任务的状态;反复读同一个任务而输出没变,就是官方说的
|
|
37904
|
+
* 「polling repeat」。
|
|
37905
|
+
*/
|
|
37906
|
+
const POLLING_TOOL_NAMES = Object.freeze(["job_output", "task_output"]);
|
|
37907
|
+
/**
|
|
37908
|
+
* 规范化一段错误文本,取它的「族」。
|
|
37909
|
+
*
|
|
37910
|
+
* 族的作用是**把同一类错误认成同一类**:路径里的数字、id、时间戳都不该让
|
|
37911
|
+
* 两次一模一样的失败看起来是两回事。
|
|
37912
|
+
* @param text - 错误文本。
|
|
37913
|
+
* @returns 族标识。
|
|
37914
|
+
*/
|
|
37915
|
+
function errorFamilyOf(text) {
|
|
37916
|
+
if (text === void 0 || text === "") return "unknown";
|
|
37917
|
+
return (text.split(/\r?\n/, 1)[0] ?? "").replace(/\d+/g, "#").slice(0, 200);
|
|
37918
|
+
}
|
|
37919
|
+
/**
|
|
37920
|
+
* 把参数规范化成可比较的字符串(键排序)。
|
|
37921
|
+
* @param value - 参数值。
|
|
37922
|
+
* @returns 规范化后的 JSON 文本。
|
|
37923
|
+
*/
|
|
37924
|
+
function canonicalize(value) {
|
|
37925
|
+
return JSON.stringify(sortJsonValue$1(value));
|
|
37926
|
+
}
|
|
37927
|
+
/**
|
|
37928
|
+
* 深拷贝一份键排序后的 JSON 值。
|
|
37929
|
+
* @param value - 任意值。
|
|
37930
|
+
* @returns 排序后的副本。
|
|
37931
|
+
*/
|
|
37932
|
+
function sortJsonValue$1(value) {
|
|
37933
|
+
if (Array.isArray(value)) return value.map(sortJsonValue$1);
|
|
37934
|
+
if (isPlainRecord$1(value)) {
|
|
37935
|
+
const sorted = {};
|
|
37936
|
+
for (const key of Object.keys(value).sort()) sorted[key] = sortJsonValue$1(value[key]);
|
|
37937
|
+
return sorted;
|
|
37938
|
+
}
|
|
37939
|
+
return value;
|
|
37940
|
+
}
|
|
37941
|
+
/**
|
|
37942
|
+
* 造一台工具级失控守卫。
|
|
37943
|
+
*
|
|
37944
|
+
* 三种可提醒信号(顺序即官方提醒优先级):
|
|
37945
|
+
*
|
|
37946
|
+
* 1. `same_error_family` —— 同一个工具连续报同一族错误;
|
|
37947
|
+
* 2. `exact_action_repeat` —— 同一次动作(同名 + 同参数)立刻重复;
|
|
37948
|
+
* 3. `polling_repeat` —— 连续轮询同一个后台任务而输出没变。
|
|
37949
|
+
*
|
|
37950
|
+
* `abab_action_cycle`(A B A B 的循环)**只记录不提醒**:官方把它排在提醒
|
|
37951
|
+
* 候选之外——模型在两个动作之间来回跳时,提醒它「别重复」是没有意义的。
|
|
37952
|
+
*
|
|
37953
|
+
* 每轮**至多一条**提醒:官方在发出第一条后就把本轮的提醒机会用掉了。
|
|
37954
|
+
*
|
|
37955
|
+
* @param options - 守卫选项。
|
|
37956
|
+
* @returns 守卫。
|
|
37957
|
+
*/
|
|
37958
|
+
function createMinimaxRunawayGuard(options = {}) {
|
|
37959
|
+
const threshold = options.remindAfterOccurrences ?? 3;
|
|
37960
|
+
/** 同一次动作的连击。 */
|
|
37961
|
+
let actionStreak;
|
|
37962
|
+
/** 同一族错误的连击(键是工具名 + 错误族)。 */
|
|
37963
|
+
const errorStreaks = /* @__PURE__ */ new Map();
|
|
37964
|
+
/** 轮询连击(键是工具名)。 */
|
|
37965
|
+
const pollingStreaks = /* @__PURE__ */ new Map();
|
|
37966
|
+
/** 最近几次动作,用来认 A B A B 的循环。 */
|
|
37967
|
+
const recentActions = [];
|
|
37968
|
+
/** 当前正在计数的 A B 循环对。 */
|
|
37969
|
+
let activeAbabKey;
|
|
37970
|
+
/** 本轮是否已经提醒过。 */
|
|
37971
|
+
let reminderAttempted = false;
|
|
37972
|
+
/** 观察到的信号。 */
|
|
37973
|
+
const signals = [];
|
|
37974
|
+
/**
|
|
37975
|
+
* 记一条信号。
|
|
37976
|
+
* @param kind - 信号种类。
|
|
37977
|
+
* @param occurrences - 连击次数。
|
|
37978
|
+
* @param toolName - 工具名。
|
|
37979
|
+
*/
|
|
37980
|
+
const record = (kind, occurrences, toolName) => {
|
|
37981
|
+
signals.push({
|
|
37982
|
+
kind,
|
|
37983
|
+
occurrences,
|
|
37984
|
+
toolName
|
|
37985
|
+
});
|
|
37986
|
+
};
|
|
37987
|
+
/**
|
|
37988
|
+
* 判断这次执行是不是一次「原地不动」的轮询。
|
|
37989
|
+
* @param observation - 观察事实。
|
|
37990
|
+
* @returns 是轮询时为 true。
|
|
37991
|
+
*/
|
|
37992
|
+
const isPolling = (observation) => {
|
|
37993
|
+
if (!POLLING_TOOL_NAMES.includes(observation.toolName)) return false;
|
|
37994
|
+
return (isPlainRecord$1(observation.arguments) ? observation.arguments : void 0)?.["wait"] !== true;
|
|
37995
|
+
};
|
|
37996
|
+
return {
|
|
37997
|
+
observe(observation) {
|
|
37998
|
+
const toolName = observation.toolName;
|
|
37999
|
+
const actionKey = `${toolName}\u0000${canonicalize(observation.arguments)}`;
|
|
38000
|
+
const countsAsAction = !POLLING_TOOL_NAMES.includes(toolName);
|
|
38001
|
+
if (countsAsAction) {
|
|
38002
|
+
if (actionStreak?.key === actionKey) actionStreak = {
|
|
38003
|
+
key: actionKey,
|
|
38004
|
+
count: actionStreak.count + 1
|
|
38005
|
+
};
|
|
38006
|
+
else actionStreak = {
|
|
38007
|
+
key: actionKey,
|
|
38008
|
+
count: 1
|
|
38009
|
+
};
|
|
38010
|
+
record("exact_action_repeat", actionStreak.count, toolName);
|
|
38011
|
+
}
|
|
38012
|
+
if (countsAsAction) {
|
|
38013
|
+
recentActions.push(actionKey);
|
|
38014
|
+
if (recentActions.length > 4) recentActions.shift();
|
|
38015
|
+
if (recentActions.length === 4) {
|
|
38016
|
+
const [a, b, c, d] = recentActions;
|
|
38017
|
+
if (a !== void 0 && b !== void 0 && a !== b && a === c && b === d) {
|
|
38018
|
+
const episode = `${a}\u0000${b}`;
|
|
38019
|
+
if (activeAbabKey !== episode) {
|
|
38020
|
+
activeAbabKey = episode;
|
|
38021
|
+
record("abab_action_cycle", 2, toolName);
|
|
38022
|
+
}
|
|
38023
|
+
} else activeAbabKey = void 0;
|
|
38024
|
+
}
|
|
38025
|
+
}
|
|
38026
|
+
if (observation.isError === true) {
|
|
38027
|
+
const key = `${toolName}\u0000${observation.errorCode ?? errorFamilyOf(observation.errorText)}`;
|
|
38028
|
+
const previous = errorStreaks.get(key);
|
|
38029
|
+
const count = previous === void 0 ? 1 : previous.count + 1;
|
|
38030
|
+
errorStreaks.set(key, {
|
|
38031
|
+
toolName,
|
|
38032
|
+
count
|
|
38033
|
+
});
|
|
38034
|
+
record("same_error_family", count, toolName);
|
|
38035
|
+
} else for (const [key, entry] of [...errorStreaks]) if (entry.toolName === toolName) errorStreaks.delete(key);
|
|
38036
|
+
if (isPolling(observation)) {
|
|
38037
|
+
const key = `${toolName}\u0000${canonicalize(observation.arguments)}\u0000${observation.resultText ?? ""}`;
|
|
38038
|
+
const previous = pollingStreaks.get(toolName);
|
|
38039
|
+
const count = previous !== void 0 && previous.key === key ? previous.count + 1 : 1;
|
|
38040
|
+
pollingStreaks.set(toolName, {
|
|
38041
|
+
key,
|
|
38042
|
+
count
|
|
38043
|
+
});
|
|
38044
|
+
record("polling_repeat", count, toolName);
|
|
38045
|
+
} else pollingStreaks.delete(toolName);
|
|
38046
|
+
if (reminderAttempted) return void 0;
|
|
38047
|
+
const errorCandidate = [...errorStreaks.values()].find((entry) => entry.count >= threshold);
|
|
38048
|
+
if (errorCandidate !== void 0) {
|
|
38049
|
+
reminderAttempted = true;
|
|
38050
|
+
return {
|
|
38051
|
+
kind: "same_error_family",
|
|
38052
|
+
occurrences: errorCandidate.count,
|
|
38053
|
+
text: renderSameErrorFamilyReminder(errorCandidate.count)
|
|
38054
|
+
};
|
|
38055
|
+
}
|
|
38056
|
+
if (countsAsAction && actionStreak !== void 0 && actionStreak.count >= threshold) {
|
|
38057
|
+
reminderAttempted = true;
|
|
38058
|
+
return {
|
|
38059
|
+
kind: "exact_action_repeat",
|
|
38060
|
+
occurrences: actionStreak.count,
|
|
38061
|
+
text: renderExactActionRepeatReminder(actionStreak.count)
|
|
38062
|
+
};
|
|
38063
|
+
}
|
|
38064
|
+
const pollingCandidate = [...pollingStreaks.values()].find((entry) => entry.count >= threshold);
|
|
38065
|
+
if (pollingCandidate !== void 0) {
|
|
38066
|
+
reminderAttempted = true;
|
|
38067
|
+
return {
|
|
38068
|
+
kind: "polling_repeat",
|
|
38069
|
+
occurrences: pollingCandidate.count,
|
|
38070
|
+
text: renderPollingRepeatReminder(pollingCandidate.count)
|
|
38071
|
+
};
|
|
38072
|
+
}
|
|
38073
|
+
},
|
|
38074
|
+
reset() {
|
|
38075
|
+
actionStreak = void 0;
|
|
38076
|
+
errorStreaks.clear();
|
|
38077
|
+
pollingStreaks.clear();
|
|
38078
|
+
recentActions.length = 0;
|
|
38079
|
+
activeAbabKey = void 0;
|
|
38080
|
+
reminderAttempted = false;
|
|
38081
|
+
},
|
|
38082
|
+
get signals() {
|
|
38083
|
+
return signals;
|
|
38084
|
+
}
|
|
38085
|
+
};
|
|
38086
|
+
}
|
|
38087
|
+
/**
|
|
38088
|
+
* 读宿主上下文上的工具注册面。
|
|
38089
|
+
* @param ctx - 宿主上下文。
|
|
38090
|
+
* @returns 工具注册面;没有时为 undefined。
|
|
38091
|
+
*/
|
|
38092
|
+
function toolsServiceOf$1(ctx) {
|
|
38093
|
+
const read = ctx.get;
|
|
38094
|
+
if (typeof read === "function") try {
|
|
38095
|
+
const found = read.call(ctx, "tools");
|
|
38096
|
+
if (found !== void 0) return found;
|
|
38097
|
+
} catch {}
|
|
38098
|
+
const direct = ctx.tools;
|
|
38099
|
+
return direct === void 0 ? void 0 : direct;
|
|
38100
|
+
}
|
|
38101
|
+
/**
|
|
38102
|
+
* 判断一个会话是不是处于 PTC 模式(模型只能直接调 `run_code`)。
|
|
38103
|
+
*
|
|
38104
|
+
* 三个来源,按可靠性排序:
|
|
38105
|
+
*
|
|
38106
|
+
* 1. **注册表自己的判定面**(结构探测 `modeFor`):这是宿主真正用来决定
|
|
38107
|
+
* 「这个作用域是 native 还是 ptc」的那一个函数,读到的就是事实。
|
|
38108
|
+
* 2. **保留通道的可见性**(公开 API `get('run_code', scope)`):`run_code` 这条
|
|
38109
|
+
* 传输通道只对 PTC 作用域可见,所以「能不能查到它」就是同一个问题的公开问法。
|
|
38110
|
+
* 3. **agent 自己声明的呈现模式**:宿主选项里直接写了 `ptc` 时的兜底。
|
|
38111
|
+
*
|
|
38112
|
+
* 读不出来时**当作不是 PTC**:提醒是加法,不是减法,宁可少提醒也不要在
|
|
38113
|
+
* native 会话里催模型去用 `run_code`。
|
|
38114
|
+
*
|
|
38115
|
+
* @param agent - 调用方 agent。
|
|
38116
|
+
* @param tools - 工具注册面。
|
|
38117
|
+
* @returns 处于 PTC 模式时为 true。
|
|
38118
|
+
*/
|
|
38119
|
+
function isPtcSessionOf(agent, tools) {
|
|
38120
|
+
const mode = declaredModeOf(tools, agent);
|
|
38121
|
+
if (mode !== void 0) return mode;
|
|
38122
|
+
if (runCodeTransportVisible(tools, agent) === true) return true;
|
|
38123
|
+
return declaredPresentationOf(agent) === "ptc";
|
|
38124
|
+
}
|
|
38125
|
+
/**
|
|
38126
|
+
* 读注册表自己的呈现模式判定面。
|
|
38127
|
+
* @param tools - 工具注册面。
|
|
38128
|
+
* @param agent - 调用方 agent。
|
|
38129
|
+
* @returns true/false 表示读到了;undefined 表示这一代宿主没有这条接缝。
|
|
38130
|
+
*/
|
|
38131
|
+
function declaredModeOf(tools, agent) {
|
|
38132
|
+
const modeFor = (isRecord$50(tools) ? tools : void 0)?.modeFor;
|
|
38133
|
+
if (typeof modeFor !== "function") return void 0;
|
|
38134
|
+
try {
|
|
38135
|
+
const mode = modeFor.call(tools, agent);
|
|
38136
|
+
if (mode === "ptc") return true;
|
|
38137
|
+
if (mode === "native") return false;
|
|
38138
|
+
} catch {}
|
|
38139
|
+
}
|
|
38140
|
+
/**
|
|
38141
|
+
* 看 `run_code` 这条保留通道对这个作用域是否可见。
|
|
38142
|
+
* @param tools - 工具注册面。
|
|
38143
|
+
* @param agent - 调用方 agent。
|
|
38144
|
+
* @returns true/false 表示读到了;undefined 表示这一代宿主没有这条接缝。
|
|
38145
|
+
*/
|
|
38146
|
+
function runCodeTransportVisible(tools, agent) {
|
|
38147
|
+
const get = (isRecord$50(tools) ? tools : void 0)?.get;
|
|
38148
|
+
if (typeof get !== "function") return void 0;
|
|
38149
|
+
try {
|
|
38150
|
+
return get.call(tools, "run_code", agent) !== void 0;
|
|
38151
|
+
} catch {
|
|
38152
|
+
return;
|
|
38153
|
+
}
|
|
38154
|
+
}
|
|
38155
|
+
/**
|
|
38156
|
+
* 读 agent 自己声明的呈现模式。
|
|
38157
|
+
* @param agent - 调用方 agent。
|
|
38158
|
+
* @returns 'ptc' / 'native' / undefined。
|
|
38159
|
+
*/
|
|
38160
|
+
function declaredPresentationOf(agent) {
|
|
38161
|
+
const record = isRecord$50(agent) ? agent : void 0;
|
|
38162
|
+
const options = isRecord$50(record?.["options"]) ? record?.["options"] : void 0;
|
|
38163
|
+
const agentOptions = isRecord$50(record?.["agentOptions"]) ? record?.["agentOptions"] : void 0;
|
|
38164
|
+
const preset = isRecord$50(record?.["preset"]) ? record?.["preset"] : void 0;
|
|
38165
|
+
const candidates = [
|
|
38166
|
+
options?.["presentation"],
|
|
38167
|
+
options?.["toolPresentation"],
|
|
38168
|
+
options?.["toolsMode"],
|
|
38169
|
+
options?.["mode"],
|
|
38170
|
+
agentOptions?.["presentation"],
|
|
38171
|
+
preset?.["presentation"]
|
|
38172
|
+
];
|
|
38173
|
+
for (const candidate of candidates) {
|
|
38174
|
+
if (candidate === "ptc") return "ptc";
|
|
38175
|
+
if (candidate === "native") return "native";
|
|
38176
|
+
}
|
|
38177
|
+
}
|
|
38178
|
+
/**
|
|
38179
|
+
* 判断一次工具执行是不是「模型直接调了原生工具」。
|
|
38180
|
+
*
|
|
38181
|
+
* 直接调用的判据是**没有父调用**:嵌套调用(`run_code` 程序里的子调用)带
|
|
38182
|
+
* 父标记,直接调用不带。DSH 用 `parent` 这枚不透明令牌,官方 minimax-code
|
|
38183
|
+
* 用 `parentToolCallId`,两个都认。
|
|
38184
|
+
*
|
|
38185
|
+
* @param exec - 工具执行。
|
|
38186
|
+
* @returns 直接调用时为 true。
|
|
38187
|
+
*/
|
|
38188
|
+
function isDirectToolCall(exec) {
|
|
38189
|
+
const record = isRecord$50(exec) ? exec : void 0;
|
|
38190
|
+
if (record?.["parent"] !== void 0) return false;
|
|
38191
|
+
if (record?.["parentToolCallId"] !== void 0) return false;
|
|
38192
|
+
return true;
|
|
38193
|
+
}
|
|
38194
|
+
/**
|
|
38195
|
+
* 读一次执行是不是「模型直接调了需要提醒的原生工具」。
|
|
38196
|
+
* @param exec - 工具执行。
|
|
38197
|
+
* @returns 工具名;不是这类调用时为 undefined。
|
|
38198
|
+
*/
|
|
38199
|
+
function directCallToolNameOf(exec) {
|
|
38200
|
+
const name = stringOf$4((isRecord$50(exec) ? exec : void 0)?.["name"]);
|
|
38201
|
+
if (name === void 0 || !DIRECT_CALL_REMINDER_TOOLS.includes(name)) return void 0;
|
|
38202
|
+
if (!isDirectToolCall(exec)) return void 0;
|
|
38203
|
+
return name;
|
|
38204
|
+
}
|
|
38205
|
+
/**
|
|
38206
|
+
* 把一条 post-execute 决策接上附加上下文,保住它原有的形状。
|
|
38207
|
+
* @param decision - `next()` 交回来的决策。
|
|
38208
|
+
* @param contexts - 要追加的上下文。
|
|
38209
|
+
* @returns 追加后的决策。
|
|
38210
|
+
*/
|
|
38211
|
+
function withAdditionalContexts$1(decision, contexts) {
|
|
38212
|
+
const additionalContexts = [...decision.additionalContexts ?? [], ...contexts];
|
|
38213
|
+
if (decision.kind === "block") return {
|
|
38214
|
+
kind: "block",
|
|
38215
|
+
feedback: decision.feedback,
|
|
38216
|
+
additionalContexts
|
|
38217
|
+
};
|
|
38218
|
+
if (decision.value !== void 0) return {
|
|
38219
|
+
kind: "accept",
|
|
38220
|
+
value: decision.value,
|
|
38221
|
+
additionalContexts
|
|
38222
|
+
};
|
|
38223
|
+
if (decision.content !== void 0) return {
|
|
38224
|
+
kind: "accept",
|
|
38225
|
+
content: decision.content,
|
|
38226
|
+
additionalContexts
|
|
38227
|
+
};
|
|
38228
|
+
return {
|
|
38229
|
+
kind: "accept",
|
|
38230
|
+
additionalContexts
|
|
38231
|
+
};
|
|
38232
|
+
}
|
|
38233
|
+
/**
|
|
38234
|
+
* 造一条 PTC 直调提醒上下文。
|
|
38235
|
+
* @param toolName - 被直接调用的工具名。
|
|
38236
|
+
* @returns 可直接放进 `additionalContexts` 的用户角色消息。
|
|
38237
|
+
*/
|
|
38238
|
+
function createDirectCallReminder(toolName) {
|
|
38239
|
+
return createUserMessage({
|
|
38240
|
+
content: [{
|
|
38241
|
+
type: "text",
|
|
38242
|
+
text: renderDirectCallReminder([toolName])
|
|
38243
|
+
}],
|
|
38244
|
+
source: {
|
|
38245
|
+
kind: "minimax-direct-call-reminder",
|
|
38246
|
+
form: "notice",
|
|
38247
|
+
summary: `PTC direct call: ${toolName}`
|
|
38248
|
+
}
|
|
38249
|
+
});
|
|
38250
|
+
}
|
|
38251
|
+
/**
|
|
38252
|
+
* 造一条失控守卫提醒上下文。
|
|
38253
|
+
* @param reminder - 提醒。
|
|
38254
|
+
* @returns 可直接放进 `additionalContexts` 的用户角色消息。
|
|
38255
|
+
*/
|
|
38256
|
+
function createRunawayReminder(reminder) {
|
|
38257
|
+
return createUserMessage({
|
|
38258
|
+
content: [{
|
|
38259
|
+
type: "text",
|
|
38260
|
+
text: reminder.text
|
|
38261
|
+
}],
|
|
38262
|
+
source: {
|
|
38263
|
+
kind: "minimax-runaway-guard",
|
|
38264
|
+
form: "notice",
|
|
38265
|
+
summary: `runaway guard: ${reminder.kind} x${reminder.occurrences}`
|
|
38266
|
+
}
|
|
38267
|
+
});
|
|
38268
|
+
}
|
|
38269
|
+
/**
|
|
38270
|
+
* 读一次执行的结果是不是失败。
|
|
38271
|
+
* @param result - 工具执行结果。
|
|
38272
|
+
* @returns 失败时为 true。
|
|
38273
|
+
*/
|
|
38274
|
+
function isErrorResult(result) {
|
|
38275
|
+
return isRecord$50(result) && result["isError"] === true;
|
|
38276
|
+
}
|
|
38277
|
+
/**
|
|
38278
|
+
* 读一次执行的结构化错误码。
|
|
38279
|
+
* @param result - 工具执行结果。
|
|
38280
|
+
* @returns 错误码;没有时为 undefined。
|
|
38281
|
+
*/
|
|
38282
|
+
function errorCodeOf$1(result) {
|
|
38283
|
+
if (!isRecord$50(result)) return void 0;
|
|
38284
|
+
const error = result["error"];
|
|
38285
|
+
if (!isRecord$50(error)) return void 0;
|
|
38286
|
+
const info = error["info"];
|
|
38287
|
+
if (!isRecord$50(info)) return void 0;
|
|
38288
|
+
return stringOf$4(info["code"]);
|
|
38289
|
+
}
|
|
38290
|
+
/**
|
|
38291
|
+
* 读一次执行的失败文本。
|
|
38292
|
+
* @param result - 工具执行结果。
|
|
38293
|
+
* @returns 失败文本;没有时为 undefined。
|
|
38294
|
+
*/
|
|
38295
|
+
function errorTextOf(result) {
|
|
38296
|
+
if (!isRecord$50(result)) return void 0;
|
|
38297
|
+
const error = result["error"];
|
|
38298
|
+
if (!isRecord$50(error)) return void 0;
|
|
38299
|
+
return stringOf$4(error["message"]);
|
|
38300
|
+
}
|
|
38301
|
+
/**
|
|
38302
|
+
* 读一次执行的结果文本(轮询判定用)。
|
|
38303
|
+
* @param result - 工具执行结果。
|
|
38304
|
+
* @returns 结果文本;没有时是空串。
|
|
38305
|
+
*/
|
|
38306
|
+
function resultTextOf(result) {
|
|
38307
|
+
if (!isRecord$50(result)) return "";
|
|
38308
|
+
const content = result["content"];
|
|
38309
|
+
if (!Array.isArray(content)) return "";
|
|
38310
|
+
const parts = [];
|
|
38311
|
+
for (const block of content) if (isRecord$50(block) && block["type"] === "text") parts.push(stringOf$4(block["text"]) ?? "");
|
|
38312
|
+
return parts.join("\n");
|
|
38313
|
+
}
|
|
38314
|
+
/**
|
|
38315
|
+
* 找一次工具调用的参数 schema。
|
|
38316
|
+
* @param tools - 工具注册面。
|
|
38317
|
+
* @param name - 工具名。
|
|
38318
|
+
* @param agent - 调用方 agent。
|
|
38319
|
+
* @returns JSON Schema;找不到时为 undefined。
|
|
38320
|
+
*/
|
|
38321
|
+
function schemaOf(tools, name, agent) {
|
|
38322
|
+
const get = tools?.get;
|
|
38323
|
+
if (typeof get !== "function") return void 0;
|
|
38324
|
+
try {
|
|
38325
|
+
const definition = get.call(tools, name, agent);
|
|
38326
|
+
if (!isRecord$50(definition)) return void 0;
|
|
38327
|
+
return definition["parameters"];
|
|
38328
|
+
} catch {
|
|
38329
|
+
return;
|
|
38330
|
+
}
|
|
38331
|
+
}
|
|
38332
|
+
/**
|
|
38333
|
+
* 就地把一次执行的参数改成修复后的形状。
|
|
38334
|
+
*
|
|
38335
|
+
* **尽力而为**:新一代宿主把执行参数**冻结**了(`deepFreeze`),写回会抛,
|
|
38336
|
+
* 于是这次修复在那一代上落不了地 —— 但函数本身不抛,调用方也拿不到错误。
|
|
38337
|
+
* 老一代宿主不冻结参数时,写回是真正生效的。
|
|
38338
|
+
*
|
|
38339
|
+
* @param execution - 工具执行。
|
|
38340
|
+
* @param tools - 工具注册面。
|
|
38341
|
+
*/
|
|
38342
|
+
function repairExecutionArguments(execution, tools) {
|
|
38343
|
+
const record = isRecord$50(execution) ? execution : void 0;
|
|
38344
|
+
const args = record?.["arguments"];
|
|
38345
|
+
if (!isPlainRecord$1(args)) return;
|
|
38346
|
+
const name = stringOf$4(record?.["name"]);
|
|
38347
|
+
if (name === void 0) return;
|
|
38348
|
+
const agent = record?.["agent"];
|
|
38349
|
+
const repaired = repairMinimaxToolArguments(name, args, schemaOf(tools, name, agent));
|
|
38350
|
+
if (repaired.fixes.length === 0) return;
|
|
38351
|
+
const target = repaired.value;
|
|
38352
|
+
if (!isPlainRecord$1(target)) return;
|
|
38353
|
+
try {
|
|
38354
|
+
for (const key of Object.keys(args)) if (!(key in target)) delete args[key];
|
|
38355
|
+
Object.assign(args, target);
|
|
38356
|
+
} catch {}
|
|
38357
|
+
}
|
|
38358
|
+
/**
|
|
38359
|
+
* 装上 MiniMax Code 的运行时增强。
|
|
38360
|
+
*
|
|
38361
|
+
* @param ctx - 宿主插件上下文。
|
|
38362
|
+
* @param options - 增强选项。
|
|
38363
|
+
* @returns 卸载函数。
|
|
38364
|
+
*/
|
|
38365
|
+
function installMinimaxRuntimeEnhancements(ctx, options = {}) {
|
|
38366
|
+
/** 登记一个副作用;上下文没有 effect 时立即执行(测试用假上下文)。 */
|
|
38367
|
+
const track = (execute, label) => {
|
|
38368
|
+
if (typeof ctx.effect === "function") ctx.effect(execute, label);
|
|
38369
|
+
else execute();
|
|
38370
|
+
};
|
|
38371
|
+
const tools = toolsServiceOf$1(ctx);
|
|
38372
|
+
/** 每个 agent 一台守卫:连击是**这个会话**的事。 */
|
|
38373
|
+
const guards = /* @__PURE__ */ new WeakMap();
|
|
38374
|
+
/**
|
|
38375
|
+
* 没有 agent 的执行(有人绕过 agent-loop 直接调 `ctx.tools.execute`)共用这一台。
|
|
38376
|
+
*
|
|
38377
|
+
* 它是**一台**,不是每次新建:连击要跨调用累积,新建一台等于永远停在第一次。
|
|
38378
|
+
*/
|
|
38379
|
+
const agentlessGuard = createMinimaxRunawayGuard(options);
|
|
38380
|
+
/**
|
|
38381
|
+
* 取一个 agent 的守卫。
|
|
38382
|
+
* @param agent - 调用方 agent。
|
|
38383
|
+
* @returns 守卫。
|
|
38384
|
+
*/
|
|
38385
|
+
const guardOf = (agent) => {
|
|
38386
|
+
const key = isRecord$50(agent) ? agent : void 0;
|
|
38387
|
+
if (key === void 0) return agentlessGuard;
|
|
38388
|
+
const existing = guards.get(key);
|
|
38389
|
+
if (existing !== void 0) return existing;
|
|
38390
|
+
const created = createMinimaxRunawayGuard(options);
|
|
38391
|
+
guards.set(key, created);
|
|
38392
|
+
return created;
|
|
38393
|
+
};
|
|
38394
|
+
track(() => {
|
|
38395
|
+
if (typeof tools?.guard !== "function") return () => void 0;
|
|
38396
|
+
const dispose = tools.guard((execution) => {
|
|
38397
|
+
try {
|
|
38398
|
+
if (!isMinimaxSession(isRecord$50(execution) ? execution["agent"] : void 0)) return void 0;
|
|
38399
|
+
repairExecutionArguments(execution, tools);
|
|
38400
|
+
} catch {}
|
|
38401
|
+
});
|
|
38402
|
+
return () => {
|
|
38403
|
+
dispose?.();
|
|
38404
|
+
};
|
|
38405
|
+
}, "dsh-chatgpt-subscription: minimax argument repair guard");
|
|
38406
|
+
const disposePreExecute = ctx.on?.("tools/pre-execute", (async (exec, next) => {
|
|
38407
|
+
try {
|
|
38408
|
+
if (isMinimaxSession(exec.agent)) repairExecutionArguments(exec, tools);
|
|
38409
|
+
} catch {}
|
|
38410
|
+
return next();
|
|
38411
|
+
}));
|
|
38412
|
+
const disposePostExecute = ctx.on?.("tools/post-execute", (async (exec, result, next) => {
|
|
38413
|
+
const decision = await next();
|
|
38414
|
+
try {
|
|
38415
|
+
const agent = exec.agent;
|
|
38416
|
+
if (!isMinimaxSession(agent)) return decision;
|
|
38417
|
+
const contexts = [];
|
|
38418
|
+
const directName = directCallToolNameOf(exec);
|
|
38419
|
+
if (directName !== void 0 && isPtcSessionOf(agent, tools)) contexts.push(createDirectCallReminder(directName));
|
|
38420
|
+
const reminder = guardOf(agent).observe({
|
|
38421
|
+
toolName: exec.name,
|
|
38422
|
+
arguments: exec.arguments,
|
|
38423
|
+
isError: isErrorResult(result),
|
|
38424
|
+
errorCode: errorCodeOf$1(result),
|
|
38425
|
+
errorText: errorTextOf(result),
|
|
38426
|
+
resultText: resultTextOf(result)
|
|
38427
|
+
});
|
|
38428
|
+
if (reminder !== void 0) contexts.push(createRunawayReminder(reminder));
|
|
38429
|
+
if (contexts.length === 0) return decision;
|
|
38430
|
+
return withAdditionalContexts$1(decision, contexts);
|
|
38431
|
+
} catch {
|
|
38432
|
+
return decision;
|
|
38433
|
+
}
|
|
38434
|
+
}));
|
|
38435
|
+
const disposePreStep = ctx.on?.("agent/pre-step", (async (payload, next) => {
|
|
38436
|
+
const decision = await next();
|
|
38437
|
+
try {
|
|
38438
|
+
if (!(Array.isArray(payload?.messages) ? payload.messages : []).some((message) => {
|
|
38439
|
+
const source = isRecord$50(message) ? message["source"] : void 0;
|
|
38440
|
+
return isRecord$50(source) && source["kind"] === "user";
|
|
38441
|
+
})) return decision;
|
|
38442
|
+
const agent = payload?.agent;
|
|
38443
|
+
if (isRecord$50(agent)) guards.get(agent)?.reset();
|
|
38444
|
+
} catch {
|
|
38445
|
+
return decision;
|
|
38446
|
+
}
|
|
38447
|
+
return decision;
|
|
38448
|
+
}));
|
|
38449
|
+
const disposeDisposed = ctx.on?.("agent/disposed", ((payload) => {
|
|
38450
|
+
const agent = payload?.agent;
|
|
38451
|
+
if (isRecord$50(agent)) guards.delete(agent);
|
|
38452
|
+
}));
|
|
38453
|
+
return () => {
|
|
38454
|
+
disposePreExecute?.();
|
|
38455
|
+
disposePostExecute?.();
|
|
38456
|
+
disposePreStep?.();
|
|
38457
|
+
disposeDisposed?.();
|
|
38458
|
+
};
|
|
38459
|
+
}
|
|
38460
|
+
//#endregion
|
|
37197
38461
|
//#region src/host/minimax-code/modalities.ts
|
|
37198
38462
|
/**
|
|
37199
38463
|
* MiniMax Code's video vocabulary.
|
|
@@ -37290,7 +38554,7 @@ function videoOmissionText(reason, label) {
|
|
|
37290
38554
|
* a caller that opts out (MinimaxRequestOptions.cacheControl === false) gets
|
|
37291
38555
|
* the original string body byte-for-byte.
|
|
37292
38556
|
*/
|
|
37293
|
-
function isRecord$
|
|
38557
|
+
function isRecord$49(value) {
|
|
37294
38558
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37295
38559
|
}
|
|
37296
38560
|
function asString$20(value) {
|
|
@@ -37343,7 +38607,7 @@ const SUPPORTED_IMAGE_MEDIA_TYPES$2 = /* @__PURE__ */ new Set([
|
|
|
37343
38607
|
]);
|
|
37344
38608
|
function attachmentOf$2(block) {
|
|
37345
38609
|
const attachment = block.attachment;
|
|
37346
|
-
return isRecord$
|
|
38610
|
+
return isRecord$49(attachment) ? attachment : void 0;
|
|
37347
38611
|
}
|
|
37348
38612
|
function attachmentLabel$2(block) {
|
|
37349
38613
|
const attachment = attachmentOf$2(block);
|
|
@@ -37379,7 +38643,7 @@ function textOf$6(content) {
|
|
|
37379
38643
|
if (!Array.isArray(content)) return "";
|
|
37380
38644
|
const parts = [];
|
|
37381
38645
|
for (const block of content) {
|
|
37382
|
-
if (!isRecord$
|
|
38646
|
+
if (!isRecord$49(block)) continue;
|
|
37383
38647
|
if (block.type === "text" && typeof block.text === "string") parts.push(sanitizeText$6(block.text));
|
|
37384
38648
|
else if (block.type === "tool-result") parts.push(textOf$6(block.content));
|
|
37385
38649
|
}
|
|
@@ -37388,7 +38652,7 @@ function textOf$6(content) {
|
|
|
37388
38652
|
function toolResultText$6(blocks) {
|
|
37389
38653
|
if (!Array.isArray(blocks)) return "";
|
|
37390
38654
|
return blocks.map((block) => {
|
|
37391
|
-
if (!isRecord$
|
|
38655
|
+
if (!isRecord$49(block)) return "";
|
|
37392
38656
|
if (block.type === "text" && typeof block.text === "string") return sanitizeText$6(block.text);
|
|
37393
38657
|
if (block.type === "tool-result") return toolResultText$6(block.content);
|
|
37394
38658
|
if (block.type === "image") return "[image: " + (attachmentLabel$2(block) ?? "attached image") + "]";
|
|
@@ -37407,7 +38671,7 @@ function toolResultBlocks(blocks, images) {
|
|
|
37407
38671
|
const out = [];
|
|
37408
38672
|
let hasImage = false;
|
|
37409
38673
|
for (const block of blocks) {
|
|
37410
|
-
if (!isRecord$
|
|
38674
|
+
if (!isRecord$49(block)) continue;
|
|
37411
38675
|
if (block.type === "text" && typeof block.text === "string") {
|
|
37412
38676
|
out.push({
|
|
37413
38677
|
type: "text",
|
|
@@ -37458,12 +38722,31 @@ function isToolResultMessage$6(message) {
|
|
|
37458
38722
|
return message.source?.kind === "tool";
|
|
37459
38723
|
}
|
|
37460
38724
|
/**
|
|
38725
|
+
* The rule a tool-enabled session must follow before it calls a tool.
|
|
38726
|
+
*
|
|
38727
|
+
* The official agent states it in the system prompt of every session that has
|
|
38728
|
+
* tools: a non-trivial tool step starts with a user-visible assistant text
|
|
38729
|
+
* block. Thinking does not count - a model that reasons and then calls the tool
|
|
38730
|
+
* without saying anything has produced a step the user cannot see, and the
|
|
38731
|
+
* official agent asks for that preamble explicitly.
|
|
38732
|
+
*
|
|
38733
|
+
* It is appended to the assembled system text rather than replacing it: the
|
|
38734
|
+
* caller's own prompt keeps its place at the head (which is the cached prefix),
|
|
38735
|
+
* and this rule lands after it.
|
|
38736
|
+
*/
|
|
38737
|
+
const TOOL_CALL_PREAMBLE_REMINDER = "For any non-trivial tool-call step, you MUST first send a non-empty, user-visible assistant text block. Thinking or reasoning content does not count as the preamble.";
|
|
38738
|
+
/**
|
|
37461
38739
|
* Concatenated system-prompt text.
|
|
37462
38740
|
*
|
|
37463
38741
|
* The system prompt is the head of the prefix the service caches, so this is a
|
|
37464
38742
|
* pure, order-stable fold of its inputs: options.system always leads and message
|
|
37465
38743
|
* text follows in history order. Nothing per-turn is added here, because one
|
|
37466
38744
|
* changed byte at the head invalidates the whole cached prefix.
|
|
38745
|
+
*
|
|
38746
|
+
* The ONE addition is {@link TOOL_CALL_PREAMBLE_REMINDER}, and it is added only
|
|
38747
|
+
* to a session that has both tools and a system prompt - a request with no tools
|
|
38748
|
+
* has no tool-call step to remind the model about, and a request with no system
|
|
38749
|
+
* text at all keeps `system === undefined` rather than gaining one.
|
|
37467
38750
|
*/
|
|
37468
38751
|
function leadingSystemText$6(options) {
|
|
37469
38752
|
const parts = [];
|
|
@@ -37473,7 +38756,11 @@ function leadingSystemText$6(options) {
|
|
|
37473
38756
|
const text = textOf$6(message.content);
|
|
37474
38757
|
if (text !== "") parts.push(text);
|
|
37475
38758
|
}
|
|
37476
|
-
|
|
38759
|
+
if (parts.length === 0) return void 0;
|
|
38760
|
+
if (options.tools && options.tools.length > 0) {
|
|
38761
|
+
if (!parts.join("\n\n").includes("For any non-trivial tool-call step, you MUST first send a non-empty, user-visible assistant text block. Thinking or reasoning content does not count as the preamble.")) parts.push(TOOL_CALL_PREAMBLE_REMINDER);
|
|
38762
|
+
}
|
|
38763
|
+
return parts.join("\n\n");
|
|
37477
38764
|
}
|
|
37478
38765
|
function nonSystemMessages$6(options) {
|
|
37479
38766
|
return options.messages.filter((message) => message.role !== "system");
|
|
@@ -37492,7 +38779,7 @@ function anthropicUserContent$1(message, images, videos, videoAccepted) {
|
|
|
37492
38779
|
if (!Array.isArray(message.content)) return [];
|
|
37493
38780
|
const blocks = [];
|
|
37494
38781
|
for (const block of message.content) {
|
|
37495
|
-
if (!isRecord$
|
|
38782
|
+
if (!isRecord$49(block)) continue;
|
|
37496
38783
|
if (block.type === "text" && typeof block.text === "string") {
|
|
37497
38784
|
const text = sanitizeText$6(block.text);
|
|
37498
38785
|
if (text !== "") blocks.push({
|
|
@@ -37562,7 +38849,7 @@ function anthropicUserContent$1(message, images, videos, videoAccepted) {
|
|
|
37562
38849
|
function computeVisibleContentHash(blocks) {
|
|
37563
38850
|
if (!Array.isArray(blocks)) return "";
|
|
37564
38851
|
const canonical = blocks.map((b) => {
|
|
37565
|
-
if (!isRecord$
|
|
38852
|
+
if (!isRecord$49(b)) return null;
|
|
37566
38853
|
const type = asString$20(b.type) ?? "";
|
|
37567
38854
|
if (type === "text" || type === "reasoning") return [type, sanitizeText$6(asString$20(b.text) ?? "")];
|
|
37568
38855
|
if (type === "tool-call") return [
|
|
@@ -37584,12 +38871,12 @@ function computeVisibleContentHash(blocks) {
|
|
|
37584
38871
|
*/
|
|
37585
38872
|
function replayedThinkingBlock$1(message, index, expectedScope, block) {
|
|
37586
38873
|
const source = message.source;
|
|
37587
|
-
if (source === void 0 || source === null || !isRecord$
|
|
38874
|
+
if (source === void 0 || source === null || !isRecord$49(source)) return void 0;
|
|
37588
38875
|
if (source.provider && source.provider !== PROVIDER_ID$8 && source.provider !== "dsh-chatgpt-subscription") return;
|
|
37589
38876
|
if (source.model && expectedScope && source.model !== expectedScope.model) return;
|
|
37590
38877
|
const state = source.replayState;
|
|
37591
|
-
if (!isRecord$
|
|
37592
|
-
const resp = isRecord$
|
|
38878
|
+
if (!isRecord$49(state)) return void 0;
|
|
38879
|
+
const resp = isRecord$49(state.response) ? state.response : state;
|
|
37593
38880
|
const stateRoute = asString$20(resp.route) ?? asString$20(resp.provider);
|
|
37594
38881
|
const stateModel = asString$20(resp.model);
|
|
37595
38882
|
const stateAuthOwner = asString$20(resp.authOwner);
|
|
@@ -37597,19 +38884,19 @@ function replayedThinkingBlock$1(message, index, expectedScope, block) {
|
|
|
37597
38884
|
if (expectedScope === void 0) return void 0;
|
|
37598
38885
|
if (expectedScope.route && stateRoute !== expectedScope.route) return void 0;
|
|
37599
38886
|
if (expectedScope.model && stateModel !== expectedScope.model) return void 0;
|
|
37600
|
-
if (!expectedScope.authOwner || expectedScope.authOwner.trim() === ""
|
|
38887
|
+
if (!expectedScope.authOwner || expectedScope.authOwner.trim() === "") return void 0;
|
|
37601
38888
|
let candidate;
|
|
37602
38889
|
if (Array.isArray(state.blocks)) {
|
|
37603
38890
|
const entry = state.blocks[index];
|
|
37604
|
-
if (isRecord$
|
|
38891
|
+
if (isRecord$49(entry)) candidate = entry;
|
|
37605
38892
|
}
|
|
37606
38893
|
if (candidate === void 0 && Array.isArray(resp.blocks)) {
|
|
37607
38894
|
const entry = resp.blocks[index];
|
|
37608
|
-
if (isRecord$
|
|
38895
|
+
if (isRecord$49(entry)) candidate = entry;
|
|
37609
38896
|
}
|
|
37610
38897
|
if (candidate === void 0 && Array.isArray(resp.nativeBlocks)) {
|
|
37611
38898
|
const entry = resp.nativeBlocks[index];
|
|
37612
|
-
if (isRecord$
|
|
38899
|
+
if (isRecord$49(entry)) candidate = entry;
|
|
37613
38900
|
}
|
|
37614
38901
|
if (candidate === void 0) return void 0;
|
|
37615
38902
|
if (Array.isArray(state.blocks) && state.blocks.length !== message.content.length) return void 0;
|
|
@@ -37635,7 +38922,7 @@ function anthropicAssistantContent$1(message, expectedScope) {
|
|
|
37635
38922
|
if (!Array.isArray(message.content)) return blocks;
|
|
37636
38923
|
for (let index = 0; index < message.content.length; index++) {
|
|
37637
38924
|
const block = message.content[index];
|
|
37638
|
-
if (!isRecord$
|
|
38925
|
+
if (!isRecord$49(block)) continue;
|
|
37639
38926
|
if (block.type === "text" && typeof block.text === "string") {
|
|
37640
38927
|
const text = sanitizeText$6(block.text);
|
|
37641
38928
|
if (text !== "") blocks.push({
|
|
@@ -37650,13 +38937,22 @@ function anthropicAssistantContent$1(message, expectedScope) {
|
|
|
37650
38937
|
type: "tool_use",
|
|
37651
38938
|
id: asString$20(block.id) ?? "toolu_" + blocks.length,
|
|
37652
38939
|
name: block.name,
|
|
37653
|
-
input: isRecord$
|
|
38940
|
+
input: isRecord$49(parsed) ? parsed : {}
|
|
37654
38941
|
});
|
|
37655
38942
|
continue;
|
|
37656
38943
|
}
|
|
37657
38944
|
if (block.type === "reasoning") {
|
|
37658
38945
|
const replay = replayedThinkingBlock$1(message, index, expectedScope, block);
|
|
37659
|
-
if (replay !== void 0)
|
|
38946
|
+
if (replay !== void 0) {
|
|
38947
|
+
blocks.push(replay);
|
|
38948
|
+
continue;
|
|
38949
|
+
}
|
|
38950
|
+
const fallbackText = sanitizeText$6(typeof block.text === "string" ? block.text : "");
|
|
38951
|
+
const trimmed = fallbackText.trim();
|
|
38952
|
+
if (trimmed !== "" && trimmed !== "[Reasoning redacted]") blocks.push({
|
|
38953
|
+
type: "text",
|
|
38954
|
+
text: fallbackText
|
|
38955
|
+
});
|
|
37660
38956
|
continue;
|
|
37661
38957
|
}
|
|
37662
38958
|
}
|
|
@@ -37733,15 +39029,17 @@ function thinkingFieldFor(modelId, requestedEffort) {
|
|
|
37733
39029
|
* The level belongs at the TOP level - `output_config.effort` - and accepts
|
|
37734
39030
|
* low, medium, high, xhigh and max. There is no `default` member: the page
|
|
37735
39031
|
* says omitting the field means max, so the old local `default` spelling never
|
|
37736
|
-
* reached the wire. This line no longer leans on that: every model that
|
|
37737
|
-
* levels states its default
|
|
37738
|
-
* resolves to
|
|
39032
|
+
* reached the wire. This line no longer leans on that either: every model that
|
|
39033
|
+
* has levels states its default as NULL, so a request that asks for nothing
|
|
39034
|
+
* resolves to no `output_config` at all - which is what the official agent
|
|
39035
|
+
* sends when the conversation picked no level.
|
|
37739
39036
|
*
|
|
37740
39037
|
* The level is the DEPTH, not the channel: measured, low and max differ by
|
|
37741
39038
|
* about 3x thinking and 4x latency, and it composes with the `thinking` object.
|
|
37742
39039
|
*
|
|
37743
39040
|
* @returns the value for `output_config`, or undefined when the request should
|
|
37744
|
-
* carry no thinking control at all
|
|
39041
|
+
* carry no thinking control at all - which is the case for an unset, empty or
|
|
39042
|
+
* unknown level.
|
|
37745
39043
|
*/
|
|
37746
39044
|
function outputConfigFor(modelId, requestedEffort) {
|
|
37747
39045
|
const model = catalogEntry$2(modelId);
|
|
@@ -37883,7 +39181,8 @@ function buildMinimaxRequest(options, images = NO_RESOLVED_IMAGES$2, request = {
|
|
|
37883
39181
|
const requestedEffort = options.reasoningEffort === void 0 ? null : String(options.reasoningEffort);
|
|
37884
39182
|
const outputConfig = outputConfigFor(options.model, requestedEffort);
|
|
37885
39183
|
const thinking = thinkingFieldFor(options.model, requestedEffort);
|
|
37886
|
-
const
|
|
39184
|
+
const modelDef = catalogEntry$2(options.model);
|
|
39185
|
+
const thinkingEngaged = outputConfig !== void 0 || thinking?.type === "adaptive" || modelDef?.thinking === "always-on" || modelDef?.thinking === "forced-effort";
|
|
37887
39186
|
const caching = request.cacheControl !== false;
|
|
37888
39187
|
const body = {
|
|
37889
39188
|
model: options.model,
|
|
@@ -37899,6 +39198,7 @@ function buildMinimaxRequest(options, images = NO_RESOLVED_IMAGES$2, request = {
|
|
|
37899
39198
|
...options.tools && options.tools.length > 0 ? { tools: options.tools.map((tool) => ({
|
|
37900
39199
|
name: tool.name,
|
|
37901
39200
|
description: tool.description,
|
|
39201
|
+
eager_input_streaming: true,
|
|
37902
39202
|
input_schema: stripMetaSchema$1(tool.parameters)
|
|
37903
39203
|
})) } : {},
|
|
37904
39204
|
...thinking === void 0 ? {} : { thinking },
|
|
@@ -37935,6 +39235,7 @@ function createStreamState(options) {
|
|
|
37935
39235
|
authOwner: options.authOwner,
|
|
37936
39236
|
provider: options.provider ?? PROVIDER_ID$8
|
|
37937
39237
|
} : void 0,
|
|
39238
|
+
toolSchemas: options?.tools && options.tools.length > 0 ? new Map(options.tools.map((tool) => [tool.name, tool.parameters])) : void 0,
|
|
37938
39239
|
replayBlocks: [],
|
|
37939
39240
|
pendingThinking: /* @__PURE__ */ new Map(),
|
|
37940
39241
|
blocks: [],
|
|
@@ -37988,6 +39289,27 @@ function openTextBlock$4(state, type) {
|
|
|
37988
39289
|
});
|
|
37989
39290
|
return out;
|
|
37990
39291
|
}
|
|
39292
|
+
/**
|
|
39293
|
+
* The argument string one finished tool call carries.
|
|
39294
|
+
*
|
|
39295
|
+
* The model writes tool arguments in shapes the schema does not accept: numbers
|
|
39296
|
+
* as strings, an `edits` array as a JSON string, an array wrapped in
|
|
39297
|
+
* `{"item": [...]}`. DSH's tool guard then refuses the call over a shape the
|
|
39298
|
+
* model had no way to know was wrong, so the arguments are repaired here - at
|
|
39299
|
+
* the end of the stream, where the whole argument string is finally known.
|
|
39300
|
+
*
|
|
39301
|
+
* The repair is LOSSLESS, and it only runs when it changes something:
|
|
39302
|
+
* arguments that need no repair come out byte-for-byte as they arrived, and
|
|
39303
|
+
* arguments that do not parse as an object are left exactly as they were.
|
|
39304
|
+
*/
|
|
39305
|
+
function finalizeToolCallArguments(name, rawArguments, toolSchemas) {
|
|
39306
|
+
if (rawArguments === "") return "{}";
|
|
39307
|
+
const parsed = safeJsonParse$6(rawArguments);
|
|
39308
|
+
if (!isRecord$49(parsed)) return rawArguments;
|
|
39309
|
+
const repaired = repairMinimaxToolArguments(name, parsed, toolSchemas?.get(name));
|
|
39310
|
+
if (repaired.fixes.length === 0) return rawArguments;
|
|
39311
|
+
return JSON.stringify(repaired.value);
|
|
39312
|
+
}
|
|
37991
39313
|
function closeToolCalls$4(state) {
|
|
37992
39314
|
const out = [];
|
|
37993
39315
|
for (const [wireIndex, call] of [...state.toolCalls.entries()].sort((a, b) => a[0] - b[0])) {
|
|
@@ -37995,7 +39317,7 @@ function closeToolCalls$4(state) {
|
|
|
37995
39317
|
type: "tool-call",
|
|
37996
39318
|
id: toToolCallId(call.id),
|
|
37997
39319
|
name: call.name,
|
|
37998
|
-
arguments: call.
|
|
39320
|
+
arguments: finalizeToolCallArguments(call.name, call.arguments, state.toolSchemas)
|
|
37999
39321
|
};
|
|
38000
39322
|
state.blocks[call.blockIndex] = block;
|
|
38001
39323
|
state.replayBlocks[call.blockIndex] = null;
|
|
@@ -38108,12 +39430,12 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38108
39430
|
const payload = trimmed.slice(5).trim();
|
|
38109
39431
|
if (payload === "" || payload === "[DONE]") return [];
|
|
38110
39432
|
const event = safeJsonParse$6(payload);
|
|
38111
|
-
if (!isRecord$
|
|
39433
|
+
if (!isRecord$49(event)) return [];
|
|
38112
39434
|
const type = asString$20(event.type);
|
|
38113
39435
|
const out = [];
|
|
38114
39436
|
if (type === "message_start") {
|
|
38115
|
-
const message = isRecord$
|
|
38116
|
-
const usage = message !== void 0 && isRecord$
|
|
39437
|
+
const message = isRecord$49(event.message) ? event.message : void 0;
|
|
39438
|
+
const usage = message !== void 0 && isRecord$49(message.usage) ? message.usage : void 0;
|
|
38117
39439
|
if (usage !== void 0) {
|
|
38118
39440
|
state.sawUsage = true;
|
|
38119
39441
|
state.inputTokens = numberOr$7(usage.input_tokens, 0);
|
|
@@ -38129,7 +39451,7 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38129
39451
|
}
|
|
38130
39452
|
if (type === "content_block_start") {
|
|
38131
39453
|
const contentIndex = numberOr$7(event.index, 0);
|
|
38132
|
-
const block = isRecord$
|
|
39454
|
+
const block = isRecord$49(event.content_block) ? event.content_block : {};
|
|
38133
39455
|
const blockType = asString$20(block.type);
|
|
38134
39456
|
out.push(...closeCurrent$4(state));
|
|
38135
39457
|
if (blockType === "tool_use") {
|
|
@@ -38180,7 +39502,7 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38180
39502
|
type: "reasoning",
|
|
38181
39503
|
text: state.current.text
|
|
38182
39504
|
});
|
|
38183
|
-
const initialReplay = isRecord$
|
|
39505
|
+
const initialReplay = isRecord$49(event.content_block) ? structuredClone(event.content_block) : { type: blockType };
|
|
38184
39506
|
state.replayBlocks[index] = initialReplay;
|
|
38185
39507
|
state.pendingThinking.set(contentIndex, {
|
|
38186
39508
|
dshIndex: index,
|
|
@@ -38208,7 +39530,7 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38208
39530
|
}
|
|
38209
39531
|
if (type === "content_block_delta") {
|
|
38210
39532
|
const contentIndex = numberOr$7(event.index, 0);
|
|
38211
|
-
const delta = isRecord$
|
|
39533
|
+
const delta = isRecord$49(event.delta) ? event.delta : {};
|
|
38212
39534
|
const deltaType = asString$20(delta.type);
|
|
38213
39535
|
if (deltaType === "input_json_delta") {
|
|
38214
39536
|
const pending = state.toolCalls.get(contentIndex);
|
|
@@ -38297,7 +39619,7 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38297
39619
|
type: "tool-call",
|
|
38298
39620
|
id: toToolCallId(pending.id),
|
|
38299
39621
|
name: pending.name,
|
|
38300
|
-
arguments: pending.
|
|
39622
|
+
arguments: finalizeToolCallArguments(pending.name, pending.arguments, state.toolSchemas)
|
|
38301
39623
|
};
|
|
38302
39624
|
state.blocks[pending.blockIndex] = block;
|
|
38303
39625
|
out.push({
|
|
@@ -38311,10 +39633,10 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38311
39633
|
return out;
|
|
38312
39634
|
}
|
|
38313
39635
|
if (type === "message_delta") {
|
|
38314
|
-
const delta = isRecord$
|
|
39636
|
+
const delta = isRecord$49(event.delta) ? event.delta : void 0;
|
|
38315
39637
|
const stop = delta === void 0 ? void 0 : asString$20(delta.stop_reason);
|
|
38316
39638
|
if (stop !== void 0 && stop !== "") state.finishReason = stop;
|
|
38317
|
-
const usage = isRecord$
|
|
39639
|
+
const usage = isRecord$49(event.usage) ? event.usage : void 0;
|
|
38318
39640
|
if (usage !== void 0) {
|
|
38319
39641
|
state.sawUsage = true;
|
|
38320
39642
|
state.inputTokens = numberOr$7(usage.input_tokens, state.inputTokens);
|
|
@@ -38329,7 +39651,7 @@ function processMinimaxStreamLine(line, state) {
|
|
|
38329
39651
|
return closeMinimaxStream(state);
|
|
38330
39652
|
}
|
|
38331
39653
|
if (type === "error") {
|
|
38332
|
-
const error = isRecord$
|
|
39654
|
+
const error = isRecord$49(event.error) ? event.error : {};
|
|
38333
39655
|
state.streamError = error;
|
|
38334
39656
|
throw new LlmError$1("MiniMax Code(编程订阅) stream error: " + (asString$20(error.message) ?? "unknown error"), isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
|
|
38335
39657
|
}
|
|
@@ -38402,7 +39724,7 @@ const MINIMAX_CODE_MODELS = [
|
|
|
38402
39724
|
"xhigh",
|
|
38403
39725
|
"max"
|
|
38404
39726
|
],
|
|
38405
|
-
defaultReasoningEffort:
|
|
39727
|
+
defaultReasoningEffort: null,
|
|
38406
39728
|
maxAttachments: 9,
|
|
38407
39729
|
maxImageBytes: 10 * 1024 * 1024,
|
|
38408
39730
|
maxVideoBytes: 50 * 1024 * 1024,
|
|
@@ -38428,7 +39750,7 @@ const MINIMAX_CODE_MODELS = [
|
|
|
38428
39750
|
"xhigh",
|
|
38429
39751
|
"max"
|
|
38430
39752
|
],
|
|
38431
|
-
defaultReasoningEffort:
|
|
39753
|
+
defaultReasoningEffort: null,
|
|
38432
39754
|
maxAttachments: 4,
|
|
38433
39755
|
maxImageBytes: 10 * 1024 * 1024,
|
|
38434
39756
|
maxVideoBytes: 50 * 1024 * 1024,
|
|
@@ -38495,14 +39817,22 @@ function isThinkingDisabledEffort(value) {
|
|
|
38495
39817
|
/**
|
|
38496
39818
|
* The effort level to put on the wire for one model.
|
|
38497
39819
|
*
|
|
38498
|
-
*
|
|
38499
|
-
*
|
|
39820
|
+
* NULL means "this request carries no `output_config.effort`", which is what
|
|
39821
|
+
* the official agent sends when the conversation picked no level. Every model in
|
|
39822
|
+
* this catalog states null as its default, so a request that names no effort
|
|
39823
|
+
* states no effort.
|
|
39824
|
+
*
|
|
39825
|
+
* An unknown value falls back to the model's documented default, so a caller
|
|
39826
|
+
* cannot talk this route into a level the model does not list - and with that
|
|
39827
|
+
* default being null, an unknown level now means no level rather than the most
|
|
39828
|
+
* expensive one.
|
|
38500
39829
|
*/
|
|
38501
39830
|
function effortForModel(modelId, requested) {
|
|
38502
39831
|
const model = minimaxCodeModelDef(modelId);
|
|
38503
39832
|
if (model === void 0) return null;
|
|
38504
39833
|
if (model.reasoningEfforts.length === 0) return null;
|
|
38505
|
-
if (requested
|
|
39834
|
+
if (isThinkingDisabledEffort(requested)) return null;
|
|
39835
|
+
if (requested === void 0 || requested === null || requested.trim() === "") return model.defaultReasoningEffort;
|
|
38506
39836
|
const normalized = requested.trim().toLowerCase();
|
|
38507
39837
|
return model.reasoningEfforts.find((effort) => effort === normalized) ?? model.defaultReasoningEffort;
|
|
38508
39838
|
}
|
|
@@ -38632,7 +39962,7 @@ function authStateJsonPath(region, buildEnv = MINIMAX_CODE_BUILD_ENV) {
|
|
|
38632
39962
|
function pluginCredentialPath() {
|
|
38633
39963
|
return path.join(dshHomeDir(), "storages", "minimax-code-credentials.json");
|
|
38634
39964
|
}
|
|
38635
|
-
function isRecord$
|
|
39965
|
+
function isRecord$48(value) {
|
|
38636
39966
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38637
39967
|
}
|
|
38638
39968
|
function asString$19(value) {
|
|
@@ -38654,7 +39984,7 @@ function asFiniteNumber$4(value) {
|
|
|
38654
39984
|
* exists to prevent.
|
|
38655
39985
|
*/
|
|
38656
39986
|
function parseMinimaxCodeCredentials(value, fallback) {
|
|
38657
|
-
if (!isRecord$
|
|
39987
|
+
if (!isRecord$48(value)) throw new Error("MiniMax Code credential payload is invalid");
|
|
38658
39988
|
const accessToken = asString$19(value.accessToken);
|
|
38659
39989
|
if (accessToken === void 0) throw new Error("MiniMax Code credential is missing its access token");
|
|
38660
39990
|
const refreshToken = asString$19(value.refreshToken);
|
|
@@ -38940,10 +40270,10 @@ async function readNativeDocument(region) {
|
|
|
38940
40270
|
} catch {
|
|
38941
40271
|
return null;
|
|
38942
40272
|
}
|
|
38943
|
-
if (!isRecord$
|
|
40273
|
+
if (!isRecord$48(parsed) || !isRecord$48(parsed.records)) return null;
|
|
38944
40274
|
const records = parsed.records;
|
|
38945
40275
|
for (const [recordKey, entry] of Object.entries(records)) {
|
|
38946
|
-
if (!isRecord$
|
|
40276
|
+
if (!isRecord$48(entry)) continue;
|
|
38947
40277
|
if (asString$19(entry.clientId) !== "mcode-public") continue;
|
|
38948
40278
|
if (asString$19(entry.accessToken) === void 0) continue;
|
|
38949
40279
|
return {
|
|
@@ -38971,7 +40301,7 @@ async function syncAuthState(region, options) {
|
|
|
38971
40301
|
} catch {
|
|
38972
40302
|
return;
|
|
38973
40303
|
}
|
|
38974
|
-
if (!isRecord$
|
|
40304
|
+
if (!isRecord$48(parsed)) return;
|
|
38975
40305
|
const next = {
|
|
38976
40306
|
...parsed,
|
|
38977
40307
|
generation: options.generation,
|
|
@@ -39894,14 +41224,25 @@ function withTimeout$8(signal, ms) {
|
|
|
39894
41224
|
*
|
|
39895
41225
|
* The token itself never appears in a log line or an error: callers that need to
|
|
39896
41226
|
* name a credential do so through `redactToken`.
|
|
41227
|
+
*
|
|
41228
|
+
* @param context the session identity the managed agent expects on a request
|
|
41229
|
+
* that belongs to a session: the session id, the agent id inside it, and the
|
|
41230
|
+
* caller's timezone offset. They are sent only when there IS a session — a
|
|
41231
|
+
* request without one carries none of them.
|
|
39897
41232
|
*/
|
|
39898
|
-
function modelRequestHeaders(accessToken) {
|
|
41233
|
+
function modelRequestHeaders(accessToken, context) {
|
|
39899
41234
|
return {
|
|
39900
41235
|
authorization: "Bearer " + accessToken,
|
|
39901
41236
|
"anthropic-version": ANTHROPIC_VERSION$2,
|
|
41237
|
+
"anthropic-beta": ANTHROPIC_INTERLEAVED_THINKING_BETA,
|
|
39902
41238
|
"content-type": "application/json",
|
|
39903
41239
|
accept: "text/event-stream",
|
|
39904
|
-
"user-agent":
|
|
41240
|
+
"user-agent": MINIMAX_AGENT_USER_AGENT,
|
|
41241
|
+
...context?.sessionId ? {
|
|
41242
|
+
"x-mavis-session-id": context.sessionId,
|
|
41243
|
+
"x-mavis-agent-id": context.agentId || "main",
|
|
41244
|
+
"x-mavis-timezone-offset": String(context.timezoneOffsetSec ?? (/* @__PURE__ */ new Date()).getTimezoneOffset() * -60)
|
|
41245
|
+
} : {}
|
|
39905
41246
|
};
|
|
39906
41247
|
}
|
|
39907
41248
|
/** Headers for a non-streaming call (the probe). */
|
|
@@ -40485,7 +41826,7 @@ var FileIdStore = class FileIdStore {
|
|
|
40485
41826
|
const raw = await (await import("node:fs/promises")).readFile(this.path, "utf8").catch(() => "");
|
|
40486
41827
|
if (raw.trim() === "") return {};
|
|
40487
41828
|
const parsed = JSON.parse(raw);
|
|
40488
|
-
return isRecord$
|
|
41829
|
+
return isRecord$47(parsed) ? parsed : {};
|
|
40489
41830
|
}
|
|
40490
41831
|
async write(value) {
|
|
40491
41832
|
if (this.path === void 0) {
|
|
@@ -40502,7 +41843,7 @@ var FileIdStore = class FileIdStore {
|
|
|
40502
41843
|
/** Shared by every in-memory instance, so they see one cache. */
|
|
40503
41844
|
static memory;
|
|
40504
41845
|
};
|
|
40505
|
-
function isRecord$
|
|
41846
|
+
function isRecord$47(value) {
|
|
40506
41847
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40507
41848
|
}
|
|
40508
41849
|
/** Stable key for one (content, account) pair. */
|
|
@@ -40620,7 +41961,7 @@ function isAbort$1(error, signal) {
|
|
|
40620
41961
|
}
|
|
40621
41962
|
/** The file id from a successful upload body, or undefined. */
|
|
40622
41963
|
function readFileId(payload) {
|
|
40623
|
-
if (!isRecord$
|
|
41964
|
+
if (!isRecord$47(payload) || !isRecord$47(payload.base_resp) || !isRecord$47(payload.file)) return void 0;
|
|
40624
41965
|
if (payload.base_resp["status_code"] !== 0) return void 0;
|
|
40625
41966
|
const fileId = payload.file["file_id"];
|
|
40626
41967
|
if (typeof fileId === "number") return Number.isSafeInteger(fileId) && fileId >= 0 ? String(fileId) : void 0;
|
|
@@ -40628,13 +41969,13 @@ function readFileId(payload) {
|
|
|
40628
41969
|
}
|
|
40629
41970
|
/** The service's own reason for a refusal, so the message names the cause. */
|
|
40630
41971
|
function describeRejection(payload, raw) {
|
|
40631
|
-
if (isRecord$
|
|
41972
|
+
if (isRecord$47(payload) && isRecord$47(payload.base_resp)) {
|
|
40632
41973
|
const status = payload.base_resp["status_code"];
|
|
40633
41974
|
const reason = payload.base_resp["status_msg"];
|
|
40634
41975
|
if (typeof reason === "string" && reason !== "") return "the Files API refused the upload (" + String(status) + "): " + reason;
|
|
40635
41976
|
}
|
|
40636
41977
|
if (raw.trim() === "") return "the Files API returned an empty body";
|
|
40637
|
-
if (!isRecord$
|
|
41978
|
+
if (!isRecord$47(payload)) return "the Files API returned a non-JSON body: " + raw.slice(0, 120).replace(/\s+/g, " ");
|
|
40638
41979
|
return "the Files API refused the upload without naming a reason";
|
|
40639
41980
|
}
|
|
40640
41981
|
/** Parse a response body without throwing on a non-JSON payload. */
|
|
@@ -41384,12 +42725,18 @@ var MinimaxCodeAdapter = class extends LlmAdapter {
|
|
|
41384
42725
|
return serialized;
|
|
41385
42726
|
};
|
|
41386
42727
|
let body = buildBodyForOwner(authOwner);
|
|
42728
|
+
const rawSessionId = options.sessionId;
|
|
42729
|
+
const rawAgentId = options.agentId;
|
|
42730
|
+
const requestContext = {
|
|
42731
|
+
sessionId: typeof rawSessionId === "string" && rawSessionId.trim() !== "" ? rawSessionId : void 0,
|
|
42732
|
+
agentId: typeof rawAgentId === "string" && rawAgentId.trim() !== "" ? rawAgentId : void 0
|
|
42733
|
+
};
|
|
41387
42734
|
let refusedBody;
|
|
41388
42735
|
for (let attempt = 0;; attempt += 1) {
|
|
41389
42736
|
try {
|
|
41390
42737
|
response = await fetchWithContextBudgetRecovery(fetchFn)(messagesUrl(credentials.region), {
|
|
41391
42738
|
method: "POST",
|
|
41392
|
-
headers: modelRequestHeaders(credentials.accessToken),
|
|
42739
|
+
headers: modelRequestHeaders(credentials.accessToken, requestContext),
|
|
41393
42740
|
body,
|
|
41394
42741
|
signal
|
|
41395
42742
|
});
|
|
@@ -41436,7 +42783,8 @@ var MinimaxCodeAdapter = class extends LlmAdapter {
|
|
|
41436
42783
|
model: options.model,
|
|
41437
42784
|
authOwner,
|
|
41438
42785
|
route: PROVIDER_ID$8,
|
|
41439
|
-
provider: PROVIDER_ID$8
|
|
42786
|
+
provider: PROVIDER_ID$8,
|
|
42787
|
+
tools: requestOptions.tools
|
|
41440
42788
|
});
|
|
41441
42789
|
let buffer = "";
|
|
41442
42790
|
/**
|
|
@@ -42352,7 +43700,7 @@ const PROVIDER_ID$7 = "minimax-code";
|
|
|
42352
43700
|
function videoHistoryPath() {
|
|
42353
43701
|
return path.join(dshHomeDir(), "storages", "minimax-code-video-history.json");
|
|
42354
43702
|
}
|
|
42355
|
-
function isRecord$
|
|
43703
|
+
function isRecord$46(value) {
|
|
42356
43704
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42357
43705
|
}
|
|
42358
43706
|
function asNonEmptyString(value) {
|
|
@@ -42374,7 +43722,7 @@ function asFiniteNumber$3(value) {
|
|
|
42374
43722
|
* @returns the normalized entry, or undefined to drop it.
|
|
42375
43723
|
*/
|
|
42376
43724
|
function parseHistoryEntry(value) {
|
|
42377
|
-
if (!isRecord$
|
|
43725
|
+
if (!isRecord$46(value)) return void 0;
|
|
42378
43726
|
const createdAtMs = asFiniteNumber$3(value.createdAtMs);
|
|
42379
43727
|
const model = asNonEmptyString(value.model);
|
|
42380
43728
|
const videoPath = asNonEmptyString(value.videoPath);
|
|
@@ -42406,7 +43754,7 @@ function parseHistoryEntry(value) {
|
|
|
42406
43754
|
* @returns the normalized document.
|
|
42407
43755
|
*/
|
|
42408
43756
|
function parseHistoryDocument(value) {
|
|
42409
|
-
if (!isRecord$
|
|
43757
|
+
if (!isRecord$46(value) || !Array.isArray(value.entries)) return {
|
|
42410
43758
|
version: 1,
|
|
42411
43759
|
entries: []
|
|
42412
43760
|
};
|
|
@@ -44459,6 +45807,429 @@ function createMinimaxGenerateVideoTool(ctx, options) {
|
|
|
44459
45807
|
}
|
|
44460
45808
|
});
|
|
44461
45809
|
}
|
|
45810
|
+
/** 官方重复刹车的开关环境变量。 */
|
|
45811
|
+
const REPEAT_BREAKER_ENV = "KIMI_CODE_REPEAT_BREAKER";
|
|
45812
|
+
/** 第一段提醒文案。 */
|
|
45813
|
+
const REMINDER_TEXT_1 = "<system-reminder>\nThe same tool call has been repeated several times in a row. Before making your next call, write one sentence stating what new information you expect it to produce. Then act on that sentence: if it names something this result does not already give you, choose the action that best provides it; otherwise, continue with the evidence you already have.\n</system-reminder>";
|
|
45814
|
+
/**
|
|
45815
|
+
* 造第二段提醒文案(连击 5-7 次时用)。
|
|
45816
|
+
*
|
|
45817
|
+
* @param repeatCount - 当前连击次数,原样写进文案。
|
|
45818
|
+
* @returns 提醒正文。
|
|
45819
|
+
*/
|
|
45820
|
+
function makeReminderText2(repeatCount) {
|
|
45821
|
+
return "<system-reminder>\nThe same tool call has now been issued " + String(repeatCount) + " times in a row. Choose exactly one of the following and state your choice before acting:\n(1) Falsification check: run the cheapest test that could conclusively disprove your current approach, if such a test exists.\n(2) Missing input: tell the user precisely what information or decision you need to proceed, and ask for it.\n(3) Conclude: deliver your best result based on the evidence already gathered, listing anything that remains uncertain.\n</system-reminder>";
|
|
45822
|
+
}
|
|
45823
|
+
/** 第三段提醒文案(连击 8 次起,以及强停那一轮)。 */
|
|
45824
|
+
const REMINDER_TEXT_3 = "<system-reminder>\nWrite your final response now, without any further tool calls. Cover: the current blocker, each approach you have tried and what it established, and the specific information or decision you need from the user to unblock progress. Text only.\n</system-reminder>";
|
|
45825
|
+
/** 强停那一轮之后,守卫用来拒绝后续工具调用的文案。 */
|
|
45826
|
+
const HANDOFF_VETO_TEXT = "This turn was ended by the repeat breaker after the same tool call was issued " + String(12) + " times in a row. This step accepts a text response only, so the tool call was not executed. Reply in text: the current blocker, what you tried, and what you need next.";
|
|
45827
|
+
/**
|
|
45828
|
+
* 不计入连击的协调类工具。
|
|
45829
|
+
*
|
|
45830
|
+
* 这些工具**本来就会**被反复调用:报一次进展、更新一次待办、问一次用户。把它们
|
|
45831
|
+
* 算进连击等于让刹车对着正常的心跳乱响。
|
|
45832
|
+
*/
|
|
45833
|
+
const REPEAT_BREAKER_EXEMPT_TOOLS = Object.freeze([
|
|
45834
|
+
"progress_update",
|
|
45835
|
+
"todo_write",
|
|
45836
|
+
"ask_user_question",
|
|
45837
|
+
"enter_plan_mode",
|
|
45838
|
+
"exit_plan_mode",
|
|
45839
|
+
"leave_plan_mode",
|
|
45840
|
+
"create_goal",
|
|
45841
|
+
"update_goal",
|
|
45842
|
+
"get_goal",
|
|
45843
|
+
"dispatch_ledger",
|
|
45844
|
+
"present"
|
|
45845
|
+
]);
|
|
45846
|
+
/**
|
|
45847
|
+
* 判断一个工具是不是不计入连击的协调类工具。
|
|
45848
|
+
*
|
|
45849
|
+
* @param toolName - 工具名。
|
|
45850
|
+
* @returns 豁免时为 true。
|
|
45851
|
+
*/
|
|
45852
|
+
function isRepeatBreakerExemptTool(toolName) {
|
|
45853
|
+
return REPEAT_BREAKER_EXEMPT_TOOLS.includes(toolName);
|
|
45854
|
+
}
|
|
45855
|
+
/** 明确表示「关掉」的环境变量取值。 */
|
|
45856
|
+
const DISABLED_ENV_VALUES = /* @__PURE__ */ new Set([
|
|
45857
|
+
"0",
|
|
45858
|
+
"false",
|
|
45859
|
+
"no",
|
|
45860
|
+
"off"
|
|
45861
|
+
]);
|
|
45862
|
+
/**
|
|
45863
|
+
* 读重复刹车当前是否启用。
|
|
45864
|
+
*
|
|
45865
|
+
* **默认开启**:刹车是保护,不是功能开关。只有环境变量明确写成
|
|
45866
|
+
* 0 / false / no / off(大小写不敏感)才关掉它。
|
|
45867
|
+
*
|
|
45868
|
+
* @param env - 环境变量视图;默认读 process.env。
|
|
45869
|
+
* @returns 启用时为 true。
|
|
45870
|
+
*/
|
|
45871
|
+
function isKimiRepeatBreakerEnabled(env = process.env) {
|
|
45872
|
+
const raw = env[REPEAT_BREAKER_ENV];
|
|
45873
|
+
if (typeof raw !== "string") return true;
|
|
45874
|
+
return !DISABLED_ENV_VALUES.has(raw.trim().toLowerCase());
|
|
45875
|
+
}
|
|
45876
|
+
/**
|
|
45877
|
+
* 判断一个值是不是普通对象(原型是 Object.prototype 或 null)。
|
|
45878
|
+
*
|
|
45879
|
+
* @param value - 任意值。
|
|
45880
|
+
* @returns 是普通对象时为 true。
|
|
45881
|
+
*/
|
|
45882
|
+
function isPlainRecord(value) {
|
|
45883
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
45884
|
+
const prototype = Object.getPrototypeOf(value);
|
|
45885
|
+
return prototype === Object.prototype || prototype === null;
|
|
45886
|
+
}
|
|
45887
|
+
/**
|
|
45888
|
+
* 判断一个值是不是对象(数组也算)。
|
|
45889
|
+
*
|
|
45890
|
+
* @param value - 任意值。
|
|
45891
|
+
* @returns 是对象时为 true。
|
|
45892
|
+
*/
|
|
45893
|
+
function isRecord$45(value) {
|
|
45894
|
+
return typeof value === "object" && value !== null;
|
|
45895
|
+
}
|
|
45896
|
+
/**
|
|
45897
|
+
* 读一个未知字段为非空字符串。
|
|
45898
|
+
*
|
|
45899
|
+
* @param value - 候选值。
|
|
45900
|
+
* @returns 字符串,或任何其它类型的 undefined。
|
|
45901
|
+
*/
|
|
45902
|
+
function stringOf$3(value) {
|
|
45903
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
45904
|
+
}
|
|
45905
|
+
/**
|
|
45906
|
+
* 读一次工具调用所属的线路。
|
|
45907
|
+
*
|
|
45908
|
+
* provider 的四个来源按可靠性排序:**请求头快照**(唯一反映「已经真的路由到
|
|
45909
|
+
* 哪个 provider」的那一份)→ **模型选择面**(首步还没有请求头时唯一还能说出
|
|
45910
|
+
* 这一场走哪条线路的地方)→ **agent 选项**(还没发出请求时唯一的意图)→
|
|
45911
|
+
* **agent 自身的 provider 字段**(最后的兜底)。
|
|
45912
|
+
*
|
|
45913
|
+
* 每一处读取都独立 try/catch:任何一处抛错都只是「这一处读不到」,不改变
|
|
45914
|
+
* 其余来源的行为,也不让整次读取失败。
|
|
45915
|
+
*
|
|
45916
|
+
* @param agent - 事件里的调用方 agent。
|
|
45917
|
+
* @returns 线路信息;读不到的字段省略。
|
|
45918
|
+
*/
|
|
45919
|
+
function kimiSessionRouteOf(agent) {
|
|
45920
|
+
const record = isRecord$45(agent) ? agent : void 0;
|
|
45921
|
+
const session = record?.session;
|
|
45922
|
+
let provider;
|
|
45923
|
+
try {
|
|
45924
|
+
provider = stringOf$3(session?.requestHeader?.()?.config?.provider);
|
|
45925
|
+
} catch {
|
|
45926
|
+
provider = void 0;
|
|
45927
|
+
}
|
|
45928
|
+
if (provider === void 0) try {
|
|
45929
|
+
provider = stringOf$3(record?.model?.current?.()?.provider);
|
|
45930
|
+
} catch {
|
|
45931
|
+
provider = void 0;
|
|
45932
|
+
}
|
|
45933
|
+
if (provider === void 0) provider = stringOf$3(record?.options?.provider);
|
|
45934
|
+
if (provider === void 0) provider = stringOf$3(record?.provider);
|
|
45935
|
+
const sessionId = stringOf$3(session?.header?.id) ?? stringOf$3(record?.id);
|
|
45936
|
+
return {
|
|
45937
|
+
...provider === void 0 ? {} : { provider },
|
|
45938
|
+
...sessionId === void 0 ? {} : { sessionId }
|
|
45939
|
+
};
|
|
45940
|
+
}
|
|
45941
|
+
/**
|
|
45942
|
+
* 递归把一个值重排成「键名有序」的形状。
|
|
45943
|
+
*
|
|
45944
|
+
* 数组**保持原序**:数组元素的顺序本身就是语义([1, 2] 与 [2, 1] 不是同一件事),
|
|
45945
|
+
* 只有对象的键名顺序没有语义。
|
|
45946
|
+
*
|
|
45947
|
+
* @param value - 当前值。
|
|
45948
|
+
* @returns 重排后的值。
|
|
45949
|
+
*/
|
|
45950
|
+
function sortJsonValue(value) {
|
|
45951
|
+
if (Array.isArray(value)) return value.map(sortJsonValue);
|
|
45952
|
+
if (!isPlainRecord(value)) return value;
|
|
45953
|
+
const out = {};
|
|
45954
|
+
for (const key of Object.keys(value).sort()) out[key] = sortJsonValue(value[key]);
|
|
45955
|
+
return out;
|
|
45956
|
+
}
|
|
45957
|
+
/**
|
|
45958
|
+
* 造一次工具调用的**规范键**。
|
|
45959
|
+
*
|
|
45960
|
+
* 键 = 工具名 + 参数的规范 JSON。参数先递归重排键名再序列化,于是
|
|
45961
|
+
* { a: 1, b: 2 } 与 { b: 2, a: 1 } 得到**完全相同**的键 —— 否则模型只是把参数
|
|
45962
|
+
* 的书写顺序换了一下,刹车就看不见这是一个连击。
|
|
45963
|
+
*
|
|
45964
|
+
* @param toolName - 工具名。
|
|
45965
|
+
* @param args - 工具参数。
|
|
45966
|
+
* @returns 规范键。
|
|
45967
|
+
*/
|
|
45968
|
+
function canonicalKimiToolCallKey(toolName, args) {
|
|
45969
|
+
let json;
|
|
45970
|
+
try {
|
|
45971
|
+
json = JSON.stringify(sortJsonValue(args));
|
|
45972
|
+
} catch {
|
|
45973
|
+
json = void 0;
|
|
45974
|
+
}
|
|
45975
|
+
return toolName + " " + (json ?? String(args));
|
|
45976
|
+
}
|
|
45977
|
+
/**
|
|
45978
|
+
* 造一台重复刹车。
|
|
45979
|
+
*
|
|
45980
|
+
* 状态**按会话**分开:连击是「这场对话里的同一件事重复了多少次」,两个会话
|
|
45981
|
+
* 互不相干。
|
|
45982
|
+
*
|
|
45983
|
+
* @returns 一台重复刹车。
|
|
45984
|
+
*/
|
|
45985
|
+
function createKimiRepeatBreaker() {
|
|
45986
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
45987
|
+
/** 取一个会话的状态;没有就新建一个。 */
|
|
45988
|
+
const stateOf = (sessionId) => {
|
|
45989
|
+
const existing = sessions.get(sessionId);
|
|
45990
|
+
if (existing !== void 0) return existing;
|
|
45991
|
+
const created = {
|
|
45992
|
+
consecutiveKey: null,
|
|
45993
|
+
consecutiveCount: 0,
|
|
45994
|
+
handoffActive: false
|
|
45995
|
+
};
|
|
45996
|
+
sessions.set(sessionId, created);
|
|
45997
|
+
return created;
|
|
45998
|
+
};
|
|
45999
|
+
return {
|
|
46000
|
+
checkBeforeExecute(sessionId, toolName, args) {
|
|
46001
|
+
const state = stateOf(sessionId);
|
|
46002
|
+
if (state.handoffActive) return HANDOFF_VETO_TEXT;
|
|
46003
|
+
const key = canonicalKimiToolCallKey(toolName, args);
|
|
46004
|
+
if (state.consecutiveKey === key && state.consecutiveCount + 1 >= 12) {
|
|
46005
|
+
state.consecutiveCount += 1;
|
|
46006
|
+
state.handoffActive = true;
|
|
46007
|
+
return HANDOFF_VETO_TEXT;
|
|
46008
|
+
}
|
|
46009
|
+
},
|
|
46010
|
+
recordAfterExecute(sessionId, toolName, args) {
|
|
46011
|
+
if (isRepeatBreakerExemptTool(toolName)) return void 0;
|
|
46012
|
+
const state = stateOf(sessionId);
|
|
46013
|
+
if (state.handoffActive) return REMINDER_TEXT_3;
|
|
46014
|
+
const key = canonicalKimiToolCallKey(toolName, args);
|
|
46015
|
+
if (state.consecutiveKey === key) state.consecutiveCount += 1;
|
|
46016
|
+
else {
|
|
46017
|
+
state.consecutiveKey = key;
|
|
46018
|
+
state.consecutiveCount = 1;
|
|
46019
|
+
}
|
|
46020
|
+
if (state.consecutiveCount >= 12) {
|
|
46021
|
+
state.handoffActive = true;
|
|
46022
|
+
return REMINDER_TEXT_3;
|
|
46023
|
+
}
|
|
46024
|
+
if (state.consecutiveCount >= 8) return REMINDER_TEXT_3;
|
|
46025
|
+
if (state.consecutiveCount >= 5) return makeReminderText2(state.consecutiveCount);
|
|
46026
|
+
if (state.consecutiveCount >= 3) return REMINDER_TEXT_1;
|
|
46027
|
+
},
|
|
46028
|
+
resetSession(sessionId) {
|
|
46029
|
+
sessions.delete(sessionId);
|
|
46030
|
+
}
|
|
46031
|
+
};
|
|
46032
|
+
}
|
|
46033
|
+
/**
|
|
46034
|
+
* 读宿主上下文上的工具注册面。
|
|
46035
|
+
*
|
|
46036
|
+
* @param ctx - 宿主上下文。
|
|
46037
|
+
* @returns 工具注册面;没有时为 undefined。
|
|
46038
|
+
*/
|
|
46039
|
+
function toolsServiceOf(ctx) {
|
|
46040
|
+
const read = ctx.get;
|
|
46041
|
+
if (typeof read === "function") try {
|
|
46042
|
+
const found = read.call(ctx, "tools");
|
|
46043
|
+
if (found !== void 0) return found;
|
|
46044
|
+
} catch {}
|
|
46045
|
+
const direct = ctx.tools;
|
|
46046
|
+
return direct === void 0 ? void 0 : direct;
|
|
46047
|
+
}
|
|
46048
|
+
/**
|
|
46049
|
+
* 已挂载的模块登记表,走一个 global symbol:同一个包的两份模块实例(npm 拷贝与
|
|
46050
|
+
* 仓库 link)仍然共享一次判定,而重复装两台刹车会让同一次调用被记两遍。
|
|
46051
|
+
*/
|
|
46052
|
+
const MOUNTED$1 = Symbol.for("dsh-chatgpt-subscription.mounted-modules");
|
|
46053
|
+
/** 本模块在登记表里的名字。 */
|
|
46054
|
+
const MODULE_ID$1 = "kimi-repeat-breaker";
|
|
46055
|
+
/**
|
|
46056
|
+
* 单实例守卫:本模块已挂载时放弃本次安装。
|
|
46057
|
+
*
|
|
46058
|
+
* @param ctx - 宿主上下文。
|
|
46059
|
+
* @returns 释放函数(交出挂载权);已经挂载过时返回 undefined。
|
|
46060
|
+
*/
|
|
46061
|
+
function claimMount$1(ctx) {
|
|
46062
|
+
const registry = globalThis;
|
|
46063
|
+
const existing = registry[MOUNTED$1];
|
|
46064
|
+
const mounted = existing instanceof Set ? existing : /* @__PURE__ */ new Set();
|
|
46065
|
+
if (existing !== mounted) registry[MOUNTED$1] = mounted;
|
|
46066
|
+
if (mounted.has(MODULE_ID$1)) return void 0;
|
|
46067
|
+
mounted.add(MODULE_ID$1);
|
|
46068
|
+
const release = () => {
|
|
46069
|
+
mounted.delete(MODULE_ID$1);
|
|
46070
|
+
};
|
|
46071
|
+
if (typeof ctx.effect === "function") ctx.effect(() => release, "dsh-chatgpt-subscription: kimi repeat breaker mount");
|
|
46072
|
+
return release;
|
|
46073
|
+
}
|
|
46074
|
+
/**
|
|
46075
|
+
* 把一条 post-execute 决策接上附加上下文,保住它原有的形状。
|
|
46076
|
+
*
|
|
46077
|
+
* @param decision - next() 交回来的决策。
|
|
46078
|
+
* @param contexts - 要追加的上下文。
|
|
46079
|
+
* @returns 追加后的决策。
|
|
46080
|
+
*/
|
|
46081
|
+
function withAdditionalContexts(decision, contexts) {
|
|
46082
|
+
const additionalContexts = [...decision.additionalContexts ?? [], ...contexts];
|
|
46083
|
+
if (decision.kind === "block") return {
|
|
46084
|
+
kind: "block",
|
|
46085
|
+
feedback: decision.feedback,
|
|
46086
|
+
additionalContexts
|
|
46087
|
+
};
|
|
46088
|
+
if (decision.value !== void 0) return {
|
|
46089
|
+
kind: "accept",
|
|
46090
|
+
value: decision.value,
|
|
46091
|
+
additionalContexts
|
|
46092
|
+
};
|
|
46093
|
+
if (decision.content !== void 0) return {
|
|
46094
|
+
kind: "accept",
|
|
46095
|
+
content: decision.content,
|
|
46096
|
+
additionalContexts
|
|
46097
|
+
};
|
|
46098
|
+
return {
|
|
46099
|
+
kind: "accept",
|
|
46100
|
+
additionalContexts
|
|
46101
|
+
};
|
|
46102
|
+
}
|
|
46103
|
+
/**
|
|
46104
|
+
* 造一条重复刹车的提醒上下文。
|
|
46105
|
+
*
|
|
46106
|
+
* @param text - 提醒正文。
|
|
46107
|
+
* @returns 可直接放进 additionalContexts 的用户角色消息。
|
|
46108
|
+
*/
|
|
46109
|
+
function createRepeatBreakerReminder(text) {
|
|
46110
|
+
return createUserMessage({
|
|
46111
|
+
content: [{
|
|
46112
|
+
type: "text",
|
|
46113
|
+
text
|
|
46114
|
+
}],
|
|
46115
|
+
source: {
|
|
46116
|
+
kind: "kimi-repeat-breaker",
|
|
46117
|
+
form: "notice",
|
|
46118
|
+
summary: "repeat breaker reminder"
|
|
46119
|
+
}
|
|
46120
|
+
});
|
|
46121
|
+
}
|
|
46122
|
+
/**
|
|
46123
|
+
* 判断一条消息是不是**真的**用户发言。
|
|
46124
|
+
*
|
|
46125
|
+
* 本模块自己追加的提醒也是 user 角色的消息(宿主要求附加上下文走 user 角色),
|
|
46126
|
+
* 所以判定不能只看角色:得看来源是不是 user。
|
|
46127
|
+
*
|
|
46128
|
+
* @param message - 候选消息。
|
|
46129
|
+
* @returns 是真人用户发言时为 true。
|
|
46130
|
+
*/
|
|
46131
|
+
function isRealUserTurn(message) {
|
|
46132
|
+
if (!isRecord$45(message)) return false;
|
|
46133
|
+
const role = message["role"];
|
|
46134
|
+
if (role !== void 0 && role !== "user") return false;
|
|
46135
|
+
const source = message["source"];
|
|
46136
|
+
if (!isRecord$45(source)) return false;
|
|
46137
|
+
return source["kind"] === "user";
|
|
46138
|
+
}
|
|
46139
|
+
/**
|
|
46140
|
+
* 装上 Kimi Code 的重复刹车。
|
|
46141
|
+
*
|
|
46142
|
+
* 四条接缝:ctx.tools.guard()(强停时拦下调用)、tools/post-execute(三段提醒)、
|
|
46143
|
+
* agent/pre-step(新一轮用户输入重置连击)、agent/disposed(会话拆除时清状态)。
|
|
46144
|
+
* 工具声明面一个字节都不改。
|
|
46145
|
+
*
|
|
46146
|
+
* @param ctx - 宿主插件上下文。
|
|
46147
|
+
* @param options - 安装选项。
|
|
46148
|
+
* @returns 卸载函数。
|
|
46149
|
+
*/
|
|
46150
|
+
function installKimiRepeatBreaker(ctx, options = {}) {
|
|
46151
|
+
const releaseMount = claimMount$1(ctx);
|
|
46152
|
+
if (releaseMount === void 0) return () => void 0;
|
|
46153
|
+
const breaker = createKimiRepeatBreaker();
|
|
46154
|
+
const enabled = options.enabled ?? (() => isKimiRepeatBreakerEnabled());
|
|
46155
|
+
/** 读一次开关。读失败按**开启**处理:保护不该因为一次读失败而失效。 */
|
|
46156
|
+
const isEnabled = () => {
|
|
46157
|
+
try {
|
|
46158
|
+
return enabled() !== false;
|
|
46159
|
+
} catch {
|
|
46160
|
+
return true;
|
|
46161
|
+
}
|
|
46162
|
+
};
|
|
46163
|
+
/**
|
|
46164
|
+
* 取一次执行所属的会话;不是 Kimi Code 这条线路时是 undefined。
|
|
46165
|
+
*
|
|
46166
|
+
* @param agent - 调用方 agent。
|
|
46167
|
+
* @returns 会话标识;不该管时是 undefined。
|
|
46168
|
+
*/
|
|
46169
|
+
const kimiSessionIdOf = (agent) => {
|
|
46170
|
+
const route = kimiSessionRouteOf(agent);
|
|
46171
|
+
if (route.provider !== "kimi-code") return void 0;
|
|
46172
|
+
return route.sessionId;
|
|
46173
|
+
};
|
|
46174
|
+
const disposeGuard = toolsServiceOf(ctx)?.guard?.((execution) => {
|
|
46175
|
+
try {
|
|
46176
|
+
if (!isEnabled()) return void 0;
|
|
46177
|
+
const record = isRecord$45(execution) ? execution : void 0;
|
|
46178
|
+
const agent = record?.["agent"];
|
|
46179
|
+
const sessionId = kimiSessionIdOf(agent);
|
|
46180
|
+
if (sessionId === void 0) return void 0;
|
|
46181
|
+
const toolName = stringOf$3(record?.["name"]);
|
|
46182
|
+
if (toolName === void 0) return void 0;
|
|
46183
|
+
const veto = breaker.checkBeforeExecute(sessionId, toolName, record?.["arguments"]);
|
|
46184
|
+
if (veto === HANDOFF_VETO_TEXT) return HANDOFF_VETO_TEXT;
|
|
46185
|
+
return veto;
|
|
46186
|
+
} catch {
|
|
46187
|
+
return;
|
|
46188
|
+
}
|
|
46189
|
+
});
|
|
46190
|
+
const disposePostExecute = ctx.on?.("tools/post-execute", (async (exec, result, next) => {
|
|
46191
|
+
const decision = await next();
|
|
46192
|
+
try {
|
|
46193
|
+
if (!isEnabled()) return decision;
|
|
46194
|
+
const agent = exec.agent;
|
|
46195
|
+
const sessionId = kimiSessionIdOf(agent);
|
|
46196
|
+
if (sessionId === void 0) return decision;
|
|
46197
|
+
const toolName = stringOf$3(exec.name);
|
|
46198
|
+
if (toolName === void 0) return decision;
|
|
46199
|
+
const reminder = breaker.recordAfterExecute(sessionId, toolName, exec.arguments);
|
|
46200
|
+
if (reminder === void 0) return decision;
|
|
46201
|
+
return withAdditionalContexts(decision, [createRepeatBreakerReminder(reminder)]);
|
|
46202
|
+
} catch {
|
|
46203
|
+
return decision;
|
|
46204
|
+
}
|
|
46205
|
+
}));
|
|
46206
|
+
const disposePreStep = ctx.on?.("agent/pre-step", (async (payload, next) => {
|
|
46207
|
+
const decision = await next();
|
|
46208
|
+
try {
|
|
46209
|
+
if (!isRealUserTurn((Array.isArray(payload?.messages) ? payload.messages : []).at(-1))) return decision;
|
|
46210
|
+
const sessionId = kimiSessionIdOf(payload?.agent);
|
|
46211
|
+
if (sessionId === void 0) return decision;
|
|
46212
|
+
breaker.resetSession(sessionId);
|
|
46213
|
+
} catch {
|
|
46214
|
+
return decision;
|
|
46215
|
+
}
|
|
46216
|
+
return decision;
|
|
46217
|
+
}));
|
|
46218
|
+
const disposeDisposed = ctx.on?.("agent/disposed", ((payload) => {
|
|
46219
|
+
try {
|
|
46220
|
+
const sessionId = kimiSessionIdOf(payload?.agent);
|
|
46221
|
+
if (sessionId === void 0) return;
|
|
46222
|
+
breaker.resetSession(sessionId);
|
|
46223
|
+
} catch {}
|
|
46224
|
+
}));
|
|
46225
|
+
return () => {
|
|
46226
|
+
disposeGuard?.();
|
|
46227
|
+
disposePostExecute?.();
|
|
46228
|
+
disposePreStep?.();
|
|
46229
|
+
disposeDisposed?.();
|
|
46230
|
+
releaseMount();
|
|
46231
|
+
};
|
|
46232
|
+
}
|
|
44462
46233
|
//#endregion
|
|
44463
46234
|
//#region src/host/minimax-code/account-pool.ts
|
|
44464
46235
|
/**
|
|
@@ -83442,6 +85213,13 @@ function markPatched$2(patched, holder, name) {
|
|
|
83442
85213
|
if (names === void 0) patched.set(holder, /* @__PURE__ */ new Set([name]));
|
|
83443
85214
|
else names.add(name);
|
|
83444
85215
|
}
|
|
85216
|
+
/**
|
|
85217
|
+
* 默认受保护的 provider 名单。
|
|
85218
|
+
*
|
|
85219
|
+
* `kimi-code` 与 `minimax-code` 都按前缀缓存计费:`tools:sdk` 段一旦被改写,
|
|
85220
|
+
* 前缀缓存从改写处起全部作废,所以这两条线路默认都要冻结 SDK 段。
|
|
85221
|
+
*/
|
|
85222
|
+
const DEFAULT_PTC_SDK_CACHE_PROVIDERS = Object.freeze(["kimi-code", "minimax-code"]);
|
|
83445
85223
|
/** PTC 生成的 SDK 段名。 */
|
|
83446
85224
|
const PTC_SDK_SECTION_NAME = "tools:sdk";
|
|
83447
85225
|
/** 没有 scope 的装配(会话标题之类)用的桶键。 */
|
|
@@ -83521,7 +85299,7 @@ function readScopeProvider(scope) {
|
|
|
83521
85299
|
*/
|
|
83522
85300
|
function installPtcSdkCacheGuard(ctx, options = {}) {
|
|
83523
85301
|
const host = isRecord$13(ctx) ? ctx : void 0;
|
|
83524
|
-
const providers = new Set(options.providers ??
|
|
85302
|
+
const providers = new Set(options.providers ?? DEFAULT_PTC_SDK_CACHE_PROVIDERS);
|
|
83525
85303
|
/** 已包装过的实例(幂等标记)。 */
|
|
83526
85304
|
const alreadyWrapped = /* @__PURE__ */ new WeakSet();
|
|
83527
85305
|
/** 已包装过的「方法宿主 + 方法名」:同一个原型不叠第二层包装。 */
|
|
@@ -98921,6 +100699,8 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
98921
100699
|
const guard = installCompactionPolicyGuard(ctx);
|
|
98922
100700
|
return () => guard.dispose();
|
|
98923
100701
|
}, "dsh-chatgpt-subscription: compaction policy guard");
|
|
100702
|
+
ctx.effect(() => installMinimaxRuntimeEnhancements(ctx), "dsh-chatgpt-subscription: MiniMax runtime enhancements");
|
|
100703
|
+
ctx.effect(() => installKimiRepeatBreaker(ctx), "dsh-chatgpt-subscription: Kimi repeat breaker");
|
|
98924
100704
|
ctx.effect(() => installDispatchExecutionGuard(ctx, { enabled: () => resolveDispatchExecutionGuardEnabled(pluginConfig) }), "dsh-chatgpt-subscription: dispatch execution guard");
|
|
98925
100705
|
ctx.effect(() => installDispatchLedger(ctx, {
|
|
98926
100706
|
enabled: () => resolveDispatchExecutionGuardEnabled(pluginConfig),
|