kc-beta 0.1.1 → 0.2.1
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/bin/kc-beta.js +14 -2
- package/package.json +1 -1
- package/src/agent/context-window.js +151 -0
- package/src/agent/context.js +58 -88
- package/src/agent/engine.js +267 -38
- package/src/agent/event-log.js +111 -0
- package/src/agent/llm-client.js +352 -59
- package/src/agent/pipelines/_archive_v1/distillation.js +113 -0
- package/src/agent/pipelines/_archive_v1/extraction.js +92 -0
- package/src/agent/pipelines/_archive_v1/initializer.js +163 -0
- package/src/agent/pipelines/_archive_v1/production-qc.js +99 -0
- package/src/agent/pipelines/_archive_v1/skill-authoring.js +83 -0
- package/src/agent/pipelines/_archive_v1/skill-testing.js +111 -0
- package/src/agent/pipelines/base.js +6 -0
- package/src/agent/pipelines/distillation.js +25 -11
- package/src/agent/pipelines/extraction.js +26 -7
- package/src/agent/pipelines/initializer.js +30 -20
- package/src/agent/pipelines/production-qc.js +22 -5
- package/src/agent/pipelines/skill-authoring.js +19 -8
- package/src/agent/pipelines/skill-testing.js +26 -8
- package/src/agent/retry.js +83 -0
- package/src/agent/session-state.js +78 -0
- package/src/agent/skill-loader.js +139 -0
- package/src/agent/token-counter.js +62 -0
- package/src/agent/tools/document-parse.js +3 -3
- package/src/agent/tools/tier-downgrade.js +11 -2
- package/src/agent/tools/web-search.js +107 -0
- package/src/agent/tools/worker-llm-call.js +14 -5
- package/src/cli/components.js +16 -4
- package/src/cli/config.js +246 -0
- package/src/cli/index.js +99 -10
- package/src/cli/onboard.js +154 -48
- package/src/config.js +25 -7
- package/src/providers.js +370 -0
package/src/cli/onboard.js
CHANGED
|
@@ -2,6 +2,8 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import readline from "node:readline";
|
|
4
4
|
import os from "node:os";
|
|
5
|
+
import { getProviders, getProviderById, getProviderLabels, classifyModels, getCuratedModels } from "../providers.js";
|
|
6
|
+
import { LLMClient } from "../agent/llm-client.js";
|
|
5
7
|
|
|
6
8
|
const CONFIG_DIR = path.join(os.homedir(), ".kc_agent");
|
|
7
9
|
const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
|
|
@@ -23,27 +25,29 @@ const L = {
|
|
|
23
25
|
langPrompt: "Language",
|
|
24
26
|
langOptions: ["English", "中文"],
|
|
25
27
|
providerPrompt: "LLM Provider",
|
|
26
|
-
providerLabels: [
|
|
27
|
-
"SiliconFlow (recommended for China)",
|
|
28
|
-
"Aliyun Bailian",
|
|
29
|
-
"Anthropic",
|
|
30
|
-
"OpenAI",
|
|
31
|
-
"Custom (enter base URL)",
|
|
32
|
-
],
|
|
33
28
|
current: "current",
|
|
34
29
|
choose: "Choose",
|
|
35
30
|
baseUrl: "Base URL",
|
|
36
31
|
baseUrlRequired: "Base URL is required for custom provider.",
|
|
37
32
|
apiKey: "API Key",
|
|
38
33
|
apiKeyRequired: "required",
|
|
39
|
-
apiKeyKeep: "Enter to keep",
|
|
34
|
+
apiKeyKeep: "Press Enter to keep",
|
|
40
35
|
apiKeyMissing: "API key is required. Run 'kc-beta onboard' again.",
|
|
36
|
+
keyType: "Key Type",
|
|
37
|
+
keyTypeOptions: ["API Key (pay-per-use)", "Coding Plan Key (subscription)"],
|
|
41
38
|
conductorModel: "Conductor Model",
|
|
42
39
|
workerTiers: "Worker LLM Tiers",
|
|
43
|
-
tierHint: "Enter to accept defaults",
|
|
40
|
+
tierHint: "Press Enter to accept defaults",
|
|
44
41
|
accuracy: "Accuracy Threshold",
|
|
45
42
|
saved: "Saved to",
|
|
46
43
|
runHint: "Run {cmd} to start the agent.",
|
|
44
|
+
discovering: "Discovering available models...",
|
|
45
|
+
discoveryFailed: "Could not auto-discover models. Using provider defaults.",
|
|
46
|
+
discoveryFound: "Found {n} models. Suggested tier assignments:",
|
|
47
|
+
discoveryAccept: "Press Enter to accept, or type model name to override",
|
|
48
|
+
enterSkip: "Press Enter to skip",
|
|
49
|
+
enterDefault: "Press Enter to use default",
|
|
50
|
+
bedrockWarn: "AWS Bedrock is not yet fully supported. Authentication will fail at runtime.",
|
|
47
51
|
},
|
|
48
52
|
zh: {
|
|
49
53
|
title: "KC Agent 配置向导",
|
|
@@ -51,13 +55,6 @@ const L = {
|
|
|
51
55
|
langPrompt: "语言",
|
|
52
56
|
langOptions: ["English", "中文"],
|
|
53
57
|
providerPrompt: "大模型服务商",
|
|
54
|
-
providerLabels: [
|
|
55
|
-
"SiliconFlow(国内推荐)",
|
|
56
|
-
"阿里云百炼",
|
|
57
|
-
"Anthropic",
|
|
58
|
-
"OpenAI",
|
|
59
|
-
"自定义(输入接口地址)",
|
|
60
|
-
],
|
|
61
58
|
current: "当前",
|
|
62
59
|
choose: "选择",
|
|
63
60
|
baseUrl: "接口地址",
|
|
@@ -66,31 +63,33 @@ const L = {
|
|
|
66
63
|
apiKeyRequired: "必填",
|
|
67
64
|
apiKeyKeep: "回车保留当前密钥",
|
|
68
65
|
apiKeyMissing: "API 密钥为必填项。请重新运行 'kc-beta onboard'。",
|
|
66
|
+
keyType: "密钥类型",
|
|
67
|
+
keyTypeOptions: ["API Key(按量付费)", "Coding Plan Key(包年包月)"],
|
|
69
68
|
conductorModel: "主模型",
|
|
70
69
|
workerTiers: "Worker 模型分层",
|
|
71
70
|
tierHint: "回车接受默认值",
|
|
72
71
|
accuracy: "准确率阈值",
|
|
73
72
|
saved: "已保存至",
|
|
74
73
|
runHint: "运行 {cmd} 启动 Agent。",
|
|
74
|
+
discovering: "正在发现可用模型...",
|
|
75
|
+
discoveryFailed: "无法自动发现模型,使用默认配置。",
|
|
76
|
+
discoveryFound: "发现 {n} 个模型。建议分层:",
|
|
77
|
+
discoveryAccept: "回车接受,或输入模型名称覆盖",
|
|
78
|
+
enterSkip: "回车跳过",
|
|
79
|
+
enterDefault: "回车使用默认值",
|
|
80
|
+
bedrockWarn: "AWS Bedrock 尚未完全支持。运行时认证将失败。",
|
|
75
81
|
},
|
|
76
82
|
};
|
|
77
83
|
|
|
78
|
-
|
|
79
|
-
{ name: "SiliconFlow", base_url: "https://api.siliconflow.cn/v1", model: "Pro/zai-org/GLM-5",
|
|
80
|
-
tiers: { tier1: "Pro/zai-org/GLM-5, Pro/moonshotai/Kimi-K2.5", tier2: "Pro/deepseek-ai/DeepSeek-V3.2, Pro/MiniMaxAI/MiniMax-M2.5", tier3: "Qwen/Qwen3.5-122B-A10B", tier4: "Qwen/Qwen3.5-35B-A3B" } },
|
|
81
|
-
{ name: "Aliyun", base_url: "https://coding.dashscope.aliyuncs.com/v1", model: "glm-5",
|
|
82
|
-
tiers: { tier1: "glm-5", tier2: "deepseek-v3", tier3: "qwen-plus", tier4: "qwen-turbo" } },
|
|
83
|
-
{ name: "Anthropic", base_url: "https://api.anthropic.com/v1", model: "claude-sonnet-4-20250514",
|
|
84
|
-
tiers: { tier1: "claude-sonnet-4-20250514", tier2: "claude-sonnet-4-20250514", tier3: "claude-haiku-4-5-20251001", tier4: "claude-haiku-4-5-20251001" } },
|
|
85
|
-
{ name: "OpenAI", base_url: "https://api.openai.com/v1", model: "gpt-4o",
|
|
86
|
-
tiers: { tier1: "gpt-4o", tier2: "gpt-4o-mini", tier3: "gpt-4o-mini", tier4: "gpt-4o-mini" } },
|
|
87
|
-
{ name: "Custom", base_url: "", model: "", tiers: { tier1: "", tier2: "", tier3: "", tier4: "" } },
|
|
88
|
-
];
|
|
89
|
-
|
|
90
|
-
function ask(rl, question, defaultValue = "") {
|
|
84
|
+
function ask(rl, question, defaultValue = "", hint = "") {
|
|
91
85
|
const suffix = defaultValue ? ` ${DIM}[${defaultValue}]${RESET}` : "";
|
|
86
|
+
const hintText = hint
|
|
87
|
+
? ` ${GRAY}(${hint})${RESET}`
|
|
88
|
+
: defaultValue
|
|
89
|
+
? ` ${GRAY}(Press Enter to keep)${RESET}`
|
|
90
|
+
: "";
|
|
92
91
|
return new Promise((resolve) => {
|
|
93
|
-
rl.question(`${question}${suffix}: `, (answer) => resolve(answer.trim() || defaultValue));
|
|
92
|
+
rl.question(`${question}${suffix}${hintText}: `, (answer) => resolve(answer.trim() || defaultValue));
|
|
94
93
|
});
|
|
95
94
|
}
|
|
96
95
|
|
|
@@ -101,11 +100,14 @@ export async function onboard() {
|
|
|
101
100
|
if (fs.existsSync(CONFIG_PATH)) {
|
|
102
101
|
try { existing = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")); } catch { /* ignore */ }
|
|
103
102
|
}
|
|
103
|
+
const isUpdate = Object.keys(existing).length > 0;
|
|
104
104
|
|
|
105
105
|
console.log();
|
|
106
106
|
console.log(` ${BOLD}KC Agent Setup / KC Agent 配置向导${RESET}`);
|
|
107
107
|
console.log(` ${GRAY}${"─".repeat(40)}${RESET}`);
|
|
108
108
|
console.log();
|
|
109
|
+
|
|
110
|
+
// --- Language ---
|
|
109
111
|
console.log(` ${CYAN}Language / 语言:${RESET}`);
|
|
110
112
|
console.log(` 1. English`);
|
|
111
113
|
console.log(` 2. 中文`);
|
|
@@ -115,61 +117,161 @@ export async function onboard() {
|
|
|
115
117
|
const t = L[lang];
|
|
116
118
|
console.log();
|
|
117
119
|
|
|
118
|
-
if (
|
|
120
|
+
if (isUpdate) {
|
|
119
121
|
console.log(` ${DIM}${t.existingConfig}${RESET}`);
|
|
120
122
|
console.log();
|
|
121
123
|
}
|
|
122
124
|
|
|
125
|
+
// --- Provider ---
|
|
126
|
+
const providers = getProviders();
|
|
127
|
+
const labels = getProviderLabels(lang);
|
|
123
128
|
console.log(` ${CYAN}${t.providerPrompt}:${RESET}`);
|
|
124
|
-
for (let i = 0; i <
|
|
125
|
-
const marker =
|
|
126
|
-
console.log(` ${i + 1}. ${
|
|
129
|
+
for (let i = 0; i < labels.length; i++) {
|
|
130
|
+
const marker = providers[i].id === existing.provider ? ` ${GREEN}(${t.current})${RESET}` : "";
|
|
131
|
+
console.log(` ${i + 1}. ${labels[i].label}${marker}`);
|
|
127
132
|
}
|
|
128
133
|
const providerIdx = parseInt(await ask(rl, ` ${GRAY}>${RESET} ${t.choose}`, "1"), 10) - 1;
|
|
129
|
-
const provider =
|
|
134
|
+
const provider = providers[Math.max(0, Math.min(providerIdx, providers.length - 1))];
|
|
130
135
|
console.log();
|
|
131
136
|
|
|
132
|
-
|
|
133
|
-
if (provider.
|
|
137
|
+
// Bedrock warning
|
|
138
|
+
if (provider.id === "bedrock") {
|
|
139
|
+
console.log(` ${YELLOW}⚠ ${t.bedrockWarn}${RESET}`);
|
|
140
|
+
console.log();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --- Base URL ---
|
|
144
|
+
let baseUrl = provider.baseUrl;
|
|
145
|
+
if (provider.id === "custom") {
|
|
134
146
|
baseUrl = await ask(rl, ` ${t.baseUrl}`, existing.base_url || "");
|
|
135
147
|
if (!baseUrl) { console.log(` ${RED}${t.baseUrlRequired}${RESET}`); rl.close(); process.exit(1); }
|
|
148
|
+
console.log();
|
|
136
149
|
}
|
|
137
150
|
|
|
151
|
+
// --- Aliyun coding plan key sub-option ---
|
|
152
|
+
let useCodingPlan = false;
|
|
153
|
+
if (provider.supportsCodingPlanKey) {
|
|
154
|
+
console.log(` ${CYAN}${t.keyType}:${RESET}`);
|
|
155
|
+
console.log(` 1. ${t.keyTypeOptions[0]}`);
|
|
156
|
+
console.log(` 2. ${t.keyTypeOptions[1]}`);
|
|
157
|
+
const keyTypeChoice = await ask(rl, ` ${GRAY}>${RESET} ${t.choose}`, "1");
|
|
158
|
+
useCodingPlan = keyTypeChoice === "2";
|
|
159
|
+
if (useCodingPlan && provider.codingPlanUrl) {
|
|
160
|
+
baseUrl = provider.codingPlanUrl;
|
|
161
|
+
}
|
|
162
|
+
console.log();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// --- API Key ---
|
|
138
166
|
const maskedExisting = existing.api_key ? existing.api_key.slice(0, 6) + "..." + existing.api_key.slice(-4) : "";
|
|
167
|
+
const keyHint = maskedExisting ? t.apiKeyKeep : t.apiKeyRequired;
|
|
139
168
|
const keyPrompt = maskedExisting
|
|
140
|
-
? ` ${CYAN}${t.apiKey}${RESET} ${DIM}(${maskedExisting}
|
|
169
|
+
? ` ${CYAN}${t.apiKey}${RESET} ${DIM}(${maskedExisting})${RESET}`
|
|
141
170
|
: ` ${CYAN}${t.apiKey}${RESET} ${YELLOW}(${t.apiKeyRequired})${RESET}`;
|
|
142
|
-
const apiKey = await ask(rl, keyPrompt, "");
|
|
171
|
+
const apiKey = await ask(rl, keyPrompt, "", keyHint);
|
|
143
172
|
const finalKey = apiKey || existing.api_key || "";
|
|
144
173
|
if (!finalKey) { console.log(` ${RED}${t.apiKeyMissing}${RESET}`); rl.close(); process.exit(1); }
|
|
145
174
|
console.log();
|
|
146
175
|
|
|
147
|
-
|
|
148
|
-
|
|
176
|
+
// --- Auto-discovery ---
|
|
177
|
+
let discoveredModels = null;
|
|
178
|
+
let suggestedTiers = null;
|
|
179
|
+
let suggestedConductor = null;
|
|
180
|
+
|
|
181
|
+
// Try curated models first (for providers without /models endpoint)
|
|
182
|
+
const curated = getCuratedModels(provider.id);
|
|
183
|
+
|
|
184
|
+
if (curated) {
|
|
185
|
+
// Use curated model list
|
|
186
|
+
discoveredModels = curated;
|
|
187
|
+
const classified = classifyModels(curated);
|
|
188
|
+
suggestedTiers = classified.tiers;
|
|
189
|
+
suggestedConductor = classified.conductor;
|
|
190
|
+
console.log(` ${GREEN}✓${RESET} ${t.discoveryFound.replace("{n}", curated.length)}`);
|
|
191
|
+
if (suggestedConductor) {
|
|
192
|
+
console.log(` ${DIM}Conductor: ${suggestedConductor}${RESET}`);
|
|
193
|
+
}
|
|
194
|
+
for (const [tier, models] of Object.entries(suggestedTiers)) {
|
|
195
|
+
if (models) console.log(` ${DIM}${tier.toUpperCase()}: ${models}${RESET}`);
|
|
196
|
+
}
|
|
197
|
+
console.log();
|
|
198
|
+
} else if (provider.modelsEndpoint) {
|
|
199
|
+
// Query /models endpoint
|
|
200
|
+
console.log(` ${DIM}${t.discovering}${RESET}`);
|
|
201
|
+
try {
|
|
202
|
+
const tempClient = new LLMClient({
|
|
203
|
+
apiKey: finalKey,
|
|
204
|
+
baseUrl: baseUrl,
|
|
205
|
+
authType: provider.authType,
|
|
206
|
+
apiFormat: provider.apiFormat,
|
|
207
|
+
});
|
|
208
|
+
discoveredModels = await tempClient.listModels();
|
|
209
|
+
|
|
210
|
+
if (discoveredModels && discoveredModels.length > 0) {
|
|
211
|
+
const classified = classifyModels(discoveredModels);
|
|
212
|
+
suggestedTiers = classified.tiers;
|
|
213
|
+
suggestedConductor = classified.conductor;
|
|
214
|
+
console.log(` ${GREEN}✓${RESET} ${t.discoveryFound.replace("{n}", discoveredModels.length)}`);
|
|
215
|
+
if (suggestedConductor) {
|
|
216
|
+
console.log(` ${DIM}Conductor: ${suggestedConductor}${RESET}`);
|
|
217
|
+
}
|
|
218
|
+
for (const [tier, models] of Object.entries(suggestedTiers)) {
|
|
219
|
+
if (models) console.log(` ${DIM}${tier.toUpperCase()}: ${models}${RESET}`);
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
console.log(` ${DIM}${t.discoveryFailed}${RESET}`);
|
|
223
|
+
}
|
|
224
|
+
} catch {
|
|
225
|
+
console.log(` ${DIM}${t.discoveryFailed}${RESET}`);
|
|
226
|
+
}
|
|
227
|
+
console.log();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// --- Conductor model ---
|
|
231
|
+
const defaultModel = suggestedConductor || provider.defaultModel || existing.conductor_model || "";
|
|
232
|
+
const model = await ask(
|
|
233
|
+
rl,
|
|
234
|
+
` ${CYAN}${t.conductorModel}${RESET}`,
|
|
235
|
+
defaultModel,
|
|
236
|
+
isUpdate ? t.enterDefault : "",
|
|
237
|
+
);
|
|
149
238
|
console.log();
|
|
150
239
|
|
|
240
|
+
// --- Worker tiers ---
|
|
151
241
|
console.log(` ${CYAN}${t.workerTiers}${RESET} ${DIM}(${t.tierHint})${RESET}`);
|
|
152
242
|
const tiers = {};
|
|
153
243
|
for (const tier of ["tier1", "tier2", "tier3", "tier4"]) {
|
|
154
|
-
const def = provider.
|
|
155
|
-
tiers[tier] = await ask(
|
|
244
|
+
const def = suggestedTiers?.[tier] || provider.defaultTiers[tier] || existing?.tiers?.[tier] || "";
|
|
245
|
+
tiers[tier] = await ask(
|
|
246
|
+
rl,
|
|
247
|
+
` ${tier.toUpperCase()}`,
|
|
248
|
+
def,
|
|
249
|
+
t.discoveryAccept ? "" : "",
|
|
250
|
+
);
|
|
156
251
|
}
|
|
157
252
|
console.log();
|
|
158
253
|
|
|
159
|
-
const defaultAcc = existing.accuracy_threshold?.toString() || "0.9";
|
|
160
|
-
const accuracy = parseFloat(await ask(rl, ` ${CYAN}${t.accuracy}${RESET}`, defaultAcc));
|
|
161
|
-
console.log();
|
|
162
|
-
|
|
163
254
|
rl.close();
|
|
164
255
|
|
|
256
|
+
// Preserve existing thresholds or set defaults (editable via 'kc-beta config')
|
|
257
|
+
const accuracy = existing.accuracy_threshold ?? 0.9;
|
|
258
|
+
const systemicThreshold = existing.systemic_threshold ?? 0.10;
|
|
259
|
+
const spotCheckRate = existing.spot_check_rate ?? 0.10;
|
|
260
|
+
const tierTolerance = existing.tier_tolerance ?? 0.05;
|
|
261
|
+
|
|
165
262
|
const config = {
|
|
166
263
|
language: lang,
|
|
167
|
-
provider: provider.
|
|
264
|
+
provider: provider.id,
|
|
168
265
|
api_key: finalKey,
|
|
169
266
|
base_url: baseUrl,
|
|
267
|
+
auth_type: provider.authType,
|
|
268
|
+
api_format: provider.apiFormat,
|
|
170
269
|
conductor_model: model,
|
|
171
270
|
tiers,
|
|
172
271
|
accuracy_threshold: accuracy,
|
|
272
|
+
systemic_threshold: systemicThreshold,
|
|
273
|
+
spot_check_rate: spotCheckRate,
|
|
274
|
+
tier_tolerance: tierTolerance,
|
|
173
275
|
};
|
|
174
276
|
|
|
175
277
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
@@ -178,5 +280,9 @@ export async function onboard() {
|
|
|
178
280
|
console.log(` ${GREEN}✓${RESET} ${t.saved} ${GRAY}${CONFIG_PATH}${RESET}`);
|
|
179
281
|
console.log();
|
|
180
282
|
console.log(` ${t.runHint.replace("{cmd}", `${BOLD}kc-beta${RESET}`)}`);
|
|
283
|
+
const configHint = lang === "zh"
|
|
284
|
+
? ` ${DIM}运行 ${BOLD}kc-beta config${RESET}${DIM} 调整阈值和高级设置。${RESET}`
|
|
285
|
+
: ` ${DIM}Run ${BOLD}kc-beta config${RESET}${DIM} to adjust thresholds and advanced settings.${RESET}`;
|
|
286
|
+
console.log(configHint);
|
|
181
287
|
console.log();
|
|
182
288
|
}
|
package/src/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import os from "node:os";
|
|
4
|
+
import { getProviderById } from "./providers.js";
|
|
4
5
|
|
|
5
6
|
const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".kc_agent");
|
|
6
7
|
const GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, "config.json");
|
|
@@ -43,23 +44,29 @@ function loadEnvFile(envPath) {
|
|
|
43
44
|
|
|
44
45
|
/**
|
|
45
46
|
* Load settings by merging: global config (lowest) -> workspace .env (highest).
|
|
47
|
+
* Supports both new generic keys (LLM_API_KEY) and legacy keys (SILICONFLOW_API_KEY).
|
|
46
48
|
* @param {string} [workspacePath] - Optional workspace directory for .env override
|
|
47
49
|
*/
|
|
48
50
|
export function loadSettings(workspacePath) {
|
|
49
51
|
const gc = loadGlobalConfig();
|
|
50
52
|
const env = workspacePath ? loadEnvFile(path.join(workspacePath, ".env")) : {};
|
|
51
53
|
|
|
54
|
+
// Resolve provider metadata for authType/apiFormat defaults
|
|
55
|
+
const provider = gc.provider || "siliconflow";
|
|
56
|
+
const providerDef = getProviderById(provider);
|
|
57
|
+
|
|
52
58
|
return {
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
// Provider identity
|
|
60
|
+
provider,
|
|
61
|
+
authType: gc.auth_type || providerDef?.authType || "bearer",
|
|
62
|
+
apiFormat: gc.api_format || providerDef?.apiFormat || "openai",
|
|
63
|
+
|
|
64
|
+
// Conductor LLM (generic keys with legacy fallback)
|
|
65
|
+
llmApiKey: env.LLM_API_KEY || env.SILICONFLOW_API_KEY || gc.api_key || "",
|
|
66
|
+
llmBaseUrl: env.LLM_BASE_URL || env.SILICONFLOW_BASE_URL || gc.base_url || "https://api.siliconflow.cn/v1",
|
|
56
67
|
kcModel: gc.conductor_model || "glm-5",
|
|
57
68
|
kcMaxTokens: 65536,
|
|
58
69
|
|
|
59
|
-
// Worker LLMs (SiliconFlow)
|
|
60
|
-
siliconflowApiKey: env.SILICONFLOW_API_KEY || gc.api_key || "",
|
|
61
|
-
siliconflowBaseUrl: env.SILICONFLOW_BASE_URL || gc.base_url || "https://api.siliconflow.cn/v1",
|
|
62
|
-
|
|
63
70
|
// Tier models (from .env or global config tiers)
|
|
64
71
|
tier1: env.TIER1 || gc.tiers?.tier1 || "",
|
|
65
72
|
tier2: env.TIER2 || gc.tiers?.tier2 || "",
|
|
@@ -81,10 +88,21 @@ export function loadSettings(workspacePath) {
|
|
|
81
88
|
skillAccuracy: parseFloat(env.SKILL_ACCURACY || gc.accuracy_threshold?.toString() || "0.9"),
|
|
82
89
|
workflowAccuracy: parseFloat(env.WORKFLOW_ACCURACY || "0.9"),
|
|
83
90
|
|
|
91
|
+
// Advanced thresholds (from onboarding or .env)
|
|
92
|
+
systemicThreshold: parseFloat(env.SYSTEMIC_THRESHOLD || gc.systemic_threshold?.toString() || "0.10"),
|
|
93
|
+
spotCheckRate: parseFloat(env.SPOT_CHECK_RATE || gc.spot_check_rate?.toString() || "0.10"),
|
|
94
|
+
tierTolerance: parseFloat(env.TIER_TOLERANCE || gc.tier_tolerance?.toString() || "0.05"),
|
|
95
|
+
|
|
84
96
|
// Evolution
|
|
85
97
|
maxIterations: parseInt(env.MAX_ITERATIONS || "20", 10),
|
|
86
98
|
monitorFrequency: env.MONITOR_FREQUENCY || "mid",
|
|
87
99
|
|
|
100
|
+
// Web search
|
|
101
|
+
tavilyApiKey: env.TAVILY_API_KEY || gc.tavily_api_key || "",
|
|
102
|
+
|
|
103
|
+
// Context management
|
|
104
|
+
kcContextLimit: parseInt(env.KC_CONTEXT_LIMIT || "200000", 10),
|
|
105
|
+
|
|
88
106
|
// Language
|
|
89
107
|
language: env.LANGUAGE || gc.language || "en",
|
|
90
108
|
};
|