@zergai/ztc 0.4.0-beta.1 → 0.4.1-dev.36919234045
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/README.md +8 -1
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/App.js +2 -2
- package/dist/agent/agent.js +41 -5
- package/dist/agent/backends/anthropic.js +5 -10
- package/dist/agent/backends/gemini.js +2 -0
- package/dist/agent/backends/index.d.ts +1 -0
- package/dist/agent/backends/index.js +10 -1
- package/dist/agent/backends/openai.d.ts +0 -6
- package/dist/agent/backends/openai.js +5 -2
- package/dist/agent/backends/openai_compatible.d.ts +2 -0
- package/dist/agent/backends/openai_compatible.js +18 -8
- package/dist/agent/backends/provider_ids.d.ts +1 -0
- package/dist/agent/backends/provider_ids.js +4 -0
- package/dist/agent/backends/types.d.ts +1 -0
- package/dist/agent/backends/zrouter_stream.d.ts +5 -1
- package/dist/agent/backends/zrouter_stream.js +141 -37
- package/dist/agent/commands/compact.js +6 -5
- package/dist/agent/commands/config.js +4 -1
- package/dist/agent/commands/context.js +6 -1
- package/dist/agent/commands/effort.js +14 -6
- package/dist/agent/commands/model.js +12 -2
- package/dist/agent/commands/profile.js +21 -2
- package/dist/agent/commands/provider_selection.js +14 -1
- package/dist/agent/commands/settings.js +45 -7
- package/dist/agent/commands/types.d.ts +19 -0
- package/dist/agent/factory.js +14 -68
- package/dist/agent/subagent.d.ts +0 -10
- package/dist/agent/subagent.js +22 -0
- package/dist/agent/tool_response_store.d.ts +1 -1
- package/dist/agent/tool_response_store.js +4 -2
- package/dist/agent/tools/pane.d.ts +0 -7
- package/dist/agent/tools/pane.js +5 -4
- package/dist/app/command_context.js +33 -10
- package/dist/app/model_catalog_cache.d.ts +5 -0
- package/dist/app/model_catalog_cache.js +138 -0
- package/dist/app/restart.d.ts +1 -1
- package/dist/app/restart.js +16 -5
- package/dist/app/selection_completion.d.ts +17 -2
- package/dist/app/selection_completion.js +74 -6
- package/dist/app/session_manager.js +13 -8
- package/dist/cli_args.js +2 -16
- package/dist/cli_main.js +25 -6
- package/dist/cli_ratatui.js +70 -33
- package/dist/config/defaults.d.ts +2 -1
- package/dist/config/defaults.js +9 -2
- package/dist/config/resolved.d.ts +2 -2
- package/dist/config.d.ts +35 -3
- package/dist/config.js +227 -29
- package/dist/headless.js +2 -0
- package/dist/onboarding/first_run.js +5 -1
- package/dist/panes/model_catalog.d.ts +3 -3
- package/dist/panes/model_catalog.js +28 -4
- package/dist/panes/pane_registry.js +6 -2
- package/dist/panes/types.d.ts +2 -0
- package/dist/panes/ztc_launch.js +12 -0
- package/dist/session.d.ts +6 -2
- package/dist/session.js +65 -10
- package/dist/ui/views/completion_menu.js +10 -5
- package/dist/ui/views/status_bar.js +9 -5
- package/dist/ui/widgets/resume_panel.d.ts +2 -0
- package/dist/ui/widgets/resume_panel.js +17 -15
- package/dist/utils/compaction.d.ts +1 -1
- package/dist/utils/compaction.js +2 -2
- package/dist/utils/context.d.ts +4 -4
- package/dist/utils/context.js +14 -12
- package/dist/utils/deepseek.d.ts +2 -2
- package/dist/utils/deepseek.js +13 -5
- package/dist/utils/model_cache.d.ts +15 -0
- package/dist/utils/model_cache.js +143 -0
- package/dist/utils/models.d.ts +4 -2
- package/dist/utils/models.js +12 -16
- package/dist/utils/reasoning.d.ts +8 -1
- package/dist/utils/reasoning.js +31 -11
- package/dist/utils/router_catalog.d.ts +47 -0
- package/dist/utils/router_catalog.js +222 -0
- package/dist/zlm-embed.mjs +1180 -514
- package/node_modules/@zerg/model-contracts/LICENSE.md +375 -0
- package/node_modules/@zerg/model-contracts/README.md +78 -0
- package/node_modules/@zerg/model-contracts/index.d.ts +18 -0
- package/node_modules/@zerg/model-contracts/index.js +220 -0
- package/node_modules/@zerg/model-contracts/package.json +8 -0
- package/node_modules/glob/node_modules/brace-expansion/index.js +78 -22
- package/node_modules/glob/node_modules/brace-expansion/package.json +1 -1
- package/node_modules/readdir-glob/node_modules/brace-expansion/index.js +78 -22
- package/node_modules/readdir-glob/node_modules/brace-expansion/package.json +1 -1
- package/package.json +9 -6
- package/packages/model-contracts/LICENSE.md +375 -0
- package/packages/model-contracts/README.md +78 -0
- package/packages/model-contracts/index.d.ts +18 -0
- package/packages/model-contracts/index.js +220 -0
- package/packages/model-contracts/package.json +8 -0
package/dist/zlm-embed.mjs
CHANGED
|
@@ -16,6 +16,200 @@ var __export = (target, all) => {
|
|
|
16
16
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
// packages/model-contracts/index.js
|
|
20
|
+
function normalizeContractProvider(provider) {
|
|
21
|
+
const normalized = provider.trim().toLowerCase();
|
|
22
|
+
return normalized === "moonshot" ? "kimi" : normalized === "claude" ? "anthropic" : normalized;
|
|
23
|
+
}
|
|
24
|
+
function normalizeContractModel(provider, model) {
|
|
25
|
+
const canonicalProvider = normalizeContractProvider(provider);
|
|
26
|
+
let id = model.trim().toLowerCase();
|
|
27
|
+
if (id.startsWith(`${canonicalProvider}/`)) id = id.slice(canonicalProvider.length + 1);
|
|
28
|
+
if (canonicalProvider === "fireworks" && id.startsWith("accounts/fireworks/models/")) {
|
|
29
|
+
id = id.slice("accounts/fireworks/models/".length);
|
|
30
|
+
}
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
function modelContract(provider, model, surface = "native_api") {
|
|
34
|
+
const canonicalProvider = normalizeContractProvider(provider);
|
|
35
|
+
const id = normalizeContractModel(canonicalProvider, model);
|
|
36
|
+
const contracts = MODEL_CONTRACTS.get(canonicalProvider);
|
|
37
|
+
const contract = contracts?.get(id) ?? (canonicalProvider === "anthropic" ? contracts?.get(id.replace(/-\d{8}$/, "")) : void 0);
|
|
38
|
+
if (contract === void 0) return void 0;
|
|
39
|
+
return {
|
|
40
|
+
reasoningEfforts: [...surface === "chat_tools" ? contract.chatToolReasoningEfforts ?? contract.reasoningEfforts : contract.reasoningEfforts],
|
|
41
|
+
...contract.chatToolReasoningEfforts ? { chatToolReasoningEfforts: [...contract.chatToolReasoningEfforts] } : {},
|
|
42
|
+
maxOutputTokens: contract.maxOutputTokens === null ? null : { ...contract.maxOutputTokens },
|
|
43
|
+
fallbackRouting: contract.fallbackRouting
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function reasoningRequestParams(provider, model, effort) {
|
|
47
|
+
const canonicalProvider = normalizeContractProvider(provider);
|
|
48
|
+
const id = normalizeContractModel(canonicalProvider, model);
|
|
49
|
+
const contract = modelContract(canonicalProvider, id);
|
|
50
|
+
const selected = typeof effort === "string" && contract?.reasoningEfforts.includes(effort) ? effort : null;
|
|
51
|
+
if (canonicalProvider === "deepseek" && contract?.reasoningEfforts.length) {
|
|
52
|
+
if (selected === "none") return { thinking: { type: "disabled" } };
|
|
53
|
+
return { thinking: { type: "enabled" }, reasoning_effort: selected ?? "high" };
|
|
54
|
+
}
|
|
55
|
+
if (selected === null) return {};
|
|
56
|
+
if (canonicalProvider === "anthropic") return { output_config: { effort: selected } };
|
|
57
|
+
if (canonicalProvider === "gemini") {
|
|
58
|
+
const thinkingConfig = id.startsWith("gemini-2.5-") ? { thinkingBudget: selected === "none" ? 0 : selected === "low" ? 1024 : selected === "medium" ? 8192 : id === "gemini-2.5-pro" ? 32768 : 24576 } : { thinkingLevel: selected };
|
|
59
|
+
return { generationConfig: { thinkingConfig } };
|
|
60
|
+
}
|
|
61
|
+
if (canonicalProvider === "zai") {
|
|
62
|
+
const thinking = { type: selected === "none" ? "disabled" : "enabled" };
|
|
63
|
+
return id === "glm-5.2" || id === "glm-5.3" || id === "glm-5.3-flash" ? { thinking, ...selected === "none" ? {} : { reasoning_effort: selected } } : { thinking };
|
|
64
|
+
}
|
|
65
|
+
if (canonicalProvider === "cohere") return { thinking: { type: selected === "none" ? "disabled" : "enabled" } };
|
|
66
|
+
return { reasoning_effort: selected };
|
|
67
|
+
}
|
|
68
|
+
function fireworksRequestModel(model) {
|
|
69
|
+
const upstream = model.trim().replace(/^fireworks\//i, "");
|
|
70
|
+
if (upstream.startsWith("accounts/")) return upstream;
|
|
71
|
+
return `accounts/fireworks/models/${normalizeContractModel("fireworks", model)}`;
|
|
72
|
+
}
|
|
73
|
+
var MODEL_CONTRACTS, CONTRACT_PROVIDERS;
|
|
74
|
+
var init_model_contracts = __esm({
|
|
75
|
+
"packages/model-contracts/index.js"() {
|
|
76
|
+
"use strict";
|
|
77
|
+
MODEL_CONTRACTS = /* @__PURE__ */ new Map([
|
|
78
|
+
["openai", /* @__PURE__ */ new Map([
|
|
79
|
+
["gpt-4o", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 16384 }, fallbackRouting: true }],
|
|
80
|
+
["gpt-4o-mini", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 16384 }, fallbackRouting: true }],
|
|
81
|
+
["gpt-5", { reasoningEfforts: ["minimal", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
82
|
+
["gpt-5-mini", { reasoningEfforts: ["minimal", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
83
|
+
["gpt-5.2", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
84
|
+
["gpt-5.2-codex", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
85
|
+
["gpt-5.3-codex", { reasoningEfforts: ["low", "medium", "high", "xhigh"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: false }],
|
|
86
|
+
["gpt-5.4", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
87
|
+
["gpt-5.4-mini", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
88
|
+
["gpt-5.5", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
89
|
+
["gpt-5.6", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
90
|
+
["gpt-5.6-current", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: true }],
|
|
91
|
+
["gpt-5.6-luna", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
92
|
+
["gpt-5.6-sol", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
93
|
+
["gpt-5.6-terra", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
94
|
+
["gpt-6-sol", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }],
|
|
95
|
+
["gpt-6-luna", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: { "min": 256, "max": 128e3 }, fallbackRouting: true }]
|
|
96
|
+
])],
|
|
97
|
+
["anthropic", /* @__PURE__ */ new Map([
|
|
98
|
+
["claude-3-5-haiku-20241022", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
99
|
+
["claude-3-5-sonnet-20241022", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
100
|
+
["claude-opus-4-6", { reasoningEfforts: ["low", "medium", "high", "max"], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
101
|
+
["claude-opus-4.8", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
102
|
+
["claude-sonnet-4", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 64e3 }, fallbackRouting: true }],
|
|
103
|
+
["claude-sonnet-4-5", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 64e3 }, fallbackRouting: true }],
|
|
104
|
+
["claude-sonnet-4-6", { reasoningEfforts: ["low", "medium", "high", "max"], maxOutputTokens: { "min": 256, "max": 64e3 }, fallbackRouting: true }],
|
|
105
|
+
["claude-sonnet-4-20250514", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 64e3 }, fallbackRouting: true }],
|
|
106
|
+
["claude-opus-4-5", { reasoningEfforts: ["low", "medium", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
107
|
+
["claude-opus-4-8", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
108
|
+
["claude-opus-4-7", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
109
|
+
["claude-opus-5", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
110
|
+
["claude-opus-5-5", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
111
|
+
["claude-sonnet-5", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
112
|
+
["claude-sonnet-5-5", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
113
|
+
["claude-fable-5", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
114
|
+
["claude-fable-5-1", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
115
|
+
["claude-mythos-5", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
116
|
+
["claude-mythos-5-1", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }]
|
|
117
|
+
])],
|
|
118
|
+
["gemini", /* @__PURE__ */ new Map([
|
|
119
|
+
["gemini-2.0-flash", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
120
|
+
["gemini-2.5-flash", { reasoningEfforts: ["none", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }],
|
|
121
|
+
["gemini-2.5-pro", { reasoningEfforts: ["low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }],
|
|
122
|
+
["gemini-3.6-flash", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
123
|
+
["gemini-2.5-flash-lite", { reasoningEfforts: ["none", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }],
|
|
124
|
+
["gemini-3-flash-preview", { reasoningEfforts: ["minimal", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }],
|
|
125
|
+
["gemini-3.5-flash", { reasoningEfforts: ["minimal", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }],
|
|
126
|
+
["gemini-3.8-flash", { reasoningEfforts: ["minimal", "low", "medium", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }],
|
|
127
|
+
["gemini-3.1-pro-preview", { reasoningEfforts: ["low", "high"], maxOutputTokens: { "min": 256, "max": 65536 }, fallbackRouting: true }]
|
|
128
|
+
])],
|
|
129
|
+
["deepseek", /* @__PURE__ */ new Map([
|
|
130
|
+
["deepseek-flash", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
131
|
+
["deepseek-chat", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
132
|
+
["deepseek-reasoner", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 8192 }, fallbackRouting: true }],
|
|
133
|
+
["deepseek-v4-flash", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
134
|
+
["deepseek-v4-flash-vision-exp", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
135
|
+
["deepseek-v4-pro", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }]
|
|
136
|
+
])],
|
|
137
|
+
["kimi", /* @__PURE__ */ new Map([
|
|
138
|
+
["kimi-for-coding", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 32e3 }, fallbackRouting: true }],
|
|
139
|
+
["kimi-for-coding-highspeed", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 32e3 }, fallbackRouting: true }],
|
|
140
|
+
["kimi-k2.6", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 32e3 }, fallbackRouting: true }],
|
|
141
|
+
["kimi-k2.7-code", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: true }],
|
|
142
|
+
["kimi-k2.7-code-highspeed", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: true }],
|
|
143
|
+
["kimi-k3", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: { "min": 256, "max": 64e3 }, fallbackRouting: true }]
|
|
144
|
+
])],
|
|
145
|
+
["cohere", /* @__PURE__ */ new Map([
|
|
146
|
+
["command-a-03-2025", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
147
|
+
["command-r", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
148
|
+
["command-r-plus", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
149
|
+
["command-a-reasoning-08-2025", { reasoningEfforts: ["none", "high"], maxOutputTokens: { "min": 256, "max": 32e3 }, fallbackRouting: true }]
|
|
150
|
+
])],
|
|
151
|
+
["zai", /* @__PURE__ */ new Map([
|
|
152
|
+
["glm-4-air", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
153
|
+
["glm-4-flash", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
154
|
+
["glm-4-plus", { reasoningEfforts: [], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
155
|
+
["glm-4.5", { reasoningEfforts: ["none", "high"], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
156
|
+
["glm-4.6", { reasoningEfforts: ["none", "high"], maxOutputTokens: { "min": 256, "max": 4096 }, fallbackRouting: true }],
|
|
157
|
+
["glm-4.5-air", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
158
|
+
["glm-4.7", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
159
|
+
["glm-5", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
160
|
+
["glm-5.1", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
161
|
+
["glm-5.2", { reasoningEfforts: ["none", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
162
|
+
["glm-5.3", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
163
|
+
["glm-5.3-flash", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: null, fallbackRouting: true }]
|
|
164
|
+
])],
|
|
165
|
+
["codex", /* @__PURE__ */ new Map([
|
|
166
|
+
["gpt-5.2", { reasoningEfforts: ["low", "medium", "high", "xhigh"], maxOutputTokens: null, fallbackRouting: false }],
|
|
167
|
+
["gpt-5.3-codex", { reasoningEfforts: ["low", "medium", "high", "xhigh"], maxOutputTokens: null, fallbackRouting: false }],
|
|
168
|
+
["gpt-5.3-codex-spark", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
169
|
+
["gpt-5.4", { reasoningEfforts: ["low", "medium", "high", "xhigh"], maxOutputTokens: null, fallbackRouting: false }],
|
|
170
|
+
["gpt-5.4-mini", { reasoningEfforts: ["low", "medium", "high", "xhigh"], maxOutputTokens: null, fallbackRouting: false }],
|
|
171
|
+
["gpt-5.5", { reasoningEfforts: ["low", "medium", "high", "xhigh"], maxOutputTokens: null, fallbackRouting: false }],
|
|
172
|
+
["gpt-5.5-codex", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
173
|
+
["gpt-5.6", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], maxOutputTokens: null, fallbackRouting: false }],
|
|
174
|
+
["gpt-5.6-luna", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: false }],
|
|
175
|
+
["gpt-5.6-sol", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], maxOutputTokens: null, fallbackRouting: false }],
|
|
176
|
+
["gpt-5.6-terra", { reasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], maxOutputTokens: null, fallbackRouting: false }]
|
|
177
|
+
])],
|
|
178
|
+
["openai_compatible", /* @__PURE__ */ new Map([
|
|
179
|
+
["gpt-6-sol", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: null, fallbackRouting: false }],
|
|
180
|
+
["gpt-6-luna", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], chatToolReasoningEfforts: ["none"], maxOutputTokens: null, fallbackRouting: false }]
|
|
181
|
+
])],
|
|
182
|
+
["modal", /* @__PURE__ */ new Map([
|
|
183
|
+
["deepseek-v4.1-flash", { reasoningEfforts: ["none", "low", "high", "xhigh", "max"], maxOutputTokens: { "min": 256, "max": 1048576 }, fallbackRouting: false }],
|
|
184
|
+
["epoch--ep-deepseek-v4-1-flash-server.us-west.modal.direct", { reasoningEfforts: ["none", "low", "high", "xhigh", "max"], maxOutputTokens: { "min": 256, "max": 1048576 }, fallbackRouting: false }],
|
|
185
|
+
["kimi-k3", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: null, fallbackRouting: false }],
|
|
186
|
+
["moonshot--kimi-k3-fast.modal.run", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: null, fallbackRouting: false }]
|
|
187
|
+
])],
|
|
188
|
+
["fireworks", /* @__PURE__ */ new Map([
|
|
189
|
+
["deepseek-v4p1-flash", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
190
|
+
["deepseek-v4-pro-0813", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
191
|
+
["deepseek-v4-flash-0731", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
192
|
+
["deepseek-v4-flash-vision-exp", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: { "min": 256, "max": 384e3 }, fallbackRouting: true }],
|
|
193
|
+
["kimi-k3", { reasoningEfforts: ["none", "low", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
194
|
+
["gpt-oss-120b", { reasoningEfforts: ["low", "medium", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
195
|
+
["qwen3p8-max", { reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
196
|
+
["glm-5p2", { reasoningEfforts: ["none", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
197
|
+
["glm-5p3", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
198
|
+
["glm-5p3-flash", { reasoningEfforts: ["low", "high", "max"], maxOutputTokens: null, fallbackRouting: true }],
|
|
199
|
+
["ember-1", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
200
|
+
["minimax-m3", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
201
|
+
["nemotron-lightning-3p5-30b-a3b", { reasoningEfforts: ["none", "high"], maxOutputTokens: null, fallbackRouting: true }],
|
|
202
|
+
["muse-glimmer-30b", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
203
|
+
["kimi-k2p7-code", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
204
|
+
["nemotron-3-ultra-nvfp4", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
205
|
+
["inkling", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }],
|
|
206
|
+
["kimi-k2p6", { reasoningEfforts: [], maxOutputTokens: null, fallbackRouting: false }]
|
|
207
|
+
])]
|
|
208
|
+
]);
|
|
209
|
+
CONTRACT_PROVIDERS = Object.freeze(["anthropic", "openai", "gemini", "deepseek", "fireworks", "kimi", "voyage", "cohere", "elevenlabs", "replicate", "fal", "zai", "modal", "codex", "self_hosted", "openai_compatible", "typesafe"]);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
19
213
|
// src/agent/backends/sse.ts
|
|
20
214
|
async function* parseSSEEvents(body) {
|
|
21
215
|
const decoder = new TextDecoder();
|
|
@@ -78,255 +272,6 @@ var init_sse = __esm({
|
|
|
78
272
|
}
|
|
79
273
|
});
|
|
80
274
|
|
|
81
|
-
// src/agent/backends/provider_ids.ts
|
|
82
|
-
function normalizeProviderId(provider) {
|
|
83
|
-
const normalized = provider.trim().toLowerCase();
|
|
84
|
-
if (CODEX_APP_SERVER_ALIASES.has(normalized)) {
|
|
85
|
-
return CODEX_APP_SERVER_PROVIDER;
|
|
86
|
-
}
|
|
87
|
-
if (CODEX_LEGACY_ALIASES.has(normalized)) {
|
|
88
|
-
return CODEX_LEGACY_PROVIDER;
|
|
89
|
-
}
|
|
90
|
-
return normalized;
|
|
91
|
-
}
|
|
92
|
-
function isCodexAppServerProvider(provider) {
|
|
93
|
-
return normalizeProviderId(provider) === CODEX_APP_SERVER_PROVIDER;
|
|
94
|
-
}
|
|
95
|
-
function isCodexLegacyProvider(provider) {
|
|
96
|
-
return normalizeProviderId(provider) === CODEX_LEGACY_PROVIDER;
|
|
97
|
-
}
|
|
98
|
-
var CODEX_APP_SERVER_PROVIDER, CODEX_LEGACY_PROVIDER, CODEX_LEGACY_ALIAS, CODEX_APP_SERVER_SENTINEL, CODEX_APP_SERVER_ALIASES, CODEX_LEGACY_ALIASES;
|
|
99
|
-
var init_provider_ids = __esm({
|
|
100
|
-
"src/agent/backends/provider_ids.ts"() {
|
|
101
|
-
"use strict";
|
|
102
|
-
CODEX_APP_SERVER_PROVIDER = "codex_app_server";
|
|
103
|
-
CODEX_LEGACY_PROVIDER = "codex_legacy";
|
|
104
|
-
CODEX_LEGACY_ALIAS = "codex";
|
|
105
|
-
CODEX_APP_SERVER_SENTINEL = "codex-app-server";
|
|
106
|
-
CODEX_APP_SERVER_ALIASES = /* @__PURE__ */ new Set([
|
|
107
|
-
CODEX_APP_SERVER_PROVIDER,
|
|
108
|
-
"codex-official"
|
|
109
|
-
]);
|
|
110
|
-
CODEX_LEGACY_ALIASES = /* @__PURE__ */ new Set([
|
|
111
|
-
CODEX_LEGACY_PROVIDER,
|
|
112
|
-
CODEX_LEGACY_ALIAS,
|
|
113
|
-
"codex-chatgpt-legacy"
|
|
114
|
-
]);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// src/utils/deepseek.ts
|
|
119
|
-
function isModalDeepSeekFlashModel(model) {
|
|
120
|
-
return model?.toLowerCase().replace(/^modal\//, "") === MODAL_DEEPSEEK_FLASH_MODEL;
|
|
121
|
-
}
|
|
122
|
-
function isDeepSeekFlashModel(model) {
|
|
123
|
-
if (isModalDeepSeekFlashModel(model)) return true;
|
|
124
|
-
return model !== void 0 && [
|
|
125
|
-
DEEPSEEK_FLASH_MODEL,
|
|
126
|
-
"deepseek-v4-flash",
|
|
127
|
-
"deepseek-v4-flash-vision-exp"
|
|
128
|
-
].includes(model.toLowerCase().replace(/^deepseek\//, ""));
|
|
129
|
-
}
|
|
130
|
-
function deepseekRequestParams(request) {
|
|
131
|
-
if (!isDeepSeekFlashModel(request.model)) return {};
|
|
132
|
-
if (isModalDeepSeekFlashModel(request.model)) {
|
|
133
|
-
const effort2 = request.codexEffort;
|
|
134
|
-
return effort2 && MODAL_DEEPSEEK_FLASH_EFFORTS.includes(effort2) ? { reasoning_effort: effort2 } : {};
|
|
135
|
-
}
|
|
136
|
-
if (request.codexEffort === "none") return { thinking: { type: "disabled" } };
|
|
137
|
-
const effort = request.codexEffort;
|
|
138
|
-
const reasoning = effort === "minimal" || effort === "low" ? "low" : effort === "max" || effort === "ultra" ? "max" : "high";
|
|
139
|
-
return { thinking: { type: "enabled" }, reasoning_effort: reasoning };
|
|
140
|
-
}
|
|
141
|
-
var DEEPSEEK_FLASH_MODEL, MODAL_DEEPSEEK_FLASH_MODEL, MODAL_DEEPSEEK_FLASH_CONTEXT, MODAL_DEEPSEEK_FLASH_MAX_OUTPUT, MODAL_DEEPSEEK_FLASH_EFFORTS, DEEPSEEK_FLASH_CONTEXT, DEEPSEEK_FLASH_MAX_OUTPUT, DEEPSEEK_FLASH_EFFORTS;
|
|
142
|
-
var init_deepseek = __esm({
|
|
143
|
-
"src/utils/deepseek.ts"() {
|
|
144
|
-
"use strict";
|
|
145
|
-
DEEPSEEK_FLASH_MODEL = "deepseek-flash";
|
|
146
|
-
MODAL_DEEPSEEK_FLASH_MODEL = "deepseek-v4.1-flash";
|
|
147
|
-
MODAL_DEEPSEEK_FLASH_CONTEXT = 1048576;
|
|
148
|
-
MODAL_DEEPSEEK_FLASH_MAX_OUTPUT = 1048576;
|
|
149
|
-
MODAL_DEEPSEEK_FLASH_EFFORTS = ["none", "low", "high", "xhigh", "max"];
|
|
150
|
-
DEEPSEEK_FLASH_CONTEXT = 1e6;
|
|
151
|
-
DEEPSEEK_FLASH_MAX_OUTPUT = 384e3;
|
|
152
|
-
DEEPSEEK_FLASH_EFFORTS = ["none", "low", "high", "max"];
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// src/utils/models.ts
|
|
157
|
-
function getKimiModelInfo(model) {
|
|
158
|
-
if (!model) return void 0;
|
|
159
|
-
const id = KIMI_ALIAS_TO_ID.get(model.toLowerCase());
|
|
160
|
-
return id ? KIMI_MODEL_INFO[id] : void 0;
|
|
161
|
-
}
|
|
162
|
-
function getOfficialCodexModelInfo(model) {
|
|
163
|
-
if (!model) return void 0;
|
|
164
|
-
const normalized = model.toLowerCase() === "gpt-5.6" ? "gpt-5.6-sol" : model.toLowerCase();
|
|
165
|
-
if (!OFFICIAL_CODEX_MODEL_IDS.includes(normalized)) return void 0;
|
|
166
|
-
return OFFICIAL_CODEX_MODEL_INFO[normalized];
|
|
167
|
-
}
|
|
168
|
-
function getSupportedClaudeReasoningEfforts(model) {
|
|
169
|
-
if (!model) return void 0;
|
|
170
|
-
const id = model.toLowerCase();
|
|
171
|
-
if (!id.startsWith("claude")) return void 0;
|
|
172
|
-
if (id.includes("haiku")) return [];
|
|
173
|
-
if (id.includes("opus") || id.includes("sonnet")) return CLAUDE_REASONING_EFFORTS;
|
|
174
|
-
return void 0;
|
|
175
|
-
}
|
|
176
|
-
function getSupportedCodexReasoningEfforts(model, provider) {
|
|
177
|
-
if (isModalDeepSeekFlashModel(model)) return MODAL_DEEPSEEK_FLASH_EFFORTS;
|
|
178
|
-
if (isDeepSeekFlashModel(model)) return DEEPSEEK_FLASH_EFFORTS;
|
|
179
|
-
const kimiInfo = getKimiModelInfo(model);
|
|
180
|
-
if (kimiInfo) return kimiInfo.supportedReasoningEfforts ?? [];
|
|
181
|
-
const appServerEfforts = getOfficialCodexModelInfo(model)?.supportedReasoningEfforts;
|
|
182
|
-
if (!appServerEfforts) return getSupportedClaudeReasoningEfforts(model);
|
|
183
|
-
if ((provider === "openai" || provider === "openai_compatible") && (model === "gpt-6-sol" || model === "gpt-6-luna")) {
|
|
184
|
-
return GPT_6_API_EFFORTS;
|
|
185
|
-
}
|
|
186
|
-
if (provider && isCodexLegacyProvider(provider)) return CODEX_LEGACY_EFFORTS;
|
|
187
|
-
if (provider === void 0) {
|
|
188
|
-
return [.../* @__PURE__ */ new Set([...appServerEfforts, ...CODEX_LEGACY_EFFORTS])];
|
|
189
|
-
}
|
|
190
|
-
return appServerEfforts;
|
|
191
|
-
}
|
|
192
|
-
function isCodexReasoningEffortSupported(provider, model, effort) {
|
|
193
|
-
const supported = getSupportedCodexReasoningEfforts(model, provider);
|
|
194
|
-
return supported === void 0 || supported.includes(effort);
|
|
195
|
-
}
|
|
196
|
-
var OFFICIAL_CODEX_MODEL_IDS, STANDARD_CODEX_EFFORTS, GPT_5_6_EFFORTS, GPT_5_6_ULTRA_EFFORTS, GPT_6_API_EFFORTS, CODEX_LEGACY_EFFORTS, OFFICIAL_CODEX_MODEL_INFO, KIMI_REASONING_EFFORTS, KIMI_MODEL_INFO, KIMI_ALIAS_TO_ID, CLAUDE_REASONING_EFFORTS;
|
|
197
|
-
var init_models = __esm({
|
|
198
|
-
"src/utils/models.ts"() {
|
|
199
|
-
"use strict";
|
|
200
|
-
init_provider_ids();
|
|
201
|
-
init_deepseek();
|
|
202
|
-
OFFICIAL_CODEX_MODEL_IDS = [
|
|
203
|
-
"gpt-6-sol",
|
|
204
|
-
"gpt-6-luna",
|
|
205
|
-
"gpt-5.6-sol",
|
|
206
|
-
"gpt-5.6-terra",
|
|
207
|
-
"gpt-5.6-luna",
|
|
208
|
-
"gpt-5.5",
|
|
209
|
-
"gpt-5.4",
|
|
210
|
-
"gpt-5.4-mini",
|
|
211
|
-
"gpt-5.3-codex",
|
|
212
|
-
"gpt-5.2"
|
|
213
|
-
];
|
|
214
|
-
STANDARD_CODEX_EFFORTS = ["low", "medium", "high", "xhigh"];
|
|
215
|
-
GPT_5_6_EFFORTS = [...STANDARD_CODEX_EFFORTS, "max"];
|
|
216
|
-
GPT_5_6_ULTRA_EFFORTS = [...GPT_5_6_EFFORTS, "ultra"];
|
|
217
|
-
GPT_6_API_EFFORTS = ["none", "low", "medium", "high", "xhigh", "max"];
|
|
218
|
-
CODEX_LEGACY_EFFORTS = ["none", "minimal", ...STANDARD_CODEX_EFFORTS];
|
|
219
|
-
OFFICIAL_CODEX_MODEL_INFO = {
|
|
220
|
-
"gpt-6-sol": {
|
|
221
|
-
displayName: "GPT-6 Sol",
|
|
222
|
-
description: "Frontier agentic coding model.",
|
|
223
|
-
defaultReasoningEffort: "medium",
|
|
224
|
-
supportedReasoningEfforts: GPT_5_6_ULTRA_EFFORTS
|
|
225
|
-
},
|
|
226
|
-
"gpt-6-luna": {
|
|
227
|
-
displayName: "GPT-6 Luna",
|
|
228
|
-
description: "Fast and affordable model for everyday work.",
|
|
229
|
-
defaultReasoningEffort: "medium",
|
|
230
|
-
supportedReasoningEfforts: GPT_5_6_EFFORTS
|
|
231
|
-
},
|
|
232
|
-
"gpt-5.6-sol": {
|
|
233
|
-
displayName: "GPT-5.6 Sol",
|
|
234
|
-
description: "Latest frontier agentic coding model.",
|
|
235
|
-
defaultReasoningEffort: "low",
|
|
236
|
-
supportedReasoningEfforts: GPT_5_6_ULTRA_EFFORTS
|
|
237
|
-
},
|
|
238
|
-
"gpt-5.6-terra": {
|
|
239
|
-
displayName: "GPT-5.6 Terra",
|
|
240
|
-
description: "Balanced agentic coding model for everyday work.",
|
|
241
|
-
defaultReasoningEffort: "medium",
|
|
242
|
-
supportedReasoningEfforts: GPT_5_6_ULTRA_EFFORTS
|
|
243
|
-
},
|
|
244
|
-
"gpt-5.6-luna": {
|
|
245
|
-
displayName: "GPT-5.6 Luna",
|
|
246
|
-
description: "Fast and affordable agentic coding model.",
|
|
247
|
-
defaultReasoningEffort: "medium",
|
|
248
|
-
supportedReasoningEfforts: GPT_5_6_EFFORTS
|
|
249
|
-
},
|
|
250
|
-
"gpt-5.5": {
|
|
251
|
-
displayName: "GPT-5.5",
|
|
252
|
-
description: "Frontier model for complex coding, research, and real-world work.",
|
|
253
|
-
defaultReasoningEffort: "medium",
|
|
254
|
-
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
255
|
-
},
|
|
256
|
-
"gpt-5.4": {
|
|
257
|
-
displayName: "GPT-5.4",
|
|
258
|
-
description: "Strong model for everyday coding.",
|
|
259
|
-
defaultReasoningEffort: "medium",
|
|
260
|
-
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
261
|
-
},
|
|
262
|
-
"gpt-5.4-mini": {
|
|
263
|
-
displayName: "GPT-5.4 Mini",
|
|
264
|
-
description: "Small, fast, and cost-efficient model for simpler coding tasks.",
|
|
265
|
-
defaultReasoningEffort: "medium",
|
|
266
|
-
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
267
|
-
},
|
|
268
|
-
"gpt-5.3-codex": {
|
|
269
|
-
displayName: "GPT-5.3 Codex",
|
|
270
|
-
description: "Codex-tuned agentic coding model.",
|
|
271
|
-
defaultReasoningEffort: "medium",
|
|
272
|
-
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
273
|
-
},
|
|
274
|
-
"gpt-5.2": {
|
|
275
|
-
displayName: "GPT-5.2",
|
|
276
|
-
description: "Earlier general-purpose Codex model.",
|
|
277
|
-
defaultReasoningEffort: "medium",
|
|
278
|
-
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
KIMI_REASONING_EFFORTS = ["low", "high", "max"];
|
|
282
|
-
KIMI_MODEL_INFO = {
|
|
283
|
-
"kimi-k3": {
|
|
284
|
-
displayName: "Kimi K3",
|
|
285
|
-
description: "Moonshot flagship \u2014 1M context, reasoning on by default, vision and tools.",
|
|
286
|
-
supportedReasoningEfforts: KIMI_REASONING_EFFORTS,
|
|
287
|
-
defaultReasoningEffort: "max",
|
|
288
|
-
aliases: ["k3", "kimi k3", "moonshot-kimi-k3", "moonshotai/kimi-k3"]
|
|
289
|
-
},
|
|
290
|
-
"kimi-k2.6": {
|
|
291
|
-
displayName: "Kimi K2.6",
|
|
292
|
-
description: "Smaller, cheaper Kimi \u2014 256K context, multimodal.",
|
|
293
|
-
// No supportedReasoningEfforts: Moonshot lists `reasoning_effort` as "Not
|
|
294
|
-
// supported" for K2.6, which instead takes a `thinking: {type}` object. ZTC
|
|
295
|
-
// does not send that object yet, so the picker must not offer a depth control
|
|
296
|
-
// here — the effort ladder and the thinking switch are different contracts.
|
|
297
|
-
aliases: ["k2.6", "kimi k2.6", "moonshotai/kimi-k2.6"]
|
|
298
|
-
},
|
|
299
|
-
"kimi-for-coding": {
|
|
300
|
-
displayName: "Kimi K2.7 Coding",
|
|
301
|
-
description: "Kimi Code subscription coding model \u2014 256K context, always-thinking, vision and tools.",
|
|
302
|
-
// No supportedReasoningEfforts: the subscription coding models are
|
|
303
|
-
// always-thinking with no documented effort ladder, so /effort stays
|
|
304
|
-
// rejected rather than forwarding a value the API silently ignores.
|
|
305
|
-
aliases: ["k2.7", "kimi k2.7", "kimi-k2.7-coding"]
|
|
306
|
-
},
|
|
307
|
-
"kimi-for-coding-highspeed": {
|
|
308
|
-
displayName: "Kimi K2.7 Coding Highspeed",
|
|
309
|
-
description: "High-speed variant of the Kimi Code subscription coding model \u2014 256K context.",
|
|
310
|
-
aliases: ["k2.7-highspeed", "kimi-for-coding-fast"]
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
KIMI_ALIAS_TO_ID = /* @__PURE__ */ new Map();
|
|
314
|
-
for (const id of Object.keys(KIMI_MODEL_INFO)) {
|
|
315
|
-
KIMI_ALIAS_TO_ID.set(id, id);
|
|
316
|
-
for (const alias of KIMI_MODEL_INFO[id].aliases) {
|
|
317
|
-
KIMI_ALIAS_TO_ID.set(alias.toLowerCase(), id);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
CLAUDE_REASONING_EFFORTS = [
|
|
321
|
-
"low",
|
|
322
|
-
"medium",
|
|
323
|
-
"high",
|
|
324
|
-
"xhigh",
|
|
325
|
-
"max"
|
|
326
|
-
];
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
|
|
330
275
|
// src/agent/backends/anthropic.ts
|
|
331
276
|
function anthropicInputTokens(usage) {
|
|
332
277
|
if (!usage) return 0;
|
|
@@ -336,8 +281,8 @@ var EXTENDED_CACHE_BETA, AnthropicBackend, AnthropicApiError;
|
|
|
336
281
|
var init_anthropic = __esm({
|
|
337
282
|
"src/agent/backends/anthropic.ts"() {
|
|
338
283
|
"use strict";
|
|
284
|
+
init_model_contracts();
|
|
339
285
|
init_sse();
|
|
340
|
-
init_models();
|
|
341
286
|
EXTENDED_CACHE_BETA = "extended-cache-ttl-2025-04-11";
|
|
342
287
|
AnthropicBackend = class {
|
|
343
288
|
apiKey;
|
|
@@ -416,8 +361,8 @@ var init_anthropic = __esm({
|
|
|
416
361
|
}
|
|
417
362
|
}
|
|
418
363
|
const effort = request.codexEffort;
|
|
419
|
-
const supportedEfforts =
|
|
420
|
-
const modelAllowsEffort =
|
|
364
|
+
const supportedEfforts = modelContract("anthropic", request.model)?.reasoningEfforts ?? [];
|
|
365
|
+
const modelAllowsEffort = effort !== void 0 && supportedEfforts.includes(effort);
|
|
421
366
|
const outputConfig = effort && ["low", "medium", "high", "xhigh", "max"].includes(effort) && modelAllowsEffort ? { output_config: { effort } } : {};
|
|
422
367
|
return {
|
|
423
368
|
model: request.model,
|
|
@@ -854,52 +799,495 @@ function buildOpenAIMessages(request) {
|
|
|
854
799
|
if (msg.reasoning) {
|
|
855
800
|
assistantMsg.reasoning_content = msg.reasoning;
|
|
856
801
|
}
|
|
857
|
-
out.push(assistantMsg);
|
|
858
|
-
continue;
|
|
859
|
-
}
|
|
860
|
-
if (toolResults.length > 0) {
|
|
861
|
-
for (const tr of toolResults) {
|
|
862
|
-
const resultText = typeof tr.content === "string" ? tr.content : tr.content.map((b) => b.type === "text" ? b.text || "" : "[image]").join("\n");
|
|
863
|
-
out.push({
|
|
864
|
-
role: "tool",
|
|
865
|
-
tool_call_id: tr.tool_use_id,
|
|
866
|
-
content: tr.is_error && !/^error\b/i.test(resultText) ? `Error: ${resultText}` : resultText
|
|
867
|
-
});
|
|
802
|
+
out.push(assistantMsg);
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
if (toolResults.length > 0) {
|
|
806
|
+
for (const tr of toolResults) {
|
|
807
|
+
const resultText = typeof tr.content === "string" ? tr.content : tr.content.map((b) => b.type === "text" ? b.text || "" : "[image]").join("\n");
|
|
808
|
+
out.push({
|
|
809
|
+
role: "tool",
|
|
810
|
+
tool_call_id: tr.tool_use_id,
|
|
811
|
+
content: tr.is_error && !/^error\b/i.test(resultText) ? `Error: ${resultText}` : resultText
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
if (textParts.length > 0 || mediaParts.length > 0) {
|
|
815
|
+
if (mediaParts.length > 0) {
|
|
816
|
+
const parts = textParts.map((t) => ({ type: "text", text: t }));
|
|
817
|
+
parts.push(...mediaParts);
|
|
818
|
+
out.push({ role: "user", content: parts });
|
|
819
|
+
} else {
|
|
820
|
+
out.push({ role: "user", content: textParts.join("\n") });
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
if (mediaParts.length > 0) {
|
|
826
|
+
const parts = textParts.map((t) => ({ type: "text", text: t }));
|
|
827
|
+
parts.push(...mediaParts);
|
|
828
|
+
out.push(withReasoning({ role: msg.role, content: parts }, msg));
|
|
829
|
+
} else {
|
|
830
|
+
out.push(withReasoning({ role: msg.role, content: textParts.join("\n") }, msg));
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return out;
|
|
834
|
+
}
|
|
835
|
+
function buildOpenAIToolDefs(tools) {
|
|
836
|
+
return tools.map((t) => ({
|
|
837
|
+
type: "function",
|
|
838
|
+
function: {
|
|
839
|
+
name: t.name,
|
|
840
|
+
description: t.description,
|
|
841
|
+
parameters: t.parameters
|
|
842
|
+
}
|
|
843
|
+
}));
|
|
844
|
+
}
|
|
845
|
+
var init_openai_format = __esm({
|
|
846
|
+
"src/agent/backends/openai_format.ts"() {
|
|
847
|
+
"use strict";
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
// src/config/profiles.ts
|
|
852
|
+
import { homedir } from "node:os";
|
|
853
|
+
import { join } from "node:path";
|
|
854
|
+
import { existsSync } from "node:fs";
|
|
855
|
+
import { readdir } from "node:fs/promises";
|
|
856
|
+
function builtinProfileEmulation(name) {
|
|
857
|
+
const builtin = BUILTIN_CONFIG_PROFILES.find((profile) => profile === name);
|
|
858
|
+
if (!builtin) return void 0;
|
|
859
|
+
const root = process.env.ZTC_CONFIG_DIR || join(homedir(), ".ztc");
|
|
860
|
+
return existsSync(join(root, "profiles", name)) ? void 0 : builtin;
|
|
861
|
+
}
|
|
862
|
+
function validateProfileName(name) {
|
|
863
|
+
if (name !== "default" && !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name)) {
|
|
864
|
+
throw new Error("Profile name must be 1\u201364 characters: letters, numbers, dots, underscores, or hyphens; it must start with a letter or number.");
|
|
865
|
+
}
|
|
866
|
+
if (name === "." || name === "..") {
|
|
867
|
+
throw new Error("Profile name cannot be . or ..");
|
|
868
|
+
}
|
|
869
|
+
return name;
|
|
870
|
+
}
|
|
871
|
+
function activeProfile() {
|
|
872
|
+
return validateProfileName(process.env.ZTC_PROFILE || "default");
|
|
873
|
+
}
|
|
874
|
+
function profileConfigDir(profile = activeProfile()) {
|
|
875
|
+
const root = process.env.ZTC_CONFIG_DIR || join(homedir(), ".ztc");
|
|
876
|
+
const name = validateProfileName(profile);
|
|
877
|
+
if (name === "default") return root;
|
|
878
|
+
const namedDir = join(root, "profiles", name);
|
|
879
|
+
return builtinProfileEmulation(name) ? root : namedDir;
|
|
880
|
+
}
|
|
881
|
+
async function listConfigProfiles() {
|
|
882
|
+
const root = process.env.ZTC_CONFIG_DIR || join(homedir(), ".ztc");
|
|
883
|
+
let entries;
|
|
884
|
+
try {
|
|
885
|
+
entries = await readdir(join(root, "profiles"), { withFileTypes: true });
|
|
886
|
+
} catch (error) {
|
|
887
|
+
if (error.code === "ENOENT") {
|
|
888
|
+
return [...BUILTIN_CONFIG_PROFILES, "default", activeProfile()].filter((name, index, names) => names.indexOf(name) === index).sort(profileOrder);
|
|
889
|
+
}
|
|
890
|
+
throw error;
|
|
891
|
+
}
|
|
892
|
+
const named = entries.filter((entry) => entry.isDirectory() && entry.name !== "default").map((entry) => entry.name).filter((name) => {
|
|
893
|
+
try {
|
|
894
|
+
validateProfileName(name);
|
|
895
|
+
return true;
|
|
896
|
+
} catch {
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
const profiles = /* @__PURE__ */ new Set([activeProfile(), ...BUILTIN_CONFIG_PROFILES, ...named]);
|
|
901
|
+
profiles.delete("default");
|
|
902
|
+
return ["default", ...profiles].sort(profileOrder);
|
|
903
|
+
}
|
|
904
|
+
function profileOrder(left, right) {
|
|
905
|
+
const rank = (name) => {
|
|
906
|
+
if (name === "default") return 0;
|
|
907
|
+
const index = BUILTIN_CONFIG_PROFILES.findIndex((profile) => profile === name);
|
|
908
|
+
return index < 0 ? Number.MAX_SAFE_INTEGER : index + 1;
|
|
909
|
+
};
|
|
910
|
+
return rank(left) - rank(right) || left.localeCompare(right);
|
|
911
|
+
}
|
|
912
|
+
var BUILTIN_CONFIG_PROFILES;
|
|
913
|
+
var init_profiles = __esm({
|
|
914
|
+
"src/config/profiles.ts"() {
|
|
915
|
+
"use strict";
|
|
916
|
+
BUILTIN_CONFIG_PROFILES = ["ztc", "ztc-coder", "ztc-datascience", "scientist"];
|
|
917
|
+
}
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
// src/utils/router_catalog.ts
|
|
921
|
+
import { createHash, randomUUID as randomUUID2 } from "node:crypto";
|
|
922
|
+
import { statSync, readFileSync } from "node:fs";
|
|
923
|
+
import { dirname, join as join2 } from "node:path";
|
|
924
|
+
function record2(value) {
|
|
925
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
926
|
+
}
|
|
927
|
+
function identifier(value) {
|
|
928
|
+
return typeof value === "string" && value.length > 0 && value.length <= 512 && !/[\x00-\x1f\x7f]/.test(value);
|
|
929
|
+
}
|
|
930
|
+
function identifiers(value, max) {
|
|
931
|
+
return Array.isArray(value) && value.length <= max && value.every(identifier);
|
|
932
|
+
}
|
|
933
|
+
function descriptor(value, legacy) {
|
|
934
|
+
if (!record2(value)) return void 0;
|
|
935
|
+
const id = value.id ?? (legacy ? value.name : void 0);
|
|
936
|
+
if (!identifier(id) || !identifier(value.owned_by)) return void 0;
|
|
937
|
+
const result = { id, owned_by: value.owned_by };
|
|
938
|
+
if (value.object !== void 0 && value.object !== "model") return void 0;
|
|
939
|
+
if (value.object === "model") result.object = "model";
|
|
940
|
+
for (const key of ["display_name", "provider_display_name"]) {
|
|
941
|
+
if (value[key] !== void 0) {
|
|
942
|
+
if (!identifier(value[key])) return void 0;
|
|
943
|
+
result[key] = value[key];
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
for (const key of ["is_default", "available"]) {
|
|
947
|
+
if (value[key] !== void 0) {
|
|
948
|
+
if (typeof value[key] !== "boolean") return void 0;
|
|
949
|
+
result[key] = value[key];
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
if (value.aliases !== void 0) {
|
|
953
|
+
if (!identifiers(value.aliases, 32)) return void 0;
|
|
954
|
+
result.aliases = value.aliases;
|
|
955
|
+
}
|
|
956
|
+
if (value.capabilities !== void 0) {
|
|
957
|
+
const caps = value.capabilities;
|
|
958
|
+
if (!record2(caps) || typeof caps.chat !== "boolean") return void 0;
|
|
959
|
+
const capabilities = { chat: caps.chat };
|
|
960
|
+
for (const key of ["tools", "images"]) {
|
|
961
|
+
if (caps[key] !== void 0) {
|
|
962
|
+
if (typeof caps[key] !== "boolean") return void 0;
|
|
963
|
+
capabilities[key] = caps[key];
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
for (const key of ["context_window", "max_output_tokens"]) {
|
|
967
|
+
if (caps[key] !== void 0) {
|
|
968
|
+
if (typeof caps[key] !== "number" || !Number.isSafeInteger(caps[key]) || caps[key] <= 0) return void 0;
|
|
969
|
+
capabilities[key] = caps[key];
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
if (caps.reasoning !== void 0) {
|
|
973
|
+
const reasoning = caps.reasoning;
|
|
974
|
+
if (!record2(reasoning) || !identifiers(reasoning.choices, 32) || reasoning.default !== void 0 && !identifier(reasoning.default)) return void 0;
|
|
975
|
+
capabilities.reasoning = { choices: reasoning.choices, ...reasoning.default === void 0 ? {} : { default: reasoning.default } };
|
|
976
|
+
}
|
|
977
|
+
result.capabilities = capabilities;
|
|
978
|
+
}
|
|
979
|
+
return result;
|
|
980
|
+
}
|
|
981
|
+
function resolveRouterModel(catalog, provider, model) {
|
|
982
|
+
const owner = provider === "moonshot" ? "kimi" : provider;
|
|
983
|
+
const rows = catalog.models.filter((row) => row.owned_by === owner);
|
|
984
|
+
const exact = rows.find((row) => row.id === model);
|
|
985
|
+
if (exact) return exact;
|
|
986
|
+
const matches = rows.filter((row) => row.id === `${owner}/${model}` || row.aliases?.includes(model));
|
|
987
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
988
|
+
}
|
|
989
|
+
function routerCatalogScope(connection) {
|
|
990
|
+
const key = createHash("sha256").update(JSON.stringify([connection.origin.replace(/\/+$/, ""), connection.token, connection.workspaceId ?? ""])).digest("hex");
|
|
991
|
+
return join2(profileConfigDir(), `router-models-${key}.json`);
|
|
992
|
+
}
|
|
993
|
+
function parseCatalog(value) {
|
|
994
|
+
if (!record2(value)) throw new Error("Invalid Router catalog");
|
|
995
|
+
if (value.model_contract_version !== void 0 && value.model_contract_version !== 1) throw new Error("Unsupported Router model contract");
|
|
996
|
+
const data = value.data ?? value.models ?? value.items ?? [];
|
|
997
|
+
if (!Array.isArray(data) || data.length > 4096) throw new Error("Invalid Router catalog");
|
|
998
|
+
const version = value.model_contract_version === 1 ? 1 : 0;
|
|
999
|
+
return { version, models: data.flatMap((value2) => {
|
|
1000
|
+
const row = descriptor(value2, version === 0);
|
|
1001
|
+
return row ? [row] : [];
|
|
1002
|
+
}) };
|
|
1003
|
+
}
|
|
1004
|
+
function readRouterCatalog(connection) {
|
|
1005
|
+
const file = routerCatalogScope(connection);
|
|
1006
|
+
try {
|
|
1007
|
+
const stat3 = statSync(file, { bigint: true });
|
|
1008
|
+
const stamp = `${stat3.mtimeNs}:${stat3.size}:${stat3.ino}`;
|
|
1009
|
+
const previous = memo.get(file);
|
|
1010
|
+
if (previous?.stamp === stamp) return previous.catalog;
|
|
1011
|
+
const saved = JSON.parse(readFileSync(file, "utf8"));
|
|
1012
|
+
const parsed = parseCatalog(saved);
|
|
1013
|
+
const catalog = { ...parsed, cached: true, fetchedAt: Number(saved.fetchedAt) || 0 };
|
|
1014
|
+
if (memo.size >= 32) memo.delete(memo.keys().next().value);
|
|
1015
|
+
memo.set(file, { stamp, catalog });
|
|
1016
|
+
return catalog;
|
|
1017
|
+
} catch {
|
|
1018
|
+
memo.delete(file);
|
|
1019
|
+
return void 0;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
var memo;
|
|
1023
|
+
var init_router_catalog = __esm({
|
|
1024
|
+
"src/utils/router_catalog.ts"() {
|
|
1025
|
+
"use strict";
|
|
1026
|
+
init_profiles();
|
|
1027
|
+
memo = /* @__PURE__ */ new Map();
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
// src/agent/backends/provider_ids.ts
|
|
1032
|
+
function normalizeProviderId(provider) {
|
|
1033
|
+
const normalized = provider.trim().toLowerCase();
|
|
1034
|
+
if (CODEX_APP_SERVER_ALIASES.has(normalized)) {
|
|
1035
|
+
return CODEX_APP_SERVER_PROVIDER;
|
|
1036
|
+
}
|
|
1037
|
+
if (CODEX_LEGACY_ALIASES.has(normalized)) {
|
|
1038
|
+
return CODEX_LEGACY_PROVIDER;
|
|
1039
|
+
}
|
|
1040
|
+
return normalized;
|
|
1041
|
+
}
|
|
1042
|
+
function isCodexAppServerProvider(provider) {
|
|
1043
|
+
return normalizeProviderId(provider) === CODEX_APP_SERVER_PROVIDER;
|
|
1044
|
+
}
|
|
1045
|
+
function isCodexLegacyProvider(provider) {
|
|
1046
|
+
return normalizeProviderId(provider) === CODEX_LEGACY_PROVIDER;
|
|
1047
|
+
}
|
|
1048
|
+
function isLocalSubscriptionProvider(provider) {
|
|
1049
|
+
return ["codex_app_server", "codex_legacy", "claude_code", "claude-code", "claude_code_direct", "claude-code-direct", "kimi_code", "kimi-code"].includes(normalizeProviderId(provider));
|
|
1050
|
+
}
|
|
1051
|
+
var CODEX_APP_SERVER_PROVIDER, CODEX_LEGACY_PROVIDER, CODEX_LEGACY_ALIAS, CODEX_APP_SERVER_SENTINEL, CODEX_APP_SERVER_ALIASES, CODEX_LEGACY_ALIASES;
|
|
1052
|
+
var init_provider_ids = __esm({
|
|
1053
|
+
"src/agent/backends/provider_ids.ts"() {
|
|
1054
|
+
"use strict";
|
|
1055
|
+
CODEX_APP_SERVER_PROVIDER = "codex_app_server";
|
|
1056
|
+
CODEX_LEGACY_PROVIDER = "codex_legacy";
|
|
1057
|
+
CODEX_LEGACY_ALIAS = "codex";
|
|
1058
|
+
CODEX_APP_SERVER_SENTINEL = "codex-app-server";
|
|
1059
|
+
CODEX_APP_SERVER_ALIASES = /* @__PURE__ */ new Set([
|
|
1060
|
+
CODEX_APP_SERVER_PROVIDER,
|
|
1061
|
+
"codex-official"
|
|
1062
|
+
]);
|
|
1063
|
+
CODEX_LEGACY_ALIASES = /* @__PURE__ */ new Set([
|
|
1064
|
+
CODEX_LEGACY_PROVIDER,
|
|
1065
|
+
CODEX_LEGACY_ALIAS,
|
|
1066
|
+
"codex-chatgpt-legacy"
|
|
1067
|
+
]);
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
// src/utils/deepseek.ts
|
|
1072
|
+
function isModalDeepSeekFlashModel(model) {
|
|
1073
|
+
return model?.toLowerCase().replace(/^modal\//, "") === MODAL_DEEPSEEK_FLASH_MODEL;
|
|
1074
|
+
}
|
|
1075
|
+
function isDeepSeekFlashModel(model) {
|
|
1076
|
+
if (isModalDeepSeekFlashModel(model)) return true;
|
|
1077
|
+
return model !== void 0 && [
|
|
1078
|
+
DEEPSEEK_FLASH_MODEL,
|
|
1079
|
+
"deepseek-v4-flash",
|
|
1080
|
+
"deepseek-v4-flash-vision-exp"
|
|
1081
|
+
].includes(model.toLowerCase().replace(/^deepseek\//, "")) || model !== void 0 && ["deepseek-v4p1-flash", "deepseek-v4-flash-0731"].includes(normalizeContractModel("fireworks", model));
|
|
1082
|
+
}
|
|
1083
|
+
function deepseekRequestParams(request) {
|
|
1084
|
+
if (!isDeepSeekFlashModel(request.model)) {
|
|
1085
|
+
return reasoningRequestParams("deepseek", request.model, request.codexEffort);
|
|
1086
|
+
}
|
|
1087
|
+
if (normalizeContractModel("fireworks", request.model) === "deepseek-v4p1-flash" || request.model.toLowerCase().startsWith("fireworks/")) {
|
|
1088
|
+
return reasoningRequestParams("fireworks", request.model, request.codexEffort);
|
|
1089
|
+
}
|
|
1090
|
+
if (isModalDeepSeekFlashModel(request.model)) {
|
|
1091
|
+
const effort2 = request.codexEffort;
|
|
1092
|
+
return effort2 && MODAL_DEEPSEEK_FLASH_EFFORTS.includes(effort2) ? { reasoning_effort: effort2 } : {};
|
|
1093
|
+
}
|
|
1094
|
+
if (request.codexEffort === "none") return { thinking: { type: "disabled" } };
|
|
1095
|
+
const effort = request.codexEffort;
|
|
1096
|
+
const reasoning = effort === "minimal" || effort === "low" ? "low" : effort === "max" || effort === "ultra" ? "max" : "high";
|
|
1097
|
+
return { thinking: { type: "enabled" }, reasoning_effort: reasoning };
|
|
1098
|
+
}
|
|
1099
|
+
var DEEPSEEK_FLASH_MODEL, MODAL_DEEPSEEK_FLASH_MODEL, MODAL_DEEPSEEK_FLASH_CONTEXT, MODAL_DEEPSEEK_FLASH_MAX_OUTPUT, MODAL_DEEPSEEK_FLASH_EFFORTS, DEEPSEEK_FLASH_CONTEXT, DEEPSEEK_FLASH_MAX_OUTPUT, DEEPSEEK_FLASH_EFFORTS;
|
|
1100
|
+
var init_deepseek = __esm({
|
|
1101
|
+
"src/utils/deepseek.ts"() {
|
|
1102
|
+
"use strict";
|
|
1103
|
+
init_model_contracts();
|
|
1104
|
+
DEEPSEEK_FLASH_MODEL = "deepseek-flash";
|
|
1105
|
+
MODAL_DEEPSEEK_FLASH_MODEL = "deepseek-v4.1-flash";
|
|
1106
|
+
MODAL_DEEPSEEK_FLASH_CONTEXT = 1048576;
|
|
1107
|
+
MODAL_DEEPSEEK_FLASH_MAX_OUTPUT = 1048576;
|
|
1108
|
+
MODAL_DEEPSEEK_FLASH_EFFORTS = modelContract("modal", MODAL_DEEPSEEK_FLASH_MODEL).reasoningEfforts;
|
|
1109
|
+
DEEPSEEK_FLASH_CONTEXT = 1e6;
|
|
1110
|
+
DEEPSEEK_FLASH_MAX_OUTPUT = 384e3;
|
|
1111
|
+
DEEPSEEK_FLASH_EFFORTS = modelContract("deepseek", DEEPSEEK_FLASH_MODEL).reasoningEfforts;
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
// src/utils/models.ts
|
|
1116
|
+
function getKimiModelInfo(model) {
|
|
1117
|
+
if (!model) return void 0;
|
|
1118
|
+
const id = KIMI_ALIAS_TO_ID.get(model.toLowerCase());
|
|
1119
|
+
return id ? KIMI_MODEL_INFO[id] : void 0;
|
|
1120
|
+
}
|
|
1121
|
+
function getOfficialCodexModelInfo(model) {
|
|
1122
|
+
if (!model) return void 0;
|
|
1123
|
+
const normalized = model.toLowerCase() === "gpt-5.6" ? "gpt-5.6-sol" : model.toLowerCase();
|
|
1124
|
+
if (!OFFICIAL_CODEX_MODEL_IDS.includes(normalized)) return void 0;
|
|
1125
|
+
return OFFICIAL_CODEX_MODEL_INFO[normalized];
|
|
1126
|
+
}
|
|
1127
|
+
function getSupportedClaudeReasoningEfforts(model) {
|
|
1128
|
+
if (!model) return void 0;
|
|
1129
|
+
const id = model.toLowerCase();
|
|
1130
|
+
if (!id.startsWith("claude")) return void 0;
|
|
1131
|
+
if (id.includes("haiku")) return [];
|
|
1132
|
+
if (id.includes("opus") || id.includes("sonnet")) return CLAUDE_REASONING_EFFORTS;
|
|
1133
|
+
return void 0;
|
|
1134
|
+
}
|
|
1135
|
+
function getSupportedCodexReasoningEfforts(model, provider, surface = provider === "openai_compatible" ? "chat_tools" : "native_api") {
|
|
1136
|
+
if (provider && model && CONTRACT_PROVIDERS.includes(normalizeContractProvider(provider))) {
|
|
1137
|
+
return modelContract(provider, model, surface)?.reasoningEfforts ?? [];
|
|
1138
|
+
}
|
|
1139
|
+
if (isModalDeepSeekFlashModel(model)) return MODAL_DEEPSEEK_FLASH_EFFORTS;
|
|
1140
|
+
if (isDeepSeekFlashModel(model)) return DEEPSEEK_FLASH_EFFORTS;
|
|
1141
|
+
const kimiInfo = getKimiModelInfo(model);
|
|
1142
|
+
if (kimiInfo) return kimiInfo.supportedReasoningEfforts ?? [];
|
|
1143
|
+
const appServerEfforts = getOfficialCodexModelInfo(model)?.supportedReasoningEfforts;
|
|
1144
|
+
if (!appServerEfforts) return getSupportedClaudeReasoningEfforts(model);
|
|
1145
|
+
if ((provider === "openai" || provider === "openai_compatible") && (model === "gpt-6-sol" || model === "gpt-6-luna")) {
|
|
1146
|
+
return GPT_6_API_EFFORTS;
|
|
1147
|
+
}
|
|
1148
|
+
if (provider && isCodexLegacyProvider(provider)) return CODEX_LEGACY_EFFORTS;
|
|
1149
|
+
if (provider === void 0) {
|
|
1150
|
+
return [.../* @__PURE__ */ new Set([...appServerEfforts, ...CODEX_LEGACY_EFFORTS])];
|
|
1151
|
+
}
|
|
1152
|
+
return appServerEfforts;
|
|
1153
|
+
}
|
|
1154
|
+
function isCodexReasoningEffortSupported(provider, model, effort, surface) {
|
|
1155
|
+
const supported = getSupportedCodexReasoningEfforts(model, provider, surface);
|
|
1156
|
+
return supported === void 0 || supported.includes(effort);
|
|
1157
|
+
}
|
|
1158
|
+
var OFFICIAL_CODEX_MODEL_IDS, STANDARD_CODEX_EFFORTS, GPT_5_6_EFFORTS, GPT_5_6_ULTRA_EFFORTS, GPT_6_API_EFFORTS, CODEX_LEGACY_EFFORTS, OFFICIAL_CODEX_MODEL_INFO, KIMI_REASONING_EFFORTS, KIMI_MODEL_INFO, KIMI_ALIAS_TO_ID, CLAUDE_REASONING_EFFORTS;
|
|
1159
|
+
var init_models = __esm({
|
|
1160
|
+
"src/utils/models.ts"() {
|
|
1161
|
+
"use strict";
|
|
1162
|
+
init_model_contracts();
|
|
1163
|
+
init_router_catalog();
|
|
1164
|
+
init_provider_ids();
|
|
1165
|
+
init_deepseek();
|
|
1166
|
+
OFFICIAL_CODEX_MODEL_IDS = [
|
|
1167
|
+
"gpt-6-sol",
|
|
1168
|
+
"gpt-6-luna",
|
|
1169
|
+
"gpt-5.6-sol",
|
|
1170
|
+
"gpt-5.6-terra",
|
|
1171
|
+
"gpt-5.6-luna",
|
|
1172
|
+
"gpt-5.5",
|
|
1173
|
+
"gpt-5.4",
|
|
1174
|
+
"gpt-5.4-mini",
|
|
1175
|
+
"gpt-5.3-codex",
|
|
1176
|
+
"gpt-5.2"
|
|
1177
|
+
];
|
|
1178
|
+
STANDARD_CODEX_EFFORTS = ["low", "medium", "high", "xhigh"];
|
|
1179
|
+
GPT_5_6_EFFORTS = [...STANDARD_CODEX_EFFORTS, "max"];
|
|
1180
|
+
GPT_5_6_ULTRA_EFFORTS = [...GPT_5_6_EFFORTS, "ultra"];
|
|
1181
|
+
GPT_6_API_EFFORTS = ["none", "low", "medium", "high", "xhigh", "max"];
|
|
1182
|
+
CODEX_LEGACY_EFFORTS = ["none", "minimal", ...STANDARD_CODEX_EFFORTS];
|
|
1183
|
+
OFFICIAL_CODEX_MODEL_INFO = {
|
|
1184
|
+
"gpt-6-sol": {
|
|
1185
|
+
displayName: "GPT-6 Sol",
|
|
1186
|
+
description: "Frontier agentic coding model.",
|
|
1187
|
+
defaultReasoningEffort: "medium",
|
|
1188
|
+
supportedReasoningEfforts: GPT_5_6_ULTRA_EFFORTS
|
|
1189
|
+
},
|
|
1190
|
+
"gpt-6-luna": {
|
|
1191
|
+
displayName: "GPT-6 Luna",
|
|
1192
|
+
description: "Fast and affordable model for everyday work.",
|
|
1193
|
+
defaultReasoningEffort: "medium",
|
|
1194
|
+
supportedReasoningEfforts: GPT_5_6_EFFORTS
|
|
1195
|
+
},
|
|
1196
|
+
"gpt-5.6-sol": {
|
|
1197
|
+
displayName: "GPT-5.6 Sol",
|
|
1198
|
+
description: "Latest frontier agentic coding model.",
|
|
1199
|
+
defaultReasoningEffort: "low",
|
|
1200
|
+
supportedReasoningEfforts: GPT_5_6_ULTRA_EFFORTS
|
|
1201
|
+
},
|
|
1202
|
+
"gpt-5.6-terra": {
|
|
1203
|
+
displayName: "GPT-5.6 Terra",
|
|
1204
|
+
description: "Balanced agentic coding model for everyday work.",
|
|
1205
|
+
defaultReasoningEffort: "medium",
|
|
1206
|
+
supportedReasoningEfforts: GPT_5_6_ULTRA_EFFORTS
|
|
1207
|
+
},
|
|
1208
|
+
"gpt-5.6-luna": {
|
|
1209
|
+
displayName: "GPT-5.6 Luna",
|
|
1210
|
+
description: "Fast and affordable agentic coding model.",
|
|
1211
|
+
defaultReasoningEffort: "medium",
|
|
1212
|
+
supportedReasoningEfforts: GPT_5_6_EFFORTS
|
|
1213
|
+
},
|
|
1214
|
+
"gpt-5.5": {
|
|
1215
|
+
displayName: "GPT-5.5",
|
|
1216
|
+
description: "Frontier model for complex coding, research, and real-world work.",
|
|
1217
|
+
defaultReasoningEffort: "medium",
|
|
1218
|
+
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
1219
|
+
},
|
|
1220
|
+
"gpt-5.4": {
|
|
1221
|
+
displayName: "GPT-5.4",
|
|
1222
|
+
description: "Strong model for everyday coding.",
|
|
1223
|
+
defaultReasoningEffort: "medium",
|
|
1224
|
+
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
1225
|
+
},
|
|
1226
|
+
"gpt-5.4-mini": {
|
|
1227
|
+
displayName: "GPT-5.4 Mini",
|
|
1228
|
+
description: "Small, fast, and cost-efficient model for simpler coding tasks.",
|
|
1229
|
+
defaultReasoningEffort: "medium",
|
|
1230
|
+
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
1231
|
+
},
|
|
1232
|
+
"gpt-5.3-codex": {
|
|
1233
|
+
displayName: "GPT-5.3 Codex",
|
|
1234
|
+
description: "Codex-tuned agentic coding model.",
|
|
1235
|
+
defaultReasoningEffort: "medium",
|
|
1236
|
+
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
1237
|
+
},
|
|
1238
|
+
"gpt-5.2": {
|
|
1239
|
+
displayName: "GPT-5.2",
|
|
1240
|
+
description: "Earlier general-purpose Codex model.",
|
|
1241
|
+
defaultReasoningEffort: "medium",
|
|
1242
|
+
supportedReasoningEfforts: STANDARD_CODEX_EFFORTS
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
KIMI_REASONING_EFFORTS = ["low", "high", "max"];
|
|
1246
|
+
KIMI_MODEL_INFO = {
|
|
1247
|
+
"kimi-k3": {
|
|
1248
|
+
displayName: "Kimi K3",
|
|
1249
|
+
description: "Moonshot flagship \u2014 1M context, reasoning on by default, vision and tools.",
|
|
1250
|
+
supportedReasoningEfforts: KIMI_REASONING_EFFORTS,
|
|
1251
|
+
defaultReasoningEffort: "max",
|
|
1252
|
+
aliases: ["k3", "kimi k3", "moonshot-kimi-k3", "moonshotai/kimi-k3"]
|
|
1253
|
+
},
|
|
1254
|
+
"kimi-k2.6": {
|
|
1255
|
+
displayName: "Kimi K2.6",
|
|
1256
|
+
description: "Smaller, cheaper Kimi \u2014 256K context, multimodal.",
|
|
1257
|
+
// No supportedReasoningEfforts: Moonshot lists `reasoning_effort` as "Not
|
|
1258
|
+
// supported" for K2.6, which instead takes a `thinking: {type}` object. ZTC
|
|
1259
|
+
// does not send that object yet, so the picker must not offer a depth control
|
|
1260
|
+
// here — the effort ladder and the thinking switch are different contracts.
|
|
1261
|
+
aliases: ["k2.6", "kimi k2.6", "moonshotai/kimi-k2.6"]
|
|
1262
|
+
},
|
|
1263
|
+
"kimi-for-coding": {
|
|
1264
|
+
displayName: "Kimi K2.7 Coding",
|
|
1265
|
+
description: "Kimi Code subscription coding model \u2014 256K context, always-thinking, vision and tools.",
|
|
1266
|
+
// No supportedReasoningEfforts: the subscription coding models are
|
|
1267
|
+
// always-thinking with no documented effort ladder, so /effort stays
|
|
1268
|
+
// rejected rather than forwarding a value the API silently ignores.
|
|
1269
|
+
aliases: ["k2.7", "kimi k2.7", "kimi-k2.7-coding"]
|
|
1270
|
+
},
|
|
1271
|
+
"kimi-for-coding-highspeed": {
|
|
1272
|
+
displayName: "Kimi K2.7 Coding Highspeed",
|
|
1273
|
+
description: "High-speed variant of the Kimi Code subscription coding model \u2014 256K context.",
|
|
1274
|
+
aliases: ["k2.7-highspeed", "kimi-for-coding-fast"]
|
|
868
1275
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
out.push({ role: "user", content: textParts.join("\n") });
|
|
876
|
-
}
|
|
1276
|
+
};
|
|
1277
|
+
KIMI_ALIAS_TO_ID = /* @__PURE__ */ new Map();
|
|
1278
|
+
for (const id of Object.keys(KIMI_MODEL_INFO)) {
|
|
1279
|
+
KIMI_ALIAS_TO_ID.set(id, id);
|
|
1280
|
+
for (const alias of KIMI_MODEL_INFO[id].aliases) {
|
|
1281
|
+
KIMI_ALIAS_TO_ID.set(alias.toLowerCase(), id);
|
|
877
1282
|
}
|
|
878
|
-
continue;
|
|
879
|
-
}
|
|
880
|
-
if (mediaParts.length > 0) {
|
|
881
|
-
const parts = textParts.map((t) => ({ type: "text", text: t }));
|
|
882
|
-
parts.push(...mediaParts);
|
|
883
|
-
out.push(withReasoning({ role: msg.role, content: parts }, msg));
|
|
884
|
-
} else {
|
|
885
|
-
out.push(withReasoning({ role: msg.role, content: textParts.join("\n") }, msg));
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
return out;
|
|
889
|
-
}
|
|
890
|
-
function buildOpenAIToolDefs(tools) {
|
|
891
|
-
return tools.map((t) => ({
|
|
892
|
-
type: "function",
|
|
893
|
-
function: {
|
|
894
|
-
name: t.name,
|
|
895
|
-
description: t.description,
|
|
896
|
-
parameters: t.parameters
|
|
897
1283
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1284
|
+
CLAUDE_REASONING_EFFORTS = [
|
|
1285
|
+
"low",
|
|
1286
|
+
"medium",
|
|
1287
|
+
"high",
|
|
1288
|
+
"xhigh",
|
|
1289
|
+
"max"
|
|
1290
|
+
];
|
|
903
1291
|
}
|
|
904
1292
|
});
|
|
905
1293
|
|
|
@@ -961,6 +1349,7 @@ var OpenAICompatibleApiError, OpenAICompatibleBackend;
|
|
|
961
1349
|
var init_openai_compatible = __esm({
|
|
962
1350
|
"src/agent/backends/openai_compatible.ts"() {
|
|
963
1351
|
"use strict";
|
|
1352
|
+
init_model_contracts();
|
|
964
1353
|
init_request_metrics();
|
|
965
1354
|
init_sse();
|
|
966
1355
|
init_token_usage();
|
|
@@ -984,6 +1373,7 @@ var init_openai_compatible = __esm({
|
|
|
984
1373
|
apiPath;
|
|
985
1374
|
headers;
|
|
986
1375
|
extraBody;
|
|
1376
|
+
provider;
|
|
987
1377
|
requestBodyExtras;
|
|
988
1378
|
authTokenProvider;
|
|
989
1379
|
constructor(config) {
|
|
@@ -992,6 +1382,7 @@ var init_openai_compatible = __esm({
|
|
|
992
1382
|
this.apiPath = config.apiPath || "/chat/completions";
|
|
993
1383
|
this.headers = config.headers || {};
|
|
994
1384
|
this.extraBody = config.extraBody || {};
|
|
1385
|
+
this.provider = config.provider;
|
|
995
1386
|
this.requestBodyExtras = config.requestBodyExtras;
|
|
996
1387
|
this.authTokenProvider = config.authTokenProvider;
|
|
997
1388
|
}
|
|
@@ -999,22 +1390,29 @@ var init_openai_compatible = __esm({
|
|
|
999
1390
|
* and generateStream(). generateStream() adds `stream`/`stream_options`. */
|
|
1000
1391
|
async buildCall(request) {
|
|
1001
1392
|
const url = `${this.baseUrl}${this.apiPath}`;
|
|
1002
|
-
const useCompletionTokens = /^o\d/.test(request.model) || /^gpt-[56]/.test(request.model) || isKimiModel(request.model);
|
|
1393
|
+
const useCompletionTokens = this.provider === "fireworks" ? false : /^o\d/.test(request.model) || /^gpt-[56]/.test(request.model) || isKimiModel(request.model);
|
|
1003
1394
|
const isGpt4o = request.model.startsWith("gpt-4o");
|
|
1004
|
-
const
|
|
1395
|
+
const reviewedLimit = this.provider ? modelContract(this.provider, request.model)?.maxOutputTokens?.max : void 0;
|
|
1396
|
+
const limit = reviewedLimit ?? (isGpt4o ? 16384 : isDeepSeekFlashModel(request.model) ? DEEPSEEK_FLASH_MAX_OUTPUT : Infinity);
|
|
1005
1397
|
const effectiveMaxTokens = request.maxTokens === void 0 ? void 0 : Math.min(request.maxTokens, limit);
|
|
1006
1398
|
const tokenParam = effectiveMaxTokens === void 0 ? {} : useCompletionTokens ? { max_completion_tokens: effectiveMaxTokens } : { max_tokens: effectiveMaxTokens };
|
|
1007
|
-
const
|
|
1008
|
-
const
|
|
1399
|
+
const policyProvider = this.provider ?? "openai";
|
|
1400
|
+
const chatEfforts = modelContract(policyProvider, request.model)?.chatToolReasoningEfforts;
|
|
1401
|
+
const toolRestricted = request.tools.length > 0 && chatEfforts !== void 0;
|
|
1402
|
+
if (toolRestricted && request.codexEffort !== void 0 && !chatEfforts.includes(request.codexEffort)) {
|
|
1403
|
+
throw new Error("Use Responses for graded reasoning with tools on this model. Chat Completions supports effort none.");
|
|
1404
|
+
}
|
|
1405
|
+
const reasoningEffort = toolRestricted ? request.codexEffort ?? "none" : request.codexEffort;
|
|
1009
1406
|
const body = {
|
|
1010
1407
|
...this.extraBody,
|
|
1408
|
+
...reasoningRequestParams(policyProvider, request.model, reasoningEffort),
|
|
1011
1409
|
...this.requestBodyExtras?.(request) ?? {},
|
|
1012
|
-
model: request.model,
|
|
1410
|
+
model: this.provider === "fireworks" ? fireworksRequestModel(request.model) : request.model,
|
|
1013
1411
|
...tokenParam,
|
|
1014
1412
|
// Chat Completions accepts GPT-6 Sol/Luna function tools only with
|
|
1015
1413
|
// reasoning disabled. The direct OpenAI backend uses Responses instead;
|
|
1016
1414
|
// keep this rule for explicitly configured compatible endpoints.
|
|
1017
|
-
...
|
|
1415
|
+
...toolRestricted ? { reasoning_effort: reasoningEffort } : {},
|
|
1018
1416
|
messages: buildOpenAIMessages(request),
|
|
1019
1417
|
...request.tools.length > 0 ? { tools: buildOpenAIToolDefs(request.tools) } : {}
|
|
1020
1418
|
};
|
|
@@ -1712,12 +2110,13 @@ var init_openai_responses = __esm({
|
|
|
1712
2110
|
|
|
1713
2111
|
// src/agent/backends/openai.ts
|
|
1714
2112
|
function needsResponsesAPI(model) {
|
|
1715
|
-
return RESPONSES_API_PATTERNS.some((p) => p.test(model));
|
|
2113
|
+
return modelContract("openai", model)?.chatToolReasoningEfforts !== void 0 || RESPONSES_API_PATTERNS.some((p) => p.test(model));
|
|
1716
2114
|
}
|
|
1717
2115
|
var RESPONSES_API_PATTERNS, OpenAIBackend;
|
|
1718
2116
|
var init_openai = __esm({
|
|
1719
2117
|
"src/agent/backends/openai.ts"() {
|
|
1720
2118
|
"use strict";
|
|
2119
|
+
init_model_contracts();
|
|
1721
2120
|
init_openai_compatible();
|
|
1722
2121
|
init_openai_responses();
|
|
1723
2122
|
RESPONSES_API_PATTERNS = [
|
|
@@ -1733,7 +2132,8 @@ var init_openai = __esm({
|
|
|
1733
2132
|
this.chatBackend = new OpenAICompatibleBackend({
|
|
1734
2133
|
apiKey: config.apiKey,
|
|
1735
2134
|
baseUrl,
|
|
1736
|
-
apiPath: "/chat/completions"
|
|
2135
|
+
apiPath: "/chat/completions",
|
|
2136
|
+
provider: "openai"
|
|
1737
2137
|
});
|
|
1738
2138
|
this.responsesBackend = new OpenAIResponsesBackend({
|
|
1739
2139
|
apiKey: config.apiKey,
|
|
@@ -1787,6 +2187,7 @@ var GeminiBackend;
|
|
|
1787
2187
|
var init_gemini = __esm({
|
|
1788
2188
|
"src/agent/backends/gemini.ts"() {
|
|
1789
2189
|
"use strict";
|
|
2190
|
+
init_model_contracts();
|
|
1790
2191
|
init_base();
|
|
1791
2192
|
GeminiBackend = class extends BaseBackend {
|
|
1792
2193
|
apiKey;
|
|
@@ -1817,6 +2218,7 @@ var init_gemini = __esm({
|
|
|
1817
2218
|
});
|
|
1818
2219
|
};
|
|
1819
2220
|
const body = {
|
|
2221
|
+
...reasoningRequestParams("gemini", request.model, request.codexEffort),
|
|
1820
2222
|
systemInstruction: { parts: [{ text: request.system }] },
|
|
1821
2223
|
contents: request.messages.map((m) => ({
|
|
1822
2224
|
role: m.role === "assistant" ? "model" : "user",
|
|
@@ -1901,43 +2303,6 @@ var init_kimi = __esm({
|
|
|
1901
2303
|
}
|
|
1902
2304
|
});
|
|
1903
2305
|
|
|
1904
|
-
// src/config/profiles.ts
|
|
1905
|
-
import { homedir } from "node:os";
|
|
1906
|
-
import { join } from "node:path";
|
|
1907
|
-
import { existsSync } from "node:fs";
|
|
1908
|
-
function builtinProfileEmulation(name) {
|
|
1909
|
-
const builtin = BUILTIN_CONFIG_PROFILES.find((profile) => profile === name);
|
|
1910
|
-
if (!builtin) return void 0;
|
|
1911
|
-
const root = process.env.ZTC_CONFIG_DIR || join(homedir(), ".ztc");
|
|
1912
|
-
return existsSync(join(root, "profiles", name)) ? void 0 : builtin;
|
|
1913
|
-
}
|
|
1914
|
-
function validateProfileName(name) {
|
|
1915
|
-
if (name !== "default" && !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name)) {
|
|
1916
|
-
throw new Error("Profile name must be 1\u201364 characters: letters, numbers, dots, underscores, or hyphens; it must start with a letter or number.");
|
|
1917
|
-
}
|
|
1918
|
-
if (name === "." || name === "..") {
|
|
1919
|
-
throw new Error("Profile name cannot be . or ..");
|
|
1920
|
-
}
|
|
1921
|
-
return name;
|
|
1922
|
-
}
|
|
1923
|
-
function activeProfile() {
|
|
1924
|
-
return validateProfileName(process.env.ZTC_PROFILE || "default");
|
|
1925
|
-
}
|
|
1926
|
-
function profileConfigDir(profile = activeProfile()) {
|
|
1927
|
-
const root = process.env.ZTC_CONFIG_DIR || join(homedir(), ".ztc");
|
|
1928
|
-
const name = validateProfileName(profile);
|
|
1929
|
-
if (name === "default") return root;
|
|
1930
|
-
const namedDir = join(root, "profiles", name);
|
|
1931
|
-
return builtinProfileEmulation(name) ? root : namedDir;
|
|
1932
|
-
}
|
|
1933
|
-
var BUILTIN_CONFIG_PROFILES;
|
|
1934
|
-
var init_profiles = __esm({
|
|
1935
|
-
"src/config/profiles.ts"() {
|
|
1936
|
-
"use strict";
|
|
1937
|
-
BUILTIN_CONFIG_PROFILES = ["ztc", "ztc-coder", "ztc-datascience", "scientist"];
|
|
1938
|
-
}
|
|
1939
|
-
});
|
|
1940
|
-
|
|
1941
2306
|
// src/agent/backends/rate_limit.ts
|
|
1942
2307
|
function parseResetAt(opts) {
|
|
1943
2308
|
const { now } = opts;
|
|
@@ -1990,13 +2355,13 @@ var init_rate_limit = __esm({
|
|
|
1990
2355
|
});
|
|
1991
2356
|
|
|
1992
2357
|
// src/agent/backends/claude_code_auth.ts
|
|
1993
|
-
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
2358
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
1994
2359
|
import { homedir as homedir2, platform, userInfo } from "os";
|
|
1995
|
-
import { join as
|
|
2360
|
+
import { join as join3 } from "path";
|
|
1996
2361
|
import { execFileSync } from "child_process";
|
|
1997
2362
|
function getClaudeCodeCredentialsFilePath() {
|
|
1998
|
-
const configDir2 = process.env.CLAUDE_CONFIG_DIR ||
|
|
1999
|
-
return
|
|
2363
|
+
const configDir2 = process.env.CLAUDE_CONFIG_DIR || join3(homedir2(), ".claude");
|
|
2364
|
+
return join3(configDir2, ".credentials.json");
|
|
2000
2365
|
}
|
|
2001
2366
|
function parseClaudeCodeCredentials(raw) {
|
|
2002
2367
|
const data = JSON.parse(raw);
|
|
@@ -2078,7 +2443,7 @@ var init_claude_code_auth = __esm({
|
|
|
2078
2443
|
return;
|
|
2079
2444
|
}
|
|
2080
2445
|
if (existsSync2(this.credentialsFilePath)) {
|
|
2081
|
-
this.credentials = parseClaudeCodeCredentials(
|
|
2446
|
+
this.credentials = parseClaudeCodeCredentials(readFileSync2(this.credentialsFilePath, "utf8"));
|
|
2082
2447
|
return;
|
|
2083
2448
|
}
|
|
2084
2449
|
const keychainRaw = this.keychainReader ? this.keychainReader() : readMacOSKeychainCredentials(this.keychainAccount);
|
|
@@ -2150,9 +2515,9 @@ var init_claude_code_auth = __esm({
|
|
|
2150
2515
|
|
|
2151
2516
|
// src/agent/backends/codex_auth.ts
|
|
2152
2517
|
import { randomBytes } from "crypto";
|
|
2153
|
-
import { chmodSync, readFileSync as
|
|
2518
|
+
import { chmodSync, readFileSync as readFileSync3, renameSync, unlinkSync, writeFileSync } from "fs";
|
|
2154
2519
|
import { homedir as homedir3 } from "os";
|
|
2155
|
-
import { join as
|
|
2520
|
+
import { join as join4 } from "path";
|
|
2156
2521
|
function resolveClientId(fileClientId) {
|
|
2157
2522
|
return process.env.CODEX_OAUTH_CLIENT_ID || fileClientId || DEFAULT_CODEX_CLIENT_ID;
|
|
2158
2523
|
}
|
|
@@ -2235,7 +2600,7 @@ function hasUsableCodexAuth(authFilePath = CODEX_AUTH_FILE_PATH) {
|
|
|
2235
2600
|
}
|
|
2236
2601
|
function _probeAuthFile(path) {
|
|
2237
2602
|
try {
|
|
2238
|
-
parseCodexAuthFile(
|
|
2603
|
+
parseCodexAuthFile(readFileSync3(path, "utf-8"));
|
|
2239
2604
|
return true;
|
|
2240
2605
|
} catch {
|
|
2241
2606
|
return false;
|
|
@@ -2248,7 +2613,7 @@ var init_codex_auth = __esm({
|
|
|
2248
2613
|
init_openai_responses();
|
|
2249
2614
|
init_rate_limit();
|
|
2250
2615
|
init_provider_ids();
|
|
2251
|
-
CODEX_AUTH_FILE_PATH =
|
|
2616
|
+
CODEX_AUTH_FILE_PATH = join4(homedir3(), ".codex", "auth.json");
|
|
2252
2617
|
CODEX_AUTH_SENTINEL = "codex-subscription-auth";
|
|
2253
2618
|
OAUTH_TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
2254
2619
|
DEFAULT_CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -2271,7 +2636,7 @@ var init_codex_auth = __esm({
|
|
|
2271
2636
|
loadCredentialsSync() {
|
|
2272
2637
|
let raw;
|
|
2273
2638
|
try {
|
|
2274
|
-
raw =
|
|
2639
|
+
raw = readFileSync3(this.authFilePath, "utf-8");
|
|
2275
2640
|
} catch {
|
|
2276
2641
|
throw new Error(
|
|
2277
2642
|
"Codex auth not found. Run 'codex' to authenticate with ChatGPT first."
|
|
@@ -2591,7 +2956,7 @@ var init_codex_auth = __esm({
|
|
|
2591
2956
|
|
|
2592
2957
|
// src/agent/backends/codex_app_server.ts
|
|
2593
2958
|
import { spawn } from "node:child_process";
|
|
2594
|
-
import { createHash } from "node:crypto";
|
|
2959
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
2595
2960
|
function buildCodexAppServerEnv(codexHome, base = process.env) {
|
|
2596
2961
|
const env = { ...base };
|
|
2597
2962
|
if (codexHome) env.CODEX_HOME = codexHome;
|
|
@@ -2607,7 +2972,7 @@ function buildCodexAppServerEnv(codexHome, base = process.env) {
|
|
|
2607
2972
|
return env;
|
|
2608
2973
|
}
|
|
2609
2974
|
function sha1(value) {
|
|
2610
|
-
return
|
|
2975
|
+
return createHash2("sha1").update(value).digest("hex");
|
|
2611
2976
|
}
|
|
2612
2977
|
function nonEmptyId(value) {
|
|
2613
2978
|
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
@@ -3826,7 +4191,7 @@ var init_codex_app_server = __esm({
|
|
|
3826
4191
|
|
|
3827
4192
|
// src/utils/debug_log.ts
|
|
3828
4193
|
import { appendFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
3829
|
-
import { join as
|
|
4194
|
+
import { join as join5 } from "path";
|
|
3830
4195
|
import { tmpdir } from "os";
|
|
3831
4196
|
function debugLog(message) {
|
|
3832
4197
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -3856,7 +4221,7 @@ var init_debug_log = __esm({
|
|
|
3856
4221
|
"src/utils/debug_log.ts"() {
|
|
3857
4222
|
"use strict";
|
|
3858
4223
|
DEBUG_ENABLED = process.env.ZTC_DEBUG === "1";
|
|
3859
|
-
DEBUG_LOG_FILE =
|
|
4224
|
+
DEBUG_LOG_FILE = join5(tmpdir(), `ztc-debug-${process.pid}.log`);
|
|
3860
4225
|
if (DEBUG_ENABLED) {
|
|
3861
4226
|
writeFileSync2(DEBUG_LOG_FILE, `[${(/* @__PURE__ */ new Date()).toISOString()}] ZTC starting, PID=${process.pid}
|
|
3862
4227
|
`);
|
|
@@ -3869,14 +4234,14 @@ var init_debug_log = __esm({
|
|
|
3869
4234
|
});
|
|
3870
4235
|
|
|
3871
4236
|
// src/agent/backends/kimi_code_auth.ts
|
|
3872
|
-
import { mkdirSync, chmodSync as chmodSync2, readFileSync as
|
|
4237
|
+
import { mkdirSync, chmodSync as chmodSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
3873
4238
|
import { homedir as homedir4 } from "os";
|
|
3874
|
-
import { dirname, join as
|
|
4239
|
+
import { dirname as dirname2, join as join6 } from "path";
|
|
3875
4240
|
function kimiCodeHome() {
|
|
3876
|
-
return process.env.KIMI_CODE_HOME ||
|
|
4241
|
+
return process.env.KIMI_CODE_HOME || join6(homedir4(), ".kimi-code");
|
|
3877
4242
|
}
|
|
3878
4243
|
function defaultKimiCodeAuthFilePath() {
|
|
3879
|
-
return
|
|
4244
|
+
return join6(kimiCodeHome(), "credentials", "kimi-code.json");
|
|
3880
4245
|
}
|
|
3881
4246
|
function kimiCodeOAuthHost() {
|
|
3882
4247
|
return (process.env.KIMI_CODE_OAUTH_HOST || process.env.KIMI_OAUTH_HOST || DEFAULT_OAUTH_HOST).replace(/\/+$/, "");
|
|
@@ -3905,14 +4270,14 @@ function parseKimiCodeAuthFile(raw) {
|
|
|
3905
4270
|
}
|
|
3906
4271
|
function hasUsableKimiCodeAuth(authFilePath = defaultKimiCodeAuthFilePath()) {
|
|
3907
4272
|
try {
|
|
3908
|
-
parseKimiCodeAuthFile(
|
|
4273
|
+
parseKimiCodeAuthFile(readFileSync4(authFilePath, "utf-8"));
|
|
3909
4274
|
return true;
|
|
3910
4275
|
} catch {
|
|
3911
4276
|
return false;
|
|
3912
4277
|
}
|
|
3913
4278
|
}
|
|
3914
4279
|
function writeKimiCodeCredentials(authFilePath, creds) {
|
|
3915
|
-
const dir =
|
|
4280
|
+
const dir = dirname2(authFilePath);
|
|
3916
4281
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
3917
4282
|
try {
|
|
3918
4283
|
chmodSync2(dir, 448);
|
|
@@ -3938,7 +4303,7 @@ function writeKimiCodeCredentials(authFilePath, creds) {
|
|
|
3938
4303
|
try {
|
|
3939
4304
|
renameSync2(tmp, authFilePath);
|
|
3940
4305
|
} catch {
|
|
3941
|
-
writeFileSync3(authFilePath,
|
|
4306
|
+
writeFileSync3(authFilePath, readFileSync4(tmp, "utf-8"), { encoding: "utf-8", mode: 384 });
|
|
3942
4307
|
}
|
|
3943
4308
|
chmodSync2(authFilePath, 384);
|
|
3944
4309
|
}
|
|
@@ -4055,7 +4420,7 @@ var init_kimi_code_auth = __esm({
|
|
|
4055
4420
|
loadCredentialsSync() {
|
|
4056
4421
|
let raw;
|
|
4057
4422
|
try {
|
|
4058
|
-
raw =
|
|
4423
|
+
raw = readFileSync4(this.authFilePath, "utf-8");
|
|
4059
4424
|
} catch {
|
|
4060
4425
|
throw new Error(
|
|
4061
4426
|
"Kimi Code auth not found. Run 'kimi' and use /login, or sign in via /accounts (kimi_code provider)."
|
|
@@ -4131,7 +4496,7 @@ var init_kimi_code_auth = __esm({
|
|
|
4131
4496
|
const detail = typeof data.error_description === "string" ? data.error_description : typeof data.error === "string" ? data.error : `HTTP ${status}`;
|
|
4132
4497
|
if (status === 401 || status === 403 || data.error === "invalid_grant") {
|
|
4133
4498
|
try {
|
|
4134
|
-
const onDisk = parseKimiCodeAuthFile(
|
|
4499
|
+
const onDisk = parseKimiCodeAuthFile(readFileSync4(this.authFilePath, "utf-8"));
|
|
4135
4500
|
if (onDisk.refreshToken !== refreshToken && !this.isExpiringSoon(onDisk.expiresAt)) {
|
|
4136
4501
|
this.credentials = onDisk;
|
|
4137
4502
|
return;
|
|
@@ -4194,7 +4559,7 @@ var init_kimi_code_auth = __esm({
|
|
|
4194
4559
|
|
|
4195
4560
|
// src/agent/backends/account_pool.ts
|
|
4196
4561
|
import { homedir as homedir5 } from "node:os";
|
|
4197
|
-
import { basename, dirname as
|
|
4562
|
+
import { basename, dirname as dirname3, join as join7, resolve } from "node:path";
|
|
4198
4563
|
function canonicalAccountProvider(provider) {
|
|
4199
4564
|
const norm = normalizeProviderId(provider);
|
|
4200
4565
|
switch (norm) {
|
|
@@ -4247,7 +4612,7 @@ function probeAccountIsolated(account) {
|
|
|
4247
4612
|
switch (source.kind) {
|
|
4248
4613
|
case "claude_config_dir":
|
|
4249
4614
|
return hasUsableClaudeCodeAuth({
|
|
4250
|
-
credentialsFilePath:
|
|
4615
|
+
credentialsFilePath: join7(source.path, ".credentials.json"),
|
|
4251
4616
|
envToken: null,
|
|
4252
4617
|
keychainReader: () => void 0
|
|
4253
4618
|
});
|
|
@@ -4258,7 +4623,7 @@ function probeAccountIsolated(account) {
|
|
|
4258
4623
|
keychainReader: () => void 0
|
|
4259
4624
|
});
|
|
4260
4625
|
case "codex_home":
|
|
4261
|
-
return hasUsableCodexAuth(
|
|
4626
|
+
return hasUsableCodexAuth(join7(source.path, "auth.json"));
|
|
4262
4627
|
case "codex_auth_file":
|
|
4263
4628
|
return hasUsableCodexAuth(source.path);
|
|
4264
4629
|
case "kimi_creds_file":
|
|
@@ -4276,7 +4641,7 @@ var init_account_pool = __esm({
|
|
|
4276
4641
|
init_kimi_code_auth();
|
|
4277
4642
|
init_debug_log();
|
|
4278
4643
|
init_profiles();
|
|
4279
|
-
ACCOUNTS_ROOT =
|
|
4644
|
+
ACCOUNTS_ROOT = join7(homedir5(), ".ztc", "accounts");
|
|
4280
4645
|
DEFAULT_ACCOUNT_ROTATION = {
|
|
4281
4646
|
enabled: false,
|
|
4282
4647
|
mode: "failover",
|
|
@@ -4334,7 +4699,7 @@ var init_trace = __esm({
|
|
|
4334
4699
|
|
|
4335
4700
|
// src/agent/backends/claude_cli.ts
|
|
4336
4701
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
4337
|
-
import { randomUUID as
|
|
4702
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
4338
4703
|
function endStdinToleratingBrokenPipe(child, prompt) {
|
|
4339
4704
|
const stdin = child.stdin;
|
|
4340
4705
|
if (!stdin) return;
|
|
@@ -4699,7 +5064,7 @@ ${detail}` : ""}`,
|
|
|
4699
5064
|
const call = extractToolCall(text);
|
|
4700
5065
|
if (!call) return resp;
|
|
4701
5066
|
return {
|
|
4702
|
-
content: [{ type: "tool_use", id: `cli_${
|
|
5067
|
+
content: [{ type: "tool_use", id: `cli_${randomUUID3()}`, name: call.name, input: call.input }],
|
|
4703
5068
|
stopReason: "tool_use",
|
|
4704
5069
|
usage: resp.usage
|
|
4705
5070
|
};
|
|
@@ -4832,7 +5197,7 @@ ${detail}` : ""}`, "claude_cli_exit", { exitCode: code ?? void 0, stderr: detail
|
|
|
4832
5197
|
if (call) {
|
|
4833
5198
|
const open = fullText.indexOf(TOOL_CALL_OPEN);
|
|
4834
5199
|
if (open > emittedLen) push({ type: "text_delta", text: fullText.slice(emittedLen, open) });
|
|
4835
|
-
const id = `cli_${
|
|
5200
|
+
const id = `cli_${randomUUID3()}`;
|
|
4836
5201
|
push({ type: "tool_use_start", id, name: call.name });
|
|
4837
5202
|
push({ type: "tool_use_delta", id, input_json: JSON.stringify(call.input) });
|
|
4838
5203
|
push({ type: "tool_use_end", id });
|
|
@@ -4878,14 +5243,16 @@ var init_fireworks = __esm({
|
|
|
4878
5243
|
});
|
|
4879
5244
|
|
|
4880
5245
|
// src/config/defaults.ts
|
|
4881
|
-
function resolveCodexEffort(config, provider, model) {
|
|
5246
|
+
function resolveCodexEffort(config, provider, model, contract = config.authMode === "zrouter" || provider === "openai_compatible" ? "chat_tools" : "native_api") {
|
|
4882
5247
|
const candidates = [
|
|
4883
5248
|
model ? config.codexEffortByModel?.[model] : void 0,
|
|
4884
5249
|
provider ? config.codexEffortByProvider?.[provider] : void 0,
|
|
4885
5250
|
config.codexEffort
|
|
4886
5251
|
];
|
|
4887
5252
|
for (const candidate of candidates) {
|
|
4888
|
-
if (candidate
|
|
5253
|
+
if (!candidate) continue;
|
|
5254
|
+
const supported = typeof contract === "string" ? isCodexReasoningEffortSupported(provider, model, candidate, contract) : contract.reasoning?.choices.includes(candidate);
|
|
5255
|
+
if (candidate && supported) return candidate;
|
|
4889
5256
|
}
|
|
4890
5257
|
return void 0;
|
|
4891
5258
|
}
|
|
@@ -4984,6 +5351,8 @@ function getDefaultApiKeyForProvider(provider) {
|
|
|
4984
5351
|
case "modal":
|
|
4985
5352
|
return void 0;
|
|
4986
5353
|
// Modal credentials belong to the Router platform.
|
|
5354
|
+
case "fireworks":
|
|
5355
|
+
return process.env.FIREWORKS_API_KEY;
|
|
4987
5356
|
default:
|
|
4988
5357
|
return process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY || process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY || process.env.OPENAI_COMPAT_API_KEY || process.env.INCEPTION_API_KEY;
|
|
4989
5358
|
}
|
|
@@ -5078,17 +5447,17 @@ var init_atomic_write = __esm({
|
|
|
5078
5447
|
});
|
|
5079
5448
|
|
|
5080
5449
|
// src/config/repo_config.ts
|
|
5081
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as
|
|
5082
|
-
import { dirname as
|
|
5450
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
5451
|
+
import { dirname as dirname4, join as join8 } from "path";
|
|
5083
5452
|
function repoConfigPath(cwd) {
|
|
5084
|
-
return
|
|
5453
|
+
return join8(cwd, REPO_CONFIG_RELATIVE_PATH);
|
|
5085
5454
|
}
|
|
5086
5455
|
function readRepoConfig(cwd) {
|
|
5087
5456
|
if (isExplicitExtensionDiscovery()) return null;
|
|
5088
5457
|
const path = repoConfigPath(cwd);
|
|
5089
5458
|
if (!existsSync3(path)) return null;
|
|
5090
5459
|
try {
|
|
5091
|
-
const parsed = JSON.parse(
|
|
5460
|
+
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
5092
5461
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
5093
5462
|
} catch {
|
|
5094
5463
|
return null;
|
|
@@ -5107,19 +5476,19 @@ var init_repo_config = __esm({
|
|
|
5107
5476
|
"use strict";
|
|
5108
5477
|
init_extension_discovery();
|
|
5109
5478
|
init_atomic_write();
|
|
5110
|
-
REPO_CONFIG_RELATIVE_PATH =
|
|
5479
|
+
REPO_CONFIG_RELATIVE_PATH = join8(".ztc", "config.json");
|
|
5111
5480
|
}
|
|
5112
5481
|
});
|
|
5113
5482
|
|
|
5114
5483
|
// src/utils/version.ts
|
|
5115
|
-
import { readFileSync as
|
|
5116
|
-
import { dirname as
|
|
5484
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
5485
|
+
import { dirname as dirname5, resolve as resolve3 } from "path";
|
|
5117
5486
|
import { fileURLToPath } from "url";
|
|
5118
5487
|
function getVersion() {
|
|
5119
5488
|
try {
|
|
5120
|
-
const here =
|
|
5489
|
+
const here = dirname5(fileURLToPath(import.meta.url));
|
|
5121
5490
|
const pkgPath = resolve3(here, "../../package.json");
|
|
5122
|
-
const raw =
|
|
5491
|
+
const raw = readFileSync6(pkgPath, "utf-8");
|
|
5123
5492
|
const parsed = JSON.parse(raw);
|
|
5124
5493
|
return parsed.version || "0.0.0";
|
|
5125
5494
|
} catch {
|
|
@@ -5134,12 +5503,12 @@ var init_version = __esm({
|
|
|
5134
5503
|
|
|
5135
5504
|
// src/router_auth.ts
|
|
5136
5505
|
import { chmod, mkdir, readFile, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
|
|
5137
|
-
import { join as
|
|
5506
|
+
import { join as join9 } from "node:path";
|
|
5138
5507
|
function credentialDirectory() {
|
|
5139
5508
|
return profileConfigDir();
|
|
5140
5509
|
}
|
|
5141
5510
|
function credentialPath() {
|
|
5142
|
-
return
|
|
5511
|
+
return join9(credentialDirectory(), "router-auth.json");
|
|
5143
5512
|
}
|
|
5144
5513
|
function routerOrigin(value) {
|
|
5145
5514
|
const url = new URL(value);
|
|
@@ -5149,7 +5518,7 @@ function routerOrigin(value) {
|
|
|
5149
5518
|
}
|
|
5150
5519
|
return url.origin;
|
|
5151
5520
|
}
|
|
5152
|
-
function
|
|
5521
|
+
function record3(value) {
|
|
5153
5522
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5154
5523
|
throw new Error("Router returned an invalid response.");
|
|
5155
5524
|
}
|
|
@@ -5175,10 +5544,10 @@ async function loadRouterCredentials() {
|
|
|
5175
5544
|
throw error;
|
|
5176
5545
|
}
|
|
5177
5546
|
try {
|
|
5178
|
-
const saved =
|
|
5547
|
+
const saved = record3(JSON.parse(data));
|
|
5179
5548
|
let previousConfig;
|
|
5180
5549
|
if (saved.previousConfig !== void 0) {
|
|
5181
|
-
const previous =
|
|
5550
|
+
const previous = record3(saved.previousConfig);
|
|
5182
5551
|
if (previous.authMode !== void 0 && !["auto", "direct", "zrouter"].includes(String(previous.authMode))) {
|
|
5183
5552
|
throw new Error("Invalid previous authentication mode.");
|
|
5184
5553
|
}
|
|
@@ -5251,7 +5620,9 @@ function estimateTokens(text) {
|
|
|
5251
5620
|
if (!text) return 0;
|
|
5252
5621
|
return Math.ceil(text.length / 4);
|
|
5253
5622
|
}
|
|
5254
|
-
function getContextWindowSize(model) {
|
|
5623
|
+
function getContextWindowSize(model, windowOverride) {
|
|
5624
|
+
if (windowOverride === null) return 0;
|
|
5625
|
+
if (typeof windowOverride === "number" && windowOverride > 0) return windowOverride;
|
|
5255
5626
|
if (MODEL_CONTEXT_WINDOWS[model]) {
|
|
5256
5627
|
return MODEL_CONTEXT_WINDOWS[model];
|
|
5257
5628
|
}
|
|
@@ -5413,7 +5784,7 @@ var init_loop_policy = __esm({
|
|
|
5413
5784
|
});
|
|
5414
5785
|
|
|
5415
5786
|
// src/agent/tool_compression.ts
|
|
5416
|
-
import { createHash as
|
|
5787
|
+
import { createHash as createHash3 } from "crypto";
|
|
5417
5788
|
function isReadToolName(name) {
|
|
5418
5789
|
return READ_TOOL_NAMES.has(name);
|
|
5419
5790
|
}
|
|
@@ -5427,7 +5798,7 @@ function extractSourcePath(toolName, args) {
|
|
|
5427
5798
|
return null;
|
|
5428
5799
|
}
|
|
5429
5800
|
function hashToolResultBody(content) {
|
|
5430
|
-
return
|
|
5801
|
+
return createHash3("sha256").update(stripRepeatGuard(content), "utf-8").digest("hex").slice(0, 16);
|
|
5431
5802
|
}
|
|
5432
5803
|
function compressionMarker(mode, toolUseId, savedTokensApprox) {
|
|
5433
5804
|
return {
|
|
@@ -5694,8 +6065,8 @@ var init_deferred = __esm({
|
|
|
5694
6065
|
});
|
|
5695
6066
|
|
|
5696
6067
|
// src/agent/tool_response_store.ts
|
|
5697
|
-
import { mkdir as mkdir2, readFile as readFile2, readdir } from "fs/promises";
|
|
5698
|
-
import { join as
|
|
6068
|
+
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir2 } from "fs/promises";
|
|
6069
|
+
import { join as join10 } from "path";
|
|
5699
6070
|
function formatOffloadPlaceholder(meta) {
|
|
5700
6071
|
const partialNote = meta.partial ? ", partial=true" : "";
|
|
5701
6072
|
const base = `[tool result offloaded \u2014 tool_use_id=${meta.tool_use_id}, tool=${meta.tool_name}, size_tokens\u2248${meta.size_tokens}, turn=${meta.turn}${partialNote}. Call recall_tool_response with tool_use_id to retrieve full content.]`;
|
|
@@ -5827,9 +6198,10 @@ var init_tool_response_store = __esm({
|
|
|
5827
6198
|
* fraction of the active model's context window so a small-context model
|
|
5828
6199
|
* (gpt-4 8k → 2k effective) doesn't get crushed by a Claude-tuned default.
|
|
5829
6200
|
*/
|
|
5830
|
-
effectiveBudget(model) {
|
|
6201
|
+
effectiveBudget(model, windowOverride) {
|
|
5831
6202
|
const configured = this.config.configuredInlineBudgetTokens;
|
|
5832
|
-
const window = getContextWindowSize(model);
|
|
6203
|
+
const window = getContextWindowSize(model, windowOverride);
|
|
6204
|
+
if (window === 0) return configured;
|
|
5833
6205
|
return Math.min(configured, Math.floor(window * PER_MODEL_BUDGET_FRACTION));
|
|
5834
6206
|
}
|
|
5835
6207
|
cacheBudgetTokens() {
|
|
@@ -5854,7 +6226,7 @@ var init_tool_response_store = __esm({
|
|
|
5854
6226
|
await mkdir2(dir, { recursive: true });
|
|
5855
6227
|
let files;
|
|
5856
6228
|
try {
|
|
5857
|
-
files = await
|
|
6229
|
+
files = await readdir2(dir);
|
|
5858
6230
|
} catch {
|
|
5859
6231
|
return;
|
|
5860
6232
|
}
|
|
@@ -5862,7 +6234,7 @@ var init_tool_response_store = __esm({
|
|
|
5862
6234
|
const records = await Promise.all(
|
|
5863
6235
|
jsonFiles.map(async (f) => {
|
|
5864
6236
|
try {
|
|
5865
|
-
const raw = await readFile2(
|
|
6237
|
+
const raw = await readFile2(join10(dir, f), "utf-8");
|
|
5866
6238
|
const rec = JSON.parse(raw);
|
|
5867
6239
|
return rec?.meta?.tool_use_id ? rec.meta : null;
|
|
5868
6240
|
} catch {
|
|
@@ -5931,7 +6303,7 @@ var init_tool_response_store = __esm({
|
|
|
5931
6303
|
this.renderMemo.delete(toolUseId);
|
|
5932
6304
|
this.cacheContent(toolUseId, content);
|
|
5933
6305
|
if (this.dir) {
|
|
5934
|
-
const path =
|
|
6306
|
+
const path = join10(this.dir, `${toolUseId}.json`);
|
|
5935
6307
|
const write = writeFileAtomic(path, JSON.stringify({ meta, content })).catch((err) => {
|
|
5936
6308
|
const message = err instanceof Error ? err.message : String(err);
|
|
5937
6309
|
debugLog2(`[ToolResponseStore] atomic write failed for ${toolUseId}: ${message}`);
|
|
@@ -5949,7 +6321,7 @@ var init_tool_response_store = __esm({
|
|
|
5949
6321
|
if (cached2 !== void 0) return cached2;
|
|
5950
6322
|
if (!this.dir) return null;
|
|
5951
6323
|
try {
|
|
5952
|
-
const raw = await readFile2(
|
|
6324
|
+
const raw = await readFile2(join10(this.dir, `${toolUseId}.json`), "utf-8");
|
|
5953
6325
|
const rec = JSON.parse(raw);
|
|
5954
6326
|
if (rec && typeof rec.content === "string") {
|
|
5955
6327
|
if (rec.meta && !this.meta.has(toolUseId)) {
|
|
@@ -6032,8 +6404,8 @@ var init_tool_response_store = __esm({
|
|
|
6032
6404
|
renderInline(e) {
|
|
6033
6405
|
if (!this.compressionActive()) return e.content;
|
|
6034
6406
|
if (e.meta.recalledAtTurn !== void 0) return e.content;
|
|
6035
|
-
const
|
|
6036
|
-
if (
|
|
6407
|
+
const memo2 = this.renderMemo.get(e.id);
|
|
6408
|
+
if (memo2) return memo2.text;
|
|
6037
6409
|
const mode = this.config.toolCompression === "aggressive" ? "aggressive" : "safe";
|
|
6038
6410
|
const stub = this.duplicateStubFor(e.meta);
|
|
6039
6411
|
const text = stub ?? compressToolResult({
|
|
@@ -6060,8 +6432,8 @@ var init_tool_response_store = __esm({
|
|
|
6060
6432
|
}
|
|
6061
6433
|
/** Cost of an inline render: the memoized token count when one was prepared. */
|
|
6062
6434
|
inlineCost(e, rendered) {
|
|
6063
|
-
const
|
|
6064
|
-
if (
|
|
6435
|
+
const memo2 = this.renderMemo.get(e.id);
|
|
6436
|
+
if (memo2 && memo2.text === rendered) return memo2.tokens;
|
|
6065
6437
|
return e.meta.size_tokens;
|
|
6066
6438
|
}
|
|
6067
6439
|
/**
|
|
@@ -6620,9 +6992,9 @@ var init_status_line_config = __esm({
|
|
|
6620
6992
|
});
|
|
6621
6993
|
|
|
6622
6994
|
// src/config.ts
|
|
6623
|
-
import { join as
|
|
6624
|
-
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, chmod as chmod2, unlink as unlink3, rename as rename3, realpath } from "fs/promises";
|
|
6625
|
-
import { randomUUID as
|
|
6995
|
+
import { dirname as dirname6, join as join11 } from "path";
|
|
6996
|
+
import { stat, readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, chmod as chmod2, rm, unlink as unlink3, rename as rename3, realpath } from "fs/promises";
|
|
6997
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
6626
6998
|
function isLocalEndpoint(url) {
|
|
6627
6999
|
try {
|
|
6628
7000
|
const parsed = new URL(url);
|
|
@@ -6746,6 +7118,20 @@ function build_default_config() {
|
|
|
6746
7118
|
function normalizedOrigin(value) {
|
|
6747
7119
|
return value?.trim().replace(/\/+$/, "") || void 0;
|
|
6748
7120
|
}
|
|
7121
|
+
function routerOriginFromEnvironment() {
|
|
7122
|
+
if (process.env.ZERG_PROXY_URL) return process.env.ZERG_PROXY_URL;
|
|
7123
|
+
if (process.env.ZERG_ROUTER_BASE_URL) return normalizedOrigin(process.env.ZERG_ROUTER_BASE_URL);
|
|
7124
|
+
const tiers = {
|
|
7125
|
+
local: "http://host.docker.internal:8000/api/zrouter",
|
|
7126
|
+
dev: "https://api-dev.zergai.com/api/zrouter",
|
|
7127
|
+
development: "https://api-dev.zergai.com/api/zrouter",
|
|
7128
|
+
prod: "https://api.zergai.com/api/zrouter",
|
|
7129
|
+
production: "https://api.zergai.com/api/zrouter",
|
|
7130
|
+
main: "https://api.zergai.com/api/zrouter"
|
|
7131
|
+
};
|
|
7132
|
+
const tier = process.env.ZERG_DEPLOY_TIER || "";
|
|
7133
|
+
return Object.hasOwn(tiers, tier) ? tiers[tier] : void 0;
|
|
7134
|
+
}
|
|
6749
7135
|
function savedRouteIsUsable(saved) {
|
|
6750
7136
|
if (!saved.provider) return false;
|
|
6751
7137
|
const provider = normalizeProviderId(saved.provider);
|
|
@@ -6761,12 +7147,12 @@ function savedRouteIsUsable(saved) {
|
|
|
6761
7147
|
function migrateSettingsDefaults(saved) {
|
|
6762
7148
|
const defaults = build_default_config();
|
|
6763
7149
|
const migrated = { ...saved, settingsDefaultsVersion: SETTINGS_DEFAULTS_VERSION };
|
|
6764
|
-
const
|
|
7150
|
+
const record4 = migrated;
|
|
6765
7151
|
const fresh = defaults;
|
|
6766
7152
|
const adopted = savedRouteIsUsable(saved) ? ADOPTED_DEFAULT_KEYS : [...ADOPTED_DEFAULT_KEYS, ...ROUTING_SETTING_KEYS];
|
|
6767
7153
|
for (const key of adopted) {
|
|
6768
|
-
if (fresh[key] === void 0) delete
|
|
6769
|
-
else
|
|
7154
|
+
if (fresh[key] === void 0) delete record4[key];
|
|
7155
|
+
else record4[key] = fresh[key];
|
|
6770
7156
|
}
|
|
6771
7157
|
if (saved.apiKey !== void 0) {
|
|
6772
7158
|
const oldProvider = saved.provider || inferDefaultProvider();
|
|
@@ -6791,7 +7177,7 @@ async function writeMigratedSettings(path, settings, original) {
|
|
|
6791
7177
|
} catch (error) {
|
|
6792
7178
|
if (error.code !== "EEXIST") throw error;
|
|
6793
7179
|
}
|
|
6794
|
-
const temporary = `${target}.${process.pid}.${
|
|
7180
|
+
const temporary = `${target}.${process.pid}.${randomUUID4()}.tmp`;
|
|
6795
7181
|
try {
|
|
6796
7182
|
await writeFile3(temporary, JSON.stringify(settings, null, 2), { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
6797
7183
|
await rename3(temporary, target);
|
|
@@ -6807,12 +7193,15 @@ function configDir() {
|
|
|
6807
7193
|
return profileConfigDir();
|
|
6808
7194
|
}
|
|
6809
7195
|
function configFile() {
|
|
6810
|
-
return
|
|
7196
|
+
return join11(configDir(), "config.json");
|
|
6811
7197
|
}
|
|
6812
7198
|
var API_ENDPOINTS, DEFAULT_TOOL_PERMISSIONS, DEFAULT_PERMISSION_PROFILES, DEFAULT_INTENTS, DEFAULT_SANDBOX, DEFAULT_CONTEXT_PROGRESS_BAR, DEFAULT_WORKFLOWS, SETTINGS_DEFAULTS_VERSION, PERSONAL_DEFAULT_PROVIDER, PERSONAL_DEFAULT_MODEL, PERSONAL_DEFAULT_PROXY_URL, ROUTE_CREDENTIAL_ENV, ADOPTED_DEFAULT_KEYS, ROUTING_SETTING_KEYS, SUPERUSER_STATUS_TIMEOUT_MS, ConfigStore, configStore;
|
|
6813
7199
|
var init_config = __esm({
|
|
6814
7200
|
"src/config.ts"() {
|
|
6815
7201
|
"use strict";
|
|
7202
|
+
init_model_contracts();
|
|
7203
|
+
init_provider_ids();
|
|
7204
|
+
init_router_catalog();
|
|
6816
7205
|
init_profiles();
|
|
6817
7206
|
init_account_pool();
|
|
6818
7207
|
init_account_events();
|
|
@@ -6960,6 +7349,12 @@ var init_config = __esm({
|
|
|
6960
7349
|
// The legacy slot also carries runtime defaults. Only a configured key may
|
|
6961
7350
|
// be migrated into apiKeys or written to disk.
|
|
6962
7351
|
legacyApiKeyFromEnvironment = true;
|
|
7352
|
+
/**
|
|
7353
|
+
* Whether the routing in `this.config` came from a saved file or an explicit
|
|
7354
|
+
* choice, rather than the built-in default. A config-less process that never
|
|
7355
|
+
* picked a route must not hard-fail on the preset Router route it inherited.
|
|
7356
|
+
*/
|
|
7357
|
+
routingIsConfigured = false;
|
|
6963
7358
|
routerCredentials = null;
|
|
6964
7359
|
routerCredentialsError = null;
|
|
6965
7360
|
routerFallbackWarning = null;
|
|
@@ -6967,6 +7362,7 @@ var init_config = __esm({
|
|
|
6967
7362
|
configScope = "global";
|
|
6968
7363
|
/** Session-local overrides. Never persisted to config.json. */
|
|
6969
7364
|
sessionOverrides = {};
|
|
7365
|
+
restoredSessionSelection = false;
|
|
6970
7366
|
/** CLI-only overrides. Never persisted to config.json. */
|
|
6971
7367
|
cliOverrides = {};
|
|
6972
7368
|
/**
|
|
@@ -7020,15 +7416,9 @@ var init_config = __esm({
|
|
|
7020
7416
|
else if (tier === "dev" || tier === "development") this.config.apiEnvironment = "development";
|
|
7021
7417
|
else if (tier === "prod" || tier === "production" || tier === "main") this.config.apiEnvironment = "production";
|
|
7022
7418
|
}
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
this.config.zergProxyUrl = process.env.ZERG_ROUTER_BASE_URL.replace(/\/+$/, "");
|
|
7027
|
-
} else if (process.env.ZERG_DEPLOY_TIER) {
|
|
7028
|
-
const tier = process.env.ZERG_DEPLOY_TIER;
|
|
7029
|
-
if (tier === "local") this.config.zergProxyUrl = "http://host.docker.internal:8000/api/zrouter";
|
|
7030
|
-
else if (tier === "dev" || tier === "development") this.config.zergProxyUrl = "https://api-dev.zergai.com/api/zrouter";
|
|
7031
|
-
else if (tier === "prod" || tier === "production" || tier === "main") this.config.zergProxyUrl = "https://api.zergai.com/api/zrouter";
|
|
7419
|
+
const originOverride = routerOriginFromEnvironment();
|
|
7420
|
+
if (originOverride) {
|
|
7421
|
+
this.config.zergProxyUrl = originOverride;
|
|
7032
7422
|
} else if (!this.config.zergProxyUrl) {
|
|
7033
7423
|
this.config.zergProxyUrl = this.routerCredentials?.origin || this.deriveZRouterUrl(this.getApiBaseUrl());
|
|
7034
7424
|
}
|
|
@@ -7119,12 +7509,59 @@ var init_config = __esm({
|
|
|
7119
7509
|
this.sessionOverrides = sessionOverrides;
|
|
7120
7510
|
this.configScope = scope;
|
|
7121
7511
|
}
|
|
7512
|
+
/** Copy saved settings and Router credentials, then activate them transactionally.
|
|
7513
|
+
* Account registrations retain their credential paths; account homes are not cloned.
|
|
7514
|
+
*/
|
|
7515
|
+
async duplicateProfile(requestedName, source = activeProfile(), activate = () => {
|
|
7516
|
+
}) {
|
|
7517
|
+
const name = validateProfileName(requestedName.trim());
|
|
7518
|
+
const from = validateProfileName(source);
|
|
7519
|
+
if (name === "default" || builtinProfileEmulation(name)) {
|
|
7520
|
+
throw new Error(`Cannot duplicate onto "${name}": it is a built-in profile sharing the default settings. Pick another name.`);
|
|
7521
|
+
}
|
|
7522
|
+
if (name === from || (await listConfigProfiles()).includes(name)) {
|
|
7523
|
+
throw new Error(`Config profile "${name}" already exists. Pick another name.`);
|
|
7524
|
+
}
|
|
7525
|
+
const sourceDir = profileConfigDir(from);
|
|
7526
|
+
const emulation = builtinProfileEmulation(from);
|
|
7527
|
+
if (from !== "default" && !emulation && !(await stat(sourceDir)).isDirectory()) {
|
|
7528
|
+
throw new Error(`Config profile "${from}" does not exist.`);
|
|
7529
|
+
}
|
|
7530
|
+
let saved = {};
|
|
7531
|
+
try {
|
|
7532
|
+
const parsed = JSON.parse(await readFile3(join11(sourceDir, "config.json"), "utf8"));
|
|
7533
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7534
|
+
throw new Error(`Invalid config profile "${from}": expected an object.`);
|
|
7535
|
+
}
|
|
7536
|
+
saved = parsed;
|
|
7537
|
+
} catch (error) {
|
|
7538
|
+
if (error.code !== "ENOENT") throw error;
|
|
7539
|
+
}
|
|
7540
|
+
if (emulation) saved.emulationId = emulation;
|
|
7541
|
+
const destination = profileConfigDir(name);
|
|
7542
|
+
await mkdir3(dirname6(destination), { recursive: true, mode: 448 });
|
|
7543
|
+
await mkdir3(destination, { mode: 448 });
|
|
7544
|
+
try {
|
|
7545
|
+
await writeFile3(join11(destination, "config.json"), JSON.stringify(saved, null, 2), { flag: "wx", mode: 384 });
|
|
7546
|
+
try {
|
|
7547
|
+
const auth = await readFile3(join11(sourceDir, "router-auth.json"));
|
|
7548
|
+
await writeFile3(join11(destination, "router-auth.json"), auth, { flag: "wx", mode: 384 });
|
|
7549
|
+
} catch (error) {
|
|
7550
|
+
if (error.code !== "ENOENT") throw error;
|
|
7551
|
+
}
|
|
7552
|
+
await this.switchProfile(name, activate);
|
|
7553
|
+
} catch (error) {
|
|
7554
|
+
await rm(destination, { recursive: true, force: true });
|
|
7555
|
+
throw error;
|
|
7556
|
+
}
|
|
7557
|
+
return name;
|
|
7558
|
+
}
|
|
7122
7559
|
/** Load a profile in this process; restore the old view if runtime activation fails. */
|
|
7123
7560
|
async switchProfile(name, activate) {
|
|
7124
7561
|
const next = validateProfileName(name);
|
|
7125
7562
|
if (next === activeProfile()) return;
|
|
7126
7563
|
const sameConfigDirectory = profileConfigDir(next) === profileConfigDir();
|
|
7127
|
-
const target =
|
|
7564
|
+
const target = join11(profileConfigDir(next), "config.json");
|
|
7128
7565
|
try {
|
|
7129
7566
|
const saved = JSON.parse(await readFile3(target, "utf-8"));
|
|
7130
7567
|
if (!saved || typeof saved !== "object" || Array.isArray(saved)) {
|
|
@@ -7145,6 +7582,7 @@ var init_config = __esm({
|
|
|
7145
7582
|
routerCredentialsError: this.routerCredentialsError,
|
|
7146
7583
|
routerFallbackWarning: this.routerFallbackWarning,
|
|
7147
7584
|
sessionOverrides: this.sessionOverrides,
|
|
7585
|
+
restoredSessionSelection: this.restoredSessionSelection,
|
|
7148
7586
|
cliOverrides: this.cliOverrides,
|
|
7149
7587
|
runtimeActivePerProvider: this.runtimeActivePerProvider,
|
|
7150
7588
|
configScope: this.configScope
|
|
@@ -7155,6 +7593,7 @@ var init_config = __esm({
|
|
|
7155
7593
|
this.sessionOverrides = remainingOverrides;
|
|
7156
7594
|
} else {
|
|
7157
7595
|
this.sessionOverrides = {};
|
|
7596
|
+
this.restoredSessionSelection = false;
|
|
7158
7597
|
this.cliOverrides = {};
|
|
7159
7598
|
this.runtimeActivePerProvider = {};
|
|
7160
7599
|
this.configScope = "global";
|
|
@@ -7193,7 +7632,7 @@ var init_config = __esm({
|
|
|
7193
7632
|
}
|
|
7194
7633
|
/** Clear the active profile's saved settings and reset this process's settings view. */
|
|
7195
7634
|
async factoryReset() {
|
|
7196
|
-
for (const path of [configFile(),
|
|
7635
|
+
for (const path of [configFile(), join11(configDir(), "router-auth.json")]) {
|
|
7197
7636
|
try {
|
|
7198
7637
|
await unlink3(path);
|
|
7199
7638
|
} catch (error) {
|
|
@@ -7235,7 +7674,9 @@ var init_config = __esm({
|
|
|
7235
7674
|
cliOverridesWithoutEffort() {
|
|
7236
7675
|
return {
|
|
7237
7676
|
...this.cliOverrides.provider !== void 0 ? { provider: this.cliOverrides.provider } : {},
|
|
7238
|
-
...this.cliOverrides.model !== void 0 ? { model: this.cliOverrides.model } : {}
|
|
7677
|
+
...this.cliOverrides.model !== void 0 ? { model: this.cliOverrides.model } : {},
|
|
7678
|
+
...this.cliOverrides.authMode !== void 0 ? { authMode: this.cliOverrides.authMode } : {},
|
|
7679
|
+
...this.cliOverrides.zergProxyUrl !== void 0 ? { zergProxyUrl: this.cliOverrides.zergProxyUrl } : {}
|
|
7239
7680
|
};
|
|
7240
7681
|
}
|
|
7241
7682
|
getMaxTokensSource() {
|
|
@@ -7250,6 +7691,7 @@ var init_config = __esm({
|
|
|
7250
7691
|
}
|
|
7251
7692
|
clearSessionOverrides() {
|
|
7252
7693
|
this.sessionOverrides = {};
|
|
7694
|
+
this.restoredSessionSelection = false;
|
|
7253
7695
|
}
|
|
7254
7696
|
async withConfigScope(scope, fn) {
|
|
7255
7697
|
const previous = this.configScope;
|
|
@@ -7260,7 +7702,13 @@ var init_config = __esm({
|
|
|
7260
7702
|
this.configScope = previous;
|
|
7261
7703
|
}
|
|
7262
7704
|
}
|
|
7705
|
+
releaseRestoredSelection(key) {
|
|
7706
|
+
if (!this.restoredSessionSelection || !["provider", "model", "authMode", "zergProxyUrl"].includes(key)) return;
|
|
7707
|
+
for (const route of ["provider", "model", "authMode", "zergProxyUrl"]) delete this.sessionOverrides[route];
|
|
7708
|
+
this.restoredSessionSelection = false;
|
|
7709
|
+
}
|
|
7263
7710
|
set(key, value) {
|
|
7711
|
+
this.releaseRestoredSelection(key);
|
|
7264
7712
|
if (this.configScope === "session" || key === "emulationId" && this.profileEmulation) {
|
|
7265
7713
|
this.sessionOverrides[key] = value;
|
|
7266
7714
|
return;
|
|
@@ -7269,10 +7717,12 @@ var init_config = __esm({
|
|
|
7269
7717
|
if (key === "apiKey") this.legacyApiKeyFromEnvironment = false;
|
|
7270
7718
|
}
|
|
7271
7719
|
setGlobal(key, value) {
|
|
7720
|
+
this.releaseRestoredSelection(key);
|
|
7272
7721
|
this.config[key] = value;
|
|
7273
7722
|
if (key === "apiKey") this.legacyApiKeyFromEnvironment = false;
|
|
7274
7723
|
}
|
|
7275
7724
|
setAll(next) {
|
|
7725
|
+
for (const key of Object.keys(next)) this.releaseRestoredSelection(key);
|
|
7276
7726
|
this.config = { ...build_default_config(), ...this.config, ...next };
|
|
7277
7727
|
if (Object.hasOwn(next, "apiKey")) this.legacyApiKeyFromEnvironment = false;
|
|
7278
7728
|
if (this.config.model === "claude-opus-4-5-20250514" || this.config.model === "claude-opus-4-20250514") {
|
|
@@ -7487,8 +7937,28 @@ var init_config = __esm({
|
|
|
7487
7937
|
* Effective Codex effort for the active (or given) provider/model. Priority:
|
|
7488
7938
|
* per-model > per-provider > global. Defaults to the current provider/model.
|
|
7489
7939
|
*/
|
|
7940
|
+
getReasoningWireSurface(provider = this.getProvider(), model = this.getModel()) {
|
|
7941
|
+
if (provider === "openai_compatible") return "chat_tools";
|
|
7942
|
+
if (modelContract(provider, model)?.chatToolReasoningEfforts === void 0) return "native_api";
|
|
7943
|
+
try {
|
|
7944
|
+
return this.resolveLLMBackendConfig({ provider, model }).useProxy ? "chat_tools" : "native_api";
|
|
7945
|
+
} catch (error) {
|
|
7946
|
+
if (error instanceof RouterConfigurationError) return "chat_tools";
|
|
7947
|
+
throw error;
|
|
7948
|
+
}
|
|
7949
|
+
}
|
|
7490
7950
|
getCodexEffort(provider, model) {
|
|
7491
|
-
|
|
7951
|
+
const selectedProvider = provider ?? this.getProvider();
|
|
7952
|
+
const selectedModel = model ?? this.getModel();
|
|
7953
|
+
const catalog = this.getRoutedModelCatalog();
|
|
7954
|
+
const capabilities = catalog ? resolveRouterModel(catalog, selectedProvider, selectedModel)?.capabilities : void 0;
|
|
7955
|
+
return resolveCodexEffort(this.get(), selectedProvider, selectedModel, capabilities ?? this.getReasoningWireSurface(selectedProvider, selectedModel));
|
|
7956
|
+
}
|
|
7957
|
+
/** The active transport owns the model's choices, aliases and advertised default. */
|
|
7958
|
+
getReasoningContract(provider = this.getProvider(), model = this.getModel()) {
|
|
7959
|
+
const catalog = this.getRoutedModelCatalog();
|
|
7960
|
+
if (catalog?.version === 1) return resolveRouterModel(catalog, provider, model)?.capabilities?.reasoning ?? [];
|
|
7961
|
+
return this.getReasoningWireSurface(provider, model);
|
|
7492
7962
|
}
|
|
7493
7963
|
/** Saved effort the active (or given) model rejects; undefined when it applies. */
|
|
7494
7964
|
getUnsupportedCodexEffort(provider, model) {
|
|
@@ -7647,6 +8117,69 @@ var init_config = __esm({
|
|
|
7647
8117
|
authMode: this.getAuthMode()
|
|
7648
8118
|
};
|
|
7649
8119
|
}
|
|
8120
|
+
restoreSessionSelection(metadata) {
|
|
8121
|
+
if (!metadata.authMode || this.cliOverrides.provider || this.cliOverrides.model || metadata.configProfile && metadata.configProfile !== activeProfile()) return;
|
|
8122
|
+
this.restoredSessionSelection = true;
|
|
8123
|
+
this.sessionOverrides.provider = metadata.provider;
|
|
8124
|
+
this.sessionOverrides.model = metadata.model;
|
|
8125
|
+
this.sessionOverrides.authMode = metadata.authMode;
|
|
8126
|
+
if (metadata.authMode !== "direct" && metadata.routerOrigin && !routerOriginFromEnvironment()) this.sessionOverrides.zergProxyUrl = metadata.routerOrigin;
|
|
8127
|
+
}
|
|
8128
|
+
getRouterCatalogConnection(destination = this.get().zergProxyUrl) {
|
|
8129
|
+
const origin = normalizedOrigin(destination);
|
|
8130
|
+
if (!origin) return void 0;
|
|
8131
|
+
const credentials = this.routerCredentials;
|
|
8132
|
+
if (credentials && !this.routerCredentialsError && credentials.origin === origin) {
|
|
8133
|
+
return { origin, token: credentials.token, workspaceId: credentials.workspaceId };
|
|
8134
|
+
}
|
|
8135
|
+
const token = origin === this.deriveZRouterUrl(this.getApiBaseUrl()) ? this.getAuthToken() : void 0;
|
|
8136
|
+
return token ? { origin, token, workspaceId: this.getActiveWorkspace()?.id.toString() } : void 0;
|
|
8137
|
+
}
|
|
8138
|
+
/** New children use configured routing, not a parent's restored inference route. */
|
|
8139
|
+
getChildAuthMode() {
|
|
8140
|
+
if (!this.restoredSessionSelection) return this.getAuthMode();
|
|
8141
|
+
const { authMode: _restored, ...session } = this.sessionOverrides;
|
|
8142
|
+
return resolveAuthMode({ ...this.config, ...session, ...this.cliOverrides });
|
|
8143
|
+
}
|
|
8144
|
+
async adoptRouterCatalog(catalog) {
|
|
8145
|
+
if (catalog.version !== 1 || catalog.authRequired || this.getResolvedAuthMode() !== "zrouter") return;
|
|
8146
|
+
const provider = this.getProvider(), model = this.getModel();
|
|
8147
|
+
const row = resolveRouterModel(catalog, provider, model);
|
|
8148
|
+
if (!row || row.id === model && row.owned_by === provider) return;
|
|
8149
|
+
if (this.cliOverrides.provider || this.cliOverrides.model) {
|
|
8150
|
+
this.cliOverrides.provider = row.owned_by;
|
|
8151
|
+
this.cliOverrides.model = row.id;
|
|
8152
|
+
} else if (this.sessionOverrides.provider || this.sessionOverrides.model) {
|
|
8153
|
+
this.sessionOverrides.provider = row.owned_by;
|
|
8154
|
+
this.sessionOverrides.model = row.id;
|
|
8155
|
+
} else {
|
|
8156
|
+
this.config.provider = row.owned_by;
|
|
8157
|
+
this.config.model = row.id;
|
|
8158
|
+
await this.save();
|
|
8159
|
+
}
|
|
8160
|
+
}
|
|
8161
|
+
getRouterCatalog() {
|
|
8162
|
+
const connection = this.getRouterCatalogConnection();
|
|
8163
|
+
return connection ? readRouterCatalog(connection) : void 0;
|
|
8164
|
+
}
|
|
8165
|
+
getResolvedAuthMode() {
|
|
8166
|
+
const mode = this.getAuthMode();
|
|
8167
|
+
if (mode !== "auto") return mode;
|
|
8168
|
+
try {
|
|
8169
|
+
return this.resolveLLMBackendConfig().useProxy ? "zrouter" : "direct";
|
|
8170
|
+
} catch {
|
|
8171
|
+
return mode;
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
8174
|
+
getRoutedModelCatalog() {
|
|
8175
|
+
if (isLocalSubscriptionProvider(this.getProvider())) return void 0;
|
|
8176
|
+
return this.getResolvedAuthMode() === "zrouter" ? this.getRouterCatalog() : void 0;
|
|
8177
|
+
}
|
|
8178
|
+
getModelContextWindow(model = this.getModel(), provider = this.getProvider()) {
|
|
8179
|
+
const catalog = this.getRoutedModelCatalog();
|
|
8180
|
+
if (catalog?.version !== 1) return void 0;
|
|
8181
|
+
return resolveRouterModel(catalog, provider, model)?.capabilities?.context_window ?? null;
|
|
8182
|
+
}
|
|
7650
8183
|
/**
|
|
7651
8184
|
* Resolve everything a backend factory needs into one struct. Folds in the
|
|
7652
8185
|
* provider/model override precedence, the direct-key precedence
|
|
@@ -7661,17 +8194,16 @@ var init_config = __esm({
|
|
|
7661
8194
|
*
|
|
7662
8195
|
* Reads through `get()` and the env-aware getters (never raw `this.config`)
|
|
7663
8196
|
* so cli/session overrides stay honored. `apiKey` is the DIRECT provider key;
|
|
7664
|
-
* `authToken`/`useProxy` describe the proxy route separately
|
|
7665
|
-
* still prefer a direct key (e.g. Gemini) over the proxy.
|
|
8197
|
+
* `authToken`/`useProxy` describe the selected proxy route separately.
|
|
7666
8198
|
*/
|
|
7667
8199
|
resolveLLMBackendConfig(opts = {}) {
|
|
7668
8200
|
const cfg = opts.config ?? this.get();
|
|
7669
8201
|
const repoOverride = !opts.provider && !opts.model && !this.hasExplicitModelOverride() && opts.cwd ? resolveRepoModelOverride(opts.cwd) : null;
|
|
7670
|
-
|
|
8202
|
+
let provider = repoOverride?.provider ?? normalizeProviderId(opts.provider || cfg.provider || this.getProvider());
|
|
7671
8203
|
const configProvider = cfg.provider ? normalizeProviderId(cfg.provider) : void 0;
|
|
7672
|
-
|
|
7673
|
-
const authMode = resolveAuthMode(cfg);
|
|
7674
|
-
const proxyUrl = cfg.zergProxyUrl;
|
|
8204
|
+
let model = repoOverride?.model ?? opts.model ?? (configProvider === provider ? cfg.model : void 0) ?? getDefaultModelForProvider(provider);
|
|
8205
|
+
const authMode = isLocalSubscriptionProvider(provider) ? "direct" : resolveAuthMode(cfg);
|
|
8206
|
+
const proxyUrl = normalizedOrigin(cfg.zergProxyUrl);
|
|
7675
8207
|
const platformProxyUrl = this.deriveZRouterUrl(this.getApiBaseUrl());
|
|
7676
8208
|
let authToken = provider !== "modal" && proxyUrl?.replace(/\/+$/, "") === platformProxyUrl ? this.getAuthToken() : void 0;
|
|
7677
8209
|
let routerError = this.routerCredentialsError;
|
|
@@ -7704,7 +8236,16 @@ var init_config = __esm({
|
|
|
7704
8236
|
const apiKey = opts.apiKeyOverride || providerScopedKey || this.getApiKey(provider);
|
|
7705
8237
|
const rawCompatBaseUrl = opts.compatBaseUrlOverride || this.getOpenAICompatibleSettings(cfg).baseUrl || cfg.openaiCompatibleBaseUrl;
|
|
7706
8238
|
const proxyAvailable = Boolean(proxyUrl && authToken);
|
|
7707
|
-
const
|
|
8239
|
+
const localSubscription = isLocalSubscriptionProvider(provider);
|
|
8240
|
+
const useProxy = authMode === "direct" ? false : proxyAvailable && !localSubscription && !(authMode === "auto" && provider === "gemini" && Boolean(apiKey));
|
|
8241
|
+
if (useProxy) {
|
|
8242
|
+
const catalog = readRouterCatalog({ origin: proxyUrl, token: authToken, workspaceId: this.getRouterCatalogConnection(proxyUrl)?.workspaceId });
|
|
8243
|
+
const descriptor2 = catalog?.version === 1 ? resolveRouterModel(catalog, provider, model) : void 0;
|
|
8244
|
+
if (descriptor2) {
|
|
8245
|
+
provider = descriptor2.owned_by;
|
|
8246
|
+
model = descriptor2.id;
|
|
8247
|
+
}
|
|
8248
|
+
}
|
|
7708
8249
|
const compatBaseUrl = provider === "openai_compatible" && rawCompatBaseUrl ? compatEndpoint(rawCompatBaseUrl, { apiKey }) : rawCompatBaseUrl;
|
|
7709
8250
|
const activeAccount = resolveActiveAccount(cfg, provider);
|
|
7710
8251
|
const accountOptions = activeAccount ? accountSourceToBackendOptions(activeAccount.source) : {};
|
|
@@ -7723,7 +8264,7 @@ var init_config = __esm({
|
|
|
7723
8264
|
codexHome: accountOptions.codexHome,
|
|
7724
8265
|
codexAuthFilePath: accountOptions.codexAuthFilePath,
|
|
7725
8266
|
kimiCredsFilePath: accountOptions.kimiCredsFilePath,
|
|
7726
|
-
codexEffort:
|
|
8267
|
+
codexEffort: resolveCodexEffort(cfg, provider, model, (useProxy ? this.getRouterCatalog()?.models.find((row) => row.id === model && row.owned_by === provider)?.capabilities : void 0) ?? (useProxy || provider === "openai_compatible" ? "chat_tools" : "native_api"))
|
|
7727
8268
|
};
|
|
7728
8269
|
}
|
|
7729
8270
|
getEnvKey(provider) {
|
|
@@ -7743,6 +8284,8 @@ var init_config = __esm({
|
|
|
7743
8284
|
return process.env.OPENAI_API_KEY;
|
|
7744
8285
|
case "deepseek":
|
|
7745
8286
|
return process.env.DEEPSEEK_API_KEY;
|
|
8287
|
+
case "fireworks":
|
|
8288
|
+
return process.env.FIREWORKS_API_KEY;
|
|
7746
8289
|
case "gemini":
|
|
7747
8290
|
return process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
|
|
7748
8291
|
case "inception":
|
|
@@ -8120,7 +8663,7 @@ var init_zerg_api = __esm({
|
|
|
8120
8663
|
});
|
|
8121
8664
|
|
|
8122
8665
|
// src/agent/backends/zrouter_stream.ts
|
|
8123
|
-
import { randomUUID as
|
|
8666
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
8124
8667
|
function isPinnableDecoration(value) {
|
|
8125
8668
|
return value !== void 0 && PINNABLE_DECORATION.test(value);
|
|
8126
8669
|
}
|
|
@@ -8137,7 +8680,7 @@ function resolveReconnectPolicy() {
|
|
|
8137
8680
|
};
|
|
8138
8681
|
}
|
|
8139
8682
|
function withTransportTurn(request) {
|
|
8140
|
-
return request.transportTurnId ? request : { ...request, transportTurnId:
|
|
8683
|
+
return request.transportTurnId ? request : { ...request, transportTurnId: randomUUID5() };
|
|
8141
8684
|
}
|
|
8142
8685
|
async function fetchWithHeadersTimeout(fetcher, input, init, timeoutMs) {
|
|
8143
8686
|
const timeoutController = new AbortController();
|
|
@@ -8172,6 +8715,14 @@ async function waitForReconnect(delayMs, signal) {
|
|
|
8172
8715
|
signal?.addEventListener("abort", abort, { once: true });
|
|
8173
8716
|
});
|
|
8174
8717
|
}
|
|
8718
|
+
function failureHeaderSuffix(response) {
|
|
8719
|
+
const parts = [];
|
|
8720
|
+
for (const name of ["fly-request-id", "x-request-id", "cf-ray", "x-zerg-error-code"]) {
|
|
8721
|
+
const value = response.headers.get(name)?.trim();
|
|
8722
|
+
if (value && value.length <= 128 && !/[\r\n\0]/.test(value)) parts.push(`${name}=${value}`);
|
|
8723
|
+
}
|
|
8724
|
+
return parts.length > 0 ? ` [${parts.join(" ")}]` : "";
|
|
8725
|
+
}
|
|
8175
8726
|
function isRetryableResumeStatus(error) {
|
|
8176
8727
|
if (!(error instanceof Error)) return false;
|
|
8177
8728
|
const match = error.message.match(/ZRouter API error \((\d{3})\)/);
|
|
@@ -8190,10 +8741,22 @@ function normalizeHeaderValue(value, label, maxLength) {
|
|
|
8190
8741
|
}
|
|
8191
8742
|
return normalized;
|
|
8192
8743
|
}
|
|
8744
|
+
function chatOnlyRequest(request) {
|
|
8745
|
+
return { ...request, tools: [], messages: request.messages.map((message) => ({
|
|
8746
|
+
...message,
|
|
8747
|
+
content: typeof message.content === "string" ? message.content : message.content.map((block) => {
|
|
8748
|
+
if (block.type === "tool_use") return { type: "text", text: `Previous tool call ${block.name} (${block.id}): ${JSON.stringify(block.input)}` };
|
|
8749
|
+
if (block.type === "tool_result") return { type: "text", text: `Previous tool result (${block.tool_use_id}): ${typeof block.content === "string" ? block.content : block.content.map((part) => part.type === "text" ? part.text : "[image]").join("\n")}` };
|
|
8750
|
+
return block;
|
|
8751
|
+
})
|
|
8752
|
+
})) };
|
|
8753
|
+
}
|
|
8193
8754
|
var ZROUTER_HEADERS_TIMEOUT_MS, routerClientSession, ROUTER_PIN_MAX_LENGTH, PINNABLE_DECORATION, DEFAULT_RECONNECT_ATTEMPTS, DEFAULT_RECONNECT_BASE_MS, DEFAULT_RECONNECT_CAP_MS, MAX_RECONNECT_ATTEMPTS, MAX_RECONNECT_MS, ZRouterStreamBackend;
|
|
8194
8755
|
var init_zrouter_stream = __esm({
|
|
8195
8756
|
"src/agent/backends/zrouter_stream.ts"() {
|
|
8196
8757
|
"use strict";
|
|
8758
|
+
init_model_contracts();
|
|
8759
|
+
init_router_catalog();
|
|
8197
8760
|
init_request_metrics();
|
|
8198
8761
|
init_sse();
|
|
8199
8762
|
init_openai_format();
|
|
@@ -8205,15 +8768,16 @@ var init_zrouter_stream = __esm({
|
|
|
8205
8768
|
init_version();
|
|
8206
8769
|
init_transport_errors();
|
|
8207
8770
|
ZROUTER_HEADERS_TIMEOUT_MS = 9e4;
|
|
8208
|
-
routerClientSession =
|
|
8771
|
+
routerClientSession = randomUUID5();
|
|
8209
8772
|
ROUTER_PIN_MAX_LENGTH = 128;
|
|
8210
8773
|
PINNABLE_DECORATION = /^[A-Za-z0-9._:-]{1,64}$/;
|
|
8211
|
-
DEFAULT_RECONNECT_ATTEMPTS =
|
|
8212
|
-
DEFAULT_RECONNECT_BASE_MS =
|
|
8213
|
-
DEFAULT_RECONNECT_CAP_MS =
|
|
8214
|
-
MAX_RECONNECT_ATTEMPTS =
|
|
8774
|
+
DEFAULT_RECONNECT_ATTEMPTS = 120;
|
|
8775
|
+
DEFAULT_RECONNECT_BASE_MS = 1e3;
|
|
8776
|
+
DEFAULT_RECONNECT_CAP_MS = 3e4;
|
|
8777
|
+
MAX_RECONNECT_ATTEMPTS = 120;
|
|
8215
8778
|
MAX_RECONNECT_MS = 3e5;
|
|
8216
8779
|
ZRouterStreamBackend = class {
|
|
8780
|
+
catalog;
|
|
8217
8781
|
apiKey;
|
|
8218
8782
|
proxyUrl;
|
|
8219
8783
|
provider;
|
|
@@ -8222,6 +8786,7 @@ var init_zrouter_stream = __esm({
|
|
|
8222
8786
|
conversationId;
|
|
8223
8787
|
clientName;
|
|
8224
8788
|
constructor(config) {
|
|
8789
|
+
this.catalog = config.catalog ? structuredClone(config.catalog) : void 0;
|
|
8225
8790
|
this.apiKey = config.apiKey;
|
|
8226
8791
|
this.proxyUrl = config.proxyUrl.replace(/\/+$/, "");
|
|
8227
8792
|
this.provider = config.provider;
|
|
@@ -8242,10 +8807,38 @@ var init_zrouter_stream = __esm({
|
|
|
8242
8807
|
handlesTransportRetries() {
|
|
8243
8808
|
return true;
|
|
8244
8809
|
}
|
|
8810
|
+
getModelCapabilities(model) {
|
|
8811
|
+
return this.catalog?.version === 1 ? resolveRouterModel(this.catalog, this.provider, model)?.capabilities : void 0;
|
|
8812
|
+
}
|
|
8245
8813
|
buildOpenAIBody(request) {
|
|
8814
|
+
if (this.catalog?.version === 1) {
|
|
8815
|
+
const descriptor2 = resolveRouterModel(this.catalog, this.provider, request.model);
|
|
8816
|
+
if (!descriptor2?.capabilities?.chat) throw new Error("This model is no longer in the Router chat catalog. Refresh /model.");
|
|
8817
|
+
const caps = descriptor2.capabilities;
|
|
8818
|
+
if (request.codexEffort && caps.reasoning && !caps.reasoning.choices.includes(request.codexEffort)) {
|
|
8819
|
+
throw new Error(`Unsupported reasoning effort: ${request.codexEffort}`);
|
|
8820
|
+
}
|
|
8821
|
+
if (request.maxTokens !== void 0 && caps.max_output_tokens !== void 0 && request.maxTokens > caps.max_output_tokens) {
|
|
8822
|
+
throw new Error(`Max output tokens exceeds the advertised limit (${caps.max_output_tokens}).`);
|
|
8823
|
+
}
|
|
8824
|
+
if (caps.images === false && request.messages.some((message) => Array.isArray(message.content) && message.content.some((block) => block.type === "image" || block.type === "video"))) throw new Error("This model does not support images.");
|
|
8825
|
+
const prepared = caps.tools === false ? chatOnlyRequest(request) : request;
|
|
8826
|
+
return {
|
|
8827
|
+
provider: descriptor2.owned_by,
|
|
8828
|
+
model: descriptor2.id,
|
|
8829
|
+
...request.routePlan ? { route: request.routePlan } : {},
|
|
8830
|
+
...request.maxTokens === void 0 ? {} : { max_output_tokens: request.maxTokens },
|
|
8831
|
+
...caps.reasoning && request.codexEffort ? { reasoning_effort: request.codexEffort } : {},
|
|
8832
|
+
messages: buildOpenAIMessages(prepared),
|
|
8833
|
+
...prepared.tools.length ? { tools: buildOpenAIToolDefs(prepared.tools) } : {}
|
|
8834
|
+
};
|
|
8835
|
+
}
|
|
8246
8836
|
if (this.provider === "modal" && !/^modal\//i.test(request.model)) {
|
|
8247
8837
|
request = { ...request, model: `modal/${request.model}` };
|
|
8248
8838
|
}
|
|
8839
|
+
if (this.provider === "fireworks") {
|
|
8840
|
+
request = { ...request, model: `fireworks/${normalizeContractModel("fireworks", request.model)}` };
|
|
8841
|
+
}
|
|
8249
8842
|
const useCompletionTokens = /^o\d/.test(request.model) || /^gpt-5/.test(request.model) || isKimiModel(request.model);
|
|
8250
8843
|
const isGpt4o = request.model.startsWith("gpt-4o");
|
|
8251
8844
|
const limit = isGpt4o ? 16384 : isModalDeepSeekFlashModel(request.model) ? MODAL_DEEPSEEK_FLASH_MAX_OUTPUT : isDeepSeekFlashModel(request.model) ? DEEPSEEK_FLASH_MAX_OUTPUT : Infinity;
|
|
@@ -8256,18 +8849,32 @@ var init_zrouter_stream = __esm({
|
|
|
8256
8849
|
model: request.model,
|
|
8257
8850
|
...request.routePlan ? { route: request.routePlan } : {},
|
|
8258
8851
|
...tokenParam,
|
|
8259
|
-
|
|
8260
|
-
// selection applied on a direct key and vanished through the proxy.
|
|
8261
|
-
// No-op for every non-Kimi model.
|
|
8262
|
-
// Modal uses Kimi's effort ladder but keeps its own max_tokens contract.
|
|
8263
|
-
...buildKimiRequestParams(this.provider === "modal" ? { ...request, model: request.model.slice("modal/".length) } : request),
|
|
8264
|
-
...deepseekRequestParams(request),
|
|
8852
|
+
...request.codexEffort && modelContract(this.provider, request.model, "chat_tools")?.reasoningEfforts.includes(request.codexEffort) ? { reasoning_effort: request.codexEffort } : {},
|
|
8265
8853
|
messages: buildOpenAIMessages(request),
|
|
8266
8854
|
...request.tools.length > 0 ? { tools: buildOpenAIToolDefs(request.tools) } : {}
|
|
8267
8855
|
};
|
|
8268
8856
|
}
|
|
8269
|
-
|
|
8270
|
-
|
|
8857
|
+
serializeBody(request, stream = false) {
|
|
8858
|
+
const body = {
|
|
8859
|
+
...this.buildOpenAIBody(request),
|
|
8860
|
+
...stream ? { stream: true } : {}
|
|
8861
|
+
};
|
|
8862
|
+
const serialized = JSON.stringify(body);
|
|
8863
|
+
if (body.model === "modal/deepseek-v4.1-flash" || body.model === "fireworks/deepseek-v4p1-flash") {
|
|
8864
|
+
const pending = [JSON.parse(serialized)];
|
|
8865
|
+
let values = 1;
|
|
8866
|
+
while (pending.length > 0) {
|
|
8867
|
+
const value = pending.pop();
|
|
8868
|
+
if (value === null || typeof value !== "object") continue;
|
|
8869
|
+
for (const child of Object.values(value)) {
|
|
8870
|
+
if (++values > 1e4) {
|
|
8871
|
+
throw new Error("Prompt is too long for Router's context structure limit (10,000 JSON values). Compact the conversation before retrying.");
|
|
8872
|
+
}
|
|
8873
|
+
pending.push(child);
|
|
8874
|
+
}
|
|
8875
|
+
}
|
|
8876
|
+
}
|
|
8877
|
+
return serialized;
|
|
8271
8878
|
}
|
|
8272
8879
|
async buildHeaders(request) {
|
|
8273
8880
|
const token = this.authTokenProvider ? await this.authTokenProvider() : this.apiKey;
|
|
@@ -8278,6 +8885,7 @@ var init_zrouter_stream = __esm({
|
|
|
8278
8885
|
const conversationPin = this.conversationPin(request);
|
|
8279
8886
|
return {
|
|
8280
8887
|
"Content-Type": "application/json",
|
|
8888
|
+
...this.catalog?.version === 1 ? { "X-Zerg-Model-Contract": "1" } : {},
|
|
8281
8889
|
"Authorization": `Bearer ${normalizedToken}`,
|
|
8282
8890
|
"X-Zerg-Client": this.clientName,
|
|
8283
8891
|
"X-Zerg-Client-Version": getVersion(),
|
|
@@ -8319,7 +8927,7 @@ var init_zrouter_stream = __esm({
|
|
|
8319
8927
|
return measureResponse(routedRequest, (fetcher) => this.generateResponse(routedRequest, fetcher));
|
|
8320
8928
|
}
|
|
8321
8929
|
async generateResponse(request, fetcher) {
|
|
8322
|
-
const body = this.
|
|
8930
|
+
const body = this.serializeBody(request);
|
|
8323
8931
|
const headers = await this.buildHeaders(request);
|
|
8324
8932
|
runtimeDiag("info", `[ztc] zrouter dispatch ${JSON.stringify({
|
|
8325
8933
|
endpoint: this.endpointFor(),
|
|
@@ -8330,15 +8938,19 @@ var init_zrouter_stream = __esm({
|
|
|
8330
8938
|
const response = await fetcher(this.endpointFor(), {
|
|
8331
8939
|
method: "POST",
|
|
8332
8940
|
headers,
|
|
8333
|
-
body
|
|
8941
|
+
body,
|
|
8334
8942
|
signal: request.signal
|
|
8335
8943
|
});
|
|
8336
8944
|
if (!response.ok) {
|
|
8337
8945
|
const errorText = await response.text();
|
|
8338
|
-
throw new Error(`ZRouter API error (${response.status}): ${errorText}`);
|
|
8946
|
+
throw new Error(`ZRouter API error (${response.status}): ${errorText}${failureHeaderSuffix(response)}`);
|
|
8339
8947
|
}
|
|
8340
8948
|
const data = await response.json();
|
|
8341
|
-
|
|
8949
|
+
const parsed = this.parseOpenAIResponse(data);
|
|
8950
|
+
if (this.getModelCapabilities(request.model)?.tools === false && parsed.content.some((block) => block.type === "tool_use")) {
|
|
8951
|
+
throw new Error("Chat-only model returned tools; execution is disabled.");
|
|
8952
|
+
}
|
|
8953
|
+
return parsed;
|
|
8342
8954
|
}
|
|
8343
8955
|
parseOpenAIResponse(data) {
|
|
8344
8956
|
const choices = data.choices || [];
|
|
@@ -8376,12 +8988,15 @@ var init_zrouter_stream = __esm({
|
|
|
8376
8988
|
return measureStream(routedRequest, (fetcher) => this.streamResponse(routedRequest, fetcher));
|
|
8377
8989
|
}
|
|
8378
8990
|
async *streamResponse(request, fetcher) {
|
|
8379
|
-
const body =
|
|
8991
|
+
const body = this.serializeBody(request, true);
|
|
8380
8992
|
const mapEvent = createZrouterEventMapper();
|
|
8381
8993
|
let resumeAfter;
|
|
8382
8994
|
let emittedMappedEvent = false;
|
|
8383
8995
|
let resumeSupported = false;
|
|
8384
8996
|
const policy = resolveReconnectPolicy();
|
|
8997
|
+
let reconnectStarted;
|
|
8998
|
+
const budget = () => resumeAfter ? 3e5 : 3e4;
|
|
8999
|
+
const remaining = () => budget() - (reconnectStarted === void 0 ? 0 : Date.now() - reconnectStarted);
|
|
8385
9000
|
for (let attempt = 1; attempt <= policy.attempts; attempt++) {
|
|
8386
9001
|
try {
|
|
8387
9002
|
const headers = await this.buildHeaders(request);
|
|
@@ -8389,12 +9004,12 @@ var init_zrouter_stream = __esm({
|
|
|
8389
9004
|
const response = await fetchWithHeadersTimeout(fetcher, this.endpointFor(), {
|
|
8390
9005
|
method: "POST",
|
|
8391
9006
|
headers,
|
|
8392
|
-
body
|
|
9007
|
+
body,
|
|
8393
9008
|
signal: request.signal
|
|
8394
|
-
}, ZROUTER_HEADERS_TIMEOUT_MS);
|
|
9009
|
+
}, Math.min(ZROUTER_HEADERS_TIMEOUT_MS, Math.max(1, remaining())));
|
|
8395
9010
|
if (!response.ok) {
|
|
8396
9011
|
const errorText = await response.text();
|
|
8397
|
-
throw new Error(`ZRouter API error (${response.status}): ${errorText}`);
|
|
9012
|
+
throw new Error(`ZRouter API error (${response.status}): ${errorText}${failureHeaderSuffix(response)}`);
|
|
8398
9013
|
}
|
|
8399
9014
|
if (!response.body) {
|
|
8400
9015
|
throw new Error("ZRouter API error: no response body for streaming request");
|
|
@@ -8415,6 +9030,9 @@ var init_zrouter_stream = __esm({
|
|
|
8415
9030
|
throw new Error(`ZRouter API error (${status}): ${JSON.stringify(ev.body ?? {})}`);
|
|
8416
9031
|
}
|
|
8417
9032
|
const mapped = mapEvent(ev);
|
|
9033
|
+
if (this.getModelCapabilities(request.model)?.tools === false && mapped.some((event2) => event2.type.startsWith("tool_use"))) {
|
|
9034
|
+
throw new Error("Chat-only model returned tools; execution is disabled.");
|
|
9035
|
+
}
|
|
8418
9036
|
if (mapped.length > 0) {
|
|
8419
9037
|
if (mapped.some((event2) => event2.type !== "heartbeat")) emittedMappedEvent = true;
|
|
8420
9038
|
if (!validEventId) resumeSupported = false;
|
|
@@ -8427,12 +9045,16 @@ var init_zrouter_stream = __esm({
|
|
|
8427
9045
|
if (request.signal?.aborted || !retryable || emittedMappedEvent && (!resumeSupported || !resumeAfter)) {
|
|
8428
9046
|
throw error;
|
|
8429
9047
|
}
|
|
8430
|
-
|
|
8431
|
-
const
|
|
9048
|
+
reconnectStarted ??= Date.now();
|
|
9049
|
+
const attempts = resumeAfter ? policy.attempts : Math.min(6, policy.attempts);
|
|
9050
|
+
if (attempt >= attempts || remaining() <= 0) throw error;
|
|
9051
|
+
const delayMs = Math.min(reconnectDelay(policy, attempt), remaining());
|
|
8432
9052
|
const reason = error instanceof Error ? error.message : String(error);
|
|
8433
9053
|
runtimeDiag("warn", `[ztc] zrouter stream dropped (${reason}); reconnecting in ${delayMs}ms (attempt ${attempt + 1}/${policy.attempts})`);
|
|
8434
|
-
|
|
9054
|
+
const publicReason = isRetryableResumeStatus(error) ? `Router temporarily unavailable ${reason.match(/\(\d{3}\)/)?.[0] ?? ""}. Resuming the response.` : reason;
|
|
9055
|
+
request.onTransportRetry?.({ attempt, maxAttempts: attempts, delayMs, reason: publicReason });
|
|
8435
9056
|
await waitForReconnect(delayMs, request.signal);
|
|
9057
|
+
if (remaining() <= 0) throw error;
|
|
8436
9058
|
}
|
|
8437
9059
|
}
|
|
8438
9060
|
}
|
|
@@ -8759,10 +9381,17 @@ function createBackendForProvider(provider, opts) {
|
|
|
8759
9381
|
return traced(provider, new KimiBackend({ apiKey: opts.apiKey }));
|
|
8760
9382
|
case "deepseek":
|
|
8761
9383
|
return traced(provider, new OpenAICompatibleBackend({
|
|
9384
|
+
provider: "deepseek",
|
|
8762
9385
|
apiKey: opts.apiKey,
|
|
8763
9386
|
baseUrl: opts.baseUrl || "https://api.deepseek.com/v1",
|
|
8764
9387
|
requestBodyExtras: deepseekRequestParams
|
|
8765
9388
|
}));
|
|
9389
|
+
case "fireworks":
|
|
9390
|
+
return traced(provider, new OpenAICompatibleBackend({
|
|
9391
|
+
apiKey: opts.apiKey,
|
|
9392
|
+
baseUrl: opts.baseUrl || "https://api.fireworks.ai/inference/v1",
|
|
9393
|
+
provider: "fireworks"
|
|
9394
|
+
}));
|
|
8766
9395
|
case "clarifai":
|
|
8767
9396
|
return traced(provider, new ClarifaiBackend({ apiKey: opts.apiKey, headers: opts.extraHeaders }));
|
|
8768
9397
|
case CODEX_APP_SERVER_PROVIDER:
|
|
@@ -8802,8 +9431,9 @@ function createBackendForProvider(provider, opts) {
|
|
|
8802
9431
|
}
|
|
8803
9432
|
case "anthropic":
|
|
8804
9433
|
case "claude":
|
|
8805
|
-
default:
|
|
8806
9434
|
return traced(provider, new AnthropicBackend({ apiKey: opts.apiKey, apiEndpoint: opts.apiEndpoint }));
|
|
9435
|
+
default:
|
|
9436
|
+
throw new Error(`Unknown provider: ${provider}. Select a Router integration or a supported direct provider.`);
|
|
8807
9437
|
}
|
|
8808
9438
|
}
|
|
8809
9439
|
var TracedBackend;
|
|
@@ -8850,6 +9480,9 @@ var init_backends = __esm({
|
|
|
8850
9480
|
}
|
|
8851
9481
|
provider;
|
|
8852
9482
|
backend;
|
|
9483
|
+
getModelCapabilities(model) {
|
|
9484
|
+
return this.backend.getModelCapabilities?.(model);
|
|
9485
|
+
}
|
|
8853
9486
|
async steerUserMessage(message) {
|
|
8854
9487
|
return this.backend.steerUserMessage?.(message) ?? false;
|
|
8855
9488
|
}
|
|
@@ -9315,8 +9948,8 @@ init_backends();
|
|
|
9315
9948
|
init_token_usage();
|
|
9316
9949
|
init_transport_errors();
|
|
9317
9950
|
init_defaults();
|
|
9318
|
-
import { randomUUID as
|
|
9319
|
-
import { existsSync as existsSync5, readFileSync as
|
|
9951
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
9952
|
+
import { existsSync as existsSync5, readFileSync as readFileSync9 } from "fs";
|
|
9320
9953
|
import { extname } from "path";
|
|
9321
9954
|
|
|
9322
9955
|
// src/config/api_retry.ts
|
|
@@ -9427,10 +10060,10 @@ function createRecoveryGuard(settings) {
|
|
|
9427
10060
|
}
|
|
9428
10061
|
|
|
9429
10062
|
// src/agent/runtime/command_jobs.ts
|
|
9430
|
-
import { randomUUID as
|
|
9431
|
-
import { appendFileSync as appendFileSync4, closeSync, mkdirSync as mkdirSync3, openSync, readFileSync as
|
|
10063
|
+
import { randomUUID as randomUUID6, createHash as createHash4 } from "node:crypto";
|
|
10064
|
+
import { appendFileSync as appendFileSync4, closeSync, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync7, readSync, readdirSync, rmSync, rmdirSync, statSync as statSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
9432
10065
|
import { homedir as homedir6 } from "node:os";
|
|
9433
|
-
import { join as
|
|
10066
|
+
import { join as join12 } from "node:path";
|
|
9434
10067
|
|
|
9435
10068
|
// src/utils/subprocess_env.ts
|
|
9436
10069
|
var USER_SUBPROCESS_STRIPPED_ZTC_ENV = [
|
|
@@ -9466,14 +10099,14 @@ var MAX_LOG_BYTES = 16 * 1024 * 1024;
|
|
|
9466
10099
|
var RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
9467
10100
|
var sessions = /* @__PURE__ */ new Map();
|
|
9468
10101
|
function directory(sessionId) {
|
|
9469
|
-
return
|
|
9470
|
-
process.env.ZTC_CONFIG_DIR ||
|
|
10102
|
+
return join12(
|
|
10103
|
+
process.env.ZTC_CONFIG_DIR || join12(homedir6(), ".ztc"),
|
|
9471
10104
|
"command-jobs",
|
|
9472
|
-
|
|
10105
|
+
createHash4("sha256").update(sessionId).digest("hex").slice(0, 32)
|
|
9473
10106
|
);
|
|
9474
10107
|
}
|
|
9475
10108
|
function save(sessionId, receipt) {
|
|
9476
|
-
writeFileSync5(
|
|
10109
|
+
writeFileSync5(join12(directory(sessionId), `${receipt.job_id}.json`), JSON.stringify(receipt), { mode: 384 });
|
|
9477
10110
|
}
|
|
9478
10111
|
function resolveJob(sessionId, jobId) {
|
|
9479
10112
|
if (!/^[0-9a-f-]{36}$/.test(jobId)) throw new Error("Command job not found in this session");
|
|
@@ -9481,7 +10114,7 @@ function resolveJob(sessionId, jobId) {
|
|
|
9481
10114
|
if (live) return live;
|
|
9482
10115
|
let receipt;
|
|
9483
10116
|
try {
|
|
9484
|
-
receipt = JSON.parse(
|
|
10117
|
+
receipt = JSON.parse(readFileSync7(join12(directory(sessionId), `${jobId}.json`), "utf8"));
|
|
9485
10118
|
} catch {
|
|
9486
10119
|
throw new Error("Command job not found in this session");
|
|
9487
10120
|
}
|
|
@@ -9489,7 +10122,7 @@ function resolveJob(sessionId, jobId) {
|
|
|
9489
10122
|
receipt = { ...receipt, status: "interrupted", ended_at: (/* @__PURE__ */ new Date()).toISOString(), error: "Owning ZTC process ended; inspect output before retrying." };
|
|
9490
10123
|
save(sessionId, receipt);
|
|
9491
10124
|
}
|
|
9492
|
-
return { receipt, controller: new AbortController(), done: Promise.resolve(), loggedBytes:
|
|
10125
|
+
return { receipt, controller: new AbortController(), done: Promise.resolve(), loggedBytes: statSync2(receipt.log_path).size };
|
|
9493
10126
|
}
|
|
9494
10127
|
function listCommandJobs(sessionId) {
|
|
9495
10128
|
const jobs = [...sessions.get(sessionId)?.values() ?? []];
|
|
@@ -9859,8 +10492,8 @@ init_tool_response_store();
|
|
|
9859
10492
|
|
|
9860
10493
|
// src/utils/mirror_media.ts
|
|
9861
10494
|
import { tmpdir as tmpdir2 } from "os";
|
|
9862
|
-
import { join as
|
|
9863
|
-
var MIRROR_MEDIA_ROOT =
|
|
10495
|
+
import { join as join13, resolve as resolve5, sep as sep2 } from "path";
|
|
10496
|
+
var MIRROR_MEDIA_ROOT = join13(tmpdir2(), "ztc-mirror-media");
|
|
9864
10497
|
function isMirrorMediaPath(localPath) {
|
|
9865
10498
|
if (!localPath) return false;
|
|
9866
10499
|
const root = resolve5(MIRROR_MEDIA_ROOT);
|
|
@@ -10089,13 +10722,13 @@ init_tool_compression();
|
|
|
10089
10722
|
// src/agent/runtime/tool_runtime.ts
|
|
10090
10723
|
init_capabilities();
|
|
10091
10724
|
init_config();
|
|
10092
|
-
import { basename as basename3, dirname as
|
|
10725
|
+
import { basename as basename3, dirname as dirname8, join as join15, relative as relative2, resolve as resolve7 } from "path";
|
|
10093
10726
|
import { realpathSync } from "node:fs";
|
|
10094
10727
|
import { appendFile } from "node:fs/promises";
|
|
10095
10728
|
|
|
10096
10729
|
// src/context/intents_loader.ts
|
|
10097
|
-
import { appendFileSync as appendFileSync5, existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as
|
|
10098
|
-
import { basename as basename2, dirname as
|
|
10730
|
+
import { appendFileSync as appendFileSync5, existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync8, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
10731
|
+
import { basename as basename2, dirname as dirname7, join as join14, relative, resolve as resolve6 } from "path";
|
|
10099
10732
|
var DEFAULT_MAX_BYTES = 32 * 1024;
|
|
10100
10733
|
var DEFAULT_FILE_INTENT_THRESHOLD_LINES = 400;
|
|
10101
10734
|
function loadIntentsContext(cwd = process.cwd(), settings, options = {}) {
|
|
@@ -10166,7 +10799,7 @@ function buildIntentCandidates(cwd, relatedPaths, includeHierarchy) {
|
|
|
10166
10799
|
if (includeHierarchy) {
|
|
10167
10800
|
const roots = findRootToCwd(resolve6(cwd));
|
|
10168
10801
|
for (const dir of roots) {
|
|
10169
|
-
pushUnique(candidates, seen,
|
|
10802
|
+
pushUnique(candidates, seen, join14(dir, ".ztc-intents.md"));
|
|
10170
10803
|
}
|
|
10171
10804
|
}
|
|
10172
10805
|
for (const relatedPath of relatedPaths) {
|
|
@@ -10180,10 +10813,10 @@ function findRootToCwd(cwd) {
|
|
|
10180
10813
|
let current = cwd;
|
|
10181
10814
|
for (; ; ) {
|
|
10182
10815
|
chain.push(current);
|
|
10183
|
-
if (existsSync4(
|
|
10816
|
+
if (existsSync4(join14(current, ".git"))) {
|
|
10184
10817
|
break;
|
|
10185
10818
|
}
|
|
10186
|
-
const parent =
|
|
10819
|
+
const parent = dirname7(current);
|
|
10187
10820
|
if (parent === current) {
|
|
10188
10821
|
break;
|
|
10189
10822
|
}
|
|
@@ -10195,16 +10828,16 @@ function selectIntentTarget(cwd, absolutePath, threshold) {
|
|
|
10195
10828
|
if (isLargeFile(absolutePath, threshold)) {
|
|
10196
10829
|
return fileIntentPath(absolutePath);
|
|
10197
10830
|
}
|
|
10198
|
-
const dir = existsSync4(absolutePath) &&
|
|
10831
|
+
const dir = existsSync4(absolutePath) && statSync3(absolutePath).isDirectory() ? absolutePath : dirname7(absolutePath);
|
|
10199
10832
|
const normalizedCwd = resolve6(cwd);
|
|
10200
10833
|
const normalizedDir = resolve6(dir);
|
|
10201
10834
|
if (!isInside(normalizedDir, normalizedCwd)) {
|
|
10202
|
-
return
|
|
10835
|
+
return join14(normalizedCwd, ".ztc-intents.md");
|
|
10203
10836
|
}
|
|
10204
|
-
return
|
|
10837
|
+
return join14(normalizedDir, ".ztc-intents.md");
|
|
10205
10838
|
}
|
|
10206
10839
|
function ensureIntentFile(path) {
|
|
10207
|
-
mkdirSync4(
|
|
10840
|
+
mkdirSync4(dirname7(path), { recursive: true });
|
|
10208
10841
|
if (existsSync4(path)) {
|
|
10209
10842
|
return;
|
|
10210
10843
|
}
|
|
@@ -10219,14 +10852,14 @@ function ensureIntentFile(path) {
|
|
|
10219
10852
|
].join("\n") + "\n", "utf-8");
|
|
10220
10853
|
}
|
|
10221
10854
|
function fileIntentPath(absolutePath) {
|
|
10222
|
-
return
|
|
10855
|
+
return join14(dirname7(absolutePath), `.ztc-intents-${basename2(absolutePath)}.md`);
|
|
10223
10856
|
}
|
|
10224
10857
|
function isLargeFile(path, threshold) {
|
|
10225
10858
|
try {
|
|
10226
|
-
if (!existsSync4(path) ||
|
|
10859
|
+
if (!existsSync4(path) || statSync3(path).isDirectory()) {
|
|
10227
10860
|
return false;
|
|
10228
10861
|
}
|
|
10229
|
-
const raw =
|
|
10862
|
+
const raw = readFileSync8(path, "utf-8");
|
|
10230
10863
|
return raw.split("\n").length >= threshold;
|
|
10231
10864
|
} catch {
|
|
10232
10865
|
return false;
|
|
@@ -10237,7 +10870,7 @@ function loadBudgetedFile(path, maxBytes) {
|
|
|
10237
10870
|
return null;
|
|
10238
10871
|
}
|
|
10239
10872
|
try {
|
|
10240
|
-
const raw =
|
|
10873
|
+
const raw = readFileSync8(path, "utf-8");
|
|
10241
10874
|
const bytes = Buffer.byteLength(raw, "utf-8");
|
|
10242
10875
|
if (bytes <= maxBytes) {
|
|
10243
10876
|
return {
|
|
@@ -10282,7 +10915,7 @@ function isHostControlPlaneWrite(tool, args, cwd) {
|
|
|
10282
10915
|
try {
|
|
10283
10916
|
const noFollowLeaf = (path) => {
|
|
10284
10917
|
const absolute = resolve7(path);
|
|
10285
|
-
return
|
|
10918
|
+
return join15(realpathSync(dirname8(absolute)), basename3(absolute));
|
|
10286
10919
|
};
|
|
10287
10920
|
return noFollowLeaf(resolve7(cwd, args.path)) === noFollowLeaf(tool.hostControlPlaneWritePath);
|
|
10288
10921
|
} catch {
|
|
@@ -10350,7 +10983,7 @@ ${intentContext}`;
|
|
|
10350
10983
|
async function recordToolTrace(entry) {
|
|
10351
10984
|
const configured = process.env.ZTC_TOOL_TRACE;
|
|
10352
10985
|
if (!configured) return;
|
|
10353
|
-
const target = configured === "1" ?
|
|
10986
|
+
const target = configured === "1" ? join15(process.cwd(), "ztc-tool-trace.jsonl") : configured;
|
|
10354
10987
|
try {
|
|
10355
10988
|
await appendFile(target, `${JSON.stringify(entry)}
|
|
10356
10989
|
`, "utf-8");
|
|
@@ -10803,7 +11436,7 @@ var Agent = class _Agent {
|
|
|
10803
11436
|
routePlan: config.routePlan,
|
|
10804
11437
|
maxIterations: config.maxIterations || 10,
|
|
10805
11438
|
execution: resolveExecutionSettings(config.execution),
|
|
10806
|
-
sessionId: config.sessionId ??
|
|
11439
|
+
sessionId: config.sessionId ?? randomUUID7(),
|
|
10807
11440
|
runtimeFacts: config.runtimeFacts ?? {},
|
|
10808
11441
|
apiRetry: resolveApiRetrySettings({ apiRetry: config.apiRetry }),
|
|
10809
11442
|
llmRequestTimeoutMs: resolveLlmRequestTimeoutMs(
|
|
@@ -10829,6 +11462,10 @@ var Agent = class _Agent {
|
|
|
10829
11462
|
this.alwaysLoadedToolNames.add(name);
|
|
10830
11463
|
}
|
|
10831
11464
|
this.backend = this.config.backend;
|
|
11465
|
+
if (this.backend.getModelCapabilities?.(this.config.model)?.tools === false) {
|
|
11466
|
+
this.config.tools = [];
|
|
11467
|
+
this.config.autoContinue = false;
|
|
11468
|
+
}
|
|
10832
11469
|
this.policy = this.config.policy;
|
|
10833
11470
|
this.tracer = this.config.tracer;
|
|
10834
11471
|
this._cwd = this.config.cwd;
|
|
@@ -10843,7 +11480,7 @@ var Agent = class _Agent {
|
|
|
10843
11480
|
this._hasCustomSystemPrompt = typeof config.systemPrompt === "string" && config.systemPrompt.trim().length > 0;
|
|
10844
11481
|
}
|
|
10845
11482
|
setAutoContinue(enabled2) {
|
|
10846
|
-
this._autoContinue = enabled2;
|
|
11483
|
+
this._autoContinue = enabled2 && this.backend.getModelCapabilities?.(this.config.model)?.tools !== false;
|
|
10847
11484
|
}
|
|
10848
11485
|
/** Override the agent's system prompt (e.g., for simulation persona injection). */
|
|
10849
11486
|
setSystemPrompt(prompt) {
|
|
@@ -10978,7 +11615,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
10978
11615
|
this._currentRequestToolIds = currentTurnToolIds;
|
|
10979
11616
|
if (allToolIds.length > 0) {
|
|
10980
11617
|
const activeModel = this.config.model || "default";
|
|
10981
|
-
const budget = this.toolResponseStore.effectiveBudget(activeModel);
|
|
11618
|
+
const budget = this.toolResponseStore.effectiveBudget(activeModel, this.backend.getModelCapabilities?.(activeModel) ? this.backend.getModelCapabilities(activeModel)?.context_window ?? null : void 0);
|
|
10982
11619
|
this._selectorVerdict = this.toolResponseStore.selectInlineSet(
|
|
10983
11620
|
allToolIds,
|
|
10984
11621
|
currentTurnToolIds,
|
|
@@ -11033,7 +11670,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
11033
11670
|
const ext = extname(path).toLowerCase();
|
|
11034
11671
|
const mediaType = this.getImageMediaType(ext);
|
|
11035
11672
|
if (!mediaType) return null;
|
|
11036
|
-
const buffer =
|
|
11673
|
+
const buffer = readFileSync9(path);
|
|
11037
11674
|
return {
|
|
11038
11675
|
type: "image",
|
|
11039
11676
|
mediaType,
|
|
@@ -11093,7 +11730,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
11093
11730
|
const ext = extname(path).toLowerCase();
|
|
11094
11731
|
const mediaType = this.getVideoMediaType(ext);
|
|
11095
11732
|
if (!mediaType) return null;
|
|
11096
|
-
const buffer =
|
|
11733
|
+
const buffer = readFileSync9(path);
|
|
11097
11734
|
return {
|
|
11098
11735
|
type: "video",
|
|
11099
11736
|
mediaType,
|
|
@@ -11538,7 +12175,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
11538
12175
|
}
|
|
11539
12176
|
const result = await this.runCore(workingMessages, signal);
|
|
11540
12177
|
const assistantMessage = {
|
|
11541
|
-
id: `host_assistant_${
|
|
12178
|
+
id: `host_assistant_${randomUUID7()}`,
|
|
11542
12179
|
role: "assistant",
|
|
11543
12180
|
content: result.content,
|
|
11544
12181
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -11647,6 +12284,28 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
11647
12284
|
finalReasoning = response.reasoning;
|
|
11648
12285
|
}
|
|
11649
12286
|
if (!this._lastResponseStreamed) await this.emitStreamText(iterationText, signal);
|
|
12287
|
+
if (iterations < this.config.maxIterations) {
|
|
12288
|
+
const steering = takeSteering?.() ?? [];
|
|
12289
|
+
if (steering.length > 0) {
|
|
12290
|
+
if (iterationText.trim()) {
|
|
12291
|
+
const answer = {
|
|
12292
|
+
id: `assistant_${Date.now()}_${iterations}`,
|
|
12293
|
+
role: "assistant",
|
|
12294
|
+
content: iterationText,
|
|
12295
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
12296
|
+
...response.reasoning ? { metadata: { reasoningContent: response.reasoning } } : {}
|
|
12297
|
+
};
|
|
12298
|
+
messages.push(answer);
|
|
12299
|
+
turnMessages.push(answer);
|
|
12300
|
+
}
|
|
12301
|
+
messages.push(...steering);
|
|
12302
|
+
turnMessages.push(...steering);
|
|
12303
|
+
this.emit({ type: "history_checkpoint", messages: [...turnMessages] });
|
|
12304
|
+
finalContent = "";
|
|
12305
|
+
finalReasoning = void 0;
|
|
12306
|
+
continue;
|
|
12307
|
+
}
|
|
12308
|
+
}
|
|
11650
12309
|
if (this.shouldContinue(iterationText) && this._consecutiveAutoContinues < this.config.maxConsecutiveAutoContinues) {
|
|
11651
12310
|
this._consecutiveAutoContinues++;
|
|
11652
12311
|
const acTodos = getLatestTodos();
|
|
@@ -11880,7 +12539,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
11880
12539
|
if (recoveryAction === "stop") throw new AgentError("Automatic recovery budget exhausted after repeated tool failures. Inspect the retained results and current capabilities before retrying.", "RECOVERY_EXHAUSTED");
|
|
11881
12540
|
if (recoveryAction === "recover") {
|
|
11882
12541
|
const recoveryMessage = {
|
|
11883
|
-
id: `recovery_${
|
|
12542
|
+
id: `recovery_${randomUUID7()}`,
|
|
11884
12543
|
role: "user",
|
|
11885
12544
|
content: "[Recovery] Repeated failures share the same cause. Stop that sequence. Inspect current capabilities and active jobs, then make one changed recovery attempt. Use file/stdin tools for scripts and raw Ctrl+C for stuck shell input, then read the pane in the same response or immediately afterward. A silent running-job poll allows one further inspection before stopping; do not repeat empty polls. Continue authorized work; use ask_user only for a concrete missing prerequisite. Do not repeat an acknowledgement as proof of success.",
|
|
11886
12545
|
metadata: { synthetic: true },
|
|
@@ -12042,7 +12701,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
12042
12701
|
const { maxAttempts, baseDelayMs: baseDelay } = this.config.apiRetry;
|
|
12043
12702
|
const timeoutMs = this.config.llmRequestTimeoutMs;
|
|
12044
12703
|
if (this.backend.handlesTransportRetries?.(request) === true) {
|
|
12045
|
-
request = { ...request, transportTurnId: request.transportTurnId ??
|
|
12704
|
+
request = { ...request, transportTurnId: request.transportTurnId ?? randomUUID7() };
|
|
12046
12705
|
}
|
|
12047
12706
|
const useStream = process.env.ZTC_NO_STREAM !== "1" && !this.backend.streamsSyntheticallyFor?.(request);
|
|
12048
12707
|
let answerOutputEmitted = false;
|
|
@@ -12191,7 +12850,8 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
12191
12850
|
let errorMessage = "";
|
|
12192
12851
|
let admissionMessage = "";
|
|
12193
12852
|
try {
|
|
12194
|
-
const
|
|
12853
|
+
const bodyMessage = message.replace(/ \[(?:(?:fly-request-id|x-request-id|cf-ray|x-zerg-error-code)=[^\]\r\n ]+ ?)+\]$/, "");
|
|
12854
|
+
const jsonMatch = bodyMessage.match(/:\s*(\{[\s\S]*\})\s*$/);
|
|
12195
12855
|
if (jsonMatch) {
|
|
12196
12856
|
const parsed = JSON.parse(jsonMatch[1]);
|
|
12197
12857
|
const errorPayload = parsed.error;
|
|
@@ -12218,6 +12878,9 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
12218
12878
|
}
|
|
12219
12879
|
} catch {
|
|
12220
12880
|
}
|
|
12881
|
+
if (statusCode === 410 && message.startsWith("ZRouter API error (") && ["stream_producer_lost", "stream_producer_failed", "stream_resume_expired"].includes(errorCode)) {
|
|
12882
|
+
return { retryable: false, reason: "The Router stream was interrupted and cannot be resumed. Send a message to continue from the existing conversation." };
|
|
12883
|
+
}
|
|
12221
12884
|
if (errorCode === "context_length_exceeded" || isContextOverflowMessage(`${errorMessage} ${message}`)) {
|
|
12222
12885
|
return { retryable: false, reason: "Context window exceeded", kind: "context_overflow" };
|
|
12223
12886
|
}
|
|
@@ -12228,7 +12891,10 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
12228
12891
|
return { retryable: true, reason: "Rate limit exceeded" };
|
|
12229
12892
|
}
|
|
12230
12893
|
if (statusCode === 503 || statusCode === 502 || statusCode === 500 || errorType === "UNAVAILABLE" || errorType === "INTERNAL") {
|
|
12231
|
-
|
|
12894
|
+
const requestId = /(?:fly-request-id|x-request-id)=([A-Za-z0-9._:-]{1,128})(?:[ \]]|$)/.exec(message)?.[1];
|
|
12895
|
+
const detail = [admissionMessage.trim().replace(/\s+/g, " "), requestId && `request_id: ${requestId}`].filter(Boolean).join("; ");
|
|
12896
|
+
const cause = detail ? `: ${detail.length > 160 ? `${detail.slice(0, 159)}\u2026` : detail}` : "";
|
|
12897
|
+
return { retryable: true, reason: `Upstream server error (${statusCode || "no status"})${cause}` };
|
|
12232
12898
|
}
|
|
12233
12899
|
if (statusCode === 401 || errorType === "authentication_error" || errorType === "UNAUTHENTICATED") {
|
|
12234
12900
|
return {
|
|
@@ -12239,7 +12905,7 @@ INVESTIGATION STRATEGY \u2014 before making tool calls to explore or debug, foll
|
|
|
12239
12905
|
if (statusCode === 403 || errorType === "PERMISSION_DENIED") {
|
|
12240
12906
|
return { retryable: false, reason: admissionMessage || "Permission denied" };
|
|
12241
12907
|
}
|
|
12242
|
-
if (statusCode === 402) {
|
|
12908
|
+
if (statusCode === 402 || errorCode === "billing_required") {
|
|
12243
12909
|
const guidance = "Subscribe in Zerg Router (Dashboard \u2192 Billing), or choose another model with /model.";
|
|
12244
12910
|
return {
|
|
12245
12911
|
retryable: false,
|
|
@@ -12274,8 +12940,8 @@ init_capabilities();
|
|
|
12274
12940
|
init_logger();
|
|
12275
12941
|
init_extension_discovery();
|
|
12276
12942
|
import { homedir as homedir8 } from "os";
|
|
12277
|
-
import { join as
|
|
12278
|
-
import { readdir as
|
|
12943
|
+
import { join as join16, resolve as resolve8, basename as basename4 } from "path";
|
|
12944
|
+
import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
|
|
12279
12945
|
var MAX_DEPTH = 4;
|
|
12280
12946
|
function defaultMarkdownRoots() {
|
|
12281
12947
|
const explicitRoots = extensionPathsFromEnvironment("ZTC_SKILL_PATHS");
|
|
@@ -12283,20 +12949,20 @@ function defaultMarkdownRoots() {
|
|
|
12283
12949
|
const home = homedir8();
|
|
12284
12950
|
return [
|
|
12285
12951
|
...explicitRoots,
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12952
|
+
join16(process.cwd(), ".ztc", "skills"),
|
|
12953
|
+
join16(process.cwd(), ".claude", "skills"),
|
|
12954
|
+
join16(home, ".ztc", "skills"),
|
|
12955
|
+
join16(home, ".claude", "skills")
|
|
12290
12956
|
];
|
|
12291
12957
|
}
|
|
12292
12958
|
async function walk(dir, depth = 0) {
|
|
12293
12959
|
if (depth > MAX_DEPTH) return [];
|
|
12294
12960
|
try {
|
|
12295
|
-
const entries = await
|
|
12961
|
+
const entries = await readdir3(dir, { withFileTypes: true });
|
|
12296
12962
|
const results = [];
|
|
12297
12963
|
for (const entry of entries) {
|
|
12298
12964
|
if (entry.name.startsWith(".")) continue;
|
|
12299
|
-
const full =
|
|
12965
|
+
const full = join16(dir, entry.name);
|
|
12300
12966
|
if (entry.isDirectory()) {
|
|
12301
12967
|
results.push(...await walk(full, depth + 1));
|
|
12302
12968
|
} else if (entry.isFile() && entry.name.toLowerCase() === "skill.md") {
|
|
@@ -12438,12 +13104,12 @@ async function loadSkills(roots = defaultMarkdownRoots()) {
|
|
|
12438
13104
|
}
|
|
12439
13105
|
|
|
12440
13106
|
// src/skills/bundled/index.ts
|
|
12441
|
-
import { dirname as
|
|
13107
|
+
import { dirname as dirname9, resolve as resolve9 } from "path";
|
|
12442
13108
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12443
13109
|
|
|
12444
13110
|
// src/skills/bundled/init-context.ts
|
|
12445
|
-
import { readdir as
|
|
12446
|
-
import { join as
|
|
13111
|
+
import { readdir as readdir4, readFile as readFile5, stat as stat2 } from "fs/promises";
|
|
13112
|
+
import { join as join17 } from "path";
|
|
12447
13113
|
var MAX_ENTRIES = 60;
|
|
12448
13114
|
var TOP_LEVEL_DIRS_OF_INTEREST = [
|
|
12449
13115
|
"src",
|
|
@@ -12487,7 +13153,7 @@ var MANIFESTS = [
|
|
|
12487
13153
|
var CLAUDE_MD_CANDIDATES = ["CLAUDE.md", "AGENTS.md", "claude.md"];
|
|
12488
13154
|
async function fileExists(path) {
|
|
12489
13155
|
try {
|
|
12490
|
-
await
|
|
13156
|
+
await stat2(path);
|
|
12491
13157
|
return true;
|
|
12492
13158
|
} catch {
|
|
12493
13159
|
return false;
|
|
@@ -12495,7 +13161,7 @@ async function fileExists(path) {
|
|
|
12495
13161
|
}
|
|
12496
13162
|
async function safeReadDir(path) {
|
|
12497
13163
|
try {
|
|
12498
|
-
const entries = await
|
|
13164
|
+
const entries = await readdir4(path, { withFileTypes: true });
|
|
12499
13165
|
return entries.filter((e) => !e.name.startsWith(".")).map((e) => e.isDirectory() ? `${e.name}/` : e.name);
|
|
12500
13166
|
} catch {
|
|
12501
13167
|
return [];
|
|
@@ -12504,7 +13170,7 @@ async function safeReadDir(path) {
|
|
|
12504
13170
|
async function detectManifests(cwd) {
|
|
12505
13171
|
const found = [];
|
|
12506
13172
|
for (const { file, label } of MANIFESTS) {
|
|
12507
|
-
if (await fileExists(
|
|
13173
|
+
if (await fileExists(join17(cwd, file))) {
|
|
12508
13174
|
found.push(`- ${file} \u2014 ${label}`);
|
|
12509
13175
|
}
|
|
12510
13176
|
}
|
|
@@ -12512,7 +13178,7 @@ async function detectManifests(cwd) {
|
|
|
12512
13178
|
}
|
|
12513
13179
|
async function readClaudeMd(cwd) {
|
|
12514
13180
|
for (const name of CLAUDE_MD_CANDIDATES) {
|
|
12515
|
-
const path =
|
|
13181
|
+
const path = join17(cwd, name);
|
|
12516
13182
|
if (await fileExists(path)) {
|
|
12517
13183
|
try {
|
|
12518
13184
|
const contents = await readFile5(path, "utf-8");
|
|
@@ -12592,7 +13258,7 @@ var bundledCodeSkills = [
|
|
|
12592
13258
|
initContextSkill
|
|
12593
13259
|
];
|
|
12594
13260
|
function bundledMarkdownRoot() {
|
|
12595
|
-
const here =
|
|
13261
|
+
const here = dirname9(fileURLToPath2(import.meta.url));
|
|
12596
13262
|
return resolve9(here);
|
|
12597
13263
|
}
|
|
12598
13264
|
|
|
@@ -12771,7 +13437,7 @@ var invokeSkillTool = makeInvokeSkillTool(resolveAmbientSkills);
|
|
|
12771
13437
|
// src/zlm.ts
|
|
12772
13438
|
var ZLM_EMBED_API_VERSION = "zerglang.ztc-embed/1";
|
|
12773
13439
|
var ZLM_STDIO_PROTOCOL = "zerglang.ztc-host/1";
|
|
12774
|
-
var ZLM_ZTC_VERSION = true ? "0.4.
|
|
13440
|
+
var ZLM_ZTC_VERSION = true ? "0.4.1-dev.36919234045" : "development";
|
|
12775
13441
|
var ZLM_MAX_HOST_TOOLS = 64;
|
|
12776
13442
|
var ZLM_MAX_SYSTEM_PROMPT_BYTES = 128 * 1024;
|
|
12777
13443
|
var ZLM_HOST_APPROVAL_CAPABILITIES = Object.freeze([
|