@zhushanwen/zcode-subagent-cli 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-NC4FSPIM.js → chunk-33XN65H4.js} +261 -26
- package/dist/index.cjs +301 -66
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +1 -1
- package/dist/main.cjs +304 -69
- package/dist/main.js +1 -1
- package/package.json +4 -3
|
@@ -369,6 +369,7 @@ function synthesizeCoarseEvents(response, usage) {
|
|
|
369
369
|
import * as fs2 from "fs";
|
|
370
370
|
import * as os2 from "os";
|
|
371
371
|
import * as path2 from "path";
|
|
372
|
+
import { resolveEngineDataDir, ZCODE_PI_SYNCED_PROVIDER_CONFIG_SEGMENTS } from "@zhushanwen/subagent-engine-sdk";
|
|
372
373
|
var ZcodePrepareError = class extends Error {
|
|
373
374
|
code;
|
|
374
375
|
constructor(code, message) {
|
|
@@ -377,35 +378,81 @@ var ZcodePrepareError = class extends Error {
|
|
|
377
378
|
this.code = code;
|
|
378
379
|
}
|
|
379
380
|
};
|
|
381
|
+
var TAIJI_SYNC_GUIDANCE = "\u82E5\u4F7F\u7528 taiji \u540C\u6B65\u526F\u672C/\u9ED8\u8BA4\u6A21\u578B\uFF0C\u5230 taiji settings \u6838\u5BF9\u6216\u91CD\u9009\uFF0C\u91CD\u542F taiji \u751F\u6548\u3002";
|
|
380
382
|
function isRecord(v) {
|
|
381
383
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
382
384
|
}
|
|
383
385
|
function strArray(v) {
|
|
384
386
|
return Array.isArray(v) ? v.filter((m) => typeof m === "string" && m.trim() !== "") : [];
|
|
385
387
|
}
|
|
386
|
-
function
|
|
387
|
-
const empty = { providers: /* @__PURE__ */ new Map(), order: [] };
|
|
388
|
+
function readSourceJsonOrUndefined(absPath) {
|
|
388
389
|
let raw;
|
|
389
390
|
try {
|
|
390
391
|
raw = fs2.readFileSync(absPath, "utf8");
|
|
391
392
|
} catch {
|
|
392
|
-
return
|
|
393
|
+
return void 0;
|
|
393
394
|
}
|
|
394
|
-
let parsed;
|
|
395
395
|
try {
|
|
396
|
-
|
|
396
|
+
return JSON.parse(raw);
|
|
397
397
|
} catch {
|
|
398
|
-
return
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
const
|
|
405
|
-
if (!
|
|
406
|
-
|
|
398
|
+
return void 0;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function extractSourceConfig(parsed) {
|
|
402
|
+
const conf = { providers: /* @__PURE__ */ new Map(), order: [] };
|
|
403
|
+
if (!isRecord(parsed)) return conf;
|
|
404
|
+
const config = parsed["config"];
|
|
405
|
+
if (!isRecord(config)) return conf;
|
|
406
|
+
conf.order = strArray(config["providerOrder"]);
|
|
407
|
+
const rules = config["providerConfigRules"];
|
|
408
|
+
const providerRules = isRecord(rules) ? rules["providerRules"] : void 0;
|
|
409
|
+
if (Array.isArray(providerRules)) collectProviderRules(providerRules, conf);
|
|
407
410
|
return conf;
|
|
408
411
|
}
|
|
412
|
+
function readSourceConfig(absPath) {
|
|
413
|
+
return extractSourceConfig(readSourceJsonOrUndefined(absPath));
|
|
414
|
+
}
|
|
415
|
+
function mergePersonalProviderConfig(realObj, copyObj) {
|
|
416
|
+
if (!isRecord(copyObj)) return realObj;
|
|
417
|
+
if (!isRecord(realObj)) return copyObj;
|
|
418
|
+
const cfgOf = (obj) => isRecord(obj["config"]) ? obj["config"] : {};
|
|
419
|
+
const rulesOf = (obj) => {
|
|
420
|
+
const pcr = cfgOf(obj)["providerConfigRules"];
|
|
421
|
+
const rules = isRecord(pcr) ? pcr["providerRules"] : void 0;
|
|
422
|
+
return Array.isArray(rules) ? rules : [];
|
|
423
|
+
};
|
|
424
|
+
const mergedRules = [];
|
|
425
|
+
const seen = /* @__PURE__ */ new Set();
|
|
426
|
+
for (const rule of rulesOf(realObj)) {
|
|
427
|
+
mergedRules.push(rule);
|
|
428
|
+
if (isRecord(rule)) {
|
|
429
|
+
const id = rule["providerId"];
|
|
430
|
+
if (typeof id === "string" && id !== "") seen.add(id);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
for (const rule of rulesOf(copyObj)) {
|
|
434
|
+
if (!isRecord(rule)) continue;
|
|
435
|
+
const id = rule["providerId"];
|
|
436
|
+
if (typeof id !== "string" || id === "") continue;
|
|
437
|
+
if (seen.has(id)) continue;
|
|
438
|
+
seen.add(id);
|
|
439
|
+
mergedRules.push(rule);
|
|
440
|
+
}
|
|
441
|
+
const mergedOrder = [];
|
|
442
|
+
for (const id of [...strArray(cfgOf(realObj)["providerOrder"]), ...strArray(cfgOf(copyObj)["providerOrder"])]) {
|
|
443
|
+
if (!mergedOrder.includes(id)) mergedOrder.push(id);
|
|
444
|
+
}
|
|
445
|
+
const realCfg = cfgOf(realObj);
|
|
446
|
+
const realPcr = isRecord(realCfg["providerConfigRules"]) ? realCfg["providerConfigRules"] : {};
|
|
447
|
+
return {
|
|
448
|
+
...realObj,
|
|
449
|
+
config: {
|
|
450
|
+
...realCfg,
|
|
451
|
+
providerOrder: mergedOrder,
|
|
452
|
+
providerConfigRules: { ...realPcr, providerRules: mergedRules }
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
409
456
|
function collectProviderRules(providerRules, conf) {
|
|
410
457
|
for (const rule of providerRules) {
|
|
411
458
|
if (!isRecord(rule)) continue;
|
|
@@ -440,6 +487,40 @@ function defaultPersonalProviderConfigPath() {
|
|
|
440
487
|
function defaultV2ConfigPath() {
|
|
441
488
|
return path2.join(os2.homedir(), ...ZCODE_V2_CONFIG_PATH_SUFFIX);
|
|
442
489
|
}
|
|
490
|
+
function piSyncedProviderConfigPath(engineDataDir) {
|
|
491
|
+
return path2.join(engineDataDir, ...ZCODE_PI_SYNCED_PROVIDER_CONFIG_SEGMENTS);
|
|
492
|
+
}
|
|
493
|
+
function envEngineDataDirOrUndefined() {
|
|
494
|
+
try {
|
|
495
|
+
return resolveEngineDataDir(process.env);
|
|
496
|
+
} catch {
|
|
497
|
+
return void 0;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function resolvePersonalProviderSource(sources, engineDataDir) {
|
|
501
|
+
const explicit = sources?.personalProviderConfigPath;
|
|
502
|
+
if (explicit !== void 0) return { kind: "explicit", path: explicit };
|
|
503
|
+
const dataDir = engineDataDir ?? envEngineDataDirOrUndefined();
|
|
504
|
+
if (dataDir !== void 0 && fs2.existsSync(piSyncedProviderConfigPath(dataDir))) {
|
|
505
|
+
return { kind: "copy", path: piSyncedProviderConfigPath(dataDir), realPath: defaultPersonalProviderConfigPath() };
|
|
506
|
+
}
|
|
507
|
+
return { kind: "real", path: defaultPersonalProviderConfigPath() };
|
|
508
|
+
}
|
|
509
|
+
function resolvePersonalProviderConfigPath(sources, engineDataDir) {
|
|
510
|
+
return resolvePersonalProviderSource(sources, engineDataDir).path;
|
|
511
|
+
}
|
|
512
|
+
function readPersonalProviderView(sources) {
|
|
513
|
+
const resolution = resolvePersonalProviderSource(sources);
|
|
514
|
+
if (resolution.kind !== "copy") {
|
|
515
|
+
return { conf: readSourceConfig(resolution.path), sourceDesc: resolution.path };
|
|
516
|
+
}
|
|
517
|
+
const copyJson = readSourceJsonOrUndefined(resolution.path);
|
|
518
|
+
const realJson = readSourceJsonOrUndefined(resolution.realPath);
|
|
519
|
+
return {
|
|
520
|
+
conf: extractSourceConfig(mergePersonalProviderConfig(realJson, copyJson)),
|
|
521
|
+
sourceDesc: `merge(\u771F\u5B9E ${resolution.realPath} + \u526F\u672C ${resolution.path})`
|
|
522
|
+
};
|
|
523
|
+
}
|
|
443
524
|
var SEMVER_SEGMENTS = 3;
|
|
444
525
|
function locateZcodeBuiltinCatalog(sources) {
|
|
445
526
|
if (sources?.builtinCatalogPath !== void 0) return sources.builtinCatalogPath;
|
|
@@ -530,15 +611,14 @@ function defaultProviderForShortName(conf, withKey) {
|
|
|
530
611
|
return withKey[0][0];
|
|
531
612
|
}
|
|
532
613
|
function resolveZcodeModelRef(requested, sources) {
|
|
533
|
-
const
|
|
534
|
-
const conf = readSourceConfig(srcPath);
|
|
614
|
+
const { conf, sourceDesc } = readPersonalProviderView(sources);
|
|
535
615
|
const withKey = [...conf.providers.entries()].filter(([, e]) => hasApiKey(e));
|
|
536
616
|
const wanted = requested?.trim() || void 0;
|
|
537
617
|
if (withKey.length === 0) {
|
|
538
618
|
const hint = wanted ? `model="${wanted}" \u4E0D\u80FD\u6821\u9A8C` : "\u7F3A\u7701\u6A21\u578B\u89E3\u6790\u4E0D\u80FD\u6821\u9A8C";
|
|
539
619
|
throw new ZcodePrepareError(
|
|
540
620
|
"engine_credential_missing",
|
|
541
|
-
`zcode \u5F15\u64CE\u627E\u4E0D\u5230\u4EFB\u4F55\u5E26 apiKey \u7684\u4E2A\u4EBA provider\uFF08${hint}\uFF09\u3002\u5DF2\u8BFB\u6E90\uFF1A${
|
|
621
|
+
`zcode \u5F15\u64CE\u627E\u4E0D\u5230\u4EFB\u4F55\u5E26 apiKey \u7684\u4E2A\u4EBA provider\uFF08${hint}\uFF09\u3002\u5DF2\u8BFB\u6E90\uFF1A${sourceDesc}\u3002\u6062\u590D\u6307\u5F15\uFF1A\u5728 ZCode \u684C\u9762\u7AEF\u914D\u7F6E\u81F3\u5C11\u4E00\u4E2A\u4E2A\u4EBA provider\uFF08provider_config.json \u5185\u5B58\u5728 config.access.apiKey \u975E\u7A7A\u6761\u76EE\uFF09\u540E\u91CD\u8BD5\uFF1Bplan \u5957\u9910\u65CF\uFF08builtin:/account: \u524D\u7F00\uFF09\u7ECF\u8D26\u53F7 entitlement \u95E8\u63A7\uFF0C\u5916\u90E8 spawn \u7684\u5F15\u64CE\u6CE8\u518C\u8868\u4E0D\u88C5\u8F7D\uFF0C\u4E0D\u53EF\u4F5C\u4E3A\u5F15\u64CE\u6A21\u578B\u3002` + TAIJI_SYNC_GUIDANCE
|
|
542
622
|
);
|
|
543
623
|
}
|
|
544
624
|
if (wanted === void 0) return "";
|
|
@@ -549,26 +629,26 @@ function resolveZcodeModelRef(requested, sources) {
|
|
|
549
629
|
const known = withKey.map(([id]) => id).join(", ");
|
|
550
630
|
throw new ZcodePrepareError(
|
|
551
631
|
"model_not_available",
|
|
552
|
-
`\u672A\u77E5 provider "${provider}"\uFF08\u5E26\u51ED\u636E\u7684\u4E2A\u4EBA provider: ${known}\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u4E0A\u8FF0 provider \u4E4B\u4E00\uFF08\u5168\u540D provider/model\uFF09\uFF0C\u6216\u5728 ZCode \u684C\u9762\u7AEF\u914D\u7F6E\u8BE5 provider \u540E\u91CD\u8BD5\uFF1B\u7701\u7565 model \u53C2\u6570\u5219\u8D70\u5F15\u64CE\u7F3A\u7701\u89E3\u6790\uFF08CLI \u81EA\u8EAB\u9009\u53D6\u53EF\u7528\u6A21\u578B\uFF09\u3002`
|
|
632
|
+
`\u672A\u77E5 provider "${provider}"\uFF08\u5E26\u51ED\u636E\u7684\u4E2A\u4EBA provider: ${known}\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u4E0A\u8FF0 provider \u4E4B\u4E00\uFF08\u5168\u540D provider/model\uFF09\uFF0C\u6216\u5728 ZCode \u684C\u9762\u7AEF\u914D\u7F6E\u8BE5 provider \u540E\u91CD\u8BD5\uFF1B\u7701\u7565 model \u53C2\u6570\u5219\u8D70\u5F15\u64CE\u7F3A\u7701\u89E3\u6790\uFF08CLI \u81EA\u8EAB\u9009\u53D6\u53EF\u7528\u6A21\u578B\uFF09\u3002` + TAIJI_SYNC_GUIDANCE
|
|
553
633
|
);
|
|
554
634
|
}
|
|
555
635
|
if (!hasApiKey(entry)) {
|
|
556
636
|
throw new ZcodePrepareError(
|
|
557
637
|
"engine_credential_missing",
|
|
558
|
-
`provider "${provider}" \u5B58\u5728\u4F46\u672A\u914D\u7F6E apiKey\u3002\u6062\u590D\u6307\u5F15\uFF1A\u5728 ZCode \u684C\u9762\u7AEF\u4E3A\u8BE5 provider \u914D\u7F6E\u51ED\u636E\uFF0C\u6216\u6539\u7528\u5DF2\u914D\u51ED\u636E\u7684 provider\uFF08${withKey.map(([id]) => id).join(", ")}\uFF09\u540E\u91CD\u8BD5\u3002`
|
|
638
|
+
`provider "${provider}" \u5B58\u5728\u4F46\u672A\u914D\u7F6E apiKey\u3002\u6062\u590D\u6307\u5F15\uFF1A\u5728 ZCode \u684C\u9762\u7AEF\u4E3A\u8BE5 provider \u914D\u7F6E\u51ED\u636E\uFF0C\u6216\u6539\u7528\u5DF2\u914D\u51ED\u636E\u7684 provider\uFF08${withKey.map(([id]) => id).join(", ")}\uFF09\u540E\u91CD\u8BD5\u3002` + TAIJI_SYNC_GUIDANCE
|
|
559
639
|
);
|
|
560
640
|
}
|
|
561
641
|
const models = entry.models ?? [];
|
|
562
642
|
if (models.length > 0 && !models.includes(short)) {
|
|
563
643
|
throw new ZcodePrepareError(
|
|
564
644
|
"model_not_available",
|
|
565
|
-
`\u672A\u77E5\u6A21\u578B "${short}"\uFF08provider ${provider} \u4E0B\u53EF\u7528: ${models.join(", ")}\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u8BE5 provider \u4E0B\u7684\u6A21\u578B\uFF0C\u6216\u5728 ZCode \u684C\u9762\u7AEF\u542F\u7528\u76EE\u6807\u6A21\u578B\u540E\u91CD\u8BD5\u3002`
|
|
645
|
+
`\u672A\u77E5\u6A21\u578B "${short}"\uFF08provider ${provider} \u4E0B\u53EF\u7528: ${models.join(", ")}\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u8BE5 provider \u4E0B\u7684\u6A21\u578B\uFF0C\u6216\u5728 ZCode \u684C\u9762\u7AEF\u542F\u7528\u76EE\u6807\u6A21\u578B\u540E\u91CD\u8BD5\u3002` + TAIJI_SYNC_GUIDANCE
|
|
566
646
|
);
|
|
567
647
|
}
|
|
568
648
|
return `${provider}/${short}`;
|
|
569
649
|
}
|
|
570
650
|
function listZcodeModels(sources) {
|
|
571
|
-
const conf =
|
|
651
|
+
const { conf } = readPersonalProviderView(sources);
|
|
572
652
|
const out = [];
|
|
573
653
|
for (const [pid, entry] of conf.providers) {
|
|
574
654
|
if (!hasApiKey(entry)) continue;
|
|
@@ -600,6 +680,12 @@ const os = require('node:os');
|
|
|
600
680
|
|
|
601
681
|
const CLI_PATH = process.env.ZCODE_ENG_CLI_PATH;
|
|
602
682
|
const V2_PATH = process.env.ZCODE_ENG_V2_CONFIG || path.join(os.homedir(), '.zcode', 'v2', 'config.json');
|
|
683
|
+
// \u771F\u5B9E provider_config.json\uFF08Registry \u76F4\u8BFB\u8DEF\u5F84\uFF0CA0 \u63A2\u9488\u5B9E\u8BC1\uFF09\u2014\u2014\u4E0E CONFIG_PATH \u540C\u6B3E
|
|
684
|
+
// homedir \u63A8\u5BFC\u5F62\u6001\uFF0C\u4E0D\u53D7 env \u91CD\u5B9A\u5411\uFF08merge \u5206\u652F\u8981\u8BFB\u7684\u6B63\u662F\u8FD9\u4E2A\u771F\u5B9E\u8DEF\u5F84\u672C\u8EAB\uFF09
|
|
685
|
+
const REAL_PROVIDER_CONFIG_PATH = path.join(os.homedir(), '.zcode', 'v2', 'provider_config.json');
|
|
686
|
+
// taiji \u540C\u6B65\u526F\u672C\u8DEF\u5F84\uFF08ZCODE_ENG_PROVIDER_CONFIG \u8BED\u4E49\u6536\u7A84\uFF1B'' = \u672A\u8BBE \u2192 merge \u5206\u652F\u4E0D\u6FC0\u6D3B\uFF09
|
|
687
|
+
const PI_SYNCED_PATH = process.env.ZCODE_ENG_PROVIDER_CONFIG || '';
|
|
688
|
+
const PROVIDER_CONFIG_PATH = process.env.ZCODE_ENG_PROVIDER_CONFIG || REAL_PROVIDER_CONFIG_PATH;
|
|
603
689
|
const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
|
|
604
690
|
|
|
605
691
|
// \u5408\u5E76\u5F62\u6001\uFF1A\u771F\u5B9E cli config \u539F\u6837\uFF08model/plugins/mcp/subagents \u7B49 worker \u7EE7\u627F\u9762\u4E0D\u53D8\uFF09
|
|
@@ -608,6 +694,10 @@ const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
|
|
|
608
694
|
// \u914D\u7F6E\uFF082026-08-25 \u4E8B\u6545\uFF1A\u6B8B\u7559\u65E7 key \u538B\u8FC7\u65B0\u51ED\u636E\u81F4 turn 0 401\uFF09\uFF0C\u6545\u4E0D\u53D6 real \u4F18\u5148\u3002
|
|
609
695
|
// model.main \u7F3A\u5931\u65F6\u53EA\u4ECE v2 \u900F\u4F20\uFF08v2 \u4E5F\u6CA1\u6709\u5219\u4E0D\u4F2A\u9020\u2014\u2014CLI \u7F3A\u7701\u89E3\u6790\u81EA\u4F1A\u843D\u5230\u6CE8\u518C\u8868
|
|
610
696
|
// \u53EF\u7528\u6A21\u578B\uFF1Bplan \u5BB6\u65CF id \u5DF2\u4E0D\u53EF\u7528\uFF0C\u4E0D\u518D\u515C\u5E95\u4F2A\u9020\uFF09\u3002
|
|
697
|
+
// [D3 \u987A\u5E26\u53D1\u73B0 6] provider_config.json\uFF08\u5F15\u64CE\u4FA7\u6A21\u578B\u6821\u9A8C\u6E90\uFF09\u8865\u6CE8\u5165\uFF1A\u4EC5\u5B58\u5728\u4E8E
|
|
698
|
+
// providerRules \u7684\u4E2A\u4EBA provider\uFF08v2 \u5B57\u5178\u672A\u7269\u5316\uFF09\u4E0D\u5728\u6CE8\u5165\u96C6 \u2192 app-server \u6CE8\u518C\u8868
|
|
699
|
+
// \u7F3A\u6761\u76EE\uFF0C\u663E\u5F0F\u6A21\u578B\u9996\u6D3E\u5373\u62A5\u300CProvider Registry \u4E2D\u4E0D\u5B58\u5728 Model\u300D\u3002\u4E3A\u5E26 apiKey+baseUrl
|
|
700
|
+
// \u4E14 v2/real \u5747\u7F3A\u5931\u7684 rule \u5408\u6210 cli-config \u6761\u76EE\uFF08\u5F62\u72B6\u7167\u6284\u73B0\u7F51\u4E2A\u4EBA\u6761\u76EE\uFF09\u3002
|
|
611
701
|
// \u8FD4\u56DE null = \u65E0\u53EF\u6CE8\u5165\u51ED\u636E\uFF08v2 \u65E0 provider \u6761\u76EE\uFF09\u2014\u2014\u4E0D patch\uFF0C\u8BA9\u539F\u751F\u62A5\u9519\u900F\u51FA\u3002
|
|
612
702
|
// \u8BFB\u6E90\u7ECF readOrig \u95F4\u63A5\u53D6\uFF1Apatch \u524D\u9996\u8C03 = fs.readFileSync \u672C\u4F53\uFF1Bpatch \u540E = \u539F\u51FD\u6570
|
|
613
703
|
// \uFF08\u9632 patch \u540E\u7684\u9012\u5F52\u81EA\u8C03\u7528\uFF09\u3002
|
|
@@ -625,6 +715,7 @@ function injectedConfigText() {
|
|
|
625
715
|
}
|
|
626
716
|
return null;
|
|
627
717
|
}
|
|
718
|
+
const realProviders = real.provider && typeof real.provider === 'object' ? real.provider : {};
|
|
628
719
|
const v2Providers = v2.provider && typeof v2.provider === 'object' ? v2.provider : {};
|
|
629
720
|
const hasKey = (entry) => entry && typeof entry === 'object'
|
|
630
721
|
&& entry.options && typeof entry.options.apiKey === 'string' && entry.options.apiKey !== '';
|
|
@@ -632,9 +723,63 @@ function injectedConfigText() {
|
|
|
632
723
|
for (const [id, entry] of Object.entries(v2Providers)) {
|
|
633
724
|
if (hasKey(entry)) injectable[id] = entry;
|
|
634
725
|
}
|
|
726
|
+
// provider_config.json \u8865\u6CE8\u5165\uFF08\u8BFB\u53D6\u5931\u8D25\u9759\u9ED8\u964D\u7EA7\u2014\u2014\u6821\u9A8C\u6E90\u7F3A\u5E2D\u65F6\u5F15\u64CE\u4FA7\u6821\u9A8C\u540C\u6837\u4E0D\u53EF
|
|
727
|
+
// \u7528\uFF0C\u6CE8\u5165\u9762\u7EF4\u6301 v2-only \u73B0\u72B6\uFF1BproviderRules \u7F3A\u5931\u4E0D\u6784\u6210\u51ED\u636E\u9519\u8BEF\uFF09\u3002
|
|
728
|
+
try {
|
|
729
|
+
const pc = JSON.parse(readOrig(PROVIDER_CONFIG_PATH, 'utf8'));
|
|
730
|
+
const pcCfg = pc && typeof pc.config === 'object' && pc.config ? pc.config : {};
|
|
731
|
+
const pcr = typeof pcCfg.providerConfigRules === 'object' && pcCfg.providerConfigRules ? pcCfg.providerConfigRules : {};
|
|
732
|
+
const rules = Array.isArray(pcr.providerRules) ? pcr.providerRules : [];
|
|
733
|
+
const mcr = typeof pcCfg.modelConfigRules === 'object' && pcCfg.modelConfigRules ? pcCfg.modelConfigRules : {};
|
|
734
|
+
const modelRules = Array.isArray(mcr.providerModelRules) ? mcr.providerModelRules : [];
|
|
735
|
+
const modelMeta = {};
|
|
736
|
+
for (const mr of modelRules) {
|
|
737
|
+
if (!mr || typeof mr !== 'object' || typeof mr.providerId !== 'string' || typeof mr.modelId !== 'string') continue;
|
|
738
|
+
(modelMeta[mr.providerId] = modelMeta[mr.providerId] || []).push(mr);
|
|
739
|
+
}
|
|
740
|
+
for (const rule of rules) {
|
|
741
|
+
if (!rule || typeof rule !== 'object') continue;
|
|
742
|
+
const id = typeof rule.providerId === 'string' ? rule.providerId : '';
|
|
743
|
+
const cfg = rule.config && typeof rule.config === 'object' ? rule.config : {};
|
|
744
|
+
const access = cfg.access && typeof cfg.access === 'object' ? cfg.access : {};
|
|
745
|
+
const api = cfg.api && typeof cfg.api === 'object' ? cfg.api : {};
|
|
746
|
+
// v2/real \u5DF2\u6709 \u2192 \u4E0D\u91CD\u590D\u5408\u6210\uFF08v2 \u6761\u76EE\u66F4\u5168\uFF0C\u6574\u6761\u4F18\u5148\u8BED\u4E49\u4E0D\u53D7\u5F71\u54CD\uFF09
|
|
747
|
+
if (!id || injectable[id] || realProviders[id]) continue;
|
|
748
|
+
// hasKey \u7EAA\u5F8B\u540C\u6B3E\uFF1A\u65E0 apiKey \u4E0D\u5408\u6210\uFF1B\u65E0 baseUrl\uFF08endpoint \u7531\u6A21\u677F\u63D0\u4F9B\u7684\u5F62\u6001\uFF09
|
|
749
|
+
// \u4E0D\u5408\u6210\u2014\u2014\u6B8B\u7F3A\u6761\u76EE\u6BD4\u4E0D\u6CE8\u5165\u66F4\u7CDF\uFF0C\u539F\u751F\u300C\u4E0D\u5B58\u5728 Model\u300D\u62A5\u9519\u7167\u65E7\u900F\u51FA
|
|
750
|
+
if (typeof access.apiKey !== 'string' || access.apiKey === '') continue;
|
|
751
|
+
if (typeof api.baseUrl !== 'string' || api.baseUrl === '') continue;
|
|
752
|
+
const order = Array.isArray(cfg.modelOrder) ? cfg.modelOrder
|
|
753
|
+
: (Array.isArray(cfg.personalModelIds) ? cfg.personalModelIds : []);
|
|
754
|
+
const models = {};
|
|
755
|
+
for (const mr of modelMeta[id] || []) {
|
|
756
|
+
const mrCfg = mr.config && typeof mr.config === 'object' ? mr.config : {};
|
|
757
|
+
if (mrCfg.enabled === false) continue; // \u7981\u7528\u6A21\u578B\u4E0D\u8FDB\u6CE8\u518C\u8868\uFF08GUI \u8BED\u4E49\u4E00\u81F4\uFF09
|
|
758
|
+
const props = mrCfg.properties && typeof mrCfg.properties === 'object' ? mrCfg.properties : {};
|
|
759
|
+
models[mr.modelId] = typeof props.contextWindow === 'number'
|
|
760
|
+
? { limit: { context: props.contextWindow } }
|
|
761
|
+
: {};
|
|
762
|
+
}
|
|
763
|
+
for (const mid of order) {
|
|
764
|
+
if (typeof mid === 'string' && mid !== '' && !(mid in models)) models[mid] = {};
|
|
765
|
+
}
|
|
766
|
+
// kind \u6309\u6761\u76EE api.type \u6D3E\u751F\uFF08D3\uFF09\uFF1Aanthropic-messages \u2192 anthropic\uFF0C\u5176\u4F59
|
|
767
|
+
// \uFF08openai-chat-completions / api.type \u7F3A\u5E2D / \u672A\u77E5\u503C\uFF09\u2192 openai-compatible
|
|
768
|
+
// \u2014\u2014\u5BF9\u9F50 v2 config.json \u65E2\u6709 kind \u4E24\u503C\u5F62\u6001\uFF1B\u4F5C\u7528\u4E8E\u8865\u6CE8\u5165\u6BB5\u5168\u90E8\u6761\u76EE\uFF08\u542B\u900F\u4F20
|
|
769
|
+
// \u771F\u5B9E\u6761\u76EE\uFF0Canthropic \u534F\u8BAE\u771F\u5B9E\u6761\u76EE\u4ECE\u65E7\u9519\u914D\u503C openai-compatible \u987A\u5E26\u4FEE\u6B63\uFF09\u3002
|
|
770
|
+
// \u672A\u77E5\u534F\u8BAE\u503C\u9519\u914D\u65F6\u8BF7\u6C42\u671F\u534F\u8BAE\u9519\u8BEF\u53EF\u89C1\uFF08\u4E0D\u963B\u585E\u6CE8\u518C\u8868\u88C5\u8F7D\uFF09\uFF0C\u771F\u673A\u6F02\u79FB\u4FE1\u53F7\u660E\u786E
|
|
771
|
+
injectable[id] = {
|
|
772
|
+
name: typeof rule.providerName === 'string' ? rule.providerName : id,
|
|
773
|
+
kind: api.type === 'anthropic-messages' ? 'anthropic' : 'openai-compatible',
|
|
774
|
+
options: { apiKey: access.apiKey, baseURL: api.baseUrl },
|
|
775
|
+
source: 'custom',
|
|
776
|
+
models: models,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
} catch { /* provider_config \u7F3A\u5931/\u635F\u574F \u2192 \u8865\u6CE8\u5165\u9762\u9759\u9ED8\u964D\u7EA7\uFF08v2 \u6CE8\u5165\u4E0D\u53D7\u5F71\u54CD\uFF09 */ }
|
|
635
780
|
if (Object.keys(injectable).length === 0) return null;
|
|
636
781
|
const merged = { ...real };
|
|
637
|
-
merged.provider = { ...
|
|
782
|
+
merged.provider = { ...realProviders, ...injectable };
|
|
638
783
|
if ((!merged.model || typeof merged.model !== 'object' || !merged.model.main)
|
|
639
784
|
&& v2.model && typeof v2.model === 'object' && v2.model.main) {
|
|
640
785
|
merged.model = { ...(merged.model || {}), main: v2.model.main };
|
|
@@ -642,6 +787,77 @@ function injectedConfigText() {
|
|
|
642
787
|
return JSON.stringify(merged);
|
|
643
788
|
}
|
|
644
789
|
|
|
790
|
+
// [merge-fn-start]\uFF08\u5BF9\u8D26\u5355\u6D4B\u63D0\u53D6\u951A\u2014\u2014appserver-launcher.test.ts \u6309\u6807\u8BB0\u622A\u53D6\u672C\u51FD\u6570
|
|
791
|
+
// eval \u6267\u884C\uFF1Bpreparer.ts mergePersonalProviderConfig \u4E0E\u672C\u51FD\u6570\u540C\u89C4\u5219\u9501\u6B65\uFF0C\u6539\u4EFB\u4E00\u4FA7
|
|
792
|
+
// \u987B\u540C\u6B65\u53E6\u4E00\u4FA7\u5E76\u8DD1\u5BF9\u8D26\u5355\u6D4B\uFF09
|
|
793
|
+
// merge(\u771F\u5B9E, \u526F\u672C)\u2014\u2014D3 \u6362\u8F68\u7248\u89C4\u5219\uFF1A
|
|
794
|
+
// - \u526F\u672C\u975E\u5BF9\u8C61 \u2192 \u539F\u6837\u8FD4\u56DE real\uFF08\u526F\u672C\u7F3A\u5E2D\u56DE\u843D\u8BED\u4E49\uFF1Bwrapper \u4FA7\u66F4\u65E9\u77ED\u8DEF\uFF0C\u9632\u5FA1\u5F62\u6001\uFF09
|
|
795
|
+
// - \u771F\u5B9E\u975E\u5BF9\u8C61\uFF08ENOENT/\u635F\u574F\uFF09\u2192 \u539F\u6837\u8FD4\u56DE copy\uFF08\u526F\u672C\u72EC\u6709\u6761\u76EE\u4E3A\u5168\u96C6\uFF1AproviderRules
|
|
796
|
+
// \u4EC5\u526F\u672C\u6761\u76EE + order \u4EC5\u526F\u672C\u5E8F\uFF0C\u9876\u5C42\u5B57\u6BB5\u968F\u526F\u672C\u4FDD\u6301\u5F62\u6001\u5B8C\u6574\uFF09
|
|
797
|
+
// - providerRules\uFF1A\u771F\u5B9E\u6761\u76EE\u6574\u6761\u4FDD\u7559\u5728\u524D\uFF0C\u526F\u672C\u72EC\u6709 id \u8FFD\u52A0\uFF08\u771F\u5B9E\u4F18\u5148 = \u540C\u540D\u8BA9\u4F4D
|
|
798
|
+
// \u7684\u8FD0\u884C\u65F6\u7B2C\u4E8C\u9053\u9632\u7EBF\uFF09\uFF1B\u65E0\u6709\u6548 providerId \u7684\u526F\u672C\u6761\u76EE\u4E22\u5F03\uFF0C\u771F\u5B9E\u6761\u76EE\u539F\u6837\u4FDD\u7559
|
|
799
|
+
// - providerOrder\uFF1A\u771F\u5B9E\u73B0\u503C\u5E8F + \u526F\u672C\u72EC\u6709 id \u8FFD\u52A0\uFF08\u53BB\u91CD\u4FDD\u5E8F\uFF09
|
|
800
|
+
// - \u5176\u4F59\u5B57\u6BB5\uFF08\u542B config \u5185\u5176\u4ED6\u952E\uFF09\u53D6\u771F\u5B9E\u73B0\u503C
|
|
801
|
+
function mergeProviderConfig(realObj, copyObj) {
|
|
802
|
+
const isRec = (v) => v && typeof v === 'object' && !Array.isArray(v);
|
|
803
|
+
if (!isRec(copyObj)) return realObj;
|
|
804
|
+
if (!isRec(realObj)) return copyObj;
|
|
805
|
+
const cfgOf = (obj) => (isRec(obj.config) ? obj.config : {});
|
|
806
|
+
const rulesOf = (obj) => {
|
|
807
|
+
const pcr = cfgOf(obj).providerConfigRules;
|
|
808
|
+
const r = isRec(pcr) ? pcr.providerRules : undefined;
|
|
809
|
+
return Array.isArray(r) ? r : [];
|
|
810
|
+
};
|
|
811
|
+
const strArr = (v) => (Array.isArray(v) ? v.filter((s) => typeof s === 'string' && s.trim() !== '') : []);
|
|
812
|
+
const mergedRules = [];
|
|
813
|
+
const seen = {};
|
|
814
|
+
for (const rule of rulesOf(realObj)) {
|
|
815
|
+
mergedRules.push(rule);
|
|
816
|
+
if (isRec(rule) && typeof rule.providerId === 'string' && rule.providerId !== '') seen[rule.providerId] = true;
|
|
817
|
+
}
|
|
818
|
+
for (const rule of rulesOf(copyObj)) {
|
|
819
|
+
if (!isRec(rule) || typeof rule.providerId !== 'string' || rule.providerId === '') continue;
|
|
820
|
+
if (seen[rule.providerId]) continue;
|
|
821
|
+
seen[rule.providerId] = true;
|
|
822
|
+
mergedRules.push(rule);
|
|
823
|
+
}
|
|
824
|
+
const mergedOrder = [];
|
|
825
|
+
for (const id of strArr(cfgOf(realObj).providerOrder).concat(strArr(cfgOf(copyObj).providerOrder))) {
|
|
826
|
+
if (mergedOrder.indexOf(id) === -1) mergedOrder.push(id);
|
|
827
|
+
}
|
|
828
|
+
const outCfg = Object.assign({}, cfgOf(realObj), {
|
|
829
|
+
providerOrder: mergedOrder,
|
|
830
|
+
providerConfigRules: Object.assign(
|
|
831
|
+
{},
|
|
832
|
+
isRec(cfgOf(realObj).providerConfigRules) ? cfgOf(realObj).providerConfigRules : {},
|
|
833
|
+
{ providerRules: mergedRules },
|
|
834
|
+
),
|
|
835
|
+
});
|
|
836
|
+
return Object.assign({}, realObj, { config: outCfg });
|
|
837
|
+
}
|
|
838
|
+
// [merge-fn-end]
|
|
839
|
+
|
|
840
|
+
// D3 \u6362\u8F68\u88C5\u8F7D\u901A\u9053\uFF1A\u547D\u4E2D\u771F\u5B9E provider_config.json \u7684\u8BFB\u53D6\u91CD\u5B9A\u5411\u4E3A merge(\u771F\u5B9E\u5B9E\u65F6
|
|
841
|
+
// \u5185\u5BB9, taiji \u540C\u6B65\u526F\u672C)\u2014\u2014\u6BCF\u6B21\u8BFB\u53D6\u91CD\u7B97\uFF08\u4E8B\u5B9E\u9A71\u52A8\uFF0C\u65E0\u7F13\u5B58/\u65F6\u95F4\u7A97\uFF0CZCode \u7AEF\u53D8\u66F4
|
|
842
|
+
// \u5B9E\u65F6\u751F\u6548\uFF09\u3002\u526F\u672C\u7F3A\u5931/\u4E0D\u53EF\u8BFB \u2192 null = \u8C03\u7528\u65B9\u77ED\u8DEF\u56DE\u539F\u6587\u4EF6\uFF08\u56DE\u843D\u771F\u5B9E\u6587\u4EF6\u8BED\u4E49\uFF0C
|
|
843
|
+
// \u96F6\u884C\u4E3A\u53D8\u5316\uFF09\uFF1Benv \u672A\u8BBE \u2192 null\uFF08\u5206\u652F\u4E0D\u6FC0\u6D3B\uFF09\u3002\u8BFB\u53D6\u4E00\u5F8B\u7ECF readOrig \u95F4\u63A5\u53D6\uFF08\u9632
|
|
844
|
+
// patch \u9762\u9012\u5F52\u81EA\u8C03\u7528\uFF09\u3002
|
|
845
|
+
function mergedProviderConfigText() {
|
|
846
|
+
if (!PI_SYNCED_PATH) return null;
|
|
847
|
+
const readOrig = fs.__origReadFileSync || fs.readFileSync;
|
|
848
|
+
let copyObj;
|
|
849
|
+
try {
|
|
850
|
+
copyObj = JSON.parse(readOrig(PI_SYNCED_PATH, 'utf8'));
|
|
851
|
+
} catch { return null; }
|
|
852
|
+
if (!copyObj || typeof copyObj !== 'object' || Array.isArray(copyObj)) return null;
|
|
853
|
+
let realObj = null;
|
|
854
|
+
try {
|
|
855
|
+
const parsed = JSON.parse(readOrig(REAL_PROVIDER_CONFIG_PATH, 'utf8'));
|
|
856
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) realObj = parsed;
|
|
857
|
+
} catch { /* ENOENT/\u635F\u574F \u2192 \u526F\u672C\u72EC\u6709\u6761\u76EE\u4E3A\u5168\u96C6 */ }
|
|
858
|
+
return JSON.stringify(mergeProviderConfig(realObj, copyObj));
|
|
859
|
+
}
|
|
860
|
+
|
|
645
861
|
if (!CLI_PATH) {
|
|
646
862
|
process.stderr.write('[zcode-launcher] ZCODE_ENG_CLI_PATH \u672A\u8BBE\u7F6E\uFF0C\u65E0\u6CD5\u542F\u52A8 app-server\uFF08\u8BE5 env \u7531\u5F15\u64CE\u81EA\u52A8\u8BBE\u7F6E\uFF1B\u624B\u5DE5\u8FD0\u884C wrapper \u9700\u663E\u5F0F\u4F20\u5165\uFF09\\n');
|
|
647
863
|
process.exit(2);
|
|
@@ -665,6 +881,11 @@ if (text !== null) {
|
|
|
665
881
|
const cur = injectedConfigText();
|
|
666
882
|
if (cur !== null) return shape(rest, cur);
|
|
667
883
|
}
|
|
884
|
+
// D3 \u6362\u8F68\uFF1ARegistry \u76F4\u8BFB\u771F\u5B9E provider_config.json \u2192 merge(\u771F\u5B9E, \u526F\u672C) \u89C6\u56FE
|
|
885
|
+
if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
|
|
886
|
+
const cur = mergedProviderConfigText();
|
|
887
|
+
if (cur !== null) return shape(rest, cur);
|
|
888
|
+
}
|
|
668
889
|
return fs.__origReadFileSync.call(fs, p, ...rest);
|
|
669
890
|
};
|
|
670
891
|
fs.promises.__origReadFile = fs.promises.readFile;
|
|
@@ -673,17 +894,27 @@ if (text !== null) {
|
|
|
673
894
|
const cur = injectedConfigText();
|
|
674
895
|
if (cur !== null) return Promise.resolve(shape(rest, cur));
|
|
675
896
|
}
|
|
897
|
+
if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
|
|
898
|
+
const cur = mergedProviderConfigText();
|
|
899
|
+
if (cur !== null) return Promise.resolve(shape(rest, cur));
|
|
900
|
+
}
|
|
676
901
|
return fs.promises.__origReadFile.call(fs.promises, p, ...rest);
|
|
677
902
|
};
|
|
678
903
|
// existsSync \u62E6\u622A\uFF1A\u771F\u5B9E bundle \u7684\u7528\u6237 config \u8BFB\u53D6\uFF08loadFileConfig\uFF09\u4EE5 existsSync
|
|
679
904
|
// \u4E3A\u77ED\u8DEF\u95E8\u2014\u2014\u6587\u4EF6\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u7A7A config \u4E14 readFileSync \u4E0D\u88AB\u8C03\u7528\uFF0CGUI-only
|
|
680
|
-
// \u767B\u5F55\u5BBF\u4E3B\uFF08cli/config.json \u4ECE\u672A\u88AB CLI \u4FA7\u5199\u8FC7\uFF09\u4E0A\u6CE8\u5165\u53EA\u6302\u5728\u8BFB\u53D6\u9762 = \u4E0D\u53EF\u89C1
|
|
905
|
+
// \u767B\u5F55\u5BBF\u4E3B\uFF08cli/config.json \u4ECE\u672A\u88AB CLI \u4FA7\u5199\u8FC7\uFF09\u4E0A\u6CE8\u5165\u53EA\u6302\u5728\u8BFB\u53D6\u9762 = \u4E0D\u53EF\u89C1\u3002
|
|
906
|
+
// D3 \u6362\u8F68\uFF1A\u771F\u5B9E provider_config.json \u7684\u5B58\u5728\u6027 = \u771F\u5B9E\u6216\u526F\u672C\u4EFB\u4E00\u5B58\u5728\u5373 true
|
|
907
|
+
//\uFF08\u771F\u5B9E\u7F3A\u5931 + \u526F\u672C\u5B58\u5728\u65F6 Registry \u7684 existsSync \u95E8\u4E0D\u5F97\u62E6\u6389 merge \u89C6\u56FE\u8BFB\u53D6\uFF09
|
|
681
908
|
fs.__origExistsSync = fs.existsSync;
|
|
682
909
|
fs.existsSync = function (p) {
|
|
683
910
|
if (typeof p === 'string' && p === CONFIG_PATH) {
|
|
684
911
|
const cur = injectedConfigText();
|
|
685
912
|
if (cur !== null) return true;
|
|
686
913
|
}
|
|
914
|
+
if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH && PI_SYNCED_PATH) {
|
|
915
|
+
if (fs.__origExistsSync.call(fs, REAL_PROVIDER_CONFIG_PATH)) return true;
|
|
916
|
+
return fs.__origExistsSync.call(fs, PI_SYNCED_PATH);
|
|
917
|
+
}
|
|
687
918
|
return fs.__origExistsSync.call(fs, p);
|
|
688
919
|
};
|
|
689
920
|
}
|
|
@@ -1973,7 +2204,10 @@ var ZcodeEngine = class {
|
|
|
1973
2204
|
// --mode build/edit/plan/yolo 原生权限档位
|
|
1974
2205
|
permissionMode: "native",
|
|
1975
2206
|
// [D3-④] 无 turn_end 语义,轮数上限不可兑现(预检 gate 据此同步拒绝)
|
|
1976
|
-
maxTurns: false
|
|
2207
|
+
maxTurns: false,
|
|
2208
|
+
// [subagent-model-switch] zcode 引擎不在模型切换设计范围(协议面引擎中立预留,
|
|
2209
|
+
// 后续另立项接入)——setModel 通路未接通,unsupported 如实声明
|
|
2210
|
+
setModel: "unsupported"
|
|
1977
2211
|
};
|
|
1978
2212
|
}
|
|
1979
2213
|
/** 探针(D7):二进制存在 + 版本解析(zcode 无公开契约,版本漂移的入口信号)。 */
|
|
@@ -2290,6 +2524,7 @@ var ZcodeEngine = class {
|
|
|
2290
2524
|
const env = buildAppServerEnv(this.deps.processEnv ?? process.env);
|
|
2291
2525
|
env.ZCODE_ENG_CLI_PATH = cliPath;
|
|
2292
2526
|
env.ZCODE_ENG_V2_CONFIG = this.deps.sources?.v2ConfigPath ?? defaultV2ConfigPath();
|
|
2527
|
+
env.ZCODE_ENG_PROVIDER_CONFIG = resolvePersonalProviderConfigPath(this.deps.sources, engineDataDir);
|
|
2293
2528
|
const sessionDbPath = zcodeSessionDbPath(engineDataDir);
|
|
2294
2529
|
env.ZCODE_SESSION_DB_PATH = sessionDbPath;
|
|
2295
2530
|
delete env.ZCODE_SESSION_DB;
|
|
@@ -2823,9 +3058,9 @@ async function defaultProbeVersion(cliPath, dataDir) {
|
|
|
2823
3058
|
}
|
|
2824
3059
|
|
|
2825
3060
|
// src/registration.ts
|
|
2826
|
-
import { resolveEngineDataDir } from "@zhushanwen/subagent-engine-sdk";
|
|
3061
|
+
import { resolveEngineDataDir as resolveEngineDataDir2 } from "@zhushanwen/subagent-engine-sdk";
|
|
2827
3062
|
function defaultEngineDataDir() {
|
|
2828
|
-
return
|
|
3063
|
+
return resolveEngineDataDir2(process.env);
|
|
2829
3064
|
}
|
|
2830
3065
|
function createZcodeEngine(deps) {
|
|
2831
3066
|
return new ZcodeEngine(deps);
|