@dotobokuri/fleet-cli 1.5.5 → 1.6.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
@@ -18469,7 +18469,7 @@ var init_models = __esm({
18469
18469
  "../../packages/core-unified-agent/models.json"() {
18470
18470
  models_default = {
18471
18471
  version: 1,
18472
- updatedAt: "2026-06-13T00:00:00Z",
18472
+ updatedAt: "2026-06-16T00:00:00Z",
18473
18473
  providers: {
18474
18474
  claude: {
18475
18475
  name: "Claude Code with Anthropic",
@@ -18479,7 +18479,9 @@ var init_models = __esm({
18479
18479
  { modelId: "sonnet", name: "Claude Sonnet", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "medium" } },
18480
18480
  { modelId: "opus", name: "Claude Opus", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "xhigh" } },
18481
18481
  { modelId: "opus[1m]", name: "Claude Opus [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "xhigh" } },
18482
- { modelId: "claude-opus-4-6[1m]", name: "Claude Opus 4.6 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } }
18482
+ { modelId: "claude-opus-4-6[1m]", name: "Claude Opus 4.6 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } },
18483
+ { modelId: "claude-opus-4-7[1m]", name: "Claude Opus 4.7 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } },
18484
+ { modelId: "claude-opus-4-8[1m]", name: "Claude Opus 4.8 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } }
18483
18485
  ]
18484
18486
  },
18485
18487
  "claude-zai": {
@@ -33431,6 +33433,8 @@ function createClaudeFamilyCliDefinition(options2) {
33431
33433
  lineTerminator: "\r",
33432
33434
  multilineStrategy: "paste-mode"
33433
33435
  },
33436
+ // Claude Code 계열은 세션 이름 변경 슬래시 명령 `/rename`을 지원한다.
33437
+ renameCommand: "/rename",
33434
33438
  terminalName: "xterm-256color"
33435
33439
  };
33436
33440
  }
@@ -33454,7 +33458,7 @@ var codexCli = {
33454
33458
  async createProfile(options2) {
33455
33459
  const { bin, prefixArgs } = resolveBinary("codex", "CODEX_BIN", options2.env);
33456
33460
  return {
33457
- args: [...prefixArgs, "--no-alt-screen", ...buildModelArgs2(options2.model)],
33461
+ args: [...prefixArgs, ...buildResumeArgs(options2.resumeSessionId), "--no-alt-screen", ...buildModelArgs2(options2.model)],
33458
33462
  bin,
33459
33463
  binPrefixArgs: prefixArgs,
33460
33464
  cwd: options2.cwd,
@@ -33466,10 +33470,15 @@ var codexCli = {
33466
33470
  lineTerminator: "\r",
33467
33471
  multilineStrategy: "paste-mode"
33468
33472
  },
33473
+ // Codex CLI도 세션 이름 변경 슬래시 명령 `/rename`을 지원한다.
33474
+ renameCommand: "/rename",
33469
33475
  terminalName: "xterm-256color"
33470
33476
  };
33471
33477
  }
33472
33478
  };
33479
+ function buildResumeArgs(resumeSessionId) {
33480
+ return resumeSessionId === void 0 ? [] : ["resume", resumeSessionId];
33481
+ }
33473
33482
  function buildModelArgs2(model) {
33474
33483
  return model === void 0 ? [] : ["--model", model];
33475
33484
  }
@@ -33486,7 +33495,8 @@ async function resolveAgentCliProfile(env, cwd, options2 = {}) {
33486
33495
  authService: options2.authService,
33487
33496
  cwd,
33488
33497
  env,
33489
- model: options2.model
33498
+ model: options2.model,
33499
+ resumeSessionId: options2.resumeSessionId
33490
33500
  });
33491
33501
  }
33492
33502
  function resolveAgentCliId(env, options2 = {}) {
@@ -33562,6 +33572,7 @@ function buildClaudeNativeSubagentPlan(registry4) {
33562
33572
  function buildClaudeNativeArgs(context) {
33563
33573
  const systemPromptArg = context.replaceSystemPrompt ? "--system-prompt-file" : "--append-system-prompt-file";
33564
33574
  return [
33575
+ ...buildResumeArgs2(context.resumeSessionId),
33565
33576
  systemPromptArg,
33566
33577
  requireSystemPromptFile(context),
33567
33578
  ...context.pluginRoots.flatMap((pluginRoot) => [
@@ -33572,6 +33583,9 @@ function buildClaudeNativeArgs(context) {
33572
33583
  "--dangerously-skip-permissions"
33573
33584
  ];
33574
33585
  }
33586
+ function buildResumeArgs2(resumeSessionId) {
33587
+ return resumeSessionId === void 0 ? [] : ["--resume", resumeSessionId];
33588
+ }
33575
33589
  function buildClaudeMcpConfig(servers) {
33576
33590
  return JSON.stringify({
33577
33591
  mcpServers: Object.fromEntries(
@@ -33629,20 +33643,32 @@ function escapeTomlMultilineString(value) {
33629
33643
  });
33630
33644
  return result;
33631
33645
  }
33646
+ function buildPosixShellCommand(values) {
33647
+ return values.map(posixShellQuote).join(" ");
33648
+ }
33649
+ function posixShellQuote(value) {
33650
+ return `'${value.replaceAll("'", "'\\''")}'`;
33651
+ }
33632
33652
  var CODEX_TOOL_TIMEOUT_SEC = 1800;
33633
33653
  function buildCodexNativeArgs(context) {
33634
33654
  const profileName = requireCodexProfileName(context);
33635
33655
  const args = [
33656
+ ...buildResumeArgs3(context.resumeSessionId),
33636
33657
  "--enable",
33637
33658
  "plugins",
33638
33659
  "--enable",
33639
33660
  "child_agents_md",
33661
+ "--enable",
33662
+ "hooks",
33640
33663
  "--profile",
33641
33664
  profileName,
33642
33665
  "-c",
33643
33666
  'approval_policy="never"',
33644
33667
  "-c",
33645
- 'sandbox_mode="danger-full-access"'
33668
+ 'sandbox_mode="danger-full-access"',
33669
+ // hook 신뢰 프롬프트("Hooks need review")를 fleet 관리 세션에서 건너뛴다. bypass_hook_trust는
33670
+ // config 키가 아니라 전용 CLI 플래그이므로 -c override가 아닌 플래그로 전달해야 한다.
33671
+ "--dangerously-bypass-hook-trust"
33646
33672
  ];
33647
33673
  for (const server of context.mcpServers) {
33648
33674
  const prefix = `mcp_servers.${server.name}`;
@@ -33658,6 +33684,9 @@ function buildCodexNativeArgs(context) {
33658
33684
  }
33659
33685
  return args;
33660
33686
  }
33687
+ function buildResumeArgs3(resumeSessionId) {
33688
+ return resumeSessionId === void 0 ? [] : ["resume", resumeSessionId];
33689
+ }
33661
33690
  function requireCodexProfileName(context) {
33662
33691
  if (context.codexProfileName) return context.codexProfileName;
33663
33692
  throw new Error("Codex profile name is required for native injection");
@@ -33868,20 +33897,32 @@ function claudeHooks(options2) {
33868
33897
  if (!hookExec) {
33869
33898
  throw new Error("Fleet Claude session hook command is required");
33870
33899
  }
33900
+ const captureSessionHookExec = options2.captureSessionHookExec;
33871
33901
  return {
33872
33902
  hooks: {
33873
33903
  SessionStart: [{
33874
- hooks: [{
33875
- // exec 형식: command는 직접 spawn되는 실행 파일, args는 셸 토크나이징 없이 그대로 전달된다.
33876
- // Windows cmd/powershell의 따옴표 규칙과 무관하게 동작하며 공백 포함 경로도 안전하다.
33877
- args: [...hookExec.args],
33878
- command: hookExec.command,
33879
- type: "command"
33904
+ hooks: [claudeCommandHook(hookExec)]
33905
+ }],
33906
+ ...captureSessionHookExec ? {
33907
+ UserPromptSubmit: [{
33908
+ hooks: [claudeCommandHook(captureSessionHookExec)]
33880
33909
  }]
33881
- }]
33910
+ } : {}
33882
33911
  }
33883
33912
  };
33884
33913
  }
33914
+ function claudeCommandHook(hookExec) {
33915
+ if (!hookExec) {
33916
+ throw new Error("Fleet Claude session hook command is required");
33917
+ }
33918
+ return {
33919
+ // exec 형식: command는 직접 spawn되는 실행 파일, args는 셸 토크나이징 없이 그대로 전달된다.
33920
+ // Windows cmd/powershell의 따옴표 규칙과 무관하게 동작하며 공백 포함 경로도 안전하다.
33921
+ args: [...hookExec.args],
33922
+ command: hookExec.command,
33923
+ type: "command"
33924
+ };
33925
+ }
33885
33926
  function claudeAgentFile(subagent) {
33886
33927
  const frontmatter = [
33887
33928
  "---",
@@ -34417,7 +34458,6 @@ function renderPluginRoot(pluginRoot, bundle, options2, fleetRoot) {
34417
34458
  const stagedPluginRoot = path82.join(stageParent, path82.basename(pluginRoot));
34418
34459
  try {
34419
34460
  ensurePrivateDir(stagedPluginRoot, stagedPluginRoot);
34420
- writePrivateJson(path82.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest(bundle), stagedPluginRoot);
34421
34461
  writePrivateJson(path82.join(stagedPluginRoot, ".claude-plugin", "plugin.json"), claudeManifest(bundle), stagedPluginRoot);
34422
34462
  switch (bundle.source) {
34423
34463
  case "asset":
@@ -34432,6 +34472,7 @@ function renderPluginRoot(pluginRoot, bundle, options2, fleetRoot) {
34432
34472
  renderGlobalPluginRoot(stagedPluginRoot, fleetRoot);
34433
34473
  break;
34434
34474
  }
34475
+ writePrivateJson(path82.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest(bundle, stagedPluginRoot), stagedPluginRoot);
34435
34476
  removePrivatePath(pluginRoot, parentRoot);
34436
34477
  renameSync22(stagedPluginRoot, pluginRoot);
34437
34478
  } finally {
@@ -34563,14 +34604,36 @@ function marketplacePluginPath(target, bundle) {
34563
34604
  if (target.flat) return `./${FLAT_PLUGIN_DIR_NAME}`;
34564
34605
  return `./${PLUGIN_BUNDLES_DIR_NAME}/${bundle.directoryName}`;
34565
34606
  }
34566
- function codexManifest(bundle) {
34607
+ function codexManifest(bundle, pluginRoot) {
34567
34608
  return {
34568
34609
  name: bundle.name,
34569
- version: "0.0.0",
34610
+ version: codexManifestVersion(bundle, pluginRoot),
34570
34611
  description: bundle.description,
34571
34612
  skills: "./skills/"
34572
34613
  };
34573
34614
  }
34615
+ function codexManifestVersion(bundle, pluginRoot) {
34616
+ const hash3 = crypto4.createHash("sha256");
34617
+ hash3.update(bundle.name);
34618
+ hash3.update("\0");
34619
+ hash3.update(bundle.description);
34620
+ hash3.update("\0");
34621
+ for (const filePath of listCodexEffectivePluginFiles(pluginRoot)) {
34622
+ const relativePath = path82.relative(pluginRoot, filePath);
34623
+ hash3.update(relativePath);
34624
+ hash3.update("\0");
34625
+ hash3.update(readFileSync42(filePath));
34626
+ hash3.update("\0");
34627
+ }
34628
+ return `0.0.0+${hash3.digest("hex").slice(0, 12)}`;
34629
+ }
34630
+ function listCodexEffectivePluginFiles(pluginRoot) {
34631
+ const skillsPath = path82.join(pluginRoot, "skills");
34632
+ if (!existsSync5(skillsPath)) return [];
34633
+ const files = [];
34634
+ collectRenderableFiles(pluginRoot, skillsPath, files, /* @__PURE__ */ new Set());
34635
+ return files.sort();
34636
+ }
34574
34637
  function claudeManifest(bundle) {
34575
34638
  return {
34576
34639
  name: bundle.name,
@@ -34604,11 +34667,12 @@ async function injectAgentCliProfile(profile, options2) {
34604
34667
  cwd: profile.cwd,
34605
34668
  dataDir: options2.dataDir,
34606
34669
  rootDir: options2.pluginRootDir,
34670
+ captureSessionHookExec: options2.captureSessionHookExec,
34607
34671
  hookExec: startupDefinitions.host === "claude" ? requireHookExec(options2.hookExec) : void 0,
34608
34672
  withMarketplaceLock: options2.withMarketplaceLock
34609
34673
  });
34610
34674
  const codexPluginKeys = plugin.codexRegistrations.map((registration) => `${registration.pluginName}@${registration.marketplaceName}`);
34611
- const codexProfile = profile.id === "codex" ? writeCodexFleetProfile(profile.env, doctrine, codexPluginKeys, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
34675
+ const codexProfile = profile.id === "codex" ? writeCodexFleetProfile(profile.env, doctrine, codexPluginKeys, options2.captureSessionHookExec, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
34612
34676
  const launchWarnings = [];
34613
34677
  for (const registration of plugin.codexRegistrations) {
34614
34678
  const registrationWarning = await ensureCodexPluginRegistered(registration, {
@@ -34635,13 +34699,14 @@ async function injectAgentCliProfile(profile, options2) {
34635
34699
  pluginRoot: plugin.pluginRoot,
34636
34700
  pluginRoots: plugin.pluginRoots,
34637
34701
  codexProfileName: codexProfile?.profileName,
34638
- replaceSystemPrompt: options2.replaceSystemPrompt ?? true,
34702
+ replaceSystemPrompt: options2.replaceSystemPrompt ?? false,
34703
+ resumeSessionId: options2.resumeSessionId,
34639
34704
  systemPromptFile
34640
34705
  };
34641
34706
  const injectedArgs = buildAgentCliArgs(capability.builderId, context);
34642
34707
  return {
34643
34708
  ...profile,
34644
- args: [...profile.args, ...injectedArgs],
34709
+ args: mergeAgentCliArgs(profile, capability.builderId, context, injectedArgs),
34645
34710
  cleanup,
34646
34711
  launchWarnings: [...profile.launchWarnings ?? [], ...launchWarnings]
34647
34712
  };
@@ -34683,7 +34748,7 @@ function writeSystemPromptFile(cliId, systemPrompt, onCleanup) {
34683
34748
  chmodBestEffort2(filePath, SYSTEM_PROMPT_FILE_MODE);
34684
34749
  return filePath;
34685
34750
  }
34686
- function writeCodexFleetProfile(env, doctrine, pluginKeys, onCleanup) {
34751
+ function writeCodexFleetProfile(env, doctrine, pluginKeys, captureSessionHookExec, onCleanup) {
34687
34752
  const codexHome = env.CODEX_HOME ?? path92.join(env.HOME ?? os23.homedir(), ".codex");
34688
34753
  mkdirSync32(codexHome, { recursive: true });
34689
34754
  pruneStaleCodexFleetProfiles(codexHome);
@@ -34702,11 +34767,21 @@ function writeCodexFleetProfile(env, doctrine, pluginKeys, onCleanup) {
34702
34767
  `[plugins."${escapeTomlBasicString2(pluginKey)}"]`,
34703
34768
  "enabled = true",
34704
34769
  ""
34705
- ])
34770
+ ]),
34771
+ ...codexCaptureHookConfig(captureSessionHookExec)
34706
34772
  ].join("\n"));
34707
34773
  chmodBestEffort2(profilePath, SYSTEM_PROMPT_FILE_MODE);
34708
34774
  return { profileName, profilePath };
34709
34775
  }
34776
+ function codexCaptureHookConfig(captureSessionHookExec) {
34777
+ if (captureSessionHookExec === void 0) return [];
34778
+ const command3 = buildPosixShellCommand([captureSessionHookExec.command, ...captureSessionHookExec.args]);
34779
+ return [
34780
+ "[hooks]",
34781
+ `UserPromptSubmit = [{ hooks = [{ type = "command", command = "${escapeTomlBasicString2(command3)}" }] }]`,
34782
+ ""
34783
+ ];
34784
+ }
34710
34785
  function writeFileNoFollow2(filePath, content) {
34711
34786
  const flags = constants32.O_WRONLY | constants32.O_CREAT | constants32.O_TRUNC | constants32.O_NOFOLLOW;
34712
34787
  const fd = openSync32(filePath, flags, SYSTEM_PROMPT_FILE_MODE);
@@ -34779,6 +34854,24 @@ function buildAgentCliArgs(builderId, context) {
34779
34854
  return buildCodexNativeArgs(context);
34780
34855
  }
34781
34856
  }
34857
+ function mergeAgentCliArgs(profile, builderId, context, injectedArgs) {
34858
+ if (builderId !== "codex-native" || context.resumeSessionId === void 0) {
34859
+ return [...profile.args, ...injectedArgs];
34860
+ }
34861
+ const resumeSessionId = context.resumeSessionId;
34862
+ const prefixLength = profile.binPrefixArgs?.length ?? 0;
34863
+ const codexResumeArgs = ["resume", resumeSessionId];
34864
+ const injectedTail = injectedArgs.slice(codexResumeArgs.length);
34865
+ return [
34866
+ ...profile.args.slice(0, prefixLength),
34867
+ ...codexResumeArgs,
34868
+ ...profile.args.slice(prefixLength).filter((arg, index, args) => !isCodexResumeArgAt(args, index, resumeSessionId)),
34869
+ ...injectedTail
34870
+ ];
34871
+ }
34872
+ function isCodexResumeArgAt(args, index, resumeSessionId) {
34873
+ return args[index] === "resume" && args[index + 1] === resumeSessionId || args[index] === resumeSessionId && args[index - 1] === "resume";
34874
+ }
34782
34875
  function createOnceCleanup(cleanup) {
34783
34876
  let cleaned = false;
34784
34877
  return () => {
@@ -39592,14 +39685,14 @@ import * as fs52 from "fs";
39592
39685
  import fs5__default, { readFileSync as readFileSync8, existsSync as existsSync8, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync6, mkdirSync as mkdirSync8, rmSync as rmSync5, chmodSync as chmodSync5, renameSync as renameSync5, readdirSync as readdirSync6, constants as constants8, openSync as openSync8, closeSync as closeSync8, lstatSync as lstatSync8, unlinkSync as unlinkSync5, realpathSync as realpathSync6, statSync as statSync6, symlinkSync as symlinkSync2, fstatSync as fstatSync7 } from "fs";
39593
39686
  import * as path93 from "path";
39594
39687
  import path93__default, { join as join10, resolve, relative, dirname as dirname6 } from "path";
39595
- import process4 from "process";
39688
+ import process5 from "process";
39596
39689
  import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
39597
39690
  import * as os222 from "os";
39598
39691
  import os22__default from "os";
39599
39692
  import { EventEmitter as EventEmitter6 } from "events";
39600
39693
  import { stat, mkdir as mkdir2, readFile as readFile2, readdir, appendFile, writeFile as writeFile2, rename, access as access2, rm } from "fs/promises";
39601
39694
  import { Writable as Writable2, Readable as Readable2 } from "stream";
39602
- import crypto32, { createHash as createHash2, randomUUID as randomUUID2, timingSafeEqual } from "crypto";
39695
+ import crypto5, { createHash as createHash2, randomUUID as randomUUID2, timingSafeEqual } from "crypto";
39603
39696
  import http2 from "http";
39604
39697
  import { createRequire } from "module";
39605
39698
  import net2 from "net";
@@ -40544,10 +40637,10 @@ function mergeDefs2(...defs) {
40544
40637
  function cloneDef2(schema) {
40545
40638
  return mergeDefs2(schema._zod.def);
40546
40639
  }
40547
- function getElementAtPath2(obj, path30) {
40548
- if (!path30)
40640
+ function getElementAtPath2(obj, path34) {
40641
+ if (!path34)
40549
40642
  return obj;
40550
- return path30.reduce((acc, key) => acc?.[key], obj);
40643
+ return path34.reduce((acc, key) => acc?.[key], obj);
40551
40644
  }
40552
40645
  function promiseAllObject2(promisesObj) {
40553
40646
  const keys = Object.keys(promisesObj);
@@ -40956,11 +41049,11 @@ function explicitlyAborted2(x, startIndex = 0) {
40956
41049
  }
40957
41050
  return false;
40958
41051
  }
40959
- function prefixIssues2(path30, issues) {
41052
+ function prefixIssues2(path34, issues) {
40960
41053
  return issues.map((iss) => {
40961
41054
  var _a32;
40962
41055
  (_a32 = iss).path ?? (_a32.path = []);
40963
- iss.path.unshift(path30);
41056
+ iss.path.unshift(path34);
40964
41057
  return iss;
40965
41058
  });
40966
41059
  }
@@ -41105,16 +41198,16 @@ function flattenError2(error512, mapper = (issue32) => issue32.message) {
41105
41198
  }
41106
41199
  function formatError3(error512, mapper = (issue32) => issue32.message) {
41107
41200
  const fieldErrors = { _errors: [] };
41108
- const processError = (error522, path30 = []) => {
41201
+ const processError = (error522, path34 = []) => {
41109
41202
  for (const issue32 of error522.issues) {
41110
41203
  if (issue32.code === "invalid_union" && issue32.errors.length) {
41111
- issue32.errors.map((issues) => processError({ issues }, [...path30, ...issue32.path]));
41204
+ issue32.errors.map((issues) => processError({ issues }, [...path34, ...issue32.path]));
41112
41205
  } else if (issue32.code === "invalid_key") {
41113
- processError({ issues: issue32.issues }, [...path30, ...issue32.path]);
41206
+ processError({ issues: issue32.issues }, [...path34, ...issue32.path]);
41114
41207
  } else if (issue32.code === "invalid_element") {
41115
- processError({ issues: issue32.issues }, [...path30, ...issue32.path]);
41208
+ processError({ issues: issue32.issues }, [...path34, ...issue32.path]);
41116
41209
  } else {
41117
- const fullpath = [...path30, ...issue32.path];
41210
+ const fullpath = [...path34, ...issue32.path];
41118
41211
  if (fullpath.length === 0) {
41119
41212
  fieldErrors._errors.push(mapper(issue32));
41120
41213
  } else {
@@ -41141,17 +41234,17 @@ function formatError3(error512, mapper = (issue32) => issue32.message) {
41141
41234
  }
41142
41235
  function treeifyError2(error512, mapper = (issue32) => issue32.message) {
41143
41236
  const result = { errors: [] };
41144
- const processError = (error522, path30 = []) => {
41237
+ const processError = (error522, path34 = []) => {
41145
41238
  var _a32, _b;
41146
41239
  for (const issue32 of error522.issues) {
41147
41240
  if (issue32.code === "invalid_union" && issue32.errors.length) {
41148
- issue32.errors.map((issues) => processError({ issues }, [...path30, ...issue32.path]));
41241
+ issue32.errors.map((issues) => processError({ issues }, [...path34, ...issue32.path]));
41149
41242
  } else if (issue32.code === "invalid_key") {
41150
- processError({ issues: issue32.issues }, [...path30, ...issue32.path]);
41243
+ processError({ issues: issue32.issues }, [...path34, ...issue32.path]);
41151
41244
  } else if (issue32.code === "invalid_element") {
41152
- processError({ issues: issue32.issues }, [...path30, ...issue32.path]);
41245
+ processError({ issues: issue32.issues }, [...path34, ...issue32.path]);
41153
41246
  } else {
41154
- const fullpath = [...path30, ...issue32.path];
41247
+ const fullpath = [...path34, ...issue32.path];
41155
41248
  if (fullpath.length === 0) {
41156
41249
  result.errors.push(mapper(issue32));
41157
41250
  continue;
@@ -41183,8 +41276,8 @@ function treeifyError2(error512, mapper = (issue32) => issue32.message) {
41183
41276
  }
41184
41277
  function toDotPath2(_path) {
41185
41278
  const segs = [];
41186
- const path30 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
41187
- for (const seg of path30) {
41279
+ const path34 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
41280
+ for (const seg of path34) {
41188
41281
  if (typeof seg === "number")
41189
41282
  segs.push(`[${seg}]`);
41190
41283
  else if (typeof seg === "symbol")
@@ -53705,13 +53798,13 @@ function resolveRef2(ref, ctx) {
53705
53798
  if (!ref.startsWith("#")) {
53706
53799
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
53707
53800
  }
53708
- const path30 = ref.slice(1).split("/").filter(Boolean);
53709
- if (path30.length === 0) {
53801
+ const path34 = ref.slice(1).split("/").filter(Boolean);
53802
+ if (path34.length === 0) {
53710
53803
  return ctx.rootSchema;
53711
53804
  }
53712
53805
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
53713
- if (path30[0] === defsKey) {
53714
- const key = path30[1];
53806
+ if (path34[0] === defsKey) {
53807
+ const key = path34[1];
53715
53808
  if (!key || !ctx.defs[key]) {
53716
53809
  throw new Error(`Reference not found: ${ref}`);
53717
53810
  }
@@ -57323,7 +57416,7 @@ function inferBinName2(packageName) {
57323
57416
  }
57324
57417
  var models_default2 = {
57325
57418
  version: 1,
57326
- updatedAt: "2026-06-13T00:00:00Z",
57419
+ updatedAt: "2026-06-16T00:00:00Z",
57327
57420
  providers: {
57328
57421
  claude: {
57329
57422
  name: "Claude Code with Anthropic",
@@ -57333,7 +57426,9 @@ var models_default2 = {
57333
57426
  { modelId: "sonnet", name: "Claude Sonnet", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "medium" } },
57334
57427
  { modelId: "opus", name: "Claude Opus", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "xhigh" } },
57335
57428
  { modelId: "opus[1m]", name: "Claude Opus [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "xhigh" } },
57336
- { modelId: "claude-opus-4-6[1m]", name: "Claude Opus 4.6 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } }
57429
+ { modelId: "claude-opus-4-6[1m]", name: "Claude Opus 4.6 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } },
57430
+ { modelId: "claude-opus-4-7[1m]", name: "Claude Opus 4.7 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } },
57431
+ { modelId: "claude-opus-4-8[1m]", name: "Claude Opus 4.8 [1M]", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "high" } }
57337
57432
  ]
57338
57433
  },
57339
57434
  "claude-zai": {
@@ -60466,7 +60561,7 @@ function specToMcpTool2(spec) {
60466
60561
  }
60467
60562
  function installExecutorToolCallRouter2(runtime, sessionToken, ctx) {
60468
60563
  runtime.server.setOnToolCallArrived(sessionToken, (toolName, args) => {
60469
- const toolCallId = crypto32.randomUUID();
60564
+ const toolCallId = crypto5.randomUUID();
60470
60565
  void runtime.registry.invoke(toolName, args, { cwd: ctx.cwd, sessionLabel: ctx.sessionLabel, toolCallId, signal: ctx.signal }).then((result) => runtime.server.resolveNextToolCall(sessionToken, toolCallId, result)).catch((err) => {
60471
60566
  runtime.server.resolveNextToolCall(sessionToken, toolCallId, {
60472
60567
  content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }],
@@ -60857,7 +60952,7 @@ function createInProcessMcpServer2(deps = {}) {
60857
60952
  if (activeStopPromise) await activeStopPromise;
60858
60953
  if (activeServer && activeServerUrl) return activeServerUrl;
60859
60954
  if (activeStartPromise) return activeStartPromise;
60860
- activeOpaquePath = `/${crypto32.randomUUID()}`;
60955
+ activeOpaquePath = `/${crypto5.randomUUID()}`;
60861
60956
  activeStartPromise = new Promise((resolve2, reject) => {
60862
60957
  const srv = http2.createServer(handleRequest);
60863
60958
  srv.timeout = MCP_SERVER_TIMEOUT_MS2;
@@ -61114,7 +61209,7 @@ function createExecutorMcpSession2(deps, toolTimeoutSeconds, request) {
61114
61209
  throw new Error("Executor session cwd is required");
61115
61210
  }
61116
61211
  assertNonEmptyExecutorTools2(request.serverName, request.specs);
61117
- const token = crypto32.randomUUID();
61212
+ const token = crypto5.randomUUID();
61118
61213
  registerExecutorSessionTools2(runtime.runtime, token, [...request.specs]);
61119
61214
  installExecutorToolCallRouter2(runtime.runtime, token, {
61120
61215
  cwd,
@@ -61160,7 +61255,7 @@ function issueSessionToken2(deps, sessionTokensByLabel, request) {
61160
61255
  for (const { name, runtime } of deps.runtimes) {
61161
61256
  const tools = runtime.registry.getAllAgentTools();
61162
61257
  assertNonEmptyExecutorTools2(name, tools);
61163
- const token = crypto32.randomUUID();
61258
+ const token = crypto5.randomUUID();
61164
61259
  registerExecutorSessionTools2(runtime, token, tools);
61165
61260
  installExecutorToolCallRouter2(runtime, token, { cwd, sessionLabel: label, signal: request.signal });
61166
61261
  tokens.push({ name, token });
@@ -62526,7 +62621,8 @@ function sleepSync2(ms) {
62526
62621
  var DEFAULT_TEMP_FILE_MIN_AGE_MS2 = 6e4;
62527
62622
  function createDurableJsonStore2(deps) {
62528
62623
  const now = deps.now ?? (() => Date.now());
62529
- const mode = SECURE_FILE_MODE2;
62624
+ const sensitivity = deps.sensitivity;
62625
+ const mode = sensitivity === "sensitive" ? SECURE_FILE_MODE2 : 420;
62530
62626
  const minAgeMs = deps.tempCleanupMinAgeMs ?? DEFAULT_TEMP_FILE_MIN_AGE_MS2;
62531
62627
  const dir = path93.dirname(deps.filePath);
62532
62628
  return {
@@ -62554,10 +62650,10 @@ function createDurableJsonStore2(deps) {
62554
62650
  };
62555
62651
  function withLock(operation) {
62556
62652
  if (!deps.lockDir) {
62557
- ensureSafeDirectoryIfSensitive2(dir);
62653
+ ensureSafeDirectoryIfSensitive2(dir, sensitivity);
62558
62654
  return operation();
62559
62655
  }
62560
- ensureSafeDirectoryIfSensitive2(dir);
62656
+ ensureSafeDirectoryIfSensitive2(dir, sensitivity);
62561
62657
  return withDirectoryLock2(
62562
62658
  {
62563
62659
  lockDir: deps.lockDir,
@@ -62599,8 +62695,10 @@ function readJsonFile2(filePath, sanitize) {
62599
62695
  }
62600
62696
  }
62601
62697
  function ensureSafeDirectoryIfSensitive2(dir, sensitivity) {
62602
- {
62698
+ if (sensitivity === "sensitive") {
62603
62699
  ensureSafeDirectory2(dir);
62700
+ } else {
62701
+ fs52.mkdirSync(dir, { recursive: true });
62604
62702
  }
62605
62703
  }
62606
62704
  var memory_exports2 = {};
@@ -70278,7 +70376,7 @@ var LOCK_FILE_MODE = 384;
70278
70376
  function createConsoleLock(deps = {}) {
70279
70377
  const fsImpl = deps.fs ?? fs5__default;
70280
70378
  const now = deps.now ?? Date.now;
70281
- const randomToken = deps.randomToken ?? (() => crypto32.randomBytes(32).toString("base64url"));
70379
+ const randomToken = deps.randomToken ?? (() => crypto5.randomBytes(32).toString("base64url"));
70282
70380
  const hostname52 = deps.hostname ?? (() => "127.0.0.1");
70283
70381
  function ensureLockDir(dir) {
70284
70382
  fsImpl.mkdirSync(dir, { recursive: true, mode: LOCK_DIR_MODE });
@@ -70373,6 +70471,387 @@ function createConsoleLock(deps = {}) {
70373
70471
  }
70374
70472
  return { ensureLockDir, readLock, writeLock, removeLock, assertLockModes, assertTrustedLock };
70375
70473
  }
70474
+ var FLEET_DATA_DIR_NAME2 = ".fleet";
70475
+ function getFleetDataDir2() {
70476
+ return path93.join(os222.homedir(), FLEET_DATA_DIR_NAME2);
70477
+ }
70478
+ function readAuthStoreFile2(filePath) {
70479
+ let fd;
70480
+ try {
70481
+ fd = fs52.openSync(filePath, fs52.constants.O_RDONLY | NOFOLLOW_FLAG2);
70482
+ if (!fs52.fstatSync(fd).isFile()) {
70483
+ return {};
70484
+ }
70485
+ return JSON.parse(fs52.readFileSync(fd, "utf-8"));
70486
+ } catch {
70487
+ return {};
70488
+ } finally {
70489
+ if (fd !== void 0) {
70490
+ try {
70491
+ fs52.closeSync(fd);
70492
+ } catch {
70493
+ }
70494
+ }
70495
+ }
70496
+ }
70497
+ var DEFAULT_AUTH_PATH2 = path93.join(getFleetDataDir2(), "auth.json");
70498
+ var AUTH_LOCK_OWNER_FILE_NAME2 = "owner.json";
70499
+ var AUTH_LOCK_TIMEOUT_MS2 = 5e3;
70500
+ function createAuthService2(deps = {}) {
70501
+ const authPath = deps.authPath ?? DEFAULT_AUTH_PATH2;
70502
+ const lockDir = `${authPath}.lock`;
70503
+ return {
70504
+ // [HIGH #1] TOCTOU 수정: existsSync/read/check/delete/write 전체를 락 블록 안으로 이동
70505
+ async deleteApiKey(providerId) {
70506
+ let deleted = false;
70507
+ withAuthLock2(authPath, lockDir, () => {
70508
+ if (!fs52.existsSync(authPath)) return;
70509
+ const data = readAuthStoreFile2(authPath);
70510
+ if (!Object.prototype.hasOwnProperty.call(data, providerId)) return;
70511
+ delete data[providerId];
70512
+ writeAuthData2(authPath, data);
70513
+ deleted = true;
70514
+ });
70515
+ return deleted;
70516
+ },
70517
+ // [HIGH #2] 읽기 경로: fd 기반 O_RDONLY|O_NOFOLLOW+fstatSync isFile
70518
+ async getApiKey(providerId) {
70519
+ let fd;
70520
+ try {
70521
+ if (!fs52.existsSync(authPath)) {
70522
+ return void 0;
70523
+ }
70524
+ fd = fs52.openSync(authPath, fs52.constants.O_RDONLY | NOFOLLOW_FLAG2);
70525
+ if (!fs52.fstatSync(fd).isFile()) {
70526
+ return void 0;
70527
+ }
70528
+ const data = JSON.parse(fs52.readFileSync(fd, "utf-8"));
70529
+ return typeof data[providerId]?.key === "string" ? data[providerId].key : void 0;
70530
+ } catch {
70531
+ return void 0;
70532
+ } finally {
70533
+ if (fd !== void 0) {
70534
+ try {
70535
+ fs52.closeSync(fd);
70536
+ } catch {
70537
+ }
70538
+ }
70539
+ }
70540
+ },
70541
+ // [HIGH #2] 읽기 경로: fd 기반 O_RDONLY|O_NOFOLLOW 통일
70542
+ async listProviderIds() {
70543
+ if (!fs52.existsSync(authPath)) {
70544
+ return [];
70545
+ }
70546
+ try {
70547
+ return Object.keys(readAuthStoreFile2(authPath)).sort();
70548
+ } catch {
70549
+ return [];
70550
+ }
70551
+ },
70552
+ async setApiKey(providerId, key) {
70553
+ const dir = path93.dirname(authPath);
70554
+ ensureSafeDirectory2(dir);
70555
+ withAuthLock2(authPath, lockDir, () => {
70556
+ const data = fs52.existsSync(authPath) ? readAuthStoreFile2(authPath) : {};
70557
+ data[providerId] = {
70558
+ ...data[providerId] ?? {},
70559
+ key
70560
+ };
70561
+ writeAuthData2(authPath, data);
70562
+ });
70563
+ }
70564
+ };
70565
+ }
70566
+ function withAuthLock2(authPath, lockDir, operation) {
70567
+ return withDirectoryLock2(
70568
+ {
70569
+ lockDir,
70570
+ ownerFileName: AUTH_LOCK_OWNER_FILE_NAME2,
70571
+ timeoutMs: AUTH_LOCK_TIMEOUT_MS2
70572
+ },
70573
+ operation
70574
+ );
70575
+ }
70576
+ function writeAuthData2(authPath, data) {
70577
+ writeAtomicSync2(authPath, `${JSON.stringify(data, null, 2)}
70578
+ `, {
70579
+ mode: SECURE_FILE_MODE2,
70580
+ fsync: true
70581
+ });
70582
+ }
70583
+ function formatMissingAuthKeyMessage2(input) {
70584
+ const cliHint = input.cli ? `cli '${input.cli}'` : "selected CLI";
70585
+ return `Auth token not found for ${cliHint} (providerId: '${input.providerId}'). Run \`fleet auth login\` to register one.`;
70586
+ }
70587
+ function formatAuthValidationFailureMessage2(input) {
70588
+ const detail = input.detail ? ` Detail: ${input.detail}` : "";
70589
+ if (input.status === "unauthorized") {
70590
+ return `Auth token was rejected (providerId: '${input.providerId}'). Check the token and try again.${detail}`;
70591
+ }
70592
+ if (input.status === "forbidden") {
70593
+ return `Auth token is not allowed for this provider (providerId: '${input.providerId}'). Check the token permissions.${detail}`;
70594
+ }
70595
+ if (input.status === "timeout") {
70596
+ return `Auth token validation timed out (providerId: '${input.providerId}'). Check the connection and try again.${detail}`;
70597
+ }
70598
+ if (input.status === "network") {
70599
+ return `Auth token validation failed due to a network error (providerId: '${input.providerId}'). Check the connection and try again.${detail}`;
70600
+ }
70601
+ if (input.status === "server") {
70602
+ return `Auth token validation failed because the provider returned an error (providerId: '${input.providerId}'). Try again later.${detail}`;
70603
+ }
70604
+ return `Auth token validation failed (providerId: '${input.providerId}'). Check the token and try again.${detail}`;
70605
+ }
70606
+ var LEGACY_AUTH_PATH2 = path93.join(getFleetDataDir2(), "agent", "auth.json");
70607
+ var CURRENT_AUTH_PATH2 = path93.join(getFleetDataDir2(), "auth.json");
70608
+ function mergeAuthStoresNoOverwrite2(legacy, current) {
70609
+ const data = { ...current };
70610
+ const migratedProviderIds = [];
70611
+ const skippedProviderIds = [];
70612
+ for (const [providerId, entry] of Object.entries(legacy)) {
70613
+ if (Object.prototype.hasOwnProperty.call(data, providerId)) {
70614
+ skippedProviderIds.push(providerId);
70615
+ continue;
70616
+ }
70617
+ data[providerId] = entry;
70618
+ migratedProviderIds.push(providerId);
70619
+ }
70620
+ return {
70621
+ data,
70622
+ migratedProviderIds,
70623
+ skippedProviderIds
70624
+ };
70625
+ }
70626
+ async function migrateLegacyAuthStore2(options2 = {}) {
70627
+ const legacyPath = options2.legacyPath ?? LEGACY_AUTH_PATH2;
70628
+ const currentPath = options2.currentPath ?? CURRENT_AUTH_PATH2;
70629
+ if (!fs52.existsSync(legacyPath)) {
70630
+ return createMigrationResult2({
70631
+ legacyPath,
70632
+ currentPath,
70633
+ status: "legacy-missing",
70634
+ migratedProviderIds: [],
70635
+ skippedProviderIds: [],
70636
+ shouldPrintNotice: false
70637
+ });
70638
+ }
70639
+ const legacy = readAuthStoreFile2(legacyPath);
70640
+ const current = fs52.existsSync(currentPath) ? readAuthStoreFile2(currentPath) : {};
70641
+ const merged = mergeAuthStoresNoOverwrite2(legacy, current);
70642
+ if (merged.migratedProviderIds.length > 0) {
70643
+ const dir = path93.dirname(currentPath);
70644
+ ensureSafeDirectory2(dir);
70645
+ writeAtomicSync2(currentPath, `${JSON.stringify(merged.data, null, 2)}
70646
+ `, {
70647
+ mode: SECURE_FILE_MODE2,
70648
+ fsync: true
70649
+ });
70650
+ }
70651
+ return createMigrationResult2({
70652
+ legacyPath,
70653
+ currentPath,
70654
+ status: merged.migratedProviderIds.length > 0 ? "migrated" : "unchanged",
70655
+ migratedProviderIds: merged.migratedProviderIds,
70656
+ skippedProviderIds: merged.skippedProviderIds,
70657
+ shouldPrintNotice: options2.notify !== false && merged.migratedProviderIds.length > 0
70658
+ });
70659
+ }
70660
+ function createMigrationResult2(input) {
70661
+ return {
70662
+ legacyPath: input.legacyPath,
70663
+ currentPath: input.currentPath,
70664
+ migratedCount: input.migratedProviderIds.length,
70665
+ skippedCount: input.skippedProviderIds.length,
70666
+ migratedProviderIds: input.migratedProviderIds,
70667
+ skippedProviderIds: input.skippedProviderIds,
70668
+ shouldPrintNotice: input.shouldPrintNotice,
70669
+ status: input.status
70670
+ };
70671
+ }
70672
+ var DEFAULT_AUTH_VALIDATION_TIMEOUT_MS2 = 5e3;
70673
+ async function validateAnthropicCompatibleApiKey2(request) {
70674
+ const controller = new AbortController();
70675
+ const timeout = setTimeout(() => {
70676
+ controller.abort();
70677
+ }, request.timeoutMs ?? DEFAULT_AUTH_VALIDATION_TIMEOUT_MS2);
70678
+ try {
70679
+ const response = await fetch(buildMessagesUrl2(request.baseUrl), {
70680
+ method: "POST",
70681
+ headers: {
70682
+ "anthropic-version": "2023-06-01",
70683
+ "content-type": "application/json",
70684
+ "x-api-key": request.apiKey
70685
+ },
70686
+ body: JSON.stringify({
70687
+ model: "claude-3-5-haiku-20241022",
70688
+ max_tokens: 1,
70689
+ messages: [
70690
+ {
70691
+ role: "user",
70692
+ content: "ping"
70693
+ }
70694
+ ]
70695
+ }),
70696
+ signal: controller.signal
70697
+ });
70698
+ if (response.ok) {
70699
+ return { providerId: request.providerId, status: "success" };
70700
+ }
70701
+ if (response.status === 401) {
70702
+ return { providerId: request.providerId, status: "unauthorized" };
70703
+ }
70704
+ if (response.status === 403) {
70705
+ return { providerId: request.providerId, status: "forbidden" };
70706
+ }
70707
+ if (response.status >= 500) {
70708
+ return {
70709
+ providerId: request.providerId,
70710
+ status: "server",
70711
+ detail: `HTTP ${response.status}`
70712
+ };
70713
+ }
70714
+ return {
70715
+ providerId: request.providerId,
70716
+ status: "unknown",
70717
+ detail: `HTTP ${response.status}`
70718
+ };
70719
+ } catch (error512) {
70720
+ if (isAbortError2(error512)) {
70721
+ return { providerId: request.providerId, status: "timeout" };
70722
+ }
70723
+ return {
70724
+ providerId: request.providerId,
70725
+ status: "network",
70726
+ detail: error512 instanceof Error ? error512.message : String(error512)
70727
+ };
70728
+ } finally {
70729
+ clearTimeout(timeout);
70730
+ }
70731
+ }
70732
+ function isAuthValidationSuccess2(result) {
70733
+ return result.status === "success";
70734
+ }
70735
+ function createAuthValidationError2(result) {
70736
+ return new Error(formatAuthValidationFailureMessage2(result));
70737
+ }
70738
+ function buildMessagesUrl2(baseUrl) {
70739
+ return `${baseUrl.replace(/\/+$/, "")}/v1/messages`;
70740
+ }
70741
+ function isAbortError2(error512) {
70742
+ return error512 instanceof DOMException && error512.name === "AbortError";
70743
+ }
70744
+ var CLAUDE_ZAI_PROVIDER_ID2 = "Claude Code with Z.AI GLM";
70745
+ var CLAUDE_KIMI_PROVIDER_ID2 = "Claude Code with Moonshot Kimi";
70746
+ var AUTH_PROVIDER_DEFINITIONS2 = {
70747
+ "claude-zai": {
70748
+ providerId: CLAUDE_ZAI_PROVIDER_ID2,
70749
+ baseUrl: CLI_BACKENDS2["claude-zai"].defaultEnv.ANTHROPIC_BASE_URL,
70750
+ env: CLI_BACKENDS2["claude-zai"].defaultEnv
70751
+ },
70752
+ "claude-kimi": {
70753
+ providerId: CLAUDE_KIMI_PROVIDER_ID2,
70754
+ baseUrl: CLI_BACKENDS2["claude-kimi"].defaultEnv.ANTHROPIC_BASE_URL,
70755
+ env: CLI_BACKENDS2["claude-kimi"].defaultEnv
70756
+ }
70757
+ };
70758
+ async function resolveAuthEnv2(cli, deps) {
70759
+ const provider = AUTH_PROVIDER_DEFINITIONS2[cli];
70760
+ if (!provider) return {};
70761
+ await migrateLegacyAuthStore2();
70762
+ const auth = deps?.authService ?? createAuthService2({ authPath: DEFAULT_AUTH_PATH2 });
70763
+ const token = await auth.getApiKey(provider.providerId);
70764
+ if (!token) {
70765
+ throw new Error(formatMissingAuthKeyMessage2({ cli, providerId: provider.providerId }));
70766
+ }
70767
+ const validation = await validateAnthropicCompatibleApiKey2({
70768
+ providerId: provider.providerId,
70769
+ apiKey: token,
70770
+ baseUrl: provider.baseUrl
70771
+ });
70772
+ if (!isAuthValidationSuccess2(validation)) {
70773
+ const failure = {
70774
+ providerId: validation.providerId,
70775
+ status: validation.status,
70776
+ detail: validation.detail
70777
+ };
70778
+ throw createAuthValidationError2(failure);
70779
+ }
70780
+ return { ...provider.env, ANTHROPIC_AUTH_TOKEN: token };
70781
+ }
70782
+ var GLOBAL_OPTIONS_VERSION2 = 1;
70783
+ var GLOBAL_OPTIONS_FILE_NAME2 = "settings.json";
70784
+ var LOCK_DIR_NAME2 = "settings.json.lock";
70785
+ var LOCK_OWNER_FILE_NAME2 = "owner";
70786
+ var TEMP_FILE_PREFIX2 = `.tmp-${GLOBAL_OPTIONS_FILE_NAME2}-`;
70787
+ function createGlobalOptionsStore2(deps = {}) {
70788
+ const dataDir = deps.dataDir ?? getFleetDataDir2();
70789
+ const optionsPath = path93.join(dataDir, GLOBAL_OPTIONS_FILE_NAME2);
70790
+ const lockDir = path93.join(dataDir, LOCK_DIR_NAME2);
70791
+ const store22 = createDurableJsonStore2({
70792
+ filePath: optionsPath,
70793
+ lockDir,
70794
+ lockOwnerFileName: LOCK_OWNER_FILE_NAME2,
70795
+ sanitize: (value) => sanitizeGlobalOptionsData2(value).data,
70796
+ sensitivity: "sensitive",
70797
+ timeoutMs: deps.timeoutMs,
70798
+ staleLockMs: deps.staleLockMs,
70799
+ tempCleanupPrefix: TEMP_FILE_PREFIX2,
70800
+ now: deps.now
70801
+ });
70802
+ return {
70803
+ path: optionsPath,
70804
+ load: () => store22.load(),
70805
+ save: (data) => store22.save(sanitizeGlobalOptionsData2(data).data),
70806
+ update: (mutate) => store22.update((current) => sanitizeGlobalOptionsData2(mutate(current)).data)
70807
+ };
70808
+ }
70809
+ function createEmptyGlobalOptionsData2() {
70810
+ return {
70811
+ version: GLOBAL_OPTIONS_VERSION2
70812
+ };
70813
+ }
70814
+ function sanitizeGlobalOptionsData2(value) {
70815
+ if (!isRecord32(value)) {
70816
+ return { data: createEmptyGlobalOptionsData2(), changed: true };
70817
+ }
70818
+ if (value.version !== GLOBAL_OPTIONS_VERSION2) {
70819
+ return { data: createEmptyGlobalOptionsData2(), changed: true };
70820
+ }
70821
+ const data = {
70822
+ version: GLOBAL_OPTIONS_VERSION2,
70823
+ ...typeof value.replaceSystemPrompt === "boolean" ? { replaceSystemPrompt: value.replaceSystemPrompt } : {},
70824
+ ...typeof value.enableMetaphor === "boolean" ? { enableMetaphor: value.enableMetaphor } : {}
70825
+ };
70826
+ const allowedKeys = /* @__PURE__ */ new Set(["version", "replaceSystemPrompt", "enableMetaphor"]);
70827
+ const changed = Object.keys(value).some((key) => !allowedKeys.has(key)) || "replaceSystemPrompt" in value && typeof value.replaceSystemPrompt !== "boolean" || "enableMetaphor" in value && typeof value.enableMetaphor !== "boolean";
70828
+ return { data, changed };
70829
+ }
70830
+ function isRecord32(value) {
70831
+ return typeof value === "object" && value !== null && !Array.isArray(value);
70832
+ }
70833
+ function createGlobalOptionsService2(deps = {}) {
70834
+ const store22 = deps.store ?? createGlobalOptionsStore2({ dataDir: deps.dataDir });
70835
+ return {
70836
+ load: () => store22.load(),
70837
+ save: (data) => {
70838
+ store22.save(data);
70839
+ return store22.load();
70840
+ },
70841
+ update: (mutate) => updateGlobalOptions2(store22, mutate)
70842
+ };
70843
+ }
70844
+ function updateGlobalOptions2(store22, mutate) {
70845
+ return store22.update(mutate);
70846
+ }
70847
+ function createInfraServices2(deps = {}) {
70848
+ const globalOptionsService = createGlobalOptionsService2();
70849
+ const authService = createAuthService2({ authPath: deps.authPath ?? DEFAULT_AUTH_PATH2 });
70850
+ return {
70851
+ authService,
70852
+ globalOptionsService
70853
+ };
70854
+ }
70376
70855
  function readFleetConsoleRelease() {
70377
70856
  const requireFromHere2 = createRequire(import.meta.url);
70378
70857
  const packageJsonPath = requireFromHere2.resolve("../package.json");
@@ -70384,17 +70863,34 @@ function readFleetConsoleRelease() {
70384
70863
  }
70385
70864
  return { channel: "stable", version: version22, packageRoot };
70386
70865
  }
70387
- var LOCK_DIR_NAME2 = "fleet-console";
70866
+ var LOCK_DIR_NAME22 = "fleet-console";
70867
+ var CONSOLE_RUNTIME_DIR_NAME = "console";
70388
70868
  var LOCK_FILE_NAME = "console.lock";
70869
+ var CONSOLE_DATA_DIR_NAME = "console";
70870
+ var CONSOLE_STATE_FILE_NAME = "state.json";
70871
+ var CONSOLE_CAPTURES_DIR_NAME = "captures";
70389
70872
  function createConsolePaths(deps = {}) {
70390
70873
  const env = deps.env ?? process.env;
70391
70874
  const base = env.FLEET_CONSOLE_DIR ?? defaultConsoleBaseDir(deps);
70392
70875
  return { dir: base, lockFile: path93__default.join(base, LOCK_FILE_NAME) };
70393
70876
  }
70877
+ function createConsoleDataPaths(deps = {}) {
70878
+ const dir = path93__default.join(deps.fleetDataDir ?? getFleetDataDir2(), CONSOLE_DATA_DIR_NAME);
70879
+ return {
70880
+ dir,
70881
+ stateFile: path93__default.join(dir, CONSOLE_STATE_FILE_NAME),
70882
+ capturesDir: path93__default.join(dir, CONSOLE_CAPTURES_DIR_NAME)
70883
+ };
70884
+ }
70394
70885
  function defaultConsoleBaseDir(deps) {
70886
+ let release2;
70887
+ const channel = deps.channel ?? (release2 = readFleetConsoleRelease()).channel;
70888
+ if (channel === "local") {
70889
+ const packageRoot = deps.packageRoot ?? (release2 ??= readFleetConsoleRelease()).packageRoot;
70890
+ return path93__default.join(path93__default.resolve(packageRoot, "..", ".."), ".fleet", CONSOLE_RUNTIME_DIR_NAME);
70891
+ }
70395
70892
  const uid = deps.uid ?? (typeof process.getuid === "function" ? process.getuid() : 0);
70396
- const channel = deps.channel ?? readFleetConsoleRelease().channel;
70397
- return path93__default.join(os22__default.tmpdir(), `${LOCK_DIR_NAME2}-${uid}-${channel}`);
70893
+ return path93__default.join(os22__default.tmpdir(), `${LOCK_DIR_NAME22}-${uid}-${channel}`);
70398
70894
  }
70399
70895
  var FLEET_PROTOCOL_GATE_PROMPT2 = String.raw`# Protocol Gate
70400
70896
 
@@ -70787,6 +71283,8 @@ function createClaudeFamilyCliDefinition2(options2) {
70787
71283
  lineTerminator: "\r",
70788
71284
  multilineStrategy: "paste-mode"
70789
71285
  },
71286
+ // Claude Code 계열은 세션 이름 변경 슬래시 명령 `/rename`을 지원한다.
71287
+ renameCommand: "/rename",
70790
71288
  terminalName: "xterm-256color"
70791
71289
  };
70792
71290
  }
@@ -70810,7 +71308,7 @@ var codexCli2 = {
70810
71308
  async createProfile(options2) {
70811
71309
  const { bin, prefixArgs } = resolveBinary2("codex", "CODEX_BIN", options2.env);
70812
71310
  return {
70813
- args: [...prefixArgs, "--no-alt-screen", ...buildModelArgs22(options2.model)],
71311
+ args: [...prefixArgs, ...buildResumeArgs4(options2.resumeSessionId), "--no-alt-screen", ...buildModelArgs22(options2.model)],
70814
71312
  bin,
70815
71313
  binPrefixArgs: prefixArgs,
70816
71314
  cwd: options2.cwd,
@@ -70822,10 +71320,15 @@ var codexCli2 = {
70822
71320
  lineTerminator: "\r",
70823
71321
  multilineStrategy: "paste-mode"
70824
71322
  },
71323
+ // Codex CLI도 세션 이름 변경 슬래시 명령 `/rename`을 지원한다.
71324
+ renameCommand: "/rename",
70825
71325
  terminalName: "xterm-256color"
70826
71326
  };
70827
71327
  }
70828
71328
  };
71329
+ function buildResumeArgs4(resumeSessionId) {
71330
+ return resumeSessionId === void 0 ? [] : ["resume", resumeSessionId];
71331
+ }
70829
71332
  function buildModelArgs22(model) {
70830
71333
  return model === void 0 ? [] : ["--model", model];
70831
71334
  }
@@ -70842,7 +71345,8 @@ async function resolveAgentCliProfile2(env, cwd, options2 = {}) {
70842
71345
  authService: options2.authService,
70843
71346
  cwd,
70844
71347
  env,
70845
- model: options2.model
71348
+ model: options2.model,
71349
+ resumeSessionId: options2.resumeSessionId
70846
71350
  });
70847
71351
  }
70848
71352
  function resolveAgentCliId2(env, options2 = {}) {
@@ -70886,6 +71390,20 @@ var AGENT_CLI_INJECTION_CAPABILITIES2 = {
70886
71390
  function getAgentCliInjectionCapability2(cliId) {
70887
71391
  return AGENT_CLI_INJECTION_CAPABILITIES2[cliId];
70888
71392
  }
71393
+ function createSessionCaptureHookExec(deps) {
71394
+ const args = deps.tsxLoader ? [
71395
+ "--import",
71396
+ pathToFileURL2(deps.tsxLoader).href,
71397
+ deps.entryPath,
71398
+ "hook",
71399
+ "capture-session",
71400
+ deps.provider
71401
+ ] : [deps.entryPath, "hook", "capture-session", deps.provider];
71402
+ return {
71403
+ command: deps.execPath ?? process5.execPath,
71404
+ args
71405
+ };
71406
+ }
70889
71407
  function buildHostCarrierModelDefaults22(config22) {
70890
71408
  const cliType = resolveAgentCliType22(config22.id, config22.defaultCliType);
70891
71409
  const cliDefaults = buildCarrierModelDefaults2(config22, cliType);
@@ -70915,6 +71433,7 @@ function buildClaudeNativeSubagentPlan22(registry32) {
70915
71433
  function buildClaudeNativeArgs2(context) {
70916
71434
  const systemPromptArg = context.replaceSystemPrompt ? "--system-prompt-file" : "--append-system-prompt-file";
70917
71435
  return [
71436
+ ...buildResumeArgs22(context.resumeSessionId),
70918
71437
  systemPromptArg,
70919
71438
  requireSystemPromptFile2(context),
70920
71439
  ...context.pluginRoots.flatMap((pluginRoot) => [
@@ -70925,6 +71444,9 @@ function buildClaudeNativeArgs2(context) {
70925
71444
  "--dangerously-skip-permissions"
70926
71445
  ];
70927
71446
  }
71447
+ function buildResumeArgs22(resumeSessionId) {
71448
+ return resumeSessionId === void 0 ? [] : ["--resume", resumeSessionId];
71449
+ }
70928
71450
  function buildClaudeMcpConfig2(servers) {
70929
71451
  return JSON.stringify({
70930
71452
  mcpServers: Object.fromEntries(
@@ -70982,20 +71504,32 @@ function escapeTomlMultilineString2(value) {
70982
71504
  });
70983
71505
  return result;
70984
71506
  }
71507
+ function buildPosixShellCommand2(values) {
71508
+ return values.map(posixShellQuote2).join(" ");
71509
+ }
71510
+ function posixShellQuote2(value) {
71511
+ return `'${value.replaceAll("'", "'\\''")}'`;
71512
+ }
70985
71513
  var CODEX_TOOL_TIMEOUT_SEC2 = 1800;
70986
71514
  function buildCodexNativeArgs2(context) {
70987
71515
  const profileName = requireCodexProfileName2(context);
70988
71516
  const args = [
71517
+ ...buildResumeArgs32(context.resumeSessionId),
70989
71518
  "--enable",
70990
71519
  "plugins",
70991
71520
  "--enable",
70992
71521
  "child_agents_md",
71522
+ "--enable",
71523
+ "hooks",
70993
71524
  "--profile",
70994
71525
  profileName,
70995
71526
  "-c",
70996
71527
  'approval_policy="never"',
70997
71528
  "-c",
70998
- 'sandbox_mode="danger-full-access"'
71529
+ 'sandbox_mode="danger-full-access"',
71530
+ // hook 신뢰 프롬프트("Hooks need review")를 fleet 관리 세션에서 건너뛴다. bypass_hook_trust는
71531
+ // config 키가 아니라 전용 CLI 플래그이므로 -c override가 아닌 플래그로 전달해야 한다.
71532
+ "--dangerously-bypass-hook-trust"
70999
71533
  ];
71000
71534
  for (const server of context.mcpServers) {
71001
71535
  const prefix = `mcp_servers.${server.name}`;
@@ -71011,6 +71545,9 @@ function buildCodexNativeArgs2(context) {
71011
71545
  }
71012
71546
  return args;
71013
71547
  }
71548
+ function buildResumeArgs32(resumeSessionId) {
71549
+ return resumeSessionId === void 0 ? [] : ["resume", resumeSessionId];
71550
+ }
71014
71551
  function requireCodexProfileName2(context) {
71015
71552
  if (context.codexProfileName) return context.codexProfileName;
71016
71553
  throw new Error("Codex profile name is required for native injection");
@@ -71221,20 +71758,32 @@ function claudeHooks2(options2) {
71221
71758
  if (!hookExec) {
71222
71759
  throw new Error("Fleet Claude session hook command is required");
71223
71760
  }
71761
+ const captureSessionHookExec = options2.captureSessionHookExec;
71224
71762
  return {
71225
71763
  hooks: {
71226
71764
  SessionStart: [{
71227
- hooks: [{
71228
- // exec 형식: command는 직접 spawn되는 실행 파일, args는 셸 토크나이징 없이 그대로 전달된다.
71229
- // Windows cmd/powershell의 따옴표 규칙과 무관하게 동작하며 공백 포함 경로도 안전하다.
71230
- args: [...hookExec.args],
71231
- command: hookExec.command,
71232
- type: "command"
71765
+ hooks: [claudeCommandHook2(hookExec)]
71766
+ }],
71767
+ ...captureSessionHookExec ? {
71768
+ UserPromptSubmit: [{
71769
+ hooks: [claudeCommandHook2(captureSessionHookExec)]
71233
71770
  }]
71234
- }]
71771
+ } : {}
71235
71772
  }
71236
71773
  };
71237
71774
  }
71775
+ function claudeCommandHook2(hookExec) {
71776
+ if (!hookExec) {
71777
+ throw new Error("Fleet Claude session hook command is required");
71778
+ }
71779
+ return {
71780
+ // exec 형식: command는 직접 spawn되는 실행 파일, args는 셸 토크나이징 없이 그대로 전달된다.
71781
+ // Windows cmd/powershell의 따옴표 규칙과 무관하게 동작하며 공백 포함 경로도 안전하다.
71782
+ args: [...hookExec.args],
71783
+ command: hookExec.command,
71784
+ type: "command"
71785
+ };
71786
+ }
71238
71787
  function claudeAgentFile2(subagent) {
71239
71788
  const frontmatter = [
71240
71789
  "---",
@@ -71744,7 +72293,7 @@ function homeMarketplaceTarget2(fleetRoot) {
71744
72293
  }
71745
72294
  function projectMarketplaceTarget2(cwd) {
71746
72295
  const projectFleetRoot = resolveProjectFleetRoot2(cwd);
71747
- const hash22 = crypto32.createHash("sha256").update(path93__default.resolve(cwd, ".fleet")).digest("hex").slice(0, 12);
72296
+ const hash22 = crypto5.createHash("sha256").update(path93__default.resolve(cwd, ".fleet")).digest("hex").slice(0, 12);
71748
72297
  return {
71749
72298
  flat: true,
71750
72299
  name: `${FLEET_PROJECT_MARKETPLACE_NAME_PREFIX2}-${hash22}`,
@@ -71770,7 +72319,6 @@ function renderPluginRoot2(pluginRoot, bundle, options2, fleetRoot) {
71770
72319
  const stagedPluginRoot = path93__default.join(stageParent, path93__default.basename(pluginRoot));
71771
72320
  try {
71772
72321
  ensurePrivateDir2(stagedPluginRoot, stagedPluginRoot);
71773
- writePrivateJson2(path93__default.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest2(bundle), stagedPluginRoot);
71774
72322
  writePrivateJson2(path93__default.join(stagedPluginRoot, ".claude-plugin", "plugin.json"), claudeManifest2(bundle), stagedPluginRoot);
71775
72323
  switch (bundle.source) {
71776
72324
  case "asset":
@@ -71785,6 +72333,7 @@ function renderPluginRoot2(pluginRoot, bundle, options2, fleetRoot) {
71785
72333
  renderGlobalPluginRoot2(stagedPluginRoot, fleetRoot);
71786
72334
  break;
71787
72335
  }
72336
+ writePrivateJson2(path93__default.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest2(bundle, stagedPluginRoot), stagedPluginRoot);
71788
72337
  removePrivatePath2(pluginRoot, parentRoot);
71789
72338
  renameSync5(stagedPluginRoot, pluginRoot);
71790
72339
  } finally {
@@ -71813,7 +72362,7 @@ function pruneMarketplaceRoot2(target) {
71813
72362
  }
71814
72363
  }
71815
72364
  function buildContentHash2(target) {
71816
- const hash22 = crypto32.createHash("sha256");
72365
+ const hash22 = crypto5.createHash("sha256");
71817
72366
  for (const filePath of listRenderableFiles2(target)) {
71818
72367
  const relativePath2 = path93__default.relative(target.root, filePath);
71819
72368
  hash22.update(relativePath2);
@@ -71916,14 +72465,36 @@ function marketplacePluginPath2(target, bundle) {
71916
72465
  if (target.flat) return `./${FLAT_PLUGIN_DIR_NAME2}`;
71917
72466
  return `./${PLUGIN_BUNDLES_DIR_NAME2}/${bundle.directoryName}`;
71918
72467
  }
71919
- function codexManifest2(bundle) {
72468
+ function codexManifest2(bundle, pluginRoot) {
71920
72469
  return {
71921
72470
  name: bundle.name,
71922
- version: "0.0.0",
72471
+ version: codexManifestVersion2(bundle, pluginRoot),
71923
72472
  description: bundle.description,
71924
72473
  skills: "./skills/"
71925
72474
  };
71926
72475
  }
72476
+ function codexManifestVersion2(bundle, pluginRoot) {
72477
+ const hash22 = crypto5.createHash("sha256");
72478
+ hash22.update(bundle.name);
72479
+ hash22.update("\0");
72480
+ hash22.update(bundle.description);
72481
+ hash22.update("\0");
72482
+ for (const filePath of listCodexEffectivePluginFiles2(pluginRoot)) {
72483
+ const relativePath2 = path93__default.relative(pluginRoot, filePath);
72484
+ hash22.update(relativePath2);
72485
+ hash22.update("\0");
72486
+ hash22.update(readFileSync8(filePath));
72487
+ hash22.update("\0");
72488
+ }
72489
+ return `0.0.0+${hash22.digest("hex").slice(0, 12)}`;
72490
+ }
72491
+ function listCodexEffectivePluginFiles2(pluginRoot) {
72492
+ const skillsPath = path93__default.join(pluginRoot, "skills");
72493
+ if (!existsSync8(skillsPath)) return [];
72494
+ const files = [];
72495
+ collectRenderableFiles2(pluginRoot, skillsPath, files, /* @__PURE__ */ new Set());
72496
+ return files.sort();
72497
+ }
71927
72498
  function claudeManifest2(bundle) {
71928
72499
  return {
71929
72500
  name: bundle.name,
@@ -71943,7 +72514,7 @@ async function injectAgentCliProfile2(profile, options2) {
71943
72514
  const injectTone = options2.enableMetaphor ?? false;
71944
72515
  const endpoint = await options2.dedicatedMcpSession.getEndpoint();
71945
72516
  const startupDefinitions = buildStartupNativeDefinitions2(profile.id, options2.carrierRuntime);
71946
- const tokenLabel = options2.mcpSessionLabel ?? `agent:${profile.id}:${crypto32.randomUUID()}`;
72517
+ const tokenLabel = options2.mcpSessionLabel ?? `agent:${profile.id}:${crypto5.randomUUID()}`;
71947
72518
  const tokens = await options2.dedicatedMcpSession.issueSessionToken({ cwd: profile.cwd, label: tokenLabel });
71948
72519
  const mcpServers = buildAgentCliMcpServerConfigs2(endpoint.servers, tokens);
71949
72520
  const doctrine = options2.buildSystemPrompt(injectTone);
@@ -71957,11 +72528,12 @@ async function injectAgentCliProfile2(profile, options2) {
71957
72528
  cwd: profile.cwd,
71958
72529
  dataDir: options2.dataDir,
71959
72530
  rootDir: options2.pluginRootDir,
72531
+ captureSessionHookExec: options2.captureSessionHookExec,
71960
72532
  hookExec: startupDefinitions.host === "claude" ? requireHookExec2(options2.hookExec) : void 0,
71961
72533
  withMarketplaceLock: options2.withMarketplaceLock
71962
72534
  });
71963
72535
  const codexPluginKeys = plugin.codexRegistrations.map((registration) => `${registration.pluginName}@${registration.marketplaceName}`);
71964
- const codexProfile = profile.id === "codex" ? writeCodexFleetProfile2(profile.env, doctrine, codexPluginKeys, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
72536
+ const codexProfile = profile.id === "codex" ? writeCodexFleetProfile2(profile.env, doctrine, codexPluginKeys, options2.captureSessionHookExec, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
71965
72537
  const launchWarnings = [];
71966
72538
  for (const registration of plugin.codexRegistrations) {
71967
72539
  const registrationWarning = await ensureCodexPluginRegistered2(registration, {
@@ -71988,13 +72560,14 @@ async function injectAgentCliProfile2(profile, options2) {
71988
72560
  pluginRoot: plugin.pluginRoot,
71989
72561
  pluginRoots: plugin.pluginRoots,
71990
72562
  codexProfileName: codexProfile?.profileName,
71991
- replaceSystemPrompt: options2.replaceSystemPrompt ?? true,
72563
+ replaceSystemPrompt: options2.replaceSystemPrompt ?? false,
72564
+ resumeSessionId: options2.resumeSessionId,
71992
72565
  systemPromptFile
71993
72566
  };
71994
72567
  const injectedArgs = buildAgentCliArgs2(capability.builderId, context);
71995
72568
  return {
71996
72569
  ...profile,
71997
- args: [...profile.args, ...injectedArgs],
72570
+ args: mergeAgentCliArgs2(profile, capability.builderId, context, injectedArgs),
71998
72571
  cleanup,
71999
72572
  launchWarnings: [...profile.launchWarnings ?? [], ...launchWarnings]
72000
72573
  };
@@ -72036,11 +72609,11 @@ function writeSystemPromptFile2(cliId, systemPrompt, onCleanup) {
72036
72609
  chmodBestEffort22(filePath, SYSTEM_PROMPT_FILE_MODE2);
72037
72610
  return filePath;
72038
72611
  }
72039
- function writeCodexFleetProfile2(env, doctrine, pluginKeys, onCleanup) {
72612
+ function writeCodexFleetProfile2(env, doctrine, pluginKeys, captureSessionHookExec, onCleanup) {
72040
72613
  const codexHome = env.CODEX_HOME ?? path93__default.join(env.HOME ?? os22__default.homedir(), ".codex");
72041
72614
  mkdirSync8(codexHome, { recursive: true });
72042
72615
  pruneStaleCodexFleetProfiles2(codexHome);
72043
- const profileName = `fleet-${crypto32.randomUUID()}`;
72616
+ const profileName = `fleet-${crypto5.randomUUID()}`;
72044
72617
  const profilePath = path93__default.join(codexHome, `${profileName}.config.toml`);
72045
72618
  onCleanup(() => rmBestEffort2(profilePath));
72046
72619
  writeFileNoFollow22(profilePath, [
@@ -72055,11 +72628,21 @@ function writeCodexFleetProfile2(env, doctrine, pluginKeys, onCleanup) {
72055
72628
  `[plugins."${escapeTomlBasicString22(pluginKey)}"]`,
72056
72629
  "enabled = true",
72057
72630
  ""
72058
- ])
72631
+ ]),
72632
+ ...codexCaptureHookConfig2(captureSessionHookExec)
72059
72633
  ].join("\n"));
72060
72634
  chmodBestEffort22(profilePath, SYSTEM_PROMPT_FILE_MODE2);
72061
72635
  return { profileName, profilePath };
72062
72636
  }
72637
+ function codexCaptureHookConfig2(captureSessionHookExec) {
72638
+ if (captureSessionHookExec === void 0) return [];
72639
+ const command22 = buildPosixShellCommand2([captureSessionHookExec.command, ...captureSessionHookExec.args]);
72640
+ return [
72641
+ "[hooks]",
72642
+ `UserPromptSubmit = [{ hooks = [{ type = "command", command = "${escapeTomlBasicString22(command22)}" }] }]`,
72643
+ ""
72644
+ ];
72645
+ }
72063
72646
  function writeFileNoFollow22(filePath, content) {
72064
72647
  const flags = constants8.O_WRONLY | constants8.O_CREAT | constants8.O_TRUNC | constants8.O_NOFOLLOW;
72065
72648
  const fd = openSync8(filePath, flags, SYSTEM_PROMPT_FILE_MODE2);
@@ -72132,6 +72715,24 @@ function buildAgentCliArgs2(builderId, context) {
72132
72715
  return buildCodexNativeArgs2(context);
72133
72716
  }
72134
72717
  }
72718
+ function mergeAgentCliArgs2(profile, builderId, context, injectedArgs) {
72719
+ if (builderId !== "codex-native" || context.resumeSessionId === void 0) {
72720
+ return [...profile.args, ...injectedArgs];
72721
+ }
72722
+ const resumeSessionId = context.resumeSessionId;
72723
+ const prefixLength = profile.binPrefixArgs?.length ?? 0;
72724
+ const codexResumeArgs = ["resume", resumeSessionId];
72725
+ const injectedTail = injectedArgs.slice(codexResumeArgs.length);
72726
+ return [
72727
+ ...profile.args.slice(0, prefixLength),
72728
+ ...codexResumeArgs,
72729
+ ...profile.args.slice(prefixLength).filter((arg, index, args) => !isCodexResumeArgAt2(args, index, resumeSessionId)),
72730
+ ...injectedTail
72731
+ ];
72732
+ }
72733
+ function isCodexResumeArgAt2(args, index, resumeSessionId) {
72734
+ return args[index] === "resume" && args[index + 1] === resumeSessionId || args[index] === resumeSessionId && args[index - 1] === "resume";
72735
+ }
72135
72736
  function createOnceCleanup2(cleanup) {
72136
72737
  let cleaned = false;
72137
72738
  return () => {
@@ -72315,387 +72916,6 @@ function applyMessagePolicy2(text, policy) {
72315
72916
  submit: policy.lineTerminator
72316
72917
  };
72317
72918
  }
72318
- var FLEET_DATA_DIR_NAME2 = ".fleet";
72319
- function getFleetDataDir2() {
72320
- return path93.join(os222.homedir(), FLEET_DATA_DIR_NAME2);
72321
- }
72322
- function readAuthStoreFile2(filePath) {
72323
- let fd;
72324
- try {
72325
- fd = fs52.openSync(filePath, fs52.constants.O_RDONLY | NOFOLLOW_FLAG2);
72326
- if (!fs52.fstatSync(fd).isFile()) {
72327
- return {};
72328
- }
72329
- return JSON.parse(fs52.readFileSync(fd, "utf-8"));
72330
- } catch {
72331
- return {};
72332
- } finally {
72333
- if (fd !== void 0) {
72334
- try {
72335
- fs52.closeSync(fd);
72336
- } catch {
72337
- }
72338
- }
72339
- }
72340
- }
72341
- var DEFAULT_AUTH_PATH2 = path93.join(getFleetDataDir2(), "auth.json");
72342
- var AUTH_LOCK_OWNER_FILE_NAME2 = "owner.json";
72343
- var AUTH_LOCK_TIMEOUT_MS2 = 5e3;
72344
- function createAuthService2(deps = {}) {
72345
- const authPath = deps.authPath ?? DEFAULT_AUTH_PATH2;
72346
- const lockDir = `${authPath}.lock`;
72347
- return {
72348
- // [HIGH #1] TOCTOU 수정: existsSync/read/check/delete/write 전체를 락 블록 안으로 이동
72349
- async deleteApiKey(providerId) {
72350
- let deleted = false;
72351
- withAuthLock2(authPath, lockDir, () => {
72352
- if (!fs52.existsSync(authPath)) return;
72353
- const data = readAuthStoreFile2(authPath);
72354
- if (!Object.prototype.hasOwnProperty.call(data, providerId)) return;
72355
- delete data[providerId];
72356
- writeAuthData2(authPath, data);
72357
- deleted = true;
72358
- });
72359
- return deleted;
72360
- },
72361
- // [HIGH #2] 읽기 경로: fd 기반 O_RDONLY|O_NOFOLLOW+fstatSync isFile
72362
- async getApiKey(providerId) {
72363
- let fd;
72364
- try {
72365
- if (!fs52.existsSync(authPath)) {
72366
- return void 0;
72367
- }
72368
- fd = fs52.openSync(authPath, fs52.constants.O_RDONLY | NOFOLLOW_FLAG2);
72369
- if (!fs52.fstatSync(fd).isFile()) {
72370
- return void 0;
72371
- }
72372
- const data = JSON.parse(fs52.readFileSync(fd, "utf-8"));
72373
- return typeof data[providerId]?.key === "string" ? data[providerId].key : void 0;
72374
- } catch {
72375
- return void 0;
72376
- } finally {
72377
- if (fd !== void 0) {
72378
- try {
72379
- fs52.closeSync(fd);
72380
- } catch {
72381
- }
72382
- }
72383
- }
72384
- },
72385
- // [HIGH #2] 읽기 경로: fd 기반 O_RDONLY|O_NOFOLLOW 통일
72386
- async listProviderIds() {
72387
- if (!fs52.existsSync(authPath)) {
72388
- return [];
72389
- }
72390
- try {
72391
- return Object.keys(readAuthStoreFile2(authPath)).sort();
72392
- } catch {
72393
- return [];
72394
- }
72395
- },
72396
- async setApiKey(providerId, key) {
72397
- const dir = path93.dirname(authPath);
72398
- ensureSafeDirectory2(dir);
72399
- withAuthLock2(authPath, lockDir, () => {
72400
- const data = fs52.existsSync(authPath) ? readAuthStoreFile2(authPath) : {};
72401
- data[providerId] = {
72402
- ...data[providerId] ?? {},
72403
- key
72404
- };
72405
- writeAuthData2(authPath, data);
72406
- });
72407
- }
72408
- };
72409
- }
72410
- function withAuthLock2(authPath, lockDir, operation) {
72411
- return withDirectoryLock2(
72412
- {
72413
- lockDir,
72414
- ownerFileName: AUTH_LOCK_OWNER_FILE_NAME2,
72415
- timeoutMs: AUTH_LOCK_TIMEOUT_MS2
72416
- },
72417
- operation
72418
- );
72419
- }
72420
- function writeAuthData2(authPath, data) {
72421
- writeAtomicSync2(authPath, `${JSON.stringify(data, null, 2)}
72422
- `, {
72423
- mode: SECURE_FILE_MODE2,
72424
- fsync: true
72425
- });
72426
- }
72427
- function formatMissingAuthKeyMessage2(input) {
72428
- const cliHint = input.cli ? `cli '${input.cli}'` : "selected CLI";
72429
- return `Auth token not found for ${cliHint} (providerId: '${input.providerId}'). Run \`fleet auth login\` to register one.`;
72430
- }
72431
- function formatAuthValidationFailureMessage2(input) {
72432
- const detail = input.detail ? ` Detail: ${input.detail}` : "";
72433
- if (input.status === "unauthorized") {
72434
- return `Auth token was rejected (providerId: '${input.providerId}'). Check the token and try again.${detail}`;
72435
- }
72436
- if (input.status === "forbidden") {
72437
- return `Auth token is not allowed for this provider (providerId: '${input.providerId}'). Check the token permissions.${detail}`;
72438
- }
72439
- if (input.status === "timeout") {
72440
- return `Auth token validation timed out (providerId: '${input.providerId}'). Check the connection and try again.${detail}`;
72441
- }
72442
- if (input.status === "network") {
72443
- return `Auth token validation failed due to a network error (providerId: '${input.providerId}'). Check the connection and try again.${detail}`;
72444
- }
72445
- if (input.status === "server") {
72446
- return `Auth token validation failed because the provider returned an error (providerId: '${input.providerId}'). Try again later.${detail}`;
72447
- }
72448
- return `Auth token validation failed (providerId: '${input.providerId}'). Check the token and try again.${detail}`;
72449
- }
72450
- var LEGACY_AUTH_PATH2 = path93.join(getFleetDataDir2(), "agent", "auth.json");
72451
- var CURRENT_AUTH_PATH2 = path93.join(getFleetDataDir2(), "auth.json");
72452
- function mergeAuthStoresNoOverwrite2(legacy, current) {
72453
- const data = { ...current };
72454
- const migratedProviderIds = [];
72455
- const skippedProviderIds = [];
72456
- for (const [providerId, entry] of Object.entries(legacy)) {
72457
- if (Object.prototype.hasOwnProperty.call(data, providerId)) {
72458
- skippedProviderIds.push(providerId);
72459
- continue;
72460
- }
72461
- data[providerId] = entry;
72462
- migratedProviderIds.push(providerId);
72463
- }
72464
- return {
72465
- data,
72466
- migratedProviderIds,
72467
- skippedProviderIds
72468
- };
72469
- }
72470
- async function migrateLegacyAuthStore2(options2 = {}) {
72471
- const legacyPath = options2.legacyPath ?? LEGACY_AUTH_PATH2;
72472
- const currentPath = options2.currentPath ?? CURRENT_AUTH_PATH2;
72473
- if (!fs52.existsSync(legacyPath)) {
72474
- return createMigrationResult2({
72475
- legacyPath,
72476
- currentPath,
72477
- status: "legacy-missing",
72478
- migratedProviderIds: [],
72479
- skippedProviderIds: [],
72480
- shouldPrintNotice: false
72481
- });
72482
- }
72483
- const legacy = readAuthStoreFile2(legacyPath);
72484
- const current = fs52.existsSync(currentPath) ? readAuthStoreFile2(currentPath) : {};
72485
- const merged = mergeAuthStoresNoOverwrite2(legacy, current);
72486
- if (merged.migratedProviderIds.length > 0) {
72487
- const dir = path93.dirname(currentPath);
72488
- ensureSafeDirectory2(dir);
72489
- writeAtomicSync2(currentPath, `${JSON.stringify(merged.data, null, 2)}
72490
- `, {
72491
- mode: SECURE_FILE_MODE2,
72492
- fsync: true
72493
- });
72494
- }
72495
- return createMigrationResult2({
72496
- legacyPath,
72497
- currentPath,
72498
- status: merged.migratedProviderIds.length > 0 ? "migrated" : "unchanged",
72499
- migratedProviderIds: merged.migratedProviderIds,
72500
- skippedProviderIds: merged.skippedProviderIds,
72501
- shouldPrintNotice: options2.notify !== false && merged.migratedProviderIds.length > 0
72502
- });
72503
- }
72504
- function createMigrationResult2(input) {
72505
- return {
72506
- legacyPath: input.legacyPath,
72507
- currentPath: input.currentPath,
72508
- migratedCount: input.migratedProviderIds.length,
72509
- skippedCount: input.skippedProviderIds.length,
72510
- migratedProviderIds: input.migratedProviderIds,
72511
- skippedProviderIds: input.skippedProviderIds,
72512
- shouldPrintNotice: input.shouldPrintNotice,
72513
- status: input.status
72514
- };
72515
- }
72516
- var DEFAULT_AUTH_VALIDATION_TIMEOUT_MS2 = 5e3;
72517
- async function validateAnthropicCompatibleApiKey2(request) {
72518
- const controller = new AbortController();
72519
- const timeout = setTimeout(() => {
72520
- controller.abort();
72521
- }, request.timeoutMs ?? DEFAULT_AUTH_VALIDATION_TIMEOUT_MS2);
72522
- try {
72523
- const response = await fetch(buildMessagesUrl2(request.baseUrl), {
72524
- method: "POST",
72525
- headers: {
72526
- "anthropic-version": "2023-06-01",
72527
- "content-type": "application/json",
72528
- "x-api-key": request.apiKey
72529
- },
72530
- body: JSON.stringify({
72531
- model: "claude-3-5-haiku-20241022",
72532
- max_tokens: 1,
72533
- messages: [
72534
- {
72535
- role: "user",
72536
- content: "ping"
72537
- }
72538
- ]
72539
- }),
72540
- signal: controller.signal
72541
- });
72542
- if (response.ok) {
72543
- return { providerId: request.providerId, status: "success" };
72544
- }
72545
- if (response.status === 401) {
72546
- return { providerId: request.providerId, status: "unauthorized" };
72547
- }
72548
- if (response.status === 403) {
72549
- return { providerId: request.providerId, status: "forbidden" };
72550
- }
72551
- if (response.status >= 500) {
72552
- return {
72553
- providerId: request.providerId,
72554
- status: "server",
72555
- detail: `HTTP ${response.status}`
72556
- };
72557
- }
72558
- return {
72559
- providerId: request.providerId,
72560
- status: "unknown",
72561
- detail: `HTTP ${response.status}`
72562
- };
72563
- } catch (error512) {
72564
- if (isAbortError2(error512)) {
72565
- return { providerId: request.providerId, status: "timeout" };
72566
- }
72567
- return {
72568
- providerId: request.providerId,
72569
- status: "network",
72570
- detail: error512 instanceof Error ? error512.message : String(error512)
72571
- };
72572
- } finally {
72573
- clearTimeout(timeout);
72574
- }
72575
- }
72576
- function isAuthValidationSuccess2(result) {
72577
- return result.status === "success";
72578
- }
72579
- function createAuthValidationError2(result) {
72580
- return new Error(formatAuthValidationFailureMessage2(result));
72581
- }
72582
- function buildMessagesUrl2(baseUrl) {
72583
- return `${baseUrl.replace(/\/+$/, "")}/v1/messages`;
72584
- }
72585
- function isAbortError2(error512) {
72586
- return error512 instanceof DOMException && error512.name === "AbortError";
72587
- }
72588
- var CLAUDE_ZAI_PROVIDER_ID2 = "Claude Code with Z.AI GLM";
72589
- var CLAUDE_KIMI_PROVIDER_ID2 = "Claude Code with Moonshot Kimi";
72590
- var AUTH_PROVIDER_DEFINITIONS2 = {
72591
- "claude-zai": {
72592
- providerId: CLAUDE_ZAI_PROVIDER_ID2,
72593
- baseUrl: CLI_BACKENDS2["claude-zai"].defaultEnv.ANTHROPIC_BASE_URL,
72594
- env: CLI_BACKENDS2["claude-zai"].defaultEnv
72595
- },
72596
- "claude-kimi": {
72597
- providerId: CLAUDE_KIMI_PROVIDER_ID2,
72598
- baseUrl: CLI_BACKENDS2["claude-kimi"].defaultEnv.ANTHROPIC_BASE_URL,
72599
- env: CLI_BACKENDS2["claude-kimi"].defaultEnv
72600
- }
72601
- };
72602
- async function resolveAuthEnv2(cli, deps) {
72603
- const provider = AUTH_PROVIDER_DEFINITIONS2[cli];
72604
- if (!provider) return {};
72605
- await migrateLegacyAuthStore2();
72606
- const auth = deps?.authService ?? createAuthService2({ authPath: DEFAULT_AUTH_PATH2 });
72607
- const token = await auth.getApiKey(provider.providerId);
72608
- if (!token) {
72609
- throw new Error(formatMissingAuthKeyMessage2({ cli, providerId: provider.providerId }));
72610
- }
72611
- const validation = await validateAnthropicCompatibleApiKey2({
72612
- providerId: provider.providerId,
72613
- apiKey: token,
72614
- baseUrl: provider.baseUrl
72615
- });
72616
- if (!isAuthValidationSuccess2(validation)) {
72617
- const failure = {
72618
- providerId: validation.providerId,
72619
- status: validation.status,
72620
- detail: validation.detail
72621
- };
72622
- throw createAuthValidationError2(failure);
72623
- }
72624
- return { ...provider.env, ANTHROPIC_AUTH_TOKEN: token };
72625
- }
72626
- var GLOBAL_OPTIONS_VERSION2 = 1;
72627
- var GLOBAL_OPTIONS_FILE_NAME2 = "settings.json";
72628
- var LOCK_DIR_NAME22 = "settings.json.lock";
72629
- var LOCK_OWNER_FILE_NAME2 = "owner";
72630
- var TEMP_FILE_PREFIX2 = `.tmp-${GLOBAL_OPTIONS_FILE_NAME2}-`;
72631
- function createGlobalOptionsStore2(deps = {}) {
72632
- const dataDir = deps.dataDir ?? getFleetDataDir2();
72633
- const optionsPath = path93.join(dataDir, GLOBAL_OPTIONS_FILE_NAME2);
72634
- const lockDir = path93.join(dataDir, LOCK_DIR_NAME22);
72635
- const store22 = createDurableJsonStore2({
72636
- filePath: optionsPath,
72637
- lockDir,
72638
- lockOwnerFileName: LOCK_OWNER_FILE_NAME2,
72639
- sanitize: (value) => sanitizeGlobalOptionsData2(value).data,
72640
- sensitivity: "sensitive",
72641
- timeoutMs: deps.timeoutMs,
72642
- staleLockMs: deps.staleLockMs,
72643
- tempCleanupPrefix: TEMP_FILE_PREFIX2,
72644
- now: deps.now
72645
- });
72646
- return {
72647
- path: optionsPath,
72648
- load: () => store22.load(),
72649
- save: (data) => store22.save(sanitizeGlobalOptionsData2(data).data),
72650
- update: (mutate) => store22.update((current) => sanitizeGlobalOptionsData2(mutate(current)).data)
72651
- };
72652
- }
72653
- function createEmptyGlobalOptionsData2() {
72654
- return {
72655
- version: GLOBAL_OPTIONS_VERSION2
72656
- };
72657
- }
72658
- function sanitizeGlobalOptionsData2(value) {
72659
- if (!isRecord32(value)) {
72660
- return { data: createEmptyGlobalOptionsData2(), changed: true };
72661
- }
72662
- if (value.version !== GLOBAL_OPTIONS_VERSION2) {
72663
- return { data: createEmptyGlobalOptionsData2(), changed: true };
72664
- }
72665
- const data = {
72666
- version: GLOBAL_OPTIONS_VERSION2,
72667
- ...typeof value.replaceSystemPrompt === "boolean" ? { replaceSystemPrompt: value.replaceSystemPrompt } : {},
72668
- ...typeof value.enableMetaphor === "boolean" ? { enableMetaphor: value.enableMetaphor } : {}
72669
- };
72670
- const allowedKeys = /* @__PURE__ */ new Set(["version", "replaceSystemPrompt", "enableMetaphor"]);
72671
- const changed = Object.keys(value).some((key) => !allowedKeys.has(key)) || "replaceSystemPrompt" in value && typeof value.replaceSystemPrompt !== "boolean" || "enableMetaphor" in value && typeof value.enableMetaphor !== "boolean";
72672
- return { data, changed };
72673
- }
72674
- function isRecord32(value) {
72675
- return typeof value === "object" && value !== null && !Array.isArray(value);
72676
- }
72677
- function createGlobalOptionsService2(deps = {}) {
72678
- const store22 = deps.store ?? createGlobalOptionsStore2({ dataDir: deps.dataDir });
72679
- return {
72680
- load: () => store22.load(),
72681
- save: (data) => {
72682
- store22.save(data);
72683
- return store22.load();
72684
- },
72685
- update: (mutate) => updateGlobalOptions2(store22, mutate)
72686
- };
72687
- }
72688
- function updateGlobalOptions2(store22, mutate) {
72689
- return store22.update(mutate);
72690
- }
72691
- function createInfraServices2(deps = {}) {
72692
- const globalOptionsService = createGlobalOptionsService2();
72693
- const authService = createAuthService2({ authPath: deps.authPath ?? DEFAULT_AUTH_PATH2 });
72694
- return {
72695
- authService,
72696
- globalOptionsService
72697
- };
72698
- }
72699
72919
  var FLEET_WIKI_ENTRY_BEGIN = "<<<FLEET_WIKI_ENTRY_BEGIN";
72700
72920
  var FLEET_WIKI_ENTRY_END = "<<<FLEET_WIKI_ENTRY_END>>>";
72701
72921
  var FLEET_WIKI_RAW_SOURCE_BEGIN = "<<<FLEET_WIKI_RAW_SOURCE_BEGIN";
@@ -73722,7 +73942,7 @@ function stripLeadingFrontmatter(body) {
73722
73942
  return stripped ? next : body;
73723
73943
  }
73724
73944
  function computeContentHash(content) {
73725
- return crypto32.createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
73945
+ return crypto5.createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
73726
73946
  }
73727
73947
  function assertWithinRawDir(absolutePath, paths) {
73728
73948
  const relative2 = path93__default.relative(paths.rawDir, absolutePath);
@@ -73935,7 +74155,7 @@ async function writeAtomic(filePath, content, paths) {
73935
74155
  await ensureMemoryRoot(paths);
73936
74156
  const tempPath = path93__default.join(
73937
74157
  path93__default.dirname(filePath),
73938
- `.tmp-${process.pid}-${Date.now()}-${crypto32.randomUUID()}-${os22__default.hostname()}`
74158
+ `.tmp-${process.pid}-${Date.now()}-${crypto5.randomUUID()}-${os22__default.hostname()}`
73939
74159
  );
73940
74160
  await writeFile2(tempPath, content, "utf8");
73941
74161
  await rename(tempPath, filePath);
@@ -76472,7 +76692,7 @@ function parseOptionalIsoDate(value) {
76472
76692
  return Number.isFinite(timestamp) ? timestamp : null;
76473
76693
  }
76474
76694
  function hashBodyForComparison(body) {
76475
- return crypto32.createHash("sha256").update(body.replace(/\s+/g, " ").trim(), "utf8").digest("hex").slice(0, 8);
76695
+ return crypto5.createHash("sha256").update(body.replace(/\s+/g, " ").trim(), "utf8").digest("hex").slice(0, 8);
76476
76696
  }
76477
76697
  function hasConflictingStatuses(entries) {
76478
76698
  const statuses = new Set(entries.map((entry) => entry.status).filter((status) => status !== "unknown"));
@@ -78654,6 +78874,418 @@ function buildWikiToolSpec(config22, usage) {
78654
78874
  }
78655
78875
  };
78656
78876
  }
78877
+ var SUBAGENT_CLI_TYPES = /* @__PURE__ */ new Set(["claude", "claude-zai", "claude-kimi"]);
78878
+ var TASKFORCE_MIN_BACKENDS = 2;
78879
+ function createCarrierSettingsRouter(deps) {
78880
+ const controller = createStatusOverlayController(deps.registry);
78881
+ return async function handleCarrierSettingsRoute(context) {
78882
+ const { req, res, pathname } = context;
78883
+ if (pathname === "/carrier-settings/state") {
78884
+ if (req.method !== "GET") {
78885
+ deps.writeJson(res, 405, { error: "Method not allowed" });
78886
+ return true;
78887
+ }
78888
+ deps.writeJson(res, 200, buildCarrierSettingsState(deps.registry));
78889
+ return true;
78890
+ }
78891
+ if (pathname === "/carrier-settings/options") {
78892
+ if (req.method !== "GET") {
78893
+ deps.writeJson(res, 405, { error: "Method not allowed" });
78894
+ return true;
78895
+ }
78896
+ deps.writeJson(res, 200, buildCarrierSettingsOptions());
78897
+ return true;
78898
+ }
78899
+ const mutation = parseCarrierMutation(pathname);
78900
+ if (!mutation) return false;
78901
+ await handleCarrierMutation(req, res, deps, controller, mutation);
78902
+ return true;
78903
+ };
78904
+ }
78905
+ function buildCarrierSettingsState(registry32) {
78906
+ const defaultsByCarrier = buildDefaultsByCarrier(registry32);
78907
+ const snapshot = readCarriersSnapshot2(defaultsByCarrier);
78908
+ return {
78909
+ generation: snapshot.generation,
78910
+ carriers: getRegisteredOrder2(registry32).map((carrierId) => {
78911
+ const config22 = requireCarrierConfig(registry32, carrierId);
78912
+ const resolved = snapshot.carriers[carrierId] ?? fallbackResolvedState(config22);
78913
+ return toCarrierSettingsCarrier(registry32, config22, resolved);
78914
+ })
78915
+ };
78916
+ }
78917
+ function buildCarrierSettingsOptions() {
78918
+ return {
78919
+ cliTypes: getCliTypes().map(toCliOption),
78920
+ taskForceConstraints: { minBackends: TASKFORCE_MIN_BACKENDS }
78921
+ };
78922
+ }
78923
+ async function handleCarrierMutation(req, res, deps, controller, mutation) {
78924
+ const method = req.method ?? "GET";
78925
+ const expectedMethod = mutation.kind === "display-name" ? "PATCH" : mutation.kind === "taskforce-backend" || mutation.kind === "taskforce-all" ? method : "PUT";
78926
+ if (!isExpectedCarrierMethod(mutation, method, expectedMethod)) {
78927
+ deps.writeJson(res, 405, { error: "Method not allowed" });
78928
+ return;
78929
+ }
78930
+ if (!deps.isAuthorized(req)) {
78931
+ deps.writeJson(res, 401, { error: "unauthorized" });
78932
+ return;
78933
+ }
78934
+ if (!isJsonRequest(req)) {
78935
+ deps.writeJson(res, 415, { error: "unsupported_media_type" });
78936
+ return;
78937
+ }
78938
+ if (!getRegisteredCarrierConfig2(deps.registry, mutation.carrierId)) {
78939
+ deps.writeJson(res, 404, { error: "carrier_not_found" });
78940
+ return;
78941
+ }
78942
+ if (mutation.kind === "taskforce-backend" && !isCliType(mutation.cliType)) {
78943
+ deps.writeJson(res, 400, { error: "invalid_cli_type" });
78944
+ return;
78945
+ }
78946
+ try {
78947
+ if (mutation.kind === "cli") {
78948
+ const body2 = await readRequiredJsonBody(req, res, deps);
78949
+ if (!body2.ok) return;
78950
+ await mutateCarrierCli(res, deps, controller, mutation.carrierId, body2.body);
78951
+ return;
78952
+ }
78953
+ if (mutation.kind === "model") {
78954
+ const body2 = await readRequiredJsonBody(req, res, deps);
78955
+ if (!body2.ok) return;
78956
+ await mutateCarrierModel(res, deps, mutation.carrierId, body2.body);
78957
+ return;
78958
+ }
78959
+ if (mutation.kind === "display-name") {
78960
+ const body2 = await readRequiredJsonBody(req, res, deps);
78961
+ if (!body2.ok) return;
78962
+ mutateDisplayName(res, deps, mutation.carrierId, body2.body);
78963
+ return;
78964
+ }
78965
+ if (mutation.kind === "agent-mode") {
78966
+ const body2 = await readRequiredJsonBody(req, res, deps);
78967
+ if (!body2.ok) return;
78968
+ mutateAgentMode(res, deps, mutation.carrierId, body2.body);
78969
+ return;
78970
+ }
78971
+ if (mutation.kind === "taskforce-backend") {
78972
+ if (method === "DELETE") {
78973
+ const body3 = await readRequiredJsonBody(req, res, deps);
78974
+ if (!body3.ok) return;
78975
+ resetTaskForceModelSelection2(mutation.carrierId, mutation.cliType);
78976
+ refreshTaskForceConfiguredCarriers(deps.registry);
78977
+ writeMutationState(res, deps);
78978
+ return;
78979
+ }
78980
+ const body2 = await readRequiredJsonBody(req, res, deps);
78981
+ if (!body2.ok) return;
78982
+ mutateTaskForceBackend(res, deps, mutation.carrierId, mutation.cliType, body2.body);
78983
+ return;
78984
+ }
78985
+ const body = await readRequiredJsonBody(req, res, deps);
78986
+ if (!body.ok) return;
78987
+ resetCarrierTaskForceConfig2(mutation.carrierId);
78988
+ refreshTaskForceConfiguredCarriers(deps.registry);
78989
+ writeMutationState(res, deps);
78990
+ } catch (error512) {
78991
+ deps.writeJson(res, 400, { error: error512 instanceof Error ? error512.message : "invalid_request" });
78992
+ }
78993
+ }
78994
+ async function mutateCarrierCli(res, deps, controller, carrierId, body) {
78995
+ const cliType = readCliType(body.cliType);
78996
+ if (!cliType) {
78997
+ deps.writeJson(res, 400, { error: "invalid_cli_type" });
78998
+ return;
78999
+ }
79000
+ await controller.changeCliType(carrierId, cliType);
79001
+ if (!SUBAGENT_CLI_TYPES.has(cliType)) {
79002
+ const resolved = readCarriersSnapshot2(buildDefaultsByCarrier(deps.registry)).carriers[carrierId];
79003
+ if (resolved?.agentMode === "subagent") {
79004
+ const config22 = requireCarrierConfig(deps.registry, carrierId);
79005
+ updateCarrierAgentModeAtomically(carrierId, "cli", config22.defaultAgentMode ?? "cli");
79006
+ }
79007
+ }
79008
+ writeMutationState(res, deps);
79009
+ }
79010
+ async function mutateCarrierModel(res, deps, carrierId, body) {
79011
+ const config22 = requireCarrierConfig(deps.registry, carrierId);
79012
+ const cliType = resolveAgentCliType22(carrierId, config22.defaultCliType);
79013
+ const selection = readSelection(cliType, body);
79014
+ if (!selection) {
79015
+ deps.writeJson(res, 400, { error: "invalid_model_selection" });
79016
+ return;
79017
+ }
79018
+ await updateAgentCliSelection2(carrierId, cliType, selection);
79019
+ notifyStatusUpdate2(deps.registry);
79020
+ writeMutationState(res, deps);
79021
+ }
79022
+ function mutateDisplayName(res, deps, carrierId, body) {
79023
+ const displayName = normalizeCarrierDisplayNameInput2(body.displayName);
79024
+ if (displayName === null) {
79025
+ deps.writeJson(res, 400, { error: "invalid_display_name" });
79026
+ return;
79027
+ }
79028
+ updateCarrierDisplayName2(carrierId, displayName, getCarrierSourceDisplayName2(deps.registry, carrierId));
79029
+ notifyStatusUpdate2(deps.registry);
79030
+ writeMutationState(res, deps);
79031
+ }
79032
+ function mutateAgentMode(res, deps, carrierId, body) {
79033
+ const config22 = requireCarrierConfig(deps.registry, carrierId);
79034
+ const agentMode = body.agentMode;
79035
+ if (agentMode !== "cli" && agentMode !== "subagent") {
79036
+ deps.writeJson(res, 400, { error: "invalid_agent_mode" });
79037
+ return;
79038
+ }
79039
+ const cliType = resolveAgentCliType22(carrierId, config22.defaultCliType);
79040
+ if (agentMode === "subagent" && !SUBAGENT_CLI_TYPES.has(cliType)) {
79041
+ deps.writeJson(res, 400, { error: "subagent_unsupported" });
79042
+ return;
79043
+ }
79044
+ updateCarrierAgentModeAtomically(carrierId, agentMode, config22.defaultAgentMode ?? "cli");
79045
+ if (agentMode === "subagent") refreshTaskForceConfiguredCarriers(deps.registry);
79046
+ notifyStatusUpdate2(deps.registry);
79047
+ writeMutationState(res, deps);
79048
+ }
79049
+ function mutateTaskForceBackend(res, deps, carrierId, cliType, body) {
79050
+ const selection = readSelection(cliType, body);
79051
+ if (!selection) {
79052
+ deps.writeJson(res, 400, { error: "invalid_model_selection" });
79053
+ return;
79054
+ }
79055
+ updateTaskForceBackendAtomically(carrierId, cliType, selection);
79056
+ refreshTaskForceConfiguredCarriers(deps.registry);
79057
+ notifyStatusUpdate2(deps.registry);
79058
+ writeMutationState(res, deps);
79059
+ }
79060
+ function writeMutationState(res, deps) {
79061
+ const response = { state: buildCarrierSettingsState(deps.registry) };
79062
+ deps.writeJson(res, 200, response);
79063
+ }
79064
+ async function readRequiredJsonBody(req, res, deps) {
79065
+ const body = await deps.readJsonBody(req);
79066
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
79067
+ deps.writeJson(res, 400, { error: "invalid_json" });
79068
+ return { ok: false };
79069
+ }
79070
+ return { ok: true, body };
79071
+ }
79072
+ function buildDefaultsByCarrier(registry32) {
79073
+ return Object.fromEntries(
79074
+ getRegisteredOrder2(registry32).map((carrierId) => {
79075
+ const config22 = requireCarrierConfig(registry32, carrierId);
79076
+ return [carrierId, {
79077
+ cliType: config22.defaultCliType,
79078
+ ...config22.defaultAgentMode ? { defaultAgentMode: config22.defaultAgentMode } : {},
79079
+ ...buildCarrierModelDefaults2(config22, config22.defaultCliType)
79080
+ }];
79081
+ })
79082
+ );
79083
+ }
79084
+ function toCarrierSettingsCarrier(registry32, config22, resolved) {
79085
+ const cliType = resolved.agentCliType ?? config22.defaultCliType;
79086
+ const selection = resolved.agentCli[cliType] ?? readDefaultSelection(cliType);
79087
+ const taskForceBackends = toTaskForceBackends(resolved.taskforce);
79088
+ return {
79089
+ carrierId: config22.id,
79090
+ displayName: resolved.displayName ?? getCarrierSourceDisplayName2(registry32, config22.id),
79091
+ sourceDisplayName: getCarrierSourceDisplayName2(registry32, config22.id),
79092
+ role: config22.carrierMetadata?.title ?? config22.displayName,
79093
+ roleDescription: config22.carrierMetadata?.summary ?? "",
79094
+ ...config22.carrierMetadata?.category ? { category: config22.carrierMetadata.category } : {},
79095
+ slot: config22.slot,
79096
+ cliType,
79097
+ defaultCliType: config22.defaultCliType,
79098
+ model: selection.model,
79099
+ ...selection.effort ? { effort: selection.effort } : {},
79100
+ agentMode: resolved.agentMode,
79101
+ subagentMode: resolved.agentMode === "subagent",
79102
+ taskForceBackendCount: taskForceBackends.length,
79103
+ taskforce: { backends: taskForceBackends }
79104
+ };
79105
+ }
79106
+ function toTaskForceBackends(taskforce) {
79107
+ return TASKFORCE_CLI_TYPES2.map((cliType) => {
79108
+ const selection = taskforce[cliType];
79109
+ if (!selection) return null;
79110
+ return {
79111
+ cliType,
79112
+ model: selection.model,
79113
+ ...selection.effort ? { effort: selection.effort } : {}
79114
+ };
79115
+ }).filter((backend) => backend !== null);
79116
+ }
79117
+ function toCliOption(cliType) {
79118
+ const provider = getProviderModels2(cliType);
79119
+ return {
79120
+ id: cliType,
79121
+ displayName: CLI_DISPLAY_NAMES2[cliType] ?? provider.name,
79122
+ supportsSubagent: SUBAGENT_CLI_TYPES.has(cliType),
79123
+ models: provider.models.map((model) => {
79124
+ const effort = getEffort2(cliType, model.modelId);
79125
+ return {
79126
+ modelId: model.modelId,
79127
+ name: model.name,
79128
+ ...effort.supported ? { effort: { levels: effort.levels, default: effort.default } } : {}
79129
+ };
79130
+ }),
79131
+ defaultModel: provider.defaultModel ?? provider.models[0]?.modelId
79132
+ };
79133
+ }
79134
+ function createStatusOverlayController(registry32) {
79135
+ return new StatusOverlayController2({
79136
+ getEntries: () => [],
79137
+ getRegisteredOrder: () => getRegisteredOrder2(registry32),
79138
+ getCarrierConfig: (carrierId) => getRegisteredCarrierConfig2(registry32, carrierId),
79139
+ getResolvedCliType: (carrierId) => {
79140
+ const config22 = getRegisteredCarrierConfig2(registry32, carrierId);
79141
+ return config22 ? resolveAgentCliType22(carrierId, config22.defaultCliType) : void 0;
79142
+ },
79143
+ getCurrentModelSelection: (carrierId) => {
79144
+ return readCurrentModelSelection(registry32, carrierId);
79145
+ },
79146
+ getAvailableModels: (cliType) => {
79147
+ const provider = getProviderModels2(cliType);
79148
+ return {
79149
+ defaultModel: provider.defaultModel,
79150
+ models: provider.models.map((model) => ({
79151
+ modelId: model.modelId,
79152
+ name: model.name,
79153
+ effort: getEffort2(cliType, model.modelId)
79154
+ }))
79155
+ };
79156
+ },
79157
+ getEffort: (cliType, modelId) => getEffort2(cliType, modelId),
79158
+ getAgentCliSelection: (carrierId, cliType) => getAgentCliSelection2(carrierId, cliType),
79159
+ saveAgentCliSelection: saveAgentCliSelection2,
79160
+ updateCarrierCliType: (carrierId, cliType) => updateCarrierCliType2(registry32, carrierId),
79161
+ applyAgentCliTypeSelectionUpdate: applyAgentCliTypeSelectionUpdate2,
79162
+ refreshAgentPanel: () => void 0,
79163
+ syncModelConfig: () => void 0,
79164
+ notifyStatusUpdate: () => notifyStatusUpdate2(registry32)
79165
+ });
79166
+ }
79167
+ function updateCarrierAgentModeAtomically(carrierId, agentMode, defaultAgentMode) {
79168
+ if (agentMode === "cli") {
79169
+ setCarrierAgentMode2(carrierId, false, defaultAgentMode);
79170
+ return;
79171
+ }
79172
+ updateCarriers2((states) => {
79173
+ const carriers = { ...states.carriers ?? {} };
79174
+ const current = carriers[carrierId] ?? {};
79175
+ const next = { ...current };
79176
+ next.agentMode = "subagent";
79177
+ delete next.taskforce;
79178
+ carriers[carrierId] = next;
79179
+ states.carriers = carriers;
79180
+ });
79181
+ }
79182
+ function updateTaskForceBackendAtomically(carrierId, cliType, selection) {
79183
+ updateCarriers2((states) => {
79184
+ const carriers = { ...states.carriers ?? {} };
79185
+ const current = carriers[carrierId] ?? {};
79186
+ carriers[carrierId] = {
79187
+ ...current,
79188
+ agentMode: "cli",
79189
+ taskforce: {
79190
+ ...current.taskforce ?? {},
79191
+ [cliType]: selection
79192
+ }
79193
+ };
79194
+ states.carriers = carriers;
79195
+ });
79196
+ }
79197
+ function refreshTaskForceConfiguredCarriers(registry32) {
79198
+ setTaskForceConfiguredCarriers2(registry32, getConfiguredTaskForceCarrierIds2(getRegisteredOrder2(registry32)));
79199
+ notifyStatusUpdate2(registry32);
79200
+ }
79201
+ function readSelection(cliType, body) {
79202
+ if (typeof body.model !== "string") return null;
79203
+ const provider = getProviderModels2(cliType);
79204
+ if (!provider.models.some((model) => model.modelId === body.model)) return null;
79205
+ const effort = getEffort2(cliType, body.model);
79206
+ if (!effort.supported) {
79207
+ return body.effort === void 0 ? { model: body.model } : null;
79208
+ }
79209
+ if (typeof body.effort !== "string" || !effort.levels.includes(body.effort)) return null;
79210
+ return { model: body.model, effort: body.effort };
79211
+ }
79212
+ function readDefaultSelection(cliType) {
79213
+ const provider = getProviderModels2(cliType);
79214
+ const model = provider.defaultModel;
79215
+ const effort = getEffort2(cliType, model);
79216
+ return {
79217
+ model,
79218
+ ...effort.supported ? { effort: effort.default } : {}
79219
+ };
79220
+ }
79221
+ function readCurrentModelSelection(registry32, carrierId) {
79222
+ const config22 = getRegisteredCarrierConfig2(registry32, carrierId);
79223
+ if (!config22) return void 0;
79224
+ const defaults = {
79225
+ [carrierId]: {
79226
+ cliType: config22.defaultCliType,
79227
+ ...config22.defaultAgentMode ? { defaultAgentMode: config22.defaultAgentMode } : {},
79228
+ ...buildCarrierModelDefaults2(config22, config22.defaultCliType)
79229
+ }
79230
+ };
79231
+ const resolved = readCarriersSnapshot2(defaults).carriers[carrierId] ?? fallbackResolvedState(config22);
79232
+ const cliType = resolved.agentCliType ?? config22.defaultCliType;
79233
+ return resolved.agentCli[cliType] ?? readDefaultSelection(cliType);
79234
+ }
79235
+ function fallbackResolvedState(config22) {
79236
+ return {
79237
+ agentMode: config22.defaultAgentMode ?? "cli",
79238
+ agentCliType: config22.defaultCliType,
79239
+ agentCli: { [config22.defaultCliType]: readDefaultSelection(config22.defaultCliType) },
79240
+ taskforce: {}
79241
+ };
79242
+ }
79243
+ function parseCarrierMutation(pathname) {
79244
+ const parts = pathname.split("/").filter(Boolean);
79245
+ if (parts[0] !== "carrier-settings" || parts[1] !== "carriers" || !parts[2]) return null;
79246
+ const carrierId = safeDecodeURIComponent(parts[2]);
79247
+ if (!carrierId) return null;
79248
+ if (parts.length === 4 && parts[3] === "cli") return { kind: "cli", carrierId };
79249
+ if (parts.length === 4 && parts[3] === "model") return { kind: "model", carrierId };
79250
+ if (parts.length === 4 && parts[3] === "display-name") return { kind: "display-name", carrierId };
79251
+ if (parts.length === 4 && parts[3] === "agent-mode") return { kind: "agent-mode", carrierId };
79252
+ if (parts.length === 4 && parts[3] === "taskforce") return { kind: "taskforce-all", carrierId };
79253
+ if (parts.length === 5 && parts[3] === "taskforce") {
79254
+ const cliType = safeDecodeURIComponent(parts[4] ?? "");
79255
+ return cliType ? { kind: "taskforce-backend", carrierId, cliType } : null;
79256
+ }
79257
+ return null;
79258
+ }
79259
+ function safeDecodeURIComponent(value) {
79260
+ try {
79261
+ return decodeURIComponent(value);
79262
+ } catch {
79263
+ return null;
79264
+ }
79265
+ }
79266
+ function isExpectedCarrierMethod(mutation, method, expectedMethod) {
79267
+ if (mutation.kind === "taskforce-backend") return method === "PUT" || method === "DELETE";
79268
+ if (mutation.kind === "taskforce-all") return method === "DELETE";
79269
+ return method === expectedMethod;
79270
+ }
79271
+ function isJsonRequest(req) {
79272
+ const contentType = req.headers["content-type"];
79273
+ return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
79274
+ }
79275
+ function readCliType(value) {
79276
+ return typeof value === "string" && isCliType(value) ? value : null;
79277
+ }
79278
+ function isCliType(value) {
79279
+ return Object.prototype.hasOwnProperty.call(CLI_BACKENDS2, value);
79280
+ }
79281
+ function getCliTypes() {
79282
+ return Object.keys(CLI_BACKENDS2);
79283
+ }
79284
+ function requireCarrierConfig(registry32, carrierId) {
79285
+ const config22 = getRegisteredCarrierConfig2(registry32, carrierId);
79286
+ if (!config22) throw new Error(`Carrier not found: ${carrierId}`);
79287
+ return config22;
79288
+ }
78657
79289
  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'";
78658
79290
  var SECURITY_HEADERS = {
78659
79291
  "content-security-policy": CONTENT_SECURITY_POLICY,
@@ -78680,7 +79312,7 @@ function safeEqual(left, right) {
78680
79312
  return timingSafeEqual(leftBytes, rightBytes);
78681
79313
  }
78682
79314
  function workspaceHash(canonicalCwd) {
78683
- return crypto32.createHash("sha256").update(canonicalCwd).digest("hex").slice(0, 12);
79315
+ return crypto5.createHash("sha256").update(canonicalCwd).digest("hex").slice(0, 12);
78684
79316
  }
78685
79317
  async function canonicalizeTheaterPath(cwd) {
78686
79318
  return canonicalizeTheaterPathSync(cwd);
@@ -79552,7 +80184,7 @@ function createCodexGateway(deps) {
79552
80184
  return true;
79553
80185
  }
79554
80186
  if (selected.kind === "no-workspace") {
79555
- if (isJsonRequest(request)) {
80187
+ if (isJsonRequest2(request)) {
79556
80188
  sendJson2(response, 404, { error: "no_workspace_registered" });
79557
80189
  return true;
79558
80190
  }
@@ -79664,7 +80296,7 @@ function legacyWorkspacePath(url22) {
79664
80296
  }
79665
80297
  return null;
79666
80298
  }
79667
- function isJsonRequest(request) {
80299
+ function isJsonRequest2(request) {
79668
80300
  const accept = Array.isArray(request.headers.accept) ? request.headers.accept.join(",") : request.headers.accept ?? "";
79669
80301
  const requestedWith = Array.isArray(request.headers["x-requested-with"]) ? request.headers["x-requested-with"].join(",") : request.headers["x-requested-with"] ?? "";
79670
80302
  return accept.includes("application/json") || requestedWith.toLowerCase() === "xmlhttprequest";
@@ -79739,6 +80371,155 @@ function readRawHeaderValues(rawHeaders, name) {
79739
80371
  function stripIpv6Brackets2(host) {
79740
80372
  return host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
79741
80373
  }
80374
+ var STATE_VERSION = 1;
80375
+ var STATE_LOCK_DIR_NAME = "state.lock";
80376
+ var STATE_LOCK_OWNER_FILE_NAME = "owner.json";
80377
+ var STATE_TEMP_PREFIX = ".state.";
80378
+ function createConsoleDurableStateStore(deps = {}) {
80379
+ const paths = deps.paths ?? createConsoleDataPaths();
80380
+ const createStore = deps.createStore ?? createDurableJsonStore2;
80381
+ return createStore({
80382
+ filePath: paths.stateFile,
80383
+ lockDir: path93__default.join(paths.dir, STATE_LOCK_DIR_NAME),
80384
+ lockOwnerFileName: STATE_LOCK_OWNER_FILE_NAME,
80385
+ now: deps.now,
80386
+ sanitize: sanitizeDurableConsoleState,
80387
+ sensitivity: "sensitive",
80388
+ tempCleanupPrefix: STATE_TEMP_PREFIX
80389
+ });
80390
+ }
80391
+ function sanitizeDurableConsoleState(value) {
80392
+ if (!isRecord4(value) || value.version !== STATE_VERSION) return emptyDurableConsoleState();
80393
+ return {
80394
+ version: STATE_VERSION,
80395
+ theaters: readTheaterRegistrations(value.theaters),
80396
+ operations: readDurableOperations(value.operations)
80397
+ };
80398
+ }
80399
+ function emptyDurableConsoleState() {
80400
+ return { version: STATE_VERSION, theaters: [], operations: [] };
80401
+ }
80402
+ function readProviderSessionCapture(fleetSessionId, deps = {}) {
80403
+ if (!isSafeCaptureId(fleetSessionId)) return null;
80404
+ const capturesDir = deps.capturesDir ?? createConsoleDataPaths().capturesDir;
80405
+ const filePath = path93__default.join(capturesDir, `${fleetSessionId}.json`);
80406
+ try {
80407
+ const parsed = JSON.parse(fs5__default.readFileSync(filePath, "utf8"));
80408
+ return sanitizeProviderSession(parsed);
80409
+ } catch {
80410
+ return null;
80411
+ }
80412
+ }
80413
+ function mergeProviderSessionCaptures(state, deps = {}) {
80414
+ let changed = false;
80415
+ const operations = state.operations.map((operation) => {
80416
+ if (operation.providerSession) return operation;
80417
+ const providerSession = readProviderSessionCapture(operation.sessionId, deps);
80418
+ if (!providerSession) return operation;
80419
+ changed = true;
80420
+ return { ...operation, providerSession };
80421
+ });
80422
+ return changed ? { ...state, operations } : state;
80423
+ }
80424
+ function unlinkProviderSessionCapture(fleetSessionId, deps = {}) {
80425
+ if (!isSafeCaptureId(fleetSessionId)) return false;
80426
+ const capturesDir = deps.capturesDir ?? createConsoleDataPaths().capturesDir;
80427
+ try {
80428
+ fs5__default.unlinkSync(path93__default.join(capturesDir, `${fleetSessionId}.json`));
80429
+ return true;
80430
+ } catch {
80431
+ return false;
80432
+ }
80433
+ }
80434
+ function cleanupProviderSessionCaptures(state, deps = {}) {
80435
+ for (const operation of state.operations) {
80436
+ if (operation.providerSession) unlinkProviderSessionCapture(operation.sessionId, deps);
80437
+ }
80438
+ }
80439
+ function readTheaterRegistrations(value) {
80440
+ if (!Array.isArray(value)) return [];
80441
+ const registrations = [];
80442
+ for (const item of value) {
80443
+ const registration = sanitizeTheaterRegistration(item);
80444
+ if (registration) registrations.push(registration);
80445
+ }
80446
+ return registrations;
80447
+ }
80448
+ function readDurableOperations(value) {
80449
+ if (!Array.isArray(value)) return [];
80450
+ const operations = [];
80451
+ for (const item of value) {
80452
+ const operation = sanitizeDurableOperation(item);
80453
+ if (operation) operations.push(operation);
80454
+ }
80455
+ return operations;
80456
+ }
80457
+ function sanitizeTheaterRegistration(value) {
80458
+ if (!isRecord4(value)) return null;
80459
+ const id = readNonEmptyString(value.id);
80460
+ const theaterPath = readNonEmptyString(value.path);
80461
+ const realpath = readNonEmptyString(value.realpath);
80462
+ const label = readNonEmptyString(value.label);
80463
+ const registeredAt = readNonEmptyString(value.registeredAt);
80464
+ const lastOpenedAt = readNonEmptyString(value.lastOpenedAt);
80465
+ if (!id || !theaterPath || !realpath || !label || !registeredAt || !lastOpenedAt) return null;
80466
+ return { id, path: theaterPath, realpath, label, registeredAt, lastOpenedAt };
80467
+ }
80468
+ function sanitizeDurableOperation(value) {
80469
+ if (!isRecord4(value)) return null;
80470
+ const sessionId = readNonEmptyString(value.sessionId);
80471
+ const theaterId = readNonEmptyString(value.theaterId);
80472
+ const cwd = readNonEmptyString(value.cwd);
80473
+ const cwdLabel = readNonEmptyString(value.cwdLabel);
80474
+ const sequence = readPositiveInteger(value.sequence);
80475
+ const createdAt = readFiniteNumber(value.createdAt);
80476
+ if (!sessionId || !theaterId || !cwd || !cwdLabel || sequence === null || createdAt === null) return null;
80477
+ const providerSession = sanitizeProviderSession(value.providerSession);
80478
+ return {
80479
+ sessionId,
80480
+ theaterId,
80481
+ cwd,
80482
+ cwdLabel,
80483
+ sequence,
80484
+ ...readOptionalString(value.label) ? { label: readOptionalString(value.label) } : {},
80485
+ ...readOptionalString(value.cliId) ? { cliId: readOptionalString(value.cliId) } : {},
80486
+ ...readOptionalString(value.cliLabel) ? { cliLabel: readOptionalString(value.cliLabel) } : {},
80487
+ createdAt,
80488
+ ...providerSession ? { providerSession } : {}
80489
+ };
80490
+ }
80491
+ function sanitizeProviderSession(value) {
80492
+ if (!isRecord4(value)) return null;
80493
+ const provider = value.provider === "claude" || value.provider === "codex" ? value.provider : null;
80494
+ const sessionId = readNonEmptyString(value.sessionId);
80495
+ const capturedAt = readNonEmptyString(value.capturedAt);
80496
+ if (!provider || !sessionId || !capturedAt) return null;
80497
+ return {
80498
+ provider,
80499
+ sessionId,
80500
+ ...readOptionalString(value.transcriptPath) ? { transcriptPath: readOptionalString(value.transcriptPath) } : {},
80501
+ ...readOptionalString(value.source) ? { source: readOptionalString(value.source) } : {},
80502
+ capturedAt
80503
+ };
80504
+ }
80505
+ function isRecord4(value) {
80506
+ return typeof value === "object" && value !== null && !Array.isArray(value);
80507
+ }
80508
+ function isSafeCaptureId(value) {
80509
+ return value.length > 0 && path93__default.basename(value) === value && !value.includes(path93__default.sep) && !value.includes(path93__default.posix.sep);
80510
+ }
80511
+ function readNonEmptyString(value) {
80512
+ return typeof value === "string" && value.length > 0 ? value : null;
80513
+ }
80514
+ function readOptionalString(value) {
80515
+ return typeof value === "string" && value.length > 0 ? value : void 0;
80516
+ }
80517
+ function readPositiveInteger(value) {
80518
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
80519
+ }
80520
+ function readFiniteNumber(value) {
80521
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
80522
+ }
79742
80523
  function writeObserverEvents(req, res, workspace, store22) {
79743
80524
  res.writeHead(200, withSecurityHeaders2({
79744
80525
  "Content-Type": "text/event-stream",
@@ -79947,15 +80728,71 @@ function createConsoleObservabilityStore(deps = {}) {
79947
80728
  terminalSessionsById.set(state.sessionId, state);
79948
80729
  return toTerminalSessionInfo(state);
79949
80730
  }
80731
+ function injectDormantOperation(operation) {
80732
+ const currentSequence = terminalSequenceByTheater.get(operation.theaterId) ?? 0;
80733
+ terminalSequenceByTheater.set(operation.theaterId, Math.max(currentSequence, operation.sequence));
80734
+ const state = {
80735
+ sessionId: operation.sessionId,
80736
+ cwd: operation.cwd,
80737
+ canonicalCwd: canonicalizeTheaterPathSync(operation.cwd),
80738
+ cwdLabel: operation.cwdLabel,
80739
+ sequence: operation.sequence,
80740
+ label: operation.label,
80741
+ cliId: operation.cliId,
80742
+ cliLabel: operation.cliLabel,
80743
+ createdAt: operation.createdAt,
80744
+ theaterId: operation.theaterId,
80745
+ terminalSessionId: operation.sessionId,
80746
+ status: "dormant",
80747
+ providerSession: operation.providerSession
80748
+ };
80749
+ terminalSessionsById.set(state.sessionId, state);
80750
+ return toTerminalSessionInfo(state);
80751
+ }
79950
80752
  function listTerminalSessions() {
79951
80753
  return Array.from(terminalSessionsById.values()).map(toTerminalSessionInfo).sort((a, b) => b.createdAt - a.createdAt);
79952
80754
  }
80755
+ function listDurableOperations() {
80756
+ return Array.from(terminalSessionsById.values()).map((session) => ({
80757
+ sessionId: session.sessionId,
80758
+ theaterId: session.theaterId,
80759
+ cwd: session.cwd,
80760
+ cwdLabel: session.cwdLabel,
80761
+ sequence: session.sequence,
80762
+ ...session.label ? { label: session.label } : {},
80763
+ ...session.cliId ? { cliId: session.cliId } : {},
80764
+ ...session.cliLabel ? { cliLabel: session.cliLabel } : {},
80765
+ createdAt: session.createdAt,
80766
+ ...session.providerSession ? { providerSession: session.providerSession } : {}
80767
+ }));
80768
+ }
80769
+ function getDurableOperation(sessionId) {
80770
+ return listDurableOperations().find((operation) => operation.sessionId === sessionId) ?? null;
80771
+ }
80772
+ function updateTerminalSessionProviderSession(sessionId, providerSession) {
80773
+ const session = terminalSessionsById.get(sessionId);
80774
+ if (!session) return null;
80775
+ session.providerSession = providerSession;
80776
+ return toTerminalSessionInfo(session);
80777
+ }
79953
80778
  function updateTerminalSessionStatus(sessionId, status) {
79954
80779
  const session = terminalSessionsById.get(sessionId);
79955
80780
  if (!session) return null;
79956
80781
  session.status = status;
79957
80782
  return toTerminalSessionInfo(session);
79958
80783
  }
80784
+ function transitionTerminalSessionToDormant(sessionId, providerSession) {
80785
+ const session = terminalSessionsById.get(sessionId);
80786
+ if (!session) return null;
80787
+ const workspace = workspacesByCliRunId.get(sessionId);
80788
+ if (workspace?.terminalSessionId === sessionId) {
80789
+ removeWorkspaceIndexes(workspace);
80790
+ workspacesByCliRunId.delete(sessionId);
80791
+ }
80792
+ session.status = "dormant";
80793
+ session.providerSession = providerSession;
80794
+ return toTerminalSessionInfo(session);
80795
+ }
79959
80796
  function renameTerminalSession(sessionId, rawLabel) {
79960
80797
  const session = terminalSessionsById.get(sessionId);
79961
80798
  if (!session) return null;
@@ -79995,18 +80832,23 @@ function createConsoleObservabilityStore(deps = {}) {
79995
80832
  clear,
79996
80833
  getLaunchCwd,
79997
80834
  getTruncation,
80835
+ getDurableOperation,
79998
80836
  getWorkspace,
79999
80837
  listEvents,
80000
80838
  listJobs,
80839
+ listDurableOperations,
80001
80840
  listTerminalSessions,
80002
80841
  listWorkspaces,
80003
80842
  appendTerminalRuntimeEvent,
80004
80843
  createPendingTerminalSession,
80844
+ injectDormantOperation,
80005
80845
  notifySessionUpdated,
80006
80846
  renameTerminalSession,
80007
80847
  subscribe,
80008
80848
  subscribeAll,
80849
+ updateTerminalSessionProviderSession,
80009
80850
  updateTerminalSessionStatus,
80851
+ transitionTerminalSessionToDormant,
80010
80852
  removeTerminalSession,
80011
80853
  registerTerminalRuntimeSession,
80012
80854
  workspaceCount: () => listWorkspaces().length
@@ -80078,7 +80920,8 @@ function toTerminalSessionInfo(state) {
80078
80920
  theaterId: state.theaterId,
80079
80921
  registrationId: state.registrationId,
80080
80922
  cliRunId: state.cliRunId,
80081
- tenantId: state.cliRunId
80923
+ tenantId: state.cliRunId,
80924
+ resumeAvailable: state.providerSession !== void 0
80082
80925
  };
80083
80926
  }
80084
80927
  function pruneTenantJobs(state) {
@@ -80292,7 +81135,7 @@ function resolveConsolePath(pathname) {
80292
81135
  var GRANT_ID_BYTES = 24;
80293
81136
  var DEFAULT_GRANT_TTL_MS = 6e4;
80294
81137
  function createFolderGrantStore(deps = {}) {
80295
- const randomId = deps.randomId ?? (() => crypto32.randomBytes(GRANT_ID_BYTES).toString("base64url"));
81138
+ const randomId = deps.randomId ?? (() => crypto5.randomBytes(GRANT_ID_BYTES).toString("base64url"));
80296
81139
  const statSync52 = deps.statSync ?? fs5__default.statSync;
80297
81140
  const ttlMs = deps.ttlMs ?? DEFAULT_GRANT_TTL_MS;
80298
81141
  const now = deps.now ?? Date.now;
@@ -80505,6 +81348,31 @@ function buildConsoleHookCommand(entry) {
80505
81348
  }
80506
81349
  throw new Error(`Unsupported Fleet Console session hook entry extension: ${extension}`);
80507
81350
  }
81351
+ function buildConsoleCaptureHookCommand(entry, cliId) {
81352
+ const extension = path93__default.extname(entry.entryPath);
81353
+ if (JAVASCRIPT_ENTRY_EXTENSIONS2.has(extension)) {
81354
+ return createSessionCaptureHookExec({
81355
+ entryPath: entry.entryPath,
81356
+ execPath: entry.execPath,
81357
+ provider: toCaptureProvider(cliId)
81358
+ });
81359
+ }
81360
+ if (TYPESCRIPT_ENTRY_EXTENSIONS2.has(extension)) {
81361
+ if (!entry.tsxLoaderPath) {
81362
+ throw new Error("Fleet Console capture session hook requires a tsx loader path");
81363
+ }
81364
+ return createSessionCaptureHookExec({
81365
+ entryPath: entry.entryPath,
81366
+ execPath: entry.execPath,
81367
+ provider: toCaptureProvider(cliId),
81368
+ tsxLoader: entry.tsxLoaderPath
81369
+ });
81370
+ }
81371
+ throw new Error(`Unsupported Fleet Console session hook entry extension: ${extension}`);
81372
+ }
81373
+ function toCaptureProvider(cliId) {
81374
+ return cliId === "codex" ? "codex" : "claude";
81375
+ }
80508
81376
  function runCodexCommand2(command22) {
80509
81377
  const result = spawnSync2(command22.bin, command22.args, {
80510
81378
  cwd: command22.cwd,
@@ -80528,12 +81396,12 @@ var CONSOLE_ENTRY_PATH = fileURLToPath(import.meta.url);
80528
81396
  var HOOK_ENTRY_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".js", ".mjs", ".mts", ".ts", ".tsx"]);
80529
81397
  var require2 = createRequire(import.meta.url);
80530
81398
  function createDefaultTerminalLaunchResolver(deps = {}) {
80531
- const baseCwd = deps.cwd ?? process4.cwd();
80532
- const env = deps.env ?? process4.env;
80533
- const execPath = deps.execPath ?? process4.execPath;
81399
+ const baseCwd = deps.cwd ?? process5.cwd();
81400
+ const env = deps.env ?? process5.env;
81401
+ const execPath = deps.execPath ?? process5.execPath;
80534
81402
  const homedir32 = deps.homedir ?? DEFAULT_TERMINAL_CWD_FALLBACK;
80535
- const platform2 = deps.platform ?? process4.platform;
80536
- const entryPath = resolveHookEntryPath(deps.entryPath ?? process4.argv[1]);
81403
+ const platform2 = deps.platform ?? process5.platform;
81404
+ const entryPath = resolveHookEntryPath(deps.entryPath ?? process5.argv[1]);
80537
81405
  const tsxLoaderPath = deps.tsxLoaderPath ?? resolveOptionalPackage("tsx");
80538
81406
  const dataDir = deps.dataDir ?? getFleetDataDir2();
80539
81407
  const infraServices = deps.infraServices ?? createInfraServices2();
@@ -80573,6 +81441,7 @@ function createDefaultTerminalLaunchResolver(deps = {}) {
80573
81441
  onRuntimeSessionStart: deps.onRuntimeSessionStart,
80574
81442
  resolveProfile,
80575
81443
  cliId: context?.cliId,
81444
+ resumeSessionId: context?.resumeSessionId,
80576
81445
  sessionId
80577
81446
  });
80578
81447
  };
@@ -80593,7 +81462,7 @@ function hasHookEntryExtension(entryPath) {
80593
81462
  }
80594
81463
  function startTerminalShell(launch, size) {
80595
81464
  const { spawn: spawnPty } = require2("node-pty");
80596
- const useConptyDll = resolveUseConptyDll2(process4.platform, process4.env);
81465
+ const useConptyDll = resolveUseConptyDll2(process5.platform, process5.env);
80597
81466
  return spawnPty(launch.bin, [...launch.args], {
80598
81467
  cols: size.cols,
80599
81468
  rows: size.rows,
@@ -80618,7 +81487,8 @@ async function createAgentCliLaunchSpec(options2) {
80618
81487
  const profile = await options2.resolveProfile(options2.env, options2.cwd, {
80619
81488
  authEnvResolver: options2.authEnvResolver,
80620
81489
  authService: options2.infraServices.authService,
80621
- cliId: options2.cliId
81490
+ cliId: options2.cliId,
81491
+ resumeSessionId: options2.resumeSessionId
80622
81492
  });
80623
81493
  const injectedProfile = await options2.injectProfile(profile, {
80624
81494
  buildSystemPrompt: (injectTone) => createSystemPromptBuilder2({ carrierRuntime: agentRuntime.carrierRuntime }).build(injectTone),
@@ -80627,9 +81497,11 @@ async function createAgentCliLaunchSpec(options2) {
80627
81497
  dataDir: options2.dataDir,
80628
81498
  dedicatedMcpSession: agentRuntime.dedicatedMcpSession,
80629
81499
  enableMetaphor: false,
81500
+ captureSessionHookExec: buildConsoleCaptureHookCommand(options2.hookEntry, profile.id),
80630
81501
  hookExec: buildConsoleHookCommand(options2.hookEntry),
80631
81502
  onCleanup: (cleanup) => cleanupStack.push(cleanup),
80632
- replaceSystemPrompt: true,
81503
+ replaceSystemPrompt: false,
81504
+ resumeSessionId: options2.resumeSessionId,
80633
81505
  withMarketplaceLock: withConsoleMarketplaceLock,
80634
81506
  mcpSessionLabel: options2.sessionId
80635
81507
  });
@@ -80663,6 +81535,7 @@ function toLaunchSpec(profile, cleanup) {
80663
81535
  cwd: profile.cwd,
80664
81536
  env: { ...profile.env },
80665
81537
  messagePolicy: profile.messagePolicy,
81538
+ renameCommand: profile.renameCommand,
80666
81539
  terminalName: profile.terminalName
80667
81540
  };
80668
81541
  }
@@ -80754,6 +81627,9 @@ function createTerminalSessionManager(deps) {
80754
81627
  function getSessionMessagePolicy(sessionId) {
80755
81628
  return sessions.get(sessionId)?.messagePolicy;
80756
81629
  }
81630
+ function getSessionRenameCommand(sessionId) {
81631
+ return sessions.get(sessionId)?.renameCommand;
81632
+ }
80757
81633
  function writeToSession(sessionId, data) {
80758
81634
  const session = sessions.get(sessionId);
80759
81635
  if (!session || typeof session.pty.write !== "function") return false;
@@ -80791,7 +81667,7 @@ function createTerminalSessionManager(deps) {
80791
81667
  }
80792
81668
  }
80793
81669
  async function launchSession(context) {
80794
- const launch = await deps.launch(context.cwd, { sessionId: context.sessionId, kind: context.kind, cliId: context.cliId });
81670
+ const launch = await deps.launch(context.cwd, { sessionId: context.sessionId, kind: context.kind, cliId: context.cliId, resumeSessionId: context.resumeSessionId });
80795
81671
  let pty;
80796
81672
  try {
80797
81673
  pty = startShell2(launch, { cols: DEFAULT_COLS, rows: DEFAULT_ROWS2 });
@@ -80806,6 +81682,7 @@ function createTerminalSessionManager(deps) {
80806
81682
  scrollback: [],
80807
81683
  cleanup: launch.cleanup,
80808
81684
  messagePolicy: launch.messagePolicy,
81685
+ renameCommand: launch.renameCommand,
80809
81686
  activeSocket: null,
80810
81687
  cols: DEFAULT_COLS,
80811
81688
  rows: DEFAULT_ROWS2
@@ -80870,7 +81747,7 @@ function createTerminalSessionManager(deps) {
80870
81747
  await runLaunchCleanup(session.cleanup);
80871
81748
  }
80872
81749
  }
80873
- return { canAttach, createSession, attach, getSessionMessagePolicy, terminate, stop, writeToSession };
81750
+ return { canAttach, createSession, attach, getSessionMessagePolicy, getSessionRenameCommand, terminate, stop, writeToSession };
80874
81751
  }
80875
81752
  async function runLaunchCleanup(cleanup) {
80876
81753
  try {
@@ -80900,7 +81777,7 @@ var DEFAULT_TICKET_TTL_MS = 1e4;
80900
81777
  function createTerminalTicketRegistry(deps = {}) {
80901
81778
  const ttlMs = deps.ttlMs ?? DEFAULT_TICKET_TTL_MS;
80902
81779
  const now = deps.now ?? Date.now;
80903
- const randomTicket = deps.randomTicket ?? (() => crypto32.randomBytes(32).toString("base64url"));
81780
+ const randomTicket = deps.randomTicket ?? (() => crypto5.randomBytes(32).toString("base64url"));
80904
81781
  const tickets = /* @__PURE__ */ new Map();
80905
81782
  function issue32(context) {
80906
81783
  prune();
@@ -81088,6 +81965,26 @@ var TheaterRegistry = class {
81088
81965
  this.#mruId = id;
81089
81966
  return item;
81090
81967
  }
81968
+ load(items) {
81969
+ this.restore(items);
81970
+ }
81971
+ restore(items) {
81972
+ const restored = /* @__PURE__ */ new Map();
81973
+ let mruId = null;
81974
+ for (const item of items) {
81975
+ const existing = restored.get(item.id);
81976
+ if (existing && existing.realpath !== item.realpath) {
81977
+ throw new Error("theater_id_collision");
81978
+ }
81979
+ restored.set(item.id, item);
81980
+ if (!mruId || item.lastOpenedAt.localeCompare(restored.get(mruId)?.lastOpenedAt ?? "") > 0) {
81981
+ mruId = item.id;
81982
+ }
81983
+ }
81984
+ this.#items.clear();
81985
+ for (const [id, item] of restored) this.#items.set(id, item);
81986
+ this.#mruId = mruId;
81987
+ }
81091
81988
  get(id) {
81092
81989
  return this.#items.get(id) ?? null;
81093
81990
  }
@@ -81097,6 +81994,11 @@ var TheaterRegistry = class {
81097
81994
  list() {
81098
81995
  return [...this.#items.values()].sort((left, right) => right.lastOpenedAt.localeCompare(left.lastOpenedAt));
81099
81996
  }
81997
+ remove(id) {
81998
+ const removed = this.#items.delete(id);
81999
+ if (this.#mruId === id) this.#mruId = this.list()[0]?.id ?? null;
82000
+ return removed;
82001
+ }
81100
82002
  };
81101
82003
  var FLEET_CONSOLE_PACKAGE_NAME = "@dotobokuri/fleet-console";
81102
82004
  var UPDATE_CHECK_TTL_MS = 60 * 60 * 1e3;
@@ -81169,6 +82071,9 @@ function createConsoleServer(deps = {}) {
81169
82071
  const folderGrants = createFolderGrantStore();
81170
82072
  const infraServices = createInfraServices2();
81171
82073
  const dataDir = deps.dataDir ?? getFleetDataDir2();
82074
+ initStore2(dataDir);
82075
+ const durablePaths = createConsoleDataPaths({ fleetDataDir: dataDir });
82076
+ const durableStateStore = createConsoleDurableStateStore({ paths: durablePaths });
81172
82077
  const authEnvResolver = (cli) => resolveAuthEnv2(cli, { authService: infraServices.authService });
81173
82078
  const ownsAgentRuntime = deps.agentRuntime === void 0;
81174
82079
  const agentRuntime = deps.agentRuntime ?? createFleetAgentRuntimeLifecycle2({
@@ -81207,10 +82112,18 @@ function createConsoleServer(deps = {}) {
81207
82112
  }),
81208
82113
  startShell: deps.terminalStartShell,
81209
82114
  maxSessions: deps.maxTerminalSessions,
81210
- // PTY가 종료되면 콘솔 세션 목록에서도 제거해 잔존/재실행을 막는다.
81211
82115
  onSessionExit: (sessionId) => {
81212
82116
  pendingRuntimeSessions.delete(sessionId);
81213
- observability.removeTerminalSession(sessionId);
82117
+ const operation = observability.getDurableOperation(sessionId);
82118
+ const providerSession = operation?.providerSession ?? readProviderSessionCapture(sessionId, { capturesDir: durablePaths.capturesDir });
82119
+ if (providerSession) {
82120
+ observability.updateTerminalSessionProviderSession(sessionId, providerSession);
82121
+ const dormant = observability.transitionTerminalSessionToDormant(sessionId, providerSession);
82122
+ if (dormant) observability.notifySessionUpdated(dormant);
82123
+ } else {
82124
+ observability.removeTerminalSession(sessionId);
82125
+ }
82126
+ persistDurableState();
81214
82127
  }
81215
82128
  });
81216
82129
  const unsubscribeCarrierReminderRouter = createCarrierResultReminderRouter2({
@@ -81242,6 +82155,12 @@ function createConsoleServer(deps = {}) {
81242
82155
  let activeEndpoint = null;
81243
82156
  let agentRuntimeStopped = false;
81244
82157
  let consoleResourcesDisposed = false;
82158
+ const carrierSettingsRouter = createCarrierSettingsRouter({
82159
+ registry: carrierRegistry,
82160
+ isAuthorized: isTerminalAuthorized,
82161
+ readJsonBody,
82162
+ writeJson
82163
+ });
81245
82164
  function handleRequest(req, res) {
81246
82165
  const pathname = getPathname(req);
81247
82166
  if (pathname === "/console/codex" || pathname.startsWith("/console/codex/")) {
@@ -81269,6 +82188,11 @@ function createConsoleServer(deps = {}) {
81269
82188
  runAsyncHandler(handleTerminalSessions(req, res), res);
81270
82189
  return;
81271
82190
  }
82191
+ const terminalSessionResumeMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)\/resume$/);
82192
+ if (terminalSessionResumeMatch) {
82193
+ runAsyncHandler(handleTerminalSessionResume(req, res, decodeURIComponent(terminalSessionResumeMatch[1] ?? "")), res);
82194
+ return;
82195
+ }
81272
82196
  const terminalSessionItemMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)$/);
81273
82197
  if (terminalSessionItemMatch) {
81274
82198
  runAsyncHandler(handleTerminalSessionItem(req, res, decodeURIComponent(terminalSessionItemMatch[1] ?? "")), res);
@@ -81278,6 +82202,11 @@ function createConsoleServer(deps = {}) {
81278
82202
  runAsyncHandler(handleObserverTheaters(req, res), res);
81279
82203
  return;
81280
82204
  }
82205
+ const theaterItemMatch = pathname.match(/^\/observer\/theaters\/([^/]+)$/);
82206
+ if (theaterItemMatch) {
82207
+ runAsyncHandler(handleObserverTheaterItem(req, res, decodeURIComponent(theaterItemMatch[1] ?? "")), res);
82208
+ return;
82209
+ }
81281
82210
  const theaterSessionMatch = pathname.match(/^\/observer\/theaters\/([^/]+)\/sessions$/);
81282
82211
  if (theaterSessionMatch) {
81283
82212
  runAsyncHandler(handleObserverTheaterSessions(req, res, decodeURIComponent(theaterSessionMatch[1] ?? "")), res);
@@ -81291,6 +82220,10 @@ function createConsoleServer(deps = {}) {
81291
82220
  handleObserverCarriers(req, res);
81292
82221
  return;
81293
82222
  }
82223
+ if (pathname === "/carrier-settings" || pathname.startsWith("/carrier-settings/")) {
82224
+ runAsyncBooleanHandler(carrierSettingsRouter({ req, res, pathname }), res);
82225
+ return;
82226
+ }
81294
82227
  if (pathname === "/observer/tenants") {
81295
82228
  handleObserverWorkspaces(req, res);
81296
82229
  return;
@@ -81409,6 +82342,17 @@ function createConsoleServer(deps = {}) {
81409
82342
  }
81410
82343
  await createTerminalSessionForCwd(cwd, res, cliId);
81411
82344
  }
82345
+ function injectRenameCommand(sessionId, label) {
82346
+ if (!label) return;
82347
+ const renameCommand = terminalSessions.getSessionRenameCommand(sessionId);
82348
+ if (!renameCommand) return;
82349
+ const safeLabel = sanitizeCarrierResultReminder2(label.replace(/[\r\n\t]+/g, " ")).trim();
82350
+ if (safeLabel.length === 0) return;
82351
+ const policy = terminalSessions.getSessionMessagePolicy(sessionId) ?? {};
82352
+ for (const chunk of formatCarrierResultReminderMessage2(policy, `${renameCommand} ${safeLabel}`)) {
82353
+ terminalSessions.writeToSession(sessionId, chunk);
82354
+ }
82355
+ }
81412
82356
  async function handleTerminalSessionItem(req, res, sessionId) {
81413
82357
  if (req.method !== "DELETE" && req.method !== "PATCH") {
81414
82358
  writeJson(res, 405, { error: "Method not allowed" });
@@ -81430,13 +82374,62 @@ function createConsoleServer(deps = {}) {
81430
82374
  return;
81431
82375
  }
81432
82376
  observability.notifySessionUpdated(updated);
82377
+ injectRenameCommand(sessionId, updated.label);
82378
+ persistDurableState();
81433
82379
  writeJson(res, 200, updated);
81434
82380
  return;
81435
82381
  }
81436
- terminalSessions.terminate(sessionId);
81437
- observability.removeTerminalSession(sessionId);
82382
+ forgetTerminalSession(sessionId);
81438
82383
  writeJson(res, 200, { ok: true });
81439
82384
  }
82385
+ async function handleTerminalSessionResume(req, res, sessionId) {
82386
+ if (req.method !== "POST") {
82387
+ writeJson(res, 405, { error: "Method not allowed" });
82388
+ return;
82389
+ }
82390
+ if (!isTerminalAuthorized(req)) {
82391
+ writeJson(res, 401, { error: "unauthorized" });
82392
+ return;
82393
+ }
82394
+ const dormantSession = observability.listTerminalSessions().find((session) => session.sessionId === sessionId && session.status === "dormant");
82395
+ const operation = dormantSession ? observability.getDurableOperation(sessionId) : null;
82396
+ if (!operation) {
82397
+ writeJson(res, 404, { error: "session_not_found" });
82398
+ return;
82399
+ }
82400
+ const cliId = readDurableAgentCliId(operation);
82401
+ if (!cliId) {
82402
+ writeJson(res, 409, { error: "resume_unavailable" });
82403
+ return;
82404
+ }
82405
+ const providerSession = operation.providerSession ?? readProviderSessionCapture(sessionId, { capturesDir: durablePaths.capturesDir });
82406
+ if (!providerSession) {
82407
+ writeJson(res, 409, { error: "resume_unavailable" });
82408
+ return;
82409
+ }
82410
+ observability.updateTerminalSessionProviderSession(sessionId, providerSession);
82411
+ const starting = observability.updateTerminalSessionStatus(sessionId, "starting");
82412
+ if (starting) observability.notifySessionUpdated(starting);
82413
+ try {
82414
+ await terminalSessions.createSession({ sessionId, cwd: operation.cwd, cliId, resumeSessionId: providerSession.sessionId });
82415
+ const runtimeSession = pendingRuntimeSessions.get(sessionId);
82416
+ pendingRuntimeSessions.delete(sessionId);
82417
+ const resumed = runtimeSession ? observability.registerTerminalRuntimeSession(runtimeSession) ?? starting : observability.updateTerminalSessionStatus(sessionId, "terminal-only") ?? starting;
82418
+ if (!resumed) {
82419
+ writeJson(res, 404, { error: "session_not_found" });
82420
+ return;
82421
+ }
82422
+ observability.notifySessionUpdated(resumed);
82423
+ persistDurableState();
82424
+ writeJson(res, 200, resumed);
82425
+ } catch {
82426
+ pendingRuntimeSessions.delete(sessionId);
82427
+ const reverted = observability.updateTerminalSessionStatus(sessionId, "dormant");
82428
+ if (reverted) observability.notifySessionUpdated(reverted);
82429
+ persistDurableState();
82430
+ writeJson(res, 503, { error: "terminal_unavailable" });
82431
+ }
82432
+ }
81440
82433
  async function handleObserverTheaters(req, res) {
81441
82434
  if (req.method === "GET") {
81442
82435
  writeJson(res, 200, { theaters: listTheaterInfos(), agentClis: getAgentCliMetadata2() });
@@ -81469,8 +82462,28 @@ function createConsoleServer(deps = {}) {
81469
82462
  console.warn(`[fleet-console] Codex workspace registration skipped for Theater ${theater.id}: ${error512 instanceof Error ? error512.message : String(error512)}`);
81470
82463
  }
81471
82464
  }
82465
+ persistDurableState();
81472
82466
  writeJson(res, 200, toTheaterInfo(theater, hasWiki));
81473
82467
  }
82468
+ async function handleObserverTheaterItem(req, res, theaterId) {
82469
+ if (req.method !== "DELETE") {
82470
+ writeJson(res, 405, { error: "Method not allowed" });
82471
+ return;
82472
+ }
82473
+ if (!isTerminalAuthorized(req)) {
82474
+ writeJson(res, 401, { error: "unauthorized" });
82475
+ return;
82476
+ }
82477
+ const operations = observability.listDurableOperations().filter((operation) => operation.theaterId === theaterId);
82478
+ const removed = theaters.remove(theaterId);
82479
+ if (!removed) {
82480
+ writeJson(res, 404, { error: "theater_not_found" });
82481
+ return;
82482
+ }
82483
+ for (const operation of operations) forgetTerminalSession(operation.sessionId, { persist: false });
82484
+ persistDurableState();
82485
+ writeJson(res, 200, { ok: true });
82486
+ }
81474
82487
  async function handleObserverTheaterSessions(req, res, theaterId) {
81475
82488
  if (req.method !== "POST") {
81476
82489
  writeJson(res, 405, { error: "Method not allowed" });
@@ -81491,7 +82504,7 @@ function createConsoleServer(deps = {}) {
81491
82504
  await createTerminalSessionForCwd(theater.path, res, cliId);
81492
82505
  }
81493
82506
  async function createTerminalSessionForCwd(cwd, res, cliId) {
81494
- const sessionId = crypto32.randomUUID();
82507
+ const sessionId = crypto5.randomUUID();
81495
82508
  const session = observability.createPendingTerminalSession({ sessionId, cwd, cliId });
81496
82509
  try {
81497
82510
  await terminalSessions.createSession({ sessionId, cwd, cliId });
@@ -81499,6 +82512,7 @@ function createConsoleServer(deps = {}) {
81499
82512
  pendingRuntimeSessions.delete(sessionId);
81500
82513
  const created = runtimeSession ? observability.registerTerminalRuntimeSession(runtimeSession) ?? session : observability.updateTerminalSessionStatus(sessionId, "terminal-only") ?? session;
81501
82514
  observability.notifySessionUpdated(created);
82515
+ persistDurableState();
81502
82516
  writeJson(res, 200, created);
81503
82517
  } catch (error512) {
81504
82518
  pendingRuntimeSessions.delete(sessionId);
@@ -81572,6 +82586,13 @@ function createConsoleServer(deps = {}) {
81572
82586
  function listTheaterInfos() {
81573
82587
  return theaters.list().map((theater) => toTheaterInfo(theater, codex.getWorkspace(theater.id) !== null));
81574
82588
  }
82589
+ function forgetTerminalSession(sessionId, options2 = {}) {
82590
+ terminalSessions.terminate(sessionId);
82591
+ pendingRuntimeSessions.delete(sessionId);
82592
+ observability.removeTerminalSession(sessionId);
82593
+ unlinkProviderSessionCapture(sessionId, { capturesDir: durablePaths.capturesDir });
82594
+ if (options2.persist !== false) persistDurableState();
82595
+ }
81575
82596
  function toTheaterInfo(theater, hasWiki) {
81576
82597
  return {
81577
82598
  id: theater.id,
@@ -81634,12 +82655,69 @@ function createConsoleServer(deps = {}) {
81634
82655
  terminalUpgrade.close();
81635
82656
  currentLock?.release();
81636
82657
  }
82658
+ function rehydrateDurableState() {
82659
+ let state;
82660
+ try {
82661
+ state = durableStateStore.load();
82662
+ theaters.restore(state.theaters);
82663
+ } catch (error512) {
82664
+ console.warn(`[fleet-console] Durable state restore skipped: ${error512 instanceof Error ? error512.message : String(error512)}`);
82665
+ state = emptyDurableConsoleState();
82666
+ theaters.restore([]);
82667
+ }
82668
+ const merged = mergeProviderSessionCaptures(state, { capturesDir: durablePaths.capturesDir });
82669
+ syncProviderSessionsToObservability(merged);
82670
+ const restorable = {
82671
+ ...merged,
82672
+ operations: merged.operations.filter((operation) => operation.providerSession)
82673
+ };
82674
+ if (merged !== state || restorable.operations.length !== merged.operations.length) {
82675
+ try {
82676
+ durableStateStore.save(restorable);
82677
+ cleanupProviderSessionCaptures(restorable, { capturesDir: durablePaths.capturesDir });
82678
+ } catch (error512) {
82679
+ console.warn(`[fleet-console] Durable state capture merge was not persisted: ${error512 instanceof Error ? error512.message : String(error512)}`);
82680
+ }
82681
+ } else {
82682
+ cleanupProviderSessionCaptures(restorable, { capturesDir: durablePaths.capturesDir });
82683
+ }
82684
+ for (const operation of restorable.operations) {
82685
+ if (theaters.get(operation.theaterId)) observability.injectDormantOperation(operation);
82686
+ }
82687
+ }
82688
+ function persistDurableState() {
82689
+ try {
82690
+ const state = mergeProviderSessionCaptures({
82691
+ version: 1,
82692
+ theaters: theaters.list(),
82693
+ operations: observability.listDurableOperations()
82694
+ }, { capturesDir: durablePaths.capturesDir });
82695
+ syncProviderSessionsToObservability(state);
82696
+ const operationsWithProviderSession = state.operations.filter((operation) => operation.providerSession);
82697
+ durableStateStore.save({
82698
+ version: state.version,
82699
+ theaters: state.theaters,
82700
+ // 대화 없는 빈 Operation 드롭은 rehydrate에서 capture 머지 뒤에만 수행한다.
82701
+ // create 시점의 메타데이터를 먼저 남겨야 이후 도착한 capture 파일이 재시작 때 병합될 수 있다.
82702
+ operations: state.operations
82703
+ });
82704
+ cleanupProviderSessionCaptures({ ...state, operations: operationsWithProviderSession }, { capturesDir: durablePaths.capturesDir });
82705
+ } catch (error512) {
82706
+ console.warn(`[fleet-console] Durable state save failed: ${error512 instanceof Error ? error512.message : String(error512)}`);
82707
+ }
82708
+ }
82709
+ function syncProviderSessionsToObservability(state) {
82710
+ for (const operation of state.operations) {
82711
+ if (operation.providerSession) observability.updateTerminalSessionProviderSession(operation.sessionId, operation.providerSession);
82712
+ }
82713
+ }
81637
82714
  return {
81638
82715
  host,
81639
82716
  port,
81640
82717
  async start(lockPaths) {
81641
82718
  if (server && lockHandle) return lockHandle.payload.endpoint;
81642
82719
  try {
82720
+ rehydrateDurableState();
81643
82721
  await new Promise((resolve2, reject) => {
81644
82722
  const srv = createHttpServer(handleRequest, terminalUpgrade);
81645
82723
  srv.once("error", reject);
@@ -81722,6 +82800,14 @@ function resolveCarrierEventOrigin(event, jobOriginById) {
81722
82800
  function queueOriginCleanup(jobId, jobOriginById) {
81723
82801
  queueMicrotask(() => jobOriginById.delete(jobId));
81724
82802
  }
82803
+ function readDurableAgentCliId(operation) {
82804
+ if (!operation.cliId) return null;
82805
+ try {
82806
+ return parseAgentCliId2(operation.cliId) ?? null;
82807
+ } catch {
82808
+ return null;
82809
+ }
82810
+ }
81725
82811
  function createHttpServer(handler, terminalUpgrade) {
81726
82812
  const srv = http2.createServer(handler);
81727
82813
  srv.timeout = SERVER_TIMEOUT_MS;
@@ -81839,6 +82925,78 @@ function isAllowedTerminalOrigin(req, expectedPort) {
81839
82925
  if (origin === void 0) return true;
81840
82926
  return origin === `http://127.0.0.1:${expectedPort}`;
81841
82927
  }
82928
+ var CAPTURE_TEMP_PREFIX = ".capture.";
82929
+ async function runCaptureSessionHook(provider, env = process5.env) {
82930
+ return captureSession({
82931
+ diagnostics: process5.stderr,
82932
+ env,
82933
+ input: await readStdin(),
82934
+ provider
82935
+ });
82936
+ }
82937
+ function captureSession(options2) {
82938
+ try {
82939
+ return captureSessionStrict(options2);
82940
+ } catch (error512) {
82941
+ options2.diagnostics?.write(`[fleet-console] capture-session skipped: ${error512 instanceof Error ? error512.message : String(error512)}
82942
+ `);
82943
+ return null;
82944
+ }
82945
+ }
82946
+ function captureSessionStrict(options2) {
82947
+ const provider = parseProvider(options2.provider);
82948
+ const fleetSessionId = readFleetSessionId(options2.env ?? process5.env);
82949
+ const input = parseHookInput(options2.input ?? "");
82950
+ const providerSession = toProviderSession(provider, input, options2.now ?? (() => /* @__PURE__ */ new Date()));
82951
+ const capturesDir = (options2.paths ?? createConsoleDataPaths()).capturesDir;
82952
+ const finalPath = path93__default.join(capturesDir, `${fleetSessionId}.json`);
82953
+ const tempPath = path93__default.join(capturesDir, `${CAPTURE_TEMP_PREFIX}${fleetSessionId}.${process5.pid}.${Date.now()}.tmp`);
82954
+ fs5__default.mkdirSync(capturesDir, { recursive: true, mode: 448 });
82955
+ fs5__default.writeFileSync(tempPath, `${JSON.stringify(providerSession, null, 2)}
82956
+ `, { mode: 384 });
82957
+ fs5__default.renameSync(tempPath, finalPath);
82958
+ return { path: finalPath, providerSession };
82959
+ }
82960
+ function parseProvider(value) {
82961
+ if (value === "claude" || value === "codex") return value;
82962
+ throw new Error("invalid_provider");
82963
+ }
82964
+ function readFleetSessionId(env) {
82965
+ const value = env.FLEET_CONSOLE_SESSION_ID;
82966
+ if (!value) throw new Error("missing_fleet_session_id");
82967
+ if (path93__default.basename(value) !== value || value.includes(path93__default.sep) || value.includes(path93__default.posix.sep)) {
82968
+ throw new Error("invalid_fleet_session_id");
82969
+ }
82970
+ return value;
82971
+ }
82972
+ function parseHookInput(input) {
82973
+ try {
82974
+ const parsed = JSON.parse(input);
82975
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return parsed;
82976
+ } catch {
82977
+ }
82978
+ throw new Error("invalid_hook_input");
82979
+ }
82980
+ function toProviderSession(provider, input, now) {
82981
+ if (typeof input.session_id !== "string" || input.session_id.length === 0) throw new Error("missing_provider_session_id");
82982
+ return {
82983
+ provider,
82984
+ sessionId: input.session_id,
82985
+ ...typeof input.transcript_path === "string" && input.transcript_path.length > 0 ? { transcriptPath: input.transcript_path } : {},
82986
+ ...typeof input.source === "string" && input.source.length > 0 ? { source: input.source } : {},
82987
+ capturedAt: now().toISOString()
82988
+ };
82989
+ }
82990
+ function readStdin() {
82991
+ return new Promise((resolve2, reject) => {
82992
+ const chunks = [];
82993
+ process5.stdin.on("data", (chunk) => {
82994
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
82995
+ });
82996
+ process5.stdin.on("error", reject);
82997
+ process5.stdin.on("end", () => resolve2(Buffer.concat(chunks).toString("utf8")));
82998
+ });
82999
+ }
81842
83000
  function createConsoleStalePolicy(deps = {}) {
81843
83001
  const fsImpl = deps.fs ?? fs5__default;
81844
83002
  function isBuildStale(lock, buildFile) {
@@ -81854,7 +83012,7 @@ function createConsoleStalePolicy(deps = {}) {
81854
83012
  var FIXED_HOST = "127.0.0.1";
81855
83013
  var HELP_BANNER_INDENT = " ";
81856
83014
  var DEFAULT_HELP_RELEASE = "local";
81857
- var CONSOLE_HOOK_COMMANDS = /* @__PURE__ */ new Set(["subagents-context"]);
83015
+ var CONSOLE_HOOK_COMMANDS = /* @__PURE__ */ new Set(["capture-session", "subagents-context"]);
81858
83016
  function parseConsoleCliMode(argv2) {
81859
83017
  if (argv2.length === 0) return "start";
81860
83018
  const [first, ...rest] = argv2;
@@ -81881,10 +83039,12 @@ Run 'fleet console --help' for usage.`);
81881
83039
  }
81882
83040
  function parseConsoleHookCommand(argv2) {
81883
83041
  const [commandName, ...rest] = argv2;
81884
- if (!commandName || !CONSOLE_HOOK_COMMANDS.has(commandName) || rest.length > 0) {
83042
+ if (!commandName || !CONSOLE_HOOK_COMMANDS.has(commandName)) {
81885
83043
  throw new Error("Unknown fleet-console hook command");
81886
83044
  }
81887
- return "subagents-context";
83045
+ if (commandName === "subagents-context" && rest.length === 0) return { command: "subagents-context" };
83046
+ if (commandName === "capture-session" && rest.length === 1 && rest[0]) return { command: "capture-session", provider: rest[0] };
83047
+ throw new Error("Unknown fleet-console hook command");
81888
83048
  }
81889
83049
  function buildConsoleHelpText(options2 = {}) {
81890
83050
  const colorEnabled = resolveColorEnabled2(options2);
@@ -81946,8 +83106,8 @@ function buildWikiHelpText(options2 = {}) {
81946
83106
  return colorEnabled ? text : stripAnsi2(text);
81947
83107
  }
81948
83108
  function createConsoleDaemonLifecycle(deps = {}) {
81949
- const env = deps.env ?? process4.env;
81950
- const execPath = deps.execPath ?? process4.execPath;
83109
+ const env = deps.env ?? process5.env;
83110
+ const execPath = deps.execPath ?? process5.execPath;
81951
83111
  const serverModulePath = deps.serverModulePath ?? resolveDefaultServerModulePath();
81952
83112
  const spawnDetached = deps.spawnDetached ?? ((bin, args, options2) => {
81953
83113
  spawn3(bin, [...args], options2).unref();
@@ -81961,10 +83121,10 @@ function createConsoleDaemonLifecycle(deps = {}) {
81961
83121
  const server = createConsoleServer();
81962
83122
  await server.start(paths);
81963
83123
  await new Promise((resolve2) => {
81964
- process4.once("SIGTERM", () => {
83124
+ process5.once("SIGTERM", () => {
81965
83125
  void server.stop().finally(resolve2);
81966
83126
  });
81967
- process4.once("SIGINT", () => {
83127
+ process5.once("SIGINT", () => {
81968
83128
  void server.stop().finally(resolve2);
81969
83129
  });
81970
83130
  });
@@ -81978,14 +83138,14 @@ function createConsoleDaemonLifecycle(deps = {}) {
81978
83138
  const payload = readTrustedLock();
81979
83139
  if (!payload) return;
81980
83140
  try {
81981
- process4.kill(payload.pid, "SIGTERM");
83141
+ process5.kill(payload.pid, "SIGTERM");
81982
83142
  } catch (err) {
81983
83143
  if (err.code !== "ESRCH") throw err;
81984
83144
  }
81985
83145
  await sleep(200);
81986
83146
  try {
81987
- process4.kill(payload.pid, 0);
81988
- process4.kill(payload.pid, "SIGKILL");
83147
+ process5.kill(payload.pid, 0);
83148
+ process5.kill(payload.pid, "SIGKILL");
81989
83149
  } catch (err) {
81990
83150
  if (err.code !== "ESRCH") throw err;
81991
83151
  }
@@ -82103,49 +83263,51 @@ async function runConsoleRestart(deps = {}) {
82103
83263
  return openFleetConsole({ lifecycle, openBrowser: deps.openBrowser });
82104
83264
  }
82105
83265
  async function main() {
82106
- if (process4.argv[2] === "serve") {
83266
+ if (process5.argv[2] === "serve") {
82107
83267
  await createConsoleDaemonLifecycle().runServer();
82108
83268
  return;
82109
83269
  }
82110
- if (process4.argv[2] === "hook") {
82111
- parseConsoleHookCommand(process4.argv.slice(3));
82112
- {
82113
- process4.stdout.write(`${runSubagentsContextHook(process4.env)}
83270
+ if (process5.argv[2] === "hook") {
83271
+ const hookCommand = parseConsoleHookCommand(process5.argv.slice(3));
83272
+ if (hookCommand.command === "subagents-context") {
83273
+ process5.stdout.write(`${runSubagentsContextHook(process5.env)}
82114
83274
  `);
82115
83275
  return;
82116
83276
  }
83277
+ await runCaptureSessionHook(hookCommand.provider, process5.env);
83278
+ return;
82117
83279
  }
82118
- if (process4.argv[2] === "codex") {
82119
- await mainWiki(process4.argv.slice(3));
83280
+ if (process5.argv[2] === "codex") {
83281
+ await mainWiki(process5.argv.slice(3));
82120
83282
  return;
82121
83283
  }
82122
- const mode = parseConsoleCliMode(process4.argv.slice(2));
83284
+ const mode = parseConsoleCliMode(process5.argv.slice(2));
82123
83285
  if (mode === "help") {
82124
- process4.stdout.write(`${buildConsoleHelpText({ env: process4.env, isTTY: process4.stdout.isTTY })}
83286
+ process5.stdout.write(`${buildConsoleHelpText({ env: process5.env, isTTY: process5.stdout.isTTY })}
82125
83287
  `);
82126
83288
  return;
82127
83289
  }
82128
83290
  if (mode === "status") {
82129
- process4.stdout.write(`${await runConsoleStatus()}
83291
+ process5.stdout.write(`${await runConsoleStatus()}
82130
83292
  `);
82131
83293
  return;
82132
83294
  }
82133
83295
  if (mode === "stop") {
82134
- process4.stdout.write(`${await runConsoleStop()}
83296
+ process5.stdout.write(`${await runConsoleStop()}
82135
83297
  `);
82136
83298
  return;
82137
83299
  }
82138
83300
  if (mode === "restart") {
82139
83301
  await runConsoleRestart();
82140
- process4.stdout.write("Fleet Console restarted.\n");
83302
+ process5.stdout.write("Fleet Console restarted.\n");
82141
83303
  return;
82142
83304
  }
82143
83305
  await openFleetConsole();
82144
- process4.stdout.write("Fleet Console opened.\n");
83306
+ process5.stdout.write("Fleet Console opened.\n");
82145
83307
  }
82146
- async function mainWiki(argv2 = process4.argv.slice(2)) {
83308
+ async function mainWiki(argv2 = process5.argv.slice(2)) {
82147
83309
  if (argv2.includes("--help") || argv2.includes("-h")) {
82148
- process4.stdout.write(`${buildWikiHelpText({ env: process4.env, isTTY: process4.stdout.isTTY })}
83310
+ process5.stdout.write(`${buildWikiHelpText({ env: process5.env, isTTY: process5.stdout.isTTY })}
82149
83311
  `);
82150
83312
  return;
82151
83313
  }
@@ -82157,19 +83319,19 @@ async function mainWiki(argv2 = process4.argv.slice(2)) {
82157
83319
  if (unsupported.length > 0) {
82158
83320
  throw new Error(`Unknown fleet wiki option: ${unsupported[0]}`);
82159
83321
  }
82160
- await openFleetWikiWorkspace({ cwd: process4.cwd() });
83322
+ await openFleetWikiWorkspace({ cwd: process5.cwd() });
82161
83323
  }
82162
83324
  function resolveDefaultServerModulePath() {
82163
83325
  const builtPath = new URL("../dist/cli.mjs", import.meta.url).pathname;
82164
83326
  if (fs5__default.existsSync(builtPath)) return builtPath;
82165
83327
  return fileURLToPath(import.meta.url);
82166
83328
  }
82167
- var isDirectRun = process4.argv[1] && path93__default.resolve(process4.argv[1]) === fileURLToPath(import.meta.url);
83329
+ var isDirectRun = process5.argv[1] && path93__default.resolve(process5.argv[1]) === fileURLToPath(import.meta.url);
82168
83330
  if (isDirectRun) {
82169
83331
  await main().catch((error512) => {
82170
- process4.stderr.write(`${error512 instanceof Error ? error512.message : String(error512)}
83332
+ process5.stderr.write(`${error512 instanceof Error ? error512.message : String(error512)}
82171
83333
  `);
82172
- process4.exitCode = 1;
83334
+ process5.exitCode = 1;
82173
83335
  });
82174
83336
  }
82175
83337
 
@@ -82997,7 +84159,7 @@ import { join as join11 } from "path";
82997
84159
  import path63 from "path";
82998
84160
  import path12 from "path";
82999
84161
  import path53 from "path";
83000
- import crypto5 from "crypto";
84162
+ import crypto6 from "crypto";
83001
84163
  import { mkdir as mkdir4, readdir as readdir2, readFile as readFile3, rename as rename2, rm as rm2, stat as stat2, writeFile as writeFile22 } from "fs/promises";
83002
84164
  import os6 from "os";
83003
84165
  import path43 from "path";
@@ -84050,7 +85212,7 @@ function stripLeadingFrontmatter2(body) {
84050
85212
  return stripped ? next : body;
84051
85213
  }
84052
85214
  function computeContentHash2(content) {
84053
- return crypto5.createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
85215
+ return crypto6.createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
84054
85216
  }
84055
85217
  function assertWithinRawDir2(absolutePath, paths) {
84056
85218
  const relative2 = path43.relative(paths.rawDir, absolutePath);
@@ -84263,7 +85425,7 @@ async function writeAtomic2(filePath, content, paths) {
84263
85425
  await ensureMemoryRoot2(paths);
84264
85426
  const tempPath = path43.join(
84265
85427
  path43.dirname(filePath),
84266
- `.tmp-${process.pid}-${Date.now()}-${crypto5.randomUUID()}-${os6.hostname()}`
85428
+ `.tmp-${process.pid}-${Date.now()}-${crypto6.randomUUID()}-${os6.hostname()}`
84267
85429
  );
84268
85430
  await writeFile22(tempPath, content, "utf8");
84269
85431
  await rename2(tempPath, filePath);
@@ -90884,7 +92046,7 @@ async function runApp(options2 = {}) {
90884
92046
  defaults: {
90885
92047
  cliId: getDefaultAgentCliId(),
90886
92048
  enableMetaphor: false,
90887
- replaceSystemPrompt: true
92049
+ replaceSystemPrompt: false
90888
92050
  },
90889
92051
  env: process.env,
90890
92052
  globalOptionsService: runtime.infraServices.globalOptionsService,
@@ -91269,11 +92431,11 @@ function canReadCarrierState2(filePath) {
91269
92431
  }
91270
92432
  }
91271
92433
  function isReadableCarrierStateRoot2(value) {
91272
- if (!isRecord4(value)) return false;
92434
+ if (!isRecord5(value)) return false;
91273
92435
  const carriers = value.carriers;
91274
- return carriers === void 0 || isRecord4(carriers);
92436
+ return carriers === void 0 || isRecord5(carriers);
91275
92437
  }
91276
- function isRecord4(value) {
92438
+ function isRecord5(value) {
91277
92439
  return typeof value === "object" && value !== null && !Array.isArray(value);
91278
92440
  }
91279
92441
 
@@ -91314,7 +92476,7 @@ async function runNativeApp(options2 = {}) {
91314
92476
  defaults: {
91315
92477
  cliId: getDefaultAgentCliId(),
91316
92478
  enableMetaphor: false,
91317
- replaceSystemPrompt: true
92479
+ replaceSystemPrompt: false
91318
92480
  },
91319
92481
  env: process.env,
91320
92482
  globalOptionsService: runtime.infraServices.globalOptionsService,