@dotobokuri/fleet-cli 1.9.0 → 1.10.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.js CHANGED
@@ -29321,6 +29321,7 @@ __export(typebox_exports, {
29321
29321
 
29322
29322
  // ../../packages/fleet-carriers/dist/index.js
29323
29323
  init_dist2();
29324
+ import path23 from "path";
29324
29325
  init_dist2();
29325
29326
  init_dist();
29326
29327
  var __defProp2 = Object.defineProperty;
@@ -29515,11 +29516,11 @@ function sanitizeCarriersMap(value) {
29515
29516
  return result;
29516
29517
  }
29517
29518
  var TASK_FORCE_POOL_KEY_PATTERN = /(?:^|:)taskforce:[^:]+:([^:]+)$/;
29518
- function buildCarrierExecutorPoolKey(carrierId, originSessionId) {
29519
- return namespacePoolKey(carrierId, originSessionId);
29519
+ function buildCarrierExecutorPoolKey(carrierId, originSessionId, cwd) {
29520
+ return namespacePoolKey(carrierId, joinSessionCwdNamespace(originSessionId, cwd));
29520
29521
  }
29521
- function buildTaskForceExecutorPoolKey(carrierId, cliType, originSessionId) {
29522
- return namespacePoolKey(buildTaskForceRunId(carrierId, cliType), originSessionId);
29522
+ function buildTaskForceExecutorPoolKey(carrierId, cliType, originSessionId, cwd) {
29523
+ return namespacePoolKey(buildTaskForceRunId(carrierId, cliType), joinSessionCwdNamespace(originSessionId, cwd));
29523
29524
  }
29524
29525
  function buildTaskForceRunId(carrierId, cliType) {
29525
29526
  const encodedCarrierId = Buffer.from(carrierId, "utf-8").toString("base64url");
@@ -29534,6 +29535,11 @@ function matchesCarrierPoolKey(poolKey, carrierId) {
29534
29535
  function namespacePoolKey(baseKey, originSessionId) {
29535
29536
  return originSessionId ? `${originSessionId}:${baseKey}` : baseKey;
29536
29537
  }
29538
+ function joinSessionCwdNamespace(originSessionId, cwd) {
29539
+ const cwdNamespace = cwd ? `cwd-${Buffer.from(cwd, "utf-8").toString("base64url")}` : void 0;
29540
+ if (originSessionId && cwdNamespace) return `${originSessionId}:${cwdNamespace}`;
29541
+ return originSessionId ?? cwdNamespace;
29542
+ }
29537
29543
  async function disconnectCarrierExecutorPools(carrierId) {
29538
29544
  const poolKeys = new Set(listActivePoolKeys().filter((poolKey) => matchesCarrierPoolKey(poolKey, carrierId)));
29539
29545
  poolKeys.add(carrierId);
@@ -32338,7 +32344,7 @@ function escapeRegExp(str) {
32338
32344
  }
32339
32345
  var taskForceStateStore = /* @__PURE__ */ new Map();
32340
32346
  function launchTaskForceJob(options2) {
32341
- const { registry: registry4, carrierId, request, label, startedAt, toolName, ctx, deps } = options2;
32347
+ const { registry: registry4, carrierId, request, label, startedAt, toolName, ctx, cwd, deps } = options2;
32342
32348
  const requestKey = buildTaskForceRequestKey(carrierId, request);
32343
32349
  const backendIds = getConfiguredTaskForceBackends(carrierId);
32344
32350
  assertRegisteredCarrier(registry4, carrierId);
@@ -32391,7 +32397,7 @@ function launchTaskForceJob(options2) {
32391
32397
  request,
32392
32398
  state,
32393
32399
  signal: launch.signal,
32394
- cwd: ctx.cwd,
32400
+ cwd,
32395
32401
  permit: launch.permit,
32396
32402
  startedAt,
32397
32403
  toolName,
@@ -32483,7 +32489,7 @@ function getRequiredTaskForceModelConfig(carrierId, cliType) {
32483
32489
  async function runTaskForceBackend(registry4, cliType, carrierId, originSessionId, requestKey, request, state, signal, cwd, jobId, trackModelInfoByCli, deps) {
32484
32490
  const execStartedAt = Date.now();
32485
32491
  const progress = state.backends.get(cliType);
32486
- const poolKey = buildTaskForceExecutorPoolKey(carrierId, cliType, originSessionId);
32492
+ const poolKey = buildTaskForceExecutorPoolKey(carrierId, cliType, originSessionId, cwd);
32487
32493
  const streamKey = buildTaskForceScopedRunId(requestKey, cliType);
32488
32494
  const modelInfo = trackModelInfoByCli.get(cliType);
32489
32495
  if (!modelInfo) throw new Error(`Task Force config missing for ${cliType} on carrier "${carrierId}".`);
@@ -32688,7 +32694,8 @@ function buildCarrierDispatchToolSpec(registry4, deps) {
32688
32694
  CARRIER_REQUEST_BREVITY_GUIDELINE
32689
32695
  ],
32690
32696
  guardrails: [
32691
- `Multiple agents may be working on this codebase at the same time on a single filesystem and branch. Only touch changes you made \u2014 never revert or overwrite modifications made by others. Prefer precise edits (edit) over full-file writes (write). Always re-read a file before modifying it, as it may have changed since your last read.`
32697
+ `Multiple agents may be working on this codebase at the same time on a single filesystem and branch. Only touch changes you made \u2014 never revert or overwrite modifications made by others. Prefer precise edits (edit) over full-file writes (write). Always re-read a file before modifying it, as it may have changed since your last read.`,
32698
+ `When the carrier must work in a directory other than the host session cwd (e.g. a git worktree checkout), pass cwd as an absolute path so the carrier's CLI spawns there; never pass a relative path. Omit cwd to use the host session cwd.`
32692
32699
  ],
32693
32700
  get parameters() {
32694
32701
  const carrierIds = getRegisteredOrder(registry4);
@@ -32702,12 +32709,14 @@ function buildCarrierDispatchToolSpec(registry4, deps) {
32702
32709
  }),
32703
32710
  request: typebox_exports.String({
32704
32711
  description: `The task/prompt to send to the carrier. Required blocks per carrier -- see <fleet section="roster">. Missing blocks cause hard-error rejection.`
32705
- })
32712
+ }),
32713
+ cwd: typebox_exports.Optional(typebox_exports.String({
32714
+ description: `Optional absolute working directory for the carrier's CLI spawn. MUST be an absolute path. Provide it when delegating work to a directory other than the host session cwd (e.g. a git worktree checkout) so the carrier spawns deterministically at that path. Omit to default to the host session cwd.`
32715
+ }))
32706
32716
  });
32707
32717
  },
32708
32718
  async execute(args, ctx) {
32709
32719
  const t0 = Date.now();
32710
- const cwd = ctx.cwd;
32711
32720
  const toolCallId = ctx.toolCallId ?? "";
32712
32721
  const jobId = buildCarrierJobId("carrier", toolCallId);
32713
32722
  const toolName = "carrier_dispatch";
@@ -32718,6 +32727,11 @@ function buildCarrierDispatchToolSpec(registry4, deps) {
32718
32727
  error: "Invalid arguments: carrier_id, label, and request must be non-empty strings."
32719
32728
  });
32720
32729
  }
32730
+ const cwdResolution = resolveDispatchCwd(args.cwd, ctx.cwd);
32731
+ if (!cwdResolution.ok) {
32732
+ return launchResponseResult({ job_id: jobId, accepted: false, error: cwdResolution.error });
32733
+ }
32734
+ const cwd = cwdResolution.cwd;
32721
32735
  const carrierId = args.carrier_id.trim();
32722
32736
  const label = args.label.trim();
32723
32737
  const request = args.request;
@@ -32750,6 +32764,7 @@ function buildCarrierDispatchToolSpec(registry4, deps) {
32750
32764
  startedAt: t0,
32751
32765
  toolName,
32752
32766
  ctx,
32767
+ cwd,
32753
32768
  deps
32754
32769
  });
32755
32770
  }
@@ -32862,7 +32877,7 @@ async function runSingleCarrier(opts) {
32862
32877
  });
32863
32878
  try {
32864
32879
  const execResult = await executeWithPool({
32865
- poolKey: buildCarrierExecutorPoolKey(opts.carrierId, opts.originSessionId),
32880
+ poolKey: buildCarrierExecutorPoolKey(opts.carrierId, opts.originSessionId, opts.cwd),
32866
32881
  scopeId: opts.carrierId,
32867
32882
  authEnvResolver: opts.deps.authEnvResolver,
32868
32883
  reservedExternalMcpServerIds: opts.deps.reservedExternalMcpServerIds,
@@ -32992,7 +33007,19 @@ function buildCarrierDispatchRunId(jobId, carrierId) {
32992
33007
  function isDispatchArgs(v) {
32993
33008
  if (typeof v !== "object" || v === null) return false;
32994
33009
  const obj = v;
32995
- return typeof obj.carrier_id === "string" && obj.carrier_id.trim().length > 0 && typeof obj.label === "string" && obj.label.trim().length > 0 && typeof obj.request === "string" && obj.request.trim().length > 0;
33010
+ return typeof obj.carrier_id === "string" && obj.carrier_id.trim().length > 0 && typeof obj.label === "string" && obj.label.trim().length > 0 && typeof obj.request === "string" && obj.request.trim().length > 0 && (obj.cwd === void 0 || typeof obj.cwd === "string");
33011
+ }
33012
+ function resolveDispatchCwd(rawCwd, fallbackCwd) {
33013
+ if (rawCwd === void 0) return { ok: true, cwd: fallbackCwd };
33014
+ const trimmed = rawCwd.trim();
33015
+ if (trimmed.length === 0) return { ok: true, cwd: fallbackCwd };
33016
+ if (!path23.isAbsolute(trimmed)) {
33017
+ return {
33018
+ ok: false,
33019
+ error: `Invalid cwd "${rawCwd}": must be an absolute path. Provide an absolute directory or omit cwd to use the host session cwd.`
33020
+ };
33021
+ }
33022
+ return { ok: true, cwd: trimmed };
32996
33023
  }
32997
33024
  function buildCarrierRoster(registry4, carrierIds, options2) {
32998
33025
  const { excludeCarrierIds, heading, preambleLines, extraLines } = options2 ?? {};
@@ -33185,7 +33212,7 @@ init_dist2();
33185
33212
  import crypto4 from "crypto";
33186
33213
  import { existsSync as existsSync32, lstatSync as lstatSync22, mkdtempSync, readFileSync as readFileSync32, readdirSync as readdirSync3, realpathSync as realpathSync4, renameSync as renameSync22, statSync as statSync2 } from "fs";
33187
33214
  import path52 from "path";
33188
- import path23 from "path";
33215
+ import path24 from "path";
33189
33216
  import { chmodSync as chmodSync3, closeSync as closeSync6, constants as constants7, lstatSync as lstatSync6, mkdirSync as mkdirSync5, openSync as openSync6, realpathSync as realpathSync2, rmSync as rmSync3, symlinkSync, writeFileSync as writeFileSync4 } from "fs";
33190
33217
  import path10 from "path";
33191
33218
  import { existsSync as existsSync22, readFileSync as readFileSync22, realpathSync as realpathSync3 } from "fs";
@@ -34031,11 +34058,11 @@ function renderAssetPluginRoot(pluginRoot, bundle, options2) {
34031
34058
  if (bundle.includeClaudeAgents) {
34032
34059
  for (const subagent of options2.claudeDefinitions) {
34033
34060
  const fileStem = parseClaudeAgentFileStem(subagent.name);
34034
- writePrivateFile(path23.join(pluginRoot, "agents", `${fileStem}.md`), claudeAgentFile(subagent), pluginRoot);
34061
+ writePrivateFile(path24.join(pluginRoot, "agents", `${fileStem}.md`), claudeAgentFile(subagent), pluginRoot);
34035
34062
  }
34036
34063
  }
34037
34064
  if (options2.cliId === "claude" || options2.cliId === "claude-kimi" || options2.cliId === "claude-glm") {
34038
- writePrivateJson(path23.join(pluginRoot, "hooks", "hooks.json"), claudeHooks(options2), pluginRoot);
34065
+ writePrivateJson(path24.join(pluginRoot, "hooks", "hooks.json"), claudeHooks(options2), pluginRoot);
34039
34066
  }
34040
34067
  }
34041
34068
  function validateClaudeAgentFileStems(subagents) {
@@ -34044,7 +34071,7 @@ function validateClaudeAgentFileStems(subagents) {
34044
34071
  }
34045
34072
  }
34046
34073
  function parseClaudeAgentFileStem(name) {
34047
- if (CLAUDE_AGENT_FILE_STEM_ALLOWLIST.test(name) && path23.basename(name) === name) return name;
34074
+ if (CLAUDE_AGENT_FILE_STEM_ALLOWLIST.test(name) && path24.basename(name) === name) return name;
34048
34075
  throw new Error(`Invalid Claude agent file name: ${name}`);
34049
34076
  }
34050
34077
  function claudeHooks(options2) {
@@ -34114,7 +34141,7 @@ function yamlScalar(value) {
34114
34141
  }
34115
34142
  function renderEmbeddedSkillAssets(pluginRoot) {
34116
34143
  for (const asset of EMBEDDED_AGENT_CLI_SKILL_ASSETS) {
34117
- writePrivateFile(path23.join(pluginRoot, "skills", asset.relativePath), asset.content, pluginRoot);
34144
+ writePrivateFile(path24.join(pluginRoot, "skills", asset.relativePath), asset.content, pluginRoot);
34118
34145
  }
34119
34146
  }
34120
34147
  var CONFIG_FILE_NAME = "config.toml";
@@ -40974,10 +41001,10 @@ function mergeDefs2(...defs) {
40974
41001
  function cloneDef2(schema) {
40975
41002
  return mergeDefs2(schema._zod.def);
40976
41003
  }
40977
- function getElementAtPath2(obj, path36) {
40978
- if (!path36)
41004
+ function getElementAtPath2(obj, path37) {
41005
+ if (!path37)
40979
41006
  return obj;
40980
- return path36.reduce((acc, key) => acc?.[key], obj);
41007
+ return path37.reduce((acc, key) => acc?.[key], obj);
40981
41008
  }
40982
41009
  function promiseAllObject2(promisesObj) {
40983
41010
  const keys = Object.keys(promisesObj);
@@ -41386,11 +41413,11 @@ function explicitlyAborted2(x, startIndex = 0) {
41386
41413
  }
41387
41414
  return false;
41388
41415
  }
41389
- function prefixIssues2(path36, issues) {
41416
+ function prefixIssues2(path37, issues) {
41390
41417
  return issues.map((iss) => {
41391
41418
  var _a32;
41392
41419
  (_a32 = iss).path ?? (_a32.path = []);
41393
- iss.path.unshift(path36);
41420
+ iss.path.unshift(path37);
41394
41421
  return iss;
41395
41422
  });
41396
41423
  }
@@ -41535,16 +41562,16 @@ function flattenError2(error512, mapper = (issue32) => issue32.message) {
41535
41562
  }
41536
41563
  function formatError4(error512, mapper = (issue32) => issue32.message) {
41537
41564
  const fieldErrors = { _errors: [] };
41538
- const processError = (error522, path36 = []) => {
41565
+ const processError = (error522, path37 = []) => {
41539
41566
  for (const issue32 of error522.issues) {
41540
41567
  if (issue32.code === "invalid_union" && issue32.errors.length) {
41541
- issue32.errors.map((issues) => processError({ issues }, [...path36, ...issue32.path]));
41568
+ issue32.errors.map((issues) => processError({ issues }, [...path37, ...issue32.path]));
41542
41569
  } else if (issue32.code === "invalid_key") {
41543
- processError({ issues: issue32.issues }, [...path36, ...issue32.path]);
41570
+ processError({ issues: issue32.issues }, [...path37, ...issue32.path]);
41544
41571
  } else if (issue32.code === "invalid_element") {
41545
- processError({ issues: issue32.issues }, [...path36, ...issue32.path]);
41572
+ processError({ issues: issue32.issues }, [...path37, ...issue32.path]);
41546
41573
  } else {
41547
- const fullpath = [...path36, ...issue32.path];
41574
+ const fullpath = [...path37, ...issue32.path];
41548
41575
  if (fullpath.length === 0) {
41549
41576
  fieldErrors._errors.push(mapper(issue32));
41550
41577
  } else {
@@ -41571,17 +41598,17 @@ function formatError4(error512, mapper = (issue32) => issue32.message) {
41571
41598
  }
41572
41599
  function treeifyError2(error512, mapper = (issue32) => issue32.message) {
41573
41600
  const result = { errors: [] };
41574
- const processError = (error522, path36 = []) => {
41601
+ const processError = (error522, path37 = []) => {
41575
41602
  var _a32, _b;
41576
41603
  for (const issue32 of error522.issues) {
41577
41604
  if (issue32.code === "invalid_union" && issue32.errors.length) {
41578
- issue32.errors.map((issues) => processError({ issues }, [...path36, ...issue32.path]));
41605
+ issue32.errors.map((issues) => processError({ issues }, [...path37, ...issue32.path]));
41579
41606
  } else if (issue32.code === "invalid_key") {
41580
- processError({ issues: issue32.issues }, [...path36, ...issue32.path]);
41607
+ processError({ issues: issue32.issues }, [...path37, ...issue32.path]);
41581
41608
  } else if (issue32.code === "invalid_element") {
41582
- processError({ issues: issue32.issues }, [...path36, ...issue32.path]);
41609
+ processError({ issues: issue32.issues }, [...path37, ...issue32.path]);
41583
41610
  } else {
41584
- const fullpath = [...path36, ...issue32.path];
41611
+ const fullpath = [...path37, ...issue32.path];
41585
41612
  if (fullpath.length === 0) {
41586
41613
  result.errors.push(mapper(issue32));
41587
41614
  continue;
@@ -41613,8 +41640,8 @@ function treeifyError2(error512, mapper = (issue32) => issue32.message) {
41613
41640
  }
41614
41641
  function toDotPath2(_path) {
41615
41642
  const segs = [];
41616
- const path36 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
41617
- for (const seg of path36) {
41643
+ const path37 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
41644
+ for (const seg of path37) {
41618
41645
  if (typeof seg === "number")
41619
41646
  segs.push(`[${seg}]`);
41620
41647
  else if (typeof seg === "symbol")
@@ -54135,13 +54162,13 @@ function resolveRef2(ref, ctx) {
54135
54162
  if (!ref.startsWith("#")) {
54136
54163
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
54137
54164
  }
54138
- const path36 = ref.slice(1).split("/").filter(Boolean);
54139
- if (path36.length === 0) {
54165
+ const path37 = ref.slice(1).split("/").filter(Boolean);
54166
+ if (path37.length === 0) {
54140
54167
  return ctx.rootSchema;
54141
54168
  }
54142
54169
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
54143
- if (path36[0] === defsKey) {
54144
- const key = path36[1];
54170
+ if (path37[0] === defsKey) {
54171
+ const key = path37[1];
54145
54172
  if (!key || !ctx.defs[key]) {
54146
54173
  throw new Error(`Reference not found: ${ref}`);
54147
54174
  }
@@ -67593,11 +67620,11 @@ function sanitizeCarriersMap2(value) {
67593
67620
  return result;
67594
67621
  }
67595
67622
  var TASK_FORCE_POOL_KEY_PATTERN2 = /(?:^|:)taskforce:[^:]+:([^:]+)$/;
67596
- function buildCarrierExecutorPoolKey2(carrierId, originSessionId) {
67597
- return namespacePoolKey2(carrierId, originSessionId);
67623
+ function buildCarrierExecutorPoolKey2(carrierId, originSessionId, cwd) {
67624
+ return namespacePoolKey2(carrierId, joinSessionCwdNamespace2(originSessionId, cwd));
67598
67625
  }
67599
- function buildTaskForceExecutorPoolKey2(carrierId, cliType, originSessionId) {
67600
- return namespacePoolKey2(buildTaskForceRunId2(carrierId, cliType), originSessionId);
67626
+ function buildTaskForceExecutorPoolKey2(carrierId, cliType, originSessionId, cwd) {
67627
+ return namespacePoolKey2(buildTaskForceRunId2(carrierId, cliType), joinSessionCwdNamespace2(originSessionId, cwd));
67601
67628
  }
67602
67629
  function buildTaskForceRunId2(carrierId, cliType) {
67603
67630
  const encodedCarrierId = Buffer.from(carrierId, "utf-8").toString("base64url");
@@ -67612,6 +67639,11 @@ function matchesCarrierPoolKey2(poolKey, carrierId) {
67612
67639
  function namespacePoolKey2(baseKey, originSessionId) {
67613
67640
  return originSessionId ? `${originSessionId}:${baseKey}` : baseKey;
67614
67641
  }
67642
+ function joinSessionCwdNamespace2(originSessionId, cwd) {
67643
+ const cwdNamespace = cwd ? `cwd-${Buffer.from(cwd, "utf-8").toString("base64url")}` : void 0;
67644
+ if (originSessionId && cwdNamespace) return `${originSessionId}:${cwdNamespace}`;
67645
+ return originSessionId ?? cwdNamespace;
67646
+ }
67615
67647
  async function disconnectCarrierExecutorPools2(carrierId) {
67616
67648
  const poolKeys = new Set(listActivePoolKeys2().filter((poolKey) => matchesCarrierPoolKey2(poolKey, carrierId)));
67617
67649
  poolKeys.add(carrierId);
@@ -70415,7 +70447,7 @@ function escapeRegExp2(str) {
70415
70447
  }
70416
70448
  var taskForceStateStore2 = /* @__PURE__ */ new Map();
70417
70449
  function launchTaskForceJob2(options2) {
70418
- const { registry: registry32, carrierId, request, label, startedAt, toolName, ctx, deps } = options2;
70450
+ const { registry: registry32, carrierId, request, label, startedAt, toolName, ctx, cwd, deps } = options2;
70419
70451
  const requestKey = buildTaskForceRequestKey2(carrierId, request);
70420
70452
  getConfiguredTaskForceBackends2(carrierId);
70421
70453
  assertRegisteredCarrier2(registry32, carrierId);
@@ -70468,7 +70500,7 @@ function launchTaskForceJob2(options2) {
70468
70500
  request,
70469
70501
  state,
70470
70502
  signal: launch.signal,
70471
- cwd: ctx.cwd,
70503
+ cwd,
70472
70504
  permit: launch.permit,
70473
70505
  startedAt,
70474
70506
  toolName,
@@ -70560,7 +70592,7 @@ function getRequiredTaskForceModelConfig2(carrierId, cliType) {
70560
70592
  async function runTaskForceBackend2(registry32, cliType, carrierId, originSessionId, requestKey, request, state, signal, cwd, jobId, trackModelInfoByCli, deps) {
70561
70593
  const execStartedAt = Date.now();
70562
70594
  const progress = state.backends.get(cliType);
70563
- const poolKey = buildTaskForceExecutorPoolKey2(carrierId, cliType, originSessionId);
70595
+ const poolKey = buildTaskForceExecutorPoolKey2(carrierId, cliType, originSessionId, cwd);
70564
70596
  buildTaskForceScopedRunId2(requestKey, cliType);
70565
70597
  const modelInfo = trackModelInfoByCli.get(cliType);
70566
70598
  if (!modelInfo) throw new Error(`Task Force config missing for ${cliType} on carrier "${carrierId}".`);
@@ -70765,7 +70797,8 @@ function buildCarrierDispatchToolSpec2(registry32, deps) {
70765
70797
  CARRIER_REQUEST_BREVITY_GUIDELINE2
70766
70798
  ],
70767
70799
  guardrails: [
70768
- `Multiple agents may be working on this codebase at the same time on a single filesystem and branch. Only touch changes you made \u2014 never revert or overwrite modifications made by others. Prefer precise edits (edit) over full-file writes (write). Always re-read a file before modifying it, as it may have changed since your last read.`
70800
+ `Multiple agents may be working on this codebase at the same time on a single filesystem and branch. Only touch changes you made \u2014 never revert or overwrite modifications made by others. Prefer precise edits (edit) over full-file writes (write). Always re-read a file before modifying it, as it may have changed since your last read.`,
70801
+ `When the carrier must work in a directory other than the host session cwd (e.g. a git worktree checkout), pass cwd as an absolute path so the carrier's CLI spawns there; never pass a relative path. Omit cwd to use the host session cwd.`
70769
70802
  ],
70770
70803
  get parameters() {
70771
70804
  const carrierIds = getRegisteredOrder2(registry32);
@@ -70779,12 +70812,14 @@ function buildCarrierDispatchToolSpec2(registry32, deps) {
70779
70812
  }),
70780
70813
  request: typebox_exports2.String({
70781
70814
  description: `The task/prompt to send to the carrier. Required blocks per carrier -- see <fleet section="roster">. Missing blocks cause hard-error rejection.`
70782
- })
70815
+ }),
70816
+ cwd: typebox_exports2.Optional(typebox_exports2.String({
70817
+ description: `Optional absolute working directory for the carrier's CLI spawn. MUST be an absolute path. Provide it when delegating work to a directory other than the host session cwd (e.g. a git worktree checkout) so the carrier spawns deterministically at that path. Omit to default to the host session cwd.`
70818
+ }))
70783
70819
  });
70784
70820
  },
70785
70821
  async execute(args, ctx) {
70786
70822
  const t0 = Date.now();
70787
- const cwd = ctx.cwd;
70788
70823
  const toolCallId = ctx.toolCallId ?? "";
70789
70824
  const jobId = buildCarrierJobId2("carrier", toolCallId);
70790
70825
  const toolName = "carrier_dispatch";
@@ -70795,6 +70830,11 @@ function buildCarrierDispatchToolSpec2(registry32, deps) {
70795
70830
  error: "Invalid arguments: carrier_id, label, and request must be non-empty strings."
70796
70831
  });
70797
70832
  }
70833
+ const cwdResolution = resolveDispatchCwd2(args.cwd, ctx.cwd);
70834
+ if (!cwdResolution.ok) {
70835
+ return launchResponseResult2({ job_id: jobId, accepted: false, error: cwdResolution.error });
70836
+ }
70837
+ const cwd = cwdResolution.cwd;
70798
70838
  const carrierId = args.carrier_id.trim();
70799
70839
  const label = args.label.trim();
70800
70840
  const request = args.request;
@@ -70827,6 +70867,7 @@ function buildCarrierDispatchToolSpec2(registry32, deps) {
70827
70867
  startedAt: t0,
70828
70868
  toolName,
70829
70869
  ctx,
70870
+ cwd,
70830
70871
  deps
70831
70872
  });
70832
70873
  }
@@ -70939,7 +70980,7 @@ async function runSingleCarrier2(opts) {
70939
70980
  });
70940
70981
  try {
70941
70982
  const execResult = await executeWithPool2({
70942
- poolKey: buildCarrierExecutorPoolKey2(opts.carrierId, opts.originSessionId),
70983
+ poolKey: buildCarrierExecutorPoolKey2(opts.carrierId, opts.originSessionId, opts.cwd),
70943
70984
  scopeId: opts.carrierId,
70944
70985
  authEnvResolver: opts.deps.authEnvResolver,
70945
70986
  reservedExternalMcpServerIds: opts.deps.reservedExternalMcpServerIds,
@@ -71069,7 +71110,19 @@ function buildCarrierDispatchRunId2(jobId, carrierId) {
71069
71110
  function isDispatchArgs2(v) {
71070
71111
  if (typeof v !== "object" || v === null) return false;
71071
71112
  const obj = v;
71072
- return typeof obj.carrier_id === "string" && obj.carrier_id.trim().length > 0 && typeof obj.label === "string" && obj.label.trim().length > 0 && typeof obj.request === "string" && obj.request.trim().length > 0;
71113
+ return typeof obj.carrier_id === "string" && obj.carrier_id.trim().length > 0 && typeof obj.label === "string" && obj.label.trim().length > 0 && typeof obj.request === "string" && obj.request.trim().length > 0 && (obj.cwd === void 0 || typeof obj.cwd === "string");
71114
+ }
71115
+ function resolveDispatchCwd2(rawCwd, fallbackCwd) {
71116
+ if (rawCwd === void 0) return { ok: true, cwd: fallbackCwd };
71117
+ const trimmed = rawCwd.trim();
71118
+ if (trimmed.length === 0) return { ok: true, cwd: fallbackCwd };
71119
+ if (!path92__default.isAbsolute(trimmed)) {
71120
+ return {
71121
+ ok: false,
71122
+ error: `Invalid cwd "${rawCwd}": must be an absolute path. Provide an absolute directory or omit cwd to use the host session cwd.`
71123
+ };
71124
+ }
71125
+ return { ok: true, cwd: trimmed };
71073
71126
  }
71074
71127
  function buildCarrierRoster2(registry32, carrierIds, options2) {
71075
71128
  const { excludeCarrierIds, heading, preambleLines, extraLines } = options2 ?? {};
@@ -71186,68 +71239,6 @@ function getClaudeModel2(config22) {
71186
71239
  function clampClaudeEffort2(effort) {
71187
71240
  return effort === "max" ? CLAUDE_MAX_EFFORT2 : effort;
71188
71241
  }
71189
- var ROLE_DESCRIPTION_SEPARATOR2 = " - ";
71190
- function readCarrierStatusEntries(registry32) {
71191
- const carrierDefaults = buildCarrierDefaultsByCarrier(registry32);
71192
- return buildCarrierStatusEntriesFromSnapshot(registry32, readFileBackedCarriersSnapshot2(carrierDefaults));
71193
- }
71194
- function buildCarrierStatusEntriesFromSnapshot(registry32, snapshot) {
71195
- const entries = [];
71196
- for (const carrierId of getRegisteredOrder2(registry32)) {
71197
- const config22 = getRegisteredCarrierConfig2(registry32, carrierId);
71198
- if (!config22) continue;
71199
- const state = snapshot.carriers[carrierId];
71200
- const cliType = snapshot.carriers[carrierId]?.agentCliType ?? config22.defaultCliType;
71201
- const selection = snapshot.carriers[carrierId]?.agentCli[cliType];
71202
- const provider = getProviderModels2(cliType);
71203
- const role = sanitizeCarrierMetadataText2(config22.carrierMetadata?.title);
71204
- const roleSummary = sanitizeCarrierMetadataText2(config22.carrierMetadata?.summary);
71205
- entries.push({
71206
- carrierId,
71207
- category: config22.carrierMetadata?.category,
71208
- cliType,
71209
- defaultCliType: config22.defaultCliType,
71210
- displayName: state?.displayName ?? getCarrierSourceDisplayName2(registry32, carrierId),
71211
- effort: selection?.effort ?? null,
71212
- isDefault: !selection?.model,
71213
- model: selection?.model || provider.defaultModel,
71214
- role,
71215
- roleDescription: buildRoleDescription2(role, roleSummary),
71216
- slot: config22.slot,
71217
- subagentMode: state?.agentMode === "subagent",
71218
- taskForceBackendCount: getConfiguredTaskForceBackendsFromSnapshot2(snapshot, carrierId).length
71219
- });
71220
- }
71221
- return entries;
71222
- }
71223
- function buildCarrierDefaultsByCarrier(registry32) {
71224
- return Object.fromEntries(
71225
- getRegisteredOrder2(registry32).map((carrierId) => {
71226
- const config22 = getRegisteredCarrierConfig2(registry32, carrierId);
71227
- if (!config22) return null;
71228
- return [carrierId, buildCarrierDefaults(config22)];
71229
- }).filter((entry) => entry !== null)
71230
- );
71231
- }
71232
- function buildCarrierDefaults(config22) {
71233
- const cliType = resolveAgentCliType22(config22.id, config22.defaultCliType);
71234
- const cliDefaults = buildCarrierModelDefaults2(config22, cliType);
71235
- return {
71236
- cliType,
71237
- ...config22.defaultAgentMode ? { defaultAgentMode: config22.defaultAgentMode } : {},
71238
- ...cliDefaults.defaultEffort ? { defaultEffort: cliDefaults.defaultEffort } : {},
71239
- ...cliDefaults.defaultModel ? { defaultModel: cliDefaults.defaultModel } : {}
71240
- };
71241
- }
71242
- function buildRoleDescription2(role, summary) {
71243
- if (role && summary) return `${role}${ROLE_DESCRIPTION_SEPARATOR2}${summary}`;
71244
- return role ?? summary;
71245
- }
71246
- function sanitizeCarrierMetadataText2(value) {
71247
- if (typeof value !== "string") return null;
71248
- const sanitized = sanitizeToolBlockLabel2(value).trim();
71249
- return sanitized.length > 0 ? sanitized : null;
71250
- }
71251
71242
  var dispatch2 = {
71252
71243
  ...framework_exports2,
71253
71244
  framework: framework_exports2,
@@ -79375,8 +79366,98 @@ function buildWikiToolSpec(config22, usage) {
79375
79366
  }
79376
79367
  };
79377
79368
  }
79369
+ var AGENT_CLI_API_CATALOG = [
79370
+ {
79371
+ method: "GET",
79372
+ path: "/agent-cli/state",
79373
+ summary: "\uC124\uCE58\uB41C Agent CLI \uC0C1\uD0DC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.",
79374
+ category: "Agent CLI",
79375
+ gate: "loopback"
79376
+ }
79377
+ ];
79378
+ function createAgentCliRouter(deps) {
79379
+ return async function handleAgentCliRoute(context) {
79380
+ const { req, res, pathname } = context;
79381
+ if (pathname === "/agent-cli/state") {
79382
+ if (req.method !== "GET") {
79383
+ deps.writeJson(res, 405, { error: "Method not allowed" });
79384
+ return true;
79385
+ }
79386
+ const clis = await deps.detect();
79387
+ const body = { clis };
79388
+ deps.writeJson(res, 200, body);
79389
+ return true;
79390
+ }
79391
+ return false;
79392
+ };
79393
+ }
79378
79394
  var SUBAGENT_CLI_TYPES = /* @__PURE__ */ new Set(["claude", "claude-zai", "claude-kimi", "claude-glm"]);
79379
79395
  var TASKFORCE_MIN_BACKENDS = 2;
79396
+ var CARRIER_SETTINGS_API_CATALOG = [
79397
+ {
79398
+ method: "GET",
79399
+ path: "/carrier-settings/state",
79400
+ summary: "\uCE90\uB9AC\uC5B4 \uC124\uC815 \uC0C1\uD0DC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.",
79401
+ category: "Carrier Settings",
79402
+ gate: "loopback"
79403
+ },
79404
+ {
79405
+ method: "GET",
79406
+ path: "/carrier-settings/options",
79407
+ summary: "\uCE90\uB9AC\uC5B4 \uC124\uC815 \uC120\uD0DD\uC9C0\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.",
79408
+ category: "Carrier Settings",
79409
+ gate: "loopback"
79410
+ },
79411
+ {
79412
+ method: "PUT",
79413
+ path: "/carrier-settings/carriers/:id/cli",
79414
+ summary: "\uCE90\uB9AC\uC5B4 Agent CLI\uB97C \uBCC0\uACBD\uD569\uB2C8\uB2E4.",
79415
+ category: "Carrier Settings",
79416
+ gate: "terminal-origin"
79417
+ },
79418
+ {
79419
+ method: "PUT",
79420
+ path: "/carrier-settings/carriers/:id/model",
79421
+ summary: "\uCE90\uB9AC\uC5B4 \uBAA8\uB378 \uC120\uD0DD\uC744 \uBCC0\uACBD\uD569\uB2C8\uB2E4.",
79422
+ category: "Carrier Settings",
79423
+ gate: "terminal-origin"
79424
+ },
79425
+ {
79426
+ method: "PATCH",
79427
+ path: "/carrier-settings/carriers/:id/display-name",
79428
+ summary: "\uCE90\uB9AC\uC5B4 \uD45C\uC2DC \uC774\uB984\uC744 \uBCC0\uACBD\uD569\uB2C8\uB2E4.",
79429
+ category: "Carrier Settings",
79430
+ gate: "terminal-origin"
79431
+ },
79432
+ {
79433
+ method: "PUT",
79434
+ path: "/carrier-settings/carriers/:id/agent-mode",
79435
+ summary: "\uCE90\uB9AC\uC5B4 \uC2E4\uD589 \uBAA8\uB4DC\uB97C \uBCC0\uACBD\uD569\uB2C8\uB2E4.",
79436
+ category: "Carrier Settings",
79437
+ gate: "terminal-origin"
79438
+ },
79439
+ {
79440
+ method: "PUT",
79441
+ path: "/carrier-settings/carriers/:id/taskforce/:cliType",
79442
+ summary: "Task Force \uBC31\uC5D4\uB4DC \uBAA8\uB378\uC744 \uC124\uC815\uD569\uB2C8\uB2E4.",
79443
+ category: "Carrier Settings",
79444
+ gate: "terminal-origin"
79445
+ },
79446
+ {
79447
+ method: "DELETE",
79448
+ path: "/carrier-settings/carriers/:id/taskforce/:cliType",
79449
+ summary: "Task Force \uBC31\uC5D4\uB4DC \uBAA8\uB378 \uC124\uC815\uC744 \uD574\uC81C\uD569\uB2C8\uB2E4.",
79450
+ category: "Carrier Settings",
79451
+ gate: "terminal-origin"
79452
+ },
79453
+ {
79454
+ method: "DELETE",
79455
+ path: "/carrier-settings/carriers/:id/taskforce",
79456
+ summary: "\uCE90\uB9AC\uC5B4 Task Force \uC124\uC815\uC744 \uCD08\uAE30\uD654\uD569\uB2C8\uB2E4.",
79457
+ category: "Carrier Settings",
79458
+ gate: "terminal-origin"
79459
+ }
79460
+ ];
79380
79461
  function createCarrierSettingsRouter(deps) {
79381
79462
  const controller = createStatusOverlayController(deps.registry);
79382
79463
  return async function handleCarrierSettingsRoute(context) {
@@ -79787,6 +79868,255 @@ function requireCarrierConfig(registry32, carrierId) {
79787
79868
  if (!config22) throw new Error(`Carrier not found: ${carrierId}`);
79788
79869
  return config22;
79789
79870
  }
79871
+ var GLOBAL_SETTINGS_API_CATALOG = [
79872
+ {
79873
+ method: "GET",
79874
+ path: "/global-settings/state",
79875
+ summary: "\uC804\uC5ED \uCF58\uC194 \uC124\uC815 \uC0C1\uD0DC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.",
79876
+ category: "Global Settings",
79877
+ gate: "loopback"
79878
+ },
79879
+ {
79880
+ method: "PUT",
79881
+ path: "/global-settings",
79882
+ summary: "\uC804\uC5ED \uCF58\uC194 \uC124\uC815\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4.",
79883
+ category: "Global Settings",
79884
+ gate: "terminal-origin"
79885
+ }
79886
+ ];
79887
+ function createGlobalSettingsRouter(deps) {
79888
+ return async function handleGlobalSettingsRoute(context) {
79889
+ const { req, res, pathname } = context;
79890
+ if (pathname === "/global-settings/state") {
79891
+ if (req.method !== "GET") {
79892
+ deps.writeJson(res, 405, { error: "Method not allowed" });
79893
+ return true;
79894
+ }
79895
+ deps.writeJson(res, 200, buildGlobalSettingsState(deps.globalOptionsService));
79896
+ return true;
79897
+ }
79898
+ if (pathname === "/global-settings") {
79899
+ if (req.method !== "PUT") {
79900
+ deps.writeJson(res, 405, { error: "Method not allowed" });
79901
+ return true;
79902
+ }
79903
+ await mutateGlobalSettings(req, res, deps);
79904
+ return true;
79905
+ }
79906
+ return false;
79907
+ };
79908
+ }
79909
+ function buildGlobalSettingsState(service) {
79910
+ return toGlobalSettingsState(service.load());
79911
+ }
79912
+ async function mutateGlobalSettings(req, res, deps) {
79913
+ if (!deps.isAuthorized(req)) {
79914
+ deps.writeJson(res, 401, { error: "unauthorized" });
79915
+ return;
79916
+ }
79917
+ if (!isJsonRequest2(req)) {
79918
+ deps.writeJson(res, 415, { error: "unsupported_media_type" });
79919
+ return;
79920
+ }
79921
+ const body = await deps.readJsonBody(req);
79922
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
79923
+ deps.writeJson(res, 400, { error: "invalid_json" });
79924
+ return;
79925
+ }
79926
+ if (body.replaceSystemPrompt !== void 0 && typeof body.replaceSystemPrompt !== "boolean") {
79927
+ deps.writeJson(res, 400, { error: "invalid_replace_system_prompt" });
79928
+ return;
79929
+ }
79930
+ if (body.enableMetaphor !== void 0 && typeof body.enableMetaphor !== "boolean") {
79931
+ deps.writeJson(res, 400, { error: "invalid_enable_metaphor" });
79932
+ return;
79933
+ }
79934
+ const updated = deps.globalOptionsService.update((current) => ({
79935
+ ...current,
79936
+ ...typeof body.replaceSystemPrompt === "boolean" ? { replaceSystemPrompt: body.replaceSystemPrompt } : {},
79937
+ ...typeof body.enableMetaphor === "boolean" ? { enableMetaphor: body.enableMetaphor } : {}
79938
+ }));
79939
+ const response = { state: toGlobalSettingsState(updated) };
79940
+ deps.writeJson(res, 200, response);
79941
+ }
79942
+ function toGlobalSettingsState(data) {
79943
+ return {
79944
+ replaceSystemPrompt: data.replaceSystemPrompt ?? false,
79945
+ enableMetaphor: data.enableMetaphor ?? false
79946
+ };
79947
+ }
79948
+ function isJsonRequest2(req) {
79949
+ const contentType = req.headers["content-type"];
79950
+ return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
79951
+ }
79952
+ var MODEL_AUTH_PROVIDERS = [
79953
+ { cli: "claude-kimi", displayName: "Moonshot Kimi" },
79954
+ { cli: "claude-glm", displayName: "ZhipuAI GLM" }
79955
+ ];
79956
+ var UPSTREAM_FAILURE_STATUSES = /* @__PURE__ */ new Set(["timeout", "network", "server"]);
79957
+ var MODEL_AUTH_API_CATALOG = [
79958
+ {
79959
+ method: "GET",
79960
+ path: "/model-auth/state",
79961
+ summary: "\uBAA8\uB378 \uB85C\uADF8\uC778 \uC0C1\uD0DC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.",
79962
+ category: "Model Auth",
79963
+ gate: "loopback"
79964
+ },
79965
+ {
79966
+ method: "PUT",
79967
+ path: "/model-auth/providers/:cli",
79968
+ summary: "\uBAA8\uB378 \uC81C\uACF5\uC790 API \uD0A4\uB97C \uB4F1\uB85D\uD569\uB2C8\uB2E4.",
79969
+ category: "Model Auth",
79970
+ gate: "terminal-origin"
79971
+ },
79972
+ {
79973
+ method: "DELETE",
79974
+ path: "/model-auth/providers/:cli",
79975
+ summary: "\uBAA8\uB378 \uC81C\uACF5\uC790 API \uD0A4\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4.",
79976
+ category: "Model Auth",
79977
+ gate: "terminal-origin"
79978
+ }
79979
+ ];
79980
+ function createModelAuthRouter(deps) {
79981
+ return async function handleModelAuthRoute(context) {
79982
+ const { req, res, pathname } = context;
79983
+ if (pathname === "/model-auth/state") {
79984
+ if (req.method !== "GET") {
79985
+ deps.writeJson(res, 405, { error: "Method not allowed" });
79986
+ return true;
79987
+ }
79988
+ deps.writeJson(res, 200, await buildModelAuthState(deps.authService));
79989
+ return true;
79990
+ }
79991
+ const cli = parseProviderPath(pathname);
79992
+ if (!cli) return false;
79993
+ const provider = MODEL_AUTH_PROVIDERS.find((entry) => entry.cli === cli);
79994
+ if (!provider) {
79995
+ deps.writeJson(res, 404, { error: "provider_not_found" });
79996
+ return true;
79997
+ }
79998
+ if (req.method === "PUT") {
79999
+ await signInProvider(req, res, deps, provider);
80000
+ return true;
80001
+ }
80002
+ if (req.method === "DELETE") {
80003
+ await signOutProvider(req, res, deps, provider);
80004
+ return true;
80005
+ }
80006
+ deps.writeJson(res, 405, { error: "Method not allowed" });
80007
+ return true;
80008
+ };
80009
+ }
80010
+ async function buildModelAuthState(authService) {
80011
+ const signedInIds = new Set(await authService.listProviderIds());
80012
+ return {
80013
+ providers: MODEL_AUTH_PROVIDERS.map((provider) => toProviderState(provider, signedInIds))
80014
+ };
80015
+ }
80016
+ async function signInProvider(req, res, deps, provider) {
80017
+ if (!deps.isAuthorized(req)) {
80018
+ deps.writeJson(res, 401, { error: "unauthorized" });
80019
+ return;
80020
+ }
80021
+ if (!isJsonRequest3(req)) {
80022
+ deps.writeJson(res, 415, { error: "unsupported_media_type" });
80023
+ return;
80024
+ }
80025
+ const body = await deps.readJsonBody(req);
80026
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
80027
+ deps.writeJson(res, 400, { error: "invalid_json" });
80028
+ return;
80029
+ }
80030
+ const apiKey = typeof body.apiKey === "string" ? body.apiKey.trim() : "";
80031
+ if (apiKey.length === 0) {
80032
+ deps.writeJson(res, 400, { error: "invalid_api_key" });
80033
+ return;
80034
+ }
80035
+ const providerId = CLI_TO_AUTH_PROVIDER_ID2[provider.cli];
80036
+ if (!providerId) {
80037
+ deps.writeJson(res, 500, { error: "provider_unavailable" });
80038
+ return;
80039
+ }
80040
+ const validation = await deps.validateApiKey(provider.cli, apiKey);
80041
+ if (validation.status !== "success") {
80042
+ const status = UPSTREAM_FAILURE_STATUSES.has(validation.status) ? 502 : 400;
80043
+ deps.writeJson(res, status, {
80044
+ error: formatSignInFailureMessage(provider.displayName, validation.status),
80045
+ status: validation.status
80046
+ });
80047
+ return;
80048
+ }
80049
+ await deps.authService.setApiKey(providerId, apiKey);
80050
+ await writeMutationState2(res, deps);
80051
+ }
80052
+ async function signOutProvider(req, res, deps, provider) {
80053
+ if (!deps.isAuthorized(req)) {
80054
+ deps.writeJson(res, 401, { error: "unauthorized" });
80055
+ return;
80056
+ }
80057
+ const providerId = CLI_TO_AUTH_PROVIDER_ID2[provider.cli];
80058
+ if (!providerId) {
80059
+ deps.writeJson(res, 500, { error: "provider_unavailable" });
80060
+ return;
80061
+ }
80062
+ await deps.authService.deleteApiKey(providerId);
80063
+ await writeMutationState2(res, deps);
80064
+ }
80065
+ async function writeMutationState2(res, deps) {
80066
+ const response = { state: await buildModelAuthState(deps.authService) };
80067
+ deps.writeJson(res, 200, response);
80068
+ }
80069
+ function toProviderState(provider, signedInIds) {
80070
+ const providerId = CLI_TO_AUTH_PROVIDER_ID2[provider.cli] ?? provider.cli;
80071
+ return {
80072
+ cli: provider.cli,
80073
+ displayName: provider.displayName,
80074
+ signedIn: signedInIds.has(providerId)
80075
+ };
80076
+ }
80077
+ function parseProviderPath(pathname) {
80078
+ const parts = pathname.split("/").filter(Boolean);
80079
+ if (parts.length !== 3 || parts[0] !== "model-auth" || parts[1] !== "providers") return null;
80080
+ const cli = safeDecodeURIComponent2(parts[2] ?? "");
80081
+ return cli ? cli : null;
80082
+ }
80083
+ function safeDecodeURIComponent2(value) {
80084
+ try {
80085
+ return decodeURIComponent(value);
80086
+ } catch {
80087
+ return null;
80088
+ }
80089
+ }
80090
+ function isJsonRequest3(req) {
80091
+ const contentType = req.headers["content-type"];
80092
+ return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
80093
+ }
80094
+ function formatSignInFailureMessage(displayName, status) {
80095
+ switch (status) {
80096
+ case "unauthorized":
80097
+ return `${displayName} rejected the API key. Check the key and try again.`;
80098
+ case "forbidden":
80099
+ return `The API key is not allowed for ${displayName}. Check its permissions.`;
80100
+ case "timeout":
80101
+ return `Validating the ${displayName} API key timed out. Check your connection and try again.`;
80102
+ case "network":
80103
+ return `Could not reach ${displayName} to validate the API key. Check your connection and try again.`;
80104
+ case "server":
80105
+ return `${displayName} returned an error while validating the API key. Try again later.`;
80106
+ default:
80107
+ return `Could not validate the ${displayName} API key. Check the key and try again.`;
80108
+ }
80109
+ }
80110
+ var compareApiCatalogEntries = (left, right) => left.category.localeCompare(right.category) || left.path.localeCompare(right.path) || left.method.localeCompare(right.method);
80111
+ function buildApiCatalog() {
80112
+ return [
80113
+ ...SERVER_API_CATALOG,
80114
+ ...CARRIER_SETTINGS_API_CATALOG,
80115
+ ...GLOBAL_SETTINGS_API_CATALOG,
80116
+ ...AGENT_CLI_API_CATALOG,
80117
+ ...MODEL_AUTH_API_CATALOG
80118
+ ].slice().sort(compareApiCatalogEntries);
80119
+ }
79790
80120
  var CONTENT_SECURITY_POLICY = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'none'";
79791
80121
  var SECURITY_HEADERS = {
79792
80122
  "content-security-policy": CONTENT_SECURITY_POLICY,
@@ -80693,7 +81023,7 @@ function createCodexGateway(deps) {
80693
81023
  return true;
80694
81024
  }
80695
81025
  if (selected.kind === "no-workspace") {
80696
- if (isJsonRequest2(request)) {
81026
+ if (isJsonRequest4(request)) {
80697
81027
  sendJson2(response, 404, { error: "no_workspace_registered" });
80698
81028
  return true;
80699
81029
  }
@@ -80814,7 +81144,7 @@ function legacyWorkspacePath(url22) {
80814
81144
  }
80815
81145
  return null;
80816
81146
  }
80817
- function isJsonRequest2(request) {
81147
+ function isJsonRequest4(request) {
80818
81148
  const accept = Array.isArray(request.headers.accept) ? request.headers.accept.join(",") : request.headers.accept ?? "";
80819
81149
  const requestedWith = Array.isArray(request.headers["x-requested-with"]) ? request.headers["x-requested-with"].join(",") : request.headers["x-requested-with"] ?? "";
80820
81150
  return accept.includes("application/json") || requestedWith.toLowerCase() === "xmlhttprequest";
@@ -81107,71 +81437,6 @@ function looksSecretToken(rawToken) {
81107
81437
  if (SECRET_PREFIX_PATTERN.test(token)) return true;
81108
81438
  return token.length >= SECRET_MIN_TOKEN_LENGTH && SECRET_CHARSET_PATTERN.test(token) && /[0-9]/.test(token) && /[A-Za-z]/.test(token);
81109
81439
  }
81110
- function createGlobalSettingsRouter(deps) {
81111
- return async function handleGlobalSettingsRoute(context) {
81112
- const { req, res, pathname } = context;
81113
- if (pathname === "/global-settings/state") {
81114
- if (req.method !== "GET") {
81115
- deps.writeJson(res, 405, { error: "Method not allowed" });
81116
- return true;
81117
- }
81118
- deps.writeJson(res, 200, buildGlobalSettingsState(deps.globalOptionsService));
81119
- return true;
81120
- }
81121
- if (pathname === "/global-settings") {
81122
- if (req.method !== "PUT") {
81123
- deps.writeJson(res, 405, { error: "Method not allowed" });
81124
- return true;
81125
- }
81126
- await mutateGlobalSettings(req, res, deps);
81127
- return true;
81128
- }
81129
- return false;
81130
- };
81131
- }
81132
- function buildGlobalSettingsState(service) {
81133
- return toGlobalSettingsState(service.load());
81134
- }
81135
- async function mutateGlobalSettings(req, res, deps) {
81136
- if (!deps.isAuthorized(req)) {
81137
- deps.writeJson(res, 401, { error: "unauthorized" });
81138
- return;
81139
- }
81140
- if (!isJsonRequest3(req)) {
81141
- deps.writeJson(res, 415, { error: "unsupported_media_type" });
81142
- return;
81143
- }
81144
- const body = await deps.readJsonBody(req);
81145
- if (!body || typeof body !== "object" || Array.isArray(body)) {
81146
- deps.writeJson(res, 400, { error: "invalid_json" });
81147
- return;
81148
- }
81149
- if (body.replaceSystemPrompt !== void 0 && typeof body.replaceSystemPrompt !== "boolean") {
81150
- deps.writeJson(res, 400, { error: "invalid_replace_system_prompt" });
81151
- return;
81152
- }
81153
- if (body.enableMetaphor !== void 0 && typeof body.enableMetaphor !== "boolean") {
81154
- deps.writeJson(res, 400, { error: "invalid_enable_metaphor" });
81155
- return;
81156
- }
81157
- const updated = deps.globalOptionsService.update((current) => ({
81158
- ...current,
81159
- ...typeof body.replaceSystemPrompt === "boolean" ? { replaceSystemPrompt: body.replaceSystemPrompt } : {},
81160
- ...typeof body.enableMetaphor === "boolean" ? { enableMetaphor: body.enableMetaphor } : {}
81161
- }));
81162
- const response = { state: toGlobalSettingsState(updated) };
81163
- deps.writeJson(res, 200, response);
81164
- }
81165
- function toGlobalSettingsState(data) {
81166
- return {
81167
- replaceSystemPrompt: data.replaceSystemPrompt ?? false,
81168
- enableMetaphor: data.enableMetaphor ?? false
81169
- };
81170
- }
81171
- function isJsonRequest3(req) {
81172
- const contentType = req.headers["content-type"];
81173
- return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
81174
- }
81175
81440
  var BINARY_DISPLAY_NAMES = {
81176
81441
  claude: "Claude Code",
81177
81442
  codex: "Codex CLI",
@@ -81268,157 +81533,6 @@ function combineAgentCliLaunchMetadata(metadata, installStatuses, authStatuses)
81268
81533
  signedIn: signedInByCli.has(meta32.id) ? signedInByCli.get(meta32.id) ?? false : true
81269
81534
  }));
81270
81535
  }
81271
- function createAgentCliRouter(deps) {
81272
- return async function handleAgentCliRoute(context) {
81273
- const { req, res, pathname } = context;
81274
- if (pathname === "/agent-cli/state") {
81275
- if (req.method !== "GET") {
81276
- deps.writeJson(res, 405, { error: "Method not allowed" });
81277
- return true;
81278
- }
81279
- const clis = await deps.detect();
81280
- const body = { clis };
81281
- deps.writeJson(res, 200, body);
81282
- return true;
81283
- }
81284
- return false;
81285
- };
81286
- }
81287
- var MODEL_AUTH_PROVIDERS = [
81288
- { cli: "claude-kimi", displayName: "Moonshot Kimi" },
81289
- { cli: "claude-glm", displayName: "ZhipuAI GLM" }
81290
- ];
81291
- var UPSTREAM_FAILURE_STATUSES = /* @__PURE__ */ new Set(["timeout", "network", "server"]);
81292
- function createModelAuthRouter(deps) {
81293
- return async function handleModelAuthRoute(context) {
81294
- const { req, res, pathname } = context;
81295
- if (pathname === "/model-auth/state") {
81296
- if (req.method !== "GET") {
81297
- deps.writeJson(res, 405, { error: "Method not allowed" });
81298
- return true;
81299
- }
81300
- deps.writeJson(res, 200, await buildModelAuthState(deps.authService));
81301
- return true;
81302
- }
81303
- const cli = parseProviderPath(pathname);
81304
- if (!cli) return false;
81305
- const provider = MODEL_AUTH_PROVIDERS.find((entry) => entry.cli === cli);
81306
- if (!provider) {
81307
- deps.writeJson(res, 404, { error: "provider_not_found" });
81308
- return true;
81309
- }
81310
- if (req.method === "PUT") {
81311
- await signInProvider(req, res, deps, provider);
81312
- return true;
81313
- }
81314
- if (req.method === "DELETE") {
81315
- await signOutProvider(req, res, deps, provider);
81316
- return true;
81317
- }
81318
- deps.writeJson(res, 405, { error: "Method not allowed" });
81319
- return true;
81320
- };
81321
- }
81322
- async function buildModelAuthState(authService) {
81323
- const signedInIds = new Set(await authService.listProviderIds());
81324
- return {
81325
- providers: MODEL_AUTH_PROVIDERS.map((provider) => toProviderState(provider, signedInIds))
81326
- };
81327
- }
81328
- async function signInProvider(req, res, deps, provider) {
81329
- if (!deps.isAuthorized(req)) {
81330
- deps.writeJson(res, 401, { error: "unauthorized" });
81331
- return;
81332
- }
81333
- if (!isJsonRequest4(req)) {
81334
- deps.writeJson(res, 415, { error: "unsupported_media_type" });
81335
- return;
81336
- }
81337
- const body = await deps.readJsonBody(req);
81338
- if (!body || typeof body !== "object" || Array.isArray(body)) {
81339
- deps.writeJson(res, 400, { error: "invalid_json" });
81340
- return;
81341
- }
81342
- const apiKey = typeof body.apiKey === "string" ? body.apiKey.trim() : "";
81343
- if (apiKey.length === 0) {
81344
- deps.writeJson(res, 400, { error: "invalid_api_key" });
81345
- return;
81346
- }
81347
- const providerId = CLI_TO_AUTH_PROVIDER_ID2[provider.cli];
81348
- if (!providerId) {
81349
- deps.writeJson(res, 500, { error: "provider_unavailable" });
81350
- return;
81351
- }
81352
- const validation = await deps.validateApiKey(provider.cli, apiKey);
81353
- if (validation.status !== "success") {
81354
- const status = UPSTREAM_FAILURE_STATUSES.has(validation.status) ? 502 : 400;
81355
- deps.writeJson(res, status, {
81356
- error: formatSignInFailureMessage(provider.displayName, validation.status),
81357
- status: validation.status
81358
- });
81359
- return;
81360
- }
81361
- await deps.authService.setApiKey(providerId, apiKey);
81362
- await writeMutationState2(res, deps);
81363
- }
81364
- async function signOutProvider(req, res, deps, provider) {
81365
- if (!deps.isAuthorized(req)) {
81366
- deps.writeJson(res, 401, { error: "unauthorized" });
81367
- return;
81368
- }
81369
- const providerId = CLI_TO_AUTH_PROVIDER_ID2[provider.cli];
81370
- if (!providerId) {
81371
- deps.writeJson(res, 500, { error: "provider_unavailable" });
81372
- return;
81373
- }
81374
- await deps.authService.deleteApiKey(providerId);
81375
- await writeMutationState2(res, deps);
81376
- }
81377
- async function writeMutationState2(res, deps) {
81378
- const response = { state: await buildModelAuthState(deps.authService) };
81379
- deps.writeJson(res, 200, response);
81380
- }
81381
- function toProviderState(provider, signedInIds) {
81382
- const providerId = CLI_TO_AUTH_PROVIDER_ID2[provider.cli] ?? provider.cli;
81383
- return {
81384
- cli: provider.cli,
81385
- displayName: provider.displayName,
81386
- signedIn: signedInIds.has(providerId)
81387
- };
81388
- }
81389
- function parseProviderPath(pathname) {
81390
- const parts = pathname.split("/").filter(Boolean);
81391
- if (parts.length !== 3 || parts[0] !== "model-auth" || parts[1] !== "providers") return null;
81392
- const cli = safeDecodeURIComponent2(parts[2] ?? "");
81393
- return cli ? cli : null;
81394
- }
81395
- function safeDecodeURIComponent2(value) {
81396
- try {
81397
- return decodeURIComponent(value);
81398
- } catch {
81399
- return null;
81400
- }
81401
- }
81402
- function isJsonRequest4(req) {
81403
- const contentType = req.headers["content-type"];
81404
- return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
81405
- }
81406
- function formatSignInFailureMessage(displayName, status) {
81407
- switch (status) {
81408
- case "unauthorized":
81409
- return `${displayName} rejected the API key. Check the key and try again.`;
81410
- case "forbidden":
81411
- return `The API key is not allowed for ${displayName}. Check its permissions.`;
81412
- case "timeout":
81413
- return `Validating the ${displayName} API key timed out. Check your connection and try again.`;
81414
- case "network":
81415
- return `Could not reach ${displayName} to validate the API key. Check your connection and try again.`;
81416
- case "server":
81417
- return `${displayName} returned an error while validating the API key. Try again later.`;
81418
- default:
81419
- return `Could not validate the ${displayName} API key. Check the key and try again.`;
81420
- }
81421
- }
81422
81536
  function writeObserverEvents(req, res, workspace, store22) {
81423
81537
  res.writeHead(200, withSecurityHeaders2({
81424
81538
  "Content-Type": "text/event-stream",
@@ -83411,6 +83525,162 @@ var THEATER_SHELL_SESSION_PREFIX2 = "shell:";
83411
83525
  var SERVER_TIMEOUT_MS = 30 * 60 * 1e3;
83412
83526
  var MAX_BODY_BYTES = 1024 * 1024;
83413
83527
  var UPDATE_APPLY_FORBIDDEN_BODY_KEYS = /* @__PURE__ */ new Set(["channel", "package", "packageName", "packageVersion", "packages", "targetVersion", "version"]);
83528
+ var SERVER_API_CATALOG = [
83529
+ {
83530
+ method: "GET",
83531
+ path: "/observer/status",
83532
+ summary: "Get the console observation status.",
83533
+ category: "Observer",
83534
+ gate: "loopback"
83535
+ },
83536
+ {
83537
+ method: "GET",
83538
+ path: "/observer/api-catalog",
83539
+ summary: "Get the backend API catalog.",
83540
+ category: "Observer",
83541
+ gate: "loopback"
83542
+ },
83543
+ {
83544
+ method: "GET",
83545
+ path: "/observer/tenants",
83546
+ summary: "List observed terminal workspaces.",
83547
+ category: "Observer",
83548
+ gate: "loopback"
83549
+ },
83550
+ {
83551
+ method: "GET",
83552
+ path: "/observer/jobs",
83553
+ summary: "List observed carrier jobs.",
83554
+ category: "Observer",
83555
+ gate: "loopback"
83556
+ },
83557
+ {
83558
+ method: "GET",
83559
+ path: "/observer/events",
83560
+ summary: "Open the observation event stream.",
83561
+ category: "Observer",
83562
+ gate: "loopback"
83563
+ },
83564
+ {
83565
+ method: "GET",
83566
+ path: "/observer/theaters",
83567
+ summary: "List Theaters.",
83568
+ category: "Observer",
83569
+ gate: "loopback"
83570
+ },
83571
+ {
83572
+ method: "POST",
83573
+ path: "/observer/theaters",
83574
+ summary: "Register a new Theater.",
83575
+ category: "Observer",
83576
+ gate: "terminal-origin"
83577
+ },
83578
+ {
83579
+ method: "DELETE",
83580
+ path: "/observer/theaters/:theaterId",
83581
+ summary: "Remove a Theater and its Operations.",
83582
+ category: "Observer",
83583
+ gate: "terminal-origin"
83584
+ },
83585
+ {
83586
+ method: "POST",
83587
+ path: "/observer/theaters/:theaterId/sessions",
83588
+ summary: "Create a new Operation in a Theater.",
83589
+ category: "Observer",
83590
+ gate: "terminal-origin"
83591
+ },
83592
+ {
83593
+ method: "POST",
83594
+ path: "/terminal/ticket",
83595
+ summary: "Issue a terminal WebSocket connection ticket.",
83596
+ category: "Terminal",
83597
+ gate: "terminal-origin"
83598
+ },
83599
+ {
83600
+ method: "POST",
83601
+ path: "/terminal/folders/list",
83602
+ summary: "List terminal folder selection entries.",
83603
+ category: "Terminal",
83604
+ gate: "terminal-origin"
83605
+ },
83606
+ {
83607
+ method: "POST",
83608
+ path: "/terminal/folders/grants",
83609
+ summary: "Issue a terminal folder access grant.",
83610
+ category: "Terminal",
83611
+ gate: "terminal-origin"
83612
+ },
83613
+ {
83614
+ method: "GET",
83615
+ path: "/terminal/sessions",
83616
+ summary: "List terminal Operations.",
83617
+ category: "Terminal",
83618
+ gate: "terminal-origin"
83619
+ },
83620
+ {
83621
+ method: "POST",
83622
+ path: "/terminal/sessions",
83623
+ summary: "Create a new terminal Operation.",
83624
+ category: "Terminal",
83625
+ gate: "terminal-origin"
83626
+ },
83627
+ {
83628
+ method: "POST",
83629
+ path: "/terminal/sessions/:sessionId/resume",
83630
+ summary: "Resume a dormant Operation.",
83631
+ category: "Terminal",
83632
+ gate: "terminal-origin"
83633
+ },
83634
+ {
83635
+ method: "POST",
83636
+ path: "/terminal/sessions/:sessionId/turn",
83637
+ summary: "Receive an Agent CLI turn state hook.",
83638
+ category: "Terminal",
83639
+ gate: "lock-token"
83640
+ },
83641
+ {
83642
+ method: "POST",
83643
+ path: "/terminal/sessions/:sessionId/attention",
83644
+ summary: "Receive an input-waiting attention hook.",
83645
+ category: "Terminal",
83646
+ gate: "lock-token"
83647
+ },
83648
+ {
83649
+ method: "POST",
83650
+ path: "/terminal/sessions/:sessionId/auto-name",
83651
+ summary: "Receive an Operation auto-name hook.",
83652
+ category: "Terminal",
83653
+ gate: "lock-token"
83654
+ },
83655
+ {
83656
+ method: "DELETE",
83657
+ path: "/terminal/sessions/:sessionId",
83658
+ summary: "Remove a terminal Operation.",
83659
+ category: "Terminal",
83660
+ gate: "terminal-origin"
83661
+ },
83662
+ {
83663
+ method: "PATCH",
83664
+ path: "/terminal/sessions/:sessionId",
83665
+ summary: "Rename a terminal Operation.",
83666
+ category: "Terminal",
83667
+ gate: "terminal-origin"
83668
+ },
83669
+ {
83670
+ method: "POST",
83671
+ path: "/update/apply",
83672
+ summary: "Request console update application.",
83673
+ category: "Update",
83674
+ gate: "console-origin"
83675
+ },
83676
+ {
83677
+ method: "GET",
83678
+ path: "/health",
83679
+ summary: "Check console status with the lock token.",
83680
+ category: "Health",
83681
+ gate: "lock-token"
83682
+ }
83683
+ ];
83414
83684
  function createConsoleServer(deps = {}) {
83415
83685
  const host = deps.host ?? DEFAULT_HOST22;
83416
83686
  const port = deps.port ?? DEFAULT_PORT22;
@@ -83611,12 +83881,12 @@ function createConsoleServer(deps = {}) {
83611
83881
  handleObserverStatus(req, res);
83612
83882
  return;
83613
83883
  }
83614
- if (pathname === "/update/apply") {
83615
- runAsyncHandler(handleUpdateApply(req, res), res);
83884
+ if (pathname === "/observer/api-catalog") {
83885
+ handleObserverApiCatalog(req, res);
83616
83886
  return;
83617
83887
  }
83618
- if (pathname === "/observer/carriers") {
83619
- handleObserverCarriers(req, res);
83888
+ if (pathname === "/update/apply") {
83889
+ runAsyncHandler(handleUpdateApply(req, res), res);
83620
83890
  return;
83621
83891
  }
83622
83892
  if (pathname === "/carrier-settings" || pathname.startsWith("/carrier-settings/")) {
@@ -84062,6 +84332,9 @@ function createConsoleServer(deps = {}) {
84062
84332
  };
84063
84333
  writeJson(res, 200, payload);
84064
84334
  }
84335
+ function handleObserverApiCatalog(_req, res) {
84336
+ writeJson(res, 200, { version: version22, routes: buildApiCatalog() });
84337
+ }
84065
84338
  async function handleUpdateApply(req, res) {
84066
84339
  if (req.method !== "POST") {
84067
84340
  writeJson(res, 405, { error: "Method not allowed" });
@@ -84125,11 +84398,6 @@ function createConsoleServer(deps = {}) {
84125
84398
  const payload = { status: "accepted" };
84126
84399
  writeJson(res, 202, payload);
84127
84400
  }
84128
- function handleObserverCarriers(_req, res) {
84129
- writeJson(res, 200, {
84130
- carriers: readCarrierStatusEntries(carrierRegistry).map(toCarrierReadinessEntry)
84131
- });
84132
- }
84133
84401
  function handleObserverWorkspaces(_req, res) {
84134
84402
  writeJson(res, 200, { tenants: observability.listWorkspaces() });
84135
84403
  }
@@ -84199,20 +84467,6 @@ function createConsoleServer(deps = {}) {
84199
84467
  activeAdmiralCount: observability.listWorkspaces().filter((workspace) => workspace.theaterId === theater.id).length
84200
84468
  };
84201
84469
  }
84202
- function toCarrierReadinessEntry(entry) {
84203
- return {
84204
- carrierId: entry.carrierId,
84205
- displayName: entry.displayName,
84206
- role: entry.role,
84207
- model: entry.model,
84208
- effort: entry.effort,
84209
- taskForceBackendCount: entry.taskForceBackendCount,
84210
- subagentMode: entry.subagentMode,
84211
- ...entry.category ? { category: entry.category } : {},
84212
- slot: entry.slot,
84213
- cliType: entry.cliType
84214
- };
84215
- }
84216
84470
  function resolveWikiServerStatus(theaterId) {
84217
84471
  if (!theaterId) return "unknown";
84218
84472
  if (!theaters.get(theaterId)) return "unknown";
@@ -85902,7 +86156,7 @@ import { appendFile as appendFile2, mkdir as mkdir3, readFile as readFile22 } fr
85902
86156
  import { mkdir as mkdir22 } from "fs/promises";
85903
86157
  import path33 from "path";
85904
86158
  import { mkdir as mkdir5, readdir as readdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
85905
- import path24 from "path";
86159
+ import path25 from "path";
85906
86160
  import path102 from "path";
85907
86161
  import { mkdir as mkdir52 } from "fs/promises";
85908
86162
  import path72 from "path";
@@ -86384,18 +86638,18 @@ Always read \`schema/wiki-schema.md\` directly before composing or revising entr
86384
86638
  `;
86385
86639
  async function ensureWorkspaceSchema2(paths) {
86386
86640
  await mkdir5(paths.schemaDir, { recursive: true });
86387
- await writeDefaultFileIfMissing2(path24.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME2), DEFAULT_WORKSPACE_SCHEMA_AGENTS2);
86388
- await writeDefaultFileIfMissing2(path24.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME2), DEFAULT_WORKSPACE_WIKI_SCHEMA2);
86641
+ await writeDefaultFileIfMissing2(path25.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME2), DEFAULT_WORKSPACE_SCHEMA_AGENTS2);
86642
+ await writeDefaultFileIfMissing2(path25.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME2), DEFAULT_WORKSPACE_WIKI_SCHEMA2);
86389
86643
  await writeDefaultFileIfMissing2(buildTemplatePath2(paths, "prd"), DEFAULT_TEMPLATE_PRD2);
86390
86644
  return readWorkspaceSchemaSummary2(paths);
86391
86645
  }
86392
86646
  async function ensureWorkspaceDoctrine2(paths) {
86393
86647
  await mkdir5(paths.root, { recursive: true });
86394
- await writeDefaultFileIfMissing2(path24.join(paths.root, WORKSPACE_KNOWLEDGE_AGENTS_FILENAME2), DEFAULT_WORKSPACE_KNOWLEDGE_AGENTS2);
86648
+ await writeDefaultFileIfMissing2(path25.join(paths.root, WORKSPACE_KNOWLEDGE_AGENTS_FILENAME2), DEFAULT_WORKSPACE_KNOWLEDGE_AGENTS2);
86395
86649
  }
86396
86650
  async function readWorkspaceSchemaSummary2(paths) {
86397
- const agentsPath = path24.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME2);
86398
- const wikiSchemaPath = path24.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME2);
86651
+ const agentsPath = path25.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME2);
86652
+ const wikiSchemaPath = path25.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME2);
86399
86653
  const wikiSchemaContent = await tryReadFile2(wikiSchemaPath);
86400
86654
  const templates = await scanTemplates2(paths);
86401
86655
  if (wikiSchemaContent === null) {
@@ -86434,7 +86688,7 @@ async function scanTemplates2(paths) {
86434
86688
  if (!entry.name.startsWith(WORKSPACE_TEMPLATE_PREFIX2) || !entry.name.endsWith(WORKSPACE_TEMPLATE_SUFFIX2)) continue;
86435
86689
  const id = entry.name.slice(WORKSPACE_TEMPLATE_PREFIX2.length, -WORKSPACE_TEMPLATE_SUFFIX2.length);
86436
86690
  if (!id) continue;
86437
- const filePath = path24.join(paths.schemaDir, entry.name);
86691
+ const filePath = path25.join(paths.schemaDir, entry.name);
86438
86692
  try {
86439
86693
  const parsed = parseTemplateMarkdown2(await readFile4(filePath, "utf8"));
86440
86694
  templates.push({
@@ -86468,7 +86722,7 @@ async function validateTemplateCompliance2(paths, templateId, body) {
86468
86722
  }
86469
86723
  }
86470
86724
  function inferTemplateIdFromTarget2(target, knownTemplateIds) {
86471
- const basename = path24.basename(target, ".md");
86725
+ const basename = path25.basename(target, ".md");
86472
86726
  const ids = knownTemplateIds ?? DEFAULT_TEMPLATE_IDS2;
86473
86727
  const sorted = [...ids].sort((a, b) => b.length - a.length);
86474
86728
  for (const id of sorted) {
@@ -86497,7 +86751,7 @@ function extractSchemaSummary2(content) {
86497
86751
  return lines.find((line) => line.length > 0 && !line.startsWith("#")) ?? "Workspace schema is present.";
86498
86752
  }
86499
86753
  function buildTemplatePath2(paths, id) {
86500
- return path24.join(paths.schemaDir, `${WORKSPACE_TEMPLATE_PREFIX2}${id}${WORKSPACE_TEMPLATE_SUFFIX2}`);
86754
+ return path25.join(paths.schemaDir, `${WORKSPACE_TEMPLATE_PREFIX2}${id}${WORKSPACE_TEMPLATE_SUFFIX2}`);
86501
86755
  }
86502
86756
  function parseTemplateMarkdown2(content) {
86503
86757
  const normalized = content.replace(/\r\n/g, "\n");
@@ -92314,7 +92568,7 @@ function renderCarrierHudStrip(width, carriers, frame, theme) {
92314
92568
  return [line];
92315
92569
  }
92316
92570
  function appendWidgetJobSummary(carrierRuntime, lines, width, jobs3, frame, theme, now) {
92317
- const subagentModes = readCarrierAgentModeSnapshot(buildCarrierDefaults2(carrierRuntime)).agentModes;
92571
+ const subagentModes = readCarrierAgentModeSnapshot(buildCarrierDefaults(carrierRuntime)).agentModes;
92318
92572
  const groups = buildCarrierJobGroups(
92319
92573
  jobs3,
92320
92574
  getRegisteredOrder(carrierRuntime.registry),
@@ -92365,7 +92619,7 @@ function appendTrackRows(carrierRuntime, lines, width, job, jobColor, frame, the
92365
92619
  }
92366
92620
  function buildCarrierTiles(carrierRuntime, activeJobs) {
92367
92621
  const snapshot = readCarriersSnapshot();
92368
- const subagentModes = readCarrierAgentModeSnapshot(buildCarrierDefaults2(carrierRuntime)).agentModes;
92622
+ const subagentModes = readCarrierAgentModeSnapshot(buildCarrierDefaults(carrierRuntime)).agentModes;
92369
92623
  return getRegisteredOrder(carrierRuntime.registry).map((carrierId) => {
92370
92624
  const activeCarrierJobs = activeJobs.filter((job) => job.ownerCarrierId === carrierId);
92371
92625
  const taskForceBackendCount = getConfiguredTaskForceBackendsFromSnapshot(snapshot, carrierId).length;
@@ -92450,7 +92704,7 @@ function groupTrackModelEffortLabel(group) {
92450
92704
  const track = carrierJobs[0]?.tracks[0];
92451
92705
  return track ? trackModelEffortLabel(track) : "";
92452
92706
  }
92453
- function buildCarrierDefaults2(carrierRuntime) {
92707
+ function buildCarrierDefaults(carrierRuntime) {
92454
92708
  return Object.fromEntries(
92455
92709
  getRegisteredOrder(carrierRuntime.registry).map((carrierId) => {
92456
92710
  const config3 = getCarrierConfig(carrierRuntime.registry, carrierId);