@runtypelabs/cli 2.17.0 → 2.19.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 (3) hide show
  1. package/README.md +28 -1
  2. package/dist/index.js +1993 -721
  3. package/package.json +7 -5
package/dist/index.js CHANGED
@@ -7,8 +7,13 @@ var __require = /* @__PURE__ */ ((x2) => typeof require !== "undefined" ? requir
7
7
  if (typeof require !== "undefined") return require.apply(this, arguments);
8
8
  throw Error('Dynamic require of "' + x2 + '" is not supported');
9
9
  });
10
- var __esm = (fn, res) => function __init() {
11
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ var __esm = (fn, res, err) => function __init() {
11
+ if (err) throw err[0];
12
+ try {
13
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
14
+ } catch (e) {
15
+ throw err = [e], e;
16
+ }
12
17
  };
13
18
  var __export = (target, all) => {
14
19
  for (var name in all)
@@ -68,9 +73,9 @@ var init_credential_store = __esm({
68
73
  }
69
74
  }
70
75
  getMachineKey() {
71
- const hostname3 = os.hostname();
76
+ const hostname4 = os.hostname();
72
77
  const username = os.userInfo().username;
73
- return crypto3.createHash("sha256").update(`runtype-cli-${hostname3}-${username}`).digest("hex").substring(0, 32);
78
+ return crypto3.createHash("sha256").update(`runtype-cli-${hostname4}-${username}`).digest("hex").substring(0, 32);
74
79
  }
75
80
  async saveCredentials(credentials) {
76
81
  const configData = {
@@ -131,15 +136,15 @@ var init_credential_store = __esm({
131
136
  });
132
137
 
133
138
  // src/index.ts
134
- import { Command as Command32 } from "commander";
135
- import chalk41 from "chalk";
139
+ import { Command as Command33 } from "commander";
140
+ import chalk42 from "chalk";
136
141
 
137
142
  // src/lib/load-env.ts
138
143
  import { readFileSync } from "fs";
139
144
  import { resolve } from "path";
140
- function loadEnv(path17 = resolve(process.cwd(), ".env")) {
145
+ function loadEnv(path18 = resolve(process.cwd(), ".env")) {
141
146
  try {
142
- const content = readFileSync(path17, "utf8").replace(/\r\n?/g, "\n");
147
+ const content = readFileSync(path18, "utf8").replace(/\r\n?/g, "\n");
143
148
  for (const line of content.split("\n")) {
144
149
  if (!line.trim() || line.trimStart().startsWith("#")) continue;
145
150
  const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)?\s*$/);
@@ -174,8 +179,8 @@ var CallbackServer = class {
174
179
  expectedState;
175
180
  constructor() {
176
181
  this.app = express();
177
- this.codePromise = new Promise((resolve10, reject) => {
178
- this.codeResolve = resolve10;
182
+ this.codePromise = new Promise((resolve11, reject) => {
183
+ this.codeResolve = resolve11;
179
184
  this.codeReject = reject;
180
185
  });
181
186
  this.app.get("/callback", (req, res) => {
@@ -1381,10 +1386,10 @@ function mergeDefs(...defs) {
1381
1386
  function cloneDef(schema) {
1382
1387
  return mergeDefs(schema._zod.def);
1383
1388
  }
1384
- function getElementAtPath(obj, path17) {
1385
- if (!path17)
1389
+ function getElementAtPath(obj, path18) {
1390
+ if (!path18)
1386
1391
  return obj;
1387
- return path17.reduce((acc, key) => acc?.[key], obj);
1392
+ return path18.reduce((acc, key) => acc?.[key], obj);
1388
1393
  }
1389
1394
  function promiseAllObject(promisesObj) {
1390
1395
  const keys = Object.keys(promisesObj);
@@ -1793,11 +1798,11 @@ function explicitlyAborted(x2, startIndex = 0) {
1793
1798
  }
1794
1799
  return false;
1795
1800
  }
1796
- function prefixIssues(path17, issues) {
1801
+ function prefixIssues(path18, issues) {
1797
1802
  return issues.map((iss) => {
1798
1803
  var _a3;
1799
1804
  (_a3 = iss).path ?? (_a3.path = []);
1800
- iss.path.unshift(path17);
1805
+ iss.path.unshift(path18);
1801
1806
  return iss;
1802
1807
  });
1803
1808
  }
@@ -1944,16 +1949,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1944
1949
  }
1945
1950
  function formatError(error51, mapper = (issue2) => issue2.message) {
1946
1951
  const fieldErrors = { _errors: [] };
1947
- const processError = (error52, path17 = []) => {
1952
+ const processError = (error52, path18 = []) => {
1948
1953
  for (const issue2 of error52.issues) {
1949
1954
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1950
- issue2.errors.map((issues) => processError({ issues }, [...path17, ...issue2.path]));
1955
+ issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
1951
1956
  } else if (issue2.code === "invalid_key") {
1952
- processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1957
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1953
1958
  } else if (issue2.code === "invalid_element") {
1954
- processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1959
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1955
1960
  } else {
1956
- const fullpath = [...path17, ...issue2.path];
1961
+ const fullpath = [...path18, ...issue2.path];
1957
1962
  if (fullpath.length === 0) {
1958
1963
  fieldErrors._errors.push(mapper(issue2));
1959
1964
  } else {
@@ -1980,17 +1985,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1980
1985
  }
1981
1986
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1982
1987
  const result = { errors: [] };
1983
- const processError = (error52, path17 = []) => {
1988
+ const processError = (error52, path18 = []) => {
1984
1989
  var _a3, _b;
1985
1990
  for (const issue2 of error52.issues) {
1986
1991
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1987
- issue2.errors.map((issues) => processError({ issues }, [...path17, ...issue2.path]));
1992
+ issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
1988
1993
  } else if (issue2.code === "invalid_key") {
1989
- processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1994
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1990
1995
  } else if (issue2.code === "invalid_element") {
1991
- processError({ issues: issue2.issues }, [...path17, ...issue2.path]);
1996
+ processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
1992
1997
  } else {
1993
- const fullpath = [...path17, ...issue2.path];
1998
+ const fullpath = [...path18, ...issue2.path];
1994
1999
  if (fullpath.length === 0) {
1995
2000
  result.errors.push(mapper(issue2));
1996
2001
  continue;
@@ -2022,8 +2027,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
2022
2027
  }
2023
2028
  function toDotPath(_path) {
2024
2029
  const segs = [];
2025
- const path17 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2026
- for (const seg of path17) {
2030
+ const path18 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2031
+ for (const seg of path18) {
2027
2032
  if (typeof seg === "number")
2028
2033
  segs.push(`[${seg}]`);
2029
2034
  else if (typeof seg === "symbol")
@@ -14709,13 +14714,13 @@ function resolveRef(ref, ctx) {
14709
14714
  if (!ref.startsWith("#")) {
14710
14715
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14711
14716
  }
14712
- const path17 = ref.slice(1).split("/").filter(Boolean);
14713
- if (path17.length === 0) {
14717
+ const path18 = ref.slice(1).split("/").filter(Boolean);
14718
+ if (path18.length === 0) {
14714
14719
  return ctx.rootSchema;
14715
14720
  }
14716
14721
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14717
- if (path17[0] === defsKey) {
14718
- const key = path17[1];
14722
+ if (path18[0] === defsKey) {
14723
+ const key = path18[1];
14719
14724
  if (!key || !ctx.defs[key]) {
14720
14725
  throw new Error(`Reference not found: ${ref}`);
14721
14726
  }
@@ -15160,8 +15165,8 @@ var apiRoutingDocSchema = external_exports.object({
15160
15165
  });
15161
15166
 
15162
15167
  // ../shared/dist/chunk-3V2W6XMX.mjs
15163
- function getNestedValue(obj, path17) {
15164
- let normalizedPath = path17;
15168
+ function getNestedValue(obj, path18) {
15169
+ let normalizedPath = path18;
15165
15170
  normalizedPath = normalizedPath.replace(/^\$\.?/, "");
15166
15171
  normalizedPath = normalizedPath.replace(/\[(\d+)\]/g, ".$1");
15167
15172
  normalizedPath = normalizedPath.replace(/\[['"]([^'"\]]+)['"]\]/g, ".$1");
@@ -16095,6 +16100,27 @@ var artifactSSEEventSchema = external_exports.discriminatedUnion("type", [
16095
16100
  artifactCompleteEventSchema,
16096
16101
  artifactSingleEventSchema
16097
16102
  ]);
16103
+ var AGENT_CONTENT_CONFIG_KEYS = {
16104
+ model: true,
16105
+ systemPrompt: true,
16106
+ temperature: true,
16107
+ topP: true,
16108
+ topK: true,
16109
+ frequencyPenalty: true,
16110
+ presencePenalty: true,
16111
+ seed: true,
16112
+ tools: true,
16113
+ reasoning: true,
16114
+ advisor: true,
16115
+ loopConfig: true,
16116
+ voice: true,
16117
+ errorHandling: true,
16118
+ artifacts: true,
16119
+ loggingPolicy: true,
16120
+ temporal: true,
16121
+ memory: true
16122
+ };
16123
+ var AGENT_CONTENT_CONFIG_KEY_LIST = Object.keys(AGENT_CONTENT_CONFIG_KEYS).sort();
16098
16124
  var configurationStatusSchema = external_exports.enum([
16099
16125
  "configured",
16100
16126
  "needs_configuration",
@@ -17594,6 +17620,10 @@ var runtimeArtifactSandboxSchema = external_exports.enum([
17594
17620
  var runtimeArtifactServiceBackingSchema = external_exports.enum(["none", "service-binding"]);
17595
17621
  var runtimeArtifactPersistenceSchema = external_exports.enum(["none", "kv", "service-binding"]);
17596
17622
  var runtimeArtifactKeyModeSchema = external_exports.enum(["own", "platform", "hybrid"]);
17623
+ var runtimeArtifactServiceBindingTargetSchema = external_exports.string().regex(
17624
+ /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/,
17625
+ "Service binding target must be a Cloudflare service name (lowercase letters, numbers, and hyphens; no leading/trailing hyphen)."
17626
+ );
17597
17627
  var runtimeArtifactBindingTypeSchema = external_exports.enum([
17598
17628
  "service",
17599
17629
  "kv_namespace",
@@ -17613,6 +17643,13 @@ var runtimeArtifactBindingSchema = external_exports.object({
17613
17643
  type: runtimeArtifactBindingTypeSchema,
17614
17644
  target: external_exports.string().min(1).optional(),
17615
17645
  optional: external_exports.boolean().optional()
17646
+ }).superRefine((binding, ctx) => {
17647
+ if (binding.type !== "service" || binding.target === void 0) return;
17648
+ const parsed = runtimeArtifactServiceBindingTargetSchema.safeParse(binding.target);
17649
+ if (parsed.success) return;
17650
+ for (const issue2 of parsed.error.issues) {
17651
+ ctx.addIssue({ ...issue2, path: ["target", ...issue2.path] });
17652
+ }
17616
17653
  });
17617
17654
  var runtimeArtifactEligibilityReasonSchema = external_exports.object({
17618
17655
  code: external_exports.string().min(1),
@@ -33460,9 +33497,9 @@ var DEFAULT_MODELS_FOR_NEW_ACCOUNTS = [
33460
33497
  { provider: "runtype", modelId: "gemini-3-1-flash-lite", isDefault: false },
33461
33498
  { provider: "runtype", modelId: "gemini-3-1-flash-image", isDefault: false },
33462
33499
  { provider: "runtype", modelId: "gemini-3.1-pro", isDefault: false },
33463
- // xAI models (routed via xAI direct, with Vercel fallback)
33464
- { provider: "runtype", modelId: "grok-4", isDefault: false },
33465
- { provider: "runtype", modelId: "grok-4-fast", isDefault: false },
33500
+ // xAI models (routed via Vercel, with xAI fallback when available)
33501
+ { provider: "runtype", modelId: "grok-4.3", isDefault: false },
33502
+ { provider: "runtype", modelId: "grok-4.1-fast-non-reasoning", isDefault: false },
33466
33503
  // Inception models (routed via Vercel)
33467
33504
  { provider: "runtype", modelId: "mercury-2", isDefault: false },
33468
33505
  // Moonshot models (routed via Cloudflare Workers AI)
@@ -33483,16 +33520,15 @@ var userProfileFeaturesSchema = external_exports.object({
33483
33520
  enableDashboardAssistant: external_exports.boolean(),
33484
33521
  // Routed model id the dashboard assistant dispatches with. Driven by the
33485
33522
  // `dashboard-assistant-model` string flag.
33486
- dashboardAssistantModel: external_exports.string()
33523
+ dashboardAssistantModel: external_exports.string(),
33524
+ // Gates the chrome_extension surface type in the dashboard (surface picker
33525
+ // and downstream config/ship UI). Driven by the `CHROME_SURFACE` boolean
33526
+ // flag.
33527
+ enableChromeSurface: external_exports.boolean()
33487
33528
  });
33488
33529
  var MODEL_FAMILY_PROVIDER_IDS = {
33489
- "claude-4-opus": {
33490
- "vercel": "anthropic/claude-4-opus"
33491
- },
33492
- "claude-4-sonnet": {
33493
- "vercel": "anthropic/claude-4-sonnet"
33494
- },
33495
33530
  "claude-fable-5": {
33531
+ "anthropic": "claude-fable-5",
33496
33532
  "vercel": "anthropic/claude-fable-5"
33497
33533
  },
33498
33534
  "claude-haiku-4-5": {
@@ -33507,12 +33543,13 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33507
33543
  },
33508
33544
  "claude-opus-4": {
33509
33545
  "anthropic": "claude-opus-4-20250514",
33510
- "bedrock": "bedrock/claude-opus-4",
33511
33546
  "vercel": "anthropic/claude-opus-4"
33512
33547
  },
33548
+ "claude-opus-4-0": {
33549
+ "anthropic": "claude-opus-4-0"
33550
+ },
33513
33551
  "claude-opus-4-1": {
33514
33552
  "anthropic": "claude-opus-4-1-20250805",
33515
- "bedrock": "bedrock/claude-opus-4-1",
33516
33553
  "vercel": "anthropic/claude-opus-4.1"
33517
33554
  },
33518
33555
  "claude-opus-4-1-20250805": {
@@ -33522,17 +33559,22 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33522
33559
  "anthropic": "claude-opus-4-20250514"
33523
33560
  },
33524
33561
  "claude-opus-4-5": {
33525
- "anthropic": "anthropic/claude-opus-4-5",
33562
+ "anthropic": "claude-opus-4-5-20251101",
33526
33563
  "vercel": "anthropic/claude-opus-4.5"
33527
33564
  },
33565
+ "claude-opus-4-5-20251101": {
33566
+ "anthropic": "claude-opus-4-5-20251101"
33567
+ },
33528
33568
  "claude-opus-4-6": {
33529
- "anthropic": "anthropic/claude-opus-4-6",
33569
+ "anthropic": "claude-opus-4-6",
33530
33570
  "vercel": "anthropic/claude-opus-4.6"
33531
33571
  },
33532
33572
  "claude-opus-4-7": {
33573
+ "anthropic": "claude-opus-4-7",
33533
33574
  "vercel": "anthropic/claude-opus-4.7"
33534
33575
  },
33535
33576
  "claude-opus-4-8": {
33577
+ "anthropic": "claude-opus-4-8",
33536
33578
  "vercel": "anthropic/claude-opus-4.8"
33537
33579
  },
33538
33580
  "claude-opus-4.1": {
@@ -33552,9 +33594,11 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33552
33594
  },
33553
33595
  "claude-sonnet-4": {
33554
33596
  "anthropic": "claude-sonnet-4-20250514",
33555
- "bedrock": "bedrock/claude-sonnet-4",
33556
33597
  "vercel": "anthropic/claude-sonnet-4"
33557
33598
  },
33599
+ "claude-sonnet-4-0": {
33600
+ "anthropic": "claude-sonnet-4-0"
33601
+ },
33558
33602
  "claude-sonnet-4-20250514": {
33559
33603
  "anthropic": "claude-sonnet-4-20250514"
33560
33604
  },
@@ -33566,12 +33610,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33566
33610
  "anthropic": "claude-sonnet-4-5-20250929"
33567
33611
  },
33568
33612
  "claude-sonnet-4-6": {
33569
- "anthropic": "claude-sonnet-4-6-20260217",
33613
+ "anthropic": "claude-sonnet-4-6",
33570
33614
  "vercel": "anthropic/claude-sonnet-4.6"
33571
33615
  },
33572
- "claude-sonnet-4-6-20260217": {
33573
- "anthropic": "claude-sonnet-4-6-20260217"
33574
- },
33575
33616
  "claude-sonnet-4.5": {
33576
33617
  "vercel": "anthropic/claude-sonnet-4.5"
33577
33618
  },
@@ -33584,36 +33625,40 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33584
33625
  "codestral-embed": {
33585
33626
  "vercel": "mistral/codestral-embed"
33586
33627
  },
33628
+ "cogito-v2-1-671b": {
33629
+ "togetherai": "togetherai/deepcogito/cogito-v2-1-671b"
33630
+ },
33587
33631
  "command-a": {
33588
33632
  "vercel": "cohere/command-a"
33589
33633
  },
33590
- "command-r": {
33591
- "vercel": "cohere/command-r"
33592
- },
33593
- "command-r-plus": {
33594
- "vercel": "cohere/command-r-plus"
33634
+ "deepcogito/cogito-v2-1-671b": {
33635
+ "togetherai": "togetherai/deepcogito/cogito-v2-1-671b"
33595
33636
  },
33596
33637
  "deepseek": {
33597
- "togetherai": "deepseek-ai/DeepSeek-V3",
33638
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-V3",
33598
33639
  "vercel": "deepseek/deepseek-v3"
33599
33640
  },
33600
- "deepseek-r1": {
33601
- "togetherai": "deepseek-ai/DeepSeek-R1",
33602
- "vercel": "deepseek/deepseek-r1"
33641
+ "deepseek-ai/DeepSeek-R1": {
33642
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-R1"
33643
+ },
33644
+ "deepseek-ai/DeepSeek-V3": {
33645
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-V3"
33603
33646
  },
33604
- "DeepSeek-R1": {
33605
- "togetherai": "deepseek-ai/DeepSeek-R1"
33647
+ "deepseek-ai/DeepSeek-V3-1": {
33648
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-V3-1"
33606
33649
  },
33607
- "deepseek-r1-distill-llama-70b": {
33608
- "vercel": "deepseek/deepseek-r1-distill-llama-70b"
33650
+ "deepseek-ai/DeepSeek-V4-Pro": {
33651
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-V4-Pro"
33652
+ },
33653
+ "deepseek-r1": {
33654
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-R1",
33655
+ "vercel": "deepseek/deepseek-r1"
33609
33656
  },
33610
33657
  "deepseek-v3": {
33611
33658
  "vercel": "deepseek/deepseek-v3"
33612
33659
  },
33613
- "DeepSeek-V3": {
33614
- "togetherai": "deepseek-ai/DeepSeek-V3"
33615
- },
33616
33660
  "deepseek-v3-1": {
33661
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-V3-1",
33617
33662
  "vercel": "deepseek/deepseek-v3.1"
33618
33663
  },
33619
33664
  "deepseek-v3-1-terminus": {
@@ -33638,6 +33683,7 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33638
33683
  "vercel": "deepseek/deepseek-v4-flash"
33639
33684
  },
33640
33685
  "deepseek-v4-pro": {
33686
+ "togetherai": "togetherai/deepseek-ai/DeepSeek-V4-Pro",
33641
33687
  "vercel": "deepseek/deepseek-v4-pro"
33642
33688
  },
33643
33689
  "devstral-2": {
@@ -33655,91 +33701,162 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33655
33701
  "embed-v4.0": {
33656
33702
  "vercel": "cohere/embed-v4.0"
33657
33703
  },
33704
+ "essentialai/Rnj-1-Instruct": {
33705
+ "togetherai": "togetherai/essentialai/Rnj-1-Instruct"
33706
+ },
33707
+ "flux-2-flex": {
33708
+ "vercel": "bfl/flux-2-flex"
33709
+ },
33710
+ "flux-2-klein-4b": {
33711
+ "vercel": "bfl/flux-2-klein-4b"
33712
+ },
33713
+ "flux-2-klein-9b": {
33714
+ "vercel": "bfl/flux-2-klein-9b"
33715
+ },
33716
+ "flux-2-max": {
33717
+ "vercel": "bfl/flux-2-max"
33718
+ },
33719
+ "flux-2-pro": {
33720
+ "vercel": "bfl/flux-2-pro"
33721
+ },
33722
+ "flux-fast-schnell": {
33723
+ "vercel": "prodia/flux-fast-schnell"
33724
+ },
33725
+ "flux-kontext-max": {
33726
+ "vercel": "bfl/flux-kontext-max"
33727
+ },
33728
+ "flux-kontext-pro": {
33729
+ "vercel": "bfl/flux-kontext-pro"
33730
+ },
33731
+ "flux-pro-1-0-fill": {
33732
+ "vercel": "bfl/flux-pro-1.0-fill"
33733
+ },
33734
+ "flux-pro-1-1": {
33735
+ "vercel": "bfl/flux-pro-1.1"
33736
+ },
33737
+ "flux-pro-1-1-ultra": {
33738
+ "vercel": "bfl/flux-pro-1.1-ultra"
33739
+ },
33740
+ "flux-pro-1.0-fill": {
33741
+ "vercel": "bfl/flux-pro-1.0-fill"
33742
+ },
33743
+ "flux-pro-1.1": {
33744
+ "vercel": "bfl/flux-pro-1.1"
33745
+ },
33746
+ "flux-pro-1.1-ultra": {
33747
+ "vercel": "bfl/flux-pro-1.1-ultra"
33748
+ },
33658
33749
  "gemini-2-5-flash": {
33659
- "google": "google/gemini-2.5-flash-preview",
33660
- "vercel": "google/gemini-2-5-flash"
33750
+ "google": "gemini-2.5-flash",
33751
+ "vercel": "google/gemini-2.5-flash"
33661
33752
  },
33662
33753
  "gemini-2-5-flash-image": {
33663
33754
  "google": "google/gemini-2.5-flash-image-preview",
33664
33755
  "vercel": "google/gemini-2.5-flash-image"
33665
33756
  },
33666
33757
  "gemini-2-5-flash-lite": {
33758
+ "google": "gemini-2.5-flash-lite",
33667
33759
  "vercel": "google/gemini-2.5-flash-lite"
33668
33760
  },
33669
- "gemini-2-5-flash-preview-image": {
33670
- "google": "google/gemini-2.5-flash-preview-image"
33761
+ "gemini-2-5-flash-preview-tts": {
33762
+ "google": "gemini-2.5-flash-preview-tts"
33671
33763
  },
33672
33764
  "gemini-2-5-pro": {
33673
33765
  "google": "gemini-2.5-pro",
33674
- "vercel": "google/gemini-2-5-pro"
33766
+ "vercel": "google/gemini-2.5-pro"
33767
+ },
33768
+ "gemini-2-5-pro-preview-tts": {
33769
+ "google": "gemini-2.5-pro-preview-tts"
33675
33770
  },
33676
33771
  "gemini-2.5-flash": {
33677
33772
  "google": "gemini-2.5-flash",
33678
33773
  "vercel": "google/gemini-2.5-flash"
33679
33774
  },
33680
33775
  "gemini-2.5-flash-image": {
33776
+ "google": "gemini-2.5-flash-image",
33681
33777
  "vercel": "google/gemini-2.5-flash-image"
33682
33778
  },
33683
33779
  "gemini-2.5-flash-image-preview": {
33684
33780
  "google": "google/gemini-2.5-flash-image-preview"
33685
33781
  },
33686
33782
  "gemini-2.5-flash-lite": {
33783
+ "google": "gemini-2.5-flash-lite",
33687
33784
  "vercel": "google/gemini-2.5-flash-lite"
33688
33785
  },
33689
- "gemini-2.5-flash-preview": {
33690
- "google": "google/gemini-2.5-flash-preview"
33691
- },
33692
- "gemini-2.5-flash-preview-image": {
33693
- "google": "google/gemini-2.5-flash-preview-image"
33786
+ "gemini-2.5-flash-preview-tts": {
33787
+ "google": "gemini-2.5-flash-preview-tts"
33694
33788
  },
33695
33789
  "gemini-2.5-pro": {
33696
33790
  "google": "gemini-2.5-pro",
33697
33791
  "vercel": "google/gemini-2.5-pro"
33698
33792
  },
33793
+ "gemini-2.5-pro-preview-tts": {
33794
+ "google": "gemini-2.5-pro-preview-tts"
33795
+ },
33699
33796
  "gemini-3-1-flash-image": {
33700
33797
  "vercel": "google/gemini-3.1-flash-image"
33701
33798
  },
33702
33799
  "gemini-3-1-flash-lite": {
33800
+ "google": "gemini-3.1-flash-lite",
33703
33801
  "vercel": "google/gemini-3.1-flash-lite"
33704
33802
  },
33705
33803
  "gemini-3-1-pro": {
33804
+ "google": "gemini-3.1-pro-preview",
33706
33805
  "vercel": "google/gemini-3.1-pro-preview"
33707
33806
  },
33807
+ "gemini-3-1-pro-preview-customtools": {
33808
+ "google": "gemini-3.1-pro-preview-customtools"
33809
+ },
33708
33810
  "gemini-3-5-flash": {
33811
+ "google": "gemini-3.5-flash",
33709
33812
  "vercel": "google/gemini-3.5-flash"
33710
33813
  },
33711
33814
  "gemini-3-flash": {
33712
- "google": "google/gemini-3-flash-preview",
33815
+ "google": "gemini-3-flash-preview",
33713
33816
  "vercel": "google/gemini-3-flash"
33714
33817
  },
33715
33818
  "gemini-3-flash-preview": {
33716
- "google": "google/gemini-3-flash-preview"
33819
+ "google": "gemini-3-flash-preview"
33717
33820
  },
33718
33821
  "gemini-3-pro-image": {
33822
+ "google": "gemini-3-pro-image-preview",
33719
33823
  "vercel": "google/gemini-3-pro-image"
33720
33824
  },
33825
+ "gemini-3-pro-image-preview": {
33826
+ "google": "gemini-3-pro-image-preview"
33827
+ },
33721
33828
  "gemini-3.1-flash-image": {
33722
33829
  "vercel": "google/gemini-3.1-flash-image"
33723
33830
  },
33724
33831
  "gemini-3.1-flash-lite": {
33832
+ "google": "gemini-3.1-flash-lite",
33725
33833
  "vercel": "google/gemini-3.1-flash-lite"
33726
33834
  },
33727
33835
  "gemini-3.1-pro-preview": {
33836
+ "google": "gemini-3.1-pro-preview",
33728
33837
  "vercel": "google/gemini-3.1-pro-preview"
33729
33838
  },
33839
+ "gemini-3.1-pro-preview-customtools": {
33840
+ "google": "gemini-3.1-pro-preview-customtools"
33841
+ },
33730
33842
  "gemini-3.5-flash": {
33843
+ "google": "gemini-3.5-flash",
33731
33844
  "vercel": "google/gemini-3.5-flash"
33732
33845
  },
33733
33846
  "gemini-embedding-001": {
33847
+ "google": "gemini-embedding-001",
33734
33848
  "vercel": "google/gemini-embedding-001"
33735
33849
  },
33736
33850
  "gemini-embedding-2": {
33737
33851
  "vercel": "google/gemini-embedding-2"
33738
33852
  },
33739
33853
  "gemma-4-26b-a4b-it": {
33854
+ "google": "gemma-4-26b-a4b-it",
33740
33855
  "vercel": "google/gemma-4-26b-a4b-it"
33741
33856
  },
33742
33857
  "gemma-4-31b-it": {
33858
+ "google": "gemma-4-31b-it",
33859
+ "togetherai": "togetherai/pearl-ai/gemma-4-31b-it",
33743
33860
  "vercel": "google/gemma-4-31b-it"
33744
33861
  },
33745
33862
  "glm-4-5": {
@@ -33797,9 +33914,11 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33797
33914
  "vercel": "zai/glm-4.7-flashx"
33798
33915
  },
33799
33916
  "glm-5": {
33917
+ "togetherai": "togetherai/zai-org/GLM-5",
33800
33918
  "vercel": "zai/glm-5"
33801
33919
  },
33802
33920
  "glm-5-1": {
33921
+ "togetherai": "togetherai/zai-org/GLM-5.1",
33803
33922
  "vercel": "zai/glm-5.1"
33804
33923
  },
33805
33924
  "glm-5-turbo": {
@@ -33811,87 +33930,47 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33811
33930
  "glm-5v-turbo": {
33812
33931
  "vercel": "zai/glm-5v-turbo"
33813
33932
  },
33933
+ "google/gemma-4-31B-it": {
33934
+ "togetherai": "togetherai/google/gemma-4-31B-it"
33935
+ },
33814
33936
  "gpt-4-1": {
33815
33937
  "openai": "gpt-4.1",
33816
- "vercel": "openai/gpt-4-1"
33817
- },
33818
- "gpt-4-1-batch": {
33819
- "openai": "gpt-4.1-batch"
33938
+ "vercel": "openai/gpt-4.1"
33820
33939
  },
33821
33940
  "gpt-4-1-mini": {
33822
33941
  "openai": "gpt-4.1-mini",
33823
- "vercel": "openai/gpt-4-1-mini"
33824
- },
33825
- "gpt-4-1-mini-batch": {
33826
- "openai": "gpt-4.1-mini-batch"
33942
+ "vercel": "openai/gpt-4.1-mini"
33827
33943
  },
33828
33944
  "gpt-4-1-nano": {
33829
33945
  "openai": "gpt-4.1-nano",
33830
- "vercel": "openai/gpt-4-1-nano"
33831
- },
33832
- "gpt-4-1-nano-batch": {
33833
- "openai": "gpt-4.1-nano-batch"
33946
+ "vercel": "openai/gpt-4.1-nano"
33834
33947
  },
33835
33948
  "gpt-4.1": {
33836
33949
  "openai": "gpt-4.1",
33837
33950
  "vercel": "openai/gpt-4.1"
33838
33951
  },
33839
- "gpt-4.1-batch": {
33840
- "openai": "gpt-4.1-batch"
33841
- },
33842
33952
  "gpt-4.1-mini": {
33843
33953
  "openai": "gpt-4.1-mini",
33844
33954
  "vercel": "openai/gpt-4.1-mini"
33845
33955
  },
33846
- "gpt-4.1-mini-batch": {
33847
- "openai": "gpt-4.1-mini-batch"
33848
- },
33849
33956
  "gpt-4.1-nano": {
33850
33957
  "openai": "gpt-4.1-nano",
33851
33958
  "vercel": "openai/gpt-4.1-nano"
33852
33959
  },
33853
- "gpt-4.1-nano-batch": {
33854
- "openai": "gpt-4.1-nano-batch"
33855
- },
33856
33960
  "gpt-4o": {
33857
33961
  "openai": "gpt-4o",
33858
33962
  "vercel": "openai/gpt-4o"
33859
33963
  },
33860
- "gpt-4o-batch": {
33861
- "openai": "gpt-4o-batch"
33862
- },
33863
33964
  "gpt-4o-mini": {
33864
33965
  "openai": "gpt-4o-mini",
33865
33966
  "vercel": "openai/gpt-4o-mini"
33866
33967
  },
33867
- "gpt-4o-mini-batch": {
33868
- "openai": "gpt-4o-mini-batch"
33869
- },
33870
- "gpt-4o-mini-realtime": {
33871
- "openai": "openai/gpt-4o-mini-realtime"
33872
- },
33873
- "gpt-4o-mini-realtime-batch": {
33874
- "openai": "gpt-4o-mini-realtime-batch"
33875
- },
33876
33968
  "gpt-4o-mini-search": {
33877
- "openai": "openai/openai/gpt-4o-mini-search-preview",
33878
33969
  "vercel": "openai/gpt-4o-mini-search-preview"
33879
33970
  },
33880
33971
  "gpt-4o-mini-search-preview": {
33881
33972
  "vercel": "openai/gpt-4o-mini-search-preview"
33882
33973
  },
33883
- "gpt-4o-mini-search-preview-batch": {
33884
- "openai": "openai/gpt-4o-mini-search-preview-batch"
33885
- },
33886
- "gpt-4o-realtime": {
33887
- "openai": "openai/gpt-4o-realtime"
33888
- },
33889
- "gpt-4o-realtime-batch": {
33890
- "openai": "gpt-4o-realtime-batch"
33891
- },
33892
- "gpt-4o-search-preview-batch": {
33893
- "openai": "gpt-4o-search-preview-batch"
33894
- },
33895
33974
  "gpt-5": {
33896
33975
  "openai": "gpt-5",
33897
33976
  "vercel": "openai/gpt-5"
@@ -33900,26 +33979,18 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33900
33979
  "openai": "gpt-5.1",
33901
33980
  "vercel": "openai/gpt-5.1-thinking"
33902
33981
  },
33903
- "gpt-5-1-batch": {
33904
- "openai": "gpt-5.1-batch"
33905
- },
33906
33982
  "gpt-5-1-codex": {
33907
33983
  "openai": "gpt-5.1-codex",
33908
33984
  "vercel": "openai/gpt-5.1-codex"
33909
33985
  },
33910
- "gpt-5-1-codex-batch": {
33911
- "openai": "gpt-5.1-codex-batch"
33912
- },
33913
33986
  "gpt-5-1-codex-max": {
33987
+ "openai": "gpt-5.1-codex-max",
33914
33988
  "vercel": "openai/gpt-5.1-codex-max"
33915
33989
  },
33916
33990
  "gpt-5-1-codex-mini": {
33917
33991
  "openai": "gpt-5.1-codex-mini",
33918
33992
  "vercel": "openai/gpt-5.1-codex-mini"
33919
33993
  },
33920
- "gpt-5-1-codex-mini-batch": {
33921
- "openai": "gpt-5.1-codex-mini-batch"
33922
- },
33923
33994
  "gpt-5-1-instant": {
33924
33995
  "vercel": "openai/gpt-5.1-instant"
33925
33996
  },
@@ -33927,95 +33998,85 @@ var MODEL_FAMILY_PROVIDER_IDS = {
33927
33998
  "openai": "gpt-5.2",
33928
33999
  "vercel": "openai/gpt-5.2"
33929
34000
  },
33930
- "gpt-5-2-batch": {
33931
- "openai": "gpt-5.2-batch"
33932
- },
33933
34001
  "gpt-5-2-chat": {
33934
34002
  "vercel": "openai/gpt-5.2-chat"
33935
34003
  },
33936
34004
  "gpt-5-2-codex": {
34005
+ "openai": "gpt-5.2-codex",
33937
34006
  "vercel": "openai/gpt-5.2-codex"
33938
34007
  },
33939
34008
  "gpt-5-2-pro": {
33940
34009
  "openai": "gpt-5.2-pro",
33941
34010
  "vercel": "openai/gpt-5.2-pro"
33942
34011
  },
33943
- "gpt-5-2-pro-batch": {
33944
- "openai": "gpt-5.2-pro-batch"
33945
- },
33946
34012
  "gpt-5-3-chat": {
33947
34013
  "vercel": "openai/gpt-5.3-chat"
33948
34014
  },
33949
34015
  "gpt-5-3-codex": {
34016
+ "openai": "gpt-5.3-codex",
33950
34017
  "vercel": "openai/gpt-5.3-codex"
33951
34018
  },
34019
+ "gpt-5-3-codex-spark": {
34020
+ "openai": "gpt-5.3-codex-spark"
34021
+ },
33952
34022
  "gpt-5-4": {
34023
+ "openai": "gpt-5.4",
33953
34024
  "vercel": "openai/gpt-5.4"
33954
34025
  },
33955
34026
  "gpt-5-4-mini": {
34027
+ "openai": "gpt-5.4-mini",
33956
34028
  "vercel": "openai/gpt-5.4-mini"
33957
34029
  },
33958
34030
  "gpt-5-4-nano": {
34031
+ "openai": "gpt-5.4-nano",
33959
34032
  "vercel": "openai/gpt-5.4-nano"
33960
34033
  },
33961
34034
  "gpt-5-4-pro": {
34035
+ "openai": "gpt-5.4-pro",
33962
34036
  "vercel": "openai/gpt-5.4-pro"
33963
34037
  },
33964
34038
  "gpt-5-5": {
34039
+ "openai": "gpt-5.5",
33965
34040
  "vercel": "openai/gpt-5.5"
33966
34041
  },
33967
34042
  "gpt-5-5-pro": {
34043
+ "openai": "gpt-5.5-pro",
33968
34044
  "vercel": "openai/gpt-5.5-pro"
33969
34045
  },
33970
- "gpt-5-batch": {
33971
- "openai": "gpt-5-batch"
33972
- },
33973
34046
  "gpt-5-chat": {
33974
34047
  "vercel": "openai/gpt-5-chat"
33975
34048
  },
33976
34049
  "gpt-5-codex": {
34050
+ "openai": "gpt-5-codex",
33977
34051
  "vercel": "openai/gpt-5-codex"
33978
34052
  },
33979
34053
  "gpt-5-mini": {
33980
34054
  "openai": "gpt-5-mini",
33981
34055
  "vercel": "openai/gpt-5-mini"
33982
34056
  },
33983
- "gpt-5-mini-batch": {
33984
- "openai": "gpt-5-mini-batch"
33985
- },
33986
34057
  "gpt-5-nano": {
33987
34058
  "openai": "gpt-5-nano",
33988
34059
  "vercel": "openai/gpt-5-nano"
33989
34060
  },
33990
- "gpt-5-nano-batch": {
33991
- "openai": "gpt-5-nano-batch"
33992
- },
33993
34061
  "gpt-5-pro": {
34062
+ "openai": "gpt-5-pro",
33994
34063
  "vercel": "openai/gpt-5-pro"
33995
34064
  },
33996
34065
  "gpt-5.1": {
33997
34066
  "openai": "gpt-5.1"
33998
34067
  },
33999
- "gpt-5.1-batch": {
34000
- "openai": "gpt-5.1-batch"
34001
- },
34002
34068
  "gpt-5.1-codex": {
34003
34069
  "openai": "gpt-5.1-codex",
34004
34070
  "vercel": "openai/gpt-5.1-codex"
34005
34071
  },
34006
- "gpt-5.1-codex-batch": {
34007
- "openai": "gpt-5.1-codex-batch"
34008
- },
34009
34072
  "gpt-5.1-codex-max": {
34073
+ "openai": "gpt-5.1-codex-max",
34010
34074
  "vercel": "openai/gpt-5.1-codex-max"
34011
34075
  },
34012
34076
  "gpt-5.1-codex-mini": {
34013
34077
  "openai": "gpt-5.1-codex-mini",
34014
34078
  "vercel": "openai/gpt-5.1-codex-mini"
34015
34079
  },
34016
- "gpt-5.1-codex-mini-batch": {
34017
- "openai": "gpt-5.1-codex-mini-batch"
34018
- },
34019
34080
  "gpt-5.1-instant": {
34020
34081
  "vercel": "openai/gpt-5.1-instant"
34021
34082
  },
@@ -34026,68 +34087,99 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34026
34087
  "openai": "gpt-5.2",
34027
34088
  "vercel": "openai/gpt-5.2"
34028
34089
  },
34029
- "gpt-5.2-batch": {
34030
- "openai": "gpt-5.2-batch"
34031
- },
34032
34090
  "gpt-5.2-chat": {
34033
34091
  "vercel": "openai/gpt-5.2-chat"
34034
34092
  },
34035
34093
  "gpt-5.2-codex": {
34094
+ "openai": "gpt-5.2-codex",
34036
34095
  "vercel": "openai/gpt-5.2-codex"
34037
34096
  },
34038
34097
  "gpt-5.2-pro": {
34039
34098
  "openai": "gpt-5.2-pro",
34040
34099
  "vercel": "openai/gpt-5.2-pro"
34041
34100
  },
34042
- "gpt-5.2-pro-batch": {
34043
- "openai": "gpt-5.2-pro-batch"
34044
- },
34045
34101
  "gpt-5.3-chat": {
34046
34102
  "vercel": "openai/gpt-5.3-chat"
34047
34103
  },
34048
34104
  "gpt-5.3-codex": {
34105
+ "openai": "gpt-5.3-codex",
34049
34106
  "vercel": "openai/gpt-5.3-codex"
34050
34107
  },
34108
+ "gpt-5.3-codex-spark": {
34109
+ "openai": "gpt-5.3-codex-spark"
34110
+ },
34051
34111
  "gpt-5.4": {
34112
+ "openai": "gpt-5.4",
34052
34113
  "vercel": "openai/gpt-5.4"
34053
34114
  },
34054
34115
  "gpt-5.4-mini": {
34116
+ "openai": "gpt-5.4-mini",
34055
34117
  "vercel": "openai/gpt-5.4-mini"
34056
34118
  },
34057
34119
  "gpt-5.4-nano": {
34120
+ "openai": "gpt-5.4-nano",
34058
34121
  "vercel": "openai/gpt-5.4-nano"
34059
34122
  },
34060
34123
  "gpt-5.4-pro": {
34124
+ "openai": "gpt-5.4-pro",
34061
34125
  "vercel": "openai/gpt-5.4-pro"
34062
34126
  },
34063
34127
  "gpt-5.5": {
34128
+ "openai": "gpt-5.5",
34064
34129
  "vercel": "openai/gpt-5.5"
34065
34130
  },
34066
34131
  "gpt-5.5-pro": {
34132
+ "openai": "gpt-5.5-pro",
34067
34133
  "vercel": "openai/gpt-5.5-pro"
34068
34134
  },
34135
+ "gpt-image-1": {
34136
+ "openai": "gpt-image-1",
34137
+ "vercel": "openai/gpt-image-1"
34138
+ },
34139
+ "gpt-image-1-5": {
34140
+ "openai": "gpt-image-1.5",
34141
+ "vercel": "openai/gpt-image-1.5"
34142
+ },
34143
+ "gpt-image-1-mini": {
34144
+ "openai": "gpt-image-1-mini",
34145
+ "vercel": "openai/gpt-image-1-mini"
34146
+ },
34147
+ "gpt-image-1.5": {
34148
+ "openai": "gpt-image-1.5",
34149
+ "vercel": "openai/gpt-image-1.5"
34150
+ },
34151
+ "gpt-image-2": {
34152
+ "vercel": "openai/gpt-image-2"
34153
+ },
34069
34154
  "gpt-oss-120b": {
34155
+ "togetherai": "togetherai/openai/gpt-oss-120b",
34070
34156
  "vercel": "openai/gpt-oss-120b"
34071
34157
  },
34072
34158
  "gpt-oss-20b": {
34159
+ "togetherai": "togetherai/openai/gpt-oss-20b",
34073
34160
  "vercel": "openai/gpt-oss-20b"
34074
34161
  },
34075
34162
  "gpt-oss-safeguard-20b": {
34076
34163
  "vercel": "openai/gpt-oss-safeguard-20b"
34077
34164
  },
34078
- "grok-4": {
34079
- "vercel": "xai/grok-4",
34080
- "xai": "x/grok-4"
34081
- },
34082
34165
  "grok-4-1-fast-non-reasoning": {
34083
34166
  "vercel": "xai/grok-4.1-fast-non-reasoning"
34084
34167
  },
34085
34168
  "grok-4-1-fast-reasoning": {
34086
34169
  "vercel": "xai/grok-4.1-fast-reasoning"
34087
34170
  },
34171
+ "grok-4-20-0309-non-reasoning": {
34172
+ "xai": "grok-4.20-0309-non-reasoning"
34173
+ },
34174
+ "grok-4-20-0309-reasoning": {
34175
+ "xai": "grok-4.20-0309-reasoning"
34176
+ },
34088
34177
  "grok-4-20-multi-agent": {
34089
34178
  "vercel": "xai/grok-4.20-multi-agent"
34090
34179
  },
34180
+ "grok-4-20-multi-agent-0309": {
34181
+ "xai": "grok-4.20-multi-agent-0309"
34182
+ },
34091
34183
  "grok-4-20-multi-agent-beta": {
34092
34184
  "vercel": "xai/grok-4.20-multi-agent-beta"
34093
34185
  },
@@ -34104,10 +34196,8 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34104
34196
  "vercel": "xai/grok-4.20-reasoning-beta"
34105
34197
  },
34106
34198
  "grok-4-3": {
34107
- "vercel": "xai/grok-4.3"
34108
- },
34109
- "grok-4-fast": {
34110
- "xai": "x/grok-4-fast"
34199
+ "vercel": "xai/grok-4.3",
34200
+ "xai": "grok-4.3"
34111
34201
  },
34112
34202
  "grok-4.1-fast-non-reasoning": {
34113
34203
  "vercel": "xai/grok-4.1-fast-non-reasoning"
@@ -34115,9 +34205,18 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34115
34205
  "grok-4.1-fast-reasoning": {
34116
34206
  "vercel": "xai/grok-4.1-fast-reasoning"
34117
34207
  },
34208
+ "grok-4.20-0309-non-reasoning": {
34209
+ "xai": "grok-4.20-0309-non-reasoning"
34210
+ },
34211
+ "grok-4.20-0309-reasoning": {
34212
+ "xai": "grok-4.20-0309-reasoning"
34213
+ },
34118
34214
  "grok-4.20-multi-agent": {
34119
34215
  "vercel": "xai/grok-4.20-multi-agent"
34120
34216
  },
34217
+ "grok-4.20-multi-agent-0309": {
34218
+ "xai": "grok-4.20-multi-agent-0309"
34219
+ },
34121
34220
  "grok-4.20-multi-agent-beta": {
34122
34221
  "vercel": "xai/grok-4.20-multi-agent-beta"
34123
34222
  },
@@ -34134,16 +34233,51 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34134
34233
  "vercel": "xai/grok-4.20-reasoning-beta"
34135
34234
  },
34136
34235
  "grok-4.3": {
34137
- "vercel": "xai/grok-4.3"
34236
+ "vercel": "xai/grok-4.3",
34237
+ "xai": "grok-4.3"
34138
34238
  },
34139
34239
  "grok-build-0-1": {
34140
- "vercel": "xai/grok-build-0.1"
34240
+ "vercel": "xai/grok-build-0.1",
34241
+ "xai": "grok-build-0.1"
34141
34242
  },
34142
34243
  "grok-build-0.1": {
34143
- "vercel": "xai/grok-build-0.1"
34244
+ "vercel": "xai/grok-build-0.1",
34245
+ "xai": "grok-build-0.1"
34246
+ },
34247
+ "grok-imagine-image": {
34248
+ "vercel": "xai/grok-imagine-image",
34249
+ "xai": "grok-imagine-image"
34250
+ },
34251
+ "grok-imagine-image-quality": {
34252
+ "xai": "grok-imagine-image-quality"
34253
+ },
34254
+ "grok-imagine-video": {
34255
+ "vercel": "xai/grok-imagine-video",
34256
+ "xai": "grok-imagine-video"
34257
+ },
34258
+ "grok-imagine-video-1-5": {
34259
+ "vercel": "xai/grok-imagine-video-1.5-preview"
34260
+ },
34261
+ "grok-imagine-video-1.5-preview": {
34262
+ "vercel": "xai/grok-imagine-video-1.5-preview"
34263
+ },
34264
+ "imagen-4-0-fast-generate-001": {
34265
+ "vercel": "google/imagen-4.0-fast-generate-001"
34144
34266
  },
34145
- "grok-code-fast-1": {
34146
- "xai": "x/grok-code-fast-1"
34267
+ "imagen-4-0-generate-001": {
34268
+ "vercel": "google/imagen-4.0-generate-001"
34269
+ },
34270
+ "imagen-4-0-ultra-generate-001": {
34271
+ "vercel": "google/imagen-4.0-ultra-generate-001"
34272
+ },
34273
+ "imagen-4.0-fast-generate-001": {
34274
+ "vercel": "google/imagen-4.0-fast-generate-001"
34275
+ },
34276
+ "imagen-4.0-generate-001": {
34277
+ "vercel": "google/imagen-4.0-generate-001"
34278
+ },
34279
+ "imagen-4.0-ultra-generate-001": {
34280
+ "vercel": "google/imagen-4.0-ultra-generate-001"
34147
34281
  },
34148
34282
  "interfaze-beta": {
34149
34283
  "vercel": "interfaze/interfaze-beta"
@@ -34161,49 +34295,96 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34161
34295
  "vercel": "moonshotai/kimi-k2-thinking"
34162
34296
  },
34163
34297
  "kimi-k2-5": {
34298
+ "togetherai": "togetherai/moonshotai/Kimi-K2.5",
34164
34299
  "vercel": "moonshotai/kimi-k2.5"
34165
34300
  },
34166
34301
  "kimi-k2-6": {
34302
+ "togetherai": "togetherai/moonshotai/Kimi-K2.6",
34167
34303
  "vercel": "moonshotai/kimi-k2.6"
34168
34304
  },
34305
+ "kimi-k2-7-code": {
34306
+ "vercel": "moonshotai/kimi-k2.7-code"
34307
+ },
34169
34308
  "kimi-k2-thinking": {
34170
34309
  "vercel": "moonshotai/kimi-k2-thinking"
34171
34310
  },
34172
- "kimi-k2-thinking-turbo": {
34173
- "vercel": "moonshotai/kimi-k2-thinking-turbo"
34174
- },
34175
- "kimi-k2-turbo": {
34176
- "vercel": "moonshotai/kimi-k2-turbo"
34177
- },
34178
34311
  "kimi-k2.5": {
34179
34312
  "vercel": "moonshotai/kimi-k2.5"
34180
34313
  },
34181
34314
  "kimi-k2.6": {
34182
34315
  "vercel": "moonshotai/kimi-k2.6"
34183
34316
  },
34184
- "llama-3-1-70b": {
34185
- "vercel": "meta/llama-3-1-70b"
34317
+ "kimi-k2.7-code": {
34318
+ "vercel": "moonshotai/kimi-k2.7-code"
34319
+ },
34320
+ "kling-v2-5-turbo-i2v": {
34321
+ "vercel": "klingai/kling-v2.5-turbo-i2v"
34322
+ },
34323
+ "kling-v2-5-turbo-t2v": {
34324
+ "vercel": "klingai/kling-v2.5-turbo-t2v"
34325
+ },
34326
+ "kling-v2-6-i2v": {
34327
+ "vercel": "klingai/kling-v2.6-i2v"
34328
+ },
34329
+ "kling-v2-6-motion-control": {
34330
+ "vercel": "klingai/kling-v2.6-motion-control"
34331
+ },
34332
+ "kling-v2-6-t2v": {
34333
+ "vercel": "klingai/kling-v2.6-t2v"
34334
+ },
34335
+ "kling-v2.5-turbo-i2v": {
34336
+ "vercel": "klingai/kling-v2.5-turbo-i2v"
34337
+ },
34338
+ "kling-v2.5-turbo-t2v": {
34339
+ "vercel": "klingai/kling-v2.5-turbo-t2v"
34340
+ },
34341
+ "kling-v2.6-i2v": {
34342
+ "vercel": "klingai/kling-v2.6-i2v"
34343
+ },
34344
+ "kling-v2.6-motion-control": {
34345
+ "vercel": "klingai/kling-v2.6-motion-control"
34346
+ },
34347
+ "kling-v2.6-t2v": {
34348
+ "vercel": "klingai/kling-v2.6-t2v"
34349
+ },
34350
+ "kling-v3-0-i2v": {
34351
+ "vercel": "klingai/kling-v3.0-i2v"
34352
+ },
34353
+ "kling-v3-0-motion-control": {
34354
+ "vercel": "klingai/kling-v3.0-motion-control"
34355
+ },
34356
+ "kling-v3-0-t2v": {
34357
+ "vercel": "klingai/kling-v3.0-t2v"
34358
+ },
34359
+ "kling-v3.0-i2v": {
34360
+ "vercel": "klingai/kling-v3.0-i2v"
34361
+ },
34362
+ "kling-v3.0-motion-control": {
34363
+ "vercel": "klingai/kling-v3.0-motion-control"
34364
+ },
34365
+ "kling-v3.0-t2v": {
34366
+ "vercel": "klingai/kling-v3.0-t2v"
34367
+ },
34368
+ "lfm2-24b-a2b": {
34369
+ "togetherai": "togetherai/LiquidAI/LFM2-24B-A2B"
34186
34370
  },
34187
- "llama-3-1-8b": {
34188
- "vercel": "meta/llama-3-1-8b"
34371
+ "LiquidAI/LFM2-24B-A2B": {
34372
+ "togetherai": "togetherai/LiquidAI/LFM2-24B-A2B"
34189
34373
  },
34190
34374
  "llama-3-2-11b": {
34191
- "vercel": "meta/llama-3-2-11b"
34375
+ "vercel": "meta/llama-3.2-11b"
34192
34376
  },
34193
34377
  "llama-3-2-1b": {
34194
- "vercel": "meta/llama-3-2-1b"
34378
+ "vercel": "meta/llama-3.2-1b"
34195
34379
  },
34196
34380
  "llama-3-2-3b": {
34197
- "vercel": "meta/llama-3-2-3b"
34381
+ "vercel": "meta/llama-3.2-3b"
34198
34382
  },
34199
34383
  "llama-3-2-90b": {
34200
- "vercel": "meta/llama-3-2-90b"
34201
- },
34202
- "llama-3-3-70b": {
34203
- "vercel": "meta/llama-3-3-70b"
34384
+ "vercel": "meta/llama-3.2-90b"
34204
34385
  },
34205
34386
  "llama-3-3-70b-instruct-turbo": {
34206
- "togetherai": "meta-llama/Llama-3.3-70B-Instruct-Turbo"
34387
+ "togetherai": "togetherai/meta-llama/Llama-3.3-70B-Instruct-Turbo"
34207
34388
  },
34208
34389
  "llama-3.1-70b": {
34209
34390
  "vercel": "meta/llama-3.1-70b"
@@ -34226,17 +34407,14 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34226
34407
  "llama-3.3-70b": {
34227
34408
  "vercel": "meta/llama-3.3-70b"
34228
34409
  },
34229
- "Llama-3.3-70B-Instruct-Turbo": {
34230
- "togetherai": "meta-llama/Llama-3.3-70B-Instruct-Turbo"
34231
- },
34232
34410
  "llama3-1-70b": {
34233
- "vercel": "meta/llama-3-1-70b"
34411
+ "vercel": "meta/llama-3.1-70b"
34234
34412
  },
34235
34413
  "llama3-1-8b": {
34236
- "vercel": "meta/llama-3-1-8b"
34414
+ "vercel": "meta/llama-3.1-8b"
34237
34415
  },
34238
34416
  "llama3-3-70b": {
34239
- "vercel": "meta/llama-3-3-70b"
34417
+ "vercel": "meta/llama-3.3-70b"
34240
34418
  },
34241
34419
  "longcat-flash-chat": {
34242
34420
  "vercel": "meituan/longcat-flash-chat"
@@ -34256,29 +34434,8 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34256
34434
  "mercury-coder-small": {
34257
34435
  "vercel": "inception/mercury-coder-small"
34258
34436
  },
34259
- "meta-llama-3-1-405b-instruct-turbo": {
34260
- "togetherai": "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo"
34261
- },
34262
- "meta-llama-3-1-70b-instruct-turbo": {
34263
- "togetherai": "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo"
34264
- },
34265
- "meta-llama-3-1-8b-instruct-turbo": {
34266
- "togetherai": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"
34267
- },
34268
- "meta-llama-3-3-70b-instruct-turbo": {
34269
- "togetherai": "meta-llama/Meta-Llama-3.3-70B-Instruct-Turbo"
34270
- },
34271
- "Meta-Llama-3.1-405B-Instruct-Turbo": {
34272
- "togetherai": "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo"
34273
- },
34274
- "Meta-Llama-3.1-70B-Instruct-Turbo": {
34275
- "togetherai": "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo"
34276
- },
34277
- "Meta-Llama-3.1-8B-Instruct-Turbo": {
34278
- "togetherai": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"
34279
- },
34280
- "Meta-Llama-3.3-70B-Instruct-Turbo": {
34281
- "togetherai": "meta-llama/Meta-Llama-3.3-70B-Instruct-Turbo"
34437
+ "meta-llama/Llama-3.3-70B-Instruct-Turbo": {
34438
+ "togetherai": "togetherai/meta-llama/Llama-3.3-70B-Instruct-Turbo"
34282
34439
  },
34283
34440
  "mimo-v2-5": {
34284
34441
  "vercel": "xiaomi/mimo-v2.5"
@@ -34308,6 +34465,7 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34308
34465
  "vercel": "minimax/minimax-m2.1-lightning"
34309
34466
  },
34310
34467
  "minimax-m2-5": {
34468
+ "togetherai": "togetherai/MiniMaxAI/MiniMax-M2.5",
34311
34469
  "vercel": "minimax/minimax-m2.5"
34312
34470
  },
34313
34471
  "minimax-m2-5-highspeed": {
@@ -34315,6 +34473,7 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34315
34473
  },
34316
34474
  "minimax-m2-7": {
34317
34475
  "general-compute": "general-compute/minimax-m2.7",
34476
+ "togetherai": "togetherai/MiniMaxAI/MiniMax-M2.7",
34318
34477
  "vercel": "minimax/minimax-m2.7"
34319
34478
  },
34320
34479
  "minimax-m2-7-highspeed": {
@@ -34342,6 +34501,12 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34342
34501
  "minimax-m3": {
34343
34502
  "vercel": "minimax/minimax-m3"
34344
34503
  },
34504
+ "MiniMaxAI/MiniMax-M2.5": {
34505
+ "togetherai": "togetherai/MiniMaxAI/MiniMax-M2.5"
34506
+ },
34507
+ "MiniMaxAI/MiniMax-M2.7": {
34508
+ "togetherai": "togetherai/MiniMaxAI/MiniMax-M2.7"
34509
+ },
34345
34510
  "ministral-14b": {
34346
34511
  "vercel": "mistral/ministral-14b"
34347
34512
  },
@@ -34351,9 +34516,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34351
34516
  "ministral-8b": {
34352
34517
  "vercel": "mistral/ministral-8b"
34353
34518
  },
34354
- "mistral-large": {
34355
- "vercel": "mistral/mistral-large"
34356
- },
34357
34519
  "mistral-large-3": {
34358
34520
  "vercel": "mistral/mistral-large-3"
34359
34521
  },
@@ -34363,12 +34525,15 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34363
34525
  "mistral-medium-3.5": {
34364
34526
  "vercel": "mistral/mistral-medium-3.5"
34365
34527
  },
34366
- "mistral-saba-24b": {
34367
- "vercel": "mistral/mistral-saba-24b"
34368
- },
34369
34528
  "mistral-small": {
34370
34529
  "vercel": "mistral/mistral-small"
34371
34530
  },
34531
+ "moonshotai/Kimi-K2.5": {
34532
+ "togetherai": "togetherai/moonshotai/Kimi-K2.5"
34533
+ },
34534
+ "moonshotai/Kimi-K2.6": {
34535
+ "togetherai": "togetherai/moonshotai/Kimi-K2.6"
34536
+ },
34372
34537
  "morph-v3-fast": {
34373
34538
  "vercel": "morph/morph-v3-fast"
34374
34539
  },
@@ -34382,6 +34547,7 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34382
34547
  "vercel": "nvidia/nemotron-3-super-120b-a12b"
34383
34548
  },
34384
34549
  "nemotron-3-ultra-550b-a55b": {
34550
+ "togetherai": "togetherai/nvidia/nemotron-3-ultra-550b-a55b",
34385
34551
  "vercel": "nvidia/nemotron-3-ultra-550b-a55b"
34386
34552
  },
34387
34553
  "nemotron-nano-12b-v2-vl": {
@@ -34405,26 +34571,36 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34405
34571
  "nova-pro": {
34406
34572
  "vercel": "amazon/nova-pro"
34407
34573
  },
34574
+ "nvidia/nemotron-3-ultra-550b-a55b": {
34575
+ "togetherai": "togetherai/nvidia/nemotron-3-ultra-550b-a55b"
34576
+ },
34408
34577
  "o3": {
34578
+ "openai": "o3",
34409
34579
  "vercel": "openai/o3"
34410
34580
  },
34411
34581
  "o3-deep-research": {
34582
+ "openai": "o3-deep-research",
34412
34583
  "vercel": "openai/o3-deep-research"
34413
34584
  },
34414
34585
  "o3-pro": {
34586
+ "openai": "o3-pro",
34415
34587
  "vercel": "openai/o3-pro"
34416
34588
  },
34417
- "o3-pro-batch": {
34418
- "openai": "o3-pro-batch"
34419
- },
34420
34589
  "o4-mini": {
34590
+ "openai": "o4-mini",
34421
34591
  "vercel": "openai/o4-mini"
34422
34592
  },
34423
- "o4-mini-batch": {
34424
- "openai": "o4-mini-batch"
34593
+ "o4-mini-deep-research": {
34594
+ "openai": "o4-mini-deep-research"
34425
34595
  },
34426
- "openai/gpt-4o-mini-search-preview": {
34427
- "openai": "openai/openai/gpt-4o-mini-search-preview"
34596
+ "openai/gpt-oss-120b": {
34597
+ "togetherai": "togetherai/openai/gpt-oss-120b"
34598
+ },
34599
+ "openai/gpt-oss-20b": {
34600
+ "togetherai": "togetherai/openai/gpt-oss-20b"
34601
+ },
34602
+ "pearl-ai/gemma-4-31b-it": {
34603
+ "togetherai": "togetherai/pearl-ai/gemma-4-31b-it"
34428
34604
  },
34429
34605
  "pixtral-12b": {
34430
34606
  "vercel": "mistral/pixtral-12b"
@@ -34450,26 +34626,55 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34450
34626
  "qwen-3.6-max-preview": {
34451
34627
  "vercel": "alibaba/qwen-3.6-max-preview"
34452
34628
  },
34629
+ "Qwen/Qwen3-235B-A22B-Instruct-2507-tput": {
34630
+ "togetherai": "togetherai/Qwen/Qwen3-235B-A22B-Instruct-2507-tput"
34631
+ },
34632
+ "Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8": {
34633
+ "togetherai": "togetherai/Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8"
34634
+ },
34635
+ "Qwen/Qwen3-Coder-Next-FP8": {
34636
+ "togetherai": "togetherai/Qwen/Qwen3-Coder-Next-FP8"
34637
+ },
34638
+ "Qwen/Qwen3.5-397B-A17B": {
34639
+ "togetherai": "togetherai/Qwen/Qwen3.5-397B-A17B"
34640
+ },
34641
+ "Qwen/Qwen3.5-9B": {
34642
+ "togetherai": "togetherai/Qwen/Qwen3.5-9B"
34643
+ },
34644
+ "Qwen/Qwen3.6-Plus": {
34645
+ "togetherai": "togetherai/Qwen/Qwen3.6-Plus"
34646
+ },
34647
+ "Qwen/Qwen3.7-Max": {
34648
+ "togetherai": "togetherai/Qwen/Qwen3.7-Max"
34649
+ },
34453
34650
  "qwen3-235b-a22b": {
34454
34651
  "vercel": "alibaba/qwen3-235b-a22b-thinking"
34455
34652
  },
34653
+ "qwen3-235b-a22b-instruct-2507-tput": {
34654
+ "togetherai": "togetherai/Qwen/Qwen3-235B-A22B-Instruct-2507-tput"
34655
+ },
34456
34656
  "qwen3-235b-a22b-thinking": {
34457
34657
  "vercel": "alibaba/qwen3-235b-a22b-thinking"
34458
34658
  },
34459
34659
  "qwen3-32b": {
34460
34660
  "vercel": "alibaba/qwen-3-32b"
34461
34661
  },
34662
+ "qwen3-5-122b-a10b": {
34663
+ "mixlayer": "qwen/qwen3.5-122b-a10b"
34664
+ },
34462
34665
  "qwen3-5-35b-a3b": {
34463
34666
  "mixlayer": "qwen/qwen3.5-35b-a3b"
34464
34667
  },
34465
34668
  "qwen3-5-397b-a17b": {
34466
- "mixlayer": "qwen/qwen3.5-397b-a17b"
34669
+ "mixlayer": "qwen/qwen3.5-397b-a17b",
34670
+ "togetherai": "togetherai/Qwen/Qwen3.5-397B-A17B"
34467
34671
  },
34468
34672
  "qwen3-5-4b-free": {
34469
34673
  "mixlayer": "qwen/qwen3.5-4b-free"
34470
34674
  },
34471
34675
  "qwen3-5-9b": {
34472
- "mixlayer": "qwen/qwen3.5-9b"
34676
+ "mixlayer": "qwen/qwen3.5-9b",
34677
+ "togetherai": "togetherai/Qwen/Qwen3.5-9B"
34473
34678
  },
34474
34679
  "qwen3-5-flash": {
34475
34680
  "vercel": "alibaba/qwen3.5-flash"
@@ -34485,9 +34690,11 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34485
34690
  "mixlayer": "qwen/qwen3.6-35b-a3b"
34486
34691
  },
34487
34692
  "qwen3-6-plus": {
34693
+ "togetherai": "togetherai/Qwen/Qwen3.6-Plus",
34488
34694
  "vercel": "alibaba/qwen3.6-plus"
34489
34695
  },
34490
34696
  "qwen3-7-max": {
34697
+ "togetherai": "togetherai/Qwen/Qwen3.7-Max",
34491
34698
  "vercel": "alibaba/qwen3.7-max"
34492
34699
  },
34493
34700
  "qwen3-7-plus": {
@@ -34499,9 +34706,15 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34499
34706
  "qwen3-coder-30b-a3b": {
34500
34707
  "vercel": "alibaba/qwen3-coder-30b-a3b"
34501
34708
  },
34709
+ "qwen3-coder-480b-a35b-instruct-fp8": {
34710
+ "togetherai": "togetherai/Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8"
34711
+ },
34502
34712
  "qwen3-coder-next": {
34503
34713
  "vercel": "alibaba/qwen3-coder-next"
34504
34714
  },
34715
+ "qwen3-coder-next-fp8": {
34716
+ "togetherai": "togetherai/Qwen/Qwen3-Coder-Next-FP8"
34717
+ },
34505
34718
  "qwen3-coder-plus": {
34506
34719
  "vercel": "alibaba/qwen3-coder-plus"
34507
34720
  },
@@ -34547,6 +34760,9 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34547
34760
  "qwen3-vl-thinking": {
34548
34761
  "vercel": "alibaba/qwen3-vl-thinking"
34549
34762
  },
34763
+ "qwen3.5-122b-a10b": {
34764
+ "mixlayer": "qwen/qwen3.5-122b-a10b"
34765
+ },
34550
34766
  "qwen3.5-35b-a3b": {
34551
34767
  "mixlayer": "qwen/qwen3.5-35b-a3b"
34552
34768
  },
@@ -34581,6 +34797,72 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34581
34797
  "qwen3.7-plus": {
34582
34798
  "vercel": "alibaba/qwen3.7-plus"
34583
34799
  },
34800
+ "recraft": {
34801
+ "vercel": "recraft/recraft-v4"
34802
+ },
34803
+ "recraft-v2": {
34804
+ "vercel": "recraft/recraft-v2"
34805
+ },
34806
+ "recraft-v3": {
34807
+ "vercel": "recraft/recraft-v3"
34808
+ },
34809
+ "recraft-v4": {
34810
+ "vercel": "recraft/recraft-v4"
34811
+ },
34812
+ "recraft-v4-1": {
34813
+ "vercel": "recraft/recraft-v4.1"
34814
+ },
34815
+ "recraft-v4-1-pro": {
34816
+ "vercel": "recraft/recraft-v4.1-pro"
34817
+ },
34818
+ "recraft-v4-1-utility": {
34819
+ "vercel": "recraft/recraft-v4.1-utility"
34820
+ },
34821
+ "recraft-v4-1-utility-pro": {
34822
+ "vercel": "recraft/recraft-v4.1-utility-pro"
34823
+ },
34824
+ "recraft-v4-pro": {
34825
+ "vercel": "recraft/recraft-v4-pro"
34826
+ },
34827
+ "recraft-v4.1": {
34828
+ "vercel": "recraft/recraft-v4.1"
34829
+ },
34830
+ "recraft-v4.1-pro": {
34831
+ "vercel": "recraft/recraft-v4.1-pro"
34832
+ },
34833
+ "recraft-v4.1-utility": {
34834
+ "vercel": "recraft/recraft-v4.1-utility"
34835
+ },
34836
+ "recraft-v4.1-utility-pro": {
34837
+ "vercel": "recraft/recraft-v4.1-utility-pro"
34838
+ },
34839
+ "rerank-2-5": {
34840
+ "vercel": "voyage/rerank-2.5"
34841
+ },
34842
+ "rerank-2-5-lite": {
34843
+ "vercel": "voyage/rerank-2.5-lite"
34844
+ },
34845
+ "rerank-2.5": {
34846
+ "vercel": "voyage/rerank-2.5"
34847
+ },
34848
+ "rerank-2.5-lite": {
34849
+ "vercel": "voyage/rerank-2.5-lite"
34850
+ },
34851
+ "rerank-v3-5": {
34852
+ "vercel": "cohere/rerank-v3.5"
34853
+ },
34854
+ "rerank-v3.5": {
34855
+ "vercel": "cohere/rerank-v3.5"
34856
+ },
34857
+ "rerank-v4-fast": {
34858
+ "vercel": "cohere/rerank-v4-fast"
34859
+ },
34860
+ "rerank-v4-pro": {
34861
+ "vercel": "cohere/rerank-v4-pro"
34862
+ },
34863
+ "rnj-1-instruct": {
34864
+ "togetherai": "togetherai/essentialai/Rnj-1-Instruct"
34865
+ },
34584
34866
  "seed-1-6": {
34585
34867
  "vercel": "bytedance/seed-1.6"
34586
34868
  },
@@ -34593,15 +34875,72 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34593
34875
  "seed-1.8": {
34594
34876
  "vercel": "bytedance/seed-1.8"
34595
34877
  },
34878
+ "seedance-2-0": {
34879
+ "vercel": "bytedance/seedance-2.0"
34880
+ },
34881
+ "seedance-2-0-fast": {
34882
+ "vercel": "bytedance/seedance-2.0-fast"
34883
+ },
34884
+ "seedance-2.0": {
34885
+ "vercel": "bytedance/seedance-2.0"
34886
+ },
34887
+ "seedance-2.0-fast": {
34888
+ "vercel": "bytedance/seedance-2.0-fast"
34889
+ },
34890
+ "seedance-v1-0-lite-i2v": {
34891
+ "vercel": "bytedance/seedance-v1.0-lite-i2v"
34892
+ },
34893
+ "seedance-v1-0-lite-t2v": {
34894
+ "vercel": "bytedance/seedance-v1.0-lite-t2v"
34895
+ },
34896
+ "seedance-v1-0-pro": {
34897
+ "vercel": "bytedance/seedance-v1.0-pro"
34898
+ },
34899
+ "seedance-v1-0-pro-fast": {
34900
+ "vercel": "bytedance/seedance-v1.0-pro-fast"
34901
+ },
34902
+ "seedance-v1-5-pro": {
34903
+ "vercel": "bytedance/seedance-v1.5-pro"
34904
+ },
34905
+ "seedance-v1.0-lite-i2v": {
34906
+ "vercel": "bytedance/seedance-v1.0-lite-i2v"
34907
+ },
34908
+ "seedance-v1.0-lite-t2v": {
34909
+ "vercel": "bytedance/seedance-v1.0-lite-t2v"
34910
+ },
34911
+ "seedance-v1.0-pro": {
34912
+ "vercel": "bytedance/seedance-v1.0-pro"
34913
+ },
34914
+ "seedance-v1.0-pro-fast": {
34915
+ "vercel": "bytedance/seedance-v1.0-pro-fast"
34916
+ },
34917
+ "seedance-v1.5-pro": {
34918
+ "vercel": "bytedance/seedance-v1.5-pro"
34919
+ },
34920
+ "seedream-4-0": {
34921
+ "vercel": "bytedance/seedream-4.0"
34922
+ },
34923
+ "seedream-4-5": {
34924
+ "vercel": "bytedance/seedream-4.5"
34925
+ },
34926
+ "seedream-4.0": {
34927
+ "vercel": "bytedance/seedream-4.0"
34928
+ },
34929
+ "seedream-4.5": {
34930
+ "vercel": "bytedance/seedream-4.5"
34931
+ },
34932
+ "seedream-5-0-lite": {
34933
+ "vercel": "bytedance/seedream-5.0-lite"
34934
+ },
34935
+ "seedream-5.0-lite": {
34936
+ "vercel": "bytedance/seedream-5.0-lite"
34937
+ },
34596
34938
  "sonar": {
34597
34939
  "vercel": "perplexity/sonar"
34598
34940
  },
34599
34941
  "sonar-pro": {
34600
34942
  "vercel": "perplexity/sonar-pro"
34601
34943
  },
34602
- "sonar-reasoning": {
34603
- "vercel": "perplexity/sonar-reasoning"
34604
- },
34605
34944
  "sonar-reasoning-pro": {
34606
34945
  "vercel": "perplexity/sonar-reasoning-pro"
34607
34946
  },
@@ -34624,35 +34963,14 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34624
34963
  "openai": "text-embedding-3-large",
34625
34964
  "vercel": "openai/text-embedding-3-large"
34626
34965
  },
34627
- "text-embedding-3-large-batch": {
34628
- "openai": "text-embedding-3-large-batch"
34629
- },
34630
34966
  "text-embedding-3-small": {
34631
34967
  "openai": "text-embedding-3-small",
34632
34968
  "vercel": "openai/text-embedding-3-small"
34633
34969
  },
34634
- "text-embedding-3-small-batch": {
34635
- "openai": "text-embedding-3-small-batch"
34636
- },
34637
- "text-embedding-ada": {
34638
- "openai": "text-embedding-ada"
34639
- },
34640
34970
  "text-embedding-ada-002": {
34641
- "openai": "text-embedding-ada-002-v2",
34971
+ "openai": "text-embedding-ada-002",
34642
34972
  "vercel": "openai/text-embedding-ada-002"
34643
34973
  },
34644
- "text-embedding-ada-002-batch": {
34645
- "openai": "text-embedding-ada-002-batch"
34646
- },
34647
- "text-embedding-ada-002-v2": {
34648
- "openai": "text-embedding-ada-002-v2"
34649
- },
34650
- "text-embedding-ada-002-v2-batch": {
34651
- "openai": "text-embedding-ada-002-v2-batch"
34652
- },
34653
- "text-embedding-ada-batch": {
34654
- "openai": "text-embedding-ada-batch"
34655
- },
34656
34974
  "text-multilingual-embedding-002": {
34657
34975
  "vercel": "google/text-multilingual-embedding-002"
34658
34976
  },
@@ -34674,17 +34992,29 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34674
34992
  "trinity-mini": {
34675
34993
  "vercel": "arcee-ai/trinity-mini"
34676
34994
  },
34677
- "v0-1-0-md": {
34678
- "vercel": "v0-1.0-md"
34995
+ "veo-3-0-fast-generate-001": {
34996
+ "vercel": "google/veo-3.0-fast-generate-001"
34679
34997
  },
34680
- "v0-1-5-md": {
34681
- "vercel": "v0-1.5-md"
34998
+ "veo-3-0-generate-001": {
34999
+ "vercel": "google/veo-3.0-generate-001"
34682
35000
  },
34683
- "v0-1.0-md": {
34684
- "vercel": "v0-1.0-md"
35001
+ "veo-3-1-fast-generate-001": {
35002
+ "vercel": "google/veo-3.1-fast-generate-001"
34685
35003
  },
34686
- "v0-1.5-md": {
34687
- "vercel": "v0-1.5-md"
35004
+ "veo-3-1-generate-001": {
35005
+ "vercel": "google/veo-3.1-generate-001"
35006
+ },
35007
+ "veo-3.0-fast-generate-001": {
35008
+ "vercel": "google/veo-3.0-fast-generate-001"
35009
+ },
35010
+ "veo-3.0-generate-001": {
35011
+ "vercel": "google/veo-3.0-generate-001"
35012
+ },
35013
+ "veo-3.1-fast-generate-001": {
35014
+ "vercel": "google/veo-3.1-fast-generate-001"
35015
+ },
35016
+ "veo-3.1-generate-001": {
35017
+ "vercel": "google/veo-3.1-generate-001"
34688
35018
  },
34689
35019
  "voyage-3-5": {
34690
35020
  "vercel": "voyage/voyage-3.5"
@@ -34721,6 +35051,48 @@ var MODEL_FAMILY_PROVIDER_IDS = {
34721
35051
  },
34722
35052
  "voyage-law-2": {
34723
35053
  "vercel": "voyage/voyage-law-2"
35054
+ },
35055
+ "wan-v2-5-t2v": {
35056
+ "vercel": "alibaba/wan-v2.5-t2v-preview"
35057
+ },
35058
+ "wan-v2-6-i2v": {
35059
+ "vercel": "alibaba/wan-v2.6-i2v"
35060
+ },
35061
+ "wan-v2-6-i2v-flash": {
35062
+ "vercel": "alibaba/wan-v2.6-i2v-flash"
35063
+ },
35064
+ "wan-v2-6-r2v": {
35065
+ "vercel": "alibaba/wan-v2.6-r2v"
35066
+ },
35067
+ "wan-v2-6-r2v-flash": {
35068
+ "vercel": "alibaba/wan-v2.6-r2v-flash"
35069
+ },
35070
+ "wan-v2-6-t2v": {
35071
+ "vercel": "alibaba/wan-v2.6-t2v"
35072
+ },
35073
+ "wan-v2.5-t2v-preview": {
35074
+ "vercel": "alibaba/wan-v2.5-t2v-preview"
35075
+ },
35076
+ "wan-v2.6-i2v": {
35077
+ "vercel": "alibaba/wan-v2.6-i2v"
35078
+ },
35079
+ "wan-v2.6-i2v-flash": {
35080
+ "vercel": "alibaba/wan-v2.6-i2v-flash"
35081
+ },
35082
+ "wan-v2.6-r2v": {
35083
+ "vercel": "alibaba/wan-v2.6-r2v"
35084
+ },
35085
+ "wan-v2.6-r2v-flash": {
35086
+ "vercel": "alibaba/wan-v2.6-r2v-flash"
35087
+ },
35088
+ "wan-v2.6-t2v": {
35089
+ "vercel": "alibaba/wan-v2.6-t2v"
35090
+ },
35091
+ "zai-org/GLM-5": {
35092
+ "togetherai": "togetherai/zai-org/GLM-5"
35093
+ },
35094
+ "zai-org/GLM-5.1": {
35095
+ "togetherai": "togetherai/zai-org/GLM-5.1"
34724
35096
  }
34725
35097
  };
34726
35098
  var PLATFORM_KEY_PROVIDER_MAP = {
@@ -34751,12 +35123,13 @@ var MANUAL_PROVIDER_MAP_OVERRIDES = {
34751
35123
  "claude-sonnet-4-5": {
34752
35124
  "bedrock": "anthropic.claude-3-5-sonnet-20241022-v2:0"
34753
35125
  },
34754
- // xAI uses x/ prefix internally
35126
+ // Legacy xAI aliases route to the current successor model IDs.
34755
35127
  "grok-4": {
34756
- "xai": "x/grok-4"
35128
+ "vercel": "xai/grok-4.3",
35129
+ "xai": "grok-4.3"
34757
35130
  },
34758
35131
  "grok-4-fast": {
34759
- "xai": "x/grok-4-fast"
35132
+ "vercel": "xai/grok-4.1-fast-non-reasoning"
34760
35133
  },
34761
35134
  // TogetherAI uses their own model ID format
34762
35135
  "llama-3-3-70b": {
@@ -34775,6 +35148,9 @@ var MANUAL_PROVIDER_MAP_OVERRIDES = {
34775
35148
  "kimi-k2.6": {
34776
35149
  "workers-ai": "@cf/moonshotai/kimi-k2.6"
34777
35150
  },
35151
+ "kimi-k2.7-code": {
35152
+ "workers-ai": "@cf/moonshotai/kimi-k2.7-code"
35153
+ },
34778
35154
  "nemotron-3-120b-a12b": {
34779
35155
  "workers-ai": "@cf/nvidia/nemotron-3-120b-a12b"
34780
35156
  },
@@ -36115,7 +36491,8 @@ var surfaceSchema = external_exports.object({
36115
36491
  "messaging",
36116
36492
  "telegram",
36117
36493
  "a2a",
36118
- "hosted-page"
36494
+ "hosted-page",
36495
+ "chrome_extension"
36119
36496
  ]),
36120
36497
  config: external_exports.record(external_exports.string(), external_exports.any()),
36121
36498
  createPolicy: createPolicySchema,
@@ -36258,8 +36635,8 @@ var FLAT_ADVANCED_CONFIG_KEYS = {
36258
36635
  var FLAT_ADVANCED_CONFIG_KEY_LIST = Object.keys(
36259
36636
  FLAT_ADVANCED_CONFIG_KEYS
36260
36637
  );
36261
- function createIssue(severity, code, message, path17, suggestedFix) {
36262
- return { code, message, path: path17, severity, ...suggestedFix ? { suggestedFix } : {} };
36638
+ function createIssue(severity, code, message, path18, suggestedFix) {
36639
+ return { code, message, path: path18, severity, ...suggestedFix ? { suggestedFix } : {} };
36263
36640
  }
36264
36641
  function emptyResult() {
36265
36642
  return { valid: true, errors: [], warnings: [], recommendations: [] };
@@ -36965,16 +37342,16 @@ var fullProductObjectTemplateSchema = external_exports.object({
36965
37342
  });
36966
37343
  var FLOW_PREFIX = "flow:";
36967
37344
  var SECRET_PREFIX = "secret:";
36968
- function collectStringLeafPaths(value, path17 = []) {
37345
+ function collectStringLeafPaths(value, path18 = []) {
36969
37346
  if (typeof value === "string") {
36970
- return [{ path: path17, value }];
37347
+ return [{ path: path18, value }];
36971
37348
  }
36972
37349
  if (Array.isArray(value)) {
36973
- return value.flatMap((item, index) => collectStringLeafPaths(item, [...path17, String(index)]));
37350
+ return value.flatMap((item, index) => collectStringLeafPaths(item, [...path18, String(index)]));
36974
37351
  }
36975
37352
  if (value && typeof value === "object") {
36976
37353
  return Object.entries(value).flatMap(
36977
- ([key, nestedValue]) => collectStringLeafPaths(nestedValue, [...path17, key])
37354
+ ([key, nestedValue]) => collectStringLeafPaths(nestedValue, [...path18, key])
36978
37355
  );
36979
37356
  }
36980
37357
  return [];
@@ -37579,7 +37956,8 @@ var PLATFORM_CATALOG = {
37579
37956
  "whatsapp",
37580
37957
  "messaging",
37581
37958
  "telegram",
37582
- "a2a"
37959
+ "a2a",
37960
+ "chrome_extension"
37583
37961
  ],
37584
37962
  availableFlowPrimitives: FLOW_STEP_TYPES.map((stepType) => {
37585
37963
  const meta3 = FLOW_STEP_TYPE_METADATA[stepType];
@@ -37969,6 +38347,37 @@ var SURFACE_TYPE_METADATA = {
37969
38347
  maxResponseLength: null,
37970
38348
  executionHint: null
37971
38349
  }
38350
+ },
38351
+ // @snake-case-ok: surface type identifier
38352
+ chrome_extension: {
38353
+ description: "Downloadable Manifest V3 Chrome extension embedding the agent in the browser side panel, with packaged browser tools (read page, fill forms, navigate tabs) executed locally via the WebMCP client-tool loop.",
38354
+ useCases: [
38355
+ "browser copilots",
38356
+ "page-aware assistants",
38357
+ "form filling and data extraction",
38358
+ "internal browser tooling"
38359
+ ],
38360
+ examples: [
38361
+ "CRM sidekick that reads and updates records on the page",
38362
+ "Research assistant that summarizes and compares open tabs",
38363
+ "Support agent that drafts replies inside a ticketing UI"
38364
+ ],
38365
+ traits: {
38366
+ streaming: "required",
38367
+ messagesMutable: false,
38368
+ deliveryModel: "real_time",
38369
+ mediaSupport: "images",
38370
+ interactiveUI: "generative",
38371
+ inboundMediaSupport: true,
38372
+ consumerType: "human",
38373
+ reasoningVisibility: "pass_through",
38374
+ markdownDialect: "mdx",
38375
+ threadModel: "flat",
38376
+ senderIdentity: "anonymous",
38377
+ maxResponseLength: null,
38378
+ executionHint: "You are running inside a Chrome extension side panel. You may have browser tools (chrome:*) to read the current page, interact with forms, and manage tabs \u2014 use them when the user asks about or wants to act on the page they are viewing. Mutating actions (clicking, filling, navigating) ask the user for confirmation before running."
38379
+ },
38380
+ behaviorTypeRef: "runtype://types/surface-configs"
37972
38381
  }
37973
38382
  };
37974
38383
  var SURFACE_TYPE_GUIDE = (() => {
@@ -38773,7 +39182,7 @@ function buildDashboardUrl(opts) {
38773
39182
  while (base.endsWith("/")) {
38774
39183
  base = base.slice(0, -1);
38775
39184
  }
38776
- const path17 = opts.path.startsWith("/") ? opts.path : `/${opts.path}`;
39185
+ const path18 = opts.path.startsWith("/") ? opts.path : `/${opts.path}`;
38777
39186
  const params = new URLSearchParams();
38778
39187
  if (isValidAccountId(opts.account)) {
38779
39188
  params.set(ACCOUNT_QUERY_PARAM, opts.account);
@@ -38786,7 +39195,7 @@ function buildDashboardUrl(opts) {
38786
39195
  }
38787
39196
  }
38788
39197
  const qs = params.toString();
38789
- return qs ? `${base}${path17}?${qs}` : `${base}${path17}`;
39198
+ return qs ? `${base}${path18}?${qs}` : `${base}${path18}`;
38790
39199
  }
38791
39200
  function parseAccountId(value) {
38792
39201
  if (!value) return null;
@@ -40018,13 +40427,13 @@ function parseJsonObject(raw, label) {
40018
40427
  }
40019
40428
  return parsed;
40020
40429
  }
40021
- function readJsonFile(path17, opts = {}) {
40430
+ function readJsonFile(path18, opts = {}) {
40022
40431
  const label = opts.label ?? "file";
40023
40432
  let raw;
40024
40433
  try {
40025
- raw = readFileSync3(path17, "utf-8");
40434
+ raw = readFileSync3(path18, "utf-8");
40026
40435
  } catch {
40027
- console.error(chalk2.red(`Failed to read ${label}: ${path17}`));
40436
+ console.error(chalk2.red(`Failed to read ${label}: ${path18}`));
40028
40437
  process.exit(1);
40029
40438
  }
40030
40439
  const obj = parseJsonObject(raw, label);
@@ -40068,14 +40477,14 @@ async function promptConfirm(message, options) {
40068
40477
  output: process.stdout,
40069
40478
  terminal: true
40070
40479
  });
40071
- return new Promise((resolve10) => {
40480
+ return new Promise((resolve11) => {
40072
40481
  rl.question(chalk3.cyan(`${message} (${hint}): `), (answer) => {
40073
40482
  rl.close();
40074
40483
  const trimmed = answer.trim().toLowerCase();
40075
40484
  if (trimmed === "") {
40076
- resolve10(defaultYes);
40485
+ resolve11(defaultYes);
40077
40486
  } else {
40078
- resolve10(trimmed === "y" || trimmed === "yes");
40487
+ resolve11(trimmed === "y" || trimmed === "yes");
40079
40488
  }
40080
40489
  });
40081
40490
  });
@@ -41523,13 +41932,13 @@ promptsCommand.command("delete <id>").description("Delete a prompt").option("--t
41523
41932
  await waitUntilExit2();
41524
41933
  return;
41525
41934
  }
41526
- const confirmed = await new Promise((resolve10) => {
41935
+ const confirmed = await new Promise((resolve11) => {
41527
41936
  const { unmount } = render4(
41528
41937
  React4.createElement(ConfirmPrompt, {
41529
41938
  message: `Delete prompt ${id}?`,
41530
41939
  defaultValue: false,
41531
41940
  onConfirm: (result) => {
41532
- resolve10(result);
41941
+ resolve11(result);
41533
41942
  unmount();
41534
41943
  }
41535
41944
  })
@@ -42414,13 +42823,13 @@ secretsCommand.command("delete <id>").description("Delete a secret").option("--t
42414
42823
  await waitUntilExit2();
42415
42824
  return;
42416
42825
  }
42417
- const confirmed = await new Promise((resolve10) => {
42826
+ const confirmed = await new Promise((resolve11) => {
42418
42827
  const { unmount } = render6(
42419
42828
  React6.createElement(ConfirmPrompt, {
42420
42829
  message: `Delete secret ${id}?`,
42421
42830
  defaultValue: false,
42422
42831
  onConfirm: (result) => {
42423
- resolve10(result);
42832
+ resolve11(result);
42424
42833
  unmount();
42425
42834
  }
42426
42835
  })
@@ -42832,13 +43241,13 @@ toolsCommand.command("delete <id>").description("Delete a tool").option("--tty",
42832
43241
  await waitUntilExit2();
42833
43242
  return;
42834
43243
  }
42835
- const confirmed = await new Promise((resolve10) => {
43244
+ const confirmed = await new Promise((resolve11) => {
42836
43245
  const { unmount } = render7(
42837
43246
  React7.createElement(ConfirmPrompt, {
42838
43247
  message: `Delete tool ${id}?`,
42839
43248
  defaultValue: false,
42840
43249
  onConfirm: (result) => {
42841
- resolve10(result);
43250
+ resolve11(result);
42842
43251
  unmount();
42843
43252
  }
42844
43253
  })
@@ -45229,13 +45638,13 @@ conversationsCommand.command("delete <id>").description("Delete a conversation")
45229
45638
  await waitUntilExit2();
45230
45639
  return;
45231
45640
  }
45232
- const confirmed = await new Promise((resolve10) => {
45641
+ const confirmed = await new Promise((resolve11) => {
45233
45642
  const { unmount } = render14(
45234
45643
  React14.createElement(ConfirmPrompt, {
45235
45644
  message: `Delete conversation ${id}?`,
45236
45645
  defaultValue: false,
45237
45646
  onConfirm: (result) => {
45238
- resolve10(result);
45647
+ resolve11(result);
45239
45648
  unmount();
45240
45649
  }
45241
45650
  })
@@ -47492,7 +47901,8 @@ var CHECKPOINT_COMMANDS = [
47492
47901
  var STEERING_SHORTCUTS = [
47493
47902
  { key: "Enter", desc: "Queue a steering message while the agent works" },
47494
47903
  { key: "Tab", desc: "Toggle delivery: next turn / after all work" },
47495
- { key: "Esc", desc: "Close the composer (keeps your draft)" }
47904
+ { key: "Esc", desc: "Close the composer (keeps your draft)" },
47905
+ { key: "Esc Esc", desc: "Interrupt the agent (queued text restores at the prompt)" }
47496
47906
  ];
47497
47907
  function buildLines(isCheckpoint) {
47498
47908
  const lines = [];
@@ -48185,14 +48595,24 @@ function readSessionEventLog(stateFilePath2, sessionIndex) {
48185
48595
  import * as fs4 from "fs";
48186
48596
  import * as path4 from "path";
48187
48597
  import { randomUUID } from "crypto";
48598
+ import * as os3 from "os";
48188
48599
  var TREE_LOG_FORMAT_VERSION = 1;
48189
48600
  function treeLogPathForStateFile(stateFilePath2) {
48190
48601
  return `${stateFilePath2.replace(/\.json$/, "")}.tree.jsonl`;
48191
48602
  }
48603
+ function artifactStoreDirForStateFile(stateFilePath2) {
48604
+ return path4.join(path4.dirname(stateFilePath2), path4.basename(stateFilePath2, ".json"), "outputs");
48605
+ }
48606
+ function artifactRelativePathForStateFile(stateFilePath2, fileName) {
48607
+ return path4.relative(
48608
+ path4.dirname(treeLogPathForStateFile(stateFilePath2)),
48609
+ path4.join(artifactStoreDirForStateFile(stateFilePath2), fileName)
48610
+ ).replace(/\\/g, "/");
48611
+ }
48192
48612
  function isTreeLogEntry(value) {
48193
48613
  if (typeof value !== "object" || value === null) return false;
48194
48614
  const record2 = value;
48195
- return record2.v === TREE_LOG_FORMAT_VERSION && typeof record2.id === "string" && (record2.parentId === null || typeof record2.parentId === "string") && typeof record2.ts === "string" && (record2.type === "meta" || record2.type === "delta" || record2.type === "fork" || record2.type === "head") && typeof record2.payload === "object" && record2.payload !== null;
48615
+ return record2.v === TREE_LOG_FORMAT_VERSION && typeof record2.id === "string" && (record2.parentId === null || typeof record2.parentId === "string") && typeof record2.ts === "string" && (record2.type === "meta" || record2.type === "delta" || record2.type === "fork" || record2.type === "artifact" || record2.type === "summary" || record2.type === "head") && typeof record2.payload === "object" && record2.payload !== null;
48196
48616
  }
48197
48617
  function loadTreeLog(filePath) {
48198
48618
  let raw;
@@ -48281,6 +48701,33 @@ function appendFork(log, fromEntryId, payload) {
48281
48701
  appendLine(log, entry);
48282
48702
  return entry;
48283
48703
  }
48704
+ function appendArtifact(log, payload) {
48705
+ const entry = {
48706
+ v: TREE_LOG_FORMAT_VERSION,
48707
+ id: newEntryId(),
48708
+ parentId: log.headId,
48709
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
48710
+ type: "artifact",
48711
+ payload: {
48712
+ ...payload,
48713
+ host: payload.host || os3.hostname()
48714
+ }
48715
+ };
48716
+ appendLine(log, entry);
48717
+ return entry;
48718
+ }
48719
+ function appendSummary(log, payload) {
48720
+ const entry = {
48721
+ v: TREE_LOG_FORMAT_VERSION,
48722
+ id: newEntryId(),
48723
+ parentId: log.headId,
48724
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
48725
+ type: "summary",
48726
+ payload
48727
+ };
48728
+ appendLine(log, entry);
48729
+ return entry;
48730
+ }
48284
48731
  function setHead(log, entryId) {
48285
48732
  if (!log.byId.has(entryId)) {
48286
48733
  throw new Error(`Cannot set head to unknown entry ${entryId}`);
@@ -48345,6 +48792,7 @@ function materializeAtEntry(log, entryId) {
48345
48792
  let meta3 = null;
48346
48793
  let state = null;
48347
48794
  let messages = [];
48795
+ const summaries = [];
48348
48796
  for (const entry of chain) {
48349
48797
  if (entry.type === "meta") {
48350
48798
  meta3 = entry.payload;
@@ -48357,9 +48805,31 @@ function materializeAtEntry(log, entryId) {
48357
48805
  if (entry.payload.truncateAtMessageIndex !== void 0) {
48358
48806
  messages = messages.slice(0, entry.payload.truncateAtMessageIndex);
48359
48807
  }
48808
+ } else if (entry.type === "artifact") {
48809
+ } else if (entry.type === "summary") {
48810
+ summaries.push(entry.payload);
48811
+ }
48812
+ }
48813
+ return { meta: meta3, state, messages, summaries };
48814
+ }
48815
+ function summariesToContextEntries(summaries) {
48816
+ return summaries.slice(-20).map((summary) => ({
48817
+ id: summary.summaryId,
48818
+ sessionIndex: summary.sessionIndex,
48819
+ mode: summary.mode,
48820
+ strategy: summary.strategy,
48821
+ content: summary.content,
48822
+ createdAt: summary.createdAt
48823
+ }));
48824
+ }
48825
+ function findArtifactPayload(log, id) {
48826
+ for (const entry of log.entries) {
48827
+ if (entry.type !== "artifact") continue;
48828
+ if (entry.payload.artifactId === id || entry.payload.outputId === id) {
48829
+ return entry.payload;
48360
48830
  }
48361
48831
  }
48362
- return { meta: meta3, state, messages };
48832
+ return void 0;
48363
48833
  }
48364
48834
  function materializeAtHead(log) {
48365
48835
  if (!log.headId) return null;
@@ -48398,10 +48868,33 @@ function toCheckpoint(state) {
48398
48868
  const {
48399
48869
  messages: _messages,
48400
48870
  sessionSnapshots: _snapshots,
48871
+ contextCompactionSummaries: _summaries,
48401
48872
  ...checkpoint
48402
48873
  } = state;
48403
48874
  return checkpoint;
48404
48875
  }
48876
+ function collectNewSummaries(log, state) {
48877
+ const summaries = state.contextCompactionSummaries ?? [];
48878
+ if (summaries.length === 0) return [];
48879
+ const existingIds = new Set(
48880
+ log.entries.filter(
48881
+ (entry) => entry.type === "summary"
48882
+ ).map((entry) => entry.payload.summaryId)
48883
+ );
48884
+ return summaries.filter((summary) => !existingIds.has(summary.id));
48885
+ }
48886
+ function appendNewSummaries(log, newSummaries) {
48887
+ for (const summary of newSummaries) {
48888
+ appendSummary(log, {
48889
+ summaryId: summary.id,
48890
+ sessionIndex: summary.sessionIndex,
48891
+ mode: summary.mode,
48892
+ strategy: summary.strategy,
48893
+ content: summary.content,
48894
+ createdAt: summary.createdAt
48895
+ });
48896
+ }
48897
+ }
48405
48898
  var syncStates = /* @__PURE__ */ new Map();
48406
48899
  function primeTreeLogSyncFromState(stateFilePath2, log, state) {
48407
48900
  syncStates.set(stateFilePath2, {
@@ -48437,15 +48930,19 @@ function syncTreeLogWithState(stateFilePath2, state) {
48437
48930
  const messagesDelta = computeMessagesDelta(sync.lastMessages, nextMessages);
48438
48931
  const checkpoint = toCheckpoint(state);
48439
48932
  const checkpointJson = JSON.stringify(checkpoint);
48440
- if (!messagesDelta && checkpointJson === sync.lastCheckpointJson) {
48933
+ const newSummaries = collectNewSummaries(sync.log, state);
48934
+ if (!messagesDelta && checkpointJson === sync.lastCheckpointJson && newSummaries.length === 0) {
48441
48935
  return;
48442
48936
  }
48443
- appendDelta(sync.log, {
48444
- ...messagesDelta ? { messages: messagesDelta } : {},
48445
- state: checkpoint
48446
- });
48447
- sync.lastMessages = nextMessages.map((message) => structuredClone(message));
48448
- sync.lastCheckpointJson = checkpointJson;
48937
+ appendNewSummaries(sync.log, newSummaries);
48938
+ if (messagesDelta || checkpointJson !== sync.lastCheckpointJson) {
48939
+ appendDelta(sync.log, {
48940
+ ...messagesDelta ? { messages: messagesDelta } : {},
48941
+ state: checkpoint
48942
+ });
48943
+ sync.lastMessages = nextMessages.map((message) => structuredClone(message));
48944
+ sync.lastCheckpointJson = checkpointJson;
48945
+ }
48449
48946
  } catch {
48450
48947
  }
48451
48948
  }
@@ -48465,6 +48962,13 @@ function entryLabel(entry) {
48465
48962
  const where = entry.payload.truncateAtMessageIndex !== void 0 ? ` @ message ${entry.payload.truncateAtMessageIndex}` : "";
48466
48963
  return entry.payload.label ? `fork${where} \xB7 ${previewText(entry.payload.label)}` : `fork${where}`;
48467
48964
  }
48965
+ if (entry.type === "artifact") {
48966
+ const tool = entry.payload.toolName ? `${entry.payload.toolName} ` : "";
48967
+ return `artifact \xB7 ${tool}${entry.payload.artifactId} (${entry.payload.charLength.toLocaleString()} chars)`;
48968
+ }
48969
+ if (entry.type === "summary") {
48970
+ return `summary \xB7 session ${entry.payload.sessionIndex} ${entry.payload.mode}`;
48971
+ }
48468
48972
  if (entry.type !== "delta") return entry.type;
48469
48973
  const state = entry.payload.state;
48470
48974
  const cost = typeof state.totalCost === "number" ? ` \xB7 $${state.totalCost.toFixed(4)}` : "";
@@ -48503,7 +49007,8 @@ function buildTreeView(log) {
48503
49007
  kind: entry.type,
48504
49008
  label: entryLabel(entry),
48505
49009
  isHead: entry.id === log.headId,
48506
- isOnHeadPath: onHeadPath.has(entry.id)
49010
+ isOnHeadPath: onHeadPath.has(entry.id),
49011
+ isSelectable: entry.type === "delta" || entry.type === "fork"
48507
49012
  });
48508
49013
  const children = childrenByParent.get(entry.id) ?? [];
48509
49014
  for (const child of children) {
@@ -49372,9 +49877,10 @@ function CheckpointRecap({
49372
49877
  reasoningTokens,
49373
49878
  cost,
49374
49879
  historyWarning,
49375
- isTerminal
49880
+ isTerminal,
49881
+ isStopped
49376
49882
  }) {
49377
- const label = isTerminal ? `\u2713 Run ${sessionNumber} complete` : `Run ${sessionNumber} complete`;
49883
+ const label = isStopped ? `Run ${sessionNumber} stopped` : isTerminal ? `\u2713 Run ${sessionNumber} complete` : `Run ${sessionNumber} complete`;
49378
49884
  const separator = theme22.separator ?? " \xB7 ";
49379
49885
  const usageSummary = [
49380
49886
  `Tools: ${toolCallsMade}`,
@@ -49392,7 +49898,7 @@ function CheckpointRecap({
49392
49898
  paddingX: theme22.panelPaddingX,
49393
49899
  paddingY: theme22.panelPaddingY,
49394
49900
  children: [
49395
- /* @__PURE__ */ jsx23(Text23, { color: isTerminal ? theme22.accentActive : theme22.accent, children: label }),
49901
+ /* @__PURE__ */ jsx23(Text23, { color: isStopped ? theme22.warning : isTerminal ? theme22.accentActive : theme22.accent, children: label }),
49396
49902
  /* @__PURE__ */ jsx23(Text23, { color: theme22.textMuted, children: usageSummary }),
49397
49903
  historyWarning && /* @__PURE__ */ jsx23(Text23, { color: theme22.warning, children: historyWarning })
49398
49904
  ]
@@ -49418,7 +49924,8 @@ function TreePanel({ rows, onSelect, onCancel }) {
49418
49924
  return;
49419
49925
  }
49420
49926
  if (key.return) {
49421
- if (rows.length > 0) onSelect(rows[selectedIndex]);
49927
+ const selected = rows[selectedIndex];
49928
+ if (selected && selected.isSelectable !== false) onSelect(selected);
49422
49929
  return;
49423
49930
  }
49424
49931
  if (key.upArrow) {
@@ -49455,10 +49962,11 @@ function TreePanel({ rows, onSelect, onCancel }) {
49455
49962
  const indicator = isHighlighted ? "\u203A " : " ";
49456
49963
  const indent = " ".repeat(row.depth);
49457
49964
  const headMark = row.isHead ? " \u2190 head" : "";
49965
+ const disabledMark = row.isSelectable === false ? " \xB7 metadata" : "";
49458
49966
  const color = isHighlighted ? theme23.accentActive : row.isOnHeadPath ? theme23.textMuted : theme23.textSubtle;
49459
- return /* @__PURE__ */ jsx24(Box21, { children: /* @__PURE__ */ jsx24(Text24, { color, bold: isHighlighted, children: `${indicator}${indent}${row.label}${headMark}` }) }, row.entryId);
49967
+ return /* @__PURE__ */ jsx24(Box21, { children: /* @__PURE__ */ jsx24(Text24, { color, bold: isHighlighted, children: `${indicator}${indent}${row.label}${headMark}${disabledMark}` }) }, row.entryId);
49460
49968
  }) }),
49461
- /* @__PURE__ */ jsx24(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text24, { color: theme23.textSubtle, children: ["\u2191\u2193 navigate", "Enter switch to entry", "Esc cancel"].join(
49969
+ /* @__PURE__ */ jsx24(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text24, { color: theme23.textSubtle, children: ["\u2191\u2193 navigate", "Enter switch to checkpoint", "Esc cancel"].join(
49462
49970
  theme23.separator ?? " \xB7 "
49463
49971
  ) }) })
49464
49972
  ]
@@ -49540,10 +50048,11 @@ function ForkPicker({ candidates, onSelect, onCancel }) {
49540
50048
  // src/ink/marathon/checkpoint-prompt-state.ts
49541
50049
  function shouldPauseCheckpointTimer(state) {
49542
50050
  return Boolean(
49543
- state.isTerminal || state.timeout === 0 || state.isTyping || state.hasPendingChanges || state.showModelPicker || state.showReflectEditor || state.showCommandPicker || state.showTreePanel || state.showForkPicker || state.isReviewing
50051
+ state.isTerminal || state.isStopped || state.timeout === 0 || state.isTyping || state.hasPendingChanges || state.showModelPicker || state.showReflectEditor || state.showCommandPicker || state.showTreePanel || state.showForkPicker || state.isReviewing
49544
50052
  );
49545
50053
  }
49546
50054
  function getCheckpointCountdownText(state) {
50055
+ if (state.isStopped) return "(stopped)";
49547
50056
  if (state.isTerminal) return "(complete)";
49548
50057
  if (state.timeout === 0) return "";
49549
50058
  if (state.isTyping) return "(typing)";
@@ -49564,13 +50073,15 @@ function CheckpointPrompt({
49564
50073
  onLoadForkCandidates,
49565
50074
  timeout,
49566
50075
  isTerminal,
50076
+ isStopped = false,
50077
+ initialMessage,
49567
50078
  currentModel,
49568
50079
  recap,
49569
50080
  isReviewing = false
49570
50081
  }) {
49571
- const [value, setValue] = useState26("");
50082
+ const [value, setValue] = useState26(initialMessage ?? "");
49572
50083
  const [remaining, setRemaining] = useState26(timeout);
49573
- const [isTyping, setIsTyping] = useState26(false);
50084
+ const [isTyping, setIsTyping] = useState26(Boolean(initialMessage));
49574
50085
  const [showModelPicker, setShowModelPicker] = useState26(false);
49575
50086
  const [showReflectEditor, setShowReflectEditor] = useState26(false);
49576
50087
  const [showCommandPicker, setShowCommandPicker] = useState26(false);
@@ -49618,7 +50129,7 @@ function CheckpointPrompt({
49618
50129
  };
49619
50130
  useEffect21(() => {
49620
50131
  const title = "Marathon";
49621
- const body = isTerminal ? "Marathon complete" : `Run ${recap?.sessionNumber ?? "?"} complete`;
50132
+ const body = isStopped ? `Run ${recap?.sessionNumber ?? "?"} stopped` : isTerminal ? "Marathon complete" : `Run ${recap?.sessionNumber ?? "?"} complete`;
49622
50133
  process.stderr.write(`\x1B]777;notify;${title};${body}\x07`);
49623
50134
  process.stderr.write(`\x1B]9;${body}\x07`);
49624
50135
  process.stderr.write("\x07");
@@ -49639,6 +50150,7 @@ function CheckpointPrompt({
49639
50150
  useEffect21(() => {
49640
50151
  if (shouldPauseCheckpointTimer({
49641
50152
  isTerminal,
50153
+ isStopped,
49642
50154
  timeout,
49643
50155
  isTyping,
49644
50156
  hasPendingChanges,
@@ -49671,7 +50183,20 @@ function CheckpointPrompt({
49671
50183
  timerRef.current = null;
49672
50184
  }
49673
50185
  };
49674
- }, [isTerminal, timeout, isTyping, hasPendingChanges, showModelPicker, showReflectEditor, showCommandPicker, treePanelRows, forkCandidates, isReviewing, onSubmit]);
50186
+ }, [
50187
+ isTerminal,
50188
+ isStopped,
50189
+ timeout,
50190
+ isTyping,
50191
+ hasPendingChanges,
50192
+ showModelPicker,
50193
+ showReflectEditor,
50194
+ showCommandPicker,
50195
+ treePanelRows,
50196
+ forkCandidates,
50197
+ isReviewing,
50198
+ onSubmit
50199
+ ]);
49675
50200
  const handleSubmit = (text) => {
49676
50201
  const trimmed = text.trim();
49677
50202
  const modelArg = trimmed.startsWith("/model") ? trimmed.slice("/model".length).trim() : "";
@@ -49779,6 +50304,7 @@ ${trimmed}` : trimmed);
49779
50304
  };
49780
50305
  const handleTreeSelect = (row) => {
49781
50306
  setTreePanelRows(null);
50307
+ if (row.isSelectable === false) return;
49782
50308
  if (row.isHead) return;
49783
50309
  setPendingFork(void 0);
49784
50310
  setPendingTreeHead({ entryId: row.entryId, label: row.label });
@@ -49790,6 +50316,7 @@ ${trimmed}` : trimmed);
49790
50316
  };
49791
50317
  const countdownText = getCheckpointCountdownText({
49792
50318
  isTerminal,
50319
+ isStopped,
49793
50320
  timeout,
49794
50321
  isTyping,
49795
50322
  hasPendingChanges,
@@ -49808,17 +50335,11 @@ ${trimmed}` : trimmed);
49808
50335
  const enterHint = (() => {
49809
50336
  if (isCommandDraft) return "Enter: stage command";
49810
50337
  if (pendingStop || hasPendingChanges || isTyping) return "Enter: submit";
49811
- if (isTerminal) return "Enter: exit";
50338
+ if (isTerminal || isStopped) return "Enter: exit";
49812
50339
  return "Enter: continue";
49813
50340
  })();
49814
50341
  return /* @__PURE__ */ jsxs22(Box23, { flexDirection: "column", flexShrink: 0, children: [
49815
- showCommandPicker ? /* @__PURE__ */ jsx26(
49816
- CommandPicker,
49817
- {
49818
- onSelect: handleCommandSelect,
49819
- onCancel: handleCommandCancel
49820
- }
49821
- ) : treePanelRows !== null ? /* @__PURE__ */ jsx26(
50342
+ showCommandPicker ? /* @__PURE__ */ jsx26(CommandPicker, { onSelect: handleCommandSelect, onCancel: handleCommandCancel }) : treePanelRows !== null ? /* @__PURE__ */ jsx26(
49822
50343
  TreePanel,
49823
50344
  {
49824
50345
  rows: treePanelRows,
@@ -49839,13 +50360,7 @@ ${trimmed}` : trimmed);
49839
50360
  onSelect: handleModelSelect,
49840
50361
  onCancel: handleModelCancel
49841
50362
  }
49842
- ) : showReflectEditor ? /* @__PURE__ */ jsx26(
49843
- ReflectEditor,
49844
- {
49845
- onSubmit: handleReflectSubmit,
49846
- onCancel: handleReflectCancel
49847
- }
49848
- ) : /* @__PURE__ */ jsxs22(
50363
+ ) : showReflectEditor ? /* @__PURE__ */ jsx26(ReflectEditor, { onSubmit: handleReflectSubmit, onCancel: handleReflectCancel }) : /* @__PURE__ */ jsxs22(
49849
50364
  Box23,
49850
50365
  {
49851
50366
  borderStyle: "bold",
@@ -49867,7 +50382,7 @@ ${trimmed}` : trimmed);
49867
50382
  value,
49868
50383
  onChange: handleChange,
49869
50384
  onSubmit: handleSubmit,
49870
- placeholder: isTerminal ? "Send new instructions to continue marathon, or press enter to exit..." : "Guide next iteration..."
50385
+ placeholder: isStopped ? "Send new instructions to continue, or press enter to exit..." : isTerminal ? "Send new instructions to continue marathon, or press enter to exit..." : "Guide next iteration..."
49871
50386
  }
49872
50387
  ) }),
49873
50388
  countdownText && /* @__PURE__ */ jsxs22(Text26, { color: theme25.textSubtle, children: [
@@ -49875,16 +50390,12 @@ ${trimmed}` : trimmed);
49875
50390
  countdownText
49876
50391
  ] })
49877
50392
  ] }),
49878
- /* @__PURE__ */ jsx26(Text26, { color: theme25.textSubtle, children: [
49879
- enterHint,
49880
- "/: commands",
49881
- "/help"
49882
- ].join(separator) }),
50393
+ /* @__PURE__ */ jsx26(Text26, { color: theme25.textSubtle, children: [enterHint, "/: commands", "/help"].join(separator) }),
49883
50394
  pendingSummary.length > 0 && /* @__PURE__ */ jsx26(Text26, { color: theme25.textMuted, children: `Pending: ${pendingSummary.join(separator)}` })
49884
50395
  ]
49885
50396
  }
49886
50397
  ),
49887
- /* @__PURE__ */ jsx26(CheckpointRecap, { ...recap, isTerminal })
50398
+ /* @__PURE__ */ jsx26(CheckpointRecap, { ...recap, isTerminal, isStopped })
49888
50399
  ] });
49889
50400
  }
49890
50401
 
@@ -50830,7 +51341,7 @@ function MarathonApp({
50830
51341
  stateFilePath: stateFilePath2,
50831
51342
  debug: _debug,
50832
51343
  plainText,
50833
- noCheckpoint: _noCheckpoint,
51344
+ noCheckpoint = false,
50834
51345
  checkpointTimeout,
50835
51346
  workflowMilestones,
50836
51347
  currentMilestone: initialCurrentMilestone,
@@ -50838,6 +51349,7 @@ function MarathonApp({
50838
51349
  billingUrl,
50839
51350
  onSaveState,
50840
51351
  onComplete: _onComplete,
51352
+ onAbortTurn,
50841
51353
  streamRef
50842
51354
  }) {
50843
51355
  const {
@@ -50876,6 +51388,7 @@ function MarathonApp({
50876
51388
  const [previewUrl, setPreviewUrl] = useState31(initialPreviewUrl);
50877
51389
  const [isCheckpointExploring, setIsCheckpointExploring] = useState31(false);
50878
51390
  const isRunnerAnimating = state.phase === "thinking" || state.phase === "streaming" || state.phase === "tool" || Boolean(state.contextCompaction?.active);
51391
+ const isAgentWorkingPhase = state.phase === "thinking" || state.phase === "streaming" || state.phase === "tool";
50879
51392
  const isTerminalCheckpointRef = useRef9(false);
50880
51393
  const markCheckpointExploring = useCallback8(() => {
50881
51394
  if (state.phase === "checkpoint" && checkpointRecap) {
@@ -50895,6 +51408,8 @@ function MarathonApp({
50895
51408
  const handleCheckpointSubmit = useCallback8(
50896
51409
  (result) => {
50897
51410
  setIsCheckpointExploring(false);
51411
+ setIsStoppedCheckpoint(false);
51412
+ setCheckpointInitialMessage(void 0);
50898
51413
  if (result.model) {
50899
51414
  setCurrentModel(result.model);
50900
51415
  }
@@ -50957,12 +51472,10 @@ function MarathonApp({
50957
51472
  setCheckpoint();
50958
51473
  setCheckpointRecap(recap);
50959
51474
  setIsCheckpointExploring(false);
50960
- if (isTerminal) {
50961
- setIsTerminalCheckpoint(true);
50962
- isTerminalCheckpointRef.current = true;
50963
- }
50964
- return new Promise((resolve10) => {
50965
- checkpointResolveRef.current = resolve10;
51475
+ setIsTerminalCheckpoint(Boolean(isTerminal));
51476
+ isTerminalCheckpointRef.current = Boolean(isTerminal);
51477
+ return new Promise((resolve11) => {
51478
+ checkpointResolveRef.current = resolve11;
50966
51479
  });
50967
51480
  },
50968
51481
  updateMilestone: (milestone) => {
@@ -51002,6 +51515,18 @@ function MarathonApp({
51002
51515
  const toolPanelWidth = terminalWidth < NARROW_THRESHOLD ? TOOL_PANEL_NARROW : TOOL_PANEL_WIDE;
51003
51516
  const [ctrlCPressed, setCtrlCPressed] = useState31(false);
51004
51517
  const ctrlCTimeout = useRef9(null);
51518
+ const [escAbortArmed, setEscAbortArmed] = useState31(false);
51519
+ const escAbortTimeout = useRef9(null);
51520
+ const [isStoppedCheckpoint, setIsStoppedCheckpoint] = useState31(false);
51521
+ const [checkpointInitialMessage, setCheckpointInitialMessage] = useState31(
51522
+ void 0
51523
+ );
51524
+ useEffect25(() => {
51525
+ if (!isAgentWorkingPhase && escAbortArmed) {
51526
+ if (escAbortTimeout.current) clearTimeout(escAbortTimeout.current);
51527
+ setEscAbortArmed(false);
51528
+ }
51529
+ }, [isAgentWorkingPhase, escAbortArmed]);
51005
51530
  const steeringQueueRef = useRef9([]);
51006
51531
  const followUpQueueRef = useRef9([]);
51007
51532
  const [queuedSteerCount, setQueuedSteerCount] = useState31(0);
@@ -51340,6 +51865,10 @@ function MarathonApp({
51340
51865
  [filteredEvents]
51341
51866
  );
51342
51867
  useInput14((_input, key) => {
51868
+ if (escAbortArmed && !key.escape) {
51869
+ if (escAbortTimeout.current) clearTimeout(escAbortTimeout.current);
51870
+ setEscAbortArmed(false);
51871
+ }
51343
51872
  if (_input === "u" && upgradePrompt) {
51344
51873
  void open4(billingPageUrl);
51345
51874
  setUpgradeModalDismissed(true);
@@ -51495,6 +52024,24 @@ function MarathonApp({
51495
52024
  setActiveScreen("overview");
51496
52025
  } else if (goalExpanded) {
51497
52026
  setGoalExpanded(false);
52027
+ } else if (state.phase === "thinking" || state.phase === "streaming" || state.phase === "tool") {
52028
+ if (escAbortArmed) {
52029
+ if (escAbortTimeout.current) clearTimeout(escAbortTimeout.current);
52030
+ setEscAbortArmed(false);
52031
+ if (onAbortTurn?.() && !noCheckpoint) {
52032
+ const queued = steeringQueueRef.current.splice(0);
52033
+ setQueuedSteerCount(0);
52034
+ const restored = [...queued, steerDraft].map((text) => text.trim()).filter(Boolean).join("\n\n");
52035
+ setSteerDraft("");
52036
+ setCheckpointInitialMessage(restored || void 0);
52037
+ setIsStoppedCheckpoint(true);
52038
+ }
52039
+ } else {
52040
+ setEscAbortArmed(true);
52041
+ escAbortTimeout.current = setTimeout(() => {
52042
+ setEscAbortArmed(false);
52043
+ }, 3e3);
52044
+ }
51498
52045
  }
51499
52046
  return;
51500
52047
  }
@@ -51780,6 +52327,7 @@ function MarathonApp({
51780
52327
  const statusRight = (() => {
51781
52328
  const joinHints = (...parts) => parts.filter(Boolean).join(separator);
51782
52329
  if (ctrlCPressed) return "Press Ctrl+C again to exit";
52330
+ if (escAbortArmed) return "Press Esc again to interrupt the agent";
51783
52331
  if (clipboardFlash) return clipboardFlash;
51784
52332
  if (showUpgradeModal) return joinHints("u: upgrade", "Enter: upgrade", "Esc: close", "Ctrl+C");
51785
52333
  if (state.phase === "error" && !canBrowseAfterUpgradeError) return joinHints("Enter: exit", "Ctrl+C");
@@ -52048,6 +52596,8 @@ function MarathonApp({
52048
52596
  onLoadForkCandidates: handleLoadForkCandidates,
52049
52597
  timeout: checkpointTimeout ?? 10,
52050
52598
  isTerminal: isTerminalCheckpoint,
52599
+ isStopped: isStoppedCheckpoint,
52600
+ initialMessage: checkpointInitialMessage,
52051
52601
  currentModel,
52052
52602
  currentSandbox,
52053
52603
  recap: checkpointRecap,
@@ -52330,16 +52880,16 @@ function MarathonStartupShell({
52330
52880
  latestAppPropsRef.current = marathonAppProps;
52331
52881
  useEffect26(() => {
52332
52882
  if (scene !== "app" || !appReadyResolverRef.current) return;
52333
- const resolve10 = appReadyResolverRef.current;
52883
+ const resolve11 = appReadyResolverRef.current;
52334
52884
  appReadyResolverRef.current = null;
52335
- resolve10();
52885
+ resolve11();
52336
52886
  }, [scene]);
52337
52887
  const beginTransition = (target) => {
52338
52888
  if (transitionPromiseRef.current) return transitionPromiseRef.current;
52339
52889
  if (target === "app" && !latestAppPropsRef.current) {
52340
52890
  throw new Error("Cannot complete startup before marathon app props are ready.");
52341
52891
  }
52342
- const promise2 = new Promise((resolve10) => {
52892
+ const promise2 = new Promise((resolve11) => {
52343
52893
  globalThis.setTimeout(() => {
52344
52894
  setPrompt(null);
52345
52895
  setModelChoices(null);
@@ -52360,12 +52910,12 @@ function MarathonStartupShell({
52360
52910
  if (target === "app") {
52361
52911
  appReadyResolverRef.current = () => {
52362
52912
  transitionPromiseRef.current = null;
52363
- resolve10();
52913
+ resolve11();
52364
52914
  };
52365
52915
  } else {
52366
52916
  dismissResolverRef.current = () => {
52367
52917
  transitionPromiseRef.current = null;
52368
- resolve10();
52918
+ resolve11();
52369
52919
  };
52370
52920
  }
52371
52921
  }, Math.max(0, MIN_HOLD_MS - (Date.now() - mountedAtRef.current)));
@@ -52382,8 +52932,8 @@ function MarathonStartupShell({
52382
52932
  setModelChoices(null);
52383
52933
  setPrompt(nextPrompt);
52384
52934
  setSelectedPromptIndex(0);
52385
- return new Promise((resolve10) => {
52386
- promptResolverRef.current = resolve10;
52935
+ return new Promise((resolve11) => {
52936
+ promptResolverRef.current = resolve11;
52387
52937
  });
52388
52938
  },
52389
52939
  requestModelChoice: async (nextCurrentModel, models) => {
@@ -52391,8 +52941,8 @@ function MarathonStartupShell({
52391
52941
  setPlaybookConfirm(null);
52392
52942
  setCurrentModel(nextCurrentModel);
52393
52943
  setModelChoices(models);
52394
- return new Promise((resolve10) => {
52395
- modelResolverRef.current = resolve10;
52944
+ return new Promise((resolve11) => {
52945
+ modelResolverRef.current = resolve11;
52396
52946
  });
52397
52947
  },
52398
52948
  requestPlaybookModelConfirm: async (playbookName, milestoneModels) => {
@@ -52407,8 +52957,8 @@ function MarathonStartupShell({
52407
52957
  // Default selection is the "Confirm" action (first item after milestones)
52408
52958
  selectedIndex: names.length
52409
52959
  });
52410
- return new Promise((resolve10) => {
52411
- playbookConfirmResolverRef.current = resolve10;
52960
+ return new Promise((resolve11) => {
52961
+ playbookConfirmResolverRef.current = resolve11;
52412
52962
  });
52413
52963
  },
52414
52964
  completeStartup: () => beginTransition("app"),
@@ -52675,7 +53225,7 @@ function MarathonStartupShell({
52675
53225
  }
52676
53226
 
52677
53227
  // src/commands/agents-task.ts
52678
- import * as fs14 from "fs";
53228
+ import * as fs15 from "fs";
52679
53229
  import {
52680
53230
  RuntypeClient as RuntypeClient2,
52681
53231
  defaultWorkflow,
@@ -52706,12 +53256,12 @@ import * as fs7 from "fs";
52706
53256
  import * as path8 from "path";
52707
53257
 
52708
53258
  // src/config/paths.ts
52709
- import * as os3 from "os";
53259
+ import * as os4 from "os";
52710
53260
  import * as path7 from "path";
52711
53261
  import * as crypto4 from "crypto";
52712
53262
  import * as fs6 from "fs";
52713
53263
  function getRuntypeHomeDir() {
52714
- return process.env.RUNTYPE_STATE_DIR || path7.join(os3.homedir(), ".runtype");
53264
+ return process.env.RUNTYPE_STATE_DIR || path7.join(os4.homedir(), ".runtype");
52715
53265
  }
52716
53266
  function getProjectStateDir(projectDir) {
52717
53267
  const dir = projectDir || process.cwd();
@@ -52735,20 +53285,23 @@ function defaultStateDir() {
52735
53285
  function stateSafeName(name) {
52736
53286
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
52737
53287
  }
52738
- function marathonArtifactsDir(taskName, stateDir) {
53288
+ function marathonArtifactsDir(taskName, stateDir, stateFilePath2) {
53289
+ if (stateFilePath2) {
53290
+ return path8.join(path8.dirname(stateFilePath2), path8.basename(stateFilePath2, ".json"));
53291
+ }
52739
53292
  return path8.join(stateDir || defaultStateDir(), stateSafeName(taskName));
52740
53293
  }
52741
- function resolveMarathonCheckpointPath(taskName, targetPath, stateDir) {
53294
+ function resolveMarathonCheckpointPath(taskName, targetPath, stateDir, stateFilePath2) {
52742
53295
  const normalizedTargetPath = path8.normalize(targetPath);
52743
53296
  const relativeTargetPath = path8.isAbsolute(normalizedTargetPath) ? path8.relative(process.cwd(), normalizedTargetPath) : normalizedTargetPath;
52744
53297
  return path8.join(
52745
- marathonArtifactsDir(taskName, stateDir),
53298
+ marathonArtifactsDir(taskName, stateDir, stateFilePath2),
52746
53299
  "checkpoints",
52747
53300
  "original",
52748
53301
  relativeTargetPath
52749
53302
  );
52750
53303
  }
52751
- function ensureMarathonFileCheckpoint(taskName, targetPath, stateDir) {
53304
+ function ensureMarathonFileCheckpoint(taskName, targetPath, stateDir, stateFilePath2) {
52752
53305
  const normalizedTargetPath = path8.resolve(targetPath);
52753
53306
  const relativeTargetPath = path8.relative(process.cwd(), normalizedTargetPath);
52754
53307
  if (!relativeTargetPath || relativeTargetPath.startsWith("..")) return void 0;
@@ -52757,13 +53310,18 @@ function ensureMarathonFileCheckpoint(taskName, targetPath, stateDir) {
52757
53310
  const normalizedRelativeTargetPath = relativeTargetPath.replace(/\\/g, "/");
52758
53311
  if (normalizedRelativeTargetPath.startsWith(".runtype/")) return void 0;
52759
53312
  if (normalizedTargetPath.startsWith(getRuntypeHomeDir() + path8.sep)) return void 0;
52760
- const checkpointPath = resolveMarathonCheckpointPath(taskName, normalizedTargetPath, stateDir);
53313
+ const checkpointPath = resolveMarathonCheckpointPath(
53314
+ taskName,
53315
+ normalizedTargetPath,
53316
+ stateDir,
53317
+ stateFilePath2
53318
+ );
52761
53319
  if (fs7.existsSync(checkpointPath)) return checkpointPath;
52762
53320
  fs7.mkdirSync(path8.dirname(checkpointPath), { recursive: true });
52763
53321
  fs7.copyFileSync(normalizedTargetPath, checkpointPath);
52764
53322
  return checkpointPath;
52765
53323
  }
52766
- function restoreMarathonFileCheckpoint(taskName, targetPath, stateDir) {
53324
+ function restoreMarathonFileCheckpoint(taskName, targetPath, stateDir, stateFilePath2) {
52767
53325
  const normalizedTargetPath = path8.resolve(targetPath);
52768
53326
  const relativeTargetPath = path8.relative(process.cwd(), normalizedTargetPath);
52769
53327
  if (!relativeTargetPath || relativeTargetPath.startsWith("..")) {
@@ -52772,7 +53330,12 @@ function restoreMarathonFileCheckpoint(taskName, targetPath, stateDir) {
52772
53330
  error: `Cannot restore checkpoint outside the current repository: ${normalizedTargetPath}`
52773
53331
  };
52774
53332
  }
52775
- const checkpointPath = resolveMarathonCheckpointPath(taskName, normalizedTargetPath, stateDir);
53333
+ const checkpointPath = resolveMarathonCheckpointPath(
53334
+ taskName,
53335
+ normalizedTargetPath,
53336
+ stateDir,
53337
+ stateFilePath2
53338
+ );
52776
53339
  if (!fs7.existsSync(checkpointPath)) {
52777
53340
  return {
52778
53341
  restored: false,
@@ -52897,16 +53460,33 @@ async function retryOnNetworkError(fn, opts = {}) {
52897
53460
  const maxDelay = opts.maxDelayMs ?? 6e4;
52898
53461
  let lastError;
52899
53462
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
53463
+ if (attempt > 0 && opts.signal?.aborted) {
53464
+ throw lastError;
53465
+ }
52900
53466
  try {
52901
53467
  return await fn();
52902
53468
  } catch (error51) {
52903
53469
  lastError = error51;
52904
- if (!isTransientNetworkError(error51) || attempt === maxRetries) {
53470
+ if (opts.signal?.aborted || !isTransientNetworkError(error51) || attempt === maxRetries) {
52905
53471
  throw error51;
52906
53472
  }
52907
53473
  const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
52908
53474
  opts.onRetry?.(attempt + 1, delay, error51);
52909
- await new Promise((resolve10) => setTimeout(resolve10, delay));
53475
+ await new Promise((resolve11) => {
53476
+ const signal = opts.signal;
53477
+ const onAbort = () => {
53478
+ clearTimeout(timer);
53479
+ resolve11();
53480
+ };
53481
+ const timer = setTimeout(() => {
53482
+ signal?.removeEventListener("abort", onAbort);
53483
+ resolve11();
53484
+ }, delay);
53485
+ if (signal) {
53486
+ if (signal.aborted) onAbort();
53487
+ else signal.addEventListener("abort", onAbort, { once: true });
53488
+ }
53489
+ });
52910
53490
  }
52911
53491
  }
52912
53492
  throw lastError;
@@ -53166,14 +53746,14 @@ async function promptNumericSelect(choices, promptLabel) {
53166
53746
  output: process.stdout,
53167
53747
  terminal: true
53168
53748
  });
53169
- return new Promise((resolve10) => {
53749
+ return new Promise((resolve11) => {
53170
53750
  const ask = () => {
53171
53751
  rl.question(chalk21.cyan(`
53172
53752
  ${promptLabel} (1-${choices.length}): `), (answer) => {
53173
53753
  const value = parseInt(answer.trim(), 10);
53174
53754
  if (value >= 1 && value <= choices.length) {
53175
53755
  rl.close();
53176
- resolve10(choices[value - 1].value);
53756
+ resolve11(choices[value - 1].value);
53177
53757
  return;
53178
53758
  }
53179
53759
  console.log(chalk21.red(`Please enter a number between 1 and ${choices.length}.`));
@@ -53201,7 +53781,7 @@ ${message}`));
53201
53781
  const previousRawMode = input.isRaw === true;
53202
53782
  let selectedIndex = 0;
53203
53783
  let renderedLineCount = 0;
53204
- return new Promise((resolve10) => {
53784
+ return new Promise((resolve11) => {
53205
53785
  const renderMenu = () => {
53206
53786
  if (renderedLineCount > 0) {
53207
53787
  clearRenderedLines(output, renderedLineCount);
@@ -53223,7 +53803,7 @@ ${message}`));
53223
53803
  };
53224
53804
  const finish = (value) => {
53225
53805
  cleanup();
53226
- resolve10(value);
53806
+ resolve11(value);
53227
53807
  };
53228
53808
  const onKeypress = (_, key) => {
53229
53809
  if (key.ctrl && key.name === "c") {
@@ -53373,7 +53953,9 @@ function sanitizeMarathonSessionSnapshots(snapshots) {
53373
53953
  };
53374
53954
  bySessionIndex.set(sanitizedSnapshot.sessionIndex, sanitizedSnapshot);
53375
53955
  }
53376
- return Array.from(bySessionIndex.values()).sort((left, right) => left.sessionIndex - right.sessionIndex);
53956
+ return Array.from(bySessionIndex.values()).sort(
53957
+ (left, right) => left.sessionIndex - right.sessionIndex
53958
+ );
53377
53959
  }
53378
53960
  function upsertMarathonSessionSnapshot(snapshots, nextSnapshot) {
53379
53961
  const bySessionIndex = /* @__PURE__ */ new Map();
@@ -53381,7 +53963,9 @@ function upsertMarathonSessionSnapshot(snapshots, nextSnapshot) {
53381
53963
  bySessionIndex.set(snapshot.sessionIndex, cloneSessionSnapshot2(snapshot));
53382
53964
  }
53383
53965
  bySessionIndex.set(nextSnapshot.sessionIndex, cloneSessionSnapshot2(nextSnapshot));
53384
- return Array.from(bySessionIndex.values()).sort((left, right) => left.sessionIndex - right.sessionIndex);
53966
+ return Array.from(bySessionIndex.values()).sort(
53967
+ (left, right) => left.sessionIndex - right.sessionIndex
53968
+ );
53385
53969
  }
53386
53970
  function mergeMarathonSessionSummaries(existingSessions, nextSessions, offset) {
53387
53971
  const byIndex = /* @__PURE__ */ new Map();
@@ -53434,7 +54018,9 @@ function sanitizeLoadedMarathonState(state) {
53434
54018
  (candidatePath) => marathonStatePathExists(candidatePath)
53435
54019
  );
53436
54020
  const normalizedBestCandidate = normalizeMarathonStatePath(state.bestCandidatePath);
53437
- const bestCandidatePath = normalizedBestCandidate && !isMarathonArtifactStatePath(normalizedBestCandidate) && marathonStatePathExists(normalizedBestCandidate) ? normalizedBestCandidate : [...candidatePaths, ...recentReadPaths].sort((left, right) => scoreMarathonCandidatePath(right) - scoreMarathonCandidatePath(left))[0];
54021
+ const bestCandidatePath = normalizedBestCandidate && !isMarathonArtifactStatePath(normalizedBestCandidate) && marathonStatePathExists(normalizedBestCandidate) ? normalizedBestCandidate : [...candidatePaths, ...recentReadPaths].sort(
54022
+ (left, right) => scoreMarathonCandidatePath(right) - scoreMarathonCandidatePath(left)
54023
+ )[0];
53438
54024
  const persisted = state;
53439
54025
  const {
53440
54026
  runnerPosition: _runnerPosition,
@@ -53493,8 +54079,25 @@ function extractRunTaskResumeState(state) {
53493
54079
  ...sanitized.verificationRequired !== void 0 ? { verificationRequired: sanitized.verificationRequired } : {},
53494
54080
  ...sanitized.lastVerificationPassed ? { lastVerificationPassed: sanitized.lastVerificationPassed } : {},
53495
54081
  ...sanitized.isCreationTask !== void 0 ? { isCreationTask: sanitized.isCreationTask } : {},
53496
- ...sanitized.outputRoot ? { outputRoot: sanitized.outputRoot } : {}
53497
- };
54082
+ ...sanitized.outputRoot ? { outputRoot: sanitized.outputRoot } : {},
54083
+ ...sanitized.contextCompactionSummaries?.length ? { contextCompactionSummaries: sanitized.contextCompactionSummaries } : {},
54084
+ ...typeof sanitized.contextWindowBaseIndex === "number" && sanitized.contextWindowBaseIndex > 0 ? { contextWindowBaseIndex: sanitized.contextWindowBaseIndex } : {}
54085
+ };
54086
+ }
54087
+ function offsetNewContextCompactionSummaries(summaries, existingSummaryIds, sessionOffset) {
54088
+ if (!summaries?.length) return void 0;
54089
+ if (sessionOffset === 0) return summaries;
54090
+ const existingIds = new Set(existingSummaryIds);
54091
+ return summaries.map((summary) => {
54092
+ if (existingIds.has(summary.id)) return summary;
54093
+ const absoluteSessionIndex = summary.sessionIndex + sessionOffset;
54094
+ const idPrefix = `ctx_${summary.sessionIndex}_`;
54095
+ return {
54096
+ ...summary,
54097
+ id: summary.id.startsWith(idPrefix) ? `ctx_${absoluteSessionIndex}_${summary.id.slice(idPrefix.length)}` : summary.id,
54098
+ sessionIndex: absoluteSessionIndex
54099
+ };
54100
+ });
53498
54101
  }
53499
54102
  function findStateFile(name, stateDir) {
53500
54103
  if (stateDir) {
@@ -53649,6 +54252,8 @@ function applyCheckpointTreeNavigation(stateFilePath2, navigation) {
53649
54252
  if (!log || !log.headId) return null;
53650
54253
  const destinationId = navigation.fork ? log.headId : navigation.treeHead;
53651
54254
  if (!destinationId || !log.byId.has(destinationId)) return null;
54255
+ const destination = log.byId.get(destinationId);
54256
+ if (!destination || destination.type !== "delta" && destination.type !== "fork") return null;
53652
54257
  try {
53653
54258
  if (!materializeAtEntry(log, destinationId).state) return null;
53654
54259
  } catch {
@@ -53675,21 +54280,39 @@ function applyCheckpointTreeNavigation(stateFilePath2, navigation) {
53675
54280
  lastOutput: anchor.lastOutput,
53676
54281
  lastStopReason: anchor.lastStopReason
53677
54282
  } : {};
54283
+ const forkAnchoredBase = anchor?.contextWindowBaseIndex ?? 0;
54284
+ const windowBaseOverride = navigation.fork ? {
54285
+ contextWindowBaseIndex: forkAnchoredBase <= navigation.fork.atMessageIndex ? forkAnchoredBase : 0
54286
+ } : {};
53678
54287
  const effectiveSessionCount = sessionShapedOverrides.sessionCount ?? materialized.state.sessionCount;
53679
54288
  const currentJson = loadState(stateFilePath2);
53680
54289
  const now = (/* @__PURE__ */ new Date()).toISOString();
53681
- const { sessionSnapshots: priorSnapshots, ...restJson } = currentJson ?? {};
54290
+ const {
54291
+ sessionSnapshots: priorSnapshots,
54292
+ contextCompactionSummaries: _priorSummaries,
54293
+ ...restJson
54294
+ } = currentJson ?? {};
53682
54295
  const keptSnapshots = (priorSnapshots ?? []).filter(
53683
54296
  (snapshot) => snapshot.sessionIndex <= effectiveSessionCount
53684
54297
  );
54298
+ const branchSummaries = summariesToContextEntries(materialized.summaries);
54299
+ const contextCompactionSummaries = branchSummaries.length ? branchSummaries : materialized.state.contextCompactionSummaries;
53685
54300
  const mergedState = {
53686
54301
  ...restJson,
53687
54302
  ...materialized.state,
53688
54303
  ...sessionShapedOverrides,
54304
+ ...windowBaseOverride,
53689
54305
  messages: materialized.messages,
54306
+ ...contextCompactionSummaries?.length ? { contextCompactionSummaries } : {},
53690
54307
  ...keptSnapshots.length > 0 ? { sessionSnapshots: keptSnapshots } : {},
53691
54308
  updatedAt: now
53692
54309
  };
54310
+ if (typeof mergedState.contextWindowBaseIndex === "number") {
54311
+ mergedState.contextWindowBaseIndex = Math.max(
54312
+ 0,
54313
+ Math.min(mergedState.contextWindowBaseIndex, materialized.messages.length)
54314
+ );
54315
+ }
53693
54316
  primeTreeLogSyncFromState(stateFilePath2, log, mergedState);
53694
54317
  saveState(stateFilePath2, mergedState);
53695
54318
  return { messages: materialized.messages, mergedState };
@@ -53698,7 +54321,11 @@ function applyCheckpointTreeNavigation(stateFilePath2, navigation) {
53698
54321
  // src/marathon/local-tools.ts
53699
54322
  import * as fs10 from "fs";
53700
54323
  import * as path11 from "path";
54324
+ import { createHash as createHash2 } from "crypto";
53701
54325
  import { spawnSync } from "child_process";
54326
+ import {
54327
+ LEDGER_ARTIFACT_LINE_PREFIX
54328
+ } from "@runtypelabs/sdk";
53702
54329
 
53703
54330
  // src/marathon/repo-discovery.ts
53704
54331
  import * as fs9 from "fs";
@@ -53914,8 +54541,11 @@ var DIRECT_TOOL_BLOCKED_SEGMENTS = /* @__PURE__ */ new Set([".git", ".runtype"])
53914
54541
  function stateSafeName3(name) {
53915
54542
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
53916
54543
  }
53917
- function getOffloadedOutputDir(taskName, stateDir) {
53918
- return path11.join(stateDir || getMarathonStateDir(), stateSafeName3(taskName), "outputs");
54544
+ function getStateFilePathForTask(taskName, stateDir, stateFilePath2) {
54545
+ return stateFilePath2 || path11.join(stateDir || getMarathonStateDir(), `${stateSafeName3(taskName)}.json`);
54546
+ }
54547
+ function getOffloadedOutputDir(taskName, stateDir, stateFilePath2) {
54548
+ return artifactStoreDirForStateFile(getStateFilePathForTask(taskName, stateDir, stateFilePath2));
53919
54549
  }
53920
54550
  function isPathWithinRoot(targetPath, rootPath) {
53921
54551
  const relativePath = path11.relative(rootPath, targetPath);
@@ -53962,11 +54592,10 @@ function resolveToolPath(toolPath, options = {}) {
53962
54592
  return { ok: false, error: `Path does not exist: ${requestedPath}` };
53963
54593
  }
53964
54594
  const workspaceRoot = fs10.realpathSync.native(process.cwd());
53965
- const extraRoots = (options.allowedRoots || []).map((rootPath) => canonicalizeAllowedRoot(rootPath));
53966
- const allowedRoots = [
53967
- ...extraRoots,
53968
- workspaceRoot
53969
- ];
54595
+ const extraRoots = (options.allowedRoots || []).map(
54596
+ (rootPath) => canonicalizeAllowedRoot(rootPath)
54597
+ );
54598
+ const allowedRoots = [...extraRoots, workspaceRoot];
53970
54599
  const matchedRoot = allowedRoots.find(
53971
54600
  (rootPath) => isPathWithinRoot(resolved.canonicalPath, rootPath)
53972
54601
  );
@@ -54016,15 +54645,15 @@ function resolveToolPath(toolPath, options = {}) {
54016
54645
  }
54017
54646
  return { ok: true, resolvedPath: resolved.canonicalPath };
54018
54647
  }
54019
- function getTaskStateRoot(taskName, stateDir) {
54020
- return path11.join(stateDir || getMarathonStateDir(), stateSafeName3(taskName));
54648
+ function getTaskStateRoot(taskName, stateDir, stateFilePath2) {
54649
+ return path11.dirname(getOffloadedOutputDir(taskName, stateDir, stateFilePath2));
54021
54650
  }
54022
54651
  function createDefaultLocalTools(context) {
54023
- const taskStateRoot = context?.taskName ? getTaskStateRoot(context.taskName, context.stateDir) : void 0;
54652
+ const taskStateRoot = context?.taskName ? getTaskStateRoot(context.taskName, context.stateDir, context.stateFilePath) : void 0;
54024
54653
  const planDir = context?.taskName ? path11.resolve(`.runtype/marathons/${stateSafeName3(context.taskName)}`) : void 0;
54025
54654
  const planPathDir = context?.planPath ? path11.resolve(path11.dirname(context.planPath)) : void 0;
54026
54655
  const allowedReadRoots = context?.taskName ? [
54027
- getOffloadedOutputDir(context.taskName, context.stateDir),
54656
+ getOffloadedOutputDir(context.taskName, context.stateDir, context.stateFilePath),
54028
54657
  ...taskStateRoot ? [taskStateRoot] : [],
54029
54658
  ...planDir ? [planDir] : [],
54030
54659
  ...planPathDir ? [planPathDir] : []
@@ -54082,7 +54711,9 @@ function createDefaultLocalTools(context) {
54082
54711
  requireDirectory: true
54083
54712
  });
54084
54713
  if (!resolvedPath.ok) return `Error: ${resolvedPath.error}`;
54085
- return fs10.readdirSync(resolvedPath.resolvedPath, { withFileTypes: true }).filter((entry) => !shouldIgnoreRepoEntry(path11.join(resolvedPath.resolvedPath, entry.name))).map((entry) => entry.name).join("\n");
54714
+ return fs10.readdirSync(resolvedPath.resolvedPath, { withFileTypes: true }).filter(
54715
+ (entry) => !shouldIgnoreRepoEntry(path11.join(resolvedPath.resolvedPath, entry.name))
54716
+ ).map((entry) => entry.name).join("\n");
54086
54717
  }
54087
54718
  },
54088
54719
  search_repo: {
@@ -54114,7 +54745,10 @@ function createDefaultLocalTools(context) {
54114
54745
  if (!startPath.ok) return `Error: ${startPath.error}`;
54115
54746
  const maxResults = Math.max(
54116
54747
  1,
54117
- Math.min(100, Number.isFinite(Number(args.maxResults)) ? Math.floor(Number(args.maxResults)) : 20)
54748
+ Math.min(
54749
+ 100,
54750
+ Number.isFinite(Number(args.maxResults)) ? Math.floor(Number(args.maxResults)) : 20
54751
+ )
54118
54752
  );
54119
54753
  const needle = query.toLowerCase();
54120
54754
  const tokens = tokenizeSearchQuery(query);
@@ -54221,20 +54855,31 @@ function createDefaultLocalTools(context) {
54221
54855
  if (!dirPath.ok) return `Error: ${dirPath.error}`;
54222
54856
  const maxDepth = Math.max(
54223
54857
  0,
54224
- Math.min(6, Number.isFinite(Number(args.maxDepth)) ? Math.floor(Number(args.maxDepth)) : 2)
54858
+ Math.min(
54859
+ 6,
54860
+ Number.isFinite(Number(args.maxDepth)) ? Math.floor(Number(args.maxDepth)) : 2
54861
+ )
54225
54862
  );
54226
- const lines = [`${normalizeToolPath(dirPath.resolvedPath)}/`, ...buildTree(dirPath.resolvedPath, maxDepth)];
54863
+ const lines = [
54864
+ `${normalizeToolPath(dirPath.resolvedPath)}/`,
54865
+ ...buildTree(dirPath.resolvedPath, maxDepth)
54866
+ ];
54227
54867
  return lines.join("\n");
54228
54868
  }
54229
54869
  }
54230
54870
  };
54231
54871
  }
54232
- function createCheckpointedWriteFileTool(taskName, stateDir, planPath) {
54233
- const taskStateRoot = getTaskStateRoot(taskName, stateDir);
54872
+ function createCheckpointedWriteFileTool(taskName, stateDir, planPath, stateFilePath2) {
54873
+ const taskStateRoot = getTaskStateRoot(taskName, stateDir, stateFilePath2);
54234
54874
  const planDir = path11.resolve(`.runtype/marathons/${stateSafeName3(taskName)}`);
54235
54875
  const marathonPlanRoot = path11.resolve(".runtype/marathons");
54236
54876
  const planPathDir = planPath ? path11.resolve(path11.dirname(planPath)) : void 0;
54237
- const writeAllowedRoots = [taskStateRoot, planDir, marathonPlanRoot, ...planPathDir ? [planPathDir] : []];
54877
+ const writeAllowedRoots = [
54878
+ taskStateRoot,
54879
+ planDir,
54880
+ marathonPlanRoot,
54881
+ ...planPathDir ? [planPathDir] : []
54882
+ ];
54238
54883
  return {
54239
54884
  description: "Write content to a file, creating directories as needed and checkpointing original repo files",
54240
54885
  parametersSchema: {
@@ -54252,7 +54897,7 @@ function createCheckpointedWriteFileTool(taskName, stateDir, planPath) {
54252
54897
  });
54253
54898
  if (!resolvedPath.ok) return `Error: ${resolvedPath.error}`;
54254
54899
  const content = String(args.content || "");
54255
- ensureMarathonFileCheckpoint(taskName, resolvedPath.resolvedPath, stateDir);
54900
+ ensureMarathonFileCheckpoint(taskName, resolvedPath.resolvedPath, stateDir, stateFilePath2);
54256
54901
  const dir = path11.dirname(resolvedPath.resolvedPath);
54257
54902
  fs10.mkdirSync(dir, { recursive: true });
54258
54903
  fs10.writeFileSync(resolvedPath.resolvedPath, content);
@@ -54280,12 +54925,17 @@ function quickJsSyntaxCheck(content) {
54280
54925
  return void 0;
54281
54926
  }
54282
54927
  }
54283
- function createEditFileTool(taskName, stateDir, planPath) {
54284
- const taskStateRoot = getTaskStateRoot(taskName, stateDir);
54928
+ function createEditFileTool(taskName, stateDir, planPath, stateFilePath2) {
54929
+ const taskStateRoot = getTaskStateRoot(taskName, stateDir, stateFilePath2);
54285
54930
  const planDir = path11.resolve(`.runtype/marathons/${stateSafeName3(taskName)}`);
54286
54931
  const marathonPlanRoot = path11.resolve(".runtype/marathons");
54287
54932
  const planPathDir = planPath ? path11.resolve(path11.dirname(planPath)) : void 0;
54288
- const writeAllowedRoots = [taskStateRoot, planDir, marathonPlanRoot, ...planPathDir ? [planPathDir] : []];
54933
+ const writeAllowedRoots = [
54934
+ taskStateRoot,
54935
+ planDir,
54936
+ marathonPlanRoot,
54937
+ ...planPathDir ? [planPathDir] : []
54938
+ ];
54289
54939
  return {
54290
54940
  description: "Make a targeted edit to a file by replacing a specific string. Much more efficient than rewriting the entire file with write_file. The old_string must appear exactly once in the file (or use replace_all for global replacement). Always read the file first to get the exact text to replace.",
54291
54941
  parametersSchema: {
@@ -54293,7 +54943,10 @@ function createEditFileTool(taskName, stateDir, planPath) {
54293
54943
  properties: {
54294
54944
  path: { type: "string", description: "File path to edit" },
54295
54945
  // @snake-case-ok: Parameter names use snake_case to match agent tool conventions
54296
- old_string: { type: "string", description: "Exact string to find and replace (must be unique in the file)" },
54946
+ old_string: {
54947
+ type: "string",
54948
+ description: "Exact string to find and replace (must be unique in the file)"
54949
+ },
54297
54950
  // @snake-case-ok: Parameter names use snake_case to match agent tool conventions
54298
54951
  new_string: { type: "string", description: "Replacement string" },
54299
54952
  // @snake-case-ok: Parameter names use snake_case to match agent tool conventions
@@ -54332,7 +54985,7 @@ function createEditFileTool(taskName, stateDir, planPath) {
54332
54985
  return `Error: old_string appears ${count} times in the file. Provide more surrounding context to make it unique, or set replace_all to true.`;
54333
54986
  }
54334
54987
  }
54335
- ensureMarathonFileCheckpoint(taskName, resolvedPath.resolvedPath, stateDir);
54988
+ ensureMarathonFileCheckpoint(taskName, resolvedPath.resolvedPath, stateDir, stateFilePath2);
54336
54989
  const updated = replaceAll ? content.split(oldString).join(newString) : content.replace(oldString, newString);
54337
54990
  fs10.writeFileSync(resolvedPath.resolvedPath, updated);
54338
54991
  const ext = path11.extname(resolvedPath.resolvedPath).toLowerCase();
@@ -54348,7 +55001,7 @@ function createEditFileTool(taskName, stateDir, planPath) {
54348
55001
  }
54349
55002
  };
54350
55003
  }
54351
- function createRestoreFileCheckpointTool(taskName, stateDir) {
55004
+ function createRestoreFileCheckpointTool(taskName, stateDir, stateFilePath2) {
54352
55005
  return {
54353
55006
  description: "Restore the original checkpointed contents for a previously edited repo file if a change regresses behavior",
54354
55007
  parametersSchema: {
@@ -54363,7 +55016,12 @@ function createRestoreFileCheckpointTool(taskName, stateDir) {
54363
55016
  requireFile: true
54364
55017
  });
54365
55018
  if (!resolvedPath.ok) return `Error: ${resolvedPath.error}`;
54366
- const result = restoreMarathonFileCheckpoint(taskName, resolvedPath.resolvedPath, stateDir);
55019
+ const result = restoreMarathonFileCheckpoint(
55020
+ taskName,
55021
+ resolvedPath.resolvedPath,
55022
+ stateDir,
55023
+ stateFilePath2
55024
+ );
54367
55025
  if (!result.restored) {
54368
55026
  return result.error || `No checkpoint found for ${String(args.path || "")}`;
54369
55027
  }
@@ -54371,15 +55029,15 @@ function createRestoreFileCheckpointTool(taskName, stateDir) {
54371
55029
  }
54372
55030
  };
54373
55031
  }
54374
- function createReadOffloadedOutputTool(taskName, stateDir) {
55032
+ function createReadOffloadedOutputTool(taskName, stateDir, stateFilePath2) {
54375
55033
  return {
54376
- description: "Read the full contents of a previously offloaded tool result by id",
55034
+ description: "Read the full contents of a previously offloaded ledger artifact by id",
54377
55035
  parametersSchema: {
54378
55036
  type: "object",
54379
55037
  properties: {
54380
55038
  id: {
54381
55039
  type: "string",
54382
- description: "Offloaded output id returned by a previous tool result"
55040
+ description: "Offloaded output or ledger artifact id returned by a previous tool result"
54383
55041
  }
54384
55042
  },
54385
55043
  required: ["id"]
@@ -54390,11 +55048,41 @@ function createReadOffloadedOutputTool(taskName, stateDir) {
54390
55048
  if (!/^[a-zA-Z0-9_-]+$/.test(outputId)) {
54391
55049
  return `Error: invalid offloaded output id: ${outputId}`;
54392
55050
  }
54393
- const outputPath = path11.join(getOffloadedOutputDir(taskName, stateDir), `${outputId}.txt`);
55051
+ const verifyContent = (content, expectedSha256) => {
55052
+ if (!expectedSha256) return content;
55053
+ const actual = createHash2("sha256").update(content).digest("hex");
55054
+ if (actual === expectedSha256) return content;
55055
+ return [
55056
+ `[Warning: artifact content no longer matches its recorded sha256 (${outputId}) \u2014 the file was modified after it was offloaded]`,
55057
+ content
55058
+ ].join("\n");
55059
+ };
55060
+ const idEmbeddedSha256 = /^art_([0-9a-f]{64})$/.exec(outputId)?.[1];
55061
+ const outputPath = path11.join(
55062
+ getOffloadedOutputDir(taskName, stateDir, stateFilePath2),
55063
+ `${outputId}.txt`
55064
+ );
54394
55065
  if (!fs10.existsSync(outputPath) || !fs10.statSync(outputPath).isFile()) {
55066
+ const resolvedStateFilePath = getStateFilePathForTask(taskName, stateDir, stateFilePath2);
55067
+ const log = loadTreeLog(treeLogPathForStateFile(resolvedStateFilePath));
55068
+ const artifact = log ? findArtifactPayload(log, outputId) : void 0;
55069
+ if (artifact) {
55070
+ const ledgerPath = path11.resolve(
55071
+ path11.dirname(treeLogPathForStateFile(resolvedStateFilePath)),
55072
+ artifact.relativePath
55073
+ );
55074
+ if (fs10.existsSync(ledgerPath) && fs10.statSync(ledgerPath).isFile()) {
55075
+ return verifyContent(fs10.readFileSync(ledgerPath, "utf-8"), artifact.sha256);
55076
+ }
55077
+ return [
55078
+ `Error: offloaded output recorded in the context ledger but missing locally: ${outputId}`,
55079
+ artifact.host ? `Stored on host: ${artifact.host}` : void 0,
55080
+ `${LEDGER_ARTIFACT_LINE_PREFIX}${artifact.relativePath}`
55081
+ ].filter(Boolean).join("\n");
55082
+ }
54395
55083
  return `Error: offloaded output not found: ${outputId}`;
54396
55084
  }
54397
- return fs10.readFileSync(outputPath, "utf-8");
55085
+ return verifyContent(fs10.readFileSync(outputPath, "utf-8"), idEmbeddedSha256);
54398
55086
  }
54399
55087
  };
54400
55088
  }
@@ -54533,19 +55221,34 @@ function buildLocalTools(client, sandboxProvider, options, context) {
54533
55221
  if (!options.noLocalTools) {
54534
55222
  Object.assign(enabledTools, createDefaultLocalTools(context));
54535
55223
  if (context) {
54536
- enabledTools.write_file = createCheckpointedWriteFileTool(context.taskName, context.stateDir, context.planPath);
54537
- enabledTools.edit_file = createEditFileTool(context.taskName, context.stateDir, context.planPath);
55224
+ enabledTools.write_file = createCheckpointedWriteFileTool(
55225
+ context.taskName,
55226
+ context.stateDir,
55227
+ context.planPath,
55228
+ context.stateFilePath
55229
+ );
55230
+ enabledTools.edit_file = createEditFileTool(
55231
+ context.taskName,
55232
+ context.stateDir,
55233
+ context.planPath,
55234
+ context.stateFilePath
55235
+ );
54538
55236
  enabledTools.restore_file_checkpoint = createRestoreFileCheckpointTool(
54539
55237
  context.taskName,
54540
- context.stateDir
55238
+ context.stateDir,
55239
+ context.stateFilePath
54541
55240
  );
54542
55241
  enabledTools.read_offloaded_output = createReadOffloadedOutputTool(
54543
55242
  context.taskName,
54544
- context.stateDir
55243
+ context.stateDir,
55244
+ context.stateFilePath
54545
55245
  );
54546
55246
  enabledTools.run_check = createRunCheckTool();
54547
- if (options.sessionSearch === true) {
54548
- enabledTools.search_session_history = createSearchSessionHistoryTool(client, context.taskName);
55247
+ if (options.sessionSearch !== false) {
55248
+ enabledTools.search_session_history = createSearchSessionHistoryTool(
55249
+ client,
55250
+ context.taskName
55251
+ );
54549
55252
  }
54550
55253
  }
54551
55254
  }
@@ -54561,9 +55264,33 @@ function buildLocalTools(client, sandboxProvider, options, context) {
54561
55264
  }
54562
55265
 
54563
55266
  // src/marathon/session-chunker.ts
55267
+ import * as fs11 from "fs";
55268
+ import * as path12 from "path";
55269
+ import {
55270
+ parseLedgerArtifactRelativePath,
55271
+ parseOffloadedOutputId
55272
+ } from "@runtypelabs/sdk";
54564
55273
  var DEFAULT_MAX_CHUNK_CHARS = 2e3;
54565
55274
  var MIN_CONTENT_LENGTH = 50;
54566
- function extractSessionChunks(snapshot, maxChunkChars = DEFAULT_MAX_CHUNK_CHARS) {
55275
+ function extractSessionChunksWithLedger(snapshot, options) {
55276
+ const maxChunkChars = options.maxChunkChars ?? DEFAULT_MAX_CHUNK_CHARS;
55277
+ const log = loadTreeLog(treeLogPathForStateFile(options.stateFilePath));
55278
+ const chunks = extractCoreSessionChunks(
55279
+ snapshot,
55280
+ maxChunkChars,
55281
+ (tool) => resolveLedgerToolResult(tool, options.stateFilePath, log)
55282
+ );
55283
+ for (const summary of options.summaries ?? []) {
55284
+ if (summary.sessionIndex !== snapshot.sessionIndex) continue;
55285
+ const content = `[Compaction summary]
55286
+ ${summary.content}`;
55287
+ if (content.length >= MIN_CONTENT_LENGTH) {
55288
+ chunks.push(...chunkText(content, "reasoning", maxChunkChars));
55289
+ }
55290
+ }
55291
+ return chunks;
55292
+ }
55293
+ function extractCoreSessionChunks(snapshot, maxChunkChars, resolveToolResult) {
54567
55294
  const chunks = [];
54568
55295
  if (snapshot.content && snapshot.content.length >= MIN_CONTENT_LENGTH) {
54569
55296
  chunks.push(...chunkText(snapshot.content, "response", maxChunkChars));
@@ -54572,15 +55299,43 @@ function extractSessionChunks(snapshot, maxChunkChars = DEFAULT_MAX_CHUNK_CHARS)
54572
55299
  chunks.push(...chunkText(snapshot.reasoning, "reasoning", maxChunkChars));
54573
55300
  }
54574
55301
  for (const tool of snapshot.tools) {
54575
- const result = typeof tool.result === "string" ? tool.result : JSON.stringify(tool.result ?? "");
55302
+ const result = resolveToolResult(tool);
54576
55303
  if (result.length >= MIN_CONTENT_LENGTH) {
54577
- chunks.push(
54578
- ...chunkText(result, "tool_output", maxChunkChars, tool.name)
54579
- );
55304
+ chunks.push(...chunkText(result, "tool_output", maxChunkChars, tool.name));
54580
55305
  }
54581
55306
  }
54582
55307
  return chunks;
54583
55308
  }
55309
+ function stringifyToolResult(result) {
55310
+ return typeof result === "string" ? result : JSON.stringify(result ?? "");
55311
+ }
55312
+ function resolveLedgerToolResult(tool, stateFilePath2, log) {
55313
+ const result = stringifyToolResult(tool.result);
55314
+ const artifact = findReferencedArtifact(result, log);
55315
+ if (!artifact) return result;
55316
+ const artifactPath = path12.resolve(
55317
+ path12.dirname(treeLogPathForStateFile(stateFilePath2)),
55318
+ artifact.relativePath
55319
+ );
55320
+ try {
55321
+ if (fs11.existsSync(artifactPath) && fs11.statSync(artifactPath).isFile()) {
55322
+ return fs11.readFileSync(artifactPath, "utf-8");
55323
+ }
55324
+ } catch {
55325
+ }
55326
+ return result;
55327
+ }
55328
+ function findReferencedArtifact(result, log) {
55329
+ if (!log) return void 0;
55330
+ const id = parseOffloadedOutputId(result);
55331
+ if (id) {
55332
+ const artifact = findArtifactPayload(log, id);
55333
+ if (artifact) return artifact;
55334
+ }
55335
+ const relativePath = parseLedgerArtifactRelativePath(result);
55336
+ if (!relativePath) return void 0;
55337
+ return log.entries.filter((entry) => entry.type === "artifact").map((entry) => entry.payload).find((payload) => payload.relativePath === relativePath);
55338
+ }
54584
55339
  function chunkText(text, type, maxChars, toolName) {
54585
55340
  if (text.length <= maxChars) {
54586
55341
  return [{ content: text, type, ...toolName ? { toolName } : {} }];
@@ -54696,14 +55451,15 @@ function createLoopDetector(options = {}) {
54696
55451
  }
54697
55452
 
54698
55453
  // src/marathon/context-offload.ts
54699
- import * as fs11 from "fs";
54700
- import * as path12 from "path";
55454
+ import * as fs12 from "fs";
55455
+ import * as path13 from "path";
55456
+ import { createHash as createHash3 } from "crypto";
55457
+ import { buildLedgerOffloadReference } from "@runtypelabs/sdk";
54701
55458
  var DEFAULT_OUTPUT_THRESHOLD = 2e3;
54702
55459
  var DEFAULT_PREVIEW_LENGTH = 200;
54703
- function buildOffloadedOutputId(toolName) {
54704
- offloadCounter += 1;
54705
- const safeToolName = toolName.replace(/[^a-zA-Z0-9_-]/g, "_");
54706
- return `${safeToolName}-${offloadCounter}`;
55460
+ function buildOffloadedOutputId(output) {
55461
+ const sha256 = createHash3("sha256").update(output).digest("hex");
55462
+ return `art_${sha256}`;
54707
55463
  }
54708
55464
  function defaultStateDir3() {
54709
55465
  return getMarathonStateDir();
@@ -54711,7 +55467,33 @@ function defaultStateDir3() {
54711
55467
  function stateSafeName4(name) {
54712
55468
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
54713
55469
  }
54714
- var offloadCounter = 0;
55470
+ function stateFilePathForTask(taskName, stateDir) {
55471
+ return path13.join(stateDir || defaultStateDir3(), `${stateSafeName4(taskName)}.json`);
55472
+ }
55473
+ function recordOffloadedArtifact(details) {
55474
+ const stateFilePath2 = details.options.ledger?.stateFilePath || stateFilePathForTask(details.taskName, details.stateDir);
55475
+ const logPath = treeLogPathForStateFile(stateFilePath2);
55476
+ try {
55477
+ const log = loadTreeLog(logPath) || createTreeLog(logPath, {
55478
+ taskName: details.taskName,
55479
+ agentId: details.options.ledger?.agentId || "unknown",
55480
+ ...details.options.ledger?.originalMessage ? { originalMessage: details.options.ledger.originalMessage } : {}
55481
+ });
55482
+ if (findArtifactPayload(log, details.outputId)) return;
55483
+ appendArtifact(log, {
55484
+ artifactId: details.outputId,
55485
+ outputId: details.outputId,
55486
+ kind: "tool_output",
55487
+ toolName: details.toolName,
55488
+ relativePath: artifactRelativePathForStateFile(stateFilePath2, details.fileName),
55489
+ contentType: "text/plain",
55490
+ sha256: details.sha256,
55491
+ byteLength: Buffer.byteLength(details.output, "utf-8"),
55492
+ charLength: details.output.length
55493
+ });
55494
+ } catch {
55495
+ }
55496
+ }
54715
55497
  function offloadToolOutput(taskName, toolName, output, options = {}, stateDir) {
54716
55498
  const threshold = options.threshold ?? DEFAULT_OUTPUT_THRESHOLD;
54717
55499
  const warnThreshold = options.warnThreshold;
@@ -54728,23 +55510,35 @@ function offloadToolOutput(taskName, toolName, output, options = {}, stateDir) {
54728
55510
  if (output.length <= threshold) {
54729
55511
  return { offloaded: false, content: output };
54730
55512
  }
54731
- const outputId = buildOffloadedOutputId(toolName);
54732
- const dir = path12.join(
54733
- stateDir || defaultStateDir3(),
54734
- stateSafeName4(taskName),
54735
- "outputs"
54736
- );
55513
+ const outputId = buildOffloadedOutputId(output);
55514
+ const sha256 = outputId.replace(/^art_/, "");
55515
+ const stateFilePath2 = options.ledger?.stateFilePath || stateFilePathForTask(taskName, stateDir);
55516
+ const dir = artifactStoreDirForStateFile(stateFilePath2);
54737
55517
  const fileName = `${outputId}.txt`;
54738
- const filePath = path12.join(dir, fileName);
54739
- fs11.mkdirSync(dir, { recursive: true });
54740
- fs11.writeFileSync(filePath, output, "utf-8");
55518
+ const filePath = path13.join(dir, fileName);
55519
+ fs12.mkdirSync(dir, { recursive: true });
55520
+ if (!fs12.existsSync(filePath)) {
55521
+ fs12.writeFileSync(filePath, output, "utf-8");
55522
+ }
55523
+ recordOffloadedArtifact({
55524
+ taskName,
55525
+ toolName,
55526
+ outputId,
55527
+ sha256,
55528
+ output,
55529
+ fileName,
55530
+ options,
55531
+ stateDir
55532
+ });
54741
55533
  const preview = output.slice(0, previewLength).replace(/\n/g, " ");
54742
- const reference = [
54743
- `[Output offloaded as ${outputId} \u2014 ${output.length.toLocaleString()} chars stored internally]`,
54744
- `Preview: ${preview}${output.length > previewLength ? "..." : ""}`,
54745
- "",
54746
- `Use read_offloaded_output with id "${outputId}" to retrieve the full output if needed.`
54747
- ].join("\n");
55534
+ const relativePath = artifactRelativePathForStateFile(stateFilePath2, fileName);
55535
+ const reference = buildLedgerOffloadReference({
55536
+ outputId,
55537
+ charLength: output.length,
55538
+ relativePath,
55539
+ preview,
55540
+ truncated: output.length > previewLength
55541
+ });
54748
55542
  options.onEvent?.({
54749
55543
  kind: "offloaded",
54750
55544
  toolName,
@@ -54909,20 +55703,20 @@ function resolveAutoCompactTokenThreshold(modelContextLength, rawThreshold, stra
54909
55703
  }
54910
55704
 
54911
55705
  // src/marathon/recipes.ts
54912
- import * as fs12 from "fs";
54913
- import * as path13 from "path";
55706
+ import * as fs13 from "fs";
55707
+ import * as path14 from "path";
54914
55708
  var RULES_DIR = ".marathon/rules";
54915
55709
  function loadRules(cwd) {
54916
55710
  const baseCwd = cwd || process.cwd();
54917
- const rulesDir = path13.resolve(baseCwd, RULES_DIR);
54918
- if (!fs12.existsSync(rulesDir)) return [];
55711
+ const rulesDir = path14.resolve(baseCwd, RULES_DIR);
55712
+ if (!fs13.existsSync(rulesDir)) return [];
54919
55713
  const rules = [];
54920
55714
  try {
54921
- const entries = fs12.readdirSync(rulesDir).filter((f2) => f2.endsWith(".md"));
55715
+ const entries = fs13.readdirSync(rulesDir).filter((f2) => f2.endsWith(".md"));
54922
55716
  for (const entry of entries) {
54923
- const filePath = path13.join(rulesDir, entry);
55717
+ const filePath = path14.join(rulesDir, entry);
54924
55718
  try {
54925
- const raw = fs12.readFileSync(filePath, "utf-8");
55719
+ const raw = fs13.readFileSync(filePath, "utf-8");
54926
55720
  const parsed = parseRuleFile(raw);
54927
55721
  rules.push({ ...parsed, filePath });
54928
55722
  } catch {
@@ -54996,41 +55790,81 @@ function resolveErrorHandlingForPhase(phase, cliFallbackModel, milestoneFallback
54996
55790
  }
54997
55791
 
54998
55792
  // src/marathon/playbook-loader.ts
54999
- import * as fs13 from "fs";
55000
- import * as path14 from "path";
55001
- import * as os4 from "os";
55793
+ import * as fs14 from "fs";
55794
+ import * as path15 from "path";
55795
+ import * as os5 from "os";
55796
+ import { pathToFileURL } from "url";
55797
+ import { createJiti } from "jiti";
55002
55798
  import micromatch from "micromatch";
55003
55799
  import { parse as parseYaml } from "yaml";
55004
- var DISCOVERY_TOOLS = /* @__PURE__ */ new Set([
55005
- "search_repo",
55006
- "glob_files",
55007
- "tree_directory",
55008
- "list_directory"
55009
- ]);
55800
+ import {
55801
+ DEFAULT_STALL_STOP_AFTER,
55802
+ compileWorkflowConfig,
55803
+ ensureDefaultWorkflowHooks,
55804
+ isWorkflowHookRef,
55805
+ registerWorkflowHook
55806
+ } from "@runtypelabs/sdk";
55010
55807
  var PLAYBOOKS_DIR = ".runtype/marathons/playbooks";
55011
55808
  function getCandidatePaths(nameOrPath, cwd) {
55012
- const home = os4.homedir();
55809
+ const home = os5.homedir();
55013
55810
  return [
55014
55811
  // Exact path
55015
- path14.resolve(cwd, nameOrPath),
55812
+ path15.resolve(cwd, nameOrPath),
55016
55813
  // Repo-level
55017
- path14.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.yaml`),
55018
- path14.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.yml`),
55019
- path14.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.json`),
55814
+ path15.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.yaml`),
55815
+ path15.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.yml`),
55816
+ path15.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.json`),
55817
+ path15.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.ts`),
55818
+ path15.resolve(cwd, PLAYBOOKS_DIR, `${nameOrPath}.mts`),
55020
55819
  // User-level
55021
- path14.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.yaml`),
55022
- path14.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.yml`),
55023
- path14.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.json`)
55820
+ path15.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.yaml`),
55821
+ path15.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.yml`),
55822
+ path15.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.json`),
55823
+ path15.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.ts`),
55824
+ path15.resolve(home, PLAYBOOKS_DIR, `${nameOrPath}.mts`)
55024
55825
  ];
55025
55826
  }
55827
+ var MODULE_PLAYBOOK_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".mts"]);
55828
+ var jitiLoader;
55829
+ async function loadModulePlaybook(filePath) {
55830
+ jitiLoader ??= createJiti(import.meta.url, { interopDefault: false });
55831
+ let mod;
55832
+ try {
55833
+ mod = await jitiLoader.import(filePath);
55834
+ } catch (error51) {
55835
+ const message = error51 instanceof Error ? error51.message : String(error51);
55836
+ throw new Error(`Failed to load TypeScript playbook at ${filePath}: ${message}`, {
55837
+ cause: error51
55838
+ });
55839
+ }
55840
+ const exported = mod.default;
55841
+ if (exported === void 0 || exported === null) {
55842
+ throw new Error(
55843
+ `TypeScript playbook at ${filePath} must have a default export: a playbook config object, or a factory function receiving { registerWorkflowHook }. Wrap it in definePlaybook(...) from @runtypelabs/sdk for type inference.`
55844
+ );
55845
+ }
55846
+ const config3 = typeof exported === "function" ? await exported({ registerWorkflowHook }) : exported;
55847
+ if (!config3 || typeof config3 !== "object" || Array.isArray(config3)) {
55848
+ throw new Error(
55849
+ `TypeScript playbook at ${filePath} did not produce a playbook config object.`
55850
+ );
55851
+ }
55852
+ return config3;
55853
+ }
55026
55854
  function parsePlaybookFile(filePath) {
55027
- const raw = fs13.readFileSync(filePath, "utf-8");
55028
- const ext = path14.extname(filePath).toLowerCase();
55855
+ const raw = fs14.readFileSync(filePath, "utf-8");
55856
+ const ext = path15.extname(filePath).toLowerCase();
55029
55857
  if (ext === ".json") {
55030
55858
  return JSON.parse(raw);
55031
55859
  }
55032
55860
  return parseYaml(raw);
55033
55861
  }
55862
+ function assertPositiveInteger(value, label, playbookName) {
55863
+ if (value === void 0) return;
55864
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
55865
+ throw new Error(`Playbook '${playbookName}': ${label} must be a positive integer`);
55866
+ }
55867
+ }
55034
55868
  function validatePlaybook(config3, filePath) {
55035
55869
  if (!config3.name) {
55036
55870
  throw new Error(`Playbook at ${filePath} is missing required 'name' field`);
@@ -55045,131 +55879,140 @@ function validatePlaybook(config3, filePath) {
55045
55879
  if (!milestone.instructions) {
55046
55880
  throw new Error(`Playbook '${config3.name}': milestone '${milestone.name}' is missing 'instructions'`);
55047
55881
  }
55882
+ if (milestone.recovery !== void 0 && typeof milestone.recovery !== "function" && !isWorkflowHookRef(milestone.recovery)) {
55883
+ const recovery = milestone.recovery;
55884
+ if (typeof recovery.message !== "string" || !recovery.message.trim()) {
55885
+ throw new Error(
55886
+ `Playbook '${config3.name}': milestone '${milestone.name}' recovery is missing 'message'`
55887
+ );
55888
+ }
55889
+ assertPositiveInteger(
55890
+ recovery.afterEmptySessions,
55891
+ `milestone '${milestone.name}' recovery.afterEmptySessions`,
55892
+ config3.name
55893
+ );
55894
+ }
55048
55895
  }
55049
- }
55050
- function interpolate(template, state) {
55051
- return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
55052
- const value = state[key];
55053
- if (value === void 0 || value === null) return `{{${key}}}`;
55054
- return String(value);
55055
- });
55056
- }
55057
- function buildIsComplete(criteria) {
55058
- if (!criteria) return () => false;
55059
- switch (criteria.type) {
55060
- case "evidence":
55061
- return (ctx) => {
55062
- const minFiles = criteria.minReadFiles ?? 1;
55063
- return (ctx.state.recentReadPaths?.length ?? 0) >= minFiles;
55064
- };
55065
- case "sessions": {
55066
- let baselineSessionCount;
55067
- return (ctx) => {
55068
- const minSessions = criteria.minSessions ?? 1;
55069
- if (baselineSessionCount === void 0) {
55070
- baselineSessionCount = ctx.state.sessions.length;
55071
- }
55072
- return ctx.state.sessions.length - baselineSessionCount >= minSessions;
55073
- };
55896
+ if (config3.stallPolicy) {
55897
+ assertPositiveInteger(config3.stallPolicy.nudgeAfter, "stallPolicy.nudgeAfter", config3.name);
55898
+ assertPositiveInteger(
55899
+ config3.stallPolicy.escalateModelAfter,
55900
+ "stallPolicy.escalateModelAfter",
55901
+ config3.name
55902
+ );
55903
+ assertPositiveInteger(config3.stallPolicy.stopAfter, "stallPolicy.stopAfter", config3.name);
55904
+ }
55905
+ if (config3.plugins !== void 0) {
55906
+ if (!Array.isArray(config3.plugins)) {
55907
+ throw new Error(`Playbook '${config3.name}': 'plugins' must be a list of relative module paths`);
55908
+ }
55909
+ for (const plugin of config3.plugins) {
55910
+ if (typeof plugin !== "string" || !plugin.trim()) {
55911
+ throw new Error(`Playbook '${config3.name}': each plugins entry must be a relative module path`);
55912
+ }
55074
55913
  }
55075
- case "planWritten":
55076
- return (ctx) => {
55077
- return ctx.trace.planWritten;
55078
- };
55079
- case "never":
55080
- default:
55081
- return () => false;
55082
55914
  }
55083
55915
  }
55084
- function buildPolicyIntercept(policy) {
55085
- if (!policy.blockedTools?.length && !policy.blockDiscoveryTools && !policy.allowedReadGlobs?.length && !policy.allowedWriteGlobs?.length && !policy.requirePlanBeforeWrite) {
55086
- return void 0;
55087
- }
55088
- const blockedSet = new Set(
55089
- (policy.blockedTools ?? []).map((t) => t.trim()).filter(Boolean)
55916
+ function collectPlaybookWarnings(config3) {
55917
+ const warnings = [];
55918
+ const anyCompletable = config3.milestones.some(
55919
+ (m2) => m2.canAcceptCompletion === true || typeof m2.canAcceptCompletion === "function" || isWorkflowHookRef(m2.canAcceptCompletion)
55090
55920
  );
55091
- const readGlobs = policy.allowedReadGlobs ?? [];
55092
- const writeGlobs = policy.allowedWriteGlobs ?? [];
55093
- return (toolName, args, ctx) => {
55094
- if (blockedSet.has(toolName)) {
55095
- return `Blocked by playbook policy: ${toolName} is not allowed for this task.`;
55096
- }
55097
- if (policy.blockDiscoveryTools && DISCOVERY_TOOLS.has(toolName)) {
55098
- return `Blocked by playbook policy: discovery tools are disabled for this task.`;
55099
- }
55100
- const pathArg = typeof args.path === "string" && args.path.trim() ? ctx.normalizePath(String(args.path)) : void 0;
55101
- if (pathArg) {
55102
- const isWrite = toolName === "write_file" || toolName === "restore_file_checkpoint";
55103
- const isRead = toolName === "read_file";
55104
- if (isRead && readGlobs.length > 0) {
55105
- const allowed = micromatch.some(pathArg, readGlobs, { dot: true });
55106
- if (!allowed) {
55107
- return `Blocked by playbook policy: ${toolName} path "${pathArg}" is outside allowed read globs: ${readGlobs.join(", ")}`;
55108
- }
55109
- }
55110
- if (isWrite && writeGlobs.length > 0) {
55111
- const planPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
55112
- if (planPath && pathArg === planPath) {
55113
- } else {
55114
- const allowed = micromatch.some(pathArg, writeGlobs, { dot: true });
55115
- if (!allowed) {
55116
- return `Blocked by playbook policy: ${toolName} path "${pathArg}" is outside allowed write globs: ${writeGlobs.join(", ")}`;
55117
- }
55118
- }
55119
- }
55120
- if (isWrite && policy.requirePlanBeforeWrite && !ctx.state.planWritten && !ctx.trace.planWritten) {
55121
- const planPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
55122
- if (!planPath || pathArg !== planPath) {
55123
- return `Blocked by playbook policy: write the plan before creating other files.`;
55124
- }
55125
- }
55921
+ if (!anyCompletable) {
55922
+ warnings.push(
55923
+ `Playbook '${config3.name}': no milestone sets canAcceptCompletion: true \u2014 TASK_COMPLETE will never be accepted and the run can only end by stalling or exhausting its budget. Set it on the final milestone.`
55924
+ );
55925
+ }
55926
+ const escalateAfter = config3.stallPolicy?.escalateModelAfter;
55927
+ if (escalateAfter !== void 0) {
55928
+ const anyFallbacks = config3.milestones.some((m2) => m2.fallbackModels?.length);
55929
+ if (!anyFallbacks) {
55930
+ warnings.push(
55931
+ `Playbook '${config3.name}': stallPolicy.escalateModelAfter is set but no milestone defines fallbackModels \u2014 the escalation signal will have no model to switch to.`
55932
+ );
55126
55933
  }
55127
- return void 0;
55128
- };
55934
+ const stopAfter = config3.stallPolicy?.stopAfter ?? DEFAULT_STALL_STOP_AFTER;
55935
+ if (escalateAfter >= stopAfter) {
55936
+ warnings.push(
55937
+ `Playbook '${config3.name}': stallPolicy.escalateModelAfter (${escalateAfter}) is not below stopAfter (${stopAfter}) \u2014 the run will stall before model escalation can fire.`
55938
+ );
55939
+ }
55940
+ }
55941
+ return warnings;
55129
55942
  }
55130
- function convertToWorkflow(config3) {
55131
- const policyIntercept = config3.policy ? buildPolicyIntercept(config3.policy) : void 0;
55132
- const phases = config3.milestones.map((milestone) => ({
55943
+ var PLUGIN_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs"]);
55944
+ async function loadPlaybookPlugins(plugins, playbookFilePath, playbookName) {
55945
+ if (!plugins?.length) return;
55946
+ const baseDir = path15.dirname(playbookFilePath);
55947
+ for (const plugin of plugins) {
55948
+ if (path15.isAbsolute(plugin)) {
55949
+ throw new Error(
55950
+ `Playbook '${playbookName}': plugin "${plugin}" must be a relative path (resolved against the playbook's directory).`
55951
+ );
55952
+ }
55953
+ const resolved = path15.resolve(baseDir, plugin);
55954
+ if (resolved !== baseDir && !resolved.startsWith(baseDir + path15.sep)) {
55955
+ throw new Error(
55956
+ `Playbook '${playbookName}': plugin "${plugin}" resolves outside the playbook's directory. Keep plugin modules next to the playbook.`
55957
+ );
55958
+ }
55959
+ if (!PLUGIN_EXTENSIONS.has(path15.extname(resolved).toLowerCase())) {
55960
+ throw new Error(
55961
+ `Playbook '${playbookName}': plugin "${plugin}" must be a .js, .mjs, or .cjs module.`
55962
+ );
55963
+ }
55964
+ if (!fs14.existsSync(resolved)) {
55965
+ throw new Error(`Playbook '${playbookName}': plugin "${plugin}" not found at ${resolved}.`);
55966
+ }
55967
+ const mod = await import(pathToFileURL(resolved).href);
55968
+ if (typeof mod.default !== "function") {
55969
+ throw new Error(
55970
+ `Playbook '${playbookName}': plugin "${plugin}" must export a default function: export default ({ registerWorkflowHook }) => { ... }`
55971
+ );
55972
+ }
55973
+ await mod.default({ registerWorkflowHook });
55974
+ }
55975
+ }
55976
+ function toWorkflowConfig(config3) {
55977
+ const milestones = config3.milestones.map((milestone) => ({
55133
55978
  name: milestone.name,
55134
- description: milestone.description,
55135
- buildInstructions(state) {
55136
- const header = `--- Workflow Phase: ${milestone.name} ---`;
55137
- const desc = milestone.description ? `
55138
- ${milestone.description}` : "";
55139
- const instructions = interpolate(milestone.instructions, state);
55140
- return `${header}${desc}
55141
- ${instructions}`;
55142
- },
55143
- buildToolGuidance(_state) {
55144
- return milestone.toolGuidance ?? [];
55145
- },
55146
- isComplete: buildIsComplete(milestone.completionCriteria),
55147
- interceptToolCall: policyIntercept,
55148
- // Default to rejecting TASK_COMPLETE unless the playbook explicitly allows it.
55149
- // The SDK accepts completion by default when canAcceptCompletion is undefined,
55150
- // which would let the model end the marathon prematurely in early phases.
55151
- canAcceptCompletion: milestone.canAcceptCompletion !== void 0 ? () => milestone.canAcceptCompletion : () => false
55979
+ ...milestone.description !== void 0 ? { description: milestone.description } : {},
55980
+ instructions: milestone.instructions,
55981
+ ...milestone.toolGuidance !== void 0 ? { toolGuidance: milestone.toolGuidance } : {},
55982
+ ...milestone.completionCriteria ? { completionCriteria: milestone.completionCriteria } : {},
55983
+ ...milestone.recovery !== void 0 ? { recovery: milestone.recovery } : {},
55984
+ ...milestone.transitionSummary !== void 0 ? { transitionSummary: milestone.transitionSummary } : {},
55985
+ ...milestone.intercept ? { intercept: milestone.intercept } : {},
55986
+ ...milestone.forceEndTurn ? { forceEndTurn: milestone.forceEndTurn } : {},
55987
+ // Playbooks reject TASK_COMPLETE unless explicitly allowed — the SDK
55988
+ // accepts completion when the slot is absent, which would let the model
55989
+ // end the marathon prematurely in early milestones.
55990
+ canAcceptCompletion: milestone.canAcceptCompletion ?? false
55152
55991
  }));
55153
55992
  return {
55154
55993
  name: config3.name,
55155
- phases
55156
- };
55157
- }
55158
- function normalizeFallbackModel(input) {
55159
- if (typeof input === "string") return { model: input };
55160
- return {
55161
- model: input.model,
55162
- ...input.temperature !== void 0 ? { temperature: input.temperature } : {},
55163
- ...input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {}
55994
+ ...config3.description !== void 0 ? { description: config3.description } : {},
55995
+ ...config3.stallPolicy ? { stallPolicy: config3.stallPolicy } : {},
55996
+ ...config3.policy ? { policy: config3.policy } : {},
55997
+ ...config3.classifyVariant ? { classifyVariant: config3.classifyVariant } : {},
55998
+ ...config3.bootstrap ? { bootstrap: config3.bootstrap } : {},
55999
+ ...config3.candidateBlock ? { candidateBlock: config3.candidateBlock } : {},
56000
+ milestones
55164
56001
  };
55165
56002
  }
55166
- function loadPlaybook(nameOrPath, cwd) {
56003
+ async function loadPlaybook(nameOrPath, cwd) {
55167
56004
  const baseCwd = cwd || process.cwd();
55168
56005
  const candidates = getCandidatePaths(nameOrPath, baseCwd);
55169
56006
  for (const candidate of candidates) {
55170
- if (!fs13.existsSync(candidate) || fs13.statSync(candidate).isDirectory()) continue;
55171
- const config3 = parsePlaybookFile(candidate);
56007
+ if (!fs14.existsSync(candidate) || fs14.statSync(candidate).isDirectory()) continue;
56008
+ const ext = path15.extname(candidate).toLowerCase();
56009
+ const config3 = MODULE_PLAYBOOK_EXTENSIONS.has(ext) ? await loadModulePlaybook(candidate) : parsePlaybookFile(candidate);
55172
56010
  validatePlaybook(config3, candidate);
56011
+ await loadPlaybookPlugins(config3.plugins, candidate, config3.name);
56012
+ ensureDefaultWorkflowHooks();
56013
+ const workflow = compileWorkflowConfig(toWorkflowConfig(config3), {
56014
+ matchPathGlobs: (filePath, globs) => micromatch.some(filePath, globs, { dot: true })
56015
+ });
55173
56016
  const milestoneModels = {};
55174
56017
  const milestoneFallbackModels = {};
55175
56018
  for (const m2 of config3.milestones) {
@@ -55179,13 +56022,14 @@ function loadPlaybook(nameOrPath, cwd) {
55179
56022
  }
55180
56023
  }
55181
56024
  return {
55182
- workflow: convertToWorkflow(config3),
56025
+ workflow,
55183
56026
  milestones: config3.milestones.map((m2) => m2.name),
55184
56027
  milestoneModels: Object.keys(milestoneModels).length > 0 ? milestoneModels : void 0,
55185
56028
  milestoneFallbackModels: Object.keys(milestoneFallbackModels).length > 0 ? milestoneFallbackModels : void 0,
55186
56029
  verification: config3.verification,
55187
56030
  rules: config3.rules,
55188
- policy: config3.policy
56031
+ policy: config3.policy,
56032
+ warnings: collectPlaybookWarnings(config3)
55189
56033
  };
55190
56034
  }
55191
56035
  throw new Error(
@@ -55193,6 +56037,14 @@ function loadPlaybook(nameOrPath, cwd) {
55193
56037
  ${candidates.map((c2) => ` ${c2}`).join("\n")}`
55194
56038
  );
55195
56039
  }
56040
+ function normalizeFallbackModel(input) {
56041
+ if (typeof input === "string") return { model: input };
56042
+ return {
56043
+ model: input.model,
56044
+ ...input.temperature !== void 0 ? { temperature: input.temperature } : {},
56045
+ ...input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {}
56046
+ };
56047
+ }
55196
56048
 
55197
56049
  // src/commands/agents-task.ts
55198
56050
  function shouldRequestResumeCheckpoint(status, resumeMessage, noCheckpoint, originalMessage, continuations) {
@@ -55352,7 +56204,9 @@ function normalizeMarathonAgentArgument(agent) {
55352
56204
  }
55353
56205
  function buildMarathonAutoCreatedAgentBootstrap(agentName, options = {}) {
55354
56206
  const normalizedModel = options.model?.trim();
55355
- const normalizedToolIds = [...new Set((options.toolIds || []).map((toolId) => toolId.trim()).filter(Boolean))];
56207
+ const normalizedToolIds = [
56208
+ ...new Set((options.toolIds || []).map((toolId) => toolId.trim()).filter(Boolean))
56209
+ ];
55356
56210
  const normalizedFallbackModel = options.fallbackModel?.trim();
55357
56211
  const errorHandling = normalizedFallbackModel ? {
55358
56212
  onError: "fallback",
@@ -55428,7 +56282,11 @@ async function taskAction(agent, options) {
55428
56282
  });
55429
56283
  let parsedSandbox = parseSandboxProvider(options.sandbox);
55430
56284
  if (options.sandbox && !parsedSandbox) {
55431
- console.error(chalk23.red(`Invalid --sandbox value "${options.sandbox}". Use: cloudflare-worker, runtype-sandbox, quickjs, or daytona`));
56285
+ console.error(
56286
+ chalk23.red(
56287
+ `Invalid --sandbox value "${options.sandbox}". Use: cloudflare-worker, runtype-sandbox, quickjs, or daytona`
56288
+ )
56289
+ );
55432
56290
  process.exit(1);
55433
56291
  }
55434
56292
  let requestedCompactStrategy;
@@ -55442,11 +56300,9 @@ async function taskAction(agent, options) {
55442
56300
  const rulesContext = rules.length > 0 ? rules.map((r) => r.content).join("\n\n---\n\n") : "";
55443
56301
  const allModels = [
55444
56302
  ...new Set(
55445
- [
55446
- options.model,
55447
- options.planningModel,
55448
- options.executionModel
55449
- ].filter((m2) => Boolean(m2))
56303
+ [options.model, options.planningModel, options.executionModel].filter(
56304
+ (m2) => Boolean(m2)
56305
+ )
55450
56306
  )
55451
56307
  ];
55452
56308
  let resolvedToolIds = [];
@@ -55488,7 +56344,7 @@ async function taskAction(agent, options) {
55488
56344
  waitForUiExit = renderedShell.waitUntilExit;
55489
56345
  rerenderUi = renderedShell.rerender;
55490
56346
  unmountUi = renderedShell.unmount;
55491
- await new Promise((resolve10) => setTimeout(resolve10, 0));
56347
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
55492
56348
  if (!startupShellRef.current) {
55493
56349
  exitAltScreen();
55494
56350
  unmountUi?.();
@@ -55565,10 +56421,7 @@ async function taskAction(agent, options) {
55565
56421
  await failBeforeMain(formatMarathonApiError(error51));
55566
56422
  }
55567
56423
  const errMsg = error51 instanceof Error ? error51.message : String(error51);
55568
- await failBeforeMain([
55569
- chalk23.red("Failed to list agents"),
55570
- chalk23.red(errMsg)
55571
- ]);
56424
+ await failBeforeMain([chalk23.red("Failed to list agents"), chalk23.red(errMsg)]);
55572
56425
  }
55573
56426
  }
55574
56427
  let agentConfigModel;
@@ -55617,7 +56470,7 @@ async function taskAction(agent, options) {
55617
56470
  forcedResumeFilePath = stateResolution.filePath;
55618
56471
  } else {
55619
56472
  resumeRequested = false;
55620
- if (options.fresh && fs14.existsSync(filePath)) {
56473
+ if (options.fresh && fs15.existsSync(filePath)) {
55621
56474
  if (useStartupShell) {
55622
56475
  setStartupStatus("starting fresh");
55623
56476
  } else {
@@ -55732,12 +56585,19 @@ async function taskAction(agent, options) {
55732
56585
  let playbookMilestoneFallbackModels;
55733
56586
  let playbookPolicy;
55734
56587
  if (options.playbook) {
55735
- const result = loadPlaybook(options.playbook);
56588
+ const result = await loadPlaybook(options.playbook);
55736
56589
  playbookWorkflow = result.workflow;
55737
56590
  playbookMilestones = result.milestones;
55738
56591
  playbookMilestoneModels = result.milestoneModels;
55739
56592
  playbookMilestoneFallbackModels = result.milestoneFallbackModels;
55740
56593
  playbookPolicy = result.policy;
56594
+ for (const warning of result.warnings) {
56595
+ if (useStartupShell) {
56596
+ setStartupStatus(`playbook warning: ${warning}`);
56597
+ } else {
56598
+ console.log(chalk23.yellow(`Playbook warning: ${warning}`));
56599
+ }
56600
+ }
55741
56601
  } else {
55742
56602
  playbookPolicy = void 0;
55743
56603
  }
@@ -55757,7 +56617,10 @@ async function taskAction(agent, options) {
55757
56617
  if (firstMilestoneModel) options.model = firstMilestoneModel;
55758
56618
  confirmed = true;
55759
56619
  } else if (confirmResult.action === "edit" && confirmResult.editMilestone) {
55760
- let startupModelOptions = buildMarathonStartupModelOptions(configuredModels, availableModels);
56620
+ let startupModelOptions = buildMarathonStartupModelOptions(
56621
+ configuredModels,
56622
+ availableModels
56623
+ );
55761
56624
  if (startupModelOptions.length === 0) {
55762
56625
  startupModelOptions = DEFAULT_MODELS;
55763
56626
  }
@@ -55831,11 +56694,15 @@ ${sandboxPrompt}`;
55831
56694
 
55832
56695
  ${rulesContext}`;
55833
56696
  const currentPhase = resumeState?.workflowPhase;
55834
- const resolvedModel = resolveModelForPhase(currentPhase, {
55835
- planningModel: options.planningModel,
55836
- executionModel: options.executionModel,
55837
- defaultModel: options.model
55838
- }, playbookMilestoneModels);
56697
+ const resolvedModel = resolveModelForPhase(
56698
+ currentPhase,
56699
+ {
56700
+ planningModel: options.planningModel,
56701
+ executionModel: options.executionModel,
56702
+ defaultModel: options.model
56703
+ },
56704
+ playbookMilestoneModels
56705
+ );
55839
56706
  if (resolvedModel) options.model = resolvedModel;
55840
56707
  if (autoCreatedAgent) {
55841
56708
  const bootstrapPayload = buildMarathonAutoCreatedAgentBootstrap(normalizedAgent, {
@@ -55872,6 +56739,7 @@ ${rulesContext}`;
55872
56739
  let localTools = buildLocalTools(client, parsedSandbox, options, {
55873
56740
  taskName,
55874
56741
  stateDir: options.stateDir,
56742
+ stateFilePath: filePath,
55875
56743
  planPath: resolvedPlanPath
55876
56744
  });
55877
56745
  const resolveContextLimitForModel = (modelId) => resolveModelContextLength(modelId, configuredModels, availableModels);
@@ -55894,16 +56762,21 @@ ${rulesContext}`;
55894
56762
  const reportContextNotice = (event) => {
55895
56763
  streamRef.current?.reportContextNotice(event);
55896
56764
  };
55897
- if (localTools && offloadOptions) {
55898
- const toolNames = Object.keys(localTools);
55899
- for (const toolName of toolNames) {
56765
+ const applyOffloadWrapping = (tools) => {
56766
+ if (!tools || !offloadOptions) return tools;
56767
+ for (const toolName of Object.keys(tools)) {
55900
56768
  if (toolName === "search_repo" || toolName === "read_file" || toolName === "glob_files" || toolName === "tree_directory" || toolName === "list_directory") {
55901
- localTools[toolName] = withOffloading(
55902
- localTools[toolName],
56769
+ tools[toolName] = withOffloading(
56770
+ tools[toolName],
55903
56771
  taskName,
55904
56772
  toolName,
55905
56773
  {
55906
56774
  ...offloadOptions,
56775
+ ledger: {
56776
+ stateFilePath: filePath,
56777
+ agentId,
56778
+ originalMessage: baseMessage
56779
+ },
55907
56780
  onEvent: (event) => {
55908
56781
  if (event.kind === "warning") {
55909
56782
  reportContextNotice({
@@ -55927,14 +56800,19 @@ ${rulesContext}`;
55927
56800
  );
55928
56801
  }
55929
56802
  }
55930
- }
56803
+ return tools;
56804
+ };
56805
+ localTools = applyOffloadWrapping(localTools);
55931
56806
  let toolsEnabled = true;
55932
56807
  const checkpointHasConfigChanges = (result) => Boolean(result.model) || result.tools === true || result.sandbox !== void 0;
55933
- const rebuildCheckpointTools = () => buildLocalTools(client, parsedSandbox, options, {
55934
- taskName,
55935
- stateDir: options.stateDir,
55936
- planPath: resolvedPlanPath
55937
- });
56808
+ const rebuildCheckpointTools = () => applyOffloadWrapping(
56809
+ buildLocalTools(client, parsedSandbox, options, {
56810
+ taskName,
56811
+ stateDir: options.stateDir,
56812
+ stateFilePath: filePath,
56813
+ planPath: resolvedPlanPath
56814
+ })
56815
+ );
55938
56816
  const applyCheckpointConfig = (result) => {
55939
56817
  if (result.model) {
55940
56818
  options.model = result.model;
@@ -55961,6 +56839,7 @@ ${rulesContext}`;
55961
56839
  let lastKnownState = null;
55962
56840
  try {
55963
56841
  const marathonDashboardBaseUrl = getDashboardUrl().replace(/\/$/, "");
56842
+ const turnAbortRef = { current: null };
55964
56843
  const marathonAppProps = {
55965
56844
  taskName,
55966
56845
  agentId,
@@ -55999,7 +56878,9 @@ ${rulesContext}`;
55999
56878
  sessions: persistedSessionSummaries,
56000
56879
  startedAt: lastKnownState?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
56001
56880
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
56002
- ...persistedSessionSnapshots.length > 0 || payload.sessionSnapshots.length > 0 ? { sessionSnapshots: payload.sessionSnapshots.length > 0 ? payload.sessionSnapshots : persistedSessionSnapshots } : {},
56881
+ ...persistedSessionSnapshots.length > 0 || payload.sessionSnapshots.length > 0 ? {
56882
+ sessionSnapshots: payload.sessionSnapshots.length > 0 ? payload.sessionSnapshots : persistedSessionSnapshots
56883
+ } : {},
56003
56884
  ...priorContinuations.length > 0 ? { continuations: priorContinuations } : {},
56004
56885
  ...Object.keys(priorCostByModel).length > 0 ? { costByModel: priorCostByModel } : {},
56005
56886
  ...priorOriginalMessage ? { originalMessage: priorOriginalMessage } : {},
@@ -56012,6 +56893,14 @@ Saving state... done. Session saved to ${filePath}`);
56012
56893
  },
56013
56894
  onComplete: () => {
56014
56895
  },
56896
+ onAbortTurn: () => {
56897
+ const controller = turnAbortRef.current;
56898
+ if (controller && !controller.signal.aborted) {
56899
+ controller.abort();
56900
+ return true;
56901
+ }
56902
+ return false;
56903
+ },
56015
56904
  streamRef
56016
56905
  };
56017
56906
  setMarathonTitle();
@@ -56027,14 +56916,13 @@ Saving state... done. Session saved to ${filePath}`);
56027
56916
  await startupShellRef.current?.completeStartup();
56028
56917
  } else {
56029
56918
  exitAltScreen = enterAltScreen();
56030
- const renderedApp = render15(
56031
- React15.createElement(MarathonApp, marathonAppProps),
56032
- { exitOnCtrlC: false }
56033
- );
56919
+ const renderedApp = render15(React15.createElement(MarathonApp, marathonAppProps), {
56920
+ exitOnCtrlC: false
56921
+ });
56034
56922
  waitForUiExit = renderedApp.waitUntilExit;
56035
56923
  unmountUi = renderedApp.unmount;
56036
56924
  }
56037
- await new Promise((resolve10) => setTimeout(resolve10, 0));
56925
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
56038
56926
  const streamActions = streamRef.current;
56039
56927
  if (!streamActions) {
56040
56928
  exitAltScreen();
@@ -56085,6 +56973,20 @@ Saving state... done. Session saved to ${filePath}`);
56085
56973
  break;
56086
56974
  }
56087
56975
  }
56976
+ const stallEscalationUsedModels = /* @__PURE__ */ new Map();
56977
+ const pickNextStallFallbackModel = (phase, currentModel) => {
56978
+ if (!phase) return void 0;
56979
+ const chain = [
56980
+ ...playbookMilestoneFallbackModels?.[phase]?.map((fb) => fb.model) ?? [],
56981
+ ...options.fallbackModel ? [options.fallbackModel] : []
56982
+ ];
56983
+ const used = stallEscalationUsedModels.get(phase) ?? /* @__PURE__ */ new Set();
56984
+ const next = chain.find((model) => model !== currentModel && !used.has(model));
56985
+ if (!next) return void 0;
56986
+ used.add(next);
56987
+ stallEscalationUsedModels.set(phase, used);
56988
+ return next;
56989
+ };
56088
56990
  let shouldContinue = true;
56089
56991
  let accumulatedSessions = 0;
56090
56992
  let accumulatedCost = 0;
@@ -56092,6 +56994,7 @@ Saving state... done. Session saved to ${filePath}`);
56092
56994
  let accumulatedToolCalls = 0;
56093
56995
  let lastResult = null;
56094
56996
  let lastSessionMessages = [];
56997
+ let undeliveredSteering = [];
56095
56998
  if (resumeLoadedState) {
56096
56999
  const continuationStartedAt = (/* @__PURE__ */ new Date()).toISOString();
56097
57000
  const continuation = {
@@ -56133,14 +57036,18 @@ Saving state... done. Session saved to ${filePath}`);
56133
57036
  const effectiveModelForContext = phaseModel || options.model || agentConfigModel || defaultConfiguredModel;
56134
57037
  const compactStrategy = resolveCompactStrategyForModel(effectiveModelForContext);
56135
57038
  const contextLimitTokens = resolveContextLimitForModel(effectiveModelForContext);
56136
- const autoCompactTokenThreshold = resolveCompactThresholdForModel(
56137
- effectiveModelForContext
57039
+ const autoCompactTokenThreshold = resolveCompactThresholdForModel(effectiveModelForContext);
57040
+ const existingContextSummaryIds = new Set(
57041
+ (resumeState?.contextCompactionSummaries ?? []).map((summary) => summary.id)
56138
57042
  );
57043
+ const turnAbortController = new AbortController();
57044
+ turnAbortRef.current = turnAbortController;
56139
57045
  const runTaskOptions = {
56140
57046
  message: taskMessage,
56141
57047
  maxSessions: remainingSessions - accumulatedSessions,
56142
57048
  maxCost: currentRemainingCost,
56143
57049
  model: phaseModel || options.model,
57050
+ abortSignal: turnAbortController.signal,
56144
57051
  reasoning: !options.noReasoning,
56145
57052
  debugMode: options.debug ?? true,
56146
57053
  stream: true,
@@ -56174,7 +57081,7 @@ Saving state... done. Session saved to ${filePath}`);
56174
57081
  };
56175
57082
  if (event.phase === "start") {
56176
57083
  currentActions.startContextCompaction(absoluteEvent);
56177
- await new Promise((resolve10) => setTimeout(resolve10, 0));
57084
+ await new Promise((resolve11) => setTimeout(resolve11, 0));
56178
57085
  return;
56179
57086
  }
56180
57087
  currentActions.finishContextCompaction(absoluteEvent);
@@ -56227,11 +57134,17 @@ Saving state... done. Session saved to ${filePath}`);
56227
57134
  );
56228
57135
  currentActions.appendSessionSnapshot(sessionSnapshot);
56229
57136
  }
57137
+ const contextCompactionSummaries = offsetNewContextCompactionSummaries(
57138
+ state.contextCompactionSummaries,
57139
+ existingContextSummaryIds,
57140
+ currentSessionOffset
57141
+ );
56230
57142
  const adjustedState = {
56231
57143
  ...state,
56232
57144
  sessionCount: currentSessionOffset + state.sessionCount,
56233
57145
  totalCost: priorCost + accumulatedCost + state.totalCost,
56234
57146
  sessions: persistedSessionSummaries,
57147
+ ...contextCompactionSummaries?.length ? { contextCompactionSummaries } : {},
56235
57148
  ...persistedSessionSnapshots.length > 0 ? { sessionSnapshots: persistedSessionSnapshots } : {},
56236
57149
  ...getActiveDeploySandboxId() ? { deploySandboxId: getActiveDeploySandboxId() } : {},
56237
57150
  ...getActiveDeploySandboxPreviewUrl() ? { deploySandboxPreviewUrl: getActiveDeploySandboxPreviewUrl() } : {}
@@ -56240,10 +57153,13 @@ Saving state... done. Session saved to ${filePath}`);
56240
57153
  resumeState = extractRunTaskResumeState(adjustedState);
56241
57154
  lastSessionMessages = state.messages ?? [];
56242
57155
  saveState(filePath, adjustedState, { stripSnapshotEvents: !!eventLogWriter });
56243
- if (options.sessionSearch === true) {
57156
+ if (options.sessionSearch !== false) {
56244
57157
  const latestSnapshot = persistedSessionSnapshots[persistedSessionSnapshots.length - 1];
56245
57158
  if (latestSnapshot) {
56246
- const chunks = extractSessionChunks(latestSnapshot);
57159
+ const chunks = extractSessionChunksWithLedger(latestSnapshot, {
57160
+ stateFilePath: filePath,
57161
+ summaries: adjustedState.contextCompactionSummaries
57162
+ });
56247
57163
  if (chunks.length > 0) {
56248
57164
  const sessionIdx = currentSessionOffset + state.sessionCount - 1;
56249
57165
  client.post("/session-context/index", {
@@ -56286,6 +57202,20 @@ Saving state... done. Session saved to ${filePath}`);
56286
57202
  });
56287
57203
  }
56288
57204
  }
57205
+ if (state.stallEscalationRequested && state.status === "running") {
57206
+ const escalationPhase = state.workflowPhase;
57207
+ const activeModel = phaseModel || options.model;
57208
+ const nextModel = pickNextStallFallbackModel(escalationPhase, activeModel);
57209
+ if (escalationPhase && nextModel) {
57210
+ playbookMilestoneModels = {
57211
+ ...playbookMilestoneModels ?? {},
57212
+ [escalationPhase]: nextModel
57213
+ };
57214
+ options.model = nextModel;
57215
+ shouldContinue = true;
57216
+ return false;
57217
+ }
57218
+ }
56289
57219
  if (state.recentActionKeys && state.recentActionKeys.length > 0) {
56290
57220
  for (const key of state.recentActionKeys) {
56291
57221
  loopDetector.recordAction(key);
@@ -56348,17 +57278,21 @@ Saving state... done. Session saved to ${filePath}`);
56348
57278
  if (resumeRequested) {
56349
57279
  streamActions.markPendingStart();
56350
57280
  }
56351
- const result2 = await retryOnNetworkError(
56352
- () => client.agents.runTask(agentId, runTaskOptions),
56353
- {
57281
+ let result2;
57282
+ try {
57283
+ result2 = await retryOnNetworkError(() => client.agents.runTask(agentId, runTaskOptions), {
56354
57284
  maxRetries: 3,
56355
57285
  baseDelayMs: 5e3,
56356
57286
  maxDelayMs: 6e4,
57287
+ // A user hard abort surfaces as an AbortError — never retry it
57288
+ signal: turnAbortController.signal,
56357
57289
  onRetry: (attempt, delayMs, error51) => {
56358
57290
  const delaySec = Math.round(delayMs / 1e3);
56359
57291
  const msg = error51 instanceof Error ? error51.message : String(error51);
56360
57292
  console.error(
56361
- chalk23.yellow(`Network error (attempt ${attempt}/3): ${msg}. Retrying in ${delaySec}s...`)
57293
+ chalk23.yellow(
57294
+ `Network error (attempt ${attempt}/3): ${msg}. Retrying in ${delaySec}s...`
57295
+ )
56362
57296
  );
56363
57297
  if (lastKnownState) {
56364
57298
  previousMessages = lastSessionMessages;
@@ -56369,8 +57303,23 @@ Saving state... done. Session saved to ${filePath}`);
56369
57303
  runTaskOptions.compact = false;
56370
57304
  }
56371
57305
  }
56372
- }
56373
- );
57306
+ });
57307
+ } catch (error51) {
57308
+ if (!turnAbortController.signal.aborted) throw error51;
57309
+ const knownState2 = lastKnownState;
57310
+ result2 = {
57311
+ status: "paused",
57312
+ sessionCount: Math.max(
57313
+ 0,
57314
+ (knownState2?.sessionCount ?? currentSessionOffset) - currentSessionOffset
57315
+ ),
57316
+ totalCost: Math.max(0, (knownState2?.totalCost ?? 0) - (priorCost + accumulatedCost)),
57317
+ lastOutput: knownState2?.lastOutput ?? "",
57318
+ sessions: []
57319
+ };
57320
+ }
57321
+ const wasAborted = turnAbortController.signal.aborted;
57322
+ turnAbortRef.current = null;
56374
57323
  persistedSessionSummaries = mergeMarathonSessionSummaries(
56375
57324
  persistedSessionSummaries,
56376
57325
  result2.sessions,
@@ -56385,7 +57334,7 @@ Saving state... done. Session saved to ${filePath}`);
56385
57334
  const completedTools = existingSnapshot.tools.map(
56386
57335
  (t) => t.status === "running" ? { ...t, status: "complete", executionTime: Date.now() - t.startedAt } : t
56387
57336
  );
56388
- const finalStatus = mapRunTaskStatusToSnapshotStatus(result2.status, existingSnapshot.status);
57337
+ const finalStatus = wasAborted ? "stopped" : mapRunTaskStatusToSnapshotStatus(result2.status, existingSnapshot.status);
56389
57338
  const updatedSnapshot = {
56390
57339
  ...existingSnapshot,
56391
57340
  status: finalStatus,
@@ -56396,7 +57345,10 @@ Saving state... done. Session saved to ${filePath}`);
56396
57345
  tools: completedTools,
56397
57346
  ...finalStatus === "error" && lastKnownState?.lastError ? { errorMessage: lastKnownState.lastError } : {}
56398
57347
  };
56399
- persistedSessionSnapshots = upsertMarathonSessionSnapshot(persistedSessionSnapshots, updatedSnapshot);
57348
+ persistedSessionSnapshots = upsertMarathonSessionSnapshot(
57349
+ persistedSessionSnapshots,
57350
+ updatedSnapshot
57351
+ );
56400
57352
  streamRef.current?.appendSessionSnapshot(updatedSnapshot);
56401
57353
  }
56402
57354
  }
@@ -56419,11 +57371,16 @@ Saving state... done. Session saved to ${filePath}`);
56419
57371
  useCompact = false;
56420
57372
  resumeState = extractRunTaskResumeState(lastKnownState);
56421
57373
  }
56422
- if (result2.status === "complete" || result2.status === "budget_exceeded" || result2.status === "max_sessions") {
56423
- if (options.noCheckpoint) break;
57374
+ if (wasAborted || result2.status === "complete" || result2.status === "budget_exceeded" || result2.status === "max_sessions") {
57375
+ if (options.noCheckpoint) {
57376
+ if (wasAborted) {
57377
+ undeliveredSteering = streamRef.current?.drainSteeringQueue?.() ?? [];
57378
+ }
57379
+ break;
57380
+ }
56424
57381
  const currentActions = streamRef.current;
56425
57382
  if (!currentActions) break;
56426
- const queuedFollowUps = currentActions.drainFollowUpQueue?.();
57383
+ const queuedFollowUps = wasAborted ? void 0 : currentActions.drainFollowUpQueue?.();
56427
57384
  if (queuedFollowUps && queuedFollowUps.length > 0) {
56428
57385
  currentActions.resetForNewSession();
56429
57386
  taskMessage = queuedFollowUps.join("\n\n");
@@ -56533,6 +57490,18 @@ Saving state... done. Session saved to ${filePath}`);
56533
57490
  if (typeof finalState.lastError === "string" && finalState.lastError.trim()) {
56534
57491
  console.log(`Last error: ${chalk23.red(finalState.lastError)}`);
56535
57492
  }
57493
+ if (undeliveredSteering.length > 0) {
57494
+ console.log(
57495
+ chalk23.yellow(
57496
+ `
57497
+ Undelivered steering (${undeliveredSteering.length} message${undeliveredSteering.length === 1 ? "" : "s"} queued before the abort):`
57498
+ )
57499
+ );
57500
+ for (const message of undeliveredSteering) {
57501
+ console.log(chalk23.gray(` - ${message}`));
57502
+ }
57503
+ console.log(chalk23.gray(' Include it when resuming, e.g. --resume "<message>".'));
57504
+ }
56536
57505
  const dashboardBaseUrl = getDashboardUrl();
56537
57506
  console.log(`Dashboard: ${chalk23.cyan(`${dashboardBaseUrl}/agents/${agentId}`)}`);
56538
57507
  if (result.recordId) {
@@ -56554,7 +57523,9 @@ Saving state... done. Session saved to ${filePath}`);
56554
57523
  const msg = c2.userMessage ? ` "${c2.userMessage.slice(0, 50)}"` : " (no message)";
56555
57524
  const modelName = c2.model ? ` [${c2.model}]` : "";
56556
57525
  console.log(
56557
- chalk23.gray(` #${i + 1}: ${c2.continuedAt}${modelName}${msg} \u2014 $${c2.segmentCost.toFixed(4)}`)
57526
+ chalk23.gray(
57527
+ ` #${i + 1}: ${c2.continuedAt}${modelName}${msg} \u2014 $${c2.segmentCost.toFixed(4)}`
57528
+ )
56558
57529
  );
56559
57530
  }
56560
57531
  }
@@ -56565,12 +57536,8 @@ Saving state... done. Session saved to ${filePath}`);
56565
57536
  }
56566
57537
  }
56567
57538
  if (isMarathonResumableStatus(result.status)) {
56568
- console.log(
56569
- chalk23.gray(
56570
- `
56571
- Resume: ${buildResumeCommand(agent, options, parsedSandbox)}`
56572
- )
56573
- );
57539
+ console.log(chalk23.gray(`
57540
+ Resume: ${buildResumeCommand(agent, options, parsedSandbox)}`));
56574
57541
  }
56575
57542
  if (options.json) {
56576
57543
  console.log();
@@ -56600,7 +57567,9 @@ Resume: ${buildResumeCommand(agent, options, parsedSandbox)}`
56600
57567
  }
56601
57568
  if (isTransientNetworkError(error51)) {
56602
57569
  console.error(chalk23.red("Network connection lost after multiple retry attempts."));
56603
- console.error(chalk23.gray("Your progress has been saved. Resume when connectivity is restored:"));
57570
+ console.error(
57571
+ chalk23.gray("Your progress has been saved. Resume when connectivity is restored:")
57572
+ );
56604
57573
  } else {
56605
57574
  for (const line of formatMarathonApiError(error51)) {
56606
57575
  console.error(line);
@@ -56648,7 +57617,9 @@ function resolveBuiltinToolIds(tools, models) {
56648
57617
  }
56649
57618
  const errors = [];
56650
57619
  if (invalid.length > 0) {
56651
- errors.push(`Unknown built-in tool(s): ${invalid.join(", ")}. Available tools: ${available.join(", ")}`);
57620
+ errors.push(
57621
+ `Unknown built-in tool(s): ${invalid.join(", ")}. Available tools: ${available.join(", ")}`
57622
+ );
56652
57623
  }
56653
57624
  if (excluded.length > 0) {
56654
57625
  errors.push(
@@ -56701,7 +57672,53 @@ function resolveSandboxWorkflowSelection(message, sandboxProvider, resumeState)
56701
57672
  };
56702
57673
  }
56703
57674
  function applyTaskOptions(cmd) {
56704
- return cmd.argument("<agent>", "Agent ID or name").option("-g, --goal <text>", "Goal message for the agent").option("--max-sessions <n>", "Maximum sessions", "50").option("--max-cost <n>", "Budget in USD").option("--model <modelId>", "Model ID to use (overrides agent config)").option("--name <name>", "Task name (used for state file, defaults to agent name)").option("--session <name>", "Resume a specific session by name").option("--state-dir <path>", "Directory for state files (default: ~/.runtype/projects/<hash>/marathons/)").option("--resume [message]", "Resume from existing local state, optionally with a new message").option("--fresh", "Start a new run and ignore any existing local state for this task").option("--compact", "Force compact-summary resume mode instead of replaying full history").option("--compact-strategy <strategy>", "Compaction strategy: auto (default), provider_native, or summary_fallback").option("--compact-threshold <value>", "Auto-compact when estimated context crosses this threshold (default: 80% fallback, 90% native; accepts percent like 90% or absolute token count like 120000)").option("--compact-instructions <text>", "Extra instructions for what a compact summary must preserve").option("--no-auto-compact", "Disable automatic context-aware history compaction").option("--track", "Sync progress to a Runtype record (visible in dashboard)").option("--debug", "Show debug output from each session").option("--json", "Output final result as JSON").option("--sandbox <provider>", "Enable sandbox code execution tool (cloudflare-worker, quickjs, or daytona)").option("--no-local-tools", "Disable built-in local tool execution (read_file, write_file, list_directory)").option("--session-search", "Enable session context indexing and search_session_history tool").option("-t, --tools <tools...>", "Enable built-in tools (e.g., exa, firecrawl, dalle, openai_web_search, anthropic_web_search)").option("--plain-text", "Disable markdown rendering in output").option("--no-reasoning", "Disable model reasoning/thinking (enabled by default for supported models)").option("--no-checkpoint", "Run all iterations without checkpoint pauses (fully autonomous)").option("--checkpoint-timeout <seconds>", "Auto-continue timeout in seconds (default: 10)", "10").option("--planning-model <modelId>", "Model to use during research/planning phases").option("--execution-model <modelId>", "Model to use during execution phase").option("--fallback-model <modelId>", "Model to fall back to when primary model fails").option("--playbook <name>", "Load a playbook from .runtype/marathons/playbooks/").option("--offload-threshold <chars>", 'Offload tool outputs larger than this to files (default: 100000; use "off" or "0" to disable guardrails)').option("--tool-context <mode>", "Tool result storage: hot-tail (default), observation-mask, or full-inline").option("--tool-window <window>", 'Compaction window: "session" (default) or a number for last-N tool results (e.g. 10)').option("--runner-char <char>", "Custom runner emoji (default: \u{1F3C3})").option("--finish-char <char>", "Custom finish line emoji (default: \u{1F3C1})").option("--no-runner", "Hide the runner emoji from the header border").option("--no-finish", "Hide the finish line emoji from the header border").action(taskAction);
57675
+ return cmd.argument("<agent>", "Agent ID or name").option("-g, --goal <text>", "Goal message for the agent").option("--max-sessions <n>", "Maximum sessions", "50").option("--max-cost <n>", "Budget in USD").option("--model <modelId>", "Model ID to use (overrides agent config)").option("--name <name>", "Task name (used for state file, defaults to agent name)").option("--session <name>", "Resume a specific session by name").option(
57676
+ "--state-dir <path>",
57677
+ "Directory for state files (default: ~/.runtype/projects/<hash>/marathons/)"
57678
+ ).option(
57679
+ "--resume [message]",
57680
+ "Resume from existing local state, optionally with a new message"
57681
+ ).option("--fresh", "Start a new run and ignore any existing local state for this task").option("--compact", "Force compact-summary resume mode instead of replaying full history").option(
57682
+ "--compact-strategy <strategy>",
57683
+ "Compaction strategy: auto (default), provider_native, or summary_fallback"
57684
+ ).option(
57685
+ "--compact-threshold <value>",
57686
+ "Auto-compact when estimated context crosses this threshold (default: 80% fallback, 90% native; accepts percent like 90% or absolute token count like 120000)"
57687
+ ).option(
57688
+ "--compact-instructions <text>",
57689
+ "Extra instructions for what a compact summary must preserve"
57690
+ ).option("--no-auto-compact", "Disable automatic context-aware history compaction").option("--track", "Sync progress to a Runtype record (visible in dashboard)").option("--debug", "Show debug output from each session").option("--json", "Output final result as JSON").option(
57691
+ "--sandbox <provider>",
57692
+ "Enable sandbox code execution tool (cloudflare-worker, quickjs, or daytona)"
57693
+ ).option(
57694
+ "--no-local-tools",
57695
+ "Disable built-in local tool execution (read_file, write_file, list_directory)"
57696
+ ).option(
57697
+ "--session-search",
57698
+ "Enable session context indexing and search_session_history tool (default)"
57699
+ ).option(
57700
+ "--no-session-search",
57701
+ "Disable session context indexing and search_session_history tool"
57702
+ ).option(
57703
+ "-t, --tools <tools...>",
57704
+ "Enable built-in tools (e.g., exa, firecrawl, dalle, openai_web_search, anthropic_web_search)"
57705
+ ).option("--plain-text", "Disable markdown rendering in output").option(
57706
+ "--no-reasoning",
57707
+ "Disable model reasoning/thinking (enabled by default for supported models)"
57708
+ ).option("--no-checkpoint", "Run all iterations without checkpoint pauses (fully autonomous)").option(
57709
+ "--checkpoint-timeout <seconds>",
57710
+ "Auto-continue timeout in seconds (default: 10)",
57711
+ "10"
57712
+ ).option("--planning-model <modelId>", "Model to use during research/planning phases").option("--execution-model <modelId>", "Model to use during execution phase").option("--fallback-model <modelId>", "Model to fall back to when primary model fails").option("--playbook <name>", "Load a playbook from .runtype/marathons/playbooks/").option(
57713
+ "--offload-threshold <chars>",
57714
+ 'Offload tool outputs larger than this to files (default: 100000; use "off" or "0" to disable guardrails)'
57715
+ ).option(
57716
+ "--tool-context <mode>",
57717
+ "Tool result storage: hot-tail (default), observation-mask, or full-inline"
57718
+ ).option(
57719
+ "--tool-window <window>",
57720
+ 'Compaction window: "session" (default) or a number for last-N tool results (e.g. 10)'
57721
+ ).option("--runner-char <char>", "Custom runner emoji (default: \u{1F3C3})").option("--finish-char <char>", "Custom finish line emoji (default: \u{1F3C1})").option("--no-runner", "Hide the runner emoji from the header border").option("--no-finish", "Hide the finish line emoji from the header border").action(taskAction);
56705
57722
  }
56706
57723
  var taskCommand = applyTaskOptions(
56707
57724
  new Command16("task").description("Run a multi-session agent task")
@@ -57865,14 +58882,14 @@ import React19 from "react";
57865
58882
  import { render as render19 } from "ink";
57866
58883
  import { useState as useState36, useEffect as useEffect30 } from "react";
57867
58884
  import { Text as Text34 } from "ink";
57868
- import { readFileSync as readFileSync15 } from "fs";
58885
+ import { readFileSync as readFileSync16 } from "fs";
57869
58886
  var evalCommand = new Command20("eval").description("Manage evaluations");
57870
58887
  evalCommand.command("submit").description("Submit an eval batch").requiredOption("-f, --flow <id>", "Flow ID to evaluate").requiredOption("-r, --records <file>", "JSON file with record IDs").option("-n, --name <name>", "Eval batch name").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
57871
58888
  const apiKey = await ensureAuth();
57872
58889
  if (!apiKey) return;
57873
58890
  let recordIds;
57874
58891
  try {
57875
- const content = readFileSync15(options.records, "utf-8");
58892
+ const content = readFileSync16(options.records, "utf-8");
57876
58893
  const parsed = JSON.parse(content);
57877
58894
  recordIds = Array.isArray(parsed) ? parsed : parsed.recordIds || parsed.records || [];
57878
58895
  } catch (error51) {
@@ -58430,13 +59447,13 @@ apiKeysCommand.command("delete <id>").description("Delete an API key").option("-
58430
59447
  await waitUntilExit2();
58431
59448
  return;
58432
59449
  }
58433
- const confirmed = await new Promise((resolve10) => {
59450
+ const confirmed = await new Promise((resolve11) => {
58434
59451
  const { unmount } = render20(
58435
59452
  React20.createElement(ConfirmPrompt, {
58436
59453
  message: `Delete API key ${id}?`,
58437
59454
  defaultValue: false,
58438
59455
  onConfirm: (result) => {
58439
- resolve10(result);
59456
+ resolve11(result);
58440
59457
  unmount();
58441
59458
  }
58442
59459
  })
@@ -58541,8 +59558,8 @@ apiKeysCommand.command("analytics").description("Show API key usage analytics").
58541
59558
  const client = createCliClient(apiKey);
58542
59559
  if (!isTTY(options) || options.json) {
58543
59560
  try {
58544
- const path17 = options.key ? `/api-keys/${options.key}/analytics` : "/api-keys/analytics";
58545
- const data = await client.get(path17);
59561
+ const path18 = options.key ? `/api-keys/${options.key}/analytics` : "/api-keys/analytics";
59562
+ const data = await client.get(path18);
58546
59563
  printJson(data);
58547
59564
  } catch (error51) {
58548
59565
  const message = error51 instanceof Error ? error51.message : "Unknown error";
@@ -58559,8 +59576,8 @@ apiKeysCommand.command("analytics").description("Show API key usage analytics").
58559
59576
  useEffect31(() => {
58560
59577
  const run2 = async () => {
58561
59578
  try {
58562
- const path17 = options.key ? `/api-keys/${options.key}/analytics` : "/api-keys/analytics";
58563
- const data = await client.get(path17);
59579
+ const path18 = options.key ? `/api-keys/${options.key}/analytics` : "/api-keys/analytics";
59580
+ const data = await client.get(path18);
58564
59581
  printJson(data);
58565
59582
  setSuccess(true);
58566
59583
  setLoading(false);
@@ -58902,13 +59919,13 @@ clientTokensCommand.command("delete <id>").description("Delete a client token").
58902
59919
  await waitUntilExit2();
58903
59920
  return;
58904
59921
  }
58905
- const confirmed = await new Promise((resolve10) => {
59922
+ const confirmed = await new Promise((resolve11) => {
58906
59923
  const { unmount } = render21(
58907
59924
  React21.createElement(ConfirmPrompt, {
58908
59925
  message: `Delete client token ${id}?`,
58909
59926
  defaultValue: false,
58910
59927
  onConfirm: (result) => {
58911
- resolve10(result);
59928
+ resolve11(result);
58912
59929
  unmount();
58913
59930
  }
58914
59931
  })
@@ -59432,8 +60449,8 @@ function defaultTokenName(agentName) {
59432
60449
  }
59433
60450
  async function promptLine(rl, question, defaultValue) {
59434
60451
  const hint = defaultValue ? chalk30.dim(` (${defaultValue})`) : "";
59435
- const answer = await new Promise((resolve10) => {
59436
- rl.question(`${question}${hint}: `, resolve10);
60452
+ const answer = await new Promise((resolve11) => {
60453
+ rl.question(`${question}${hint}: `, resolve11);
59437
60454
  });
59438
60455
  const trimmed = answer.trim();
59439
60456
  if (!trimmed && defaultValue !== void 0) {
@@ -59443,8 +60460,8 @@ async function promptLine(rl, question, defaultValue) {
59443
60460
  }
59444
60461
  async function promptConfirm2(rl, message, defaultYes = false) {
59445
60462
  const hint = defaultYes ? chalk30.dim(" (Y/n)") : chalk30.dim(" (y/N)");
59446
- const answer = await new Promise((resolve10) => {
59447
- rl.question(`${message}${hint}: `, resolve10);
60463
+ const answer = await new Promise((resolve11) => {
60464
+ rl.question(`${message}${hint}: `, resolve11);
59448
60465
  });
59449
60466
  const t = answer.trim().toLowerCase();
59450
60467
  if (t === "") return defaultYes;
@@ -59513,18 +60530,18 @@ Dashboard: ${initial.dashboardUrl}`));
59513
60530
  process.stdin.removeAllListeners("keypress");
59514
60531
  process.stdin.pause();
59515
60532
  };
59516
- await new Promise((resolve10) => {
60533
+ await new Promise((resolve11) => {
59517
60534
  const onKeypress = async (_str, key) => {
59518
60535
  if (!key) return;
59519
60536
  if (key.ctrl && key.name === "c") {
59520
60537
  cleanup();
59521
- resolve10();
60538
+ resolve11();
59522
60539
  process.exit(0);
59523
60540
  }
59524
60541
  const name = key.name;
59525
60542
  if (name === "q" || name === "escape") {
59526
60543
  cleanup();
59527
- resolve10();
60544
+ resolve11();
59528
60545
  return;
59529
60546
  }
59530
60547
  if (name === "c") {
@@ -60884,11 +61901,11 @@ async function runTail(options) {
60884
61901
  process.stderr.write(
60885
61902
  (useColor ? chalk35.gray(`Retrying in ${delay / 1e3}s (attempt ${attempt}/${MAX_ATTEMPTS})...`) : `Retrying in ${delay / 1e3}s (attempt ${attempt}/${MAX_ATTEMPTS})...`) + "\n"
60886
61903
  );
60887
- await new Promise((resolve10) => {
60888
- const timer = setTimeout(resolve10, delay);
61904
+ await new Promise((resolve11) => {
61905
+ const timer = setTimeout(resolve11, delay);
60889
61906
  const onAbort = () => {
60890
61907
  clearTimeout(timer);
60891
- resolve10();
61908
+ resolve11();
60892
61909
  };
60893
61910
  controller.signal.addEventListener("abort", onAbort, { once: true });
60894
61911
  });
@@ -60904,7 +61921,7 @@ var tailCommand = new Command28("tail").description("Stream live execution logs
60904
61921
  // src/commands/validate-product.ts
60905
61922
  import { Command as Command29, Option } from "commander";
60906
61923
  import chalk36 from "chalk";
60907
- import { readFileSync as readFileSync16 } from "fs";
61924
+ import { readFileSync as readFileSync17 } from "fs";
60908
61925
  function createValidateProductCommand() {
60909
61926
  return new Command29("validate-product").description("Validate a product (FPO) or FPO template locally (no API call)").argument(
60910
61927
  "[input]",
@@ -60984,7 +62001,7 @@ async function readInput(input) {
60984
62001
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
60985
62002
  return trimmed;
60986
62003
  }
60987
- return readFileSync16(input, "utf-8");
62004
+ return readFileSync17(input, "utf-8");
60988
62005
  }
60989
62006
  async function readStdin() {
60990
62007
  if (process.stdin.isTTY) {
@@ -61086,8 +62103,8 @@ function printIssues(title, issues, color) {
61086
62103
  // src/commands/deploy.ts
61087
62104
  import { Command as Command30 } from "commander";
61088
62105
  import chalk37 from "chalk";
61089
- import * as fs15 from "fs";
61090
- import * as path15 from "path";
62106
+ import * as fs16 from "fs";
62107
+ import * as path16 from "path";
61091
62108
  import { RuntypeApiError as RuntypeApiError4 } from "@runtypelabs/sdk";
61092
62109
  function bashSingleQuote(s) {
61093
62110
  return "'" + s.replace(/'/g, "'\\''") + "'";
@@ -62057,8 +63074,8 @@ var deployCommand = new Command30("deploy").description("Export an agent or flow
62057
63074
  const apiKey = await ensureAuth();
62058
63075
  if (!apiKey) return;
62059
63076
  const client = createCliClient(apiKey);
62060
- const outDir = path15.resolve(options.output);
62061
- const projectName = options.name ?? slugify2(path15.basename(outDir));
63077
+ const outDir = path16.resolve(options.output);
63078
+ const projectName = options.name ?? slugify2(path16.basename(outDir));
62062
63079
  console.log(chalk37.cyan(`
62063
63080
  Scaffolding ${target} deployment to ${outDir}
62064
63081
  `));
@@ -62123,18 +63140,18 @@ Scaffolding ${target} deployment to ${outDir}
62123
63140
  }
62124
63141
  slugSet.add(slug);
62125
63142
  }
62126
- fs15.mkdirSync(path15.join(outDir, "agents"), { recursive: true });
62127
- fs15.mkdirSync(path15.join(outDir, "packages"), { recursive: true });
63143
+ fs16.mkdirSync(path16.join(outDir, "agents"), { recursive: true });
63144
+ fs16.mkdirSync(path16.join(outDir, "packages"), { recursive: true });
62128
63145
  for (const { name, def } of agentDefs) {
62129
63146
  const filename = `${slugify2(name)}.json`;
62130
- fs15.writeFileSync(path15.join(outDir, "agents", filename), JSON.stringify(def, null, 2));
63147
+ fs16.writeFileSync(path16.join(outDir, "agents", filename), JSON.stringify(def, null, 2));
62131
63148
  console.log(` Wrote agents/${filename}`);
62132
63149
  }
62133
63150
  const agentNames = agentDefs.map((a) => a.name);
62134
63151
  let monorepoRoot = process.cwd();
62135
63152
  for (let i = 0; i < 8; i++) {
62136
- if (fs15.existsSync(path15.join(monorepoRoot, "pnpm-workspace.yaml"))) break;
62137
- const parent = path15.dirname(monorepoRoot);
63153
+ if (fs16.existsSync(path16.join(monorepoRoot, "pnpm-workspace.yaml"))) break;
63154
+ const parent = path16.dirname(monorepoRoot);
62138
63155
  if (parent === monorepoRoot) break;
62139
63156
  monorepoRoot = parent;
62140
63157
  }
@@ -62144,35 +63161,35 @@ Scaffolding ${target} deployment to ${outDir}
62144
63161
  }
62145
63162
  const secretNames = Array.from(allSecrets);
62146
63163
  if (target === "cloudflare") {
62147
- fs15.mkdirSync(path15.join(outDir, "src"), { recursive: true });
62148
- fs15.writeFileSync(path15.join(outDir, "src", "index.ts"), workerIndexTs(agentSlugs));
62149
- fs15.writeFileSync(path15.join(outDir, "wrangler.toml"), wranglerToml(projectName));
62150
- fs15.writeFileSync(path15.join(outDir, "package.json"), workerPackageJson(projectName, "workspace:*"));
62151
- fs15.writeFileSync(path15.join(outDir, "tsconfig.json"), workerTsconfigJson());
62152
- const setupPath = path15.join(outDir, "setup.sh");
62153
- fs15.writeFileSync(setupPath, workerSetupSh(monorepoRoot));
62154
- fs15.chmodSync(setupPath, 493);
62155
- fs15.writeFileSync(path15.join(outDir, "README.md"), workerReadme(agentNames, secretNames));
63164
+ fs16.mkdirSync(path16.join(outDir, "src"), { recursive: true });
63165
+ fs16.writeFileSync(path16.join(outDir, "src", "index.ts"), workerIndexTs(agentSlugs));
63166
+ fs16.writeFileSync(path16.join(outDir, "wrangler.toml"), wranglerToml(projectName));
63167
+ fs16.writeFileSync(path16.join(outDir, "package.json"), workerPackageJson(projectName, "workspace:*"));
63168
+ fs16.writeFileSync(path16.join(outDir, "tsconfig.json"), workerTsconfigJson());
63169
+ const setupPath = path16.join(outDir, "setup.sh");
63170
+ fs16.writeFileSync(setupPath, workerSetupSh(monorepoRoot));
63171
+ fs16.chmodSync(setupPath, 493);
63172
+ fs16.writeFileSync(path16.join(outDir, "README.md"), workerReadme(agentNames, secretNames));
62156
63173
  } else if (target === "vercel") {
62157
- fs15.mkdirSync(path15.join(outDir, "api"), { recursive: true });
62158
- fs15.writeFileSync(path15.join(outDir, "api", "[[...route]].ts"), vercelRouteTs(agentSlugs));
62159
- fs15.writeFileSync(path15.join(outDir, "vercel.json"), vercelJson());
62160
- fs15.writeFileSync(path15.join(outDir, "package.json"), vercelPackageJson(projectName, "workspace:*"));
62161
- fs15.writeFileSync(path15.join(outDir, "tsconfig.json"), vercelTsconfigJson());
62162
- const setupPath = path15.join(outDir, "setup.sh");
62163
- fs15.writeFileSync(setupPath, vercelSetupSh(monorepoRoot));
62164
- fs15.chmodSync(setupPath, 493);
62165
- fs15.writeFileSync(path15.join(outDir, "README.md"), vercelReadme(agentNames, secretNames));
63174
+ fs16.mkdirSync(path16.join(outDir, "api"), { recursive: true });
63175
+ fs16.writeFileSync(path16.join(outDir, "api", "[[...route]].ts"), vercelRouteTs(agentSlugs));
63176
+ fs16.writeFileSync(path16.join(outDir, "vercel.json"), vercelJson());
63177
+ fs16.writeFileSync(path16.join(outDir, "package.json"), vercelPackageJson(projectName, "workspace:*"));
63178
+ fs16.writeFileSync(path16.join(outDir, "tsconfig.json"), vercelTsconfigJson());
63179
+ const setupPath = path16.join(outDir, "setup.sh");
63180
+ fs16.writeFileSync(setupPath, vercelSetupSh(monorepoRoot));
63181
+ fs16.chmodSync(setupPath, 493);
63182
+ fs16.writeFileSync(path16.join(outDir, "README.md"), vercelReadme(agentNames, secretNames));
62166
63183
  } else {
62167
- fs15.writeFileSync(path15.join(outDir, "server.ts"), serverTs());
62168
- fs15.writeFileSync(path15.join(outDir, "Dockerfile"), dockerfile());
62169
- fs15.writeFileSync(path15.join(outDir, ".dockerignore"), dockerignore());
62170
- fs15.writeFileSync(path15.join(outDir, "tsconfig.json"), tsconfigJson());
62171
- fs15.writeFileSync(path15.join(outDir, "package.json"), packageJson(projectName, "workspace:*"));
62172
- const setupPath = path15.join(outDir, "setup.sh");
62173
- fs15.writeFileSync(setupPath, setupSh(monorepoRoot));
62174
- fs15.chmodSync(setupPath, 493);
62175
- fs15.writeFileSync(path15.join(outDir, "README.md"), readme(agentNames, secretNames));
63184
+ fs16.writeFileSync(path16.join(outDir, "server.ts"), serverTs());
63185
+ fs16.writeFileSync(path16.join(outDir, "Dockerfile"), dockerfile());
63186
+ fs16.writeFileSync(path16.join(outDir, ".dockerignore"), dockerignore());
63187
+ fs16.writeFileSync(path16.join(outDir, "tsconfig.json"), tsconfigJson());
63188
+ fs16.writeFileSync(path16.join(outDir, "package.json"), packageJson(projectName, "workspace:*"));
63189
+ const setupPath = path16.join(outDir, "setup.sh");
63190
+ fs16.writeFileSync(setupPath, setupSh(monorepoRoot));
63191
+ fs16.chmodSync(setupPath, 493);
63192
+ fs16.writeFileSync(path16.join(outDir, "README.md"), readme(agentNames, secretNames));
62176
63193
  }
62177
63194
  console.log("");
62178
63195
  console.log(chalk37.green(`\u2713 Scaffold written to ${outDir}`));
@@ -62230,19 +63247,19 @@ import { Command as Command31 } from "commander";
62230
63247
  import chalk39 from "chalk";
62231
63248
 
62232
63249
  // src/lib/skills-install.ts
62233
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync17, writeFileSync as writeFileSync7 } from "fs";
62234
- import path16 from "path";
63250
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync18, writeFileSync as writeFileSync7 } from "fs";
63251
+ import path17 from "path";
62235
63252
  import readline4 from "readline";
62236
63253
  import chalk38 from "chalk";
62237
63254
  var SKILLS_REPO = "runtypelabs/skills";
62238
63255
  var SKILLS_INSTALL_RETRY_HINT = "Retry with `runtype skills install`, or install manually: npx skills add runtypelabs/skills";
62239
63256
  var METADATA_FILENAME = "agents-skills-install.json";
62240
63257
  function metadataPath() {
62241
- return path16.join(getRuntypeHomeDir(), METADATA_FILENAME);
63258
+ return path17.join(getRuntypeHomeDir(), METADATA_FILENAME);
62242
63259
  }
62243
63260
  function readSkillsInstallMetadata() {
62244
63261
  try {
62245
- const raw = readFileSync17(metadataPath(), "utf8");
63262
+ const raw = readFileSync18(metadataPath(), "utf8");
62246
63263
  const parsed = JSON.parse(raw);
62247
63264
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && parsed.version === 1 && typeof parsed.accepted === "boolean") {
62248
63265
  return parsed;
@@ -62254,7 +63271,7 @@ function readSkillsInstallMetadata() {
62254
63271
  }
62255
63272
  function writeSkillsInstallMetadata(metadata) {
62256
63273
  try {
62257
- mkdirSync9(path16.dirname(metadataPath()), { recursive: true });
63274
+ mkdirSync9(path17.dirname(metadataPath()), { recursive: true });
62258
63275
  writeFileSync7(metadataPath(), JSON.stringify(metadata, null, 2));
62259
63276
  } catch {
62260
63277
  }
@@ -62305,8 +63322,8 @@ async function promptConfirm3(message, defaultYes = true) {
62305
63322
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
62306
63323
  const hint = defaultYes ? chalk38.dim(" (Y/n)") : chalk38.dim(" (y/N)");
62307
63324
  try {
62308
- const answer = await new Promise((resolve10) => {
62309
- rl.question(`${message}${hint}: `, resolve10);
63325
+ const answer = await new Promise((resolve11) => {
63326
+ rl.question(`${message}${hint}: `, resolve11);
62310
63327
  });
62311
63328
  const t = answer.trim().toLowerCase();
62312
63329
  if (t === "") return defaultYes;
@@ -62510,11 +63527,265 @@ skillsCommand.command("install").description(`Install Runtype skills (${SKILLS_R
62510
63527
  }
62511
63528
  );
62512
63529
 
63530
+ // src/commands/apps.ts
63531
+ import { readdirSync as readdirSync6, readFileSync as readFileSync19, lstatSync, statSync as statSync7, existsSync as existsSync14 } from "fs";
63532
+ import { join as join12, relative as relative5 } from "path";
63533
+ import { Command as Command32 } from "commander";
63534
+ import chalk40 from "chalk";
63535
+ import { zipSync } from "fflate";
63536
+ var appsCommand = new Command32("apps").description(
63537
+ "Manage Runtype Apps (hosted AI apps on *.runtype.run)"
63538
+ );
63539
+ var MANIFEST_FILENAME = "runtype.app.json";
63540
+ function collectBundleFiles(dir) {
63541
+ const zippable = {};
63542
+ const walk = (current) => {
63543
+ for (const entry of readdirSync6(current)) {
63544
+ if (entry.startsWith(".")) continue;
63545
+ const full = join12(current, entry);
63546
+ const stat = lstatSync(full);
63547
+ if (stat.isSymbolicLink()) continue;
63548
+ if (stat.isDirectory()) {
63549
+ if (entry === "node_modules") continue;
63550
+ walk(full);
63551
+ } else {
63552
+ zippable[relative5(dir, full).split("\\").join("/")] = readFileSync19(full);
63553
+ }
63554
+ }
63555
+ };
63556
+ walk(dir);
63557
+ return zippable;
63558
+ }
63559
+ function fail(message, jsonMode, code) {
63560
+ if (jsonMode) {
63561
+ printJson({ status: "error", error: message, code });
63562
+ } else {
63563
+ console.error(chalk40.red(message));
63564
+ }
63565
+ process.exit(1);
63566
+ }
63567
+ appsCommand.command("list").description("List your apps").option("--json", "Structured JSON output").action(async (options, cmd) => {
63568
+ const globals = cmd.optsWithGlobals();
63569
+ const jsonMode = !!(options.json ?? globals.json);
63570
+ const apiKey = await ensureAuth();
63571
+ if (!apiKey) return;
63572
+ const client = createCliClient(apiKey);
63573
+ try {
63574
+ const { data } = await client.apps.list();
63575
+ if (jsonMode) {
63576
+ printJson({ data });
63577
+ return;
63578
+ }
63579
+ if (data.length === 0) {
63580
+ console.log(chalk40.yellow("No apps yet. Create one with `runtype apps create`."));
63581
+ return;
63582
+ }
63583
+ for (const app of data) {
63584
+ const status = app.status === "suspended" ? chalk40.red("suspended") : chalk40.green("active");
63585
+ const serving = app.activeVersionId ? "" : chalk40.dim(" (no active version)");
63586
+ console.log(`${chalk40.bold(app.name)} ${chalk40.dim(app.id)}`);
63587
+ console.log(` ${app.url} ${status} ${app.visibility}${serving}`);
63588
+ }
63589
+ } catch (error51) {
63590
+ fail(
63591
+ `Failed to list apps: ${error51 instanceof Error ? error51.message : String(error51)}`,
63592
+ jsonMode,
63593
+ "LIST_FAILED"
63594
+ );
63595
+ }
63596
+ });
63597
+ appsCommand.command("create").description("Create an app (the hostname is {slug}-{shortId}.runtype.run)").requiredOption("-s, --slug <slug>", "Hostname slug (lowercase, must start with a letter)").requiredOption("-n, --name <name>", "Display name").option("-d, --description <text>", "Description").option("--visibility <visibility>", "public or unlisted (default unlisted)").option("--json", "Structured JSON output").action(
63598
+ async (options, cmd) => {
63599
+ const globals = cmd.optsWithGlobals();
63600
+ const jsonMode = !!(options.json ?? globals.json);
63601
+ const apiKey = await ensureAuth();
63602
+ if (!apiKey) return;
63603
+ const client = createCliClient(apiKey);
63604
+ try {
63605
+ const app = await client.apps.create({
63606
+ slug: options.slug,
63607
+ name: options.name,
63608
+ description: options.description,
63609
+ visibility: options.visibility
63610
+ });
63611
+ if (jsonMode) {
63612
+ printJson(app);
63613
+ return;
63614
+ }
63615
+ console.log(chalk40.green(`Created ${app.name} (${app.id})`));
63616
+ console.log(` ${app.url}`);
63617
+ console.log(chalk40.dim(" Deploy a bundle with `runtype apps deploy <dir> --app " + app.id + "`"));
63618
+ } catch (error51) {
63619
+ fail(
63620
+ `Failed to create app: ${error51 instanceof Error ? error51.message : String(error51)}`,
63621
+ jsonMode,
63622
+ "CREATE_FAILED"
63623
+ );
63624
+ }
63625
+ }
63626
+ );
63627
+ appsCommand.command("deploy <dir>").description("Zip a bundle directory, upload it as a new version, and activate it").requiredOption("-a, --app <appId>", "The app id (app_...) to deploy to").option("--no-activate", "Upload without activating (what is served stays unchanged)").option("--json", "Structured JSON output").action(
63628
+ async (dir, options, cmd) => {
63629
+ const globals = cmd.optsWithGlobals();
63630
+ const jsonMode = !!(options.json ?? globals.json);
63631
+ const apiKey = await ensureAuth();
63632
+ if (!apiKey) return;
63633
+ if (!existsSync14(dir) || !statSync7(dir).isDirectory()) {
63634
+ fail(`Not a directory: ${dir}`, jsonMode, "INVALID_DIR");
63635
+ }
63636
+ let bundleFiles = {};
63637
+ try {
63638
+ bundleFiles = collectBundleFiles(dir);
63639
+ } catch (error51) {
63640
+ fail(
63641
+ `Failed to read ${dir}: ${error51 instanceof Error ? error51.message : String(error51)}`,
63642
+ jsonMode,
63643
+ "INVALID_DIR"
63644
+ );
63645
+ }
63646
+ if (!bundleFiles["index.html"]) {
63647
+ fail(
63648
+ `${dir} is missing index.html at its root (symlinked files are not bundled).`,
63649
+ jsonMode,
63650
+ "MISSING_INDEX"
63651
+ );
63652
+ }
63653
+ if (!bundleFiles[MANIFEST_FILENAME]) {
63654
+ fail(
63655
+ `${dir} is missing ${MANIFEST_FILENAME} at its root (symlinked files are not bundled). Every app bundle needs a manifest; see the build-runtype-app skill or the Runtype docs.`,
63656
+ jsonMode,
63657
+ "MISSING_MANIFEST"
63658
+ );
63659
+ }
63660
+ const client = createCliClient(apiKey);
63661
+ try {
63662
+ const zipBytes = zipSync(bundleFiles);
63663
+ if (!jsonMode) console.log(chalk40.dim(`Uploading ${(zipBytes.byteLength / 1024).toFixed(1)} KB bundle...`));
63664
+ const version2 = await client.apps.uploadVersion(options.app, zipBytes);
63665
+ let app;
63666
+ if (options.activate) {
63667
+ try {
63668
+ const activated = await client.apps.activate(options.app, version2.id);
63669
+ app = activated.app;
63670
+ } catch (error51) {
63671
+ const message = error51 instanceof Error ? error51.message : String(error51);
63672
+ if (jsonMode) {
63673
+ printJson({
63674
+ status: "error",
63675
+ error: `Activation failed: ${message}`,
63676
+ code: "ACTIVATE_FAILED",
63677
+ version: version2,
63678
+ activated: false
63679
+ });
63680
+ } else {
63681
+ console.error(chalk40.red(`Uploaded version ${version2.versionNumber}, but activation failed: ${message}`));
63682
+ console.error(chalk40.dim(` Retry with \`runtype apps activate ${options.app} ${version2.id}\` (no re-upload needed).`));
63683
+ }
63684
+ process.exit(1);
63685
+ }
63686
+ }
63687
+ if (jsonMode) {
63688
+ printJson({ version: version2, app, activated: options.activate });
63689
+ return;
63690
+ }
63691
+ console.log(
63692
+ chalk40.green(
63693
+ `Deployed version ${version2.versionNumber} (${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB)`
63694
+ )
63695
+ );
63696
+ if (app) {
63697
+ console.log(` Live at ${chalk40.bold(app.url)}`);
63698
+ } else {
63699
+ console.log(chalk40.dim(` Uploaded but not activated. Activate with \`runtype apps activate ${options.app} ${version2.id}\``));
63700
+ }
63701
+ } catch (error51) {
63702
+ fail(
63703
+ `Deploy failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
63704
+ jsonMode,
63705
+ "DEPLOY_FAILED"
63706
+ );
63707
+ }
63708
+ }
63709
+ );
63710
+ appsCommand.command("versions <appId>").description("List an app's versions, newest first").option("--json", "Structured JSON output").action(async (appId, options, cmd) => {
63711
+ const globals = cmd.optsWithGlobals();
63712
+ const jsonMode = !!(options.json ?? globals.json);
63713
+ const apiKey = await ensureAuth();
63714
+ if (!apiKey) return;
63715
+ const client = createCliClient(apiKey);
63716
+ try {
63717
+ const { data } = await client.apps.listVersions(appId);
63718
+ if (jsonMode) {
63719
+ printJson({ data });
63720
+ return;
63721
+ }
63722
+ if (data.length === 0) {
63723
+ console.log(chalk40.yellow("No versions uploaded yet."));
63724
+ return;
63725
+ }
63726
+ for (const version2 of data) {
63727
+ const marker = version2.status === "active" ? chalk40.green(" (active)") : "";
63728
+ console.log(
63729
+ `v${version2.versionNumber} ${chalk40.dim(version2.id)} ${version2.fileCount} files, ${(version2.sizeBytes / 1024).toFixed(1)} KB${marker}`
63730
+ );
63731
+ }
63732
+ } catch (error51) {
63733
+ fail(
63734
+ `Failed to list versions: ${error51 instanceof Error ? error51.message : String(error51)}`,
63735
+ jsonMode,
63736
+ "VERSIONS_FAILED"
63737
+ );
63738
+ }
63739
+ });
63740
+ appsCommand.command("activate <appId> <versionId>").description("Activate an uploaded version (deploy or rollback)").option("--json", "Structured JSON output").action(async (appId, versionId, options, cmd) => {
63741
+ const globals = cmd.optsWithGlobals();
63742
+ const jsonMode = !!(options.json ?? globals.json);
63743
+ const apiKey = await ensureAuth();
63744
+ if (!apiKey) return;
63745
+ const client = createCliClient(apiKey);
63746
+ try {
63747
+ const { app, version: version2 } = await client.apps.activate(appId, versionId);
63748
+ if (jsonMode) {
63749
+ printJson({ app, version: version2 });
63750
+ return;
63751
+ }
63752
+ console.log(chalk40.green(`Activated version ${version2.versionNumber}`));
63753
+ console.log(` Live at ${chalk40.bold(app.url)}`);
63754
+ } catch (error51) {
63755
+ fail(
63756
+ `Activation failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
63757
+ jsonMode,
63758
+ "ACTIVATE_FAILED"
63759
+ );
63760
+ }
63761
+ });
63762
+ appsCommand.command("delete <appId>").description("Permanently delete an app, its versions, and its hosting").option("--json", "Structured JSON output").action(async (appId, options, cmd) => {
63763
+ const globals = cmd.optsWithGlobals();
63764
+ const jsonMode = !!(options.json ?? globals.json);
63765
+ const apiKey = await ensureAuth();
63766
+ if (!apiKey) return;
63767
+ const client = createCliClient(apiKey);
63768
+ try {
63769
+ await client.apps.delete(appId);
63770
+ if (jsonMode) {
63771
+ printJson({ status: "deleted", appId });
63772
+ return;
63773
+ }
63774
+ console.log(chalk40.green(`Deleted ${appId}`));
63775
+ } catch (error51) {
63776
+ fail(
63777
+ `Delete failed: ${error51 instanceof Error ? error51.message : String(error51)}`,
63778
+ jsonMode,
63779
+ "DELETE_FAILED"
63780
+ );
63781
+ }
63782
+ });
63783
+
62513
63784
  // src/index.ts
62514
63785
  init_credential_store();
62515
63786
 
62516
63787
  // src/lib/update-check.ts
62517
- import chalk40 from "chalk";
63788
+ import chalk41 from "chalk";
62518
63789
  import Conf3 from "conf";
62519
63790
  var UPDATE_CHECK_INTERVAL_MS = 12 * 60 * 60 * 1e3;
62520
63791
  var UPDATE_NOTIFY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
@@ -62608,7 +63879,7 @@ function notifyFromCachedCliUpdate(args, options = {}) {
62608
63879
  console.error(message);
62609
63880
  });
62610
63881
  notify(
62611
- `${chalk40.yellow("Update available:")} ${chalk40.red(currentVersion)} ${chalk40.gray("->")} ${chalk40.green(latestVersion)} ${chalk40.gray(`(${getUpgradeCommand()})`)}`
63882
+ `${chalk41.yellow("Update available:")} ${chalk41.red(currentVersion)} ${chalk41.gray("->")} ${chalk41.green(latestVersion)} ${chalk41.gray(`(${getUpgradeCommand()})`)}`
62612
63883
  );
62613
63884
  store.set("lastNotifiedAt", now.toISOString());
62614
63885
  store.set("lastNotifiedVersion", latestVersion);
@@ -62650,7 +63921,7 @@ function maybeNotifyAboutCliUpdate(args, options = {}) {
62650
63921
  // src/index.ts
62651
63922
  loadEnv();
62652
63923
  setCliTitle();
62653
- var program = new Command32();
63924
+ var program = new Command33();
62654
63925
  program.name("runtype").description("CLI for Runtype AI Platform").version(getCliVersion()).option("-v, --verbose", "Enable verbose output").option("--api-url <url>", "Override API URL").option("--json", "Output as JSON");
62655
63926
  program.addCommand(initCommand);
62656
63927
  program.addCommand(loginCommand);
@@ -62684,6 +63955,7 @@ program.addCommand(tailCommand);
62684
63955
  program.addCommand(validateProductCommand);
62685
63956
  program.addCommand(deployCommand);
62686
63957
  program.addCommand(skillsCommand);
63958
+ program.addCommand(appsCommand);
62687
63959
  program.exitOverride();
62688
63960
  async function run() {
62689
63961
  const userArgs = process.argv.slice(2);
@@ -62701,15 +63973,15 @@ async function run() {
62701
63973
  run().catch((error51) => {
62702
63974
  const commanderError = error51;
62703
63975
  if (commanderError.code === "commander.missingArgument") {
62704
- console.error(chalk41.red(`Error: ${commanderError.message}`));
63976
+ console.error(chalk42.red(`Error: ${commanderError.message}`));
62705
63977
  process.exit(1);
62706
63978
  } else if (commanderError.code === "commander.unknownOption") {
62707
- console.error(chalk41.red(`Error: ${commanderError.message}`));
63979
+ console.error(chalk42.red(`Error: ${commanderError.message}`));
62708
63980
  process.exit(1);
62709
63981
  } else if (commanderError.code === "commander.help" || commanderError.code === "commander.version") {
62710
63982
  process.exit(0);
62711
63983
  } else {
62712
- console.error(chalk41.red("An unexpected error occurred:"));
63984
+ console.error(chalk42.red("An unexpected error occurred:"));
62713
63985
  console.error(error51);
62714
63986
  process.exit(1);
62715
63987
  }
@@ -62718,12 +63990,12 @@ async function handleNoCommand() {
62718
63990
  const store = new CredentialStore();
62719
63991
  const hasCredentials = await store.hasCredentials();
62720
63992
  if (!hasCredentials) {
62721
- console.log(chalk41.cyan("\nWelcome to Runtype CLI!\n"));
63993
+ console.log(chalk42.cyan("\nWelcome to Runtype CLI!\n"));
62722
63994
  console.log("It looks like this is your first time. Run the setup wizard:");
62723
- console.log(` ${chalk41.green("runtype init")}
63995
+ console.log(` ${chalk42.green("runtype init")}
62724
63996
  `);
62725
63997
  console.log("Or see all available commands:");
62726
- console.log(` ${chalk41.green("runtype --help")}
63998
+ console.log(` ${chalk42.green("runtype --help")}
62727
63999
  `);
62728
64000
  } else {
62729
64001
  try {