@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/main.cjs CHANGED
@@ -23,10 +23,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
 
25
25
  // src/main.ts
26
- var import_subagent_engine_sdk15 = require("@zhushanwen/subagent-engine-sdk");
26
+ var import_subagent_engine_sdk16 = require("@zhushanwen/subagent-engine-sdk");
27
27
 
28
28
  // src/server.ts
29
- var import_subagent_engine_sdk14 = require("@zhushanwen/subagent-engine-sdk");
29
+ var import_subagent_engine_sdk15 = require("@zhushanwen/subagent-engine-sdk");
30
30
 
31
31
  // src/constants.ts
32
32
  var ZCODE_ENGINE_ID = "zcode";
@@ -62,13 +62,13 @@ var ZCODE_RESUME_CHARS_PER_TOKEN = 4;
62
62
  var ZCODE_SESSION_SWEEP_DEFER_MS = 50;
63
63
 
64
64
  // src/registration.ts
65
- var import_subagent_engine_sdk12 = require("@zhushanwen/subagent-engine-sdk");
65
+ var import_subagent_engine_sdk13 = require("@zhushanwen/subagent-engine-sdk");
66
66
 
67
67
  // src/zcode-engine.ts
68
68
  var fs6 = __toESM(require("fs"), 1);
69
69
  var path4 = __toESM(require("path"), 1);
70
- var import_subagent_engine_sdk10 = require("@zhushanwen/subagent-engine-sdk");
71
70
  var import_subagent_engine_sdk11 = require("@zhushanwen/subagent-engine-sdk");
71
+ var import_subagent_engine_sdk12 = require("@zhushanwen/subagent-engine-sdk");
72
72
 
73
73
  // src/journal-io.ts
74
74
  var import_subagent_engine_sdk = require("@zhushanwen/subagent-engine-sdk");
@@ -139,6 +139,7 @@ function synthesizeCoarseEvents(response, usage) {
139
139
  var fs = __toESM(require("fs"), 1);
140
140
  var os2 = __toESM(require("os"), 1);
141
141
  var path2 = __toESM(require("path"), 1);
142
+ var import_subagent_engine_sdk4 = require("@zhushanwen/subagent-engine-sdk");
142
143
  var ZcodePrepareError = class extends Error {
143
144
  code;
144
145
  constructor(code, message) {
@@ -147,35 +148,81 @@ var ZcodePrepareError = class extends Error {
147
148
  this.code = code;
148
149
  }
149
150
  };
151
+ 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";
150
152
  function isRecord(v) {
151
153
  return typeof v === "object" && v !== null && !Array.isArray(v);
152
154
  }
153
155
  function strArray(v) {
154
156
  return Array.isArray(v) ? v.filter((m) => typeof m === "string" && m.trim() !== "") : [];
155
157
  }
156
- function readSourceConfig(absPath) {
157
- const empty = { providers: /* @__PURE__ */ new Map(), order: [] };
158
+ function readSourceJsonOrUndefined(absPath) {
158
159
  let raw;
159
160
  try {
160
161
  raw = fs.readFileSync(absPath, "utf8");
161
162
  } catch {
162
- return empty;
163
+ return void 0;
163
164
  }
164
- let parsed;
165
165
  try {
166
- parsed = JSON.parse(raw);
166
+ return JSON.parse(raw);
167
167
  } catch {
168
- return empty;
169
- }
170
- if (!isRecord(parsed)) return empty;
171
- const rules = parsed["config"]?.["providerConfigRules"];
172
- const providerRules = !isRecord(rules) ? void 0 : rules["providerRules"];
173
- const orderSrc = parsed["config"]?.["providerOrder"];
174
- const conf = { providers: /* @__PURE__ */ new Map(), order: strArray(orderSrc) };
175
- if (!Array.isArray(providerRules)) return conf;
176
- collectProviderRules(providerRules, conf);
168
+ return void 0;
169
+ }
170
+ }
171
+ function extractSourceConfig(parsed) {
172
+ const conf = { providers: /* @__PURE__ */ new Map(), order: [] };
173
+ if (!isRecord(parsed)) return conf;
174
+ const config = parsed["config"];
175
+ if (!isRecord(config)) return conf;
176
+ conf.order = strArray(config["providerOrder"]);
177
+ const rules = config["providerConfigRules"];
178
+ const providerRules = isRecord(rules) ? rules["providerRules"] : void 0;
179
+ if (Array.isArray(providerRules)) collectProviderRules(providerRules, conf);
177
180
  return conf;
178
181
  }
182
+ function readSourceConfig(absPath) {
183
+ return extractSourceConfig(readSourceJsonOrUndefined(absPath));
184
+ }
185
+ function mergePersonalProviderConfig(realObj, copyObj) {
186
+ if (!isRecord(copyObj)) return realObj;
187
+ if (!isRecord(realObj)) return copyObj;
188
+ const cfgOf = (obj) => isRecord(obj["config"]) ? obj["config"] : {};
189
+ const rulesOf = (obj) => {
190
+ const pcr = cfgOf(obj)["providerConfigRules"];
191
+ const rules = isRecord(pcr) ? pcr["providerRules"] : void 0;
192
+ return Array.isArray(rules) ? rules : [];
193
+ };
194
+ const mergedRules = [];
195
+ const seen = /* @__PURE__ */ new Set();
196
+ for (const rule of rulesOf(realObj)) {
197
+ mergedRules.push(rule);
198
+ if (isRecord(rule)) {
199
+ const id = rule["providerId"];
200
+ if (typeof id === "string" && id !== "") seen.add(id);
201
+ }
202
+ }
203
+ for (const rule of rulesOf(copyObj)) {
204
+ if (!isRecord(rule)) continue;
205
+ const id = rule["providerId"];
206
+ if (typeof id !== "string" || id === "") continue;
207
+ if (seen.has(id)) continue;
208
+ seen.add(id);
209
+ mergedRules.push(rule);
210
+ }
211
+ const mergedOrder = [];
212
+ for (const id of [...strArray(cfgOf(realObj)["providerOrder"]), ...strArray(cfgOf(copyObj)["providerOrder"])]) {
213
+ if (!mergedOrder.includes(id)) mergedOrder.push(id);
214
+ }
215
+ const realCfg = cfgOf(realObj);
216
+ const realPcr = isRecord(realCfg["providerConfigRules"]) ? realCfg["providerConfigRules"] : {};
217
+ return {
218
+ ...realObj,
219
+ config: {
220
+ ...realCfg,
221
+ providerOrder: mergedOrder,
222
+ providerConfigRules: { ...realPcr, providerRules: mergedRules }
223
+ }
224
+ };
225
+ }
179
226
  function collectProviderRules(providerRules, conf) {
180
227
  for (const rule of providerRules) {
181
228
  if (!isRecord(rule)) continue;
@@ -210,6 +257,40 @@ function defaultPersonalProviderConfigPath() {
210
257
  function defaultV2ConfigPath() {
211
258
  return path2.join(os2.homedir(), ...ZCODE_V2_CONFIG_PATH_SUFFIX);
212
259
  }
260
+ function piSyncedProviderConfigPath(engineDataDir) {
261
+ return path2.join(engineDataDir, ...import_subagent_engine_sdk4.ZCODE_PI_SYNCED_PROVIDER_CONFIG_SEGMENTS);
262
+ }
263
+ function envEngineDataDirOrUndefined() {
264
+ try {
265
+ return (0, import_subagent_engine_sdk4.resolveEngineDataDir)(process.env);
266
+ } catch {
267
+ return void 0;
268
+ }
269
+ }
270
+ function resolvePersonalProviderSource(sources, engineDataDir) {
271
+ const explicit = sources?.personalProviderConfigPath;
272
+ if (explicit !== void 0) return { kind: "explicit", path: explicit };
273
+ const dataDir = engineDataDir ?? envEngineDataDirOrUndefined();
274
+ if (dataDir !== void 0 && fs.existsSync(piSyncedProviderConfigPath(dataDir))) {
275
+ return { kind: "copy", path: piSyncedProviderConfigPath(dataDir), realPath: defaultPersonalProviderConfigPath() };
276
+ }
277
+ return { kind: "real", path: defaultPersonalProviderConfigPath() };
278
+ }
279
+ function resolvePersonalProviderConfigPath(sources, engineDataDir) {
280
+ return resolvePersonalProviderSource(sources, engineDataDir).path;
281
+ }
282
+ function readPersonalProviderView(sources) {
283
+ const resolution = resolvePersonalProviderSource(sources);
284
+ if (resolution.kind !== "copy") {
285
+ return { conf: readSourceConfig(resolution.path), sourceDesc: resolution.path };
286
+ }
287
+ const copyJson = readSourceJsonOrUndefined(resolution.path);
288
+ const realJson = readSourceJsonOrUndefined(resolution.realPath);
289
+ return {
290
+ conf: extractSourceConfig(mergePersonalProviderConfig(realJson, copyJson)),
291
+ sourceDesc: `merge(\u771F\u5B9E ${resolution.realPath} + \u526F\u672C ${resolution.path})`
292
+ };
293
+ }
213
294
  var SEMVER_SEGMENTS = 3;
214
295
  function locateZcodeBuiltinCatalog(sources) {
215
296
  if (sources?.builtinCatalogPath !== void 0) return sources.builtinCatalogPath;
@@ -300,15 +381,14 @@ function defaultProviderForShortName(conf, withKey) {
300
381
  return withKey[0][0];
301
382
  }
302
383
  function resolveZcodeModelRef(requested, sources) {
303
- const srcPath = sources?.personalProviderConfigPath ?? defaultPersonalProviderConfigPath();
304
- const conf = readSourceConfig(srcPath);
384
+ const { conf, sourceDesc } = readPersonalProviderView(sources);
305
385
  const withKey = [...conf.providers.entries()].filter(([, e]) => hasApiKey(e));
306
386
  const wanted = requested?.trim() || void 0;
307
387
  if (withKey.length === 0) {
308
388
  const hint = wanted ? `model="${wanted}" \u4E0D\u80FD\u6821\u9A8C` : "\u7F3A\u7701\u6A21\u578B\u89E3\u6790\u4E0D\u80FD\u6821\u9A8C";
309
389
  throw new ZcodePrepareError(
310
390
  "engine_credential_missing",
311
- `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`
391
+ `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
312
392
  );
313
393
  }
314
394
  if (wanted === void 0) return "";
@@ -319,26 +399,26 @@ function resolveZcodeModelRef(requested, sources) {
319
399
  const known = withKey.map(([id]) => id).join(", ");
320
400
  throw new ZcodePrepareError(
321
401
  "model_not_available",
322
- `\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`
402
+ `\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
323
403
  );
324
404
  }
325
405
  if (!hasApiKey(entry)) {
326
406
  throw new ZcodePrepareError(
327
407
  "engine_credential_missing",
328
- `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`
408
+ `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
329
409
  );
330
410
  }
331
411
  const models = entry.models ?? [];
332
412
  if (models.length > 0 && !models.includes(short)) {
333
413
  throw new ZcodePrepareError(
334
414
  "model_not_available",
335
- `\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`
415
+ `\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
336
416
  );
337
417
  }
338
418
  return `${provider}/${short}`;
339
419
  }
340
420
  function listZcodeModels(sources) {
341
- const conf = readSourceConfig(sources?.personalProviderConfigPath ?? defaultPersonalProviderConfigPath());
421
+ const { conf } = readPersonalProviderView(sources);
342
422
  const out = [];
343
423
  for (const [pid, entry] of conf.providers) {
344
424
  if (!hasApiKey(entry)) continue;
@@ -358,7 +438,7 @@ var fs2 = __toESM(require("fs"), 1);
358
438
  var path3 = __toESM(require("path"), 1);
359
439
 
360
440
  // src/error-message.ts
361
- var import_subagent_engine_sdk4 = require("@zhushanwen/subagent-engine-sdk");
441
+ var import_subagent_engine_sdk5 = require("@zhushanwen/subagent-engine-sdk");
362
442
 
363
443
  // src/appserver-launcher.ts
364
444
  var ZCODE_APPSERVER_LAUNCHER_NAME = "appserver-launcher.cjs";
@@ -370,6 +450,12 @@ const os = require('node:os');
370
450
 
371
451
  const CLI_PATH = process.env.ZCODE_ENG_CLI_PATH;
372
452
  const V2_PATH = process.env.ZCODE_ENG_V2_CONFIG || path.join(os.homedir(), '.zcode', 'v2', 'config.json');
453
+ // \u771F\u5B9E provider_config.json\uFF08Registry \u76F4\u8BFB\u8DEF\u5F84\uFF0CA0 \u63A2\u9488\u5B9E\u8BC1\uFF09\u2014\u2014\u4E0E CONFIG_PATH \u540C\u6B3E
454
+ // 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
455
+ const REAL_PROVIDER_CONFIG_PATH = path.join(os.homedir(), '.zcode', 'v2', 'provider_config.json');
456
+ // 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
457
+ const PI_SYNCED_PATH = process.env.ZCODE_ENG_PROVIDER_CONFIG || '';
458
+ const PROVIDER_CONFIG_PATH = process.env.ZCODE_ENG_PROVIDER_CONFIG || REAL_PROVIDER_CONFIG_PATH;
373
459
  const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
374
460
 
375
461
  // \u5408\u5E76\u5F62\u6001\uFF1A\u771F\u5B9E cli config \u539F\u6837\uFF08model/plugins/mcp/subagents \u7B49 worker \u7EE7\u627F\u9762\u4E0D\u53D8\uFF09
@@ -378,6 +464,10 @@ const CONFIG_PATH = path.join(os.homedir(), '.zcode', 'cli', 'config.json');
378
464
  // \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
379
465
  // 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
380
466
  // \u53EF\u7528\u6A21\u578B\uFF1Bplan \u5BB6\u65CF id \u5DF2\u4E0D\u53EF\u7528\uFF0C\u4E0D\u518D\u515C\u5E95\u4F2A\u9020\uFF09\u3002
467
+ // [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
468
+ // providerRules \u7684\u4E2A\u4EBA provider\uFF08v2 \u5B57\u5178\u672A\u7269\u5316\uFF09\u4E0D\u5728\u6CE8\u5165\u96C6 \u2192 app-server \u6CE8\u518C\u8868
469
+ // \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
470
+ // \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
381
471
  // \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
382
472
  // \u8BFB\u6E90\u7ECF readOrig \u95F4\u63A5\u53D6\uFF1Apatch \u524D\u9996\u8C03 = fs.readFileSync \u672C\u4F53\uFF1Bpatch \u540E = \u539F\u51FD\u6570
383
473
  // \uFF08\u9632 patch \u540E\u7684\u9012\u5F52\u81EA\u8C03\u7528\uFF09\u3002
@@ -395,6 +485,7 @@ function injectedConfigText() {
395
485
  }
396
486
  return null;
397
487
  }
488
+ const realProviders = real.provider && typeof real.provider === 'object' ? real.provider : {};
398
489
  const v2Providers = v2.provider && typeof v2.provider === 'object' ? v2.provider : {};
399
490
  const hasKey = (entry) => entry && typeof entry === 'object'
400
491
  && entry.options && typeof entry.options.apiKey === 'string' && entry.options.apiKey !== '';
@@ -402,9 +493,63 @@ function injectedConfigText() {
402
493
  for (const [id, entry] of Object.entries(v2Providers)) {
403
494
  if (hasKey(entry)) injectable[id] = entry;
404
495
  }
496
+ // 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
497
+ // \u7528\uFF0C\u6CE8\u5165\u9762\u7EF4\u6301 v2-only \u73B0\u72B6\uFF1BproviderRules \u7F3A\u5931\u4E0D\u6784\u6210\u51ED\u636E\u9519\u8BEF\uFF09\u3002
498
+ try {
499
+ const pc = JSON.parse(readOrig(PROVIDER_CONFIG_PATH, 'utf8'));
500
+ const pcCfg = pc && typeof pc.config === 'object' && pc.config ? pc.config : {};
501
+ const pcr = typeof pcCfg.providerConfigRules === 'object' && pcCfg.providerConfigRules ? pcCfg.providerConfigRules : {};
502
+ const rules = Array.isArray(pcr.providerRules) ? pcr.providerRules : [];
503
+ const mcr = typeof pcCfg.modelConfigRules === 'object' && pcCfg.modelConfigRules ? pcCfg.modelConfigRules : {};
504
+ const modelRules = Array.isArray(mcr.providerModelRules) ? mcr.providerModelRules : [];
505
+ const modelMeta = {};
506
+ for (const mr of modelRules) {
507
+ if (!mr || typeof mr !== 'object' || typeof mr.providerId !== 'string' || typeof mr.modelId !== 'string') continue;
508
+ (modelMeta[mr.providerId] = modelMeta[mr.providerId] || []).push(mr);
509
+ }
510
+ for (const rule of rules) {
511
+ if (!rule || typeof rule !== 'object') continue;
512
+ const id = typeof rule.providerId === 'string' ? rule.providerId : '';
513
+ const cfg = rule.config && typeof rule.config === 'object' ? rule.config : {};
514
+ const access = cfg.access && typeof cfg.access === 'object' ? cfg.access : {};
515
+ const api = cfg.api && typeof cfg.api === 'object' ? cfg.api : {};
516
+ // 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
517
+ if (!id || injectable[id] || realProviders[id]) continue;
518
+ // hasKey \u7EAA\u5F8B\u540C\u6B3E\uFF1A\u65E0 apiKey \u4E0D\u5408\u6210\uFF1B\u65E0 baseUrl\uFF08endpoint \u7531\u6A21\u677F\u63D0\u4F9B\u7684\u5F62\u6001\uFF09
519
+ // \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
520
+ if (typeof access.apiKey !== 'string' || access.apiKey === '') continue;
521
+ if (typeof api.baseUrl !== 'string' || api.baseUrl === '') continue;
522
+ const order = Array.isArray(cfg.modelOrder) ? cfg.modelOrder
523
+ : (Array.isArray(cfg.personalModelIds) ? cfg.personalModelIds : []);
524
+ const models = {};
525
+ for (const mr of modelMeta[id] || []) {
526
+ const mrCfg = mr.config && typeof mr.config === 'object' ? mr.config : {};
527
+ if (mrCfg.enabled === false) continue; // \u7981\u7528\u6A21\u578B\u4E0D\u8FDB\u6CE8\u518C\u8868\uFF08GUI \u8BED\u4E49\u4E00\u81F4\uFF09
528
+ const props = mrCfg.properties && typeof mrCfg.properties === 'object' ? mrCfg.properties : {};
529
+ models[mr.modelId] = typeof props.contextWindow === 'number'
530
+ ? { limit: { context: props.contextWindow } }
531
+ : {};
532
+ }
533
+ for (const mid of order) {
534
+ if (typeof mid === 'string' && mid !== '' && !(mid in models)) models[mid] = {};
535
+ }
536
+ // kind \u6309\u6761\u76EE api.type \u6D3E\u751F\uFF08D3\uFF09\uFF1Aanthropic-messages \u2192 anthropic\uFF0C\u5176\u4F59
537
+ // \uFF08openai-chat-completions / api.type \u7F3A\u5E2D / \u672A\u77E5\u503C\uFF09\u2192 openai-compatible
538
+ // \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
539
+ // \u771F\u5B9E\u6761\u76EE\uFF0Canthropic \u534F\u8BAE\u771F\u5B9E\u6761\u76EE\u4ECE\u65E7\u9519\u914D\u503C openai-compatible \u987A\u5E26\u4FEE\u6B63\uFF09\u3002
540
+ // \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
541
+ injectable[id] = {
542
+ name: typeof rule.providerName === 'string' ? rule.providerName : id,
543
+ kind: api.type === 'anthropic-messages' ? 'anthropic' : 'openai-compatible',
544
+ options: { apiKey: access.apiKey, baseURL: api.baseUrl },
545
+ source: 'custom',
546
+ models: models,
547
+ };
548
+ }
549
+ } catch { /* provider_config \u7F3A\u5931/\u635F\u574F \u2192 \u8865\u6CE8\u5165\u9762\u9759\u9ED8\u964D\u7EA7\uFF08v2 \u6CE8\u5165\u4E0D\u53D7\u5F71\u54CD\uFF09 */ }
405
550
  if (Object.keys(injectable).length === 0) return null;
406
551
  const merged = { ...real };
407
- merged.provider = { ...(real.provider && typeof real.provider === 'object' ? real.provider : {}), ...injectable };
552
+ merged.provider = { ...realProviders, ...injectable };
408
553
  if ((!merged.model || typeof merged.model !== 'object' || !merged.model.main)
409
554
  && v2.model && typeof v2.model === 'object' && v2.model.main) {
410
555
  merged.model = { ...(merged.model || {}), main: v2.model.main };
@@ -412,6 +557,77 @@ function injectedConfigText() {
412
557
  return JSON.stringify(merged);
413
558
  }
414
559
 
560
+ // [merge-fn-start]\uFF08\u5BF9\u8D26\u5355\u6D4B\u63D0\u53D6\u951A\u2014\u2014appserver-launcher.test.ts \u6309\u6807\u8BB0\u622A\u53D6\u672C\u51FD\u6570
561
+ // eval \u6267\u884C\uFF1Bpreparer.ts mergePersonalProviderConfig \u4E0E\u672C\u51FD\u6570\u540C\u89C4\u5219\u9501\u6B65\uFF0C\u6539\u4EFB\u4E00\u4FA7
562
+ // \u987B\u540C\u6B65\u53E6\u4E00\u4FA7\u5E76\u8DD1\u5BF9\u8D26\u5355\u6D4B\uFF09
563
+ // merge(\u771F\u5B9E, \u526F\u672C)\u2014\u2014D3 \u6362\u8F68\u7248\u89C4\u5219\uFF1A
564
+ // - \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
565
+ // - \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
566
+ // \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
567
+ // - 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
568
+ // \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
569
+ // - providerOrder\uFF1A\u771F\u5B9E\u73B0\u503C\u5E8F + \u526F\u672C\u72EC\u6709 id \u8FFD\u52A0\uFF08\u53BB\u91CD\u4FDD\u5E8F\uFF09
570
+ // - \u5176\u4F59\u5B57\u6BB5\uFF08\u542B config \u5185\u5176\u4ED6\u952E\uFF09\u53D6\u771F\u5B9E\u73B0\u503C
571
+ function mergeProviderConfig(realObj, copyObj) {
572
+ const isRec = (v) => v && typeof v === 'object' && !Array.isArray(v);
573
+ if (!isRec(copyObj)) return realObj;
574
+ if (!isRec(realObj)) return copyObj;
575
+ const cfgOf = (obj) => (isRec(obj.config) ? obj.config : {});
576
+ const rulesOf = (obj) => {
577
+ const pcr = cfgOf(obj).providerConfigRules;
578
+ const r = isRec(pcr) ? pcr.providerRules : undefined;
579
+ return Array.isArray(r) ? r : [];
580
+ };
581
+ const strArr = (v) => (Array.isArray(v) ? v.filter((s) => typeof s === 'string' && s.trim() !== '') : []);
582
+ const mergedRules = [];
583
+ const seen = {};
584
+ for (const rule of rulesOf(realObj)) {
585
+ mergedRules.push(rule);
586
+ if (isRec(rule) && typeof rule.providerId === 'string' && rule.providerId !== '') seen[rule.providerId] = true;
587
+ }
588
+ for (const rule of rulesOf(copyObj)) {
589
+ if (!isRec(rule) || typeof rule.providerId !== 'string' || rule.providerId === '') continue;
590
+ if (seen[rule.providerId]) continue;
591
+ seen[rule.providerId] = true;
592
+ mergedRules.push(rule);
593
+ }
594
+ const mergedOrder = [];
595
+ for (const id of strArr(cfgOf(realObj).providerOrder).concat(strArr(cfgOf(copyObj).providerOrder))) {
596
+ if (mergedOrder.indexOf(id) === -1) mergedOrder.push(id);
597
+ }
598
+ const outCfg = Object.assign({}, cfgOf(realObj), {
599
+ providerOrder: mergedOrder,
600
+ providerConfigRules: Object.assign(
601
+ {},
602
+ isRec(cfgOf(realObj).providerConfigRules) ? cfgOf(realObj).providerConfigRules : {},
603
+ { providerRules: mergedRules },
604
+ ),
605
+ });
606
+ return Object.assign({}, realObj, { config: outCfg });
607
+ }
608
+ // [merge-fn-end]
609
+
610
+ // 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
611
+ // \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
612
+ // \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
613
+ // \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
614
+ // patch \u9762\u9012\u5F52\u81EA\u8C03\u7528\uFF09\u3002
615
+ function mergedProviderConfigText() {
616
+ if (!PI_SYNCED_PATH) return null;
617
+ const readOrig = fs.__origReadFileSync || fs.readFileSync;
618
+ let copyObj;
619
+ try {
620
+ copyObj = JSON.parse(readOrig(PI_SYNCED_PATH, 'utf8'));
621
+ } catch { return null; }
622
+ if (!copyObj || typeof copyObj !== 'object' || Array.isArray(copyObj)) return null;
623
+ let realObj = null;
624
+ try {
625
+ const parsed = JSON.parse(readOrig(REAL_PROVIDER_CONFIG_PATH, 'utf8'));
626
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) realObj = parsed;
627
+ } catch { /* ENOENT/\u635F\u574F \u2192 \u526F\u672C\u72EC\u6709\u6761\u76EE\u4E3A\u5168\u96C6 */ }
628
+ return JSON.stringify(mergeProviderConfig(realObj, copyObj));
629
+ }
630
+
415
631
  if (!CLI_PATH) {
416
632
  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');
417
633
  process.exit(2);
@@ -435,6 +651,11 @@ if (text !== null) {
435
651
  const cur = injectedConfigText();
436
652
  if (cur !== null) return shape(rest, cur);
437
653
  }
654
+ // D3 \u6362\u8F68\uFF1ARegistry \u76F4\u8BFB\u771F\u5B9E provider_config.json \u2192 merge(\u771F\u5B9E, \u526F\u672C) \u89C6\u56FE
655
+ if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
656
+ const cur = mergedProviderConfigText();
657
+ if (cur !== null) return shape(rest, cur);
658
+ }
438
659
  return fs.__origReadFileSync.call(fs, p, ...rest);
439
660
  };
440
661
  fs.promises.__origReadFile = fs.promises.readFile;
@@ -443,17 +664,27 @@ if (text !== null) {
443
664
  const cur = injectedConfigText();
444
665
  if (cur !== null) return Promise.resolve(shape(rest, cur));
445
666
  }
667
+ if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH) {
668
+ const cur = mergedProviderConfigText();
669
+ if (cur !== null) return Promise.resolve(shape(rest, cur));
670
+ }
446
671
  return fs.promises.__origReadFile.call(fs.promises, p, ...rest);
447
672
  };
448
673
  // existsSync \u62E6\u622A\uFF1A\u771F\u5B9E bundle \u7684\u7528\u6237 config \u8BFB\u53D6\uFF08loadFileConfig\uFF09\u4EE5 existsSync
449
674
  // \u4E3A\u77ED\u8DEF\u95E8\u2014\u2014\u6587\u4EF6\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u7A7A config \u4E14 readFileSync \u4E0D\u88AB\u8C03\u7528\uFF0CGUI-only
450
- // \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
675
+ // \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
676
+ // D3 \u6362\u8F68\uFF1A\u771F\u5B9E provider_config.json \u7684\u5B58\u5728\u6027 = \u771F\u5B9E\u6216\u526F\u672C\u4EFB\u4E00\u5B58\u5728\u5373 true
677
+ //\uFF08\u771F\u5B9E\u7F3A\u5931 + \u526F\u672C\u5B58\u5728\u65F6 Registry \u7684 existsSync \u95E8\u4E0D\u5F97\u62E6\u6389 merge \u89C6\u56FE\u8BFB\u53D6\uFF09
451
678
  fs.__origExistsSync = fs.existsSync;
452
679
  fs.existsSync = function (p) {
453
680
  if (typeof p === 'string' && p === CONFIG_PATH) {
454
681
  const cur = injectedConfigText();
455
682
  if (cur !== null) return true;
456
683
  }
684
+ if (typeof p === 'string' && p === REAL_PROVIDER_CONFIG_PATH && PI_SYNCED_PATH) {
685
+ if (fs.__origExistsSync.call(fs, REAL_PROVIDER_CONFIG_PATH)) return true;
686
+ return fs.__origExistsSync.call(fs, PI_SYNCED_PATH);
687
+ }
457
688
  return fs.__origExistsSync.call(fs, p);
458
689
  };
459
690
  }
@@ -548,7 +779,7 @@ function ensureAppServerLauncher(engineDataDir) {
548
779
  fs2.writeFileSync(tmp, APPSERVER_LAUNCHER_SOURCE);
549
780
  fs2.renameSync(tmp, file);
550
781
  } catch (err) {
551
- const reason = (0, import_subagent_engine_sdk4.toErrorMessage)(err);
782
+ const reason = (0, import_subagent_engine_sdk5.toErrorMessage)(err);
552
783
  throw new Error(
553
784
  `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`
554
785
  );
@@ -806,21 +1037,21 @@ async function readZcodeSessionView(dbPath, sessionId) {
806
1037
  var fs4 = __toESM(require("fs"), 1);
807
1038
  var import_node_path = require("path");
808
1039
  var import_node_os = require("os");
809
- var import_subagent_engine_sdk7 = require("@zhushanwen/subagent-engine-sdk");
1040
+ var import_subagent_engine_sdk8 = require("@zhushanwen/subagent-engine-sdk");
810
1041
 
811
1042
  // src/logs/stderr-rotation.ts
812
- var import_subagent_engine_sdk5 = require("@zhushanwen/subagent-engine-sdk");
813
1043
  var import_subagent_engine_sdk6 = require("@zhushanwen/subagent-engine-sdk");
1044
+ var import_subagent_engine_sdk7 = require("@zhushanwen/subagent-engine-sdk");
814
1045
  var ZCODE_STDERR_LOG_PREFIX = "zcode-appserver-stderr-";
815
1046
  function stderrLogPathFor(engineDataDir, pid) {
816
- return (0, import_subagent_engine_sdk5.stderrLogPathFor)(engineDataDir, pid, ZCODE_STDERR_LOG_PREFIX);
1047
+ return (0, import_subagent_engine_sdk6.stderrLogPathFor)(engineDataDir, pid, ZCODE_STDERR_LOG_PREFIX);
817
1048
  }
818
1049
  function cleanupSiblingStderrLogs(logPath, env, now) {
819
- return (0, import_subagent_engine_sdk5.cleanupSiblingStderrLogs)(logPath, env, ZCODE_STDERR_LOG_PREFIX, now);
1050
+ return (0, import_subagent_engine_sdk6.cleanupSiblingStderrLogs)(logPath, env, ZCODE_STDERR_LOG_PREFIX, now);
820
1051
  }
821
1052
 
822
1053
  // src/connection.ts
823
- var logger = (0, import_subagent_engine_sdk7.getLogger)("subagents");
1054
+ var logger = (0, import_subagent_engine_sdk8.getLogger)("subagents");
824
1055
  var RAW_FRAME_LOG_CHARS = 200;
825
1056
  var RUNTIME_PREFERENCES = Object.freeze({
826
1057
  nativeSearchEnhancementsEnabled: true,
@@ -842,11 +1073,11 @@ function frameIdOf(frame) {
842
1073
  return typeof id === "string" || typeof id === "number" ? id : void 0;
843
1074
  }
844
1075
  function errMessage(err) {
845
- return (0, import_subagent_engine_sdk4.toErrorMessage)(err);
1076
+ return (0, import_subagent_engine_sdk5.toErrorMessage)(err);
846
1077
  }
847
1078
  function buildAppServerEnv(baseEnv = process.env) {
848
1079
  return {
849
- ...(0, import_subagent_engine_sdk7.buildNestedSpawnEnv)(baseEnv),
1080
+ ...(0, import_subagent_engine_sdk8.buildNestedSpawnEnv)(baseEnv),
850
1081
  ZCODE_MODEL_TELEMETRY_ENABLED: "false"
851
1082
  };
852
1083
  }
@@ -996,7 +1227,7 @@ var AppServerConnection = class {
996
1227
  close() {
997
1228
  const child = this.child;
998
1229
  if (child === null || this.killChainPromise !== void 0) return;
999
- this.killChainPromise = (0, import_subagent_engine_sdk7.killChain)(child, { graceMs: ZCODE_KILL_GRACE_MS });
1230
+ this.killChainPromise = (0, import_subagent_engine_sdk8.killChain)(child, { graceMs: ZCODE_KILL_GRACE_MS });
1000
1231
  }
1001
1232
  /**
1002
1233
  * 异步完整关闭面:SIGTERM → grace → SIGKILL 杀链走完(含收尸),resolve 于进程
@@ -1008,7 +1239,7 @@ var AppServerConnection = class {
1008
1239
  if (this.killChainPromise === void 0) {
1009
1240
  const child = this.child;
1010
1241
  if (child === null) return;
1011
- this.killChainPromise = (0, import_subagent_engine_sdk7.killChain)(child, { graceMs: opts?.graceMs ?? ZCODE_KILL_GRACE_MS });
1242
+ this.killChainPromise = (0, import_subagent_engine_sdk8.killChain)(child, { graceMs: opts?.graceMs ?? ZCODE_KILL_GRACE_MS });
1012
1243
  }
1013
1244
  await this.killChainPromise;
1014
1245
  }
@@ -1027,10 +1258,10 @@ var AppServerConnection = class {
1027
1258
  this.generation += 1;
1028
1259
  const gen = this.generation;
1029
1260
  const script = this.launcherScript ?? this.cliPath;
1030
- const child = (0, import_subagent_engine_sdk7.spawnEngineChild)({
1261
+ const child = (0, import_subagent_engine_sdk8.spawnEngineChild)({
1031
1262
  command: this.nodeBin,
1032
1263
  args: [script, "app-server", "--cwd", this.cwd],
1033
- env: (0, import_subagent_engine_sdk7.buildEngineChildEnv)(this.env, {
1264
+ env: (0, import_subagent_engine_sdk8.buildEngineChildEnv)(this.env, {
1034
1265
  // L0 TAIJI_AGENT_DATA_DIR 缺省链:显式传参 > 宿主注入 env > tmpdir 占位
1035
1266
  //(app-server 不消费该键,占位仅满足 L0 必注入契约;生产调用方
1036
1267
  // zcode-engine.ensureAppServerRuntime 恒传 engineDataDir)。
@@ -1068,7 +1299,7 @@ var AppServerConnection = class {
1068
1299
  }
1069
1300
  }
1070
1301
  };
1071
- (0, import_subagent_engine_sdk7.pumpNdjsonLines)(child.stdout, (line) => this.handleLine(line));
1302
+ (0, import_subagent_engine_sdk8.pumpNdjsonLines)(child.stdout, (line) => this.handleLine(line));
1072
1303
  child.stderr?.setEncoding("utf8");
1073
1304
  child.stderr?.on("data", (chunk) => {
1074
1305
  this.stderrTail = (this.stderrTail + chunk).slice(-ZCODE_APPSERVER_STDERR_TAIL_BUFFER_CHARS);
@@ -1209,8 +1440,8 @@ var AppServerConnection = class {
1209
1440
  }
1210
1441
  this.stderrStream.write(chunk);
1211
1442
  if (this.activeStderrLogPath !== null) {
1212
- const params = (0, import_subagent_engine_sdk6.stderrRotationParams)(process.env);
1213
- if ((0, import_subagent_engine_sdk6.rotateStderrLogIfNeeded)(this.activeStderrLogPath, params)) {
1443
+ const params = (0, import_subagent_engine_sdk7.stderrRotationParams)(process.env);
1444
+ if ((0, import_subagent_engine_sdk7.rotateStderrLogIfNeeded)(this.activeStderrLogPath, params)) {
1214
1445
  this.closeStderrStream();
1215
1446
  }
1216
1447
  }
@@ -1228,8 +1459,8 @@ var AppServerConnection = class {
1228
1459
 
1229
1460
  // src/session-channel.ts
1230
1461
  var import_node_crypto = require("crypto");
1231
- var import_subagent_engine_sdk8 = require("@zhushanwen/subagent-engine-sdk");
1232
- var logger2 = (0, import_subagent_engine_sdk8.getLogger)("subagents");
1462
+ var import_subagent_engine_sdk9 = require("@zhushanwen/subagent-engine-sdk");
1463
+ var logger2 = (0, import_subagent_engine_sdk9.getLogger)("subagents");
1233
1464
  var SUBSCRIBE_DELIVERY_KIND = "desktop-continuous";
1234
1465
  var WORKSPACE_KEY_HASH_CHARS = 16;
1235
1466
  var CREATE_REPLY_LOG_CHARS = 300;
@@ -1238,7 +1469,7 @@ function isRecord3(v) {
1238
1469
  return typeof v === "object" && v !== null && !Array.isArray(v);
1239
1470
  }
1240
1471
  function errMessage2(err) {
1241
- return (0, import_subagent_engine_sdk4.toErrorMessage)(err);
1472
+ return (0, import_subagent_engine_sdk5.toErrorMessage)(err);
1242
1473
  }
1243
1474
  function stableWorkspaceKey(workspacePath) {
1244
1475
  return "ws-" + (0, import_node_crypto.createHash)("sha256").update(workspacePath).digest("hex").slice(0, WORKSPACE_KEY_HASH_CHARS);
@@ -1765,8 +1996,8 @@ var SessionChannel = class {
1765
1996
 
1766
1997
  // src/session-db-maintenance.ts
1767
1998
  var fs5 = __toESM(require("fs"), 1);
1768
- var import_subagent_engine_sdk9 = require("@zhushanwen/subagent-engine-sdk");
1769
- var logger3 = (0, import_subagent_engine_sdk9.getLogger)("subagents");
1999
+ var import_subagent_engine_sdk10 = require("@zhushanwen/subagent-engine-sdk");
2000
+ var logger3 = (0, import_subagent_engine_sdk10.getLogger)("subagents");
1770
2001
  var ZCODE_SESSION_TTL_MS = 2592e6;
1771
2002
  var ZCODE_SESSION_SWEEP_INTERVAL_MS = 864e5;
1772
2003
  var SWEEP_BUSY_TIMEOUT_MS = 5e3;
@@ -1922,7 +2153,7 @@ function maybeSweepExpiredZcodeSessions(dbPath, opts = {}) {
1922
2153
  }
1923
2154
 
1924
2155
  // src/zcode-engine.ts
1925
- var logger4 = (0, import_subagent_engine_sdk10.getLogger)("subagents");
2156
+ var logger4 = (0, import_subagent_engine_sdk11.getLogger)("subagents");
1926
2157
  var PROBE_VERSION_TIMEOUT_MS = 15e3;
1927
2158
  var COMMON_THOUGHT_LEVELS = ["low", "high", "max"];
1928
2159
  var ZcodeEngine = class {
@@ -1971,7 +2202,10 @@ var ZcodeEngine = class {
1971
2202
  // --mode build/edit/plan/yolo 原生权限档位
1972
2203
  permissionMode: "native",
1973
2204
  // [D3-④] 无 turn_end 语义,轮数上限不可兑现(预检 gate 据此同步拒绝)
1974
- maxTurns: false
2205
+ maxTurns: false,
2206
+ // [subagent-model-switch] zcode 引擎不在模型切换设计范围(协议面引擎中立预留,
2207
+ // 后续另立项接入)——setModel 通路未接通,unsupported 如实声明
2208
+ setModel: "unsupported"
1975
2209
  };
1976
2210
  }
1977
2211
  /** 探针(D7):二进制存在 + 版本解析(zcode 无公开契约,版本漂移的入口信号)。 */
@@ -2288,6 +2522,7 @@ var ZcodeEngine = class {
2288
2522
  const env = buildAppServerEnv(this.deps.processEnv ?? process.env);
2289
2523
  env.ZCODE_ENG_CLI_PATH = cliPath;
2290
2524
  env.ZCODE_ENG_V2_CONFIG = this.deps.sources?.v2ConfigPath ?? defaultV2ConfigPath();
2525
+ env.ZCODE_ENG_PROVIDER_CONFIG = resolvePersonalProviderConfigPath(this.deps.sources, engineDataDir);
2291
2526
  const sessionDbPath = zcodeSessionDbPath(engineDataDir);
2292
2527
  env.ZCODE_SESSION_DB_PATH = sessionDbPath;
2293
2528
  delete env.ZCODE_SESSION_DB;
@@ -2384,7 +2619,7 @@ var ZcodeEngine = class {
2384
2619
  /** abort 合成终态:exitCode=null(record 正常收尾,不留僵尸)。 */
2385
2620
  applyAbortedOutcome(outcome, task, ctx, final, emit) {
2386
2621
  outcome.exitCode = null;
2387
- 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)}`;
2622
+ 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)}`;
2388
2623
  emit({ type: "error", message: outcome.error });
2389
2624
  }
2390
2625
  /**
@@ -2489,7 +2724,7 @@ var ZcodeEngine = class {
2489
2724
  }
2490
2725
  } else {
2491
2726
  const poolDir = path4.resolve(
2492
- (0, import_subagent_engine_sdk11.resolvePoolDir)(this.deps.engineDataDir(), ZCODE_ENGINE_ID, import_subagent_engine_sdk11.SHARED_POOL_KEY)
2727
+ (0, import_subagent_engine_sdk12.resolvePoolDir)(this.deps.engineDataDir(), ZCODE_ENGINE_ID, import_subagent_engine_sdk12.SHARED_POOL_KEY)
2493
2728
  );
2494
2729
  const resolved = path4.resolve(poolDir, dbPathRaw);
2495
2730
  if (resolved.startsWith(poolDir + path4.sep)) {
@@ -2507,7 +2742,7 @@ var ZcodeEngine = class {
2507
2742
  logger4.warn("[zcode-engine] native session read failed, degrade to journal replay", {
2508
2743
  dbPath,
2509
2744
  sessionId,
2510
- reason: (0, import_subagent_engine_sdk4.toErrorMessage)(err)
2745
+ reason: (0, import_subagent_engine_sdk5.toErrorMessage)(err)
2511
2746
  });
2512
2747
  }
2513
2748
  }
@@ -2594,7 +2829,7 @@ var ZcodeEngine = class {
2594
2829
  buildPrompt(task, schema) {
2595
2830
  const segments = [...task.appendSystemPrompt ?? []];
2596
2831
  segments.push(task.prompt);
2597
- if (schema !== void 0) segments.push((0, import_subagent_engine_sdk11.buildSchemaEmulationSegment)(schema));
2832
+ if (schema !== void 0) segments.push((0, import_subagent_engine_sdk12.buildSchemaEmulationSegment)(schema));
2598
2833
  return segments.join("\n\n");
2599
2834
  }
2600
2835
  };
@@ -2637,7 +2872,7 @@ function isPlainObject(v) {
2637
2872
  return typeof v === "object" && v !== null && !Array.isArray(v);
2638
2873
  }
2639
2874
  function errMessage3(err) {
2640
- return (0, import_subagent_engine_sdk4.toErrorMessage)(err);
2875
+ return (0, import_subagent_engine_sdk5.toErrorMessage)(err);
2641
2876
  }
2642
2877
  function resolveAppserverTimingMs(envName, fallbackMs, label) {
2643
2878
  const raw = process.env[envName];
@@ -2749,7 +2984,7 @@ function parsedAppServerAttempt(task, r) {
2749
2984
  kind: "parsed",
2750
2985
  output: syntheticAppServerOutput(0),
2751
2986
  payload: turnResultToPayload(r),
2752
- ...schema !== void 0 ? { schemaResult: (0, import_subagent_engine_sdk11.extractAndValidateStructuredOutput)(r.response, schema) } : {}
2987
+ ...schema !== void 0 ? { schemaResult: (0, import_subagent_engine_sdk12.extractAndValidateStructuredOutput)(r.response, schema) } : {}
2753
2988
  };
2754
2989
  }
2755
2990
  function failedTerminalAppServerAttempt(r) {
@@ -2787,16 +3022,16 @@ function failedAppServerAttempt(err, currentSessionId, opts = {}) {
2787
3022
  };
2788
3023
  }
2789
3024
  function isHostTimeoutAbort(ctx) {
2790
- return ctx.signal?.aborted === true && ctx.signal.reason === import_subagent_engine_sdk11.HOST_TIMEOUT_ABORT_REASON;
3025
+ return ctx.signal?.aborted === true && ctx.signal.reason === import_subagent_engine_sdk12.HOST_TIMEOUT_ABORT_REASON;
2791
3026
  }
2792
3027
  var PROBE_STDOUT_CAP_CHARS = 4096;
2793
3028
  async function defaultProbeVersion(cliPath, dataDir) {
2794
3029
  try {
2795
3030
  return await new Promise((resolve2, reject) => {
2796
- const child = (0, import_subagent_engine_sdk11.spawnEngineChild)({
3031
+ const child = (0, import_subagent_engine_sdk12.spawnEngineChild)({
2797
3032
  command: "node",
2798
3033
  args: [cliPath, "--version"],
2799
- env: (0, import_subagent_engine_sdk11.buildEngineChildEnv)(process.env, { dataDir }),
3034
+ env: (0, import_subagent_engine_sdk12.buildEngineChildEnv)(process.env, { dataDir }),
2800
3035
  stdout: "pipe",
2801
3036
  stderr: "ignore",
2802
3037
  signal: AbortSignal.timeout(PROBE_VERSION_TIMEOUT_MS)
@@ -2814,7 +3049,7 @@ async function defaultProbeVersion(cliPath, dataDir) {
2814
3049
  });
2815
3050
  } catch (err) {
2816
3051
  logger4.debug(
2817
- `[zcode-engine] probe version check failed (best-effort continue): ${(0, import_subagent_engine_sdk4.toErrorMessage)(err)}`
3052
+ `[zcode-engine] probe version check failed (best-effort continue): ${(0, import_subagent_engine_sdk5.toErrorMessage)(err)}`
2818
3053
  );
2819
3054
  return void 0;
2820
3055
  }
@@ -2822,7 +3057,7 @@ async function defaultProbeVersion(cliPath, dataDir) {
2822
3057
 
2823
3058
  // src/registration.ts
2824
3059
  function defaultEngineDataDir() {
2825
- return (0, import_subagent_engine_sdk12.resolveEngineDataDir)(process.env);
3060
+ return (0, import_subagent_engine_sdk13.resolveEngineDataDir)(process.env);
2826
3061
  }
2827
3062
  function createZcodeEngine(deps) {
2828
3063
  return new ZcodeEngine(deps);
@@ -2835,11 +3070,11 @@ function createDefaultZcodeEngine() {
2835
3070
  }
2836
3071
 
2837
3072
  // src/port-types.ts
2838
- var import_subagent_engine_sdk13 = require("@zhushanwen/subagent-engine-sdk");
3073
+ var import_subagent_engine_sdk14 = require("@zhushanwen/subagent-engine-sdk");
2839
3074
 
2840
3075
  // src/server.ts
2841
3076
  var import_server = require("@zhushanwen/subagent-engine-sdk/server");
2842
- var logger5 = (0, import_subagent_engine_sdk14.getLogger)("subagents");
3077
+ var logger5 = (0, import_subagent_engine_sdk15.getLogger)("subagents");
2843
3078
  var EngineProtocolServer = class {
2844
3079
  write;
2845
3080
  engine;
@@ -2909,7 +3144,7 @@ var EngineProtocolServer = class {
2909
3144
  const active = { controller, seq: 0 };
2910
3145
  this.activeRuns.set(runId, active);
2911
3146
  const fullTask = (0, import_server.assembleFullTask)(task, ctx);
2912
- const ctxModel = (0, import_subagent_engine_sdk13.parseCtxModel)(ctx.ctxModel);
3147
+ const ctxModel = (0, import_subagent_engine_sdk14.parseCtxModel)(ctx.ctxModel);
2913
3148
  const stream = ctx.streamMode === "stream" ? {
2914
3149
  onDelta: (delta) => {
2915
3150
  void this.reverseRequestInternal("host/streamDelta", { runId, delta }).catch(this.warnReverseFailure("host/streamDelta", `run ${runId}`));
@@ -2945,7 +3180,7 @@ var EngineProtocolServer = class {
2945
3180
  }
2946
3181
  validateModel(params) {
2947
3182
  if (this.engine.validateModel === void 0) {
2948
- throw new import_subagent_engine_sdk14.EngineSdkError(
3183
+ throw new import_subagent_engine_sdk15.EngineSdkError(
2949
3184
  "engine_capability_unsupported",
2950
3185
  "engine does not implement validateModel",
2951
3186
  "Manifest omits modelCatalog; model validation falls back to run-time engine checks."
@@ -2972,7 +3207,7 @@ var EngineProtocolServer = class {
2972
3207
  warnReverseFailure(method, context) {
2973
3208
  return (err) => {
2974
3209
  logger5.warn(`[protocol] ${method} reverse request failed (${context}); continuing without it`, {
2975
- detail: (0, import_subagent_engine_sdk4.toErrorMessage)(err)
3210
+ detail: (0, import_subagent_engine_sdk5.toErrorMessage)(err)
2976
3211
  });
2977
3212
  };
2978
3213
  }
@@ -3001,7 +3236,7 @@ var EngineProtocolServer = class {
3001
3236
  clearTimeout(pending.timer);
3002
3237
  this.reverseClock?.acked(String(id));
3003
3238
  this.reverseClock?.settled(String(id));
3004
- if (frame.error !== void 0) pending.reject(new Error(`reverse request ${String(id)} rejected: ${(0, import_subagent_engine_sdk4.toErrorMessage)(frame.error)}`));
3239
+ if (frame.error !== void 0) pending.reject(new Error(`reverse request ${String(id)} rejected: ${(0, import_subagent_engine_sdk5.toErrorMessage)(frame.error)}`));
3005
3240
  else pending.resolve(frame.result);
3006
3241
  }
3007
3242
  };
@@ -3014,8 +3249,8 @@ function toProtocolError(err) {
3014
3249
  }
3015
3250
 
3016
3251
  // src/main.ts
3017
- var clock = (0, import_subagent_engine_sdk15.armEngineSelfDestruct)({ stdin: process.stdin });
3018
- (0, import_subagent_engine_sdk15.runEngineCliEntry)({
3252
+ var clock = (0, import_subagent_engine_sdk16.armEngineSelfDestruct)({ stdin: process.stdin });
3253
+ (0, import_subagent_engine_sdk16.runEngineCliEntry)({
3019
3254
  component: "zcode-engine-cli",
3020
3255
  server: new EngineProtocolServer({
3021
3256
  write: (frame) => {