@zqagent/core 0.2.16 → 0.2.20
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.oss.en.md +13 -0
- package/README.oss.md +11 -0
- package/README.oss.zh-TW.md +11 -0
- package/dist/cli/index.cjs +764 -53
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +764 -53
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +16 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +733 -47
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +739 -53
- package/dist/server/index.js.map +1 -1
- package/dist/tools/explore.cjs.map +1 -1
- package/dist/tools/explore.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -730,15 +730,27 @@ function networkErrorHints(message, errorType = "") {
|
|
|
730
730
|
hints.push("\u2464 IPv6 \u6296\u52A8\u53EF\u8BD5\uFF1ANODE_OPTIONS=--dns-result-order=ipv4first");
|
|
731
731
|
return hints;
|
|
732
732
|
}
|
|
733
|
+
function authErrorHints(message, code = "") {
|
|
734
|
+
const text = `${message} ${code}`;
|
|
735
|
+
if (!/401|403|unauthorized|forbidden|invalid[_\s]*api[_\s]*key|api[\s_-]*key\s*(?:无效|invalid)|管理令牌无效/i.test(text)) {
|
|
736
|
+
return [];
|
|
737
|
+
}
|
|
738
|
+
return [
|
|
739
|
+
"\u51ED\u636E\u65E0\u6548\uFF1A\u82E5\u7528\u7684\u662F\u300C\u5FD7\u524D\u5927\u6A21\u578B\uFF08\u5185\u7F6E\uFF09\u300D\uFF0C\u5728\u8282\u70B9\u8BBE\u7F6E\u7684\u6A21\u578B\u9875\u70B9\u300C\u5237\u65B0\u5185\u7F6E\u6A21\u578B\u300D\u91CD\u65B0\u9886\u53D6 Key\uFF08\u5728\u63A7\u5236\u53F0\u91CD\u7F6E\u8FC7 Key \u540E\u9700\u8981\u8FD9\u4E00\u6B65\uFF09\uFF1B\u82E5\u662F\u81EA\u586B\u7684\u4F9B\u5E94\u5546\uFF0C\u8BF7\u68C0\u67E5 Key \u662F\u5426\u6B63\u786E\u6216\u5DF2\u8FC7\u671F"
|
|
740
|
+
];
|
|
741
|
+
}
|
|
733
742
|
function paramErrorHints(message, code = "") {
|
|
734
743
|
const text = `${message} ${code}`;
|
|
735
744
|
const hints = [];
|
|
736
|
-
if (/not[_\s]*(activated|enabled|purchased)|arrearage|quota|subscription|insufficient
|
|
745
|
+
if (/not[_\s]*(activated|enabled|purchased)|arrearage|quota|subscription|insufficient|未开通|欠费|额度|余额不足/i.test(
|
|
737
746
|
text
|
|
738
747
|
)) {
|
|
739
748
|
hints.push(
|
|
740
749
|
"\u8BE5\u6A21\u578B\u5728\u6B64 **API Key/\u8D26\u53F7** \u4E0B\u672A\u5F00\u901A\uFF08\u6216\u8D26\u53F7\u6B20\u8D39\u3001\u989D\u5EA6\u7528\u5C3D\uFF09\uFF1A\u5230\u7F51\u5173\u63A7\u5236\u53F0\u5F00\u901A\u8BE5\u6A21\u578B\uFF0C\u6216\u6362\u4E00\u4E2A\u5DF2\u5F00\u901A\u7684\u6A21\u578B"
|
|
741
750
|
);
|
|
751
|
+
hints.push(
|
|
752
|
+
"\u5982\u679C\u4F60\u7528\u7684\u662F\u300C\u5FD7\u524D\u5927\u6A21\u578B\uFF08\u5185\u7F6E\uFF09\u300D\uFF1A\u5230 https://hub.cd-zq.com \u67E5\u770B\u4F59\u989D\u5E76\u5145\u503C\uFF1B\u4E5F\u53EF\u4EE5\u5148\u5207\u6362\u5230\u4F60\u81EA\u5DF1\u914D\u7F6E\u7684\u5176\u5B83\u6A21\u578B\u7EE7\u7EED\uFF08\u8282\u70B9\u8BBE\u7F6E \u2192 \u6A21\u578B \u2192 \u8BBE\u4E3A\u9ED8\u8BA4\uFF09"
|
|
753
|
+
);
|
|
742
754
|
}
|
|
743
755
|
if (/invalid[_\s]*parameter|invalidparameter|required[_\s]+parameter|missing[_\s]+parameter|invalid[_\s]*model|model[_\s]*not[_\s]*found|not[_\s]*support|unsupported/i.test(
|
|
744
756
|
text
|
|
@@ -4981,6 +4993,9 @@ var ConsoleHook = class {
|
|
|
4981
4993
|
for (const hint of networkErrorHints(error2, errorType)) {
|
|
4982
4994
|
cliLog(` \u{1F4A1} ${hint}`);
|
|
4983
4995
|
}
|
|
4996
|
+
for (const hint of authErrorHints(error2, errorType)) {
|
|
4997
|
+
cliLog(` \u{1F4A1} ${hint}`);
|
|
4998
|
+
}
|
|
4984
4999
|
for (const hint of paramErrorHints(error2)) {
|
|
4985
5000
|
cliLog(` \u{1F4A1} ${hint}`);
|
|
4986
5001
|
}
|
|
@@ -9974,6 +9989,15 @@ function commonLegacyFiles() {
|
|
|
9974
9989
|
return [path18.join(stateDir(), "data", "node-llm.json")];
|
|
9975
9990
|
}
|
|
9976
9991
|
|
|
9992
|
+
// src/server/llmIds.ts
|
|
9993
|
+
init_esm_shims();
|
|
9994
|
+
var GLOBAL_PROVIDER_ID = "__env__";
|
|
9995
|
+
var BUILTIN_PROVIDER_ID = "__zqai__";
|
|
9996
|
+
function isBuiltinProvider(id) {
|
|
9997
|
+
return id === BUILTIN_PROVIDER_ID;
|
|
9998
|
+
}
|
|
9999
|
+
var FALLBACK_MODEL = "gpt-4o";
|
|
10000
|
+
|
|
9977
10001
|
// src/cli/connection.ts
|
|
9978
10002
|
var PROVIDERS = Object.fromEntries(
|
|
9979
10003
|
LLM_PRESETS.map((p) => [
|
|
@@ -10088,6 +10112,7 @@ function useConnection(id) {
|
|
|
10088
10112
|
return true;
|
|
10089
10113
|
}
|
|
10090
10114
|
function removeConnection(id) {
|
|
10115
|
+
if (id === BUILTIN_PROVIDER_ID) return false;
|
|
10091
10116
|
const f = read();
|
|
10092
10117
|
const next = f.providers.filter((p) => p.id !== id);
|
|
10093
10118
|
if (next.length === f.providers.length) return false;
|
|
@@ -10371,7 +10396,7 @@ var GLYPHS = {
|
|
|
10371
10396
|
T: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " "]
|
|
10372
10397
|
};
|
|
10373
10398
|
var GLYPH_ROWS = 6;
|
|
10374
|
-
var GLYPH_COLS =
|
|
10399
|
+
var GLYPH_COLS = 11;
|
|
10375
10400
|
var GRADIENT = [
|
|
10376
10401
|
[34, 211, 238],
|
|
10377
10402
|
[99, 102, 241],
|
|
@@ -10977,7 +11002,23 @@ var Store = class {
|
|
|
10977
11002
|
legacyFiles: [path20.join(this.root, "node-llm.json")]
|
|
10978
11003
|
});
|
|
10979
11004
|
const old = new Map(cur.providers.map((p) => [p.id, p]));
|
|
10980
|
-
const
|
|
11005
|
+
const src = [...cfg.providers];
|
|
11006
|
+
const prevBuiltin = cur.providers.find((p) => p.id === BUILTIN_PROVIDER_ID);
|
|
11007
|
+
if (prevBuiltin && !src.some((p) => p.id === BUILTIN_PROVIDER_ID)) {
|
|
11008
|
+
src.unshift({
|
|
11009
|
+
id: prevBuiltin.id,
|
|
11010
|
+
name: prevBuiltin.name,
|
|
11011
|
+
type: prevBuiltin.type,
|
|
11012
|
+
baseURL: prevBuiltin.baseURL,
|
|
11013
|
+
model: prevBuiltin.model,
|
|
11014
|
+
apiKey: decryptKey(prevBuiltin.apiKeyEnc, file) ?? void 0,
|
|
11015
|
+
reasoningEffort: prevBuiltin.reasoningEffort ?? null,
|
|
11016
|
+
...prevBuiltin.models ? { models: prevBuiltin.models } : {},
|
|
11017
|
+
...prevBuiltin.nonChat ? { nonChat: prevBuiltin.nonChat } : {},
|
|
11018
|
+
...prevBuiltin.modelMeta ? { modelMeta: prevBuiltin.modelMeta } : {}
|
|
11019
|
+
});
|
|
11020
|
+
}
|
|
11021
|
+
const providers = src.map((p) => {
|
|
10981
11022
|
const prev = old.get(p.id);
|
|
10982
11023
|
const apiKeyEnc = p.apiKey ? encryptKey(p.apiKey, file) : prev?.apiKeyEnc ?? "";
|
|
10983
11024
|
return {
|
|
@@ -11168,7 +11209,6 @@ function loadServerMcpConfigs(tenant) {
|
|
|
11168
11209
|
|
|
11169
11210
|
// src/server/nodeLlm.ts
|
|
11170
11211
|
init_esm_shims();
|
|
11171
|
-
var GLOBAL_PROVIDER_ID = "__env__";
|
|
11172
11212
|
function envProvider() {
|
|
11173
11213
|
const apiKey = process.env.OPENAI_API_KEY;
|
|
11174
11214
|
if (!apiKey) return null;
|
|
@@ -11211,19 +11251,26 @@ function nodeLlmView(cfg) {
|
|
|
11211
11251
|
global: true
|
|
11212
11252
|
}
|
|
11213
11253
|
] : [],
|
|
11214
|
-
...cfg.providers.map((p) =>
|
|
11215
|
-
|
|
11216
|
-
|
|
11217
|
-
|
|
11218
|
-
|
|
11219
|
-
|
|
11220
|
-
|
|
11221
|
-
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
11226
|
-
|
|
11254
|
+
...cfg.providers.map((p) => {
|
|
11255
|
+
const builtin = isBuiltinProvider(p.id);
|
|
11256
|
+
return {
|
|
11257
|
+
id: p.id,
|
|
11258
|
+
name: p.name,
|
|
11259
|
+
type: p.type ?? "",
|
|
11260
|
+
baseURL: p.baseURL,
|
|
11261
|
+
model: p.model,
|
|
11262
|
+
hasApiKey: Boolean(p.apiKey),
|
|
11263
|
+
models: p.models ?? [],
|
|
11264
|
+
nonChat: p.nonChat ?? [],
|
|
11265
|
+
modelMeta: p.modelMeta ?? [],
|
|
11266
|
+
reasoningEffort: p.reasoningEffort ?? null,
|
|
11267
|
+
global: false,
|
|
11268
|
+
/** 平台内置(接入 Hub 后自动下发,用户不用关心 Key) */
|
|
11269
|
+
builtin,
|
|
11270
|
+
/** 不可编辑的字段:控制台据此把 baseURL / key 显示为只读 */
|
|
11271
|
+
...builtin ? { locked: ["baseURL", "apiKey"] } : {}
|
|
11272
|
+
};
|
|
11273
|
+
})
|
|
11227
11274
|
];
|
|
11228
11275
|
return {
|
|
11229
11276
|
defaultProviderId: cfg.defaultProviderId ?? null,
|
|
@@ -11236,27 +11283,42 @@ function applyNodeLlmPatch(cfg, raw) {
|
|
|
11236
11283
|
const next = { providers: cfg.providers, defaultProviderId: cfg.defaultProviderId };
|
|
11237
11284
|
if (Array.isArray(raw?.providers)) {
|
|
11238
11285
|
const old = new Map(cfg.providers.map((p) => [p.id, p]));
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11286
|
+
const incoming = raw.providers.filter((x) => Boolean(x) && typeof x === "object").filter((x) => x.global !== true && String(x.id ?? "") !== GLOBAL_PROVIDER_ID);
|
|
11287
|
+
const prevBuiltin = cfg.providers.find((p) => isBuiltinProvider(p.id));
|
|
11288
|
+
const builtinPatch = incoming.find((x) => isBuiltinProvider(String(x.id ?? "")));
|
|
11289
|
+
const keptBuiltin = prevBuiltin ? [
|
|
11290
|
+
{
|
|
11291
|
+
...prevBuiltin,
|
|
11292
|
+
...builtinPatch?.model != null ? { model: String(builtinPatch.model).trim() || prevBuiltin.model } : {},
|
|
11293
|
+
...normalizeModelList(builtinPatch?.models) ? { models: normalizeModelList(builtinPatch?.models) } : {},
|
|
11294
|
+
...builtinPatch?.reasoningEffort !== void 0 ? { reasoningEffort: normReasoningEffort(builtinPatch.reasoningEffort) } : {},
|
|
11295
|
+
...typeof builtinPatch?.name === "string" && builtinPatch.name.trim() ? { name: builtinPatch.name.trim() } : {}
|
|
11296
|
+
}
|
|
11297
|
+
] : [];
|
|
11298
|
+
next.providers = [
|
|
11299
|
+
...keptBuiltin,
|
|
11300
|
+
...incoming.filter((x) => !isBuiltinProvider(String(x.id ?? ""))).map((x) => {
|
|
11301
|
+
const id = String(x.id ?? "").trim();
|
|
11302
|
+
if (!id) throw new ApiError(400, "bad_request", "\u4F9B\u5E94\u5546 id \u4E0D\u80FD\u4E3A\u7A7A");
|
|
11303
|
+
const prev = old.get(id);
|
|
11304
|
+
const apiKey = String(x.apiKey ?? "").trim();
|
|
11305
|
+
const models = normalizeModelList(x.models) ?? prev?.models;
|
|
11306
|
+
const nonChat = normalizeModelList(x.nonChat) ?? prev?.nonChat;
|
|
11307
|
+
const modelMeta = normalizeModelMeta(x.modelMeta) ?? prev?.modelMeta;
|
|
11308
|
+
return {
|
|
11309
|
+
id,
|
|
11310
|
+
name: String(x.name ?? prev?.name ?? id).trim(),
|
|
11311
|
+
type: x.type == null ? prev?.type : String(x.type),
|
|
11312
|
+
baseURL: String(x.baseURL ?? prev?.baseURL ?? "").trim(),
|
|
11313
|
+
model: String(x.model ?? prev?.model ?? "").trim(),
|
|
11314
|
+
apiKey: apiKey || prev?.apiKey,
|
|
11315
|
+
reasoningEffort: x.reasoningEffort === void 0 ? prev?.reasoningEffort ?? null : normReasoningEffort(x.reasoningEffort),
|
|
11316
|
+
...models ? { models } : {},
|
|
11317
|
+
...nonChat ? { nonChat } : {},
|
|
11318
|
+
...modelMeta ? { modelMeta } : {}
|
|
11319
|
+
};
|
|
11320
|
+
})
|
|
11321
|
+
];
|
|
11260
11322
|
}
|
|
11261
11323
|
if (typeof raw?.defaultProviderId === "string") {
|
|
11262
11324
|
const id = raw.defaultProviderId.trim();
|
|
@@ -11276,6 +11338,9 @@ function nodeDefaultProvider(store) {
|
|
|
11276
11338
|
if (cfg.providers.length === 0) return null;
|
|
11277
11339
|
return cfg.providers.find((p) => p.id === cfg.defaultProviderId) ?? cfg.providers[0] ?? null;
|
|
11278
11340
|
}
|
|
11341
|
+
function defaultTenantModel(store) {
|
|
11342
|
+
return process.env.OPENAI_MODEL || process.env.MODEL || nodeDefaultProvider(store)?.model || FALLBACK_MODEL;
|
|
11343
|
+
}
|
|
11279
11344
|
function resolveSessionProvider(store, tenant, providerId) {
|
|
11280
11345
|
const own = tenant.provider ?? {};
|
|
11281
11346
|
if (providerId) {
|
|
@@ -11305,6 +11370,208 @@ function resolveSessionProvider(store, tenant, providerId) {
|
|
|
11305
11370
|
return { ...own, model: tenant.model };
|
|
11306
11371
|
}
|
|
11307
11372
|
|
|
11373
|
+
// src/server/builtinLlm.ts
|
|
11374
|
+
init_esm_shims();
|
|
11375
|
+
var FETCH_TIMEOUT_MS = 8e3;
|
|
11376
|
+
var RETRY_AFTER_MS = 5 * 6e4;
|
|
11377
|
+
function hubBase(cred) {
|
|
11378
|
+
return (cred.hubUrl ?? "").replace(/\/+$/, "");
|
|
11379
|
+
}
|
|
11380
|
+
function asProvider(grant) {
|
|
11381
|
+
const baseURL = String(grant.baseURL ?? "").trim();
|
|
11382
|
+
const apiKey = String(grant.apiKey ?? "").trim();
|
|
11383
|
+
const model = String(grant.model ?? "").trim();
|
|
11384
|
+
if (!baseURL || !apiKey) return null;
|
|
11385
|
+
return {
|
|
11386
|
+
id: BUILTIN_PROVIDER_ID,
|
|
11387
|
+
name: String(grant.name ?? "").trim() || "\u5FD7\u524D\u5927\u6A21\u578B\uFF08\u5185\u7F6E\uFF09",
|
|
11388
|
+
type: "builtin",
|
|
11389
|
+
baseURL,
|
|
11390
|
+
model,
|
|
11391
|
+
apiKey
|
|
11392
|
+
};
|
|
11393
|
+
}
|
|
11394
|
+
async function enrichModels(p) {
|
|
11395
|
+
try {
|
|
11396
|
+
const r = await Promise.race([
|
|
11397
|
+
fetchModels(p.baseURL, p.apiKey ?? "", p.model),
|
|
11398
|
+
new Promise((resolve25) => {
|
|
11399
|
+
const t = setTimeout(() => resolve25(null), FETCH_TIMEOUT_MS);
|
|
11400
|
+
t.unref?.();
|
|
11401
|
+
})
|
|
11402
|
+
]);
|
|
11403
|
+
if (!r?.models?.length) return p;
|
|
11404
|
+
return {
|
|
11405
|
+
...p,
|
|
11406
|
+
// 控制面没给默认型号时,取供应商返回的第一个,避免模型为空让用户卡住
|
|
11407
|
+
model: p.model || r.models[0],
|
|
11408
|
+
models: r.models,
|
|
11409
|
+
...r.nonChat?.length ? { nonChat: r.nonChat } : {},
|
|
11410
|
+
...r.modelMeta?.length ? { modelMeta: r.modelMeta } : {}
|
|
11411
|
+
};
|
|
11412
|
+
} catch {
|
|
11413
|
+
return p;
|
|
11414
|
+
}
|
|
11415
|
+
}
|
|
11416
|
+
function saveBuiltin(store, provider) {
|
|
11417
|
+
const cfg = store.loadNodeLlm();
|
|
11418
|
+
const others = cfg.providers.filter((p) => p.id !== BUILTIN_PROVIDER_ID);
|
|
11419
|
+
const prev = cfg.providers.find((p) => p.id === BUILTIN_PROVIDER_ID);
|
|
11420
|
+
const merged = {
|
|
11421
|
+
...provider,
|
|
11422
|
+
// 用户选过的型号/候选列表/推理强度/显示名都保留;只有托管字段(baseURL/key)强制以控制面为准
|
|
11423
|
+
...prev?.model ? { model: prev.model } : {},
|
|
11424
|
+
...prev?.models?.length ? { models: prev.models } : {},
|
|
11425
|
+
...prev?.reasoningEffort != null ? { reasoningEffort: prev.reasoningEffort } : {},
|
|
11426
|
+
...prev?.name ? { name: prev.name } : {}
|
|
11427
|
+
};
|
|
11428
|
+
store.saveNodeLlm({
|
|
11429
|
+
providers: [merged, ...others],
|
|
11430
|
+
// 之前没有默认且用户也没指定时,让内置模型成为默认——「开箱即用」
|
|
11431
|
+
defaultProviderId: cfg.defaultProviderId ?? BUILTIN_PROVIDER_ID
|
|
11432
|
+
});
|
|
11433
|
+
adoptBuiltinModelForTenants(store, merged.model);
|
|
11434
|
+
}
|
|
11435
|
+
var LEGACY_DEFAULT_MODELS = /* @__PURE__ */ new Set([FALLBACK_MODEL, "deepseek-v4-flash"]);
|
|
11436
|
+
function adoptBuiltinModelForTenants(store, model) {
|
|
11437
|
+
if (!model) return;
|
|
11438
|
+
for (const id of store.listTenants()) {
|
|
11439
|
+
const tenant = store.loadTenant(id);
|
|
11440
|
+
if (!tenant || !LEGACY_DEFAULT_MODELS.has(tenant.model)) continue;
|
|
11441
|
+
if (tenant.provider?.apiKey) continue;
|
|
11442
|
+
tenant.model = model;
|
|
11443
|
+
store.saveTenant(tenant);
|
|
11444
|
+
}
|
|
11445
|
+
}
|
|
11446
|
+
async function ensureBuiltinProvider(store, opts = {}) {
|
|
11447
|
+
const cred = store.loadFleetCredential();
|
|
11448
|
+
if (!cred?.fleetToken || !cred.fleetSecret) {
|
|
11449
|
+
return { status: "disabled", reason: "\u8282\u70B9\u672A\u63A5\u5165 Hub" };
|
|
11450
|
+
}
|
|
11451
|
+
const hub = hubBase(cred);
|
|
11452
|
+
if (!hub) return { status: "disabled", reason: "\u7F3A\u5C11 Hub \u5730\u5740" };
|
|
11453
|
+
const local = store.loadNodeLlm().providers.find((p) => p.id === BUILTIN_PROVIDER_ID);
|
|
11454
|
+
if (local && !opts.force) {
|
|
11455
|
+
adoptBuiltinModelForTenants(store, local.model);
|
|
11456
|
+
return { status: "ready", provider: local, refreshed: false };
|
|
11457
|
+
}
|
|
11458
|
+
const cached3 = cred.builtinLlm ? asProvider(cred.builtinLlm) : null;
|
|
11459
|
+
let res;
|
|
11460
|
+
try {
|
|
11461
|
+
res = await fetch(`${hub}/api/hub/node/builtin-llm`, {
|
|
11462
|
+
headers: {
|
|
11463
|
+
Authorization: `Bearer ${cred.fleetToken}`,
|
|
11464
|
+
"X-Fleet-Secret": cred.fleetSecret,
|
|
11465
|
+
"X-Node-Id": cred.nodeId
|
|
11466
|
+
},
|
|
11467
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
11468
|
+
});
|
|
11469
|
+
} catch (e) {
|
|
11470
|
+
if (cached3) {
|
|
11471
|
+
const provider2 = await enrichModels(cached3);
|
|
11472
|
+
saveBuiltin(store, provider2);
|
|
11473
|
+
return { status: "ready", provider: provider2, refreshed: true };
|
|
11474
|
+
}
|
|
11475
|
+
return { status: "error", reason: `\u8FDE\u63A5 Hub \u5931\u8D25\uFF1A${e.message}` };
|
|
11476
|
+
}
|
|
11477
|
+
let body = null;
|
|
11478
|
+
try {
|
|
11479
|
+
body = await res.json();
|
|
11480
|
+
} catch {
|
|
11481
|
+
}
|
|
11482
|
+
if (!res.ok) {
|
|
11483
|
+
const msg = body?.error?.message ?? `HTTP ${res.status}`;
|
|
11484
|
+
if (res.status === 401 || res.status === 403) {
|
|
11485
|
+
return { status: "unavailable", reason: msg };
|
|
11486
|
+
}
|
|
11487
|
+
if (cached3) {
|
|
11488
|
+
const provider2 = await enrichModels(cached3);
|
|
11489
|
+
saveBuiltin(store, provider2);
|
|
11490
|
+
return { status: "ready", provider: provider2, refreshed: true };
|
|
11491
|
+
}
|
|
11492
|
+
return { status: "error", reason: msg };
|
|
11493
|
+
}
|
|
11494
|
+
const grant = body?.data?.builtinLlm;
|
|
11495
|
+
if (!grant) {
|
|
11496
|
+
const why = String(body?.data?.reason ?? "").trim();
|
|
11497
|
+
return { status: "unavailable", reason: why || "\u63A7\u5236\u9762\u672A\u4E0B\u53D1\u5185\u7F6E\u6A21\u578B" };
|
|
11498
|
+
}
|
|
11499
|
+
const parsed = asProvider(grant);
|
|
11500
|
+
if (!parsed) return { status: "unavailable", reason: "\u5185\u7F6E\u6A21\u578B\u914D\u7F6E\u4E0D\u5B8C\u6574" };
|
|
11501
|
+
const provider = await enrichModels(parsed);
|
|
11502
|
+
saveBuiltin(store, provider);
|
|
11503
|
+
return { status: "ready", provider, refreshed: true };
|
|
11504
|
+
}
|
|
11505
|
+
async function fetchLlmBalance(store) {
|
|
11506
|
+
const cred = store.loadFleetCredential();
|
|
11507
|
+
const hub = cred ? hubBase(cred) : "";
|
|
11508
|
+
if (!cred?.fleetToken || !cred.fleetSecret || !hub) {
|
|
11509
|
+
return { available: null, currency: "CNY", reason: "\u8282\u70B9\u672A\u63A5\u5165 Hub" };
|
|
11510
|
+
}
|
|
11511
|
+
try {
|
|
11512
|
+
const res = await fetch(`${hub}/api/hub/node/balance`, {
|
|
11513
|
+
headers: {
|
|
11514
|
+
Authorization: `Bearer ${cred.fleetToken}`,
|
|
11515
|
+
"X-Fleet-Secret": cred.fleetSecret,
|
|
11516
|
+
"X-Node-Id": cred.nodeId
|
|
11517
|
+
},
|
|
11518
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
11519
|
+
});
|
|
11520
|
+
const body = await res.json().catch(() => null);
|
|
11521
|
+
if (!res.ok) {
|
|
11522
|
+
return {
|
|
11523
|
+
available: null,
|
|
11524
|
+
currency: "CNY",
|
|
11525
|
+
reason: body?.data ? "" : `HTTP ${res.status}`
|
|
11526
|
+
};
|
|
11527
|
+
}
|
|
11528
|
+
const d = body?.data ?? {};
|
|
11529
|
+
const available = typeof d.available === "number" ? d.available : null;
|
|
11530
|
+
return {
|
|
11531
|
+
available,
|
|
11532
|
+
currency: typeof d.currency === "string" && d.currency ? d.currency : "CNY",
|
|
11533
|
+
...typeof d.reserved === "number" ? { reserved: d.reserved } : {},
|
|
11534
|
+
// Hub 没配 HUB_PUBLIC_URL 时退回用接入时的 hubUrl
|
|
11535
|
+
topupUrl: typeof d.topupUrl === "string" && d.topupUrl ? d.topupUrl : `${hub}/topup`,
|
|
11536
|
+
...available === null && typeof d.reason === "string" ? { reason: d.reason } : {}
|
|
11537
|
+
};
|
|
11538
|
+
} catch (e) {
|
|
11539
|
+
return {
|
|
11540
|
+
available: null,
|
|
11541
|
+
currency: "CNY",
|
|
11542
|
+
reason: `\u8FDE\u63A5 Hub \u5931\u8D25\uFF1A${e.message}`
|
|
11543
|
+
};
|
|
11544
|
+
}
|
|
11545
|
+
}
|
|
11546
|
+
var AUTH_RETRY_THROTTLE_MS = 6e4;
|
|
11547
|
+
var lastAuthRetryAt = 0;
|
|
11548
|
+
function healBuiltinOnAuthFailure(store, message) {
|
|
11549
|
+
if (!/401|unauthorized|invalid[_\s]*api[_\s]*key|api[\s_-]*key\s*(?:无效|invalid)/i.test(message)) return;
|
|
11550
|
+
if (!store.loadFleetCredential()) return;
|
|
11551
|
+
if (!store.loadNodeLlm().providers.some((p) => p.id === BUILTIN_PROVIDER_ID)) return;
|
|
11552
|
+
if (Date.now() - lastAuthRetryAt < AUTH_RETRY_THROTTLE_MS) return;
|
|
11553
|
+
lastAuthRetryAt = Date.now();
|
|
11554
|
+
void ensureBuiltinProvider(store, { force: true }).catch(() => {
|
|
11555
|
+
});
|
|
11556
|
+
}
|
|
11557
|
+
var lastFailureAt = 0;
|
|
11558
|
+
function scheduleBuiltinProvider(store, log = () => {
|
|
11559
|
+
}) {
|
|
11560
|
+
if (Date.now() - lastFailureAt < RETRY_AFTER_MS) return;
|
|
11561
|
+
void ensureBuiltinProvider(store).then((r) => {
|
|
11562
|
+
if (r.status === "ready") {
|
|
11563
|
+
if (r.refreshed) log(`[builtin-llm] \u5DF2\u4E0B\u53D1\u5185\u7F6E\u6A21\u578B\uFF1A${r.provider.name}\uFF08${r.provider.model}\uFF09`);
|
|
11564
|
+
return;
|
|
11565
|
+
}
|
|
11566
|
+
if (r.status === "disabled") return;
|
|
11567
|
+
lastFailureAt = Date.now();
|
|
11568
|
+
if (r.status === "unavailable") log(`[builtin-llm] \u6682\u65E0\u5185\u7F6E\u6A21\u578B\uFF1A${r.reason}`);
|
|
11569
|
+
else log(`[builtin-llm] \u62C9\u53D6\u5185\u7F6E\u6A21\u578B\u5931\u8D25\uFF1A${r.reason}`);
|
|
11570
|
+
}).catch(() => {
|
|
11571
|
+
lastFailureAt = Date.now();
|
|
11572
|
+
});
|
|
11573
|
+
}
|
|
11574
|
+
|
|
11308
11575
|
// src/server/usage.ts
|
|
11309
11576
|
init_esm_shims();
|
|
11310
11577
|
import * as fs19 from "fs";
|
|
@@ -13366,6 +13633,7 @@ data: ${JSON.stringify(entry.data)}
|
|
|
13366
13633
|
this._setStatus(rt, "error");
|
|
13367
13634
|
this._persist(rt);
|
|
13368
13635
|
this._emitNotify(rt, "error", this._turnEndData(rt, event.data, {}));
|
|
13636
|
+
healBuiltinOnAuthFailure(this.store, String(event.data["error"] ?? ""));
|
|
13369
13637
|
break;
|
|
13370
13638
|
case "interrupted" /* INTERRUPTED */:
|
|
13371
13639
|
this._setStatus(rt, "interrupted");
|
|
@@ -13789,7 +14057,6 @@ var ApiError = class extends Error {
|
|
|
13789
14057
|
};
|
|
13790
14058
|
|
|
13791
14059
|
// src/server/projects.ts
|
|
13792
|
-
var DEFAULT_MODEL = () => process.env.OPENAI_MODEL || process.env.MODEL || "gpt-4o";
|
|
13793
14060
|
function toProjectSummary(store, tenant) {
|
|
13794
14061
|
return {
|
|
13795
14062
|
id: tenant.id,
|
|
@@ -13929,7 +14196,7 @@ function createProject(store, input) {
|
|
|
13929
14196
|
id,
|
|
13930
14197
|
name: explicitName || defaultName,
|
|
13931
14198
|
apiKey: generateApiKey(),
|
|
13932
|
-
model: typeof raw.model === "string" && raw.model.trim() ? raw.model.trim() :
|
|
14199
|
+
model: typeof raw.model === "string" && raw.model.trim() ? raw.model.trim() : defaultTenantModel(store),
|
|
13933
14200
|
provider: {
|
|
13934
14201
|
apiKey: typeof raw.providerApiKey === "string" && raw.providerApiKey.trim() ? raw.providerApiKey.trim() : void 0,
|
|
13935
14202
|
baseURL: typeof raw.baseURL === "string" && raw.baseURL.trim() ? raw.baseURL.trim() : void 0
|
|
@@ -13954,7 +14221,7 @@ function buildNodeInfo(store, opts) {
|
|
|
13954
14221
|
nodeId: opts.nodeId ?? ensureNodeId(store),
|
|
13955
14222
|
platform: process.platform,
|
|
13956
14223
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
13957
|
-
version: "0.2.
|
|
14224
|
+
version: "0.2.20",
|
|
13958
14225
|
admin: opts.admin,
|
|
13959
14226
|
projects: opts.projects
|
|
13960
14227
|
};
|
|
@@ -14170,7 +14437,7 @@ import * as path26 from "path";
|
|
|
14170
14437
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
14171
14438
|
import { createRequire as createRequire3 } from "module";
|
|
14172
14439
|
function currentVersion() {
|
|
14173
|
-
const injected = "0.2.
|
|
14440
|
+
const injected = "0.2.20"?.trim();
|
|
14174
14441
|
if (injected) return injected;
|
|
14175
14442
|
try {
|
|
14176
14443
|
const req2 = createRequire3(import.meta.url);
|
|
@@ -15506,10 +15773,133 @@ function makeDirIn(parentInput, name) {
|
|
|
15506
15773
|
init_esm_shims();
|
|
15507
15774
|
import * as fs23 from "fs";
|
|
15508
15775
|
import * as path31 from "path";
|
|
15776
|
+
|
|
15777
|
+
// src/server/zipArchive.ts
|
|
15778
|
+
init_esm_shims();
|
|
15779
|
+
import * as zlib from "zlib";
|
|
15780
|
+
var MAX_ZIP_ENTRIES = 2e4;
|
|
15781
|
+
var LOCAL_SIG = 67324752;
|
|
15782
|
+
var CENTRAL_SIG = 33639248;
|
|
15783
|
+
var EOCD_SIG = 101010256;
|
|
15784
|
+
var FLAG_UTF8 = 2048;
|
|
15785
|
+
var METHOD_STORE = 0;
|
|
15786
|
+
var METHOD_DEFLATE = 8;
|
|
15787
|
+
var CRC_TABLE = (() => {
|
|
15788
|
+
const table = new Int32Array(256);
|
|
15789
|
+
for (let n = 0; n < 256; n++) {
|
|
15790
|
+
let c = n;
|
|
15791
|
+
for (let k = 0; k < 8; k++) {
|
|
15792
|
+
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
15793
|
+
}
|
|
15794
|
+
table[n] = c;
|
|
15795
|
+
}
|
|
15796
|
+
return table;
|
|
15797
|
+
})();
|
|
15798
|
+
function crc32(buf) {
|
|
15799
|
+
let c = -1;
|
|
15800
|
+
for (let i = 0; i < buf.length; i++) {
|
|
15801
|
+
c = CRC_TABLE[(c ^ buf[i]) & 255] ^ c >>> 8;
|
|
15802
|
+
}
|
|
15803
|
+
return (c ^ -1) >>> 0;
|
|
15804
|
+
}
|
|
15805
|
+
function dosDateTime(d) {
|
|
15806
|
+
const year = Math.max(1980, d.getFullYear());
|
|
15807
|
+
return {
|
|
15808
|
+
time: d.getHours() << 11 | d.getMinutes() << 5 | d.getSeconds() >> 1,
|
|
15809
|
+
date: year - 1980 << 9 | d.getMonth() + 1 << 5 | d.getDate()
|
|
15810
|
+
};
|
|
15811
|
+
}
|
|
15812
|
+
function buildZip(entries) {
|
|
15813
|
+
if (entries.length > MAX_ZIP_ENTRIES) {
|
|
15814
|
+
throw new Error(`\u5F52\u6863\u6761\u76EE\u8FC7\u591A\uFF08${entries.length} > ${MAX_ZIP_ENTRIES}\uFF09`);
|
|
15815
|
+
}
|
|
15816
|
+
const chunks = [];
|
|
15817
|
+
const central = [];
|
|
15818
|
+
let offset = 0;
|
|
15819
|
+
for (const e of entries) {
|
|
15820
|
+
const name = Buffer.from(e.name, "utf-8");
|
|
15821
|
+
const isDir = e.name.endsWith("/");
|
|
15822
|
+
const raw = isDir ? Buffer.alloc(0) : e.data ?? Buffer.alloc(0);
|
|
15823
|
+
let method = METHOD_STORE;
|
|
15824
|
+
let body = raw;
|
|
15825
|
+
if (!isDir && raw.length > 0) {
|
|
15826
|
+
const deflated = zlib.deflateRawSync(raw, { level: 6 });
|
|
15827
|
+
if (deflated.length < raw.length) {
|
|
15828
|
+
method = METHOD_DEFLATE;
|
|
15829
|
+
body = deflated;
|
|
15830
|
+
}
|
|
15831
|
+
}
|
|
15832
|
+
const crc = isDir ? 0 : crc32(raw);
|
|
15833
|
+
const { time, date } = dosDateTime(e.mtime ?? /* @__PURE__ */ new Date());
|
|
15834
|
+
const local = Buffer.alloc(30);
|
|
15835
|
+
local.writeUInt32LE(LOCAL_SIG, 0);
|
|
15836
|
+
local.writeUInt16LE(20, 4);
|
|
15837
|
+
local.writeUInt16LE(FLAG_UTF8, 6);
|
|
15838
|
+
local.writeUInt16LE(method, 8);
|
|
15839
|
+
local.writeUInt16LE(time, 10);
|
|
15840
|
+
local.writeUInt16LE(date, 12);
|
|
15841
|
+
local.writeUInt32LE(crc, 14);
|
|
15842
|
+
local.writeUInt32LE(body.length, 18);
|
|
15843
|
+
local.writeUInt32LE(raw.length, 22);
|
|
15844
|
+
local.writeUInt16LE(name.length, 26);
|
|
15845
|
+
local.writeUInt16LE(0, 28);
|
|
15846
|
+
chunks.push(local, name);
|
|
15847
|
+
if (body.length > 0) chunks.push(body);
|
|
15848
|
+
central.push({
|
|
15849
|
+
name,
|
|
15850
|
+
method,
|
|
15851
|
+
crc,
|
|
15852
|
+
csize: body.length,
|
|
15853
|
+
usize: raw.length,
|
|
15854
|
+
offset,
|
|
15855
|
+
time,
|
|
15856
|
+
date,
|
|
15857
|
+
isDir
|
|
15858
|
+
});
|
|
15859
|
+
offset += local.length + name.length + body.length;
|
|
15860
|
+
}
|
|
15861
|
+
const cdStart = offset;
|
|
15862
|
+
for (const c of central) {
|
|
15863
|
+
const head = Buffer.alloc(46);
|
|
15864
|
+
head.writeUInt32LE(CENTRAL_SIG, 0);
|
|
15865
|
+
head.writeUInt16LE(20, 4);
|
|
15866
|
+
head.writeUInt16LE(20, 6);
|
|
15867
|
+
head.writeUInt16LE(FLAG_UTF8, 8);
|
|
15868
|
+
head.writeUInt16LE(c.method, 10);
|
|
15869
|
+
head.writeUInt16LE(c.time, 12);
|
|
15870
|
+
head.writeUInt16LE(c.date, 14);
|
|
15871
|
+
head.writeUInt32LE(c.crc, 16);
|
|
15872
|
+
head.writeUInt32LE(c.csize, 20);
|
|
15873
|
+
head.writeUInt32LE(c.usize, 24);
|
|
15874
|
+
head.writeUInt16LE(c.name.length, 28);
|
|
15875
|
+
head.writeUInt16LE(0, 30);
|
|
15876
|
+
head.writeUInt16LE(0, 32);
|
|
15877
|
+
head.writeUInt16LE(0, 34);
|
|
15878
|
+
head.writeUInt16LE(0, 36);
|
|
15879
|
+
head.writeUInt32LE(c.isDir ? 16 : 0, 38);
|
|
15880
|
+
head.writeUInt32LE(c.offset, 42);
|
|
15881
|
+
chunks.push(head, c.name);
|
|
15882
|
+
offset += head.length + c.name.length;
|
|
15883
|
+
}
|
|
15884
|
+
const eocd = Buffer.alloc(22);
|
|
15885
|
+
eocd.writeUInt32LE(EOCD_SIG, 0);
|
|
15886
|
+
eocd.writeUInt16LE(0, 4);
|
|
15887
|
+
eocd.writeUInt16LE(0, 6);
|
|
15888
|
+
eocd.writeUInt16LE(central.length, 8);
|
|
15889
|
+
eocd.writeUInt16LE(central.length, 10);
|
|
15890
|
+
eocd.writeUInt32LE(offset - cdStart, 12);
|
|
15891
|
+
eocd.writeUInt32LE(cdStart, 16);
|
|
15892
|
+
eocd.writeUInt16LE(0, 20);
|
|
15893
|
+
chunks.push(eocd);
|
|
15894
|
+
return Buffer.concat(chunks);
|
|
15895
|
+
}
|
|
15896
|
+
|
|
15897
|
+
// src/server/projectFiles.ts
|
|
15509
15898
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
15510
15899
|
var MAX_DOWNLOAD_BYTES = 16 * 1024 * 1024;
|
|
15511
15900
|
var MAX_BINARY_BYTES = 2.5 * 1024 * 1024;
|
|
15512
15901
|
var MAX_ENTRIES2 = 2e3;
|
|
15902
|
+
var MAX_ZIP_BYTES = 100 * 1024 * 1024;
|
|
15513
15903
|
function toPosix(p) {
|
|
15514
15904
|
return p.split(path31.sep).join("/");
|
|
15515
15905
|
}
|
|
@@ -15785,6 +16175,134 @@ function deleteProjectPaths(workspaceRoot, relPaths) {
|
|
|
15785
16175
|
}
|
|
15786
16176
|
return out;
|
|
15787
16177
|
}
|
|
16178
|
+
function formatBytes(n) {
|
|
16179
|
+
if (n >= 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
16180
|
+
if (n >= 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
16181
|
+
return `${n} B`;
|
|
16182
|
+
}
|
|
16183
|
+
function renameProjectPath(workspaceRoot, relPath, newName) {
|
|
16184
|
+
const base = projectRoot(workspaceRoot);
|
|
16185
|
+
const rel = (relPath ?? "").trim().replace(/^[/\\]+/, "");
|
|
16186
|
+
if (!rel) throw new Error("\u4E0D\u80FD\u91CD\u547D\u540D\u9879\u76EE\u6839\u76EE\u5F55");
|
|
16187
|
+
const abs = resolveWithin(base, rel);
|
|
16188
|
+
const name = (newName ?? "").trim();
|
|
16189
|
+
if (!name) throw new Error("\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
|
|
16190
|
+
if (name === "." || name === "..") throw new Error("\u540D\u79F0\u975E\u6CD5");
|
|
16191
|
+
if (/[/\\]/.test(name)) throw new Error("\u540D\u79F0\u4E0D\u80FD\u5305\u542B\u8DEF\u5F84\u5206\u9694\u7B26");
|
|
16192
|
+
if (!fs23.existsSync(abs)) throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
16193
|
+
const parent = path31.dirname(abs);
|
|
16194
|
+
const target = path31.join(parent, name);
|
|
16195
|
+
if (!isWithinRoot(base, target)) throw new Error("\u8DEF\u5F84\u8D8A\u754C\uFF08\u8D85\u51FA\u9879\u76EE\u5DE5\u4F5C\u533A\uFF09");
|
|
16196
|
+
if (fs23.existsSync(target)) {
|
|
16197
|
+
let same = false;
|
|
16198
|
+
try {
|
|
16199
|
+
const a = fs23.statSync(target);
|
|
16200
|
+
const b = fs23.statSync(abs);
|
|
16201
|
+
same = a.ino === b.ino && a.dev === b.dev;
|
|
16202
|
+
} catch {
|
|
16203
|
+
same = false;
|
|
16204
|
+
}
|
|
16205
|
+
if (!same) throw new Error(`\u5DF2\u5B58\u5728\u540C\u540D\u6587\u4EF6\u6216\u76EE\u5F55: ${name}`);
|
|
16206
|
+
}
|
|
16207
|
+
if (path31.resolve(target) === path31.resolve(abs)) {
|
|
16208
|
+
return { from: toPosix(path31.relative(base, abs)), path: toPosix(path31.relative(base, abs)) };
|
|
16209
|
+
}
|
|
16210
|
+
try {
|
|
16211
|
+
fs23.renameSync(abs, target);
|
|
16212
|
+
} catch (e) {
|
|
16213
|
+
throw new Error(`\u91CD\u547D\u540D\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
|
|
16214
|
+
}
|
|
16215
|
+
return { from: toPosix(path31.relative(base, abs)), path: toPosix(path31.relative(base, target)) };
|
|
16216
|
+
}
|
|
16217
|
+
function zipProjectPaths(workspaceRoot, relPaths, opts = {}) {
|
|
16218
|
+
const base = projectRoot(workspaceRoot);
|
|
16219
|
+
const maxBytes = opts.maxBytes && opts.maxBytes > 0 ? opts.maxBytes : MAX_ZIP_BYTES;
|
|
16220
|
+
const rels = (relPaths ?? []).map((x) => (x ?? "").trim().replace(/^[/\\]+/, ""));
|
|
16221
|
+
if (rels.length === 0) throw new Error("\u8BF7\u9009\u62E9\u8981\u538B\u7F29\u7684\u6587\u4EF6\u6216\u76EE\u5F55");
|
|
16222
|
+
if (rels.some((r) => !r)) throw new Error("\u4E0D\u80FD\u538B\u7F29\u9879\u76EE\u6839\u76EE\u5F55");
|
|
16223
|
+
const targets = rels.map((rel) => ({ rel, abs: resolveWithin(base, rel) }));
|
|
16224
|
+
const single = targets.length === 1 ? targets[0].abs : "";
|
|
16225
|
+
const items = [];
|
|
16226
|
+
let total = 0;
|
|
16227
|
+
const overLimit = () => new Error(
|
|
16228
|
+
`\u5171 ${formatBytes(total)}\uFF0C\u8D85\u8FC7 ${formatBytes(maxBytes)} \u4E0A\u9650\uFF0C\u4E0D\u652F\u6301\u538B\u7F29\u4E0B\u8F7D`
|
|
16229
|
+
);
|
|
16230
|
+
const walk = (absDir) => {
|
|
16231
|
+
let dirents;
|
|
16232
|
+
try {
|
|
16233
|
+
dirents = fs23.readdirSync(absDir, { withFileTypes: true });
|
|
16234
|
+
} catch {
|
|
16235
|
+
return 0;
|
|
16236
|
+
}
|
|
16237
|
+
dirents.sort((a, b) => a.name.localeCompare(b.name));
|
|
16238
|
+
let files = 0;
|
|
16239
|
+
for (const d of dirents) {
|
|
16240
|
+
if (d.isSymbolicLink()) continue;
|
|
16241
|
+
const child = path31.join(absDir, d.name);
|
|
16242
|
+
if (d.isDirectory()) {
|
|
16243
|
+
files += walk(child);
|
|
16244
|
+
continue;
|
|
16245
|
+
}
|
|
16246
|
+
if (!d.isFile()) continue;
|
|
16247
|
+
let st;
|
|
16248
|
+
try {
|
|
16249
|
+
st = fs23.statSync(child);
|
|
16250
|
+
} catch {
|
|
16251
|
+
continue;
|
|
16252
|
+
}
|
|
16253
|
+
total += st.size;
|
|
16254
|
+
if (total > maxBytes) throw overLimit();
|
|
16255
|
+
if (items.length >= MAX_ZIP_ENTRIES) {
|
|
16256
|
+
throw new Error(`\u5F52\u6863\u6761\u76EE\u8FC7\u591A\uFF08\u8D85\u8FC7 ${MAX_ZIP_ENTRIES} \u9879\uFF09\uFF0C\u8BF7\u7F29\u5C0F\u8303\u56F4\u540E\u518D\u8BD5`);
|
|
16257
|
+
}
|
|
16258
|
+
items.push({ abs: child, dir: false, size: st.size, mtime: st.mtime });
|
|
16259
|
+
files++;
|
|
16260
|
+
}
|
|
16261
|
+
if (files === 0) {
|
|
16262
|
+
let mtime = /* @__PURE__ */ new Date();
|
|
16263
|
+
try {
|
|
16264
|
+
mtime = fs23.statSync(absDir).mtime;
|
|
16265
|
+
} catch {
|
|
16266
|
+
}
|
|
16267
|
+
items.push({ abs: absDir, dir: true, size: 0, mtime });
|
|
16268
|
+
}
|
|
16269
|
+
return files;
|
|
16270
|
+
};
|
|
16271
|
+
for (const t of targets) {
|
|
16272
|
+
let st;
|
|
16273
|
+
try {
|
|
16274
|
+
st = fs23.statSync(t.abs);
|
|
16275
|
+
} catch {
|
|
16276
|
+
throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${t.rel}`);
|
|
16277
|
+
}
|
|
16278
|
+
if (st.isDirectory()) {
|
|
16279
|
+
walk(t.abs);
|
|
16280
|
+
continue;
|
|
16281
|
+
}
|
|
16282
|
+
total += st.size;
|
|
16283
|
+
if (total > maxBytes) throw overLimit();
|
|
16284
|
+
items.push({ abs: t.abs, dir: false, size: st.size, mtime: st.mtime });
|
|
16285
|
+
}
|
|
16286
|
+
const nameOf = (abs) => {
|
|
16287
|
+
const rel = toPosix(path31.relative(single || base, abs));
|
|
16288
|
+
return rel || path31.posix.basename(toPosix(abs));
|
|
16289
|
+
};
|
|
16290
|
+
const zipEntries = items.map((it) => {
|
|
16291
|
+
const name2 = nameOf(it.abs);
|
|
16292
|
+
if (it.dir) return { name: `${name2}/`, mtime: it.mtime };
|
|
16293
|
+
return { name: name2, data: fs23.readFileSync(it.abs), mtime: it.mtime };
|
|
16294
|
+
});
|
|
16295
|
+
const buf = buildZip(zipEntries);
|
|
16296
|
+
const first = targets[0].rel;
|
|
16297
|
+
const name = single ? `${path31.posix.basename(toPosix(first))}.zip` : "archive.zip";
|
|
16298
|
+
return {
|
|
16299
|
+
name,
|
|
16300
|
+
size: buf.length,
|
|
16301
|
+
total,
|
|
16302
|
+
entries: zipEntries.length,
|
|
16303
|
+
base64: buf.toString("base64")
|
|
16304
|
+
};
|
|
16305
|
+
}
|
|
15788
16306
|
|
|
15789
16307
|
// src/server/projectOps.ts
|
|
15790
16308
|
init_esm_shims();
|
|
@@ -16114,6 +16632,7 @@ function projectStats(manager, tenantId) {
|
|
|
16114
16632
|
|
|
16115
16633
|
// src/server/nodeHost.ts
|
|
16116
16634
|
init_esm_shims();
|
|
16635
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
16117
16636
|
import * as fs24 from "fs";
|
|
16118
16637
|
import * as os9 from "os";
|
|
16119
16638
|
function diskInfo(pathStr) {
|
|
@@ -16128,6 +16647,64 @@ function diskInfo(pathStr) {
|
|
|
16128
16647
|
return null;
|
|
16129
16648
|
}
|
|
16130
16649
|
}
|
|
16650
|
+
var PSEUDO_FS = /^(devfs|tmpfs|devtmpfs|proc|procfs|sysfs|none|udev|shm|mqueue|devpts|hugetlbfs|debugfs|tracefs|securityfs|pstore|bpf|configfs|fusectl|nsfs|autofs|efivarfs|ramfs|map)$/;
|
|
16651
|
+
function isInternalMount(mount) {
|
|
16652
|
+
if (mount === "/") return false;
|
|
16653
|
+
const prefixes = ["/proc", "/sys", "/run", "/snap"];
|
|
16654
|
+
if (process.platform === "darwin") prefixes.push("/System/Volumes");
|
|
16655
|
+
return prefixes.some((p) => mount === p || mount.startsWith(`${p}/`));
|
|
16656
|
+
}
|
|
16657
|
+
function readOnlyVolumes() {
|
|
16658
|
+
const out = /* @__PURE__ */ new Set();
|
|
16659
|
+
const res = spawnSync4("mount", [], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
|
|
16660
|
+
if (res.error || res.status !== 0 || !res.stdout) return out;
|
|
16661
|
+
for (const line of res.stdout.split("\n")) {
|
|
16662
|
+
const m = line.match(/^.+? on (.+?) \(([^)]*)\)$/);
|
|
16663
|
+
if (!m || m[1] === "/") continue;
|
|
16664
|
+
if (m[2].split(",").some((opt) => opt.trim() === "read-only")) out.add(m[1]);
|
|
16665
|
+
}
|
|
16666
|
+
return out;
|
|
16667
|
+
}
|
|
16668
|
+
function diskList(workspacePath) {
|
|
16669
|
+
const out = [];
|
|
16670
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16671
|
+
const push = (path45, total, free) => {
|
|
16672
|
+
if (!path45 || seen.has(path45) || !Number.isFinite(total) || total <= 0) return;
|
|
16673
|
+
seen.add(path45);
|
|
16674
|
+
out.push({ path: path45, total, free });
|
|
16675
|
+
};
|
|
16676
|
+
if (process.platform === "win32") {
|
|
16677
|
+
for (const letter of "CDEFGHIJKLMNOPQRSTUVWXYZ") {
|
|
16678
|
+
const root = `${letter}:\\`;
|
|
16679
|
+
const d = diskInfo(root);
|
|
16680
|
+
if (d) push(root, d.total, d.free);
|
|
16681
|
+
}
|
|
16682
|
+
} else {
|
|
16683
|
+
const readonly = process.platform === "darwin" ? readOnlyVolumes() : /* @__PURE__ */ new Set();
|
|
16684
|
+
const res = spawnSync4("df", ["-kP"], {
|
|
16685
|
+
encoding: "utf-8",
|
|
16686
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
16687
|
+
});
|
|
16688
|
+
if (!res.error && res.status === 0 && res.stdout) {
|
|
16689
|
+
for (const line of res.stdout.split("\n").slice(1)) {
|
|
16690
|
+
const m = line.trim().match(/^(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s+(.+)$/);
|
|
16691
|
+
if (!m || PSEUDO_FS.test(m[1])) continue;
|
|
16692
|
+
if (/^\/dev\/loop\d+$/.test(m[1])) continue;
|
|
16693
|
+
if (isInternalMount(m[5]) || readonly.has(m[5])) continue;
|
|
16694
|
+
push(m[5], Number(m[2]) * 1024, Number(m[4]) * 1024);
|
|
16695
|
+
}
|
|
16696
|
+
}
|
|
16697
|
+
}
|
|
16698
|
+
const primary = diskInfo(workspacePath);
|
|
16699
|
+
if (primary) {
|
|
16700
|
+
const covered = out.some((d) => {
|
|
16701
|
+
const root = d.path.endsWith("/") || d.path.endsWith("\\") ? d.path : `${d.path}/`;
|
|
16702
|
+
return workspacePath === d.path || workspacePath.startsWith(root);
|
|
16703
|
+
});
|
|
16704
|
+
if (!covered) push(primary.path, primary.total, primary.free);
|
|
16705
|
+
}
|
|
16706
|
+
return out.sort((a, b) => b.total - a.total);
|
|
16707
|
+
}
|
|
16131
16708
|
function networkInfo() {
|
|
16132
16709
|
const out = [];
|
|
16133
16710
|
const ifaces = os9.networkInterfaces();
|
|
@@ -16183,6 +16760,7 @@ function overview(store, manager) {
|
|
|
16183
16760
|
function buildNodeHost(store, manager, diskPath) {
|
|
16184
16761
|
const cpus2 = os9.cpus();
|
|
16185
16762
|
const ov = overview(store, manager);
|
|
16763
|
+
const disks = diskList(diskPath || process.cwd());
|
|
16186
16764
|
return {
|
|
16187
16765
|
nodeId: store.loadNodeId() ?? "",
|
|
16188
16766
|
hostname: os9.hostname(),
|
|
@@ -16190,7 +16768,7 @@ function buildNodeHost(store, manager, diskPath) {
|
|
|
16190
16768
|
arch: process.arch,
|
|
16191
16769
|
release: os9.release(),
|
|
16192
16770
|
uptimeSec: Math.round(os9.uptime()),
|
|
16193
|
-
version: "0.2.
|
|
16771
|
+
version: "0.2.20",
|
|
16194
16772
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
16195
16773
|
cpu: {
|
|
16196
16774
|
count: cpus2.length,
|
|
@@ -16200,6 +16778,7 @@ function buildNodeHost(store, manager, diskPath) {
|
|
|
16200
16778
|
memory: { total: os9.totalmem(), free: os9.freemem() },
|
|
16201
16779
|
network: networkInfo(),
|
|
16202
16780
|
disk: diskInfo(diskPath || process.cwd()),
|
|
16781
|
+
disks,
|
|
16203
16782
|
...ov
|
|
16204
16783
|
};
|
|
16205
16784
|
}
|
|
@@ -17425,6 +18004,41 @@ function createApp(store, manager, opts = {}) {
|
|
|
17425
18004
|
}
|
|
17426
18005
|
}
|
|
17427
18006
|
},
|
|
18007
|
+
{
|
|
18008
|
+
method: "POST",
|
|
18009
|
+
pattern: ["files", "rename"],
|
|
18010
|
+
// 重命名(只改同目录下的名字)
|
|
18011
|
+
fn: (_req, res, { tenant, body }) => {
|
|
18012
|
+
const raw = body ?? {};
|
|
18013
|
+
try {
|
|
18014
|
+
ok(
|
|
18015
|
+
res,
|
|
18016
|
+
renameProjectPath(
|
|
18017
|
+
tenant.workspaceRoot ?? null,
|
|
18018
|
+
String(raw.path ?? ""),
|
|
18019
|
+
String(raw.name ?? "")
|
|
18020
|
+
)
|
|
18021
|
+
);
|
|
18022
|
+
} catch (e) {
|
|
18023
|
+
throw new ApiError(400, "bad_request", e instanceof Error ? e.message : String(e));
|
|
18024
|
+
}
|
|
18025
|
+
}
|
|
18026
|
+
},
|
|
18027
|
+
{
|
|
18028
|
+
method: "POST",
|
|
18029
|
+
pattern: ["files", "zip"],
|
|
18030
|
+
// 压缩下载(多选一起打包;超上限由实现拒绝)
|
|
18031
|
+
fn: (_req, res, { tenant, body }) => {
|
|
18032
|
+
const raw = body ?? {};
|
|
18033
|
+
const paths = Array.isArray(raw.paths) ? raw.paths.map((x) => String(x)) : [];
|
|
18034
|
+
if (paths.length === 0) throw new ApiError(400, "bad_request", "paths \u4E0D\u80FD\u4E3A\u7A7A");
|
|
18035
|
+
try {
|
|
18036
|
+
ok(res, zipProjectPaths(tenant.workspaceRoot ?? null, paths));
|
|
18037
|
+
} catch (e) {
|
|
18038
|
+
throw new ApiError(400, "bad_request", e instanceof Error ? e.message : String(e));
|
|
18039
|
+
}
|
|
18040
|
+
}
|
|
18041
|
+
},
|
|
17428
18042
|
// ---------- 项目(= 租户)管理:控制台多项目视图 ----------
|
|
17429
18043
|
// 仅管理员密钥可用;项目级与会话级接口仍用项目自己的 tenant API Key
|
|
17430
18044
|
// (或管理员密钥 + X-Project-Id 头),互不暴露明文密钥。
|
|
@@ -17483,6 +18097,29 @@ function createApp(store, manager, opts = {}) {
|
|
|
17483
18097
|
ok(res, nodeLlmView(next));
|
|
17484
18098
|
}
|
|
17485
18099
|
},
|
|
18100
|
+
// 大模型账户余额(控制台「余额不足 → 查看余额并充值」用;由节点向 Hub 代查)
|
|
18101
|
+
{
|
|
18102
|
+
method: "GET",
|
|
18103
|
+
pattern: ["node", "llm", "balance"],
|
|
18104
|
+
adminOnly: true,
|
|
18105
|
+
fn: async (_req, res) => {
|
|
18106
|
+
ok(res, await fetchLlmBalance(store));
|
|
18107
|
+
}
|
|
18108
|
+
},
|
|
18109
|
+
// 重新拉取平台内置模型凭据(用户点了「刷新内置模型」,或 Key 在控制台被重置)
|
|
18110
|
+
{
|
|
18111
|
+
method: "POST",
|
|
18112
|
+
pattern: ["node", "llm", "builtin-refresh"],
|
|
18113
|
+
adminOnly: true,
|
|
18114
|
+
fn: async (_req, res) => {
|
|
18115
|
+
const r = await ensureBuiltinProvider(store, { force: true });
|
|
18116
|
+
if (r.status !== "ready") {
|
|
18117
|
+
ok(res, { ok: false, reason: r.reason });
|
|
18118
|
+
return;
|
|
18119
|
+
}
|
|
18120
|
+
ok(res, { ok: true, view: nodeLlmView(store.loadNodeLlm()) });
|
|
18121
|
+
}
|
|
18122
|
+
},
|
|
17486
18123
|
// ---------- 用量(账本 + 汇总 + 价格) ----------
|
|
17487
18124
|
{
|
|
17488
18125
|
method: "GET",
|
|
@@ -17909,7 +18546,7 @@ function createApp(store, manager, opts = {}) {
|
|
|
17909
18546
|
json(res, 200, {
|
|
17910
18547
|
status: "ok",
|
|
17911
18548
|
// 版本让运维/探针能确认线上跑的是哪个构建(更新与回滚据此判断)
|
|
17912
|
-
version: "0.2.
|
|
18549
|
+
version: "0.2.20",
|
|
17913
18550
|
features: { mcp: hasServerMcpConfig() }
|
|
17914
18551
|
});
|
|
17915
18552
|
return;
|
|
@@ -18249,6 +18886,22 @@ async function dispatchFleetCommand(deps, env3) {
|
|
|
18249
18886
|
store.saveNodeLlm(next);
|
|
18250
18887
|
return ok2(nodeLlmView(next));
|
|
18251
18888
|
}
|
|
18889
|
+
/*
|
|
18890
|
+
* 重新拉取平台内置模型(志前 API)。
|
|
18891
|
+
*
|
|
18892
|
+
* 用途:用户在控制台点了「刷新」、或内置模型的 Key 在控制台被重置后需要换新。
|
|
18893
|
+
* 走写链串行——它会改写 connections.json,不能与 update_node_llm 并发。
|
|
18894
|
+
*/
|
|
18895
|
+
// 余额查询:只读、幂等,可进只读并发池
|
|
18896
|
+
case "get_llm_balance":
|
|
18897
|
+
return ok2(await fetchLlmBalance(store));
|
|
18898
|
+
case "refresh_builtin_llm": {
|
|
18899
|
+
const r = await ensureBuiltinProvider(store, { force: true });
|
|
18900
|
+
if (r.status !== "ready") {
|
|
18901
|
+
return ok2({ ok: false, reason: r.reason });
|
|
18902
|
+
}
|
|
18903
|
+
return ok2({ ok: true, view: nodeLlmView(store.loadNodeLlm()) });
|
|
18904
|
+
}
|
|
18252
18905
|
case "get_usage_summary": {
|
|
18253
18906
|
const ledger = manager.usageLedger();
|
|
18254
18907
|
if (!ledger) return ok2({ total: null, groups: [] });
|
|
@@ -18433,6 +19086,24 @@ async function dispatchFleetCommand(deps, env3) {
|
|
|
18433
19086
|
const t = project();
|
|
18434
19087
|
return ok2(searchProjectFiles(t.workspaceRoot ?? null, String(payload.query ?? "")));
|
|
18435
19088
|
}
|
|
19089
|
+
case "rename_path": {
|
|
19090
|
+
const t = project();
|
|
19091
|
+
return ok2(
|
|
19092
|
+
renameProjectPath(
|
|
19093
|
+
t.workspaceRoot ?? null,
|
|
19094
|
+
String(payload.path ?? ""),
|
|
19095
|
+
String(payload.name ?? "")
|
|
19096
|
+
)
|
|
19097
|
+
);
|
|
19098
|
+
}
|
|
19099
|
+
case "zip_download": {
|
|
19100
|
+
const t = project();
|
|
19101
|
+
const raw = payload.paths;
|
|
19102
|
+
const paths = Array.isArray(raw) ? raw.map((x) => String(x)) : [];
|
|
19103
|
+
if (paths.length === 0) throw new ApiError(400, "bad_request", "paths \u4E0D\u80FD\u4E3A\u7A7A");
|
|
19104
|
+
const maxBytes = typeof payload.maxBytes === "number" ? payload.maxBytes : void 0;
|
|
19105
|
+
return ok2(zipProjectPaths(t.workspaceRoot ?? null, paths, { maxBytes }));
|
|
19106
|
+
}
|
|
18436
19107
|
case "list_tools": {
|
|
18437
19108
|
const t = project();
|
|
18438
19109
|
return ok2(buildToolCatalog(t.workspaceRoot ?? process.cwd()));
|
|
@@ -18785,6 +19456,22 @@ function toWireAck(ack) {
|
|
|
18785
19456
|
data: ack.data === void 0 ? void 0 : utf8Encode(JSON.stringify(ack.data))
|
|
18786
19457
|
};
|
|
18787
19458
|
}
|
|
19459
|
+
var ACK_JSON_MAX_BYTES = MAX_FRAME_BYTES - 64 * 1024;
|
|
19460
|
+
function mb(bytes) {
|
|
19461
|
+
return (bytes / (1024 * 1024)).toFixed(1);
|
|
19462
|
+
}
|
|
19463
|
+
function guardAckSize(ack, json2) {
|
|
19464
|
+
if (!ack.ok || ack.data === void 0) return ack;
|
|
19465
|
+
const bytes = Buffer.byteLength(json2, "utf8");
|
|
19466
|
+
if (bytes <= ACK_JSON_MAX_BYTES) return ack;
|
|
19467
|
+
return {
|
|
19468
|
+
reqId: ack.reqId,
|
|
19469
|
+
type: ack.type,
|
|
19470
|
+
ok: false,
|
|
19471
|
+
// 带上实际大小:用户据此能判断「差一点」还是「差很多」,而不是只看到「失败」
|
|
19472
|
+
error: `\u7ED3\u679C\u8FC7\u5927\uFF08${mb(bytes)} MB\uFF09\uFF0C\u8D85\u8FC7\u5355\u5E27\u4F20\u8F93\u4E0A\u9650\uFF08${mb(ACK_JSON_MAX_BYTES)} MB\uFF09\uFF0C\u8BF7\u7F29\u5C0F\u8303\u56F4\u540E\u91CD\u8BD5`
|
|
19473
|
+
};
|
|
19474
|
+
}
|
|
18788
19475
|
function fromWireCommand(env3) {
|
|
18789
19476
|
let payload = {};
|
|
18790
19477
|
if (env3.payload && env3.payload.length > 0) {
|
|
@@ -19190,6 +19877,7 @@ var READONLY_CMD_TYPES = /* @__PURE__ */ new Set([
|
|
|
19190
19877
|
"get_node_llm",
|
|
19191
19878
|
"list_node_llm_models",
|
|
19192
19879
|
"get_usage_summary",
|
|
19880
|
+
"get_llm_balance",
|
|
19193
19881
|
"get_usage_records",
|
|
19194
19882
|
"get_usage_pricing",
|
|
19195
19883
|
"list_projects",
|
|
@@ -19614,7 +20302,7 @@ var FleetNodeBridge = class {
|
|
|
19614
20302
|
label: this.opts.deps.store.loadNodeLabel() ?? void 0,
|
|
19615
20303
|
platform: process.platform,
|
|
19616
20304
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
19617
|
-
version: "0.2.
|
|
20305
|
+
version: "0.2.20",
|
|
19618
20306
|
ip: primaryIp()
|
|
19619
20307
|
};
|
|
19620
20308
|
}
|
|
@@ -19712,7 +20400,7 @@ var FleetNodeBridge = class {
|
|
|
19712
20400
|
label: this.opts.deps.store.loadNodeLabel() ?? void 0,
|
|
19713
20401
|
platform: process.platform,
|
|
19714
20402
|
mode: process.env.NODE_MODE ?? "standalone",
|
|
19715
|
-
version: "0.2.
|
|
20403
|
+
version: "0.2.20",
|
|
19716
20404
|
ip: primaryIp(),
|
|
19717
20405
|
projects,
|
|
19718
20406
|
totals,
|
|
@@ -19874,7 +20562,13 @@ var FleetNodeBridge = class {
|
|
|
19874
20562
|
const stamped = { ...ack, reqId: env3.reqId, type: env3.type };
|
|
19875
20563
|
const json2 = JSON.stringify(stamped);
|
|
19876
20564
|
const __t1 = dbgNow();
|
|
19877
|
-
|
|
20565
|
+
const payload = guardAckSize(stamped, json2);
|
|
20566
|
+
if (payload !== stamped) {
|
|
20567
|
+
console.warn(
|
|
20568
|
+
`[fleet] ${env3.type} \u56DE\u6267 ${(json2.length / 1024 / 1024).toFixed(1)}MB \u8D85\u8FC7\u5355\u5E27\u4E0A\u9650\uFF0C\u5DF2\u964D\u7EA7\u4E3A\u9519\u8BEF\u56DE\u6267`
|
|
20569
|
+
);
|
|
20570
|
+
}
|
|
20571
|
+
this._send({ kind: "ack", clientId: env3.clientId, ack: payload });
|
|
19878
20572
|
dbgMs(
|
|
19879
20573
|
"publishAck",
|
|
19880
20574
|
__t0,
|
|
@@ -21110,7 +21804,7 @@ import { createHash as createHash3 } from "crypto";
|
|
|
21110
21804
|
import * as fs27 from "fs";
|
|
21111
21805
|
import { Readable as Readable2 } from "stream";
|
|
21112
21806
|
import { pipeline as pipeline2 } from "stream/promises";
|
|
21113
|
-
import { spawnSync as
|
|
21807
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
21114
21808
|
import * as path36 from "path";
|
|
21115
21809
|
|
|
21116
21810
|
// src/update/manifest.ts
|
|
@@ -21337,7 +22031,7 @@ async function downloadBinary(bin, destPath, log = () => {
|
|
|
21337
22031
|
}
|
|
21338
22032
|
function selfCheck(binPath, expectedVersion) {
|
|
21339
22033
|
try {
|
|
21340
|
-
const r =
|
|
22034
|
+
const r = spawnSync5(binPath, ["--version"], {
|
|
21341
22035
|
timeout: 2e4,
|
|
21342
22036
|
encoding: "utf-8",
|
|
21343
22037
|
env: { ...process.env, ZQAGENT_AUTO_UPDATE: "0" }
|
|
@@ -21918,7 +22612,9 @@ function seedDemoTenant(store) {
|
|
|
21918
22612
|
// 未显式指定时随机生成:固定默认密钥一旦随 HOST=0.0.0.0 暴露到公网,等于公开凭据。
|
|
21919
22613
|
// 只在首次创建时生成并落盘,后续启动沿用磁盘上的值(启动日志会打印完整密钥)。
|
|
21920
22614
|
apiKey: env2("TENANT_API_KEY") ?? generateApiKey(),
|
|
21921
|
-
|
|
22615
|
+
// 不再硬编码具体厂商型号:志前 API 只认 deepseek-flash,写死 deepseek-v4-flash
|
|
22616
|
+
// 会让新装节点的第一次请求 404。默认值统一走 defaultTenantModel(见 nodeLlm.ts)。
|
|
22617
|
+
model: defaultTenantModel(store),
|
|
21922
22618
|
provider: {
|
|
21923
22619
|
apiKey: env2("OPENAI_API_KEY"),
|
|
21924
22620
|
baseURL: env2("OPENAI_BASE_URL")
|
|
@@ -22058,6 +22754,8 @@ function startServer(opts = {}) {
|
|
|
22058
22754
|
const store = new Store(dataDir);
|
|
22059
22755
|
const demo = seedDemoTenant(store);
|
|
22060
22756
|
syncTenantModels(store);
|
|
22757
|
+
const nodeModel = nodeDefaultProvider(store)?.model;
|
|
22758
|
+
if (nodeModel) adoptBuiltinModelForTenants(store, nodeModel);
|
|
22061
22759
|
const usageLedger = new UsageLedger(dataDir);
|
|
22062
22760
|
usageLedger.init();
|
|
22063
22761
|
const manager = new SessionManager(store, void 0, { usage: usageLedger });
|
|
@@ -22201,8 +22899,12 @@ function startServer(opts = {}) {
|
|
|
22201
22899
|
if (initialCred) {
|
|
22202
22900
|
connectFleet(initialCred);
|
|
22203
22901
|
} else if (opts.autoEnroll) {
|
|
22204
|
-
void fleetController.enroll(opts.autoEnroll).then((st) =>
|
|
22902
|
+
void fleetController.enroll(opts.autoEnroll).then((st) => {
|
|
22903
|
+
console.log(`[fleet] \u5DF2\u81EA\u52A8\u63A5\u5165\uFF0C\u8282\u70B9 ${st.nodeId}\uFF08${st.gatewayUrl}\uFF09`);
|
|
22904
|
+
scheduleBuiltinProvider(store, (m) => console.log(m));
|
|
22905
|
+
}).catch((e) => console.warn(`[fleet] \u81EA\u52A8\u63A5\u5165\u5931\u8D25\uFF08\u53EF\u7A0D\u540E /link \u91CD\u8BD5\uFF09: ${e instanceof Error ? e.message : e}`));
|
|
22205
22906
|
}
|
|
22907
|
+
if (initialCred) scheduleBuiltinProvider(store, (m) => console.log(m));
|
|
22206
22908
|
const pairingCodes = new PairingCodeStore();
|
|
22207
22909
|
const qq = new QqManager({
|
|
22208
22910
|
store,
|
|
@@ -23256,7 +23958,10 @@ async function connectWizard() {
|
|
|
23256
23958
|
break;
|
|
23257
23959
|
}
|
|
23258
23960
|
cliLog(`\u274C \u81EA\u68C0\u5931\u8D25: ${probe.error}${probe.code ? ` | ${probe.code}` : ""}`);
|
|
23259
|
-
for (const hint of
|
|
23961
|
+
for (const hint of [
|
|
23962
|
+
...authErrorHints(probe.error ?? "", probe.code ?? ""),
|
|
23963
|
+
...paramErrorHints(probe.error ?? "", probe.code ?? "")
|
|
23964
|
+
]) {
|
|
23260
23965
|
cliLog(` \u{1F4A1} ${hint}`);
|
|
23261
23966
|
}
|
|
23262
23967
|
const keep = (await question("\u91CD\u65B0\u9009\u62E9\u6A21\u578B (\u56DE\u8F66\u91CD\u9009) / \u8F93\u5165 y \u4ECD\u4F7F\u7528\u8BE5\u6A21\u578B: ")).trim().toLowerCase();
|
|
@@ -23490,7 +24195,7 @@ async function offerTerminalSetup(engine, canUseAgent) {
|
|
|
23490
24195
|
}
|
|
23491
24196
|
var KNOWN_SUBCOMMANDS = /* @__PURE__ */ new Set(["link", "serve", "update", "rename"]);
|
|
23492
24197
|
function cliVersion() {
|
|
23493
|
-
const env3 = "0.2.
|
|
24198
|
+
const env3 = "0.2.20"?.trim();
|
|
23494
24199
|
if (env3) return env3;
|
|
23495
24200
|
try {
|
|
23496
24201
|
const req2 = createRequire4(import.meta.url);
|
|
@@ -24003,6 +24708,12 @@ async function main() {
|
|
|
24003
24708
|
cliLog(`\u274C \u672A\u627E\u5230\u4F9B\u5E94\u5546: ${arg}`);
|
|
24004
24709
|
break;
|
|
24005
24710
|
}
|
|
24711
|
+
if (target.id === BUILTIN_PROVIDER_ID) {
|
|
24712
|
+
cliLog(
|
|
24713
|
+
"\u274C \u5E73\u53F0\u5185\u7F6E\u6A21\u578B\u4E0D\u53EF\u5220\u9664\uFF08\u63A5\u5165 Hub \u540E\u81EA\u52A8\u914D\u7F6E\uFF0CKey \u7531\u5E73\u53F0\u6258\u7BA1\uFF09\u3002\n \u5982\u9700\u6539\u7528\u5176\u5B83\u6A21\u578B\uFF1A/connect \u9009\u62E9\u6216\u6DFB\u52A0\u4F9B\u5E94\u5546\u540E\u8BBE\u4E3A\u9ED8\u8BA4\u3002"
|
|
24714
|
+
);
|
|
24715
|
+
break;
|
|
24716
|
+
}
|
|
24006
24717
|
if (removeConnection(target.id)) {
|
|
24007
24718
|
currentConnection = loadConnection();
|
|
24008
24719
|
engine = buildEngine(SESSION_ID);
|