@zhushanwen/zcode-subagent-cli 0.8.1 → 0.8.3

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.
@@ -634,41 +634,97 @@ function resolveAccountModelRef(wanted, wantedProvider, sources) {
634
634
  `\u672A\u77E5 account provider "${wantedProvider}"\uFF08\u5185\u5EFA\u76EE\u5F55\u65E0\u6B64\u89C4\u5219\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u76EE\u5F55\u5185 account:* \u89C4\u5219\uFF08\u5982 account:zai-individual-coding-plan / account:bigmodel-individual-coding-plan\uFF09\u3002`
635
635
  );
636
636
  }
637
- assertAccountModelKnown(accountRule, wanted, wantedProvider);
638
- return wanted;
637
+ return `${wantedProvider}/${normalizeAccountModel(accountRule, wanted, wantedProvider)}`;
639
638
  }
640
639
  function findAccountProviderRule(catalog, wantedProvider) {
641
640
  const catalogRules = isRecord(catalog) && isRecord(catalog["config"]) && isRecord(catalog["config"]["providerConfigRules"]) ? catalog["config"]["providerConfigRules"]["providerRules"] : void 0;
642
641
  const accountRule = Array.isArray(catalogRules) ? catalogRules.find((r) => isRecord(r) && r["providerId"] === wantedProvider) : void 0;
643
642
  return isRecord(accountRule) ? accountRule : void 0;
644
643
  }
645
- function assertAccountModelKnown(accountRule, wanted, wantedProvider) {
644
+ function normalizeAccountModel(accountRule, wanted, wantedProvider) {
646
645
  const accountConfig = isRecord(accountRule["config"]) ? accountRule["config"] : {};
647
646
  const modelIds = accountConfig["builtinModelIds"] ?? accountConfig["personalModelIds"];
648
647
  const short = modelShort(wanted);
649
- if (Array.isArray(modelIds) && modelIds.length > 0 && !modelIds.includes(short)) {
648
+ if (!Array.isArray(modelIds) || modelIds.length === 0) return short;
649
+ const matched = modelIds.find((m) => typeof m === "string" && m.toLowerCase() === short.toLowerCase());
650
+ if (matched === void 0) {
650
651
  throw new ZcodePrepareError(
651
652
  "model_not_available",
652
- `\u672A\u77E5\u6A21\u578B "${short}"\uFF08account provider ${wantedProvider} \u4E0B\u53EF\u7528: ${modelIds.join(", ")}\uFF09\u3002`
653
+ `\u672A\u77E5\u6A21\u578B "${short}"\uFF08account provider ${wantedProvider} \u4E0B\u53EF\u7528: ${modelIds.filter((m) => typeof m === "string").join(", ")}\uFF09\u3002`
653
654
  );
654
655
  }
656
+ return matched;
657
+ }
658
+ var PI_TO_ZCODE_PROVIDER_MAP = {
659
+ "zai-coding-cn": "account:bigmodel-individual-coding-plan"
660
+ };
661
+ function translatePiModelRefToZcode(requested, sources) {
662
+ if (!requested.includes("/")) return requested;
663
+ const piProvider = providerOf(requested);
664
+ const target = PI_TO_ZCODE_PROVIDER_MAP[piProvider];
665
+ if (target === void 0) return requested;
666
+ const catalogPath = locateZcodeBuiltinCatalog(sources);
667
+ if (catalogPath === void 0) {
668
+ throw new ZcodePrepareError(
669
+ "model_not_available",
670
+ `\u6A21\u578B\u901A\u9053\u7FFB\u8BD1\u5931\u8D25\uFF1Api \u4FA7 "${piProvider}" \u5728 zcode \u4FA7\u5BF9\u5E94 ${target}\uFF0C\u4F46\u5185\u5EFA\u76EE\u5F55\u5B9A\u4F4D\u5931\u8D25\uFF08ZCODE_BUILTIN_PROVIDER_CONFIG_FILE \u4E0E runtime/provider \u626B\u63CF\u5747\u672A\u547D\u4E2D\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u786E\u8BA4 ZCode \u5DF2\u5B89\u88C5\u540E\u91CD\u8BD5\u3002`
671
+ );
672
+ }
673
+ let catalog;
674
+ try {
675
+ catalog = JSON.parse(fs2.readFileSync(catalogPath, "utf8"));
676
+ } catch (err) {
677
+ throw new ZcodePrepareError(
678
+ "model_not_available",
679
+ `\u6A21\u578B\u901A\u9053\u7FFB\u8BD1\u5931\u8D25\uFF1A\u5185\u5EFA\u76EE\u5F55\u4E0D\u53EF\u8BFB\uFF08${err instanceof Error ? err.message : String(err)}\uFF09\u3002`
680
+ );
681
+ }
682
+ const accountRule = findAccountProviderRule(catalog, target);
683
+ if (accountRule === void 0) {
684
+ throw new ZcodePrepareError(
685
+ "model_not_available",
686
+ `pi \u4FA7 "${piProvider}" \u7684 zcode \u5BF9\u5E94\u901A\u9053 ${target} \u4E0D\u53EF\u7528\uFF08\u5185\u5EFA\u76EE\u5F55\u65E0\u6B64\u89C4\u5219\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u5728 ZCode \u684C\u9762\u7AEF\u5B8C\u6210\u8BE5 plan \u7684\u8D26\u53F7\u767B\u5F55/\u914D\u7F6E\u540E\u91CD\u8BD5\u3002`
687
+ );
688
+ }
689
+ const accountConfig = isRecord(accountRule["config"]) ? accountRule["config"] : {};
690
+ const modelIds = accountConfig["builtinModelIds"] ?? accountConfig["personalModelIds"];
691
+ if (!Array.isArray(modelIds) || modelIds.length === 0) {
692
+ return `${target}/${modelShort(requested)}`;
693
+ }
694
+ const wanted = modelShort(requested).toLowerCase();
695
+ const matched = modelIds.find((m) => typeof m === "string" && m.toLowerCase() === wanted);
696
+ if (matched === void 0) {
697
+ throw new ZcodePrepareError(
698
+ "model_not_available",
699
+ `\u6A21\u578B "${modelShort(requested)}" \u5728 ${target} \u4E0B\u65E0\u7B49\u4EF7\u6A21\u578B\uFF08\u53EF\u7528: ${modelIds.filter((m) => typeof m === "string").join(", ")}\uFF09\u3002\u6062\u590D\u6307\u5F15\uFF1A\u6539\u7528\u4E0A\u8FF0\u6A21\u578B\u4E4B\u4E00\uFF0C\u6216\u7701\u7565 model \u53C2\u6570\u8D70\u5F15\u64CE\u7F3A\u7701\u3002`
700
+ );
701
+ }
702
+ return `${target}/${matched}`;
703
+ }
704
+ function translateToAccountModelRef(wanted, sources) {
705
+ const translated = translatePiModelRefToZcode(wanted, sources);
706
+ const translatedProvider = translated.includes("/") ? providerOf(translated) : void 0;
707
+ if (translatedProvider !== void 0 && translatedProvider.startsWith("account:")) {
708
+ return resolveAccountModelRef(translated, translatedProvider, sources);
709
+ }
710
+ return void 0;
655
711
  }
656
712
  function resolveZcodeModelRef(requested, sources) {
657
713
  const { conf, sourceDesc } = readPersonalProviderView(sources);
658
714
  const withKey = [...conf.providers.entries()].filter(([, e]) => hasApiKey(e));
659
715
  const wanted = requested?.trim() || void 0;
716
+ if (wanted !== void 0) {
717
+ const accountRef = translateToAccountModelRef(wanted, sources);
718
+ if (accountRef !== void 0) return accountRef;
719
+ }
660
720
  if (withKey.length === 0) {
661
721
  const hint = wanted ? `model="${wanted}" \u4E0D\u80FD\u6821\u9A8C` : "\u7F3A\u7701\u6A21\u578B\u89E3\u6790\u4E0D\u80FD\u6821\u9A8C";
662
722
  throw new ZcodePrepareError(
663
723
  "engine_credential_missing",
664
- `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
724
+ `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\u4E2D account: \u524D\u7F00\u7ECF\u8D26\u53F7 entitlement \u76F4\u901A\u53EF\u7528\uFF08builtin: \u524D\u7F00\u4E0D\u88C5\u8F7D\uFF0C\u4E0D\u53EF\u4F5C\u4E3A\u5F15\u64CE\u6A21\u578B\uFF09\u3002` + TAIJI_SYNC_GUIDANCE
665
725
  );
666
726
  }
667
727
  if (wanted === void 0) return "";
668
- const wantedProvider = wanted.includes("/") ? providerOf(wanted) : void 0;
669
- if (wantedProvider !== void 0 && wantedProvider.startsWith("account:")) {
670
- return resolveAccountModelRef(wanted, wantedProvider, sources);
671
- }
672
728
  const provider = wanted.includes("/") ? providerOf(wanted) : defaultProviderForShortName(conf, withKey);
673
729
  const short = modelShort(wanted);
674
730
  const entry = conf.providers.get(provider);
@@ -697,16 +753,58 @@ function resolveZcodeModelRef(requested, sources) {
697
753
  function listZcodeModels(sources) {
698
754
  const { conf } = readPersonalProviderView(sources);
699
755
  const out = [];
756
+ const seen = /* @__PURE__ */ new Set();
700
757
  for (const [pid, entry] of conf.providers) {
701
758
  if (!hasApiKey(entry)) continue;
702
759
  const providerName = entry.providerName !== void 0 && entry.providerName.trim() !== "" ? entry.providerName.trim() : void 0;
703
760
  for (const model of entry.models ?? []) {
761
+ if (seen.has(`${pid}/${model}`)) continue;
762
+ seen.add(`${pid}/${model}`);
704
763
  out.push({
705
764
  id: `${pid}/${model}`,
706
765
  ...providerName !== void 0 ? { name: `${providerName} \xB7 ${model}` } : {}
707
766
  });
708
767
  }
709
768
  }
769
+ for (const entry of listAccountFamilyModels(sources)) {
770
+ if (seen.has(entry.id)) continue;
771
+ seen.add(entry.id);
772
+ out.push(entry);
773
+ }
774
+ return out;
775
+ }
776
+ function readCatalogProviderRules(catalog) {
777
+ const rules = isRecord(catalog) && isRecord(catalog["config"]) && isRecord(catalog["config"]["providerConfigRules"]) ? catalog["config"]["providerConfigRules"]["providerRules"] : void 0;
778
+ return Array.isArray(rules) ? rules : [];
779
+ }
780
+ function pushAccountFamilyRuleModels(rule, out) {
781
+ if (!isRecord(rule)) return;
782
+ const providerId = rule["providerId"];
783
+ if (typeof providerId !== "string" || !providerId.startsWith("account:")) return;
784
+ const cfg = isRecord(rule["config"]) ? rule["config"] : {};
785
+ const models = Array.isArray(cfg["builtinModelIds"]) ? cfg["builtinModelIds"] : cfg["personalModelIds"];
786
+ const providerName = typeof rule["providerName"] === "string" && rule["providerName"].trim() !== "" ? rule["providerName"].trim() : void 0;
787
+ for (const model of Array.isArray(models) ? models : []) {
788
+ if (typeof model !== "string" || model.trim() === "") continue;
789
+ out.push({
790
+ id: `${providerId}/${model}`,
791
+ ...providerName !== void 0 ? { name: `${providerName} \xB7 ${model}` } : {}
792
+ });
793
+ }
794
+ }
795
+ function listAccountFamilyModels(sources) {
796
+ const catalogPath = locateZcodeBuiltinCatalog(sources);
797
+ if (catalogPath === void 0) return [];
798
+ let catalog;
799
+ try {
800
+ catalog = JSON.parse(fs2.readFileSync(catalogPath, "utf8"));
801
+ } catch {
802
+ return [];
803
+ }
804
+ const out = [];
805
+ for (const rule of readCatalogProviderRules(catalog)) {
806
+ pushAccountFamilyRuleModels(rule, out);
807
+ }
710
808
  return out;
711
809
  }
712
810
 
@@ -717,6 +815,475 @@ import * as path3 from "path";
717
815
  // src/error-message.ts
718
816
  import { toErrorMessage } from "@zhushanwen/subagent-engine-sdk";
719
817
 
818
+ // src/appserver-launcher-patches.ts
819
+ var CLI_PATCH_SECTION = `
820
+ // [2026-10-13 account \u76F4\u901A\u2461] CLI bundle \u6E90\u7801\u5185\u5B58\u8865\u4E01\uFF1A\u5916\u90E8 spawn \u7684\u8D26\u53F7\u6761\u76EE\u6784\u5EFA
821
+ // \u786C\u7F16\u7801 entitled:!1\uFF08YXe\uFF09\uFF0C\u6570\u636E\u9762\u6CE8\u5165\uFF08\u76EE\u5F55 entitled \u5B57\u6BB5\uFF09\u88AB\u5176\u65E0\u89C6\u2014\u2014\u6309\u7528\u6237\u88C1\u51B3
822
+ // \u6539 zcode \u6E90\u7801\u7ED5\u8FC7\uFF1A\u62E6\u622A CLI bundle \u6E90\u7801\u8BFB\u53D6\uFF0C\u5185\u5B58\u66FF\u6362\u8BE5\u5B57\u9762\u91CF\u4E3A !0\uFF08ZCode.app
823
+ // \u78C1\u76D8\u6587\u4EF6\u96F6\u89E6\u78B0\uFF1B\u951A\u4E32\u542B ]]:[] \u5C3E\u7F00\u552F\u4E00\u547D\u4E2D YXe \u6784\u9020\uFF0C\u53E6\u4E00\u5904\u540C\u540D\u6761\u4EF6\u903B\u8F91\u4E0D\u53D7\u5F71\u54CD\uFF09\u3002
824
+ // \u951A\u4E0D\u547D\u4E2D\uFF08\u4E0A\u6E38\u6DF7\u6DC6\u5F62\u6001\u53D8\u5316\uFF09\u2192 \u539F\u6587\u900F\u51FA\uFF1A\u4EC5 account \u5BB6\u65CF\u7EE7\u7EED\u88AB\u62D2\uFF0C\u4E2A\u4EBA provider
825
+ // \u4E0D\u53D7\u5F71\u54CD\u3002
826
+ // \u8865\u4E01\u6BB5\u5185\u8054\u626B\u63CF\u5668\uFF082026-10 review\xB7MF-1-5\uFF09\uFF1A\u8DF3\u8FC7\u5B57\u7B26\u4E32/\u6A21\u677F\u5B57\u9762\u91CF/\u6CE8\u91CA\uFF0C\u8BA9\u62EC\u53F7
827
+ // \u914D\u5E73\u4E0E\u53C2\u6570\u5207\u5206\u53EA\u5728\u4EE3\u7801\u9762\u4E0A\u8FDB\u884C\u2014\u2014bundle \u5185\u8054\u4E32\u91CC\u7684 ')' \u66FE\u628A\u8C03\u7528\u70B9\u53C2\u6570\u914D\u5E73\u5E26\u504F\u3002
828
+ // \u8FD4\u56DE -1 = \u8BE5\u4F4D\u7F6E\u4E0D\u662F\u5B57\u9762\u91CF/\u6CE8\u91CA\u8D77\u70B9\uFF08\u6B63\u5E38\u4EE3\u7801\u5B57\u7B26\uFF09\u3002
829
+ function __skipLiteralOrComment(src, i) {
830
+ const ch = src[i];
831
+ if (ch === '"' || ch === "'") {
832
+ i++;
833
+ while (i < src.length) {
834
+ if (src.charCodeAt(i) === 92) { i += 2; continue; }
835
+ if (src[i] === ch) return i + 1;
836
+ i++;
837
+ }
838
+ return i;
839
+ }
840
+ if (ch === '\`') {
841
+ i++;
842
+ while (i < src.length) {
843
+ if (src.charCodeAt(i) === 92) { i += 2; continue; }
844
+ const c = src[i];
845
+ if (c === '\`') return i + 1;
846
+ if (c === '$' && src[i + 1] === '{') {
847
+ let depth = 1;
848
+ i += 2;
849
+ while (i < src.length && depth > 0) {
850
+ const cc = src[i];
851
+ if (cc === '"' || cc === "'" || cc === '\`') { i = __skipLiteralOrComment(src, i); continue; }
852
+ if (cc === '/' && src[i + 1] === '/') { const nl = src.indexOf('\\n', i + 2); i = nl < 0 ? src.length : nl + 1; continue; }
853
+ if (cc === '/' && src[i + 1] === '*') { const end = src.indexOf('*/', i + 2); i = end < 0 ? src.length : end + 2; continue; }
854
+ if (cc === '{') depth++;
855
+ else if (cc === '}') depth--;
856
+ i++;
857
+ }
858
+ continue;
859
+ }
860
+ i++;
861
+ }
862
+ return i;
863
+ }
864
+ if (ch === '/' && src[i + 1] === '/') {
865
+ const nl = src.indexOf('\\n', i + 2);
866
+ return nl < 0 ? src.length : nl + 1;
867
+ }
868
+ if (ch === '/' && src[i + 1] === '*') {
869
+ const end = src.indexOf('*/', i + 2);
870
+ return end < 0 ? src.length : end + 2;
871
+ }
872
+ return -1;
873
+ }
874
+ // \u4E0E openIdx \u5904 '(' \u914D\u5BF9\u7684\u95ED\u62EC\u53F7\uFF08\u8DF3\u8FC7\u5B57\u9762\u91CF/\u6CE8\u91CA\uFF09\uFF1B-1 = \u4E0D\u914D\u5E73\u3002
875
+ function __matchingParen(src, openIdx) {
876
+ let depth = 0;
877
+ for (let i = openIdx; i < src.length; i++) {
878
+ const skip = __skipLiteralOrComment(src, i);
879
+ if (skip >= 0) { i = skip - 1; continue; }
880
+ const c = src[i];
881
+ if (c === '(') depth++;
882
+ else if (c === ')') { depth--; if (depth === 0) return i; }
883
+ }
884
+ return -1;
885
+ }
886
+ // [start,end) \u5185\u6309\u9876\u5C42\u9017\u53F7\u5207\u5206\uFF08\u62EC\u53F7/\u65B9\u62EC\u53F7/\u5BF9\u8C61\u5B57\u9762\u91CF\u4E0E\u5B57\u9762\u91CF\u5185\u7684\u9017\u53F7\u4E0D\u8BA1\uFF09\uFF1B
887
+ // \u8FD4\u56DE\u7EDD\u5BF9\u504F\u79FB\u6BB5\u5217\u8868\u3002
888
+ function __splitTopLevel(src, start, end) {
889
+ const parts = [];
890
+ let depth = 0;
891
+ let segStart = start;
892
+ for (let i = start; i < end; i++) {
893
+ const skip = __skipLiteralOrComment(src, i);
894
+ if (skip >= 0) { i = Math.min(skip, end) - 1; continue; }
895
+ const c = src[i];
896
+ if (c === '(' || c === '[' || c === '{') depth++;
897
+ else if (c === ')' || c === ']' || c === '}') depth--;
898
+ else if (c === ',' && depth === 0) { parts.push({ start: segStart, end: i }); segStart = i + 1; }
899
+ }
900
+ parts.push({ start: segStart, end: end });
901
+ return parts;
902
+ }
903
+ const __cliPatchCache = new Map();
904
+ // \u5E94\u7528\u6001\u6807\u5FD7\u53D1\u5E03\uFF082026-10 review\uFF09\uFF1A\u5B89\u88C5\u95E8\u66FE\u4EE5\u8865\u4E01\u4EA7\u7269\u5B50\u4E32\u5224\u5B9A header-port\u2014\u2014\u771F\u5B9E
905
+ // 3.15.3 bundle \u672C\u5C31\u542B 8 \u5904 'providerRuntimeHeadersPort:'\uFF082 \u5904 ',providerRuntimeHeadersPort:'\uFF09
906
+ // \u2192 \u5B50\u4E32\u5224\u5B9A\u6052\u771F\u3001\u5BF9\u951A\u70B9\u6F02\u79FB\u96F6\u68C0\u6D4B\u529B\u3002\u6539\u7531\u8865\u4E01\u51FD\u6570\u672C\u8EAB\u53D1\u5E03 {entitled,standalone,
907
+ // headerPort}\uFF08\u7F13\u5B58\u547D\u4E2D\u4ECD\u53EF\u8BFB\uFF09\uFF0C\u95E8\u53EA\u8BFB\u6807\u5FD7\uFF08\u4E09\u5904\u5224\u5B9A\u5404\u81EA\u5177\u540D\uFF0C\u6F02\u79FB\u4E0D\u9759\u9ED8\uFF09\u3002
908
+ const __cliPatchStatus = new Map();
909
+ function patchedCliSource(path) {
910
+ if (__cliPatchCache.has(path)) return __cliPatchCache.get(path);
911
+ let result = null;
912
+ let entitledApplied = false;
913
+ let standaloneApplied = false;
914
+ let portInjected = false;
915
+ try {
916
+ const readOrig = fs.__origReadFileSync || fs.readFileSync;
917
+ let src = readOrig(path, 'utf8');
918
+ // \u2460 \u7248\u672C\u9C81\u68D2\u951A\uFF082026-10-13 \u4FEE\u8BA2\uFF09\uFF1Aminified \u6807\u8BC6\u7B26\uFF08Uk/I3 \u7B49\uFF09\u968F zcode \u91CD\u65B0\u6253\u5305
919
+ // \u6F02\u79FB\uFF0C\u5C5E\u6027\u540D\uFF08zcodeBuiltinProviders / zhipu-account / entitled\uFF09\u662F\u6570\u636E/\u5951\u7EA6
920
+ // \u771F\u540D\u4E0D\u88AB\u6DF7\u6DC6\u2014\u2014\u4EE5\u5C5E\u6027\u540D\u5B9A\u4F4D + 600 \u5B57\u7B26\u7A97\u53E3\u5185\u628A\u8D26\u53F7\u6761\u76EE\u6784\u5EFA\u7684 entitled:!1
921
+ // \u7FFB\u8F6C\u4E3A !0\u3002\u7A97\u53E3\u96F6\u547D\u4E2D = \u4E0A\u6E38\u5F62\u6001\u6F02\u79FB \u2192 \u539F\u6587\u900F\u51FA + stderr warn\uFF08\u6F02\u79FB\u53EF\u89C1\uFF0C
922
+ // \u8FDB app-server stderr \u65E5\u5FD7\uFF09\u3002
923
+ const anchorIdx = src.indexOf('zcodeBuiltinProviders.entries()');
924
+ if (anchorIdx >= 0) {
925
+ const window = src.slice(anchorIdx, Math.min(src.length, anchorIdx + 600));
926
+ if (window.indexOf('zhipu-account') >= 0 && window.indexOf('entitled:!1') >= 0) {
927
+ src = src.slice(0, anchorIdx)
928
+ + window.split('entitled:!1').join('entitled:!0')
929
+ + src.slice(anchorIdx + 600);
930
+ entitledApplied = true;
931
+ }
932
+ }
933
+ if (!entitledApplied) {
934
+ process.stderr.write('[zcode-launcher] account bypass: CLI bundle anchor not found (zcode upstream shape drifted?) - account family stays gated\\n');
935
+ }
936
+ // \u2461 [2026-10-16 standalone account] \u534F\u8BAE\u8DEF\u5F84\u7684 provider registry \u6052\u4EE5 host-account
937
+ // \u6A21\u5F0F\u521B\u5EFA\uFF08\u6E90\u7801\uFF1Acreate:r(()=>xCt(z),"create") \u4E0D\u4F20 standalone\uFF09\u2014\u2014\u8BE5\u6A21\u5F0F\u4E0B
938
+ // account \u65CF\u8BF7\u6C42\u5FC5\u987B\u7531\u5BBF\u4E3B\u5E94\u7B54 providerRuntimeHeaders\uFF1Btaiji \u7684 headless spawn \u65E0
939
+ // \u5BBF\u4E3B\u53C2\u4E0E\u8BE5\u534F\u8BAE\uFF0C\u5E94\u7B54\u5E27\u7578\u5F62 \u2192 zod invalid_union(headersApplied)\uFF082026-10-16 \u771F\u673A
940
+ // \u4E8B\u6545\u6839\u56E0\uFF1B\u5BBF\u4E3B\u65E5\u5FD7\u96F6\u8E2A\u8FF9 = \u8BF7\u6C42\u4ECE\u672A\u5230\u8FBE\u4EFB\u4F55 host \u5B9E\u73B0\uFF09\u3002\u672C\u8865\u4E01\u7ED9\u8BE5\u8C03\u7528\u6CE8\u5165
941
+ // {standalone:{}}\uFF1Astandalone \u6A21\u5F0F\u81EA\u5EFA\u672C\u5730\u8D26\u53F7\u6E90\uFF08entitled \u7531\u51ED\u636E\u5B58\u5728\u6027\u8BA1\u7B97\uFF0C
942
+ // \u8BFB credentials.json\uFF09\u5E76\u6CE8\u5165\u672C\u5730 providerRuntimeHeaders \u7AEF\u53E3\u2014\u2014\u8D26\u53F7\u65CF\u5168\u94FE\u672C\u5730
943
+ // \u5B8C\u6210\u3001\u96F6\u5BBF\u4E3B\u4F9D\u8D56\u3002\u951A\u70B9\u4E24\u5904\u7A33\u5B9A\u4E32\uFF08\u975E minified\uFF09\uFF1A\u6A21\u5757\u5BFC\u51FA\u6620\u5C04
944
+ // startProcessProviderRegistryRuntime:()=> \u53D6\u51FD\u6570\u540D + \u8C03\u7528\u70B9 create:r(()=><fn>(\u3002
945
+ const exportAnchor = 'startProcessProviderRegistryRuntime:()=>';
946
+ const exportIdx = src.indexOf(exportAnchor);
947
+ if (exportIdx >= 0) {
948
+ // \u540D\u79F0\u5C3E\u90E8\u987B\u662F\u5206\u9694\u7B26\uFF08\u771F\u5B9E\u5F62\u6001 = \u5BFC\u51FA\u6620\u5C04\u5BF9\u8C61 ',' / '}'\uFF09\uFF1A'{0,10}' \u4E0A\u9650\u4F1A\u9759\u9ED8
949
+ // \u622A\u65AD\u66F4\u957F\u7684 minified \u540D \u2192 \u53D6\u5230\u9519\u8BEF\u51FD\u6570\u540D\uFF1B\u8981\u6C42\u5206\u9694\u7B26\u540E\u622A\u65AD\u4E0D\u6210\u7ACB\uFF08\u6F02\u79FB\u53EF\u89C1\uFF09\u3002
950
+ const nameMatch = /^([A-Za-z_$][A-Za-z0-9_$]*)(?=[,}:])/.exec(src.slice(exportIdx + exportAnchor.length));
951
+ const fnName = nameMatch ? nameMatch[1] : null;
952
+ if (fnName) {
953
+ // \u951A\u70B9 A\uFF08\u9996\u9009\uFF0C\u6297\u6F02\u79FB\u6700\u5F3A\uFF09\uFF1A\u51FD\u6570\u5B9A\u4E49\u9ED8\u8BA4\u53C2\u6570\u6CD5\u2014\u2014
954
+ // 'function <fnName>(e,t={}){' \u2192 'function <fnName>(e,t={standalone:{}}){'\u3002
955
+ // \u8BED\u4E49\uFF1A\u8C03\u7528\u65B9\u7701\u7565\u7B2C\u4E8C\u53C2\uFF08\u534F\u8BAE\u8DEF\u5F84 xCt(z)\uFF09\u2192 t = {standalone:{}}\uFF1B\u663E\u5F0F\u4F20
956
+ // {}\uFF08skipUserConfig \u8DEF\u5F84\uFF09\u6216 {standalone:{...}}\uFF08TUI \u8DEF\u5F84\uFF09\u4E0D\u53D7\u5F71\u54CD\u3002
957
+ const defAnchor = 'function ' + fnName + '(';
958
+ // \u7ED3\u6784\u6821\u9A8C\uFF082026-10 review\xB7MF-1-5\uFF09\uFF1A\u66FE\u53D6\u9996\u4E2A\u6587\u672C\u547D\u4E2D\u2014\u2014\u771F\u5B9E bundle \u6709\u6570\u767E\u4E2A
959
+ // \u91CD\u540D function \u5B9A\u4E49\uFF08\u540C\u540D\u4E0D\u4EE3\u8868\u552F\u4E00\uFF09\uFF0C\u9519\u6539\u4E00\u5904\u4ECD\u662F\u8BED\u6CD5\u5408\u6CD5 bundle\uFF0C\u81EA\u68C0\u65E0\u6CD5
960
+ // \u53D1\u73B0\u4E14\u95E8\u4F1A\u62A5 armed\u3002\u5B9A\u4E49\u5FC5\u987B**\u552F\u4E00**\u4E14\u4F4D\u4E8E\u5BFC\u51FA\u6620\u5C04\u4E4B\u524D\uFF1B\u7B2C\u4E8C\u5904\u51FA\u73B0\u6216\u5B9A\u4E49
961
+ // \u843D\u5728\u5BFC\u51FA\u6620\u5C04\u4E4B\u540E = \u65E0\u6CD5\u786E\u5B9A\u5BFC\u51FA\u5BF9\u8C61\u6307\u5411\u7684\u5B9E\u73B0 \u2192 \u653E\u5F03\u672C\u951A\uFF08\u56DE\u9000\u8C03\u7528\u70B9\u951A /
962
+ // not armed\uFF09\uFF0C\u5B81\u53EF\u6F0F\u8865\u4E5F\u4E0D\u9ED8\u9ED8\u6539\u9519\u4F4D\u7F6E\u3002
963
+ let defCount = 0;
964
+ let defIdx = -1;
965
+ for (let scan = src.indexOf(defAnchor); scan >= 0; scan = src.indexOf(defAnchor, scan + 1)) {
966
+ defCount++;
967
+ if (scan < exportIdx) defIdx = scan;
968
+ }
969
+ if (defCount !== 1) defIdx = -1;
970
+ if (defIdx >= 0) {
971
+ const paramsEnd = __matchingParen(src, defIdx + defAnchor.length - 1);
972
+ if (paramsEnd > defIdx) {
973
+ // \u5FC5\u987B\u6070\u597D\u4E24\u4E2A\u9876\u5C42\u53C2\u6570\u4E14\u7B2C\u4E8C\u4E2A\u4EE5 '={}' \u6536\u5C3E\uFF1A\u66FE\u53EA\u8981\u6C42 '={}' \u552F\u4E00\u2014\u2014
974
+ // function f(e={},t) \u4F1A\u628A standalone \u6CE8\u5165\u7B2C\u4E00\u4E2A\u53C2\u6570\uFF08\u8BED\u6CD5\u5408\u6CD5\u3001\u8BED\u4E49\u9519\u8BEF\uFF09\uFF0C
975
+ // function f(e,t={},o={}) \u4E5F\u4E0D\u786E\u5B9A\u6CE8\u5165\u70B9\uFF08\u65E2\u6709\u56DE\u9000\u7528\u4F8B\uFF09\u3002
976
+ const params = __splitTopLevel(src, defIdx + defAnchor.length, paramsEnd);
977
+ if (params.length === 2) {
978
+ const second = params[1];
979
+ let secondEnd = second.end;
980
+ while (secondEnd > second.start && src.charCodeAt(secondEnd - 1) <= 32) secondEnd--;
981
+ // \u51FD\u6570\u4F53\u7A97\u53E3\u4EE4\u724C\uFF08\u53EF\u9009\u4FDD\u9669\uFF09\uFF1A\u771F\u5B9E\u6CE8\u518C\u6E90\u5B9E\u88C5\u5F15\u7528 .standalone /
982
+ // credentialStore\u2014\u2014\u540C\u540D\u4F46\u65E0\u5173\u7684\u5B9A\u4E49\uFF08\u6216\u5B57\u7B26\u4E32\u5185\u4F2A\u547D\u4E2D\uFF09\u4E0D\u5F97\u88AB\u6539\u5199\u3002
983
+ const bodyWindow = src.slice(paramsEnd + 1, paramsEnd + 500);
984
+ if (secondEnd - second.start > 3 && src.slice(secondEnd - 3, secondEnd) === '={}'
985
+ && (bodyWindow.indexOf('standalone') >= 0 || bodyWindow.indexOf('credentialStore') >= 0)) {
986
+ const at = secondEnd - 3;
987
+ src = src.slice(0, at) + '={standalone:{}}' + src.slice(secondEnd);
988
+ standaloneApplied = true;
989
+ }
990
+ }
991
+ }
992
+ }
993
+ // \u951A\u70B9 B\uFF08\u56DE\u9000\uFF09\uFF1A\u8C03\u7528\u70B9\u6CE8\u5165 create:r(()=><fn>( \u2192 (<arg>,{standalone:{}})\u3002
994
+ // \u7ED3\u6784\u6821\u9A8C\u4E0E\u5B9A\u4E49\u951A\u540C\u53E3\u5F84\uFF082026-10 review\xB7N-1\uFF09\uFF1A\u5168\u6587\u4EF6\u51FA\u73B0\u6B21\u6570\u5FC5\u987B\u6070\u597D 1
995
+ // \u2014\u2014\u66FE\u53D6\u9996\u4E2A\u6587\u672C\u547D\u4E2D\uFF0C\u672A\u6765\u7248\u672C\u51FA\u73B0\u4E24\u5904\u540C\u6B3E\u8C03\u7528\u65F6\u6CE8\u5165\u843D\u5728\u65E0\u5173\u8C03\u7528\u4E0A\u3001
996
+ // standaloneApplied \u4ECD\u7F6E true = \u771F\u5B9E\u534F\u8BAE\u8DEF\u5F84 host \u6A21\u5F0F\u800C\u95E8\u62A5 armed \u7684\u5047\u6210\u529F\u3002
997
+ // count > 1 = \u65E0\u6CD5\u786E\u5B9A\u534F\u8BAE\u8DEF\u5F84\u8C03\u7528\u70B9 \u2192 \u653E\u5F03\u672C\u951A\uFF08not armed\uFF09\u3002
998
+ if (!standaloneApplied) {
999
+ const callAnchor = 'create:r(()=>' + fnName + '(';
1000
+ let callCount = 0;
1001
+ let callIdx = -1;
1002
+ for (let scan = src.indexOf(callAnchor); scan >= 0; scan = src.indexOf(callAnchor, scan + 1)) {
1003
+ callCount++;
1004
+ callIdx = scan;
1005
+ }
1006
+ if (callCount === 1) {
1007
+ const argStart = callIdx + callAnchor.length;
1008
+ // \u62EC\u53F7\u914D\u5E73\u627E\u4E0E fnName( \u914D\u5BF9\u7684\u95ED\u62EC\u53F7\uFF08\u626B\u63CF\u5668\u8DF3\u8FC7\u5B57\u9762\u91CF/\u6A21\u677F/\u6CE8\u91CA\u2014\u2014\u5B9E\u53C2
1009
+ // \u542B\u5185\u8054\u4E32\u6216\u5185\u5C42\u8C03\u7528\u65F6\u9996\u4E2A ')' \u843D\u5728\u9519\u8BEF\u5C42\u7EA7 = \u6CE8\u5165\u9519\u4F4D\u7684\u5047\u6210\u529F\uFF09
1010
+ const closeIdx = __matchingParen(src, argStart - 1);
1011
+ if (closeIdx > argStart) {
1012
+ src = src.slice(0, closeIdx) + ',{standalone:{}}' + src.slice(closeIdx);
1013
+ standaloneApplied = true;
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+ }
1019
+ if (!standaloneApplied) {
1020
+ process.stderr.write('[zcode-launcher] standalone account: CLI bundle anchor not found (zcode upstream shape drifted?) - account family stays host-dependent\\n');
1021
+ }
1022
+ // \u2462 [2026-10-16 standalone account\xB7\u7AEF\u53E3\u6CE8\u5165] \u534F\u8BAE\u8DEF\u5F84\u7684 app \u521B\u5EFA\uFF08
1023
+ // createZCodeApp:r((ut={})=>INn({...q0c(...)}) \u552F\u4E00\u547D\u4E2D\uFF09\u672A\u4F20
1024
+ // providerRuntimeHeadersPort\u2014\u2014app \u56E0\u6B64\u56DE\u843D host \u8BF7\u6C42\u7AEF\u53E3\uFF08mai\uFF09\uFF0C\u800C taiji \u94FE\u4E0A\u65E0
1025
+ // \u5BBF\u4E3B\u4EFB\u5E94\u7B54 \u2192 zod invalid_union(headersApplied)\uFF08\u2461\u53EA\u4FEE\u4E86 registry \u4FA7\uFF1Aprovider
1026
+ // \u5DF2\u80FD\u8FDB\u6CE8\u518C\u8868\uFF0C\u4F46\u8BA4\u8BC1\u5934\u4ECD\u8D70 host \u8BF7\u6C42\uFF09\u3002\u672C\u6B65\u628A registry runtime \u5BF9\u8C61\u4E0A\u7684
1027
+ // providerRuntimeHeadersPort\uFF08standalone \u6A21\u5F0F = \u672C\u5730\u7AEF\u53E3\uFF09\u6CE8\u5165\u8BE5 app \u521B\u5EFA\u9009\u9879\uFF1A
1028
+ // \u8D26\u53F7\u65CF\u8BA4\u8BC1\u5934\u7531\u672C\u8FDB\u7A0B\u672C\u5730\u89E3\u6790\uFF08\u51ED\u636E = credentials.json \u4E2D ZCode \u81EA\u6709\u9879\uFF09\u3002
1029
+ const appAnchor = 'createZCodeApp:r(';
1030
+ const appIdx = src.indexOf(appAnchor);
1031
+ if (appIdx >= 0) {
1032
+ const closeAnchor = '}),"createZCodeApp")';
1033
+ const closeIdx = src.indexOf(closeAnchor, appIdx);
1034
+ // \u641C\u7D22\u7A97\u4EE5\u6536\u53E3\u951A\u4E3A\u754C\uFF08\u66FE\u7528 appIdx+1600 \u56FA\u5B9A\u7A97\u2014\u2014\u7A97\u53E3\u8D8A\u8FC7\u6536\u53E3\u4F1A\u6355\u83B7\u9009\u9879\u5BF9\u8C61\u5916
1035
+ // \u7684\u65E0\u5173\u540C\u540D\u5F62\u6001\uFF0C\u6CE8\u5165\u9519\u8BEF\u53D8\u91CF\u540D \u2192 \u52A0\u8F7D\u671F ReferenceError \u4E14\u8865\u4E01\u5C42\u65E0 warn\uFF09
1036
+ const regMatch = closeIdx > appIdx
1037
+ ? /([A-Za-z_$][A-Za-z0-9_$]*).runtime.registryService/.exec(src.slice(appIdx, closeIdx))
1038
+ : null;
1039
+ if (closeIdx > appIdx && regMatch) {
1040
+ // \u6761\u4EF6 spread\uFF082026-10 review\xB7S-4\uFF09\uFF1A\u4E0A\u6E38 kEt \u4EE5 \`n.providerRuntimeHeadersPort ??
1041
+ // mai(e,t)\` \u628A\u5BBF\u4E3B\u8BF7\u6C42\u7AEF\u53E3\u663E\u5F0F\u4EA4\u7ED9 createZCodeApp\uFF08...q0c($0c(ut,n),...) \u5DF2\u542B\u8BE5\u503C\uFF09\uFF1B
1042
+ // \u65E0\u6761\u4EF6\u5C3E\u63D2 <reg>.providerRuntimeHeadersPort \u5728 standalone \u672A\u6B66\u88C5\u5F62\u6001\uFF08\u503C\u4E3A
1043
+ // undefined\uFF09\u4F1A shadow \u6389\u5BBF\u4E3B\u7AEF\u53E3\u3001\u62B9\u9664 host \u56DE\u843D\u3002\u6539\u4E3A\u4EC5\u5728\u672C\u5730\u7AEF\u53E3\u5B58\u5728\u65F6\u8986\u76D6\uFF1A
1044
+ // standalone \u5F62\u6001\u5B57\u8282\u7B49\u4EF7\uFF0Chost \u5F62\u6001\u4FDD\u7559\u8C03\u7528\u65B9\u503C\u3002
1045
+ const reg = regMatch[1];
1046
+ src = src.slice(0, closeIdx)
1047
+ + ',...(' + reg + '.providerRuntimeHeadersPort?{providerRuntimeHeadersPort:' + reg + '.providerRuntimeHeadersPort}:{})'
1048
+ + src.slice(closeIdx);
1049
+ portInjected = true;
1050
+ }
1051
+ }
1052
+ if (!portInjected) {
1053
+ process.stderr.write('[zcode-launcher] standalone account: header-port injection anchor not found (zcode upstream shape drifted?) - account auth stays host-dependent\\n');
1054
+ }
1055
+ // \u4EA4\u4ED8\u6761\u4EF6\u542B portInjected\uFF082026-10 review \u4FEE\u6B63\uFF09\uFF1A\u66FE\u53EA\u8BA4 entitled/standalone\u2014\u2014
1056
+ // \u7AEF\u53E3\u951A\u5355\u72EC\u547D\u4E2D\u65F6\u8865\u4E01\u4EA7\u7269\u88AB\u9759\u9ED8\u4E22\u5F03\uFF08\u2462 \u5F62\u540C\u865A\u8BBE\uFF0C\u65E0\u4EFB\u4F55\u4FE1\u53F7\uFF09\u3002
1057
+ if (entitledApplied || standaloneApplied || portInjected) {
1058
+ // \u7F13\u5B58\u524D\u8BED\u6CD5\u81EA\u68C0\uFF08\u5EC9\u4EF7\u4FDD\u9669\uFF09\uFF1A\u951A\u6F02\u79FB\u5F62\u6001\u4E0B\u63D2\u9519\u4F4D\u7F6E\u4F1A\u4EA7\u51FA\u8BED\u6CD5\u975E\u6CD5 bundle\uFF0C
1059
+ // app-server \u542F\u52A8\u5373\u88F8 SyntaxError \u4E14\u96BE\u5F52\u56E0\u8865\u4E01\u5C42\u2014\u2014\u7F13\u5B58\u524D try \u7F16\u8BD1\u4E00\u6B21\uFF0C
1060
+ // \u5931\u8D25\u56DE\u9000\u539F\u6587 + stderr warn\uFF08\u8D70\u65E2\u6709\u300C\u539F\u6587\u900F\u51FA\u300D\u964D\u7EA7\u8BED\u4E49\uFF09\u3002BOM/shebang \u5265\u79BB
1061
+ // \u4E0E .js \u6269\u5C55\u5904\u7406\u5668\u540C\u6B3E\uFF08\u5426\u5219\u5408\u6CD5 CJS \u88AB\u8BEF\u5224\u975E\u6CD5\uFF09\u3002
1062
+ let check = src;
1063
+ if (check.charCodeAt(0) === 0xfeff) check = check.slice(1);
1064
+ if (check.startsWith('#!')) check = check.slice(check.indexOf('\\n') + 1);
1065
+ try {
1066
+ new Function(check);
1067
+ result = src;
1068
+ } catch (syntaxErr) {
1069
+ process.stderr.write('[zcode-launcher] cli-source patch produced invalid JS (' + ((syntaxErr && syntaxErr.message) || 'unknown') + ') - falling back to unpatched source\\n');
1070
+ result = null;
1071
+ }
1072
+ } else {
1073
+ result = null;
1074
+ }
1075
+ } catch { result = null; }
1076
+ __cliPatchCache.set(path, result);
1077
+ // \u6807\u5FD7\u53EA\u63CF\u8FF0\u300C\u5DF2\u4EA4\u4ED8\u4EA7\u7269\u300D\uFF1A\u8BED\u6CD5\u81EA\u68C0\u5931\u8D25/\u5F02\u5E38\u56DE\u9000\uFF08result=null\uFF09\u65F6\u5168\u90E8 false\u2014\u2014
1078
+ // \u95E8\u4E0D\u5F97\u628A\u672A\u751F\u6548\u7684\u8865\u4E01\u62A5\u6210 armed\u3002
1079
+ __cliPatchStatus.set(path, {
1080
+ entitled: result !== null && entitledApplied,
1081
+ standalone: result !== null && standaloneApplied,
1082
+ headerPort: result !== null && portInjected,
1083
+ });
1084
+ return result;
1085
+ }`;
1086
+ var ACCOUNT_METADATA_SECTION = `
1087
+ // [2026-10-16 standalone account metadata] standalone \u8D26\u53F7\u6E90\u8981\u6C42
1088
+ // account-provider:<planProviderId>:identity / :auth-source \u4E24\u6761**\u5143\u6570\u636E**\u952E\u624D\u627F\u8BA4
1089
+ // account provider\uFF08\u7F3A identity \u76F4\u63A5\u4E22\u5F03\u8BE5 provider \u2192 \u6D3E\u53D1\u62A5\u300CProvider Registry \u4E2D
1090
+ // \u4E0D\u5B58\u5728 Model\u300D\uFF09\u3002\u4E24\u952E\u975E\u79D8\u5BC6\uFF08\u8EAB\u4EFD ID / \u8BA4\u8BC1\u6765\u6E90\uFF09\uFF0C\u771F\u51ED\u636E\u4ECD\u662F ZCode \u81EA\u6709\u9879
1091
+ // \uFF08oauth token \u6216 plan api-key\uFF0C\u5747\u5728 credentials.json\uFF0C\u7531 ZCode \u767B\u5F55/\u914D\u7F6E\u5199\u5165\uFF09\u3002
1092
+ // \u672C\u6B65\u5E42\u7B49\u4F9B\u7ED9\uFF1A\u7F3A\u65F6\u8FFD\u52A0 + **\u5B64\u513F\u503C\u77EB\u6B63**\uFF082026-10 review\xB7MF-1-1\uFF09\u2014\u2014\u6D3E\u751F\u503C\u6BCF\u6B21
1093
+ // spawn \u91CD\u7B97\uFF0C\u65E2\u6709\u975E\u7A7A\u503C\u4ECD\u662F\u6743\u5A01\uFF08\u4E0D\u65E0\u5DEE\u522B\u8986\u5199\uFF09\uFF0C\u4EC5\u5F53\u5176\u80CC\u540E\u51ED\u636E\u5DF2\u4E0D\u5B58\u5728\u65F6\u624D
1094
+ // \u6539\u5199\uFF08oauth \u64A4\u9500 / plan key \u8F6E\u6362 / \u8D26\u53F7\u5207\u6362\uFF09\uFF1B\u5426\u5219\u65E7\u8EAB\u4EFD/\u65E7\u6765\u6E90\u4F1A\u6C38\u4E45\u95E8\u63A7\u8BE5
1095
+ // provider \u4E14\u6C38\u4E0D\u6536\u655B\u3002\u4EFB\u4F55\u5931\u8D25\u53EA warn \u4E0D\u963B\u65AD spawn\uFF08\u7F3A\u952E\u7684\u62A5\u9519\u8DEF\u5F84\u4E0E\u6062\u590D\u6307\u5F15\u7531
1096
+ // \u5F15\u64CE\u4FA7\u65E2\u6709\u6587\u6848\u627F\u8F7D\uFF09\u3002catches\uFF1A\u6587\u4EF6\u7F3A\u5931/\u574F JSON/\u76EE\u5F55\u4E0D\u53EF\u5199\u3002
1097
+ // \u5E76\u53D1\u8FB9\u754C\uFF08ADR-0143 \u767B\u8BB0\uFF09\uFF1A\u5BF9\u4E0E GUI \u5171\u4EAB\u7684\u51ED\u636E\u5E93\u505A\u65E0\u9501 read-modify-write \u5168\u91CF
1098
+ // \u5199\u56DE\uFF0C\u4E0E GUI token \u5237\u65B0\u5E76\u53D1\u5B58\u5728\u6BEB\u79D2\u7EA7\u4E22\u66F4\u65B0\u7A97\u53E3\u2014\u2014\u540E\u679C\u81EA\u6108\uFF08GUI \u4FA7\u91CD\u8BD5\u5237\u65B0 /
1099
+ // \u672C\u4FA7\u7F3A\u952E\u4E0B\u6B21 spawn \u5E42\u7B49\u8865\u9F50\uFF09\uFF0C\u4E8B\u5B9E\u9A71\u52A8\u539F\u5219\u4E0B\u4E0D\u52A0\u9501\u3001\u4E0D\u505A\u65F6\u95F4\u8865\u507F\u3002\u5143\u6570\u636E\u952E
1100
+ // \u9762\u53E6\u52A0 compare-and-skip \u9632\u7EBF\uFF082026-10 review\xB7N-3\uFF09\uFF1A\u5199\u56DE\u524D\u91CD\u8BFB\u78C1\u76D8\u6BD4\u5BF9
1101
+ // identity/auth-source \u4E24\u952E\uFF0C\u68C0\u6D4B\u5230\u5E76\u53D1\u5199\u5165\u5373\u653E\u5F03\u672C\u6B21\u5199\u5165\uFF08\u89C1\u843D\u5E93\u6BB5\u6CE8\u91CA\uFF09\u3002
1102
+ // \u8C03\u7528\u5951\u7EA6\uFF082026-10 review\xB7S-3\uFF09\uFF1A\u4EC5\u5728\u5B89\u88C5\u95E8\u786E\u8BA4 standalone \u4E0E header-port \u4E24\u951A
1103
+ // \u5747\u5DF2\u6B66\u88C5\u65F6\u8C03\u7528\u2014\u2014\u8FD9\u4E9B\u5143\u6570\u636E\u952E\u53EA\u88AB standalone \u8D26\u53F7\u6E90\u6D88\u8D39\uFF0C\u4E14\u8D26\u53F7\u94FE\u8981\u6210\u7ACB\u8FD8\u8981\u6C42
1104
+ // \u8BA4\u8BC1\u5934\u8D70\u672C\u5730\u7AEF\u53E3\uFF1B\u4EFB\u4E00\u951A\u6F02\u79FB\uFF08\u7248\u672C\u4E0D\u652F\u6301\uFF09\u65F6\u5199\u5165\u7528\u6237\u5171\u4EAB credentials.json \u65E0
1105
+ // \u4EFB\u4F55\u8FD0\u884C\u65F6\u6536\u76CA\uFF0C\u53EA\u589E\u98CE\u9669\u3002
1106
+ function ensureAccountMetadata() {
1107
+ try {
1108
+ const credPath = path.join(os.homedir(), '.zcode', 'v2', 'credentials.json');
1109
+ const readOrig = fs.__origReadFileSync || fs.readFileSync;
1110
+ if (!fs.existsSync(credPath)) return;
1111
+ const creds = JSON.parse(readOrig.call(fs, credPath, 'utf8'));
1112
+ if (!creds || typeof creds !== 'object' || Array.isArray(creds)) return;
1113
+ if (!CATALOG_PATH) return;
1114
+ let planIds = [];
1115
+ try {
1116
+ const cat = JSON.parse(readOrig.call(fs, CATALOG_PATH, 'utf8'));
1117
+ const pcr = (cat && cat.config && cat.config.providerConfigRules) || {};
1118
+ const rules = Array.isArray(pcr.providerRules) ? pcr.providerRules : [];
1119
+ planIds = rules
1120
+ // \u8FC7\u6EE4\u9762\u523B\u610F\u5BBD\u4E8E 3.15.3 standalone \u5FEB\u7167\u7684\u6D88\u8D39\u5224\u636E\uFF08\u6E90\u7801 NNn\uFF1Atype=zhipu-account
1121
+ // && mode=individual-coding-plan && accountType \u975E\u7A7A && builtinModelIds \u975E\u7A7A\uFF1B
1122
+ // \u771F\u5B9E\u76EE\u5F55 10 \u6761\u547D\u4E2D\u3001\u4EC5 2 \u6761\u88AB individual \u5FEB\u7167\u6D88\u8D39\uFF09\uFF1A\u591A\u5199\u7684\u952E\u662F\u975E\u79D8\u5BC6\u5143\u6570\u636E\u3001
1123
+ // \u7F3A\u65F6\u8FFD\u52A0\u6210\u672C\u2248\u96F6\uFF1B\u800C mode \u503C\u57DF\uFF08individual/team/start/off-peak/
1124
+ // highspeed\uFF09\u8DE8 CLI \u7248\u672C\u4ECD\u5728\u6F14\u5316\uFF0C\u6309\u5F53\u524D\u7248\u672C\u6536\u7A84\u4F1A\u8BA9\u522B\u7684\u7248\u672C/\u672A\u6765\u6D88\u8D39\u9762
1125
+ // \u9759\u9ED8\u7F3A\u952E\u3002\u5BBD\u5EA6\u662F\u6709\u610F\u7684\uFF0C\u4E0D\u6309 3.15.3 \u6536\u7A84\uFF082026-10 review\xB7S-5 \u6838\u5B9E\u540E\u4FDD\u7559\uFF09\u3002
1126
+ .filter(function (r) { return r && r.config && r.config.access && r.config.access.type === 'zhipu-account'; })
1127
+ .map(function (r) { return String(r.providerId || ''); })
1128
+ .filter(Boolean);
1129
+ } catch (e) {
1130
+ // \u76EE\u5F55\u635F\u574F/\u4E0D\u53EF\u8BFB = identity/auth-source \u65E0\u6CD5\u4F9B\u7ED9\u7684\u771F\u56E0\uFF0C\u4E0D\u80FD\u9759\u9ED8\u8FD4\u56DE\uFF08\u5426\u5219
1131
+ // standalone \u6D3E\u53D1\u62A5\u300CProvider Registry \u4E2D\u4E0D\u5B58\u5728 Model\u300D\u65F6\u6392\u969C\u65E0\u5165\u53E3\uFF09
1132
+ process.stderr.write('[zcode-launcher] account metadata: builtin catalog unreadable (' + ((e && e.message) || String(e)) + ') - skipping account provider metadata\\n');
1133
+ return;
1134
+ }
1135
+ const added = [];
1136
+ const reconciled = [];
1137
+ // compare-and-skip \u57FA\u7EBF\uFF082026-10 review\xB7N-3\uFF09\uFF1A\u5168\u90E8 plan \u4E24\u952E\u7684\u8BFB\u65F6\u539F\u59CB\u503C\uFF08\u9996\u89C1
1138
+ // \u6355\u83B7\u2014\u2014\u540E\u7EED\u6539\u5199 creds \u4E0D\u5F71\u54CD\u57FA\u7EBF\uFF09\u3002\u5199\u56DE\u524D\u91CD\u8BFB\u78C1\u76D8\u9010\u952E\u6BD4\u5BF9\uFF0C\u68C0\u6D4B\u300C\u5FEB\u7167\u8BFB\u53D6
1139
+ // \u2192\u5199\u56DE\u300D\u7A97\u53E3\u5185\u7684 GUI/\u767B\u5F55\u5E76\u53D1\u5199\u5165\uFF0C\u9632\u9648\u65E7\u5FEB\u7167\u8986\u76D6\u6743\u5A01\u65B0\u503C\u3002
1140
+ const metaBaseline = Object.create(null);
1141
+ for (const pid of planIds) {
1142
+ const idKey = 'account-provider:' + pid + ':identity';
1143
+ const srcKey = 'account-provider:' + pid + ':auth-source';
1144
+ if (metaBaseline[idKey] === undefined) metaBaseline[idKey] = creds[idKey];
1145
+ if (metaBaseline[srcKey] === undefined) metaBaseline[srcKey] = creds[srcKey];
1146
+ // host \u6001 plan api-key \u952E\u540D\u6A21\u677F\uFF1Aaccount-provider:coding-plan:<pid>:account:<identity>:api-key
1147
+ const apiKeyPrefix = 'account-provider:coding-plan:' + pid + ':account:';
1148
+ const apiKeySuffix = ':api-key';
1149
+ const hasPlanApiKey = (id) => {
1150
+ if (!id) return false;
1151
+ return Boolean(creds[apiKeyPrefix + encodeURIComponent(id) + apiKeySuffix]);
1152
+ };
1153
+ let identity = typeof creds[idKey] === 'string' ? creds[idKey] : '';
1154
+ const authSource = typeof creds[srcKey] === 'string' ? creds[srcKey] : '';
1155
+ // \u6D3E\u751F\u8EAB\u4EFD\u6BCF\u6B21 spawn \u91CD\u7B97\uFF08\u4E0D\u8BFB\u65E2\u6709\u952E\uFF09\u3002\u591A plan api-key\uFF08\u65E7+\u65B0 account / \u8F6E\u6362
1156
+ // \u6B8B\u7559\uFF09\u65F6\u300CObject.keys \u9996\u4E2A\u547D\u4E2D\u300D\u4F1A\u6C38\u4E45\u6307\u5411\u9648\u65E7 account \u4E14 hasPlanApiKey \u6052\u771F\u3001
1157
+ // \u6C38\u4E0D\u81EA\u6108\uFF082026-10 review\xB7DG-R2-01\uFF09\u2014\u2014\u6D3E\u751F\u4F18\u5148\u7EA7\uFF1A
1158
+ // \u2460 project-key-location:v1:[origin,family,identity,...] \u952E\u5185\u5D4C identity
1159
+ // \uFF08ZCode \u767B\u5F55\u5199\u5165\u7684\u786E\u5B9A\u6027\u4FE1\u53F7\uFF1B\u952E\u540D\u5C3E\u6BB5 URL \u7F16\u7801 JSON \u6570\u7EC4\uFF0C\u7B2C 2/3 \u5143\u7D20
1160
+ // = family/identity\uFF0Cfamily \u4E0E pid \u524D\u7F00\u5339\u914D\u540C oauth \u5BB6\u65CF\u5224\u636E\uFF09\u5168\u4F53\u53BB\u91CD\u540E
1161
+ // \u552F\u4E00\u4E14\u8BE5 identity \u540D\u4E0B\u786E\u6709 plan api-key \u2192 \u7528\u5B83\uFF1B
1162
+ // \u2461 \u65E0\u2460\u4FE1\u53F7\u65F6\uFF0C\u8BE5 pid \u540D\u4E0B plan api-key \u952E\u7684 identity \u53BB\u91CD\u540E\u552F\u4E00 \u2192 \u7528\u5B83
1163
+ // \uFF08\u5355 account \u5E38\u6001\uFF09\uFF1B
1164
+ // \u2462 \u591A\u5019\u9009\u4E14\u65E0\u2460\u786E\u5B9A\u6027\u4FE1\u53F7 \u2192 \u4E0D\u731C\u6D4B\uFF1A\u4E0D\u6D3E\u751F\uFF08\u4FDD\u7559\u65E2\u6709 stored identity\uFF09\u5E76
1165
+ // log \u6B67\u4E49\u2014\u2014\u731C\u6D4B\u6539\u5199\u6BD4\u4FDD\u7559\u9648\u65E7\u503C\u66F4\u7CDF\uFF08\u9648\u65E7\u503C\u81F3\u5C11\u662F\u767B\u5F55\u6D41\u7A0B\u5199\u8FC7\u7684\uFF09\u3002
1166
+ let derivedIdentity = '';
1167
+ let ambiguousIdentity = false;
1168
+ const keyLocPrefix = 'project-key-location:v1:';
1169
+ const keyLocIds = [];
1170
+ for (const k of Object.keys(creds)) {
1171
+ if (k.indexOf(keyLocPrefix) !== 0) continue;
1172
+ try {
1173
+ const arr = JSON.parse(decodeURIComponent(k.slice(keyLocPrefix.length)));
1174
+ if (Array.isArray(arr) && typeof arr[1] === 'string' && typeof arr[2] === 'string'
1175
+ && pid.indexOf('account:' + arr[1]) === 0 && keyLocIds.indexOf(arr[2]) === -1) {
1176
+ keyLocIds.push(arr[2]);
1177
+ }
1178
+ } catch (e2) { /* \u5F62\u6001\u5916\u952E\uFF08\u635F\u574F/\u975E\u6570\u7EC4\uFF09\u4E0D\u6784\u6210\u786E\u5B9A\u6027\u4FE1\u53F7 */ }
1179
+ }
1180
+ if (keyLocIds.length === 1 && hasPlanApiKey(keyLocIds[0])) {
1181
+ derivedIdentity = keyLocIds[0];
1182
+ } else {
1183
+ const apiKeyIds = [];
1184
+ for (const k of Object.keys(creds)) {
1185
+ if (k.indexOf(apiKeyPrefix) !== 0 || k.slice(-apiKeySuffix.length) !== apiKeySuffix) continue;
1186
+ const mid = k.slice(apiKeyPrefix.length, k.length - apiKeySuffix.length);
1187
+ if (!mid) continue;
1188
+ let id; try { id = decodeURIComponent(mid); } catch (e2) { id = mid; }
1189
+ if (apiKeyIds.indexOf(id) === -1) apiKeyIds.push(id);
1190
+ }
1191
+ if (apiKeyIds.length === 1) derivedIdentity = apiKeyIds[0];
1192
+ else if (apiKeyIds.length > 1) ambiguousIdentity = true;
1193
+ }
1194
+ if (ambiguousIdentity) {
1195
+ process.stderr.write('[zcode-launcher] account metadata: multiple plan api-key identities for ' + pid + ', no deterministic signal - keeping stored identity\\n');
1196
+ }
1197
+ // oauth \u5BB6\u65CF\u51ED\u636E\u5B58\u5728\u6027\uFF1A\u626B oauth:<family>:access_token\uFF0Cprovider id \u4EE5
1198
+ // account:<family> \u5F00\u5934\u5373\u7ED1\u5B9A\u8BE5\u5BB6\u65CF\uFF08\u96F6\u5BB6\u65CF\u540D\u5199\u6B7B\uFF09\u3002
1199
+ let oauthBacked = false;
1200
+ const oauthPrefix = 'oauth:';
1201
+ const oauthSuffix = ':access_token';
1202
+ for (const k of Object.keys(creds)) {
1203
+ if (k.indexOf(oauthPrefix) !== 0 || k.slice(-oauthSuffix.length) !== oauthSuffix) continue;
1204
+ const fam = k.slice(oauthPrefix.length, k.length - oauthSuffix.length);
1205
+ if (!fam) continue;
1206
+ const token = creds[k];
1207
+ if (typeof token !== 'string' || token === '') continue;
1208
+ if (pid.indexOf('account:' + fam) === 0) { oauthBacked = true; break; }
1209
+ }
1210
+ // \u2460 \u8EAB\u4EFD\u5B64\u513F\u77EB\u6B63\uFF1A\u65E2\u6709\u975E\u7A7A\u8EAB\u4EFD\u662F\u6743\u5A01\u5199\u5165\uFF0C\u4F46\u53EA\u5728\u300C\u8BA4\u8BC1\u5F62\u6001\u8981\u6C42\u8EAB\u4EFD\u5BF9\u5E94 plan
1211
+ // api-key\u300D\u65F6\u5224\u5B9A\u5B64\u513F\u2014\u2014oauth \u5F62\u6001\u4E0B\u8EAB\u4EFD\u4E0D\u53C2\u4E0E\u51ED\u636E\u67E5\u627E\uFF08CLI \u767B\u5F55\u5199\u5165\u7684\u8EAB\u4EFD
1212
+ // \u53EF\u80FD\u6C38\u65E0 api-key\uFF09\uFF0C\u4E0D\u5F97\u7528\u6B8B\u7559\u952E\u540D\u8986\u5199\u3002\u5B64\u513F = \u65E0\u5BF9\u5E94 api-key \u4E14\u5F53\u524D\u53EF\u6D3E\u751F
1213
+ // \u2192 \u6539\u6210\u5F53\u524D\u8EAB\u4EFD\uFF08\u5426\u5219 manual \u67E5\u65E7\u8EAB\u4EFD\u51ED\u636E\u6052\u5931\u8D25\u3001\u6C38\u4E0D\u6536\u655B\uFF09\u3002\u65E5\u5FD7\u5728\u843D\u5E93
1214
+ // \u70B9\u53D1\uFF08\u65E0\u53EF\u7528 auth-source \u65F6 continue\uFF0C\u4E0D\u5F97\u7559\u4E0B\u201C\u5DF2\u77EB\u6B63\u201D\u800C\u672A\u5199\u76D8\u7684\u5047\u65E5\u5FD7\uFF09\u3002
1215
+ let identityCorrectedFrom = '';
1216
+ if (identity && !hasPlanApiKey(identity) && (authSource === 'manual' || !oauthBacked)
1217
+ && derivedIdentity && derivedIdentity !== identity) {
1218
+ identityCorrectedFrom = identity;
1219
+ identity = derivedIdentity;
1220
+ }
1221
+ if (!identity) identity = derivedIdentity;
1222
+ if (!identity) continue;
1223
+ // \u2461 auth-source \u6D3E\u751F + \u5B64\u513F\u77EB\u6B63\uFF1Aoauth \u9700\u5339\u914D\u5BB6\u65CF\u7684 access_token\uFF1Bmanual \u9700\u8BE5
1224
+ // \u8EAB\u4EFD\u540D\u4E0B\u7684 plan api-key\u3002\u65E2\u6709\u503C\u4E0E\u5F53\u524D\u4E8B\u5B9E\u4E00\u81F4\u65F6\u539F\u6837\u4FDD\u7559\uFF08GUI/\u767B\u5F55\u5199\u5165\u7684
1225
+ // manual \u5728 oauth \u540C\u65F6\u5B58\u5728\u65F6\u4ECD\u662F\u6743\u5A01\u2014\u2014\u66FE\u65E0\u5DEE\u522B\u8986\u5199\u5DEE\u5F02\u503C\uFF09\u3002
1226
+ const derivedAuthSource = oauthBacked ? 'oauth' : (hasPlanApiKey(identity) ? 'manual' : '');
1227
+ let nextAuthSource = authSource || derivedAuthSource;
1228
+ if (authSource === 'oauth' && !oauthBacked) nextAuthSource = derivedAuthSource;
1229
+ else if (authSource === 'manual' && !hasPlanApiKey(identity)) nextAuthSource = derivedAuthSource;
1230
+ if (!nextAuthSource) continue;
1231
+ // \u843D\u5E93\u5224\u5B9A\uFF1A\u7F3A\u5931\u6001\uFF08\u7A7A\u4E32/\u975E\u4E32\uFF09\u8BB0 provisioned\uFF0C\u975E\u7A7A\u65E7\u503C\u88AB\u77EB\u6B63\u8BB0 reconciled\u3002
1232
+ if (creds[idKey] !== identity) {
1233
+ if (identityCorrectedFrom) {
1234
+ reconciled.push(idKey + ' (' + identityCorrectedFrom + ' -> ' + identity + ')');
1235
+ } else if (typeof creds[idKey] !== 'string' || creds[idKey] === '') {
1236
+ added.push(idKey);
1237
+ }
1238
+ creds[idKey] = identity;
1239
+ }
1240
+ if (creds[srcKey] !== nextAuthSource) {
1241
+ if (typeof creds[srcKey] === 'string' && creds[srcKey] !== '') {
1242
+ reconciled.push(srcKey + ' (' + creds[srcKey] + ' -> ' + nextAuthSource + ')');
1243
+ } else added.push(srcKey);
1244
+ creds[srcKey] = nextAuthSource;
1245
+ }
1246
+ }
1247
+ if (added.length === 0 && reconciled.length === 0) return;
1248
+ // compare-and-skip\uFF082026-10 review\xB7N-3\uFF09\uFF1A\u65E0\u9501 RMW \u7684\u9648\u65E7\u8986\u76D6\u9632\u7EBF\u2014\u2014\u5199\u56DE\u524D\u91CD\u8BFB
1249
+ // \u78C1\u76D8\uFF0C\u4EFB\u4E00 plan \u4E24\u952E\u5F53\u524D\u503C \u2260 \u8BFB\u65F6\u57FA\u7EBF = \u7A97\u53E3\u5185 GUI/\u767B\u5F55\u5DF2\u5B8C\u6210\u6743\u5A01\u5199\u5165 \u2192 \u653E\u5F03
1250
+ // \u672C\u6B21\u5199\u5165\uFF08log \u8BF4\u660E\uFF0C\u4E0B\u6B21 spawn \u5E42\u7B49\u91CD\u7B97\uFF1B\u653E\u5F03\u540E\u7684\u6062\u590D = \u91CD\u65B0\u767B\u5F55/\u914D\u7F6E\u6216\u5220\u9664
1251
+ // \u8BE5\u952E\uFF0CADR-0143 \u5E76\u53D1\u8FB9\u754C\uFF09\u3002\u91CD\u8BFB/\u89E3\u6790\u5931\u8D25 = \u7A97\u53E3\u4E0D\u53EF\u5224\u5B9A\uFF0C\u540C\u6837\u4FDD\u5B88\u653E\u5F03\u3002
1252
+ try {
1253
+ const reread = JSON.parse(readOrig.call(fs, credPath, 'utf8'));
1254
+ if (!reread || typeof reread !== 'object' || Array.isArray(reread)) {
1255
+ throw new Error('credentials reread is not an object');
1256
+ }
1257
+ for (const mk of Object.keys(metaBaseline)) {
1258
+ if ((reread[mk] || '') !== (metaBaseline[mk] || '')) {
1259
+ throw new Error('concurrent write detected on ' + mk);
1260
+ }
1261
+ }
1262
+ } catch (skipErr) {
1263
+ process.stderr.write('[zcode-launcher] account metadata skipped (' + ((skipErr && skipErr.message) || String(skipErr)) + ') - retry on next spawn\\n');
1264
+ return;
1265
+ }
1266
+ const tmp = credPath + '.taiji-tmp-' + process.pid;
1267
+ // rename \u6362 inode\u2014\u2014tmp \u4E0D\u5E26 mode \u843D\u76D8\u4F1A\u628A GUI \u4FA7\u6536\u7D27\u8FC7\u7684\u6587\u4EF6\u6743\u9650\u9759\u9ED8\u653E\u5BBD\u4E3A
1268
+ // \u7F3A\u7701 umask \u503C\uFF0C\u5199\u524D\u8BFB\u65E2\u6709 mode \u968F\u5199\u4F20\u9012\uFF08stat \u5931\u8D25\u56DE\u9000 0600\uFF09\uFF1B\u5199/rename
1269
+ // \u5931\u8D25\u6E05\u7406 tmp\uFF0C\u4E0D\u5728\u7528\u6237\u51ED\u636E\u76EE\u5F55\u7559\u6B8B\u7247\u3002
1270
+ let writeMode = 0o600;
1271
+ try { writeMode = fs.statSync(credPath).mode & 0o777; } catch { /* \u7F3A\u7701 0600 */ }
1272
+ try {
1273
+ fs.writeFileSync(tmp, JSON.stringify(creds, null, 2), { mode: writeMode });
1274
+ fs.renameSync(tmp, credPath);
1275
+ } catch (err) {
1276
+ try { fs.unlinkSync(tmp); } catch { /* tmp \u672A\u751F\u6210\u6216\u5DF2 rename */ }
1277
+ throw err;
1278
+ }
1279
+ if (added.length > 0) process.stderr.write('[zcode-launcher] account metadata provisioned: ' + added.join(', ') + '\\n');
1280
+ if (reconciled.length > 0) process.stderr.write('[zcode-launcher] account metadata reconciled: ' + reconciled.join(', ') + '\\n');
1281
+ } catch (err) {
1282
+ process.stderr.write('[zcode-launcher] account metadata provisioning failed (non-blocking): ' + ((err && err.message) || String(err)) + '\\n');
1283
+ }
1284
+ }
1285
+ `;
1286
+
720
1287
  // src/appserver-launcher.ts
721
1288
  var ZCODE_APPSERVER_LAUNCHER_NAME = "appserver-launcher.cjs";
722
1289
  var APPSERVER_LAUNCHER_SOURCE = `'use strict';
@@ -737,7 +1304,7 @@ const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
737
1304
 
738
1305
  // \u5408\u5E76\u5F62\u6001\uFF1A\u771F\u5B9E cli config \u539F\u6837\uFF08model/plugins/mcp/subagents \u7B49 worker \u7EE7\u627F\u9762\u4E0D\u53D8\uFF09
739
1306
  // + v2 \u7684 provider \u5B57\u5178\u6CE8\u5165\uFF0C\u540C id \u65F6 v2 \u6761\u76EE\u6574\u6761\u4F18\u5148\u2014\u2014GUI \u76F4\u4F20 modelConfig \u65F6
740
- // v2 \u5373\u6743\u5A01\u6E90\uFF08\u8FDB\u7A0B\u5916\u7B49\u4EF7\u590D\u523B\uFF09\uFF1Bcli config \u4E0D\u5728 GUI \u7BA1\u7406\u9762\u3001\u53EF\u80FD\u6B8B\u7559\u5386\u53F2\u9A8C\u8BC1
1307
+ // v2 \u5373\u6743\u5A01\u6E90\uFF08\u8FDB\u7A0B\u5916\u7B49\u4EF7\u590D\u523B\uFF09\uFF1Bcli config \u4E0D\u5728 GUI \u7BA1\u7406\u4FA7\u3001\u53EF\u80FD\u6B8B\u7559\u5386\u53F2\u9A8C\u8BC1
741
1308
  // \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
742
1309
  // 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
743
1310
  // \u53EF\u7528\u6A21\u578B\uFF1Bplan \u5BB6\u65CF id \u5DF2\u4E0D\u53EF\u7528\uFF0C\u4E0D\u518D\u515C\u5E95\u4F2A\u9020\uFF09\u3002
@@ -766,12 +1333,16 @@ function injectedConfigText() {
766
1333
  const v2Providers = v2.provider && typeof v2.provider === 'object' ? v2.provider : {};
767
1334
  const hasKey = (entry) => entry && typeof entry === 'object'
768
1335
  && entry.options && typeof entry.options.apiKey === 'string' && entry.options.apiKey !== '';
769
- const injectable = {};
1336
+ // \u65E0\u539F\u578B\u5B57\u5178\uFF08DG-R2-02\uFF09\uFF1Aprovider id \u503C\u57DF\u542B '__proto__'/'toString' \u7B49\u5371\u9669\u952E
1337
+ //\uFF08runtime \u4FA7\u6709\u610F\u4EA7\u51FA\uFF0CS-17\uFF09\u2014\u2014\u666E\u901A\u5BF9\u8C61\u4E0A\u5BF9 __proto__ \u952E\u8D4B\u503C\u89E6\u53D1\u539F\u578B setter
1338
+ // \u9759\u9ED8\u4E22\u6761\u76EE\u3001\u8BFB toString \u952E\u843D\u5230\u539F\u578B\u65B9\u6CD5\u8BEF\u5224\u5DF2\u5B58\u5728\u3002Object.create(null) \u4F7F
1339
+ // \u952E\u8BFB\u5199\u5747\u843D\u5728 own property\u3002
1340
+ const injectable = Object.create(null);
770
1341
  for (const [id, entry] of Object.entries(v2Providers)) {
771
1342
  if (hasKey(entry)) injectable[id] = entry;
772
1343
  }
773
1344
  // 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
774
- // \u7528\uFF0C\u6CE8\u5165\u9762\u7EF4\u6301 v2-only \u73B0\u72B6\uFF1BproviderRules \u7F3A\u5931\u4E0D\u6784\u6210\u51ED\u636E\u9519\u8BEF\uFF09\u3002
1345
+ // \u7528\uFF0C\u6CE8\u5165\u70B9\u7EF4\u6301 v2-only \u73B0\u72B6\uFF1BproviderRules \u7F3A\u5931\u4E0D\u6784\u6210\u51ED\u636E\u9519\u8BEF\uFF09\u3002
775
1346
  try {
776
1347
  const pc = JSON.parse(readOrig(PROVIDER_CONFIG_PATH, 'utf8'));
777
1348
  const pcCfg = pc && typeof pc.config === 'object' && pc.config ? pc.config : {};
@@ -779,7 +1350,9 @@ function injectedConfigText() {
779
1350
  const rules = Array.isArray(pcr.providerRules) ? pcr.providerRules : [];
780
1351
  const mcr = typeof pcCfg.modelConfigRules === 'object' && pcCfg.modelConfigRules ? pcCfg.modelConfigRules : {};
781
1352
  const modelRules = Array.isArray(mcr.providerModelRules) ? mcr.providerModelRules : [];
782
- const modelMeta = {};
1353
+ // \u65E0\u539F\u578B\u5B57\u5178\uFF08DG-R2-02 \u540C\u65CF\uFF09\uFF1Aid \u4E3A 'constructor' \u7B49\u539F\u578B\u65B9\u6CD5\u540D\u65F6\u666E\u901A\u5BF9\u8C61\u8BFB\u53D6
1354
+ // \u843D\u5230\u539F\u578B Function\uFF0Cfor...of \u76F4\u63A5 TypeError \u88AB catch \u9759\u9ED8\u541E\u6389\u8BE5 rule \u7684\u5408\u6210
1355
+ const modelMeta = Object.create(null);
783
1356
  for (const mr of modelRules) {
784
1357
  if (!mr || typeof mr !== 'object' || typeof mr.providerId !== 'string' || typeof mr.modelId !== 'string') continue;
785
1358
  (modelMeta[mr.providerId] = modelMeta[mr.providerId] || []).push(mr);
@@ -790,8 +1363,10 @@ function injectedConfigText() {
790
1363
  const cfg = rule.config && typeof rule.config === 'object' ? rule.config : {};
791
1364
  const access = cfg.access && typeof cfg.access === 'object' ? cfg.access : {};
792
1365
  const api = cfg.api && typeof cfg.api === 'object' ? cfg.api : {};
793
- // 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
794
- if (!id || injectable[id] || realProviders[id]) continue;
1366
+ // 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\u3002
1367
+ // realProviders \u662F JSON.parse \u666E\u901A\u5BF9\u8C61\uFF08\u6709\u539F\u578B\uFF09\u2014\u2014id \u4E3A 'toString' \u7B49
1368
+ // \u539F\u578B\u65B9\u6CD5\u540D\u65F6\u76F4\u63A5\u4E0B\u6807\u8BFB\u53D6\u6052 truthy \u8BEF\u5224 real \u5DF2\u6709\uFF0C\u987B own-property \u68C0\u67E5
1369
+ if (!id || injectable[id] || Object.prototype.hasOwnProperty.call(realProviders, id)) continue;
795
1370
  // hasKey \u7EAA\u5F8B\u540C\u6B3E\uFF1A\u65E0 apiKey \u4E0D\u5408\u6210\uFF1B\u65E0 baseUrl\uFF08endpoint \u7531\u6A21\u677F\u63D0\u4F9B\u7684\u5F62\u6001\uFF09
796
1371
  // \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
797
1372
  if (typeof access.apiKey !== 'string' || access.apiKey === '') continue;
@@ -823,7 +1398,7 @@ function injectedConfigText() {
823
1398
  models: models,
824
1399
  };
825
1400
  }
826
- } catch { /* provider_config \u7F3A\u5931/\u635F\u574F \u2192 \u8865\u6CE8\u5165\u9762\u9759\u9ED8\u964D\u7EA7\uFF08v2 \u6CE8\u5165\u4E0D\u53D7\u5F71\u54CD\uFF09 */ }
1401
+ } catch { /* provider_config \u7F3A\u5931/\u635F\u574F \u2192 \u8865\u6CE8\u5165\u70B9\u9759\u9ED8\u964D\u7EA7\uFF08v2 \u6CE8\u5165\u4E0D\u53D7\u5F71\u54CD\uFF09 */ }
827
1402
  if (Object.keys(injectable).length === 0) return null;
828
1403
  const merged = { ...real };
829
1404
  merged.provider = { ...realProviders, ...injectable };
@@ -837,7 +1412,7 @@ function injectedConfigText() {
837
1412
  // [merge-fn-start]\uFF08\u5BF9\u8D26\u5355\u6D4B\u63D0\u53D6\u951A\u2014\u2014appserver-launcher.test.ts \u6309\u6807\u8BB0\u622A\u53D6\u672C\u51FD\u6570
838
1413
  // eval \u6267\u884C\uFF1Bpreparer.ts mergePersonalProviderConfig \u4E0E\u672C\u51FD\u6570\u540C\u89C4\u5219\u9501\u6B65\uFF0C\u6539\u4EFB\u4E00\u4FA7
839
1414
  // \u987B\u540C\u6B65\u53E6\u4E00\u4FA7\u5E76\u8DD1\u5BF9\u8D26\u5355\u6D4B\uFF09
840
- // merge(\u771F\u5B9E, \u526F\u672C)\u2014\u2014D3 \u6362\u8F68\u7248\u89C4\u5219\uFF1A
1415
+ // merge(\u771F\u5B9E, \u526F\u672C)\u2014\u2014D3 \u5207\u6362\u7248\u89C4\u5219\uFF1A
841
1416
  // - \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
842
1417
  // - \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
843
1418
  // \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
@@ -857,7 +1432,10 @@ function mergeProviderConfig(realObj, copyObj) {
857
1432
  };
858
1433
  const strArr = (v) => (Array.isArray(v) ? v.filter((s) => typeof s === 'string' && s.trim() !== '') : []);
859
1434
  const mergedRules = [];
860
- const seen = {};
1435
+ // \u65E0\u539F\u578B\u5B57\u5178\uFF08DG-R2-02\uFF09\uFF1AproviderId \u4E3A '__proto__'/'toString' \u7B49\u5371\u9669\u952E\u65F6\u666E\u901A\u5BF9\u8C61
1436
+ // \u7684 seen \u8BFB\u5199\u90FD\u4F1A\u649E\u539F\u578B\u94FE\uFF08__proto__ \u8D4B\u503C\u88AB setter \u541E / toString \u8BFB\u5230\u539F\u578B\u65B9\u6CD5
1437
+ // \u8BEF\u5224\u5DF2\u89C1 \u2192 \u526F\u672C\u72EC\u6709\u6761\u76EE\u88AB\u4E22\uFF0C\u4E0E TS \u4FA7 Set \u5B9E\u88C5\u5206\u6B67\uFF09\u3002Object.create(null) \u6D88\u9664\u3002
1438
+ const seen = Object.create(null);
861
1439
  for (const rule of rulesOf(realObj)) {
862
1440
  mergedRules.push(rule);
863
1441
  if (isRec(rule) && typeof rule.providerId === 'string' && rule.providerId !== '') seen[rule.providerId] = true;
@@ -884,7 +1462,7 @@ function mergeProviderConfig(realObj, copyObj) {
884
1462
  }
885
1463
  // [merge-fn-end]
886
1464
 
887
- // 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
1465
+ // D3 \u5207\u6362\u88C5\u8F7D\u901A\u9053\uFF1A\u547D\u4E2D\u771F\u5B9E provider_config.json \u7684\u8BFB\u53D6\u91CD\u5B9A\u5411\u4E3A merge(\u771F\u5B9E\u5B9E\u65F6
888
1466
  // \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
889
1467
  // \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
890
1468
  // \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
@@ -943,42 +1521,9 @@ function catalogPatchText(path) {
943
1521
  return result;
944
1522
  }
945
1523
 
946
- // [2026-10-13 account \u76F4\u901A\u2461] CLI bundle \u6E90\u7801\u5185\u5B58\u8865\u4E01\uFF1A\u5916\u90E8 spawn \u7684\u8D26\u53F7\u6761\u76EE\u6784\u5EFA
947
- // \u786C\u7F16\u7801 entitled:!1\uFF08YXe\uFF09\uFF0C\u6570\u636E\u9762\u6CE8\u5165\uFF08\u76EE\u5F55 entitled \u5B57\u6BB5\uFF09\u88AB\u5176\u65E0\u89C6\u2014\u2014\u6309\u7528\u6237\u88C1\u51B3
948
- // \u6539 zcode \u6E90\u7801\u7ED5\u8FC7\uFF1A\u62E6\u622A CLI bundle \u6E90\u7801\u8BFB\u53D6\uFF0C\u5185\u5B58\u66FF\u6362\u8BE5\u5B57\u9762\u91CF\u4E3A !0\uFF08ZCode.app
949
- // \u78C1\u76D8\u6587\u4EF6\u96F6\u89E6\u78B0\uFF1B\u951A\u4E32\u542B ]]:[] \u5C3E\u7F00\u552F\u4E00\u547D\u4E2D YXe \u6784\u9020\uFF0C\u53E6\u4E00\u5904\u540C\u540D\u6761\u4EF6\u903B\u8F91\u4E0D\u53D7\u5F71\u54CD\uFF09\u3002
950
- // \u951A\u4E0D\u547D\u4E2D\uFF08\u4E0A\u6E38\u6DF7\u6DC6\u5F62\u6001\u53D8\u5316\uFF09\u2192 \u539F\u6587\u900F\u51FA\uFF1A\u4EC5 account \u5BB6\u65CF\u7EE7\u7EED\u88AB\u62D2\uFF0C\u4E2A\u4EBA provider
951
- // \u4E0D\u53D7\u5F71\u54CD\u3002
952
- const __cliPatchCache = new Map();
953
- function patchedCliSource(path) {
954
- if (__cliPatchCache.has(path)) return __cliPatchCache.get(path);
955
- let result = null;
956
- try {
957
- const readOrig = fs.__origReadFileSync || fs.readFileSync;
958
- const src = readOrig(path, 'utf8');
959
- // \u7248\u672C\u9C81\u68D2\u951A\uFF082026-10-13 \u4FEE\u8BA2\uFF09\uFF1Aminified \u6807\u8BC6\u7B26\uFF08Uk/I3 \u7B49\uFF09\u968F zcode \u91CD\u65B0\u6253\u5305
960
- // \u6F02\u79FB\uFF0C\u5C5E\u6027\u540D\uFF08zcodeBuiltinProviders / zhipu-account / entitled\uFF09\u662F\u6570\u636E/\u5951\u7EA6
961
- // \u771F\u540D\u4E0D\u88AB\u6DF7\u6DC6\u2014\u2014\u4EE5\u5C5E\u6027\u540D\u5B9A\u4F4D + 600 \u5B57\u7B26\u7A97\u53E3\u5185\u628A\u8D26\u53F7\u6761\u76EE\u6784\u5EFA\u7684 entitled:!1
962
- // \u7FFB\u8F6C\u4E3A !0\u3002\u7A97\u53E3\u96F6\u547D\u4E2D = \u4E0A\u6E38\u5F62\u6001\u6F02\u79FB \u2192 \u539F\u6587\u900F\u51FA + stderr warn\uFF08\u6F02\u79FB\u53EF\u89C1\uFF0C
963
- // \u8FDB app-server stderr \u65E5\u5FD7\uFF09\uFF0C\u4E2A\u4EBA provider \u4E0D\u53D7\u5F71\u54CD\u3002
964
- const anchorIdx = src.indexOf('zcodeBuiltinProviders.entries()');
965
- if (anchorIdx >= 0) {
966
- const window = src.slice(anchorIdx, Math.min(src.length, anchorIdx + 600));
967
- if (window.indexOf('zhipu-account') >= 0 && window.indexOf('entitled:!1') >= 0) {
968
- result = src.slice(0, anchorIdx)
969
- + window.split('entitled:!1').join('entitled:!0')
970
- + src.slice(anchorIdx + 600);
971
- }
972
- }
973
- if (result === null) {
974
- process.stderr.write('[zcode-launcher] account bypass: CLI bundle anchor not found (zcode upstream shape drifted?) - account family stays gated, personal providers unaffected\\n');
975
- }
976
- } catch { result = null; }
977
- __cliPatchCache.set(path, result);
978
- return result;
979
- }
1524
+ ${CLI_PATCH_SECTION}
980
1525
 
981
- // \u5185\u5EFA provider \u914D\u7F6E\u5B9A\u4F4D\uFF08\u6F02\u79FB\u9762\u2461\uFF09\uFF1A3.12.x \u8D77\u914D\u7F6E\u6587\u4EF6\u632A\u4F4D + CLI \u4F9D\u8D56\u5BBF\u4E3B\u6CE8\u5165
1526
+ // \u5185\u5EFA provider \u914D\u7F6E\u5B9A\u4F4D\uFF08\u6F02\u79FB\u98CE\u9669\u2461\uFF09\uFF1A3.12.x \u8D77\u914D\u7F6E\u6587\u4EF6\u632A\u4F4D + CLI \u4F9D\u8D56\u5BBF\u4E3B\u6CE8\u5165
982
1527
  // ZCODE_BUILTIN_PROVIDER_CONFIG_FILE \u76F4\u63A5\u5B9A\u4F4D\uFF1BZCode \u684C\u9762 spawn \u94FE\u81EA\u5E26\u8BE5\u952E\uFF0C
983
1528
  // \u672C wrapper \u94FE\u9700\u81EA\u7ED9\u3002\u663E\u5F0F\u4F20\u5165\u4F18\u5148 \u2192 v2 runtime \u76EE\u5F55\u4E0B\u5E73\u53F0\u76EE\u5F55\uFF08\u7CBE\u786E
984
1529
  // <plat>-<arch> \u4F18\u5148\uFF0CRust arch \u53D8\u4F53\u5982 darwin-aarch64 \u5B57\u5178\u5E8F\u8DDF\u540E\uFF09\xD7 \u7248\u672C\u76EE\u5F55
@@ -1050,15 +1595,32 @@ if (!process.env.ZCODE_BUILTIN_PROVIDER_CONFIG_FILE) {
1050
1595
  }
1051
1596
  }
1052
1597
 
1598
+ ${ACCOUNT_METADATA_SECTION}
1599
+
1053
1600
  // \u5B89\u88C5\u95E8\uFF1A\u4EFB\u4E00 patch \u6E90\u53EF\u7528\u5373\u5B89\u88C5\u62E6\u622A\u5C42\uFF1B\u51B3\u7B56\u4E24\u6001\u90FD\u51FA\u58F0\uFF08\u88C5\u4E86\u54EA\u4E9B patch / \u4E3A\u4F55
1054
1601
  // \u8DF3\u8FC7\uFF09\u2014\u2014\u8865\u4E01\u5C42\u7684\u5931\u6548\u5F62\u6001\u662F\u9759\u9ED8\u7684\uFF08account \u76F4\u901A\u5931\u6548 = plan \u5BB6\u65CF\u62A5\u300C\u4E0D\u5B58\u5728
1055
1602
  // Model\u300D\u800C\u65E0\u4EFB\u4F55\u65E5\u5FD7\uFF09\uFF0C\u8DF3\u8FC7\u540C\u6837\u5FC5\u987B\u7559\u75D5\u3002
1056
1603
  const text = injectedConfigText();
1057
1604
  const catalogPatch = CATALOG_PATH !== null ? catalogPatchText(CATALOG_PATH) : null;
1058
- if (text !== null || catalogPatch !== null) {
1605
+ const cliPatchProbe = CLI_PATH ? patchedCliSource(CLI_PATH) : null;
1606
+ // \u4E09\u5904\u6539\u5199\u7684\u5E94\u7528\u6001\u7531 patchedCliSource \u53D1\u5E03\uFF08__cliPatchStatus\uFF09\u2014\u2014\u66FE\u4EE5\u4EA7\u7269\u5B50\u4E32\u5224\u5B9A\uFF1A
1607
+ // header-port \u5728\u672A\u6253\u8865\u4E01\u7684 3.15.3 bundle \u4E0A\u6052\u771F\uFF088 \u5904\u65E2\u6709\u540C\u540D\u5C5E\u6027\uFF09\u2192 \u95E8\u5BF9\u951A\u70B9
1608
+ // \u6F02\u79FB\u96F6\u68C0\u6D4B\u529B\uFF1Bstandalone \u540C\u7406\u7531\u6807\u5FD7\u9A71\u52A8\uFF08\u4E09\u5904\u5224\u5B9A\u5404\u81EA\u5177\u540D\uFF09\u3002cli-source-bypass
1609
+ // \u7684\u62EC\u53F7\u540E\u7F00\u628A\u4E09\u951A\u9010\u4E00\u5217\u51FA\uFF082026-10 review\xB7S-2\uFF09\uFF1Aentitled \u6807\u5FD7\u66FE\u53D1\u5E03\u4F46\u65E0\u6D88\u8D39\u65B9\uFF0C
1610
+ // \u8BE5\u951A\u5355\u72EC\u6F02\u79FB\u65F6\u516D\u9879\u77E9\u9635\u4F1A\u5168\u90E8 armed\u2014\u2014\u9010\u951A\u53EF\u89C1\u624D\u80FD\u5B9A\u4F4D\u6F02\u79FB\uFF08\u516D\u9879\u53E3\u5F84\u4E0D\u53D8\uFF09\u3002
1611
+ const cliPatchStatus = CLI_PATH ? __cliPatchStatus.get(CLI_PATH) : null;
1612
+ const anchorFlags = cliPatchStatus
1613
+ ? '(entitled=' + (cliPatchStatus.entitled ? 'on' : 'off')
1614
+ + ',standalone=' + (cliPatchStatus.standalone ? 'on' : 'off')
1615
+ + ',port=' + (cliPatchStatus.headerPort ? 'on' : 'off') + ')'
1616
+ : '';
1617
+ if (text !== null || catalogPatch !== null || cliPatchProbe !== null) {
1059
1618
  process.stderr.write('[zcode-launcher] \u8865\u4E01\u5C42\u5DF2\u5B89\u88C5: cli-config-inject=' + (text !== null ? 'on' : 'off')
1060
1619
  + ', catalog-entitled=' + (catalogPatch !== null ? 'on' : 'off')
1061
- + ', provider-merge=' + (PI_SYNCED_PATH ? 'armed' : 'off') + ', cli-source-bypass=armed\\n');
1620
+ + ', provider-merge=' + (PI_SYNCED_PATH ? 'armed' : 'off')
1621
+ + ', cli-source-bypass=' + (cliPatchProbe !== null ? 'armed' : 'off') + anchorFlags
1622
+ + ', standalone-account=' + (cliPatchStatus && cliPatchStatus.standalone ? 'armed' : 'off')
1623
+ + ', header-port=' + (cliPatchStatus && cliPatchStatus.headerPort ? 'armed' : 'off') + '\\n');
1062
1624
  // encoding \u5F52\u4E00\uFF08Node \u522B\u540D\u9762\uFF09\uFF1A'utf8'/'utf-8'/\u5927\u5C0F\u5199\u53D8\u4F53\u7EDF\u4E00\u6309 string \u8FD4\u56DE\u2014\u2014
1063
1625
  // \u771F\u5B9E bundle \u7684 config \u8BFB\u53D6\u6070\u7528 'utf-8' \u5F62\u6001\uFF0C\u4EC5\u5339\u914D 'utf8' \u4F1A\u9519\u56DE Buffer
1064
1626
  // \uFF08\u5F53\u4E0B\u6E38\u4E0D\u53EA JSON.parse \u800C\u505A\u5B57\u7B26\u4E32\u8FD0\u7B97\u65F6\u5373 TypeError\uFF09
@@ -1072,12 +1634,17 @@ if (text !== null || catalogPatch !== null) {
1072
1634
  return Buffer.from(value);
1073
1635
  };
1074
1636
  fs.__origReadFileSync = fs.readFileSync;
1637
+ // standalone \u8D26\u53F7\u5143\u6570\u636E\u952E\u4F9B\u7ED9\uFF08ADR-0143\uFF09\uFF1A\u4EC5\u5F53 standalone \u4E0E header-port \u4E24\u951A
1638
+ // \u5747\u5DF2\u6B66\u88C5\u65F6\u6267\u884C\uFF082026-10 review\xB7S-3\uFF09\u2014\u2014\u53EA\u6B66\u88C5 standalone \u65F6\u8BA4\u8BC1\u5934\u4ECD\u56DE\u843D\u5BBF\u4E3B
1639
+ // \u8BF7\u6C42\u7AEF\u53E3\uFF08\u65E0\u5BBF\u4E3B\u4EFB\u5E94\u7B54 = \u8D26\u53F7\u94FE\u4ECD\u4E0D\u53EF\u7528\uFF09\uFF0C\u6B64\u65F6\u5199\u7528\u6237\u5171\u4EAB credentials.json
1640
+ // \u65E0\u8FD0\u884C\u65F6\u6536\u76CA\u3001\u53EA\u589E\u98CE\u9669\uFF1B\u6B64\u5904\u8BFB\u6E90\u4ECD\u662F\u539F\u751F fs\uFF08readFileSync \u62E6\u622A\u5C1A\u672A\u5B89\u88C5\uFF09\u3002
1641
+ if (cliPatchStatus && cliPatchStatus.standalone && cliPatchStatus.headerPort) ensureAccountMetadata();
1075
1642
  fs.readFileSync = function (p, ...rest) {
1076
1643
  if (typeof p === 'string' && p === CONFIG_PATH) {
1077
1644
  const cur = injectedConfigText();
1078
1645
  if (cur !== null) return shape(rest, cur);
1079
1646
  }
1080
- // D3 \u6362\u8F68\uFF1ARegistry \u76F4\u8BFB\u771F\u5B9E provider_config.json \u2192 merge(\u771F\u5B9E, \u526F\u672C) \u89C6\u56FE
1647
+ // D3 \u5207\u6362\uFF1ARegistry \u76F4\u8BFB\u771F\u5B9E provider_config.json \u2192 merge(\u771F\u5B9E, \u526F\u672C) \u89C6\u56FE
1081
1648
  if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
1082
1649
  const cur = mergedProviderConfigText();
1083
1650
  if (cur !== null) return shape(rest, cur);
@@ -1134,8 +1701,8 @@ if (text !== null || catalogPatch !== null) {
1134
1701
 
1135
1702
  // existsSync \u62E6\u622A\uFF1A\u771F\u5B9E bundle \u7684\u7528\u6237 config \u8BFB\u53D6\uFF08loadFileConfig\uFF09\u4EE5 existsSync
1136
1703
  // \u4E3A\u77ED\u8DEF\u95E8\u2014\u2014\u6587\u4EF6\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u7A7A config \u4E14 readFileSync \u4E0D\u88AB\u8C03\u7528\uFF0CGUI-only
1137
- // \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
1138
- // D3 \u6362\u8F68\uFF1A\u771F\u5B9E provider_config.json \u7684\u5B58\u5728\u6027 = \u771F\u5B9E\u6216\u526F\u672C\u4EFB\u4E00\u5B58\u5728\u5373 true
1704
+ // \u767B\u5F55\u5BBF\u4E3B\uFF08cli/config.json \u4ECE\u672A\u88AB CLI \u4FA7\u5199\u8FC7\uFF09\u4E0A\u6CE8\u5165\u53EA\u6302\u5728\u8BFB\u4FA7 = \u4E0D\u53EF\u89C1\u3002
1705
+ // D3 \u5207\u6362\uFF1A\u771F\u5B9E provider_config.json \u7684\u5B58\u5728\u6027 = \u771F\u5B9E\u6216\u526F\u672C\u4EFB\u4E00\u5B58\u5728\u5373 true
1139
1706
  //\uFF08\u771F\u5B9E\u7F3A\u5931 + \u526F\u672C\u5B58\u5728\u65F6 Registry \u7684 existsSync \u95E8\u4E0D\u5F97\u62E6\u6389 merge \u89C6\u56FE\u8BFB\u53D6\uFF09
1140
1707
  fs.__origExistsSync = fs.existsSync;
1141
1708
  fs.existsSync = function (p) {
@@ -1294,7 +1861,7 @@ var AppServerConnection = class {
1294
1861
  killChainPromise;
1295
1862
  generation = 0;
1296
1863
  pushHandlers = /* @__PURE__ */ new Map();
1297
- /** [R4] 连接级崩溃通知面(onClose 订阅者集合;与 pushHandlers 同构的 refCount 形态)。 */
1864
+ /** [R4] 连接级崩溃通知侧(onClose 订阅者集合;与 pushHandlers 同构的 refCount 形态)。 */
1298
1865
  closeHandlers = /* @__PURE__ */ new Set();
1299
1866
  capturedProtocolInfo = null;
1300
1867
  constructor(opts) {
@@ -1314,7 +1881,7 @@ var AppServerConnection = class {
1314
1881
  get pid() {
1315
1882
  return this.child?.pid;
1316
1883
  }
1317
- /** 当前代是否有活进程(关闭原语与重建测试的观测面)。 */
1884
+ /** 当前代是否有活进程(关闭原语与重建测试的观测范围)。 */
1318
1885
  get alive() {
1319
1886
  return this.child !== null;
1320
1887
  }
@@ -1595,7 +2162,7 @@ var AppServerConnection = class {
1595
2162
  return false;
1596
2163
  }
1597
2164
  }
1598
- /** stderr 实时 append 落盘(懒打开 + 尺寸轮转 + 过期清理;失败静默——取证面不
2165
+ /** stderr 实时 append 落盘(懒打开 + 尺寸轮转 + 过期清理;失败静默——取证侧不
1599
2166
  * 能拖垮主通道)。 */
1600
2167
  appendStderrLog(chunk) {
1601
2168
  if (this.stderrStreamFailed) return;
@@ -1781,7 +2348,7 @@ var SessionChannel = class {
1781
2348
  /**
1782
2349
  * [P0-1 U5/D7] dispose 标志:dispose 收割后 closeSession 短路——收割形态下连接
1783
2350
  * 可能仍 alive(close 事件迟到,finalize 未跑、child 非 null),此时发 close
1784
- * request 会写死进程(请求挂到控制面超时)或触发惰性重建(凭空 spawn 无人使用的
2351
+ * request 会写死进程(请求挂到控制范围超时)或触发惰性重建(凭空 spawn 无人使用的
1785
2352
  * 进程,违背 dispose 防泄漏语义);进程随即被引擎杀链回收,会话驻留随之消亡。
1786
2353
  */
1787
2354
  disposed = false;
@@ -1805,10 +2372,10 @@ var SessionChannel = class {
1805
2372
  /**
1806
2373
  * [P0-1 U5/D7] dispose 前收割 + 退订:「退订 = 不会再有事件」在结构上蕴含「在途
1807
2374
  * turn 不应再等」——close 缺失/被吞没形态(onClose 收割主路径未触发)下,在途
1808
- * turn 于退订前经既有 failAllTurns 收敛为明确失败(设计 §3.4 退化路径闭合;
2375
+ * turn 于退订前经既有 failAllTurns 收敛为明确失败(设计 §3.4 退化路径完成;
1809
2376
  * race 窗口在引擎 shutdownRuntimeAndDisposeChannel,量级与 awaitConnFinalized
1810
2377
  * 同源 ZCODE_APPSERVER_HARVEST_GRACE_MS)。幂等:与 onClose 收割先到者赢
1811
- * (turn.fail 的 settled 守卫——已落定 turn 不改写),activeTurns 已空则 no-op。
2378
+ * (turn.fail 的 settled 检查——已落定 turn 不改写),activeTurns 已空则 no-op。
1812
2379
  * 不影响连接自身生命周期(R4)。
1813
2380
  */
1814
2381
  dispose() {
@@ -1880,7 +2447,7 @@ var SessionChannel = class {
1880
2447
  * 原样上抛(调用方决定降级形态——引擎侧 warn 后注入锚失效声明段继续执行,
1881
2448
  * run 不失败,[U3])。
1882
2449
  * 经 conn.request 惰性启动连接(resume 是 run 的**首个**请求——调用时点连接
1883
- * 可能尚未启动,与 readBestEffort 的「已死跳过」判据不同场景,不做 alive 守卫)。
2450
+ * 可能尚未启动,与 readBestEffort 的「已死跳过」判据不同场景,不做 alive 检查)。
1884
2451
  */
1885
2452
  async resumeSession(sessionId) {
1886
2453
  return this.conn.request("session/resume", { sessionId }, { timeoutMs: ZCODE_APPSERVER_TURN_READ_TIMEOUT_MS });
@@ -2029,7 +2596,7 @@ var SessionChannel = class {
2029
2596
  }
2030
2597
  /**
2031
2598
  * 收尾帧判定与吸收(A.2 ⑤ 两种形态:payload.response / stopReason+content 变体)。
2032
- * 命中任一形态则落 finalText/finalUsage 并以 final-frame 宽松终态收口,返回 true。
2599
+ * 命中任一形态则落 finalText/finalUsage 并以 final-frame 宽松终态收尾,返回 true。
2033
2600
  */
2034
2601
  applyFinalFrame(turn, payload) {
2035
2602
  if (typeof payload.response === "string" && payload.response !== "") {
@@ -2106,7 +2673,7 @@ var SessionChannel = class {
2106
2673
  * - "interrupted":用户中断形态,debug(stderr 兜底对 debug no-op——对齐
2107
2674
  * SDK logger CONSOLE_SINK 语义,host/log 反向请求侧仍可观测);
2108
2675
  * - 失败类(isFailedTerminalStatus,与引擎失败分流同口径)与 unknown/未识别
2109
- * status:保守 warn(原样 status 已写入文案)——假成功识破的防御面,理论
2676
+ * status:保守 warn(原样 status 已写入文案)——假成功识破的防御机制,理论
2110
2677
  * 不可达但保留,宁可误报不静默。
2111
2678
  */
2112
2679
  logLateTerminal(turn, status) {
@@ -2147,7 +2714,7 @@ var SessionChannel = class {
2147
2714
  }
2148
2715
  }
2149
2716
  }
2150
- /** 终态后 read(A.2 ⑥)。失败/超时不抛——降级链由 runTurn 收口(read 只兜底不致命)。
2717
+ /** 终态后 read(A.2 ⑥)。失败/超时不抛——降级链由 runTurn 收尾(read 只兜底不致命)。
2151
2718
  * 连接已死时跳过(与 closeSession 同判——对死连接发请求会凭空重建进程)。 */
2152
2719
  async readBestEffort(sessionId) {
2153
2720
  if (!this.conn.alive) return void 0;
@@ -2302,7 +2869,7 @@ function sweepExpiredZcodeSessions(dbPath, opts = {}) {
2302
2869
  return { swept, keptActive };
2303
2870
  } catch (err) {
2304
2871
  logger3.warn(
2305
- `[zcode-ttl] sweep \u5931\u8D25\uFF08\u8F85\u52A9\u8D44\u6E90\u9762\uFF0C\u4E0D\u5F71\u54CD run \u4E3B\u94FE\u8DEF\uFF1B\u4E0B\u4E2A\u8282\u6D41\u7A97\u91CD\u8BD5\uFF09: ${err instanceof Error ? err.message : String(err)}`,
2872
+ `[zcode-ttl] sweep \u5931\u8D25\uFF08\u8F85\u52A9\u8D44\u6E90\u4FA7\uFF0C\u4E0D\u5F71\u54CD run \u4E3B\u94FE\u8DEF\uFF1B\u4E0B\u4E2A\u8282\u6D41\u7A97\u91CD\u8BD5\uFF09: ${err instanceof Error ? err.message : String(err)}`,
2306
2873
  { dbPath }
2307
2874
  );
2308
2875
  return noOp;
@@ -2380,7 +2947,7 @@ var ZcodeEngine = class {
2380
2947
  permissionMode: "native",
2381
2948
  // [D3-④] 无 turn_end 语义,轮数上限不可兑现(预检 gate 据此同步拒绝)
2382
2949
  maxTurns: false,
2383
- // [subagent-model-switch] zcode 引擎不在模型切换设计范围(协议面引擎中立预留,
2950
+ // [subagent-model-switch] zcode 引擎不在模型切换设计范围(协议范围引擎中立预留,
2384
2951
  // 后续另立项接入)——setModel 通路未接通,unsupported 如实声明
2385
2952
  setModel: "unsupported"
2386
2953
  };
@@ -2448,7 +3015,7 @@ var ZcodeEngine = class {
2448
3015
  * 常驻路径主编排:模型解析(v2 单源校验)→ 惰性连接 + runTurn(事件时序前移:
2449
3016
  * text_delta 流式、终态后 message_end/turn_end)→ schema 仿真重试 → outcome/handle。
2450
3017
  * onHandleReady 在 create 应答后(§3.4 不变量 3;原 onPoolResolved prepare 期
2451
- * 声明已随 [池抽象降级 2026-09-13] poolKey 协议面退役删除)。
3018
+ * 声明已随 [池抽象降级 2026-09-13] poolKey 协议范围退役删除)。
2452
3019
  */
2453
3020
  async runViaAppServer(task, ctx) {
2454
3021
  const startedAt = Date.now();
@@ -2468,7 +3035,7 @@ var ZcodeEngine = class {
2468
3035
  const outcome = this.finalizeOutcome(task, ctx, final, usageAcc, startedAt);
2469
3036
  return { handle: this.appServerHandle(outcome), outcome };
2470
3037
  }
2471
- /** pre-aborted 短路收口:合成中止 outcome + 'shared' 锚定 handle。 */
3038
+ /** pre-aborted 短路收尾:合成中止 outcome + 'shared' 锚定 handle。 */
2472
3039
  abortedAppServerRun(task, ctx, startedAt) {
2473
3040
  const outcome = this.finalizeOutcome(
2474
3041
  task,
@@ -2488,11 +3055,11 @@ var ZcodeEngine = class {
2488
3055
  * 新建会话)。重试轮 prompt 用 basePrompt 原样重跑(失败形态非 schema),文案补
2489
3056
  * 「已自动重试一次」句(retried 标记仅对真实发生的重试生效)。
2490
3057
  *
2491
- * 两次重试一次封顶各自独立(D6 被否①:多次重试/指数退避不做——重跑一轮=整任务
3058
+ * 两次重试一次封顶各自独立(D6 不采用①:多次重试/指数退避不做——重跑一轮=整任务
2492
3059
  * 重算,一次封顶)。组合序:瞬时重试在前、schema 重试在后——瞬时重试轮 parsed 且
2493
3060
  * 校验失败时仍进 schema 重试(末次 attempt 语义,schema 重试编排保持现状不动)。
2494
3061
  *
2495
- * 重试轮是独立会话的独立 LLM 调用:token 计入 outcome.usage 总量;事件面
3062
+ * 重试轮是独立会话的独立 LLM 调用:token 计入 outcome.usage 总量;事件范围
2496
3063
  * text_delta 按实际流出(含失败轮——journal 记录真实流水),message_end/turn_end
2497
3064
  * 只在最终轮终态后合成(不变量 2/5)。
2498
3065
  */
@@ -2539,7 +3106,7 @@ var ZcodeEngine = class {
2539
3106
  }
2540
3107
  /**
2541
3108
  * 单轮常驻执行:runTurn 组合面 + D3 abort 链 + 事件前移(text_delta 实时流出;
2542
- * 终态数据经 read 兜底收口后才 resolve——不变量 1/2)。
3109
+ * 终态数据经 read 兜底收尾后才 resolve——不变量 1/2)。
2543
3110
  *
2544
3111
  * @param opts retried:瞬时重试轮标记——失败文案补「已自动重试一次」句(F-1/F-4)。
2545
3112
  */
@@ -2562,7 +3129,7 @@ var ZcodeEngine = class {
2562
3129
  // 等,真机探针实证每 ~1s 一帧)→ activity 事件(零载荷纯活性信号——宿主无进展
2563
3130
  // 守护对任何事件类型刷新;reducer no-op、不落 journal)。zcode 引擎声明
2564
3131
  // conversation:"cold"(续聊 = session-store 冷恢复重建 + 新 run + resume 锚点,
2565
- // 无热 steering/chat 域接线),run 域是唯一发射面。
3132
+ // 无热 steering/chat 域接线),run 域是唯一发射点。
2566
3133
  onActivity: () => ctx.onEvent?.({ type: "activity" }),
2567
3134
  onSessionCreated: (sessionId) => {
2568
3135
  currentSessionId = sessionId;
@@ -2599,12 +3166,12 @@ var ZcodeEngine = class {
2599
3166
  }
2600
3167
  /**
2601
3168
  * [attemptAppServerTurn 拆分] 失败分流(catch 半边):
2602
- * - signal 已 aborted → 中止终态收口;
3169
+ * - signal 已 aborted → 中止终态收尾;
2603
3170
  * - [P0-1 U4] 连接崩溃收割形态(failAllTurns 的错误,D6 可重试形态)判据:
2604
- * 非 RPC error(服务端无明确应答——有应答即精确错误归类,非瞬时崩溃面)且
3171
+ * 非 RPC error(服务端无明确应答——有应答即精确错误归类,非瞬时崩溃)且
2605
3172
  * conn 不存活。时序可靠性:catch 时刻紧随 onClose 收割,连接重建仅由
2606
3173
  * conn.request 惰性触发——本链路中 runTurn finally 的 closeSession 对死连接
2607
- * 短路(channel 侧 !alive 守卫)、stop 只属 abort 链(已被 signal.aborted
3174
+ * 短路(channel 侧 !alive 检查)、stop 只属 abort 链(已被 signal.aborted
2608
3175
  * 短路)——此刻无 request 可重建,判据可靠;
2609
3176
  * - 其余 → 精确错误终态。
2610
3177
  */
@@ -2640,7 +3207,7 @@ var ZcodeEngine = class {
2640
3207
  * D3 abort 链执行体(用户取消入口,fire-and-forget——与 turn promise 并行推进):
2641
3208
  * stop 帧(超时 ZCODE_APPSERVER_STOP_TIMEOUT_MS)→ grace 窗口内 turn 落定即止
2642
3209
  * (不杀共享进程)→ 超窗 killChain(conn.shutdown 全序:SIGTERM→grace→SIGKILL)。
2643
- * turn 的最终落定由 attempt 主路径 await 收口,本链不直接产出终态。abort 与 create
3210
+ * turn 的最终落定由 attempt 主路径 await 收尾,本链不直接产出终态。abort 与 create
2644
3211
  * 竞态(signal 先到、session 未建立):等会话建立(带上限)再发 stop——否则 stop
2645
3212
  * 永远发不出,直接连坐杀共享进程。
2646
3213
  */
@@ -2689,7 +3256,7 @@ var ZcodeEngine = class {
2689
3256
  * workspace.workspacePath 按任务传递——D10 基线不预设任务级进程 cwd)。
2690
3257
  * spawn 经 fs 拦截 wrapper(appserver-launcher:cli config 读取重定向为
2691
3258
  * 「真实文件 + v2 provider 注入」——CLI 形态 app-server 在共享宿主 HOME 下的
2692
- * 唯一凭据供数通路,机制与漂移面见该文件头注)。
3259
+ * 唯一凭据供数通路,机制与漂移风险见该文件头注)。
2693
3260
  */
2694
3261
  ensureAppServerRuntime() {
2695
3262
  if (this.appserverRuntime !== void 0) return this.appserverRuntime;
@@ -2738,7 +3305,7 @@ var ZcodeEngine = class {
2738
3305
  * [P0-1 U5/D7] grace race 输掉(close 迟到/永不到达——stdio 被孙进程持有排空不
2739
3306
  * 尽等病态形态)时,channel.dispose() 内置的 dispose 收割(failAllTurns 先于退订,
2740
3307
  * SessionChannel.dispose)兜底在途 turn——在途 turn 收敛为「grace 窗口内明确失败」
2741
- * (设计 §3.4 退化路径闭合);race 窗口与 awaitConnFinalized 同源同量级
3308
+ * (设计 §3.4 退化路径完成);race 窗口与 awaitConnFinalized 同源同量级
2742
3309
  * (ZCODE_APPSERVER_HARVEST_GRACE_MS)。正常 close 先到时 onClose 收割先行,
2743
3310
  * dispose 收割幂等 no-op(零回归)。
2744
3311
  */
@@ -2754,10 +3321,10 @@ var ZcodeEngine = class {
2754
3321
  rt.channel.dispose();
2755
3322
  }
2756
3323
  /**
2757
- * [R1 D6 主体] 引擎停机面:①fire 全部在途会话的 session/close 帧(不等待
3324
+ * [R1 D6 主体] 引擎停机路径:①fire 全部在途会话的 session/close 帧(不等待
2758
3325
  * 应答——D6① 顺序规定:close 帧必须先于 SIGTERM,否则对面来不及处理即被杀)→
2759
- * ②同步 SIGTERM(conn.shutdown 调用内 killChain 前缀同步执行——同步面在返回
2760
- * Promise 前完成)→ ③grace → SIGKILL(异步面,Promise resolve 于进程退出)。
3326
+ * ②同步 SIGTERM(conn.shutdown 调用内 killChain 前缀同步执行——同步部分在返回
3327
+ * Promise 前完成)→ ③grace → SIGKILL(异步侧,Promise resolve 于进程退出)。
2761
3328
  * 幂等:运行时字段取走即置空,二次调用零副作用;dispose 后首个 run 经
2762
3329
  * ensureAppServerRuntime 自动重建(与崩溃重建同一代码路径,不变量 4)。
2763
3330
  */
@@ -2796,7 +3363,7 @@ var ZcodeEngine = class {
2796
3363
  /** abort 合成终态:exitCode=null(record 正常收尾,不留僵尸)。 */
2797
3364
  applyAbortedOutcome(outcome, task, ctx, final, emit) {
2798
3365
  outcome.exitCode = null;
2799
- outcome.error = isHostTimeoutAbort(ctx) ? synthesizeTimeoutOutcome(task, final.output.stdoutText, ZCODE_ENGINE_ID).error ?? engineTimeoutDetail(final.output.stdoutText) : final.abortMessage ?? `engine_run_failed: zcode \u4EFB\u52A1\u88AB\u4E2D\u6B62\uFF08app-server abort \u94FE\u6536\u53E3\uFF0C\u5BBF\u4E3B\u5408\u6210\u7EC8\u6001\uFF09\u3002\u8F93\u51FA\u5C3E\u90E8: ${final.output.stdoutText.slice(-ZCODE_ERROR_TAIL_CHARS)}`;
3366
+ outcome.error = isHostTimeoutAbort(ctx) ? synthesizeTimeoutOutcome(task, final.output.stdoutText, ZCODE_ENGINE_ID).error ?? engineTimeoutDetail(final.output.stdoutText) : final.abortMessage ?? `engine_run_failed: zcode \u4EFB\u52A1\u88AB\u4E2D\u6B62\uFF08app-server abort \u94FE\u6536\u5C3E\uFF0C\u5BBF\u4E3B\u5408\u6210\u7EC8\u6001\uFF09\u3002\u8F93\u51FA\u5C3E\u90E8: ${final.output.stdoutText.slice(-ZCODE_ERROR_TAIL_CHARS)}`;
2800
3367
  emit({ type: "error", message: outcome.error });
2801
3368
  }
2802
3369
  /**
@@ -2842,6 +3409,17 @@ var ZcodeEngine = class {
2842
3409
  listModels() {
2843
3410
  return listZcodeModels(this.deps.sources);
2844
3411
  }
3412
+ /**
3413
+ * [engine-ref-translation D1] 派发期模型 ref 翻译(EnginePort 可选成员实装):
3414
+ * pi 词汇 ref → zcode 原生 ref(zai-coding-cn/* → account:bigmodel-individual-*
3415
+ * 大小写归一,2026-10-16 用户裁决(证据驱动修正目标家族)),其余透传。编排层在 record stamp 前调用——
3416
+ * record/上报侧呈现实际发给引擎的 ref;翻译失败抛错 = 显式失败(不静默回落)。
3417
+ * 幂等:翻译产物(account:/个人 id)再入恒等,引擎内 resolveZcodeModelRef 的
3418
+ * 同名翻译分支零冲突。
3419
+ */
3420
+ translateModelRef(modelRef) {
3421
+ return translatePiModelRefToZcode(modelRef, this.deps.sources);
3422
+ }
2845
3423
  /** 模型 reasoning 值域缓存(目录 modelRules 值域;per-modelRef 记忆化——
2846
3424
  * 目录文件在引擎进程生命周期内视为静态,重复 run 不重读)。 */
2847
3425
  reasoningMemo = /* @__PURE__ */ new Map();
@@ -2873,9 +3451,9 @@ var ZcodeEngine = class {
2873
3451
  * 权威,无双实现)。校验失败原样抛 ZcodePrepareError,由编排层
2874
3452
  * (engine/model-validation.ts)包装成「引擎与模型不配套」文案。
2875
3453
  *
2876
- * [R4/D6-②] 缺席语义:本实现是进程内形态 + 协议诊断面(宿主 cli 形态消费的是
3454
+ * [R4/D6-②] 缺席语义:本实现是进程内形态 + 协议诊断范围(宿主 cli 形态消费的是
2877
3455
  * RemoteEngine 的 manifest 本地判定,不经本方法——SDK protocol methods.ts 明示
2878
- * validateModel 为诊断面)。缺席 modelRef 时返回空串 canonical(= create 帧省略
3456
+ * validateModel 为诊断范围)。缺席 modelRef 时返回空串 canonical(= create 帧省略
2879
3457
  * model 键、CLI 自身缺省解析——2026-09-29 account 体系迁移后 plan 家族兜底 id
2880
3458
  * 已不可用;record 留痕侧按 R4/D6-② 空串归一为「用户未指定」条件留空)。帧应答
2881
3459
  * 形态维持 {canonicalRef: string}(SDK port-contract 契约必填——「帧字段缺席」
@@ -2892,7 +3470,7 @@ var ZcodeEngine = class {
2892
3470
  * (zcodeSessionDbPath(engineDataDir),tier1 白名单集合见方法体——宿主路径仅
2893
3471
  * 「共享 HOME 时代」存量兼容);旧 records(池时代)的相对路径仍按池目录锚定
2894
3472
  * 解析(read 兼容旧数据,池目录不存在时自然落②级 journal 降级)。[池抽象降级
2895
- * 2026-09-13] 锚定 key 用常量 SHARED_POOL_KEY 承载——协议面 poolKey 已删,池
3473
+ * 2026-09-13] 锚定 key 用常量 SHARED_POOL_KEY 承载——协议范围 poolKey 已删,池
2896
3474
  * 时代真实池 key 不再随 handle 传输;若旧 record 的池目录恰为 shared 布局则①级
2897
3475
  * 仍可达,其余池 key 的旧 record 直接走②级 journal 降级(30 天 TTL 同尺度衰减,
2898
3476
  * 行为安全)。
@@ -2989,8 +3567,8 @@ var ZcodeEngine = class {
2989
3567
  * [U6 / §3.2.6 要点 3] resume 锚 → 历史前缀(interact-resume 的读半段)。
2990
3568
  *
2991
3569
  * 无锚 / 非 zcode 锚形态 → undefined(行为不变)。读通道失败(会话失效 / 控制
2992
- * 面错误)= 锚真失效的权威信号——宿主侧库投影预检查已退役(app-server 落库滞后
2993
- * 于 create 应答,分钟级窗 + 部分行永不落库,预检查系统性误判;resume 走
3570
+ * 面错误)= 锚真失效的权威信号——宿主侧库派生视图预检查已退役(app-server 写盘滞后
3571
+ * 于 create 应答,分钟级窗 + 部分行永不写盘,预检查系统性误判;resume 走
2994
3572
  * app-server resident 内存态才是真实活性判据),因此此处不再静默降级为无前缀
2995
3573
  * 裸跑,而是返回锚失效声明段:让模型知情「延续但无历史」,基于最新消息独立
2996
3574
  * 续推,而非在缺上下文时臆测连续性。用户消息照常执行,不炸轮。
@@ -3084,7 +3662,7 @@ function stopTimeoutMs() {
3084
3662
  return resolveAppserverTimingMs(
3085
3663
  ZCODE_APPSERVER_STOP_TIMEOUT_ENV,
3086
3664
  ZCODE_APPSERVER_STOP_TIMEOUT_MS,
3087
- "stop \u63A7\u5236\u9762\u8D85\u65F6"
3665
+ "stop \u63A7\u5236\u8303\u56F4\u8D85\u65F6"
3088
3666
  );
3089
3667
  }
3090
3668
  function abortGraceMs() {
@@ -3405,10 +3983,10 @@ var EngineProtocolServer = class {
3405
3983
  writeRunEvent(this.write, this.activeRuns, runId, event);
3406
3984
  }
3407
3985
  /**
3408
- * 发反向请求并等应答(帧④必须应答)。计时面登记:发出 → clock.started;收到
3986
+ * 发反向请求并等应答(帧④必须应答)。计时侧登记:发出 → clock.started;收到
3409
3987
  * ack 形态应答 → clock.acked(两阶段第一段,等待不计超时);终结 → clock.settled。
3410
- * 应答超时兜底 reject——数据面通道(host/log 等)core 10s 应答,reject 由调用方
3411
- * 吞掉留痕(数据面丢失不拖死主链路)。
3988
+ * 应答超时兜底 reject——数据范围通道(host/log 等)core 10s 应答,reject 由调用方
3989
+ * 吞掉留痕(数据范围丢失不拖死主链路)。
3412
3990
  */
3413
3991
  /**
3414
3992
  * fire-and-forget 反向请求(`void this.reverseRequestInternal(...)` 形态)的
@@ -3423,7 +4001,7 @@ var EngineProtocolServer = class {
3423
4001
  });
3424
4002
  };
3425
4003
  }
3426
- /** 反向请求发送(公开面:main.ts 的 host/log 桥接消费;内部 run 通道同路)。 */
4004
+ /** 反向请求发送(对外公开:main.ts 的 host/log 桥接消费;内部 run 通道同路)。 */
3427
4005
  reverseRequest(method, params) {
3428
4006
  return this.reverseRequestInternal(method, params);
3429
4007
  }
@@ -3440,7 +4018,7 @@ var EngineProtocolServer = class {
3440
4018
  params
3441
4019
  );
3442
4020
  }
3443
- /** 反向请求应答落位(ack 两阶段:{ack:true}/{unsupported:true}/{ok:true} 均先 ack 计时面)。 */
4021
+ /** 反向请求应答落位(ack 两阶段:{ack:true}/{unsupported:true}/{ok:true} 均先 ack 计时侧)。 */
3444
4022
  settleReverse(id, frame) {
3445
4023
  const pending = this.reversePending.get(String(id));
3446
4024
  if (pending === void 0) return;