@schoolai/shipyard 3.28.0-rc.20260903.0 → 3.28.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.
Files changed (63) hide show
  1. package/dist/{auth-OHZTVIQU.js → auth-7OBSJK2V.js} +3 -3
  2. package/dist/capability-detector-worker.js +10 -10
  3. package/dist/{chunk-K7EXPNAD.js → chunk-B23NPMUE.js} +6 -6
  4. package/dist/{chunk-ROEOOZOW.js → chunk-EKDLDBWX.js} +2 -2
  5. package/dist/{chunk-3OSJ2NBG.js → chunk-GBMR7R3J.js} +4 -4
  6. package/dist/{chunk-OXLH2O32.js → chunk-GUD5HUAM.js} +2 -2
  7. package/dist/{chunk-GTFOF3S6.js → chunk-HJXABEEV.js} +5 -5
  8. package/dist/{chunk-CGNWVGXL.js → chunk-HPHI6KLB.js} +4 -4
  9. package/dist/{chunk-JD4WV327.js → chunk-IR26LUE6.js} +2 -2
  10. package/dist/{chunk-IYHMELNP.js → chunk-JMXLEJCV.js} +2 -2
  11. package/dist/{chunk-D6KKCEG3.js → chunk-KKWHJ3BN.js} +4 -4
  12. package/dist/{chunk-SXXAWBW7.js → chunk-L3GRMTOI.js} +2 -1
  13. package/dist/chunk-L3GRMTOI.js.map +1 -0
  14. package/dist/{chunk-JO6BW3E2.js → chunk-P56H5RCU.js} +76 -13
  15. package/dist/chunk-P56H5RCU.js.map +1 -0
  16. package/dist/{chunk-QM5JXV3C.js → chunk-PS5MSEV6.js} +3 -3
  17. package/dist/{chunk-QM5JXV3C.js.map → chunk-PS5MSEV6.js.map} +1 -1
  18. package/dist/{chunk-2UE3TNY7.js → chunk-QMXIYUBC.js} +2 -2
  19. package/dist/{chunk-2YH743ND.js → chunk-QTCPOZUO.js} +2 -2
  20. package/dist/{chunk-CA5PKTNJ.js → chunk-SIR6MDUU.js} +2 -2
  21. package/dist/{chunk-VSRWL5SP.js → chunk-WTDP35C7.js} +2 -2
  22. package/dist/{chunk-KSY4S4X3.js → chunk-XUDNZERJ.js} +3 -3
  23. package/dist/cursor-runner.js +5 -5
  24. package/dist/electron-utility.js +6 -6
  25. package/dist/{git-repo-IVN2RQNY.js → git-repo-MMFHQHXX.js} +4 -4
  26. package/dist/index.js +10 -10
  27. package/dist/{logger-I6HU4VSX.js → logger-6BPUF2G3.js} +3 -3
  28. package/dist/{login-HKWWOXQK.js → login-5XG2GCJN.js} +7 -7
  29. package/dist/{logout-EZQ4UBLH.js → logout-J4SPGBFX.js} +5 -5
  30. package/dist/{mcp-servers-52C67MDD.js → mcp-servers-HP6LV234.js} +4 -4
  31. package/dist/{plan-backfill-VKDUUMTF.js → plan-backfill-RTYIZRZW.js} +6 -6
  32. package/dist/{roi-GUUSTWXN.js → roi-IL6634QN.js} +3 -3
  33. package/dist/{serve-APXZ7NY3.js → serve-HNZN47KN.js} +28 -19
  34. package/dist/{serve-APXZ7NY3.js.map → serve-HNZN47KN.js.map} +1 -1
  35. package/dist/{skills-XBREPCFU.js → skills-3ISTZIOH.js} +2 -2
  36. package/dist/{start-AACWXGW4.js → start-BCGXIN7G.js} +11 -11
  37. package/package.json +3 -3
  38. package/dist/chunk-JO6BW3E2.js.map +0 -1
  39. package/dist/chunk-SXXAWBW7.js.map +0 -1
  40. /package/dist/{auth-OHZTVIQU.js.map → auth-7OBSJK2V.js.map} +0 -0
  41. /package/dist/{chunk-K7EXPNAD.js.map → chunk-B23NPMUE.js.map} +0 -0
  42. /package/dist/{chunk-ROEOOZOW.js.map → chunk-EKDLDBWX.js.map} +0 -0
  43. /package/dist/{chunk-3OSJ2NBG.js.map → chunk-GBMR7R3J.js.map} +0 -0
  44. /package/dist/{chunk-OXLH2O32.js.map → chunk-GUD5HUAM.js.map} +0 -0
  45. /package/dist/{chunk-GTFOF3S6.js.map → chunk-HJXABEEV.js.map} +0 -0
  46. /package/dist/{chunk-CGNWVGXL.js.map → chunk-HPHI6KLB.js.map} +0 -0
  47. /package/dist/{chunk-JD4WV327.js.map → chunk-IR26LUE6.js.map} +0 -0
  48. /package/dist/{chunk-IYHMELNP.js.map → chunk-JMXLEJCV.js.map} +0 -0
  49. /package/dist/{chunk-D6KKCEG3.js.map → chunk-KKWHJ3BN.js.map} +0 -0
  50. /package/dist/{chunk-2UE3TNY7.js.map → chunk-QMXIYUBC.js.map} +0 -0
  51. /package/dist/{chunk-2YH743ND.js.map → chunk-QTCPOZUO.js.map} +0 -0
  52. /package/dist/{chunk-CA5PKTNJ.js.map → chunk-SIR6MDUU.js.map} +0 -0
  53. /package/dist/{chunk-VSRWL5SP.js.map → chunk-WTDP35C7.js.map} +0 -0
  54. /package/dist/{chunk-KSY4S4X3.js.map → chunk-XUDNZERJ.js.map} +0 -0
  55. /package/dist/{git-repo-IVN2RQNY.js.map → git-repo-MMFHQHXX.js.map} +0 -0
  56. /package/dist/{logger-I6HU4VSX.js.map → logger-6BPUF2G3.js.map} +0 -0
  57. /package/dist/{login-HKWWOXQK.js.map → login-5XG2GCJN.js.map} +0 -0
  58. /package/dist/{logout-EZQ4UBLH.js.map → logout-J4SPGBFX.js.map} +0 -0
  59. /package/dist/{mcp-servers-52C67MDD.js.map → mcp-servers-HP6LV234.js.map} +0 -0
  60. /package/dist/{plan-backfill-VKDUUMTF.js.map → plan-backfill-RTYIZRZW.js.map} +0 -0
  61. /package/dist/{roi-GUUSTWXN.js.map → roi-IL6634QN.js.map} +0 -0
  62. /package/dist/{skills-XBREPCFU.js.map → skills-3ISTZIOH.js.map} +0 -0
  63. /package/dist/{start-AACWXGW4.js.map → start-BCGXIN7G.js.map} +0 -0
@@ -5,8 +5,8 @@ import {
5
5
  loadAuthToken,
6
6
  readConfig,
7
7
  writeConfig
8
- } from "./chunk-2UE3TNY7.js";
9
- import "./chunk-SXXAWBW7.js";
8
+ } from "./chunk-QMXIYUBC.js";
9
+ import "./chunk-L3GRMTOI.js";
10
10
  import "./chunk-JCEWPG3R.js";
11
11
  import "./chunk-2H7UOFLK.js";
12
12
  export {
@@ -16,4 +16,4 @@ export {
16
16
  readConfig,
17
17
  writeConfig
18
18
  };
19
- //# sourceMappingURL=auth-OHZTVIQU.js.map
19
+ //# sourceMappingURL=auth-7OBSJK2V.js.map
@@ -3,28 +3,28 @@ import {
3
3
  detectCapabilities,
4
4
  refreshMcpServers,
5
5
  registerBuiltInProfiles
6
- } from "./chunk-JO6BW3E2.js";
7
- import "./chunk-VSRWL5SP.js";
6
+ } from "./chunk-P56H5RCU.js";
7
+ import "./chunk-WTDP35C7.js";
8
8
  import {
9
9
  getRepoMetadata
10
- } from "./chunk-K7EXPNAD.js";
10
+ } from "./chunk-B23NPMUE.js";
11
11
  import "./chunk-4T2OQAVL.js";
12
12
  import {
13
13
  MCPTokenStore
14
- } from "./chunk-CGNWVGXL.js";
14
+ } from "./chunk-HPHI6KLB.js";
15
15
  import "./chunk-RR6V6SNM.js";
16
- import "./chunk-ROEOOZOW.js";
16
+ import "./chunk-EKDLDBWX.js";
17
17
  import "./chunk-ZFKJAYAN.js";
18
- import "./chunk-KSY4S4X3.js";
19
- import "./chunk-IYHMELNP.js";
20
- import "./chunk-QM5JXV3C.js";
18
+ import "./chunk-XUDNZERJ.js";
19
+ import "./chunk-JMXLEJCV.js";
20
+ import "./chunk-PS5MSEV6.js";
21
21
  import "./chunk-EHQITHQX.js";
22
22
  import "./chunk-X3MULCV5.js";
23
23
  import {
24
24
  flushLogger,
25
25
  logger
26
- } from "./chunk-CA5PKTNJ.js";
27
- import "./chunk-SXXAWBW7.js";
26
+ } from "./chunk-SIR6MDUU.js";
27
+ import "./chunk-L3GRMTOI.js";
28
28
  import "./chunk-JCEWPG3R.js";
29
29
  import "./chunk-2H7UOFLK.js";
30
30
 
@@ -7,10 +7,10 @@ import {
7
7
  } from "./chunk-RR6V6SNM.js";
8
8
  import {
9
9
  logger
10
- } from "./chunk-CA5PKTNJ.js";
10
+ } from "./chunk-SIR6MDUU.js";
11
11
  import {
12
12
  getShipyardHome
13
- } from "./chunk-SXXAWBW7.js";
13
+ } from "./chunk-L3GRMTOI.js";
14
14
  import {
15
15
  external_exports
16
16
  } from "./chunk-JCEWPG3R.js";
@@ -261,7 +261,7 @@ async function refreshRepoPathsInBackground(log) {
261
261
  const startGen = cacheGeneration;
262
262
  const start = Date.now();
263
263
  try {
264
- const { findGitRepos: findGitRepos2, discoverWorktrees: discoverWorktrees2 } = await import("./git-repo-IVN2RQNY.js");
264
+ const { findGitRepos: findGitRepos2, discoverWorktrees: discoverWorktrees2 } = await import("./git-repo-MMFHQHXX.js");
265
265
  const { homedir: homedir2 } = await import("os");
266
266
  const repos = await findGitRepos2(homedir2());
267
267
  const worktrees = await discoverWorktrees2(repos);
@@ -653,7 +653,7 @@ async function runDetectEnvironments(lastKnown) {
653
653
  repoPaths = await findGitRepos(homedir2());
654
654
  } catch (err) {
655
655
  if (lastKnown && lastKnown.length > 0) {
656
- const { logger: logger2 } = await import("./logger-I6HU4VSX.js");
656
+ const { logger: logger2 } = await import("./logger-6BPUF2G3.js");
657
657
  logger2.warn(
658
658
  { err, lastKnownCount: lastKnown.length },
659
659
  "detectEnvironments findGitRepos threw \u2014 preserving lastKnown"
@@ -663,7 +663,7 @@ async function runDetectEnvironments(lastKnown) {
663
663
  return [];
664
664
  }
665
665
  if (repoPaths.length === 0 && lastKnown && lastKnown.length > 0) {
666
- const { logger: logger2 } = await import("./logger-I6HU4VSX.js");
666
+ const { logger: logger2 } = await import("./logger-6BPUF2G3.js");
667
667
  logger2.warn(
668
668
  { lastKnownCount: lastKnown.length },
669
669
  "detectEnvironments walk empty but lastKnown non-empty \u2014 preserving lastKnown"
@@ -796,4 +796,4 @@ export {
796
796
  discoverWorktrees,
797
797
  _testing
798
798
  };
799
- //# sourceMappingURL=chunk-K7EXPNAD.js.map
799
+ //# sourceMappingURL=chunk-B23NPMUE.js.map
@@ -244,7 +244,7 @@ async function detectSkills(environments, lastKnown, options) {
244
244
  try {
245
245
  return await detectSkillsInner(environments, resolvedMirror, options?.activeRepoRoot);
246
246
  } catch (err) {
247
- const { logger } = await import("./logger-I6HU4VSX.js");
247
+ const { logger } = await import("./logger-6BPUF2G3.js");
248
248
  if (lastKnown && lastKnown.length > 0) {
249
249
  logger.warn(
250
250
  { err, lastKnownCount: lastKnown.length },
@@ -428,4 +428,4 @@ export {
428
428
  scopeEnvironmentsToActiveRepo,
429
429
  _resolveBucketForTesting
430
430
  };
431
- //# sourceMappingURL=chunk-ROEOOZOW.js.map
431
+ //# sourceMappingURL=chunk-EKDLDBWX.js.map
@@ -31,17 +31,17 @@ import {
31
31
  parseShipyardDeliverableUrl,
32
32
  planEditorSerializer,
33
33
  toTaskIndexEntry
34
- } from "./chunk-IYHMELNP.js";
34
+ } from "./chunk-JMXLEJCV.js";
35
35
  import {
36
36
  assertNever
37
37
  } from "./chunk-X3MULCV5.js";
38
38
  import {
39
39
  logger
40
- } from "./chunk-CA5PKTNJ.js";
40
+ } from "./chunk-SIR6MDUU.js";
41
41
  import {
42
42
  getPlanBackfillMode,
43
43
  getShipyardHome
44
- } from "./chunk-SXXAWBW7.js";
44
+ } from "./chunk-L3GRMTOI.js";
45
45
  import {
46
46
  external_exports
47
47
  } from "./chunk-JCEWPG3R.js";
@@ -34847,4 +34847,4 @@ export {
34847
34847
  runPlanBackfill,
34848
34848
  buildTaskStateStore
34849
34849
  };
34850
- //# sourceMappingURL=chunk-3OSJ2NBG.js.map
34850
+ //# sourceMappingURL=chunk-GBMR7R3J.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  validateEnv
4
- } from "./chunk-SXXAWBW7.js";
4
+ } from "./chunk-L3GRMTOI.js";
5
5
  import {
6
6
  external_exports
7
7
  } from "./chunk-JCEWPG3R.js";
@@ -48,4 +48,4 @@ function readDaemonVersion() {
48
48
  export {
49
49
  getDaemonVersion
50
50
  };
51
- //# sourceMappingURL=chunk-OXLH2O32.js.map
51
+ //# sourceMappingURL=chunk-GUD5HUAM.js.map
@@ -2,24 +2,24 @@
2
2
  import {
3
3
  print,
4
4
  printError
5
- } from "./chunk-2YH743ND.js";
5
+ } from "./chunk-QTCPOZUO.js";
6
6
  import {
7
7
  getConfigPath,
8
8
  loadAuthToken,
9
9
  readConfig,
10
10
  writeConfig
11
- } from "./chunk-2UE3TNY7.js";
11
+ } from "./chunk-QMXIYUBC.js";
12
12
  import {
13
13
  DeviceExchangeCodeResponseSchema,
14
14
  DevicePollPendingSchema,
15
15
  DevicePollResponseSchema,
16
16
  DeviceStartResponseSchema,
17
17
  ROUTES
18
- } from "./chunk-QM5JXV3C.js";
18
+ } from "./chunk-PS5MSEV6.js";
19
19
  import {
20
20
  isDevMode,
21
21
  validateEnv
22
- } from "./chunk-SXXAWBW7.js";
22
+ } from "./chunk-L3GRMTOI.js";
23
23
  import {
24
24
  external_exports
25
25
  } from "./chunk-JCEWPG3R.js";
@@ -223,4 +223,4 @@ export {
223
223
  ensureAuthenticated,
224
224
  loginCommand
225
225
  };
226
- //# sourceMappingURL=chunk-GTFOF3S6.js.map
226
+ //# sourceMappingURL=chunk-HJXABEEV.js.map
@@ -5,10 +5,10 @@ import {
5
5
  } from "./chunk-RR6V6SNM.js";
6
6
  import {
7
7
  logger
8
- } from "./chunk-CA5PKTNJ.js";
8
+ } from "./chunk-SIR6MDUU.js";
9
9
  import {
10
10
  isClaudeCodeKeychainReadEnabled
11
- } from "./chunk-SXXAWBW7.js";
11
+ } from "./chunk-L3GRMTOI.js";
12
12
  import {
13
13
  external_exports
14
14
  } from "./chunk-JCEWPG3R.js";
@@ -1558,7 +1558,7 @@ async function detectMCPServers(environments, tokenStore, log, lastKnown, prefer
1558
1558
  lastKnown
1559
1559
  );
1560
1560
  } catch (err) {
1561
- const { logger: logger2 } = await import("./logger-I6HU4VSX.js");
1561
+ const { logger: logger2 } = await import("./logger-6BPUF2G3.js");
1562
1562
  if (lastKnown && lastKnown.length > 0) {
1563
1563
  logger2.warn(
1564
1564
  { err, lastKnownCount: lastKnown.length },
@@ -1763,4 +1763,4 @@ export {
1763
1763
  resolveAuthStatuses,
1764
1764
  detectMCPServers
1765
1765
  };
1766
- //# sourceMappingURL=chunk-CGNWVGXL.js.map
1766
+ //# sourceMappingURL=chunk-HPHI6KLB.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  getShipyardHome,
7
7
  validateEnv
8
- } from "./chunk-SXXAWBW7.js";
8
+ } from "./chunk-L3GRMTOI.js";
9
9
 
10
10
  // src/services/bootstrap/native-crash-report.ts
11
11
  import { mkdirSync } from "fs";
@@ -59,4 +59,4 @@ function setOptionalFlag(report, flag) {
59
59
  export {
60
60
  enableNativeCrashReports
61
61
  };
62
- //# sourceMappingURL=chunk-JD4WV327.js.map
62
+ //# sourceMappingURL=chunk-IR26LUE6.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  PUBLISHED_PREVIEW_KINDS,
4
4
  PUBLISH_TTL_CHOICES
5
- } from "./chunk-QM5JXV3C.js";
5
+ } from "./chunk-PS5MSEV6.js";
6
6
  import {
7
7
  external_exports
8
8
  } from "./chunk-JCEWPG3R.js";
@@ -30121,4 +30121,4 @@ export {
30121
30121
  encodeDrain,
30122
30122
  decodeFrame
30123
30123
  };
30124
- //# sourceMappingURL=chunk-IYHMELNP.js.map
30124
+ //# sourceMappingURL=chunk-JMXLEJCV.js.map
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getDaemonVersion
4
- } from "./chunk-OXLH2O32.js";
4
+ } from "./chunk-GUD5HUAM.js";
5
5
  import {
6
6
  WorkerCommandCodec,
7
7
  WorkerReplyCodec
8
8
  } from "./chunk-WW4UGZBY.js";
9
9
  import {
10
10
  buildNodeSpawnEnv
11
- } from "./chunk-VSRWL5SP.js";
11
+ } from "./chunk-WTDP35C7.js";
12
12
  import {
13
13
  createServiceSupervisor
14
14
  } from "./chunk-ZFKJAYAN.js";
@@ -19,7 +19,7 @@ import {
19
19
  getShipyardHome,
20
20
  resolveNodeExecPath,
21
21
  validateEnv
22
- } from "./chunk-SXXAWBW7.js";
22
+ } from "./chunk-L3GRMTOI.js";
23
23
 
24
24
  // src/services/metrics/metrics-collector.ts
25
25
  import { readFileSync } from "fs";
@@ -1116,4 +1116,4 @@ export {
1116
1116
  shutdownFileWatcherGuard,
1117
1117
  guardedSubscribe
1118
1118
  };
1119
- //# sourceMappingURL=chunk-D6KKCEG3.js.map
1119
+ //# sourceMappingURL=chunk-KKWHJ3BN.js.map
@@ -8,6 +8,7 @@ import { homedir } from "os";
8
8
  import { join } from "path";
9
9
  process.env.CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING = "1";
10
10
  process.env.CLAUDE_CODE_ENABLE_TASKS = "1";
11
+ process.env.CLAUDE_CODE_ENABLE_TODO_TOOLS = "1";
11
12
  function isDevMode() {
12
13
  return process.env.SHIPYARD_DEV === "1" || process.env.SHIPYARD_DEV === "true";
13
14
  }
@@ -260,4 +261,4 @@ export {
260
261
  validateEnv,
261
262
  getStallProfilerConfig
262
263
  };
263
- //# sourceMappingURL=chunk-SXXAWBW7.js.map
264
+ //# sourceMappingURL=chunk-L3GRMTOI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/env.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { z } from 'zod';\n\n/**\n * Enable fine-grained tool streaming so MCP tool inputs stream token-by-token\n * via input_json_delta events instead of being buffered as complete JSON.\n * Set early so the subprocess inherits it.\n */\nprocess.env.CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING = '1';\n\n/**\n * Enable the Task system (TaskCreate/TaskGet/TaskList/TaskUpdate) which provides\n * structured task management with dependency tracking (blocks/blockedBy).\n * Replaces TodoWrite — when enabled, CC only has TaskCreate (not TodoWrite).\n */\nprocess.env.CLAUDE_CODE_ENABLE_TASKS = '1';\n\n/**\n * Agent SDK 0.3.233 dropped the Task/Todo tools from the DEFAULT tool surface on\n * Opus 4.8, Sonnet 5, Fable 5, Mythos 5 \"and newer\" — which now includes Fable 5.1.\n * `CLAUDE_CODE_ENABLE_TASKS` alone is no longer sufficient: the 0.3.259 gate is\n * `enableTasks() && (modelNotGated || CLAUDE_CODE_ENABLE_TODO_TOOLS)`, and Shipyard\n * passes no `allowedTools`, so without this the tools silently vanish on exactly our\n * frontier models and `packages/loro-schema/src/todo-helpers.ts` extracts nothing.\n * Failure mode is silent — no type error, no test failure, just an empty todo list.\n */\nprocess.env.CLAUDE_CODE_ENABLE_TODO_TOOLS = '1';\n\n/**\n * Bootstrap exception: reads `process.env` directly because it feeds the\n * `SHIPYARD_DATA_DIR` schema transform (via `shipyardDirName`). Routing it\n * through `validateEnv()` would recurse (validateEnv → parse → transform →\n * shipyardDirName → isDevMode → validateEnv).\n */\nexport function isDevMode(): boolean {\n return process.env.SHIPYARD_DEV === '1' || process.env.SHIPYARD_DEV === 'true';\n}\n\n/**\n * When enabled, the agent runs with only Shipyard builtins (system prompt,\n * comment + visualize MCP servers) and no user/plugin MCP servers.\n * Useful for testing the harness in isolation without external interference.\n *\n * Set `SHIPYARD_VANILLA_AGENT=1` to activate.\n */\nexport function isVanillaAgentMode(): boolean {\n return validateEnv().SHIPYARD_VANILLA_AGENT;\n}\n\n/**\n * Reuse Claude Code's macOS Keychain item (\"Claude Code-credentials\") as a\n * source for MCP connector OAuth clients/tokens.\n *\n * Default OFF. The daemon is a different binary than Claude Code, so reading\n * that Keychain item triggers a macOS password prompt in a GUI session (or a\n * silent denial when headless) — unacceptable in the connector status path,\n * which runs on every capability refresh. Shipyard's own token store is the\n * source of truth, mirroring how local MCPs work (no prompt). Opt back into\n * the legacy import behavior with `SHIPYARD_MCP_REUSE_CC_KEYCHAIN=1`.\n */\nexport function isClaudeCodeKeychainReadEnabled(): boolean {\n return validateEnv().SHIPYARD_MCP_REUSE_CC_KEYCHAIN;\n}\n\n/**\n * Reuse Codex's macOS Keychain item (\"Codex MCP Credentials\") as a source for\n * per-MCP-connector OAuth clients/tokens (Codex DCRs its own atomic\n * client_id+token pairs, useful for borrowing on connectors Claude Code hasn't\n * registered with).\n *\n * Default OFF for the same reason as {@link isClaudeCodeKeychainReadEnabled}:\n * the daemon is a different binary than Codex, so reading that Keychain item\n * triggers a macOS password prompt in a GUI session (or a silent denial when\n * headless) — unacceptable in the connector status path. The\n * `~/.codex/.credentials.json` file fallback is read regardless. Opt in with\n * `SHIPYARD_MCP_REUSE_CODEX_KEYCHAIN=1`.\n */\nexport function isCodexKeychainReadEnabled(): boolean {\n return validateEnv().SHIPYARD_MCP_REUSE_CODEX_KEYCHAIN;\n}\n\nfunction shipyardDirName(): string {\n return isDevMode() ? '.shipyard-dev' : '.shipyard';\n}\n\n/**\n * The signaling worker is a RENDEZVOUS point: a browser and this daemon only\n * meet if they hit the SAME worker. This MUST equal the web build's\n * `VITE_SESSION_SERVER_URL` (.github/workflows/ci.yml + publish-npm.yml) — all\n * live clients (web next+stable, daemons all channels) point here. Do not make\n * this per-channel; a staging worker is a CI/E2E fixture only. See AGENTS.md\n * Invariant #22 (the #4186 \"install daemon\" incident).\n */\nconst DEFAULT_PRODUCTION_SIGNALING_URL = 'https://shipyard-session-server.jacob-191.workers.dev';\nconst DEFAULT_PRODUCTION_WEB_URL = 'https://shipyard.computer';\n\n/**\n * Bootstrap exception: reads `process.env` directly (not `validateEnv()`)\n * because it computes the electron-utility startup-breadcrumb path BEFORE\n * `validateEnv()` runs — the breadcrumb must still resolve when validateEnv\n * itself throws (see apps/daemon/src/electron-utility.ts).\n */\nexport function getShipyardHome(): string {\n if (process.env.SHIPYARD_HOME) return process.env.SHIPYARD_HOME;\n return join(homedir(), shipyardDirName());\n}\n\n/**\n * The executable to fork JS subprocesses with (cursor-runner, the TS language\n * server, the cursor-hook shim).\n *\n * `child_process.fork`/`spawn` default to `process.execPath`. Inside an\n * Electron *utility* process (how the packaged daemon runs) that does NOT point\n * at the main app binary — it resolves to a per-platform helper executable\n * (e.g. `…/Frameworks/Shipyard Helper.app/Contents/MacOS/Shipyard Helper`) that\n * may not exist on disk in the shipped bundle. Forking it ENOENTs, which (with\n * the cursor-runner pre-warm running at boot) crash-looped the daemon on\n * 2026-06-01 (Dylan's log).\n *\n * The Electron *main* process has a guaranteed-valid `process.execPath` (the\n * main app binary, which also honors `ELECTRON_RUN_AS_NODE=1`) and forwards it\n * as `SHIPYARD_NODE_EXEC_PATH` (see apps/electron/src/main/daemon-host.ts). The\n * CLI daemon and dev leave it unset and fall back to `process.execPath`, which\n * is already correct there. Declared in `EnvSchema` so a malformed value fails\n * at boot. Re-exported from `spawn-as-node.ts` for call-site ergonomics.\n */\nexport function resolveNodeExecPath(): string {\n return validateEnv().SHIPYARD_NODE_EXEC_PATH || process.execPath;\n}\n\n/**\n * Resolved one-time plan-backfill mode (boot). Unset/default ⇒ `auto`: the\n * daemon rebuilds missing plan CRDTs write-once on boot, gated only by the\n * marker's `completed` flag (a no-op on every later boot). The env var is an\n * OPTIONAL OVERRIDE, not the gate: `dry-run` forces a read-only fleet-telemetry\n * pass that writes nothing; `off` disables the scan entirely (escape hatch);\n * `write` forces a write pass that bypasses the completion gate (manual re-run /\n * testing).\n */\nexport function getPlanBackfillMode(): 'off' | 'auto' | 'dry-run' | 'write' {\n return validateEnv().SHIPYARD_PLAN_BACKFILL_MODE;\n}\n\nexport const EnvSchema = z.object({\n ANTHROPIC_API_KEY: z.string().min(1).optional(),\n SHIPYARD_DEV: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n SHIPYARD_DAEMON_CHILD: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n SHIPYARD_DATA_DIR: z\n .string()\n .optional()\n .transform((v) => v ?? `~/${shipyardDirName()}/data`),\n LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),\n SHIPYARD_SIGNALING_URL: z.string().url().optional(),\n SHIPYARD_PRODUCTION_SIGNALING_URL: z.string().url().default(DEFAULT_PRODUCTION_SIGNALING_URL),\n SHIPYARD_METRICS_WORKER_URL: z\n .string()\n .url()\n .default('https://shipyard-metrics.jacob-191.workers.dev'),\n SHIPYARD_TELEMETRY: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v !== '0' && v !== 'false'),\n SHIPYARD_USER_TOKEN: z.string().optional(),\n /**\n * Worker URL for the `shipyard roi` report command (distinct from\n * SHIPYARD_METRICS_WORKER_URL, which is the telemetry ingestion endpoint).\n * Falls back to the `--worker-url` CLI flag when unset.\n */\n SHIPYARD_METRICS_URL: z.string().url().optional(),\n SHIPYARD_USER_ID: z.string().optional(),\n SHIPYARD_MACHINE_ID: z.string().optional(),\n SHIPYARD_MACHINE_NAME: z.string().optional(),\n SHIPYARD_USER_DISPLAY_NAME: z.string().optional(),\n SHIPYARD_HOME: z.string().optional(),\n SHIPYARD_WORKTREE_NAME: z.string().optional(),\n /**\n * Electron utility transport mode. Absent for the CLI daemon; set by\n * apps/electron/src/main/daemon-host.ts when the daemon runs as an Electron\n * utility process.\n */\n SHIPYARD_TRANSPORT: z.enum(['electron-port']).optional(),\n /**\n * Build artifact hosting this daemon. Electron disables the daemon's npm\n * self-updater because electron-updater owns app replacement.\n */\n SHIPYARD_ARTIFACT: z.enum(['electron']).optional(),\n SHIPYARD_VANILLA_AGENT: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n /**\n * One-time plan-CRDT backfill mode (auto-on-boot). Empty/absent → `auto`:\n * every daemon rebuilds its missing plan CRDTs write-once on boot, gated ONLY\n * by the `~/.shipyard/data/plan-backfill-v1.json` marker's `completed` flag, so\n * it runs once per machine and is a no-op on every subsequent boot — no manual\n * action required. The env var is an OPTIONAL OVERRIDE, not the gate:\n * - `dry-run` → force a READ-ONLY pass that emits `plan_backfill_dryrun` fleet\n * telemetry and writes nothing (testing / observability).\n * - `off` → disable the scan entirely (escape hatch).\n * - `write` → force a write pass that bypasses the completion gate (manual\n * re-run / testing); still per-task idempotent via the marker.\n */\n SHIPYARD_PLAN_BACKFILL_MODE: z\n .enum(['off', 'auto', 'dry-run', 'write', ''])\n .optional()\n .transform((v) => (v === undefined || v === '' ? 'auto' : v)),\n /**\n * Opt in to reusing Claude Code's macOS Keychain credentials for MCP OAuth.\n * Default OFF — see {@link isClaudeCodeKeychainReadEnabled} for why (prompt\n * avoidance). Validated here so a typo fails at boot.\n */\n SHIPYARD_MCP_REUSE_CC_KEYCHAIN: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n /**\n * Opt in to reusing Codex's macOS Keychain credentials (\"Codex MCP\n * Credentials\") for MCP OAuth. Default OFF — see\n * {@link isCodexKeychainReadEnabled} for why (prompt avoidance). Validated\n * here so a typo fails at boot.\n */\n SHIPYARD_MCP_REUSE_CODEX_KEYCHAIN: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n SHIPYARD_STALL_PROFILER_ENABLED: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v !== '0' && v !== 'false'),\n /**\n * Master kill-switch for native-crash evidence capture: the supervisor exit\n * record, `process.report` fatal-error diagnostic reports, and the supervisor\n * stderr tail. Default ON. Telemetry of the distilled summary is separately\n * gated by `SHIPYARD_TELEMETRY`; this only controls the local on-disk capture.\n */\n SHIPYARD_CRASH_EVIDENCE: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v !== '0' && v !== 'false'),\n /**\n * Event-loop stall threshold (ms). Once `histogram.max` crosses this,\n * the profiler starts a CPU profile. History: raised 250ms → 5000ms in\n * May 2026 because the capture itself amplified the stalls it measured\n * (V8 inspector `post()` consumed ~493ms of an 800ms capture window);\n * lowered 5000ms → 1000ms in Jun 2026 (#4484) because the dominant fleet\n * stall volume is 1–10s jank that 5s never profiled. Amplification is now\n * bounded by the profiler's own guards instead of the threshold: the 5-min\n * SHIPYARD_STALL_PROFILER_MIN_INTERVAL_MS rate limit between captures, a\n * capture-in-progress flag, and the 250ms sample window — worst case 12\n * captures/hour (~3s of profiling per hour).\n * Override via `SHIPYARD_STALL_PROFILER_THRESHOLD_MS`.\n */\n SHIPYARD_STALL_PROFILER_THRESHOLD_MS: z.coerce.number().int().positive().default(1_000),\n /**\n * How long to sample the V8 CPU profile after a stall is detected.\n * Default 250ms — long enough for the post-stall queue drain and the\n * cascading sibling stall (if any) to land in the same profile, but\n * short enough that the capture window does not itself amplify the\n * stall on the same event loop. Lowered from 1000 → 250 in May 2026\n * after profile evidence showed `#capture` consumed ~1s of inclusive\n * time inside a 3.5s stall window — the profiler was contributing\n * to the stalls it was trying to measure once #3204 dropped the\n * threshold from 500ms to 250ms.\n */\n SHIPYARD_STALL_PROFILER_PROFILE_DURATION_MS: z.coerce.number().int().positive().default(250),\n /**\n * Cascading-stall suppression window. After one capture, subsequent\n * stalls within this window log `stall_profile_suppressed` instead of\n * starting a new profile. Raised from 30s to 300s (5min) in May 2026\n * to prevent capture storms — at 30s a recurring stall every 60s would\n * trigger 2 captures/min, each adding hundreds of ms of inspector overhead.\n */\n SHIPYARD_STALL_PROFILER_MIN_INTERVAL_MS: z.coerce.number().int().nonnegative().default(300_000),\n /**\n * Supervisor wedge detection: if the daemon child sends no IPC heartbeats\n * for this many ms, the supervisor declares the event loop wedged, sends\n * SIGUSR2 to capture a CPU profile (the inspector runs off the JS loop),\n * waits 2s, then SIGKILLs and respawns via the normal abnormal-exit flow.\n * Generous default — 30s tolerates GC pauses and other legitimate sync\n * blocks well outside human-noticeable territory.\n */\n SHIPYARD_WEDGE_TIMEOUT_MS: z.coerce.number().int().positive().default(30_000),\n /**\n * Daemon child IPC heartbeat interval. Must be smaller than\n * SHIPYARD_WEDGE_TIMEOUT_MS by a comfortable margin so a single missed\n * heartbeat doesn't trip the wedge detector.\n */\n SHIPYARD_HEARTBEAT_INTERVAL_MS: z.coerce.number().int().positive().default(2_000),\n /**\n * When set to `'electron-safe-storage'`, the vault-key-manager wraps the\n * master key via Electron's safeStorage API (macOS Keychain on macOS,\n * Secret Service on Linux). Set by daemon-host.ts in the Electron main\n * process. When absent, the daemon falls back to the existing AES-256-GCM\n * file-based path (CLI daemon path — unchanged).\n */\n SHIPYARD_VAULT_BACKEND: z.enum(['electron-safe-storage']).optional(),\n /**\n * Absolute path to a Node-capable executable for forking JS subprocesses\n * (cursor-runner, the TS language server, the cursor-hook shim). Set by\n * apps/electron/src/main/daemon-host.ts to the Electron MAIN process's\n * `process.execPath` (the main app binary), because the daemon utility\n * process's own `process.execPath` resolves to a helper executable that may\n * not exist in the packaged bundle. Absent for the CLI daemon, which falls\n * back to its own `process.execPath`. See `resolveNodeExecPath()`.\n */\n SHIPYARD_NODE_EXEC_PATH: z.string().optional(),\n /**\n * TTL (ms) for the per-repo worktree list cache. Browser polls at 4-7/sec;\n * this collapses redundant git subprocess invocations to 1 per TTL window.\n * Set to 0 to disable caching (useful for tests that need fresh results).\n */\n SHIPYARD_WORKTREE_LIST_TTL_MS: z.coerce.number().int().min(0).default(30_000),\n /**\n * Override for the web app URL the daemon advertises. Absent → derived from\n * the signaling URL (see `getWebAppUrl`). A malformed value fails at boot\n * rather than propagating into URL concatenation.\n */\n SHIPYARD_WEB_URL: z.string().url().optional(),\n SHIPYARD_PRODUCTION_WEB_URL: z.string().url().default(DEFAULT_PRODUCTION_WEB_URL),\n /**\n * Absolute path override for the Claude Code binary. When set and the file\n * exists, the daemon spawns it instead of the SDK-bundled native binary.\n * See `resolveClaudeCodePath` / `resolveClaudeBinaryPath`.\n */\n CLAUDE_CODE_PATH: z.string().optional(),\n /**\n * Suppress auto-opening the verification URL in the browser during the\n * CLI device-login flow. Default OFF (the browser opens).\n */\n SHIPYARD_NO_OPEN: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n /**\n * Kill-switch for Loro CRDT recovery on startup. Default OFF (recovery runs).\n */\n SHIPYARD_DISABLE_LORO_RECOVERY: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v === '1' || v === 'true'),\n /**\n * Harness HTTP MCP server (Codex's endpoint). Default ON — Codex ships with\n * every daemon and needs it. `SHIPYARD_HARNESS_HTTP=0` is the kill-switch for\n * Codex-disabled deployments.\n */\n SHIPYARD_HARNESS_HTTP: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v !== '0' && v !== 'false'),\n /**\n * Use the shared `codex app-server` engine (single token owner — fixes the\n * 401-storm). Default ON. Set to `0`/`false` for the legacy per-process path.\n */\n SHIPYARD_CODEX_SHARED_ENGINE: z\n .enum(['1', 'true', '0', 'false', ''])\n .optional()\n .transform((v) => v !== '0' && v !== 'false'),\n /**\n * Browser-metrics sampling cadence. Kept as a raw string here — clamp /\n * disable (`0`) / invalid-fallback semantics + logging live in\n * `parseBrowserMetricsInterval` (services/metrics/browser-metrics-config.ts),\n * which consumes this validated value.\n */\n SHIPYARD_BROWSER_METRICS_INTERVAL_MS: z.string().optional(),\n /**\n * Max concurrent file watchers before the guard sheds new subscriptions.\n * Absent → default (450). An invalid value fails at boot.\n */\n SHIPYARD_FILE_WATCHER_MAX: z.coerce.number().int().positive().optional(),\n /**\n * Override the daemon's own --max-old-space-size (MB). When absent, the\n * value is auto-derived from os.totalmem() × 25 %, clamped to [2048, 8192].\n * An explicit value is honored as-is (clamped to 65536 to catch typos) and\n * passed to --max-old-space-size at BOTH spawn sites: the outer CLI\n * supervisor (start-supervisor.ts) and the Electron utility-process fork\n * (daemon-host.ts). See apps/daemon/src/shared/daemon-heap-limit.ts. The\n * Electron path also honors a `daemon.maxHeapGb` config.json setting below\n * this env var in precedence — see daemon-heap-limit-config.ts.\n */\n SHIPYARD_DAEMON_MAX_OLD_SPACE_MB: z.coerce.number().int().positive().optional(),\n});\n\nexport type Env = z.infer<typeof EnvSchema>;\n\nexport function validateEnv(): Env {\n return EnvSchema.parse(process.env);\n}\n\n/**\n * Resolved profiler tuning derived from the validated env. Re-parses the\n * schema so a typo in one of the *_MS vars (e.g. `THRESHOLD_MS=abc`) fails\n * here too — boot already failed in `validateEnv()` (start.ts / serve.ts\n * call it), this second parse is cheap and keeps the wiring side free of\n * `process.env.X` reads at the call site.\n */\nexport interface StallProfilerConfig {\n enabled: boolean;\n thresholdMs: number;\n captureMs: number;\n rateLimitMs: number;\n}\n\nexport function getStallProfilerConfig(): StallProfilerConfig {\n const env = validateEnv();\n\n /**\n * Default OFF in packaged Electron when `SHIPYARD_STALL_PROFILER_ENABLED`\n * is unset. Rationale: the V8 inspector `post()` blocks the event loop\n * during capture — in a 2,959ms stall, `node:inspector:117 post` consumed\n * 493.5ms of 800ms captured, i.e. the profiler was profiling itself.\n * Trade: lose production stall visibility in packaged builds in exchange\n * for not amplifying stalls for users. Dev sessions and CLI daemon keep\n * profiling enabled by default. Override with `SHIPYARD_STALL_PROFILER_ENABLED=1`.\n *\n * `env.SHIPYARD_STALL_PROFILER_ENABLED` is `true` when the env var is\n * absent (the Zod transform treats missing/empty as truthy). We detect\n * \"explicitly set\" vs \"defaulted\" by reading `process.env` directly here\n * — the schema transform already validated it, so this read is safe.\n */\n const explicitlySet =\n process.env.SHIPYARD_STALL_PROFILER_ENABLED !== undefined &&\n process.env.SHIPYARD_STALL_PROFILER_ENABLED !== '';\n\n const enabled = explicitlySet\n ? env.SHIPYARD_STALL_PROFILER_ENABLED\n : env.SHIPYARD_ARTIFACT !== 'electron';\n\n return {\n enabled,\n thresholdMs: env.SHIPYARD_STALL_PROFILER_THRESHOLD_MS,\n captureMs: env.SHIPYARD_STALL_PROFILER_PROFILE_DURATION_MS,\n rateLimitMs: env.SHIPYARD_STALL_PROFILER_MIN_INTERVAL_MS,\n };\n}\n"],"mappings":"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","names":[]}
@@ -10,7 +10,7 @@ import {
10
10
  run,
11
11
  runWithTimeout,
12
12
  truncateDiff
13
- } from "./chunk-K7EXPNAD.js";
13
+ } from "./chunk-B23NPMUE.js";
14
14
  import {
15
15
  gitExecSafe
16
16
  } from "./chunk-4T2OQAVL.js";
@@ -19,13 +19,13 @@ import {
19
19
  CODEX_RUNTIME_ID,
20
20
  CURSOR_RUNTIME_ID,
21
21
  detectMCPServers
22
- } from "./chunk-CGNWVGXL.js";
22
+ } from "./chunk-HPHI6KLB.js";
23
23
  import {
24
24
  isEnoent
25
25
  } from "./chunk-RR6V6SNM.js";
26
26
  import {
27
27
  detectSkills
28
- } from "./chunk-ROEOOZOW.js";
28
+ } from "./chunk-EKDLDBWX.js";
29
29
  import {
30
30
  createOneShotPool
31
31
  } from "./chunk-ZFKJAYAN.js";
@@ -38,7 +38,7 @@ import {
38
38
  formatTaskFeedback,
39
39
  toRecord,
40
40
  toSdkContent
41
- } from "./chunk-KSY4S4X3.js";
41
+ } from "./chunk-XUDNZERJ.js";
42
42
  import {
43
43
  AGENT_IDS,
44
44
  AGENT_SYSTEM_CLAUDE_CODE,
@@ -50,22 +50,22 @@ import {
50
50
  REASONING_EFFORTS,
51
51
  inflateToolResultContent,
52
52
  isImageMimeType
53
- } from "./chunk-IYHMELNP.js";
53
+ } from "./chunk-JMXLEJCV.js";
54
54
  import {
55
55
  AnthropicAuthStatusSchema,
56
56
  CodexAuthStatusSchema,
57
57
  CursorAuthStatusSchema,
58
58
  PermissionModeSchema,
59
59
  TESTED_CODEX_VERSION
60
- } from "./chunk-QM5JXV3C.js";
60
+ } from "./chunk-PS5MSEV6.js";
61
61
  import {
62
62
  logger
63
- } from "./chunk-CA5PKTNJ.js";
63
+ } from "./chunk-SIR6MDUU.js";
64
64
  import {
65
65
  getShipyardHome,
66
66
  resolveNodeExecPath,
67
67
  validateEnv
68
- } from "./chunk-SXXAWBW7.js";
68
+ } from "./chunk-L3GRMTOI.js";
69
69
  import {
70
70
  external_exports
71
71
  } from "./chunk-JCEWPG3R.js";
@@ -1286,8 +1286,10 @@ function convertUserContent(content) {
1286
1286
  // src/services/session/profiles/model-capability-tiers.ts
1287
1287
  var MODEL_CAPABILITY_TIERS = {
1288
1288
  "claude-opus-5": "frontier",
1289
+ "claude-fable-5-1": "frontier",
1289
1290
  "claude-fable-5": "frontier",
1290
1291
  "claude-sonnet-5": "strong",
1292
+ "gpt-6-astra": "frontier",
1291
1293
  "gpt-5.6-sol": "frontier",
1292
1294
  "gpt-5.6-terra": "strong",
1293
1295
  "gpt-5.6-luna": "capable",
@@ -1515,6 +1517,45 @@ var claudeCodeProfile = {
1515
1517
  vision: true
1516
1518
  }
1517
1519
  },
1520
+ {
1521
+ /**
1522
+ * Fable 5.1 (released 2026-09-01). Specs read from the Agent SDK 0.3.259
1523
+ * native-binary model registry, which is authoritative over the docs page:
1524
+ * `context:{window:1e6,native_1m:true}`, `max_output_tokens:{upper:128000}`,
1525
+ * `default_effort:"high"`, `pricing:"tier_10_50_cache_read_0_25"`.
1526
+ *
1527
+ * `defaultEffort` is `high`, NOT the `xhigh` used by the Fable 5 entry
1528
+ * below — the registry states `high` for both, and the Fable 5 entry's
1529
+ * `xhigh` is a Shipyard deviation we are deliberately not propagating.
1530
+ *
1531
+ * The effort ladder mirrors Fable 5: the registry gives both models an
1532
+ * identical `effort_cost_index` (low/medium/high/xhigh/max) and identical
1533
+ * effort capabilities (`effort`,`max_effort`,`xhigh_effort`). `none` and
1534
+ * `ultracode` are Shipyard-synthetic tiers carried on the sibling entry.
1535
+ *
1536
+ * 1M context needs no `ONE_M_SPAWN_PREFIXES` addition — `resolveSpawnModel`
1537
+ * prefix-matches `claude-fable-5`, so `claude-fable-5-1[1m]` already routes.
1538
+ */
1539
+ id: "claude-fable-5-1",
1540
+ nativeName: "claude-fable-5-1",
1541
+ displayName: "Claude Fable 5.1",
1542
+ description: "For demanding reasoning and long-horizon agentic work",
1543
+ note: "Covered Model \xB7 30-day retention",
1544
+ contextWindow: 1e6,
1545
+ maxOutput: 128e3,
1546
+ supportedEfforts: ["none", "low", "medium", "high", "xhigh", "ultracode", "max"],
1547
+ defaultEffort: "high",
1548
+ tagline: "For demanding reasoning and long-horizon agentic work",
1549
+ speedTier: "slow",
1550
+ costInputUsd: 10,
1551
+ costOutputUsd: 50,
1552
+ capabilities: {
1553
+ reasoning: true,
1554
+ adaptiveThinking: true,
1555
+ webSearch: true,
1556
+ vision: true
1557
+ }
1558
+ },
1518
1559
  {
1519
1560
  id: "claude-fable-5",
1520
1561
  nativeName: "claude-fable-5",
@@ -1936,7 +1977,10 @@ var CODEX_PRICING_SEED = {
1936
1977
  * GPT-5.6 family standard rates (per 1M tokens), verified 2026-07-13 against
1937
1978
  * openai.com/index/gpt-5-6 + OpenRouter. cached-input ≈ 10% of input (the
1938
1979
  * convention the 5.5/5.4 rows use). No high-context tier modeled for 5.6 —
1939
- * unverified; the standard rate is used across the full 372k window.
1980
+ * unverified; the standard rate is used across the full 272k window.
1981
+ *
1982
+ * `gpt-6-astra` is intentionally absent: OpenAI has published no rates for it,
1983
+ * so its turns report no estimated cost rather than a fabricated one.
1940
1984
  */
1941
1985
  "gpt-5.6-sol": {
1942
1986
  inputUsdPerMtok: 5,
@@ -3118,7 +3162,7 @@ var CODEX_MODEL_CATALOG = withCapabilityTiers([
3118
3162
  nativeName: "gpt-5.6-sol",
3119
3163
  displayName: "GPT-5.6 Sol",
3120
3164
  description: "Latest frontier agentic coding model \u2014 complex code, research, and ambitious work.",
3121
- contextWindow: 372e3,
3165
+ contextWindow: 272e3,
3122
3166
  supportedEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"],
3123
3167
  defaultEffort: "low",
3124
3168
  pricing: pricingFor("gpt-5.6-sol"),
@@ -3137,7 +3181,7 @@ var CODEX_MODEL_CATALOG = withCapabilityTiers([
3137
3181
  nativeName: "gpt-5.6-terra",
3138
3182
  displayName: "GPT-5.6 Terra",
3139
3183
  description: "Balanced agentic coding model for everyday work.",
3140
- contextWindow: 372e3,
3184
+ contextWindow: 272e3,
3141
3185
  supportedEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"],
3142
3186
  defaultEffort: "medium",
3143
3187
  pricing: pricingFor("gpt-5.6-terra"),
@@ -3156,7 +3200,7 @@ var CODEX_MODEL_CATALOG = withCapabilityTiers([
3156
3200
  nativeName: "gpt-5.6-luna",
3157
3201
  displayName: "GPT-5.6 Luna",
3158
3202
  description: "Fast and affordable agentic coding model.",
3159
- contextWindow: 372e3,
3203
+ contextWindow: 272e3,
3160
3204
  supportedEfforts: ["low", "medium", "high", "xhigh", "max"],
3161
3205
  defaultEffort: "medium",
3162
3206
  pricing: pricingFor("gpt-5.6-luna"),
@@ -3169,6 +3213,25 @@ var CODEX_MODEL_CATALOG = withCapabilityTiers([
3169
3213
  webSearch: false,
3170
3214
  vision: true
3171
3215
  }
3216
+ },
3217
+ {
3218
+ id: "gpt-6-astra",
3219
+ nativeName: "gpt-6-astra",
3220
+ displayName: "GPT-6 Astra",
3221
+ description: "Our most capable model for complex, demanding work.",
3222
+ contextWindow: 272e3,
3223
+ supportedEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"],
3224
+ defaultEffort: "low",
3225
+ pricing: pricingFor("gpt-6-astra"),
3226
+ tagline: "Frontier OpenAI Codex \u2014 most capable, strong even at low effort",
3227
+ speedTier: "standard",
3228
+ ...displayCostFor("gpt-6-astra"),
3229
+ capabilities: {
3230
+ reasoning: true,
3231
+ adaptiveThinking: false,
3232
+ webSearch: false,
3233
+ vision: true
3234
+ }
3172
3235
  }
3173
3236
  ]);
3174
3237
 
@@ -8364,4 +8427,4 @@ export {
8364
8427
  refreshInstalledAgents,
8365
8428
  refreshCodexAuthSlice
8366
8429
  };
8367
- //# sourceMappingURL=chunk-JO6BW3E2.js.map
8430
+ //# sourceMappingURL=chunk-P56H5RCU.js.map