@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/index.cjs CHANGED
@@ -46,7 +46,7 @@ __export(src_exports, {
46
46
  module.exports = __toCommonJS(src_exports);
47
47
 
48
48
  // src/server.ts
49
- var import_subagent_engine_sdk14 = require("@zhushanwen/subagent-engine-sdk");
49
+ var import_subagent_engine_sdk15 = require("@zhushanwen/subagent-engine-sdk");
50
50
 
51
51
  // src/constants.ts
52
52
  var ZCODE_ENGINE_ID = "zcode";
@@ -82,13 +82,13 @@ var ZCODE_RESUME_CHARS_PER_TOKEN = 4;
82
82
  var ZCODE_SESSION_SWEEP_DEFER_MS = 50;
83
83
 
84
84
  // src/registration.ts
85
- var import_subagent_engine_sdk12 = require("@zhushanwen/subagent-engine-sdk");
85
+ var import_subagent_engine_sdk13 = require("@zhushanwen/subagent-engine-sdk");
86
86
 
87
87
  // src/zcode-engine.ts
88
88
  var fs6 = __toESM(require("fs"), 1);
89
89
  var path4 = __toESM(require("path"), 1);
90
- var import_subagent_engine_sdk10 = require("@zhushanwen/subagent-engine-sdk");
91
90
  var import_subagent_engine_sdk11 = require("@zhushanwen/subagent-engine-sdk");
91
+ var import_subagent_engine_sdk12 = require("@zhushanwen/subagent-engine-sdk");
92
92
 
93
93
  // src/journal-io.ts
94
94
  var import_subagent_engine_sdk = require("@zhushanwen/subagent-engine-sdk");
@@ -159,6 +159,7 @@ function synthesizeCoarseEvents(response, usage) {
159
159
  var fs = __toESM(require("fs"), 1);
160
160
  var os2 = __toESM(require("os"), 1);
161
161
  var path2 = __toESM(require("path"), 1);
162
+ var import_subagent_engine_sdk4 = require("@zhushanwen/subagent-engine-sdk");
162
163
  var ZcodePrepareError = class extends Error {
163
164
  code;
164
165
  constructor(code, message) {
@@ -167,35 +168,81 @@ var ZcodePrepareError = class extends Error {
167
168
  this.code = code;
168
169
  }
169
170
  };
171
+ 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";
170
172
  function isRecord(v) {
171
173
  return typeof v === "object" && v !== null && !Array.isArray(v);
172
174
  }
173
175
  function strArray(v) {
174
176
  return Array.isArray(v) ? v.filter((m) => typeof m === "string" && m.trim() !== "") : [];
175
177
  }
176
- function readSourceConfig(absPath) {
177
- const empty = { providers: /* @__PURE__ */ new Map(), order: [] };
178
+ function readSourceJsonOrUndefined(absPath) {
178
179
  let raw;
179
180
  try {
180
181
  raw = fs.readFileSync(absPath, "utf8");
181
182
  } catch {
182
- return empty;
183
+ return void 0;
183
184
  }
184
- let parsed;
185
185
  try {
186
- parsed = JSON.parse(raw);
186
+ return JSON.parse(raw);
187
187
  } catch {
188
- return empty;
189
- }
190
- if (!isRecord(parsed)) return empty;
191
- const rules = parsed["config"]?.["providerConfigRules"];
192
- const providerRules = !isRecord(rules) ? void 0 : rules["providerRules"];
193
- const orderSrc = parsed["config"]?.["providerOrder"];
194
- const conf = { providers: /* @__PURE__ */ new Map(), order: strArray(orderSrc) };
195
- if (!Array.isArray(providerRules)) return conf;
196
- collectProviderRules(providerRules, conf);
188
+ return void 0;
189
+ }
190
+ }
191
+ function extractSourceConfig(parsed) {
192
+ const conf = { providers: /* @__PURE__ */ new Map(), order: [] };
193
+ if (!isRecord(parsed)) return conf;
194
+ const config = parsed["config"];
195
+ if (!isRecord(config)) return conf;
196
+ conf.order = strArray(config["providerOrder"]);
197
+ const rules = config["providerConfigRules"];
198
+ const providerRules = isRecord(rules) ? rules["providerRules"] : void 0;
199
+ if (Array.isArray(providerRules)) collectProviderRules(providerRules, conf);
197
200
  return conf;
198
201
  }
202
+ function readSourceConfig(absPath) {
203
+ return extractSourceConfig(readSourceJsonOrUndefined(absPath));
204
+ }
205
+ function mergePersonalProviderConfig(realObj, copyObj) {
206
+ if (!isRecord(copyObj)) return realObj;
207
+ if (!isRecord(realObj)) return copyObj;
208
+ const cfgOf = (obj) => isRecord(obj["config"]) ? obj["config"] : {};
209
+ const rulesOf = (obj) => {
210
+ const pcr = cfgOf(obj)["providerConfigRules"];
211
+ const rules = isRecord(pcr) ? pcr["providerRules"] : void 0;
212
+ return Array.isArray(rules) ? rules : [];
213
+ };
214
+ const mergedRules = [];
215
+ const seen = /* @__PURE__ */ new Set();
216
+ for (const rule of rulesOf(realObj)) {
217
+ mergedRules.push(rule);
218
+ if (isRecord(rule)) {
219
+ const id = rule["providerId"];
220
+ if (typeof id === "string" && id !== "") seen.add(id);
221
+ }
222
+ }
223
+ for (const rule of rulesOf(copyObj)) {
224
+ if (!isRecord(rule)) continue;
225
+ const id = rule["providerId"];
226
+ if (typeof id !== "string" || id === "") continue;
227
+ if (seen.has(id)) continue;
228
+ seen.add(id);
229
+ mergedRules.push(rule);
230
+ }
231
+ const mergedOrder = [];
232
+ for (const id of [...strArray(cfgOf(realObj)["providerOrder"]), ...strArray(cfgOf(copyObj)["providerOrder"])]) {
233
+ if (!mergedOrder.includes(id)) mergedOrder.push(id);
234
+ }
235
+ const realCfg = cfgOf(realObj);
236
+ const realPcr = isRecord(realCfg["providerConfigRules"]) ? realCfg["providerConfigRules"] : {};
237
+ return {
238
+ ...realObj,
239
+ config: {
240
+ ...realCfg,
241
+ providerOrder: mergedOrder,
242
+ providerConfigRules: { ...realPcr, providerRules: mergedRules }
243
+ }
244
+ };
245
+ }
199
246
  function collectProviderRules(providerRules, conf) {
200
247
  for (const rule of providerRules) {
201
248
  if (!isRecord(rule)) continue;
@@ -230,6 +277,40 @@ function defaultPersonalProviderConfigPath() {
230
277
  function defaultV2ConfigPath() {
231
278
  return path2.join(os2.homedir(), ...ZCODE_V2_CONFIG_PATH_SUFFIX);
232
279
  }
280
+ function piSyncedProviderConfigPath(engineDataDir) {
281
+ return path2.join(engineDataDir, ...import_subagent_engine_sdk4.ZCODE_PI_SYNCED_PROVIDER_CONFIG_SEGMENTS);
282
+ }
283
+ function envEngineDataDirOrUndefined() {
284
+ try {
285
+ return (0, import_subagent_engine_sdk4.resolveEngineDataDir)(process.env);
286
+ } catch {
287
+ return void 0;
288
+ }
289
+ }
290
+ function resolvePersonalProviderSource(sources, engineDataDir) {
291
+ const explicit = sources?.personalProviderConfigPath;
292
+ if (explicit !== void 0) return { kind: "explicit", path: explicit };
293
+ const dataDir = engineDataDir ?? envEngineDataDirOrUndefined();
294
+ if (dataDir !== void 0 && fs.existsSync(piSyncedProviderConfigPath(dataDir))) {
295
+ return { kind: "copy", path: piSyncedProviderConfigPath(dataDir), realPath: defaultPersonalProviderConfigPath() };
296
+ }
297
+ return { kind: "real", path: defaultPersonalProviderConfigPath() };
298
+ }
299
+ function resolvePersonalProviderConfigPath(sources, engineDataDir) {
300
+ return resolvePersonalProviderSource(sources, engineDataDir).path;
301
+ }
302
+ function readPersonalProviderView(sources) {
303
+ const resolution = resolvePersonalProviderSource(sources);
304
+ if (resolution.kind !== "copy") {
305
+ return { conf: readSourceConfig(resolution.path), sourceDesc: resolution.path };
306
+ }
307
+ const copyJson = readSourceJsonOrUndefined(resolution.path);
308
+ const realJson = readSourceJsonOrUndefined(resolution.realPath);
309
+ return {
310
+ conf: extractSourceConfig(mergePersonalProviderConfig(realJson, copyJson)),
311
+ sourceDesc: `merge(\u771F\u5B9E ${resolution.realPath} + \u526F\u672C ${resolution.path})`
312
+ };
313
+ }
233
314
  var SEMVER_SEGMENTS = 3;
234
315
  function locateZcodeBuiltinCatalog(sources) {
235
316
  if (sources?.builtinCatalogPath !== void 0) return sources.builtinCatalogPath;
@@ -320,15 +401,14 @@ function defaultProviderForShortName(conf, withKey) {
320
401
  return withKey[0][0];
321
402
  }
322
403
  function resolveZcodeModelRef(requested, sources) {
323
- const srcPath = sources?.personalProviderConfigPath ?? defaultPersonalProviderConfigPath();
324
- const conf = readSourceConfig(srcPath);
404
+ const { conf, sourceDesc } = readPersonalProviderView(sources);
325
405
  const withKey = [...conf.providers.entries()].filter(([, e]) => hasApiKey(e));
326
406
  const wanted = requested?.trim() || void 0;
327
407
  if (withKey.length === 0) {
328
408
  const hint = wanted ? `model="${wanted}" \u4E0D\u80FD\u6821\u9A8C` : "\u7F3A\u7701\u6A21\u578B\u89E3\u6790\u4E0D\u80FD\u6821\u9A8C";
329
409
  throw new ZcodePrepareError(
330
410
  "engine_credential_missing",
331
- `zcode \u5F15\u64CE\u627E\u4E0D\u5230\u4EFB\u4F55\u5E26 apiKey \u7684\u4E2A\u4EBA provider\uFF08${hint}\uFF09\u3002\u5DF2\u8BFB\u6E90\uFF1A${srcPath}\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`
411
+ `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
332
412
  );
333
413
  }
334
414
  if (wanted === void 0) return "";
@@ -339,26 +419,26 @@ function resolveZcodeModelRef(requested, sources) {
339
419
  const known = withKey.map(([id]) => id).join(", ");
340
420
  throw new ZcodePrepareError(
341
421
  "model_not_available",
342
- `\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`
422
+ `\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
343
423
  );
344
424
  }
345
425
  if (!hasApiKey(entry)) {
346
426
  throw new ZcodePrepareError(
347
427
  "engine_credential_missing",
348
- `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`
428
+ `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
349
429
  );
350
430
  }
351
431
  const models = entry.models ?? [];
352
432
  if (models.length > 0 && !models.includes(short)) {
353
433
  throw new ZcodePrepareError(
354
434
  "model_not_available",
355
- `\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`
435
+ `\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
356
436
  );
357
437
  }
358
438
  return `${provider}/${short}`;
359
439
  }
360
440
  function listZcodeModels(sources) {
361
- const conf = readSourceConfig(sources?.personalProviderConfigPath ?? defaultPersonalProviderConfigPath());
441
+ const { conf } = readPersonalProviderView(sources);
362
442
  const out = [];
363
443
  for (const [pid, entry] of conf.providers) {
364
444
  if (!hasApiKey(entry)) continue;
@@ -378,7 +458,7 @@ var fs2 = __toESM(require("fs"), 1);
378
458
  var path3 = __toESM(require("path"), 1);
379
459
 
380
460
  // src/error-message.ts
381
- var import_subagent_engine_sdk4 = require("@zhushanwen/subagent-engine-sdk");
461
+ var import_subagent_engine_sdk5 = require("@zhushanwen/subagent-engine-sdk");
382
462
 
383
463
  // src/appserver-launcher.ts
384
464
  var ZCODE_APPSERVER_LAUNCHER_NAME = "appserver-launcher.cjs";
@@ -390,6 +470,12 @@ const os = require('node:os');
390
470
 
391
471
  const CLI_PATH = process.env.ZCODE_ENG_CLI_PATH;
392
472
  const V2_PATH = process.env.ZCODE_ENG_V2_CONFIG || path.join(os.homedir(), '.zcode', 'v2', 'config.json');
473
+ // \u771F\u5B9E provider_config.json\uFF08Registry \u76F4\u8BFB\u8DEF\u5F84\uFF0CA0 \u63A2\u9488\u5B9E\u8BC1\uFF09\u2014\u2014\u4E0E CONFIG_PATH \u540C\u6B3E
474
+ // 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
475
+ const REAL_PROVIDER_CONFIG_PATH = path.join(os.homedir(), '.zcode', 'v2', 'provider_config.json');
476
+ // 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
477
+ const PI_SYNCED_PATH = process.env.ZCODE_ENG_PROVIDER_CONFIG || '';
478
+ const PROVIDER_CONFIG_PATH = process.env.ZCODE_ENG_PROVIDER_CONFIG || REAL_PROVIDER_CONFIG_PATH;
393
479
  const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
394
480
 
395
481
  // \u5408\u5E76\u5F62\u6001\uFF1A\u771F\u5B9E cli config \u539F\u6837\uFF08model/plugins/mcp/subagents \u7B49 worker \u7EE7\u627F\u9762\u4E0D\u53D8\uFF09
@@ -398,6 +484,10 @@ const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
398
484
  // \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
399
485
  // 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
400
486
  // \u53EF\u7528\u6A21\u578B\uFF1Bplan \u5BB6\u65CF id \u5DF2\u4E0D\u53EF\u7528\uFF0C\u4E0D\u518D\u515C\u5E95\u4F2A\u9020\uFF09\u3002
487
+ // [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
488
+ // providerRules \u7684\u4E2A\u4EBA provider\uFF08v2 \u5B57\u5178\u672A\u7269\u5316\uFF09\u4E0D\u5728\u6CE8\u5165\u96C6 \u2192 app-server \u6CE8\u518C\u8868
489
+ // \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
490
+ // \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
401
491
  // \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
402
492
  // \u8BFB\u6E90\u7ECF readOrig \u95F4\u63A5\u53D6\uFF1Apatch \u524D\u9996\u8C03 = fs.readFileSync \u672C\u4F53\uFF1Bpatch \u540E = \u539F\u51FD\u6570
403
493
  // \uFF08\u9632 patch \u540E\u7684\u9012\u5F52\u81EA\u8C03\u7528\uFF09\u3002
@@ -415,6 +505,7 @@ function injectedConfigText() {
415
505
  }
416
506
  return null;
417
507
  }
508
+ const realProviders = real.provider && typeof real.provider === 'object' ? real.provider : {};
418
509
  const v2Providers = v2.provider && typeof v2.provider === 'object' ? v2.provider : {};
419
510
  const hasKey = (entry) => entry && typeof entry === 'object'
420
511
  && entry.options && typeof entry.options.apiKey === 'string' && entry.options.apiKey !== '';
@@ -422,9 +513,63 @@ function injectedConfigText() {
422
513
  for (const [id, entry] of Object.entries(v2Providers)) {
423
514
  if (hasKey(entry)) injectable[id] = entry;
424
515
  }
516
+ // 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
517
+ // \u7528\uFF0C\u6CE8\u5165\u9762\u7EF4\u6301 v2-only \u73B0\u72B6\uFF1BproviderRules \u7F3A\u5931\u4E0D\u6784\u6210\u51ED\u636E\u9519\u8BEF\uFF09\u3002
518
+ try {
519
+ const pc = JSON.parse(readOrig(PROVIDER_CONFIG_PATH, 'utf8'));
520
+ const pcCfg = pc && typeof pc.config === 'object' && pc.config ? pc.config : {};
521
+ const pcr = typeof pcCfg.providerConfigRules === 'object' && pcCfg.providerConfigRules ? pcCfg.providerConfigRules : {};
522
+ const rules = Array.isArray(pcr.providerRules) ? pcr.providerRules : [];
523
+ const mcr = typeof pcCfg.modelConfigRules === 'object' && pcCfg.modelConfigRules ? pcCfg.modelConfigRules : {};
524
+ const modelRules = Array.isArray(mcr.providerModelRules) ? mcr.providerModelRules : [];
525
+ const modelMeta = {};
526
+ for (const mr of modelRules) {
527
+ if (!mr || typeof mr !== 'object' || typeof mr.providerId !== 'string' || typeof mr.modelId !== 'string') continue;
528
+ (modelMeta[mr.providerId] = modelMeta[mr.providerId] || []).push(mr);
529
+ }
530
+ for (const rule of rules) {
531
+ if (!rule || typeof rule !== 'object') continue;
532
+ const id = typeof rule.providerId === 'string' ? rule.providerId : '';
533
+ const cfg = rule.config && typeof rule.config === 'object' ? rule.config : {};
534
+ const access = cfg.access && typeof cfg.access === 'object' ? cfg.access : {};
535
+ const api = cfg.api && typeof cfg.api === 'object' ? cfg.api : {};
536
+ // 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
537
+ if (!id || injectable[id] || realProviders[id]) continue;
538
+ // hasKey \u7EAA\u5F8B\u540C\u6B3E\uFF1A\u65E0 apiKey \u4E0D\u5408\u6210\uFF1B\u65E0 baseUrl\uFF08endpoint \u7531\u6A21\u677F\u63D0\u4F9B\u7684\u5F62\u6001\uFF09
539
+ // \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
540
+ if (typeof access.apiKey !== 'string' || access.apiKey === '') continue;
541
+ if (typeof api.baseUrl !== 'string' || api.baseUrl === '') continue;
542
+ const order = Array.isArray(cfg.modelOrder) ? cfg.modelOrder
543
+ : (Array.isArray(cfg.personalModelIds) ? cfg.personalModelIds : []);
544
+ const models = {};
545
+ for (const mr of modelMeta[id] || []) {
546
+ const mrCfg = mr.config && typeof mr.config === 'object' ? mr.config : {};
547
+ if (mrCfg.enabled === false) continue; // \u7981\u7528\u6A21\u578B\u4E0D\u8FDB\u6CE8\u518C\u8868\uFF08GUI \u8BED\u4E49\u4E00\u81F4\uFF09
548
+ const props = mrCfg.properties && typeof mrCfg.properties === 'object' ? mrCfg.properties : {};
549
+ models[mr.modelId] = typeof props.contextWindow === 'number'
550
+ ? { limit: { context: props.contextWindow } }
551
+ : {};
552
+ }
553
+ for (const mid of order) {
554
+ if (typeof mid === 'string' && mid !== '' && !(mid in models)) models[mid] = {};
555
+ }
556
+ // kind \u6309\u6761\u76EE api.type \u6D3E\u751F\uFF08D3\uFF09\uFF1Aanthropic-messages \u2192 anthropic\uFF0C\u5176\u4F59
557
+ // \uFF08openai-chat-completions / api.type \u7F3A\u5E2D / \u672A\u77E5\u503C\uFF09\u2192 openai-compatible
558
+ // \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
559
+ // \u771F\u5B9E\u6761\u76EE\uFF0Canthropic \u534F\u8BAE\u771F\u5B9E\u6761\u76EE\u4ECE\u65E7\u9519\u914D\u503C openai-compatible \u987A\u5E26\u4FEE\u6B63\uFF09\u3002
560
+ // \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
561
+ injectable[id] = {
562
+ name: typeof rule.providerName === 'string' ? rule.providerName : id,
563
+ kind: api.type === 'anthropic-messages' ? 'anthropic' : 'openai-compatible',
564
+ options: { apiKey: access.apiKey, baseURL: api.baseUrl },
565
+ source: 'custom',
566
+ models: models,
567
+ };
568
+ }
569
+ } catch { /* provider_config \u7F3A\u5931/\u635F\u574F \u2192 \u8865\u6CE8\u5165\u9762\u9759\u9ED8\u964D\u7EA7\uFF08v2 \u6CE8\u5165\u4E0D\u53D7\u5F71\u54CD\uFF09 */ }
425
570
  if (Object.keys(injectable).length === 0) return null;
426
571
  const merged = { ...real };
427
- merged.provider = { ...(real.provider && typeof real.provider === 'object' ? real.provider : {}), ...injectable };
572
+ merged.provider = { ...realProviders, ...injectable };
428
573
  if ((!merged.model || typeof merged.model !== 'object' || !merged.model.main)
429
574
  && v2.model && typeof v2.model === 'object' && v2.model.main) {
430
575
  merged.model = { ...(merged.model || {}), main: v2.model.main };
@@ -432,6 +577,77 @@ function injectedConfigText() {
432
577
  return JSON.stringify(merged);
433
578
  }
434
579
 
580
+ // [merge-fn-start]\uFF08\u5BF9\u8D26\u5355\u6D4B\u63D0\u53D6\u951A\u2014\u2014appserver-launcher.test.ts \u6309\u6807\u8BB0\u622A\u53D6\u672C\u51FD\u6570
581
+ // eval \u6267\u884C\uFF1Bpreparer.ts mergePersonalProviderConfig \u4E0E\u672C\u51FD\u6570\u540C\u89C4\u5219\u9501\u6B65\uFF0C\u6539\u4EFB\u4E00\u4FA7
582
+ // \u987B\u540C\u6B65\u53E6\u4E00\u4FA7\u5E76\u8DD1\u5BF9\u8D26\u5355\u6D4B\uFF09
583
+ // merge(\u771F\u5B9E, \u526F\u672C)\u2014\u2014D3 \u6362\u8F68\u7248\u89C4\u5219\uFF1A
584
+ // - \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
585
+ // - \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
586
+ // \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
587
+ // - 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
588
+ // \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
589
+ // - providerOrder\uFF1A\u771F\u5B9E\u73B0\u503C\u5E8F + \u526F\u672C\u72EC\u6709 id \u8FFD\u52A0\uFF08\u53BB\u91CD\u4FDD\u5E8F\uFF09
590
+ // - \u5176\u4F59\u5B57\u6BB5\uFF08\u542B config \u5185\u5176\u4ED6\u952E\uFF09\u53D6\u771F\u5B9E\u73B0\u503C
591
+ function mergeProviderConfig(realObj, copyObj) {
592
+ const isRec = (v) => v && typeof v === 'object' && !Array.isArray(v);
593
+ if (!isRec(copyObj)) return realObj;
594
+ if (!isRec(realObj)) return copyObj;
595
+ const cfgOf = (obj) => (isRec(obj.config) ? obj.config : {});
596
+ const rulesOf = (obj) => {
597
+ const pcr = cfgOf(obj).providerConfigRules;
598
+ const r = isRec(pcr) ? pcr.providerRules : undefined;
599
+ return Array.isArray(r) ? r : [];
600
+ };
601
+ const strArr = (v) => (Array.isArray(v) ? v.filter((s) => typeof s === 'string' && s.trim() !== '') : []);
602
+ const mergedRules = [];
603
+ const seen = {};
604
+ for (const rule of rulesOf(realObj)) {
605
+ mergedRules.push(rule);
606
+ if (isRec(rule) && typeof rule.providerId === 'string' && rule.providerId !== '') seen[rule.providerId] = true;
607
+ }
608
+ for (const rule of rulesOf(copyObj)) {
609
+ if (!isRec(rule) || typeof rule.providerId !== 'string' || rule.providerId === '') continue;
610
+ if (seen[rule.providerId]) continue;
611
+ seen[rule.providerId] = true;
612
+ mergedRules.push(rule);
613
+ }
614
+ const mergedOrder = [];
615
+ for (const id of strArr(cfgOf(realObj).providerOrder).concat(strArr(cfgOf(copyObj).providerOrder))) {
616
+ if (mergedOrder.indexOf(id) === -1) mergedOrder.push(id);
617
+ }
618
+ const outCfg = Object.assign({}, cfgOf(realObj), {
619
+ providerOrder: mergedOrder,
620
+ providerConfigRules: Object.assign(
621
+ {},
622
+ isRec(cfgOf(realObj).providerConfigRules) ? cfgOf(realObj).providerConfigRules : {},
623
+ { providerRules: mergedRules },
624
+ ),
625
+ });
626
+ return Object.assign({}, realObj, { config: outCfg });
627
+ }
628
+ // [merge-fn-end]
629
+
630
+ // 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
631
+ // \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
632
+ // \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
633
+ // \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
634
+ // patch \u9762\u9012\u5F52\u81EA\u8C03\u7528\uFF09\u3002
635
+ function mergedProviderConfigText() {
636
+ if (!PI_SYNCED_PATH) return null;
637
+ const readOrig = fs.__origReadFileSync || fs.readFileSync;
638
+ let copyObj;
639
+ try {
640
+ copyObj = JSON.parse(readOrig(PI_SYNCED_PATH, 'utf8'));
641
+ } catch { return null; }
642
+ if (!copyObj || typeof copyObj !== 'object' || Array.isArray(copyObj)) return null;
643
+ let realObj = null;
644
+ try {
645
+ const parsed = JSON.parse(readOrig(REAL_PROVIDER_CONFIG_PATH, 'utf8'));
646
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) realObj = parsed;
647
+ } catch { /* ENOENT/\u635F\u574F \u2192 \u526F\u672C\u72EC\u6709\u6761\u76EE\u4E3A\u5168\u96C6 */ }
648
+ return JSON.stringify(mergeProviderConfig(realObj, copyObj));
649
+ }
650
+
435
651
  if (!CLI_PATH) {
436
652
  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');
437
653
  process.exit(2);
@@ -455,6 +671,11 @@ if (text !== null) {
455
671
  const cur = injectedConfigText();
456
672
  if (cur !== null) return shape(rest, cur);
457
673
  }
674
+ // D3 \u6362\u8F68\uFF1ARegistry \u76F4\u8BFB\u771F\u5B9E provider_config.json \u2192 merge(\u771F\u5B9E, \u526F\u672C) \u89C6\u56FE
675
+ if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
676
+ const cur = mergedProviderConfigText();
677
+ if (cur !== null) return shape(rest, cur);
678
+ }
458
679
  return fs.__origReadFileSync.call(fs, p, ...rest);
459
680
  };
460
681
  fs.promises.__origReadFile = fs.promises.readFile;
@@ -463,17 +684,27 @@ if (text !== null) {
463
684
  const cur = injectedConfigText();
464
685
  if (cur !== null) return Promise.resolve(shape(rest, cur));
465
686
  }
687
+ if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
688
+ const cur = mergedProviderConfigText();
689
+ if (cur !== null) return Promise.resolve(shape(rest, cur));
690
+ }
466
691
  return fs.promises.__origReadFile.call(fs.promises, p, ...rest);
467
692
  };
468
693
  // existsSync \u62E6\u622A\uFF1A\u771F\u5B9E bundle \u7684\u7528\u6237 config \u8BFB\u53D6\uFF08loadFileConfig\uFF09\u4EE5 existsSync
469
694
  // \u4E3A\u77ED\u8DEF\u95E8\u2014\u2014\u6587\u4EF6\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u7A7A config \u4E14 readFileSync \u4E0D\u88AB\u8C03\u7528\uFF0CGUI-only
470
- // \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
695
+ // \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
696
+ // D3 \u6362\u8F68\uFF1A\u771F\u5B9E provider_config.json \u7684\u5B58\u5728\u6027 = \u771F\u5B9E\u6216\u526F\u672C\u4EFB\u4E00\u5B58\u5728\u5373 true
697
+ //\uFF08\u771F\u5B9E\u7F3A\u5931 + \u526F\u672C\u5B58\u5728\u65F6 Registry \u7684 existsSync \u95E8\u4E0D\u5F97\u62E6\u6389 merge \u89C6\u56FE\u8BFB\u53D6\uFF09
471
698
  fs.__origExistsSync = fs.existsSync;
472
699
  fs.existsSync = function (p) {
473
700
  if (typeof p === 'string' && p === CONFIG_PATH) {
474
701
  const cur = injectedConfigText();
475
702
  if (cur !== null) return true;
476
703
  }
704
+ if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH && PI_SYNCED_PATH) {
705
+ if (fs.__origExistsSync.call(fs, REAL_PROVIDER_CONFIG_PATH)) return true;
706
+ return fs.__origExistsSync.call(fs, PI_SYNCED_PATH);
707
+ }
477
708
  return fs.__origExistsSync.call(fs, p);
478
709
  };
479
710
  }
@@ -568,7 +799,7 @@ function ensureAppServerLauncher(engineDataDir) {
568
799
  fs2.writeFileSync(tmp, APPSERVER_LAUNCHER_SOURCE);
569
800
  fs2.renameSync(tmp, file);
570
801
  } catch (err) {
571
- const reason = (0, import_subagent_engine_sdk4.toErrorMessage)(err);
802
+ const reason = (0, import_subagent_engine_sdk5.toErrorMessage)(err);
572
803
  throw new Error(
573
804
  `zcode app-server launcher \u843D\u76D8\u5931\u8D25: ${file}\uFF08${reason}\uFF09\u3002\u6062\u590D\uFF1A\u68C0\u67E5\u5F15\u64CE\u6570\u636E\u76EE\u5F55 \u5199\u6743\u9650\u4E0E\u78C1\u76D8\u7A7A\u95F4\uFF08engineDataDir \u7531\u5BBF\u4E3B\u4F20\u5165\uFF0C\u8DEF\u5F84\u89C1\u4E0A\uFF09\u540E\u91CD\u8BD5\u3002`
574
805
  );
@@ -826,21 +1057,21 @@ async function readZcodeSessionView(dbPath, sessionId) {
826
1057
  var fs4 = __toESM(require("fs"), 1);
827
1058
  var import_node_path = require("path");
828
1059
  var import_node_os = require("os");
829
- var import_subagent_engine_sdk7 = require("@zhushanwen/subagent-engine-sdk");
1060
+ var import_subagent_engine_sdk8 = require("@zhushanwen/subagent-engine-sdk");
830
1061
 
831
1062
  // src/logs/stderr-rotation.ts
832
- var import_subagent_engine_sdk5 = require("@zhushanwen/subagent-engine-sdk");
833
1063
  var import_subagent_engine_sdk6 = require("@zhushanwen/subagent-engine-sdk");
1064
+ var import_subagent_engine_sdk7 = require("@zhushanwen/subagent-engine-sdk");
834
1065
  var ZCODE_STDERR_LOG_PREFIX = "zcode-appserver-stderr-";
835
1066
  function stderrLogPathFor(engineDataDir, pid) {
836
- return (0, import_subagent_engine_sdk5.stderrLogPathFor)(engineDataDir, pid, ZCODE_STDERR_LOG_PREFIX);
1067
+ return (0, import_subagent_engine_sdk6.stderrLogPathFor)(engineDataDir, pid, ZCODE_STDERR_LOG_PREFIX);
837
1068
  }
838
1069
  function cleanupSiblingStderrLogs(logPath, env, now) {
839
- return (0, import_subagent_engine_sdk5.cleanupSiblingStderrLogs)(logPath, env, ZCODE_STDERR_LOG_PREFIX, now);
1070
+ return (0, import_subagent_engine_sdk6.cleanupSiblingStderrLogs)(logPath, env, ZCODE_STDERR_LOG_PREFIX, now);
840
1071
  }
841
1072
 
842
1073
  // src/connection.ts
843
- var logger = (0, import_subagent_engine_sdk7.getLogger)("subagents");
1074
+ var logger = (0, import_subagent_engine_sdk8.getLogger)("subagents");
844
1075
  var RAW_FRAME_LOG_CHARS = 200;
845
1076
  var RUNTIME_PREFERENCES = Object.freeze({
846
1077
  nativeSearchEnhancementsEnabled: true,
@@ -862,11 +1093,11 @@ function frameIdOf(frame) {
862
1093
  return typeof id === "string" || typeof id === "number" ? id : void 0;
863
1094
  }
864
1095
  function errMessage(err) {
865
- return (0, import_subagent_engine_sdk4.toErrorMessage)(err);
1096
+ return (0, import_subagent_engine_sdk5.toErrorMessage)(err);
866
1097
  }
867
1098
  function buildAppServerEnv(baseEnv = process.env) {
868
1099
  return {
869
- ...(0, import_subagent_engine_sdk7.buildNestedSpawnEnv)(baseEnv),
1100
+ ...(0, import_subagent_engine_sdk8.buildNestedSpawnEnv)(baseEnv),
870
1101
  ZCODE_MODEL_TELEMETRY_ENABLED: "false"
871
1102
  };
872
1103
  }
@@ -1016,7 +1247,7 @@ var AppServerConnection = class {
1016
1247
  close() {
1017
1248
  const child = this.child;
1018
1249
  if (child === null || this.killChainPromise !== void 0) return;
1019
- this.killChainPromise = (0, import_subagent_engine_sdk7.killChain)(child, { graceMs: ZCODE_KILL_GRACE_MS });
1250
+ this.killChainPromise = (0, import_subagent_engine_sdk8.killChain)(child, { graceMs: ZCODE_KILL_GRACE_MS });
1020
1251
  }
1021
1252
  /**
1022
1253
  * 异步完整关闭面:SIGTERM → grace → SIGKILL 杀链走完(含收尸),resolve 于进程
@@ -1028,7 +1259,7 @@ var AppServerConnection = class {
1028
1259
  if (this.killChainPromise === void 0) {
1029
1260
  const child = this.child;
1030
1261
  if (child === null) return;
1031
- this.killChainPromise = (0, import_subagent_engine_sdk7.killChain)(child, { graceMs: opts?.graceMs ?? ZCODE_KILL_GRACE_MS });
1262
+ this.killChainPromise = (0, import_subagent_engine_sdk8.killChain)(child, { graceMs: opts?.graceMs ?? ZCODE_KILL_GRACE_MS });
1032
1263
  }
1033
1264
  await this.killChainPromise;
1034
1265
  }
@@ -1047,10 +1278,10 @@ var AppServerConnection = class {
1047
1278
  this.generation += 1;
1048
1279
  const gen = this.generation;
1049
1280
  const script = this.launcherScript ?? this.cliPath;
1050
- const child = (0, import_subagent_engine_sdk7.spawnEngineChild)({
1281
+ const child = (0, import_subagent_engine_sdk8.spawnEngineChild)({
1051
1282
  command: this.nodeBin,
1052
1283
  args: [script, "app-server", "--cwd", this.cwd],
1053
- env: (0, import_subagent_engine_sdk7.buildEngineChildEnv)(this.env, {
1284
+ env: (0, import_subagent_engine_sdk8.buildEngineChildEnv)(this.env, {
1054
1285
  // L0 TAIJI_AGENT_DATA_DIR 缺省链:显式传参 > 宿主注入 env > tmpdir 占位
1055
1286
  //(app-server 不消费该键,占位仅满足 L0 必注入契约;生产调用方
1056
1287
  // zcode-engine.ensureAppServerRuntime 恒传 engineDataDir)。
@@ -1088,7 +1319,7 @@ var AppServerConnection = class {
1088
1319
  }
1089
1320
  }
1090
1321
  };
1091
- (0, import_subagent_engine_sdk7.pumpNdjsonLines)(child.stdout, (line) => this.handleLine(line));
1322
+ (0, import_subagent_engine_sdk8.pumpNdjsonLines)(child.stdout, (line) => this.handleLine(line));
1092
1323
  child.stderr?.setEncoding("utf8");
1093
1324
  child.stderr?.on("data", (chunk) => {
1094
1325
  this.stderrTail = (this.stderrTail + chunk).slice(-ZCODE_APPSERVER_STDERR_TAIL_BUFFER_CHARS);
@@ -1229,8 +1460,8 @@ var AppServerConnection = class {
1229
1460
  }
1230
1461
  this.stderrStream.write(chunk);
1231
1462
  if (this.activeStderrLogPath !== null) {
1232
- const params = (0, import_subagent_engine_sdk6.stderrRotationParams)(process.env);
1233
- if ((0, import_subagent_engine_sdk6.rotateStderrLogIfNeeded)(this.activeStderrLogPath, params)) {
1463
+ const params = (0, import_subagent_engine_sdk7.stderrRotationParams)(process.env);
1464
+ if ((0, import_subagent_engine_sdk7.rotateStderrLogIfNeeded)(this.activeStderrLogPath, params)) {
1234
1465
  this.closeStderrStream();
1235
1466
  }
1236
1467
  }
@@ -1248,8 +1479,8 @@ var AppServerConnection = class {
1248
1479
 
1249
1480
  // src/session-channel.ts
1250
1481
  var import_node_crypto = require("crypto");
1251
- var import_subagent_engine_sdk8 = require("@zhushanwen/subagent-engine-sdk");
1252
- var logger2 = (0, import_subagent_engine_sdk8.getLogger)("subagents");
1482
+ var import_subagent_engine_sdk9 = require("@zhushanwen/subagent-engine-sdk");
1483
+ var logger2 = (0, import_subagent_engine_sdk9.getLogger)("subagents");
1253
1484
  var SUBSCRIBE_DELIVERY_KIND = "desktop-continuous";
1254
1485
  var WORKSPACE_KEY_HASH_CHARS = 16;
1255
1486
  var CREATE_REPLY_LOG_CHARS = 300;
@@ -1258,7 +1489,7 @@ function isRecord3(v) {
1258
1489
  return typeof v === "object" && v !== null && !Array.isArray(v);
1259
1490
  }
1260
1491
  function errMessage2(err) {
1261
- return (0, import_subagent_engine_sdk4.toErrorMessage)(err);
1492
+ return (0, import_subagent_engine_sdk5.toErrorMessage)(err);
1262
1493
  }
1263
1494
  function stableWorkspaceKey(workspacePath) {
1264
1495
  return "ws-" + (0, import_node_crypto.createHash)("sha256").update(workspacePath).digest("hex").slice(0, WORKSPACE_KEY_HASH_CHARS);
@@ -1785,8 +2016,8 @@ var SessionChannel = class {
1785
2016
 
1786
2017
  // src/session-db-maintenance.ts
1787
2018
  var fs5 = __toESM(require("fs"), 1);
1788
- var import_subagent_engine_sdk9 = require("@zhushanwen/subagent-engine-sdk");
1789
- var logger3 = (0, import_subagent_engine_sdk9.getLogger)("subagents");
2019
+ var import_subagent_engine_sdk10 = require("@zhushanwen/subagent-engine-sdk");
2020
+ var logger3 = (0, import_subagent_engine_sdk10.getLogger)("subagents");
1790
2021
  var ZCODE_SESSION_TTL_MS = 2592e6;
1791
2022
  var ZCODE_SESSION_SWEEP_INTERVAL_MS = 864e5;
1792
2023
  var SWEEP_BUSY_TIMEOUT_MS = 5e3;
@@ -1942,7 +2173,7 @@ function maybeSweepExpiredZcodeSessions(dbPath, opts = {}) {
1942
2173
  }
1943
2174
 
1944
2175
  // src/zcode-engine.ts
1945
- var logger4 = (0, import_subagent_engine_sdk10.getLogger)("subagents");
2176
+ var logger4 = (0, import_subagent_engine_sdk11.getLogger)("subagents");
1946
2177
  var PROBE_VERSION_TIMEOUT_MS = 15e3;
1947
2178
  var COMMON_THOUGHT_LEVELS = ["low", "high", "max"];
1948
2179
  var ZcodeEngine = class {
@@ -1991,7 +2222,10 @@ var ZcodeEngine = class {
1991
2222
  // --mode build/edit/plan/yolo 原生权限档位
1992
2223
  permissionMode: "native",
1993
2224
  // [D3-④] 无 turn_end 语义,轮数上限不可兑现(预检 gate 据此同步拒绝)
1994
- maxTurns: false
2225
+ maxTurns: false,
2226
+ // [subagent-model-switch] zcode 引擎不在模型切换设计范围(协议面引擎中立预留,
2227
+ // 后续另立项接入)——setModel 通路未接通,unsupported 如实声明
2228
+ setModel: "unsupported"
1995
2229
  };
1996
2230
  }
1997
2231
  /** 探针(D7):二进制存在 + 版本解析(zcode 无公开契约,版本漂移的入口信号)。 */
@@ -2308,6 +2542,7 @@ var ZcodeEngine = class {
2308
2542
  const env = buildAppServerEnv(this.deps.processEnv ?? process.env);
2309
2543
  env.ZCODE_ENG_CLI_PATH = cliPath;
2310
2544
  env.ZCODE_ENG_V2_CONFIG = this.deps.sources?.v2ConfigPath ?? defaultV2ConfigPath();
2545
+ env.ZCODE_ENG_PROVIDER_CONFIG = resolvePersonalProviderConfigPath(this.deps.sources, engineDataDir);
2311
2546
  const sessionDbPath = zcodeSessionDbPath(engineDataDir);
2312
2547
  env.ZCODE_SESSION_DB_PATH = sessionDbPath;
2313
2548
  delete env.ZCODE_SESSION_DB;
@@ -2404,7 +2639,7 @@ var ZcodeEngine = class {
2404
2639
  /** abort 合成终态:exitCode=null(record 正常收尾,不留僵尸)。 */
2405
2640
  applyAbortedOutcome(outcome, task, ctx, final, emit) {
2406
2641
  outcome.exitCode = null;
2407
- outcome.error = isHostTimeoutAbort(ctx) ? (0, import_subagent_engine_sdk11.synthesizeTimeoutOutcome)(task, final.output.stdoutText, ZCODE_ENGINE_ID).error ?? (0, import_subagent_engine_sdk11.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)}`;
2642
+ outcome.error = isHostTimeoutAbort(ctx) ? (0, import_subagent_engine_sdk12.synthesizeTimeoutOutcome)(task, final.output.stdoutText, ZCODE_ENGINE_ID).error ?? (0, import_subagent_engine_sdk12.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)}`;
2408
2643
  emit({ type: "error", message: outcome.error });
2409
2644
  }
2410
2645
  /**
@@ -2509,7 +2744,7 @@ var ZcodeEngine = class {
2509
2744
  }
2510
2745
  } else {
2511
2746
  const poolDir = path4.resolve(
2512
- (0, import_subagent_engine_sdk11.resolvePoolDir)(this.deps.engineDataDir(), ZCODE_ENGINE_ID, import_subagent_engine_sdk11.SHARED_POOL_KEY)
2747
+ (0, import_subagent_engine_sdk12.resolvePoolDir)(this.deps.engineDataDir(), ZCODE_ENGINE_ID, import_subagent_engine_sdk12.SHARED_POOL_KEY)
2513
2748
  );
2514
2749
  const resolved = path4.resolve(poolDir, dbPathRaw);
2515
2750
  if (resolved.startsWith(poolDir + path4.sep)) {
@@ -2527,7 +2762,7 @@ var ZcodeEngine = class {
2527
2762
  logger4.warn("[zcode-engine] native session read failed, degrade to journal replay", {
2528
2763
  dbPath,
2529
2764
  sessionId,
2530
- reason: (0, import_subagent_engine_sdk4.toErrorMessage)(err)
2765
+ reason: (0, import_subagent_engine_sdk5.toErrorMessage)(err)
2531
2766
  });
2532
2767
  }
2533
2768
  }
@@ -2614,7 +2849,7 @@ var ZcodeEngine = class {
2614
2849
  buildPrompt(task, schema) {
2615
2850
  const segments = [...task.appendSystemPrompt ?? []];
2616
2851
  segments.push(task.prompt);
2617
- if (schema !== void 0) segments.push((0, import_subagent_engine_sdk11.buildSchemaEmulationSegment)(schema));
2852
+ if (schema !== void 0) segments.push((0, import_subagent_engine_sdk12.buildSchemaEmulationSegment)(schema));
2618
2853
  return segments.join("\n\n");
2619
2854
  }
2620
2855
  };
@@ -2657,7 +2892,7 @@ function isPlainObject(v) {
2657
2892
  return typeof v === "object" && v !== null && !Array.isArray(v);
2658
2893
  }
2659
2894
  function errMessage3(err) {
2660
- return (0, import_subagent_engine_sdk4.toErrorMessage)(err);
2895
+ return (0, import_subagent_engine_sdk5.toErrorMessage)(err);
2661
2896
  }
2662
2897
  function resolveAppserverTimingMs(envName, fallbackMs, label) {
2663
2898
  const raw = process.env[envName];
@@ -2769,7 +3004,7 @@ function parsedAppServerAttempt(task, r) {
2769
3004
  kind: "parsed",
2770
3005
  output: syntheticAppServerOutput(0),
2771
3006
  payload: turnResultToPayload(r),
2772
- ...schema !== void 0 ? { schemaResult: (0, import_subagent_engine_sdk11.extractAndValidateStructuredOutput)(r.response, schema) } : {}
3007
+ ...schema !== void 0 ? { schemaResult: (0, import_subagent_engine_sdk12.extractAndValidateStructuredOutput)(r.response, schema) } : {}
2773
3008
  };
2774
3009
  }
2775
3010
  function failedTerminalAppServerAttempt(r) {
@@ -2807,16 +3042,16 @@ function failedAppServerAttempt(err, currentSessionId, opts = {}) {
2807
3042
  };
2808
3043
  }
2809
3044
  function isHostTimeoutAbort(ctx) {
2810
- return ctx.signal?.aborted === true && ctx.signal.reason === import_subagent_engine_sdk11.HOST_TIMEOUT_ABORT_REASON;
3045
+ return ctx.signal?.aborted === true && ctx.signal.reason === import_subagent_engine_sdk12.HOST_TIMEOUT_ABORT_REASON;
2811
3046
  }
2812
3047
  var PROBE_STDOUT_CAP_CHARS = 4096;
2813
3048
  async function defaultProbeVersion(cliPath, dataDir) {
2814
3049
  try {
2815
3050
  return await new Promise((resolve2, reject) => {
2816
- const child = (0, import_subagent_engine_sdk11.spawnEngineChild)({
3051
+ const child = (0, import_subagent_engine_sdk12.spawnEngineChild)({
2817
3052
  command: "node",
2818
3053
  args: [cliPath, "--version"],
2819
- env: (0, import_subagent_engine_sdk11.buildEngineChildEnv)(process.env, { dataDir }),
3054
+ env: (0, import_subagent_engine_sdk12.buildEngineChildEnv)(process.env, { dataDir }),
2820
3055
  stdout: "pipe",
2821
3056
  stderr: "ignore",
2822
3057
  signal: AbortSignal.timeout(PROBE_VERSION_TIMEOUT_MS)
@@ -2834,7 +3069,7 @@ async function defaultProbeVersion(cliPath, dataDir) {
2834
3069
  });
2835
3070
  } catch (err) {
2836
3071
  logger4.debug(
2837
- `[zcode-engine] probe version check failed (best-effort continue): ${(0, import_subagent_engine_sdk4.toErrorMessage)(err)}`
3072
+ `[zcode-engine] probe version check failed (best-effort continue): ${(0, import_subagent_engine_sdk5.toErrorMessage)(err)}`
2838
3073
  );
2839
3074
  return void 0;
2840
3075
  }
@@ -2842,7 +3077,7 @@ async function defaultProbeVersion(cliPath, dataDir) {
2842
3077
 
2843
3078
  // src/registration.ts
2844
3079
  function defaultEngineDataDir() {
2845
- return (0, import_subagent_engine_sdk12.resolveEngineDataDir)(process.env);
3080
+ return (0, import_subagent_engine_sdk13.resolveEngineDataDir)(process.env);
2846
3081
  }
2847
3082
  function createZcodeEngine(deps) {
2848
3083
  return new ZcodeEngine(deps);
@@ -2855,11 +3090,11 @@ function createDefaultZcodeEngine() {
2855
3090
  }
2856
3091
 
2857
3092
  // src/port-types.ts
2858
- var import_subagent_engine_sdk13 = require("@zhushanwen/subagent-engine-sdk");
3093
+ var import_subagent_engine_sdk14 = require("@zhushanwen/subagent-engine-sdk");
2859
3094
 
2860
3095
  // src/server.ts
2861
3096
  var import_server = require("@zhushanwen/subagent-engine-sdk/server");
2862
- var logger5 = (0, import_subagent_engine_sdk14.getLogger)("subagents");
3097
+ var logger5 = (0, import_subagent_engine_sdk15.getLogger)("subagents");
2863
3098
  var EngineProtocolServer = class {
2864
3099
  write;
2865
3100
  engine;
@@ -2929,7 +3164,7 @@ var EngineProtocolServer = class {
2929
3164
  const active = { controller, seq: 0 };
2930
3165
  this.activeRuns.set(runId, active);
2931
3166
  const fullTask = (0, import_server.assembleFullTask)(task, ctx);
2932
- const ctxModel = (0, import_subagent_engine_sdk13.parseCtxModel)(ctx.ctxModel);
3167
+ const ctxModel = (0, import_subagent_engine_sdk14.parseCtxModel)(ctx.ctxModel);
2933
3168
  const stream = ctx.streamMode === "stream" ? {
2934
3169
  onDelta: (delta) => {
2935
3170
  void this.reverseRequestInternal("host/streamDelta", { runId, delta }).catch(this.warnReverseFailure("host/streamDelta", `run ${runId}`));
@@ -2965,7 +3200,7 @@ var EngineProtocolServer = class {
2965
3200
  }
2966
3201
  validateModel(params) {
2967
3202
  if (this.engine.validateModel === void 0) {
2968
- throw new import_subagent_engine_sdk14.EngineSdkError(
3203
+ throw new import_subagent_engine_sdk15.EngineSdkError(
2969
3204
  "engine_capability_unsupported",
2970
3205
  "engine does not implement validateModel",
2971
3206
  "Manifest omits modelCatalog; model validation falls back to run-time engine checks."
@@ -2992,7 +3227,7 @@ var EngineProtocolServer = class {
2992
3227
  warnReverseFailure(method, context) {
2993
3228
  return (err) => {
2994
3229
  logger5.warn(`[protocol] ${method} reverse request failed (${context}); continuing without it`, {
2995
- detail: (0, import_subagent_engine_sdk4.toErrorMessage)(err)
3230
+ detail: (0, import_subagent_engine_sdk5.toErrorMessage)(err)
2996
3231
  });
2997
3232
  };
2998
3233
  }
@@ -3021,7 +3256,7 @@ var EngineProtocolServer = class {
3021
3256
  clearTimeout(pending.timer);
3022
3257
  this.reverseClock?.acked(String(id));
3023
3258
  this.reverseClock?.settled(String(id));
3024
- if (frame.error !== void 0) pending.reject(new Error(`reverse request ${String(id)} rejected: ${(0, import_subagent_engine_sdk4.toErrorMessage)(frame.error)}`));
3259
+ if (frame.error !== void 0) pending.reject(new Error(`reverse request ${String(id)} rejected: ${(0, import_subagent_engine_sdk5.toErrorMessage)(frame.error)}`));
3025
3260
  else pending.resolve(frame.result);
3026
3261
  }
3027
3262
  };