@runtypelabs/cli 2.32.2 → 2.32.4

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 (2) hide show
  1. package/dist/index.js +683 -240
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -619,6 +619,141 @@ import { RuntypeApiError } from "@runtypelabs/sdk";
619
619
  // src/lib/sdk-client.ts
620
620
  import { createClient } from "@runtypelabs/sdk";
621
621
 
622
+ // ../shared/dist/chunk-R7RM64AL.mjs
623
+ var DEFAULT_MODELS_FOR_NEW_ACCOUNTS = [
624
+ // Mixlayer models
625
+ {
626
+ provider: "runtype",
627
+ modelId: "qwen/qwen3.6-27b",
628
+ isDefault: false,
629
+ strengths: "Fast, low-cost open-weight workhorse with reasoning, tool-use, and vision \u2014 good for high-volume extraction, classification, and simple transforms.",
630
+ bestFor: ["fast-cheap", "vision"]
631
+ },
632
+ // Routed models - benefit from automatic provider optimization
633
+ // OpenAI models (routed via OpenAI direct, with Vercel fallback)
634
+ {
635
+ provider: "runtype",
636
+ modelId: "gpt-5.5",
637
+ isDefault: false,
638
+ strengths: "Top-tier general reasoning and tool-use with excellent structured-output reliability, vision, and a 1M context \u2014 a strong pick for complex, correctness-sensitive steps.",
639
+ bestFor: ["default", "deep-reasoning", "agentic-tools", "vision", "long-context"]
640
+ },
641
+ {
642
+ provider: "runtype",
643
+ modelId: "gpt-5.4-mini",
644
+ isDefault: false,
645
+ strengths: "Fast and affordable with dependable JSON formatting \u2014 a good fit for mid-complexity task steps.",
646
+ bestFor: ["fast-cheap", "default"]
647
+ },
648
+ {
649
+ provider: "runtype",
650
+ modelId: "gpt-5.4-nano",
651
+ isDefault: false,
652
+ strengths: "Cheapest and fastest GPT-5 tier \u2014 reserve for trivial deterministic transforms, routing, and classification, not complex authoring.",
653
+ bestFor: ["fast-cheap"]
654
+ },
655
+ // Anthropic models (routed via Anthropic direct, with Vertex/Bedrock fallback)
656
+ {
657
+ provider: "runtype",
658
+ modelId: "claude-haiku-4-5",
659
+ isDefault: false,
660
+ strengths: "Fast and inexpensive while retaining real reasoning, tool-use, and vision \u2014 great for high-volume task steps that still need some judgment.",
661
+ bestFor: ["fast-cheap", "agentic-tools", "vision"]
662
+ },
663
+ {
664
+ provider: "runtype",
665
+ modelId: "claude-sonnet-5",
666
+ isDefault: false,
667
+ strengths: "Balanced all-rounder: strong reasoning, very reliable multi-round tool loops, vision, and a 1M context \u2014 an excellent choice for agentic and structured work.",
668
+ bestFor: ["default", "agentic-tools", "vision", "long-context"]
669
+ },
670
+ {
671
+ provider: "runtype",
672
+ modelId: "claude-opus-4-8",
673
+ isDefault: false,
674
+ strengths: "Deepest reasoning and planning for hard analysis and multi-constraint synthesis, with vision and a 1M context \u2014 premium-priced, so reserve for genuinely difficult steps.",
675
+ bestFor: ["deep-reasoning", "vision", "long-context"]
676
+ },
677
+ // Google models (routed via Google direct, with Vertex/Vercel fallback)
678
+ {
679
+ provider: "runtype",
680
+ modelId: "gemini-3-1-flash-lite",
681
+ isDefault: false,
682
+ strengths: "Very fast and very cheap with full multimodal input (vision and audio), good structured output, and a 1M context \u2014 ideal for high-volume, simple steps.",
683
+ bestFor: ["fast-cheap", "vision", "long-context"]
684
+ },
685
+ {
686
+ provider: "runtype",
687
+ modelId: "gemini-3.6-flash",
688
+ isDefault: false,
689
+ strengths: "Fast, low-cost, and natively multimodal with good reasoning, tool-use, and a 1M context \u2014 a strong choice for vision and high-throughput steps.",
690
+ bestFor: ["default", "vision", "fast-cheap", "agentic-tools", "long-context"]
691
+ },
692
+ {
693
+ provider: "runtype",
694
+ modelId: "gemini-3-1-flash-image",
695
+ isDefault: false,
696
+ strengths: "Specialised for image generation and editing (image output) \u2014 use for steps that produce images, not text reasoning.",
697
+ bestFor: ["image-generation"]
698
+ },
699
+ {
700
+ provider: "runtype",
701
+ modelId: "gemini-3.1-pro",
702
+ isDefault: false,
703
+ strengths: "Google's frontier tier: strong reasoning, a 1M context, and multimodal input \u2014 for complex analytical or long-document steps.",
704
+ bestFor: ["deep-reasoning", "vision", "long-context"]
705
+ },
706
+ // Inception models (routed via Vercel)
707
+ {
708
+ provider: "runtype",
709
+ modelId: "mercury-2",
710
+ isDefault: false,
711
+ strengths: "Diffusion-based LLM optimised for very low latency \u2014 good when speed matters more than deep reasoning.",
712
+ bestFor: ["fast-cheap"]
713
+ },
714
+ // Moonshot models (routed via Vercel)
715
+ // Kimi K2.6 is the default model: a reasoning + tool-use + vision model
716
+ // already trusted as the product-generator default.
717
+ {
718
+ provider: "runtype",
719
+ modelId: "kimi-k2.6",
720
+ isDefault: true,
721
+ strengths: "Capable open agentic model with reasoning, tool-use, and vision at strong value \u2014 the current account default and a dependable general workhorse.",
722
+ bestFor: ["default", "agentic-tools", "vision"]
723
+ },
724
+ // NVIDIA Nemotron Ultra (reasoning + tool-use flagship, routed via Vercel)
725
+ {
726
+ provider: "runtype",
727
+ modelId: "nemotron-3-ultra-550b-a55b",
728
+ isDefault: false,
729
+ strengths: "Large open-weight reasoning and tool-use flagship with a 1M context at a low price \u2014 strong analytical depth where an open model is preferred.",
730
+ bestFor: ["deep-reasoning", "agentic-tools", "long-context"]
731
+ },
732
+ // Google models (routed via Cloudflare Workers AI)
733
+ {
734
+ provider: "runtype",
735
+ modelId: "gemma-4-26b-a4b-it",
736
+ isDefault: false,
737
+ strengths: "Lightweight open-weight instruct model served free on Workers AI \u2014 fine for straightforward general tasks at zero cost.",
738
+ bestFor: ["fast-cheap"]
739
+ },
740
+ // Z.ai GLM-5.2 (agentic coding flagship, routed via Cloudflare Workers AI,
741
+ // Vercel fallback). The bare routed name resolves to `@cf/zai-org/glm-5.2`.
742
+ {
743
+ provider: "runtype",
744
+ modelId: "glm-5.2",
745
+ isDefault: false,
746
+ strengths: "Agentic flagship \u2014 best-in-class at long, multi-round tool-call loops and coding/agent workflows, with a 1M context; well suited to tool-heavy agent steps.",
747
+ bestFor: ["agentic-tools", "default", "deep-reasoning", "long-context"]
748
+ }
749
+ ];
750
+ var DEFAULT_MODEL_ID = DEFAULT_MODELS_FOR_NEW_ACCOUNTS.find((m2) => m2.isDefault)?.modelId ?? "kimi-k2.6";
751
+ function renderDefaultModelStrengthsGuide() {
752
+ return DEFAULT_MODELS_FOR_NEW_ACCOUNTS.map(
753
+ (m2) => `- \`${m2.modelId}\`${m2.isDefault ? " (account default)" : ""} \u2014 ${m2.strengths}`
754
+ ).join("\n");
755
+ }
756
+
622
757
  // ../shared/dist/chunk-72QEJTK5.mjs
623
758
  var travrseConfig = {
624
759
  name: "Travrse",
@@ -15260,142 +15395,7 @@ var edgeContextPayloadSchema = external_exports.object({
15260
15395
  // ../shared/dist/chunk-SCJRL6LP.mjs
15261
15396
  var MAX_DURABLE_POLL_ATTEMPTS = 1e3;
15262
15397
 
15263
- // ../shared/dist/chunk-R7RM64AL.mjs
15264
- var DEFAULT_MODELS_FOR_NEW_ACCOUNTS = [
15265
- // Mixlayer models
15266
- {
15267
- provider: "runtype",
15268
- modelId: "qwen/qwen3.6-27b",
15269
- isDefault: false,
15270
- strengths: "Fast, low-cost open-weight workhorse with reasoning, tool-use, and vision \u2014 good for high-volume extraction, classification, and simple transforms.",
15271
- bestFor: ["fast-cheap", "vision"]
15272
- },
15273
- // Routed models - benefit from automatic provider optimization
15274
- // OpenAI models (routed via OpenAI direct, with Vercel fallback)
15275
- {
15276
- provider: "runtype",
15277
- modelId: "gpt-5.5",
15278
- isDefault: false,
15279
- strengths: "Top-tier general reasoning and tool-use with excellent structured-output reliability, vision, and a 1M context \u2014 a strong pick for complex, correctness-sensitive steps.",
15280
- bestFor: ["default", "deep-reasoning", "agentic-tools", "vision", "long-context"]
15281
- },
15282
- {
15283
- provider: "runtype",
15284
- modelId: "gpt-5.4-mini",
15285
- isDefault: false,
15286
- strengths: "Fast and affordable with dependable JSON formatting \u2014 a good fit for mid-complexity task steps.",
15287
- bestFor: ["fast-cheap", "default"]
15288
- },
15289
- {
15290
- provider: "runtype",
15291
- modelId: "gpt-5.4-nano",
15292
- isDefault: false,
15293
- strengths: "Cheapest and fastest GPT-5 tier \u2014 reserve for trivial deterministic transforms, routing, and classification, not complex authoring.",
15294
- bestFor: ["fast-cheap"]
15295
- },
15296
- // Anthropic models (routed via Anthropic direct, with Vertex/Bedrock fallback)
15297
- {
15298
- provider: "runtype",
15299
- modelId: "claude-haiku-4-5",
15300
- isDefault: false,
15301
- strengths: "Fast and inexpensive while retaining real reasoning, tool-use, and vision \u2014 great for high-volume task steps that still need some judgment.",
15302
- bestFor: ["fast-cheap", "agentic-tools", "vision"]
15303
- },
15304
- {
15305
- provider: "runtype",
15306
- modelId: "claude-sonnet-5",
15307
- isDefault: false,
15308
- strengths: "Balanced all-rounder: strong reasoning, very reliable multi-round tool loops, vision, and a 1M context \u2014 an excellent choice for agentic and structured work.",
15309
- bestFor: ["default", "agentic-tools", "vision", "long-context"]
15310
- },
15311
- {
15312
- provider: "runtype",
15313
- modelId: "claude-opus-4-8",
15314
- isDefault: false,
15315
- strengths: "Deepest reasoning and planning for hard analysis and multi-constraint synthesis, with vision and a 1M context \u2014 premium-priced, so reserve for genuinely difficult steps.",
15316
- bestFor: ["deep-reasoning", "vision", "long-context"]
15317
- },
15318
- // Google models (routed via Google direct, with Vertex/Vercel fallback)
15319
- {
15320
- provider: "runtype",
15321
- modelId: "gemini-3-1-flash-lite",
15322
- isDefault: false,
15323
- strengths: "Very fast and very cheap with full multimodal input (vision and audio), good structured output, and a 1M context \u2014 ideal for high-volume, simple steps.",
15324
- bestFor: ["fast-cheap", "vision", "long-context"]
15325
- },
15326
- {
15327
- provider: "runtype",
15328
- modelId: "gemini-3.6-flash",
15329
- isDefault: false,
15330
- strengths: "Fast, low-cost, and natively multimodal with good reasoning, tool-use, and a 1M context \u2014 a strong choice for vision and high-throughput steps.",
15331
- bestFor: ["default", "vision", "fast-cheap", "agentic-tools", "long-context"]
15332
- },
15333
- {
15334
- provider: "runtype",
15335
- modelId: "gemini-3-1-flash-image",
15336
- isDefault: false,
15337
- strengths: "Specialised for image generation and editing (image output) \u2014 use for steps that produce images, not text reasoning.",
15338
- bestFor: ["image-generation"]
15339
- },
15340
- {
15341
- provider: "runtype",
15342
- modelId: "gemini-3.1-pro",
15343
- isDefault: false,
15344
- strengths: "Google's frontier tier: strong reasoning, a 1M context, and multimodal input \u2014 for complex analytical or long-document steps.",
15345
- bestFor: ["deep-reasoning", "vision", "long-context"]
15346
- },
15347
- // Inception models (routed via Vercel)
15348
- {
15349
- provider: "runtype",
15350
- modelId: "mercury-2",
15351
- isDefault: false,
15352
- strengths: "Diffusion-based LLM optimised for very low latency \u2014 good when speed matters more than deep reasoning.",
15353
- bestFor: ["fast-cheap"]
15354
- },
15355
- // Moonshot models (routed via Vercel)
15356
- // Kimi K2.6 is the default model: a reasoning + tool-use + vision model
15357
- // already trusted as the product-generator default.
15358
- {
15359
- provider: "runtype",
15360
- modelId: "kimi-k2.6",
15361
- isDefault: true,
15362
- strengths: "Capable open agentic model with reasoning, tool-use, and vision at strong value \u2014 the current account default and a dependable general workhorse.",
15363
- bestFor: ["default", "agentic-tools", "vision"]
15364
- },
15365
- // NVIDIA Nemotron Ultra (reasoning + tool-use flagship, routed via Vercel)
15366
- {
15367
- provider: "runtype",
15368
- modelId: "nemotron-3-ultra-550b-a55b",
15369
- isDefault: false,
15370
- strengths: "Large open-weight reasoning and tool-use flagship with a 1M context at a low price \u2014 strong analytical depth where an open model is preferred.",
15371
- bestFor: ["deep-reasoning", "agentic-tools", "long-context"]
15372
- },
15373
- // Google models (routed via Cloudflare Workers AI)
15374
- {
15375
- provider: "runtype",
15376
- modelId: "gemma-4-26b-a4b-it",
15377
- isDefault: false,
15378
- strengths: "Lightweight open-weight instruct model served free on Workers AI \u2014 fine for straightforward general tasks at zero cost.",
15379
- bestFor: ["fast-cheap"]
15380
- },
15381
- // Z.ai GLM-5.2 (agentic coding flagship, routed via Cloudflare Workers AI,
15382
- // Vercel fallback). The bare routed name resolves to `@cf/zai-org/glm-5.2`.
15383
- {
15384
- provider: "runtype",
15385
- modelId: "glm-5.2",
15386
- isDefault: false,
15387
- strengths: "Agentic flagship \u2014 best-in-class at long, multi-round tool-call loops and coding/agent workflows, with a 1M context; well suited to tool-heavy agent steps.",
15388
- bestFor: ["agentic-tools", "default", "deep-reasoning", "long-context"]
15389
- }
15390
- ];
15391
- var DEFAULT_MODEL_ID = DEFAULT_MODELS_FOR_NEW_ACCOUNTS.find((m2) => m2.isDefault)?.modelId ?? "kimi-k2.6";
15392
- function renderDefaultModelStrengthsGuide() {
15393
- return DEFAULT_MODELS_FOR_NEW_ACCOUNTS.map(
15394
- (m2) => `- \`${m2.modelId}\`${m2.isDefault ? " (account default)" : ""} \u2014 ${m2.strengths}`
15395
- ).join("\n");
15396
- }
15397
-
15398
- // ../shared/dist/chunk-UB6BK3TZ.mjs
15398
+ // ../shared/dist/chunk-FXAUIBCA.mjs
15399
15399
  function getNestedValue(obj, path20) {
15400
15400
  let normalizedPath = path20;
15401
15401
  normalizedPath = normalizedPath.replace(/^\$\.?/, "");
@@ -15786,7 +15786,17 @@ function resolveFallback(parsed, context, tracking, options = {}) {
15786
15786
  }
15787
15787
  var templateEngine = new SimpleTemplateEngine();
15788
15788
 
15789
- // ../shared/dist/chunk-3DRXBLKO.mjs
15789
+ // ../shared/dist/chunk-HSXV5L7C.mjs
15790
+ var jsonPatchOperationSchema = external_exports.object({
15791
+ op: external_exports.enum(["add", "remove", "replace", "move", "copy", "test"]),
15792
+ /** JSON Pointer (RFC 6901) into the state document. `''` addresses the root. */
15793
+ path: external_exports.string(),
15794
+ /** Operand for `add` / `replace` / `test`. */
15795
+ value: external_exports.unknown().optional(),
15796
+ /** Source pointer for `move` / `copy`. */
15797
+ from: external_exports.string().optional()
15798
+ });
15799
+ var jsonPatchSchema = external_exports.array(jsonPatchOperationSchema);
15790
15800
  var tokensSchema = external_exports.object({ input: external_exports.number(), output: external_exports.number() });
15791
15801
  var wireStopReasonSchema = external_exports.enum([
15792
15802
  "end_turn",
@@ -16074,6 +16084,19 @@ var unifiedSourceEventSchema = external_exports.object({
16074
16084
  title: external_exports.string().optional(),
16075
16085
  sourceType: external_exports.string().optional()
16076
16086
  }).passthrough();
16087
+ var unifiedStateSnapshotEventSchema = external_exports.object({
16088
+ ...unifiedBase,
16089
+ type: external_exports.literal("state_snapshot"),
16090
+ /** The complete state document (open JSON, verbatim). */
16091
+ state: external_exports.record(external_exports.string(), external_exports.unknown()),
16092
+ iteration: external_exports.number().optional()
16093
+ });
16094
+ var unifiedStateDeltaEventSchema = external_exports.object({
16095
+ ...unifiedBase,
16096
+ type: external_exports.literal("state_delta"),
16097
+ patch: jsonPatchSchema,
16098
+ iteration: external_exports.number().optional()
16099
+ });
16077
16100
  var unifiedToolStartEventSchema = external_exports.object({
16078
16101
  ...unifiedBase,
16079
16102
  type: external_exports.literal("tool_start"),
@@ -16242,6 +16265,8 @@ var unifiedSSEEventSchema = external_exports.discriminatedUnion("type", [
16242
16265
  unifiedArtifactUpdateEventSchema,
16243
16266
  unifiedArtifactCompleteEventSchema,
16244
16267
  unifiedSourceEventSchema,
16268
+ unifiedStateSnapshotEventSchema,
16269
+ unifiedStateDeltaEventSchema,
16245
16270
  unifiedToolStartEventSchema,
16246
16271
  unifiedToolInputDeltaEventSchema,
16247
16272
  unifiedToolInputCompleteEventSchema,
@@ -16278,6 +16303,8 @@ var UNIFIED_SSE_EVENT_TYPES = _unifiedTuple([
16278
16303
  "artifact_update",
16279
16304
  "artifact_complete",
16280
16305
  "source",
16306
+ "state_snapshot",
16307
+ "state_delta",
16281
16308
  "tool_start",
16282
16309
  "tool_input_delta",
16283
16310
  "tool_input_complete",
@@ -16412,6 +16439,7 @@ var agentToolStartEventSchema = external_exports.object({
16412
16439
  "local"
16413
16440
  ]),
16414
16441
  parameters: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
16442
+ hiddenParameterNames: external_exports.array(external_exports.string()).optional(),
16415
16443
  origin: external_exports.enum(["webmcp", "sdk"]).optional(),
16416
16444
  pageOrigin: external_exports.string().optional()
16417
16445
  });
@@ -16463,6 +16491,19 @@ var agentMediaEventSchema = external_exports.object({
16463
16491
  toolName: external_exports.string(),
16464
16492
  media: external_exports.array(mediaContentPartSchema)
16465
16493
  });
16494
+ var agentStateSnapshotEventSchema = external_exports.object({
16495
+ ...baseAgentEvent,
16496
+ type: external_exports.literal("agent_state_snapshot"),
16497
+ /** The complete state document. Verbatim — never summarized. */
16498
+ state: external_exports.record(external_exports.string(), external_exports.unknown()),
16499
+ iteration: external_exports.number().optional()
16500
+ });
16501
+ var agentStateDeltaEventSchema = external_exports.object({
16502
+ ...baseAgentEvent,
16503
+ type: external_exports.literal("agent_state_delta"),
16504
+ patch: jsonPatchSchema,
16505
+ iteration: external_exports.number().optional()
16506
+ });
16466
16507
  var agentApprovalStartEventSchema = external_exports.object({
16467
16508
  ...baseAgentEvent,
16468
16509
  type: external_exports.literal("agent_approval_start"),
@@ -16608,6 +16649,8 @@ var agentSSEEventSchema = external_exports.discriminatedUnion("type", [
16608
16649
  agentToolInputCompleteEventSchema,
16609
16650
  agentToolCompleteEventSchema,
16610
16651
  agentMediaEventSchema,
16652
+ agentStateSnapshotEventSchema,
16653
+ agentStateDeltaEventSchema,
16611
16654
  agentApprovalStartEventSchema,
16612
16655
  agentApprovalCompleteEventSchema,
16613
16656
  agentAwaitEventSchema,
@@ -17017,7 +17060,7 @@ var artifactSSEEventSchema = external_exports.discriminatedUnion("type", [
17017
17060
  ]);
17018
17061
  var UNIFIED_SSE_EVENT_TYPE_SET = new Set(UNIFIED_SSE_EVENT_TYPES);
17019
17062
 
17020
- // ../shared/dist/chunk-REUID6D4.mjs
17063
+ // ../shared/dist/chunk-UG3J37K4.mjs
17021
17064
  function parseHTMLWithRegex(html) {
17022
17065
  if (typeof html !== "string") {
17023
17066
  throw new Error("parseHTML: input must be a string");
@@ -17025,7 +17068,7 @@ function parseHTMLWithRegex(html) {
17025
17068
  try {
17026
17069
  const parser = {
17027
17070
  stripTags(value) {
17028
- return value.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
17071
+ return value.replace(/<[^>]*>/g, " ").replace(/<(\/?[a-zA-Z][^>]*)$/, "&lt;$1").replace(/\s+/g, " ").trim();
17029
17072
  },
17030
17073
  querySelector(selector) {
17031
17074
  try {
@@ -17175,7 +17218,7 @@ function createPortableHelpers(parseHTML) {
17175
17218
  if (typeof html !== "string") {
17176
17219
  return "";
17177
17220
  }
17178
- return html.replace(/<h1[^>]*>(.*?)<\/h1>/gim, "# $1\n\n").replace(/<h2[^>]*>(.*?)<\/h2>/gim, "## $1\n\n").replace(/<h3[^>]*>(.*?)<\/h3>/gim, "### $1\n\n").replace(/<h4[^>]*>(.*?)<\/h4>/gim, "#### $1\n\n").replace(/<h5[^>]*>(.*?)<\/h5>/gim, "##### $1\n\n").replace(/<h6[^>]*>(.*?)<\/h6>/gim, "###### $1\n\n").replace(/<strong[^>]*>(.*?)<\/strong>/gim, "**$1**").replace(/<b[^>]*>(.*?)<\/b>/gim, "**$1**").replace(/<em[^>]*>(.*?)<\/em>/gim, "*$1*").replace(/<i[^>]*>(.*?)<\/i>/gim, "*$1*").replace(/<code[^>]*>(.*?)<\/code>/gim, "`$1`").replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gim, "[$2]($1)").replace(/<br[^>]*>/gim, "\n").replace(/<\/p>/gim, "\n\n").replace(/<p[^>]*>/gim, "").replace(/<li[^>]*>(.*?)<\/li>/gim, "- $1\n").replace(/<ul[^>]*>/gim, "\n").replace(/<\/ul>/gim, "\n").replace(/<ol[^>]*>/gim, "\n").replace(/<\/ol>/gim, "\n").replace(/<[^>]+>/gim, "").replace(/\n\s*\n\s*\n/gim, "\n\n").trim();
17221
+ return html.replace(/<h1[^>]*>(.*?)<\/h1>/gim, "# $1\n\n").replace(/<h2[^>]*>(.*?)<\/h2>/gim, "## $1\n\n").replace(/<h3[^>]*>(.*?)<\/h3>/gim, "### $1\n\n").replace(/<h4[^>]*>(.*?)<\/h4>/gim, "#### $1\n\n").replace(/<h5[^>]*>(.*?)<\/h5>/gim, "##### $1\n\n").replace(/<h6[^>]*>(.*?)<\/h6>/gim, "###### $1\n\n").replace(/<strong[^>]*>(.*?)<\/strong>/gim, "**$1**").replace(/<b[^>]*>(.*?)<\/b>/gim, "**$1**").replace(/<em[^>]*>(.*?)<\/em>/gim, "*$1*").replace(/<i[^>]*>(.*?)<\/i>/gim, "*$1*").replace(/<code[^>]*>(.*?)<\/code>/gim, "`$1`").replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gim, "[$2]($1)").replace(/<br[^>]*>/gim, "\n").replace(/<\/p>/gim, "\n\n").replace(/<p[^>]*>/gim, "").replace(/<li[^>]*>(.*?)<\/li>/gim, "- $1\n").replace(/<ul[^>]*>/gim, "\n").replace(/<\/ul>/gim, "\n").replace(/<ol[^>]*>/gim, "\n").replace(/<\/ol>/gim, "\n").replace(/<[^>]*>/gim, "").replace(/<(\/?[a-zA-Z][^>]*)$/, "&lt;$1").replace(/\n\s*\n\s*\n/gim, "\n\n").trim();
17179
17222
  },
17180
17223
  /**
17181
17224
  * Parse date from various string formats
@@ -17435,6 +17478,14 @@ var toolCallResultEventSchema = external_exports.object({
17435
17478
  content: external_exports.string(),
17436
17479
  role: external_exports.literal("tool").optional()
17437
17480
  });
17481
+ var stateSnapshotEventSchema = external_exports.object({
17482
+ type: external_exports.literal("STATE_SNAPSHOT"),
17483
+ snapshot: external_exports.record(external_exports.string(), external_exports.unknown())
17484
+ });
17485
+ var stateDeltaEventSchema = external_exports.object({
17486
+ type: external_exports.literal("STATE_DELTA"),
17487
+ delta: jsonPatchSchema
17488
+ });
17438
17489
  var reasoningStartEventSchema = external_exports.object({
17439
17490
  type: external_exports.literal("REASONING_START"),
17440
17491
  messageId: external_exports.string()
@@ -17476,6 +17527,8 @@ var agUiSSEEventSchema = external_exports.discriminatedUnion("type", [
17476
17527
  toolCallArgsEventSchema,
17477
17528
  toolCallEndEventSchema,
17478
17529
  toolCallResultEventSchema,
17530
+ stateSnapshotEventSchema,
17531
+ stateDeltaEventSchema,
17479
17532
  reasoningStartEventSchema,
17480
17533
  reasoningMessageStartEventSchema,
17481
17534
  reasoningMessageContentEventSchema,
@@ -17920,7 +17973,15 @@ function isBuiltInToolId(toolId) {
17920
17973
  function isPlatformToolId(toolId) {
17921
17974
  return toolId.startsWith("platform:");
17922
17975
  }
17923
- var INTEGRATION_SERVER_IDS = /* @__PURE__ */ new Set(["slack", "google", "linear", "github", "telegram"]);
17976
+ var INTEGRATION_SERVER_IDS = /* @__PURE__ */ new Set([
17977
+ "slack",
17978
+ "google",
17979
+ "linear",
17980
+ "github",
17981
+ "telegram",
17982
+ "imessage",
17983
+ "granola"
17984
+ ]);
17924
17985
  function isBuiltInIntegrationToolId(toolId) {
17925
17986
  if (!toolId.startsWith("builtin:")) return false;
17926
17987
  const { baseId } = parseToolInstanceId(toolId);
@@ -22373,6 +22434,73 @@ var AGENT_EXECUTION_STATUSES = [
22373
22434
  "interrupted"
22374
22435
  ];
22375
22436
  var agentExecutionStatusSchema = external_exports.enum(AGENT_EXECUTION_STATUSES);
22437
+ var END_USER_USAGE_PERIODS = ["billing_period", "7d", "30d", "90d"];
22438
+ var endUserUsageQuerySchema = external_exports.object({
22439
+ productId: external_exports.string().min(1),
22440
+ productTenantId: external_exports.string().min(1).optional(),
22441
+ period: external_exports.enum(END_USER_USAGE_PERIODS).optional(),
22442
+ days: external_exports.coerce.number().int().min(1).max(93).optional(),
22443
+ sort: external_exports.enum(["spend", "executions"]).default("spend"),
22444
+ limit: external_exports.coerce.number().int().min(1).max(200).default(50)
22445
+ }).refine((value) => !(value.period && value.days), {
22446
+ message: "Use either period or days, not both",
22447
+ path: ["days"]
22448
+ });
22449
+ var endUserUsageMoneySchema = external_exports.object({
22450
+ spendThousandthsCent: external_exports.number().int().nonnegative(),
22451
+ spendDollars: external_exports.number().nonnegative()
22452
+ });
22453
+ var endUserUsageResponseSchema = external_exports.object({
22454
+ generatedAt: external_exports.string(),
22455
+ period: external_exports.object({
22456
+ startDate: external_exports.string(),
22457
+ endDate: external_exports.string(),
22458
+ days: external_exports.number().int().positive(),
22459
+ preset: external_exports.enum(END_USER_USAGE_PERIODS).optional()
22460
+ }),
22461
+ scope: external_exports.object({
22462
+ productId: external_exports.string(),
22463
+ productTenantId: external_exports.string().nullable()
22464
+ }),
22465
+ /**
22466
+ * Distinct tenant ids with usage in the window, computed independently of
22467
+ * the `productTenantId` filter (most spend first, capped at 200), so a
22468
+ * tenant picker stays complete while a tenant-scoped page is shown.
22469
+ */
22470
+ tenantIds: external_exports.array(external_exports.string()),
22471
+ retention: external_exports.object({
22472
+ attributionStartedAt: external_exports.string().nullable(),
22473
+ earliestAvailableAt: external_exports.string().nullable(),
22474
+ retentionDays: external_exports.literal(93)
22475
+ }),
22476
+ totals: external_exports.object({
22477
+ executions: external_exports.number().int().nonnegative()
22478
+ }).merge(endUserUsageMoneySchema),
22479
+ coverage: external_exports.object({
22480
+ attributedExecutions: external_exports.number().int().nonnegative(),
22481
+ unattributedExecutions: external_exports.number().int().nonnegative(),
22482
+ attributedSpendThousandthsCent: external_exports.number().int().nonnegative(),
22483
+ unattributedSpendThousandthsCent: external_exports.number().int().nonnegative()
22484
+ }),
22485
+ endUsers: external_exports.array(
22486
+ external_exports.object({
22487
+ endUser: external_exports.object({
22488
+ id: external_exports.string(),
22489
+ name: external_exports.string().nullable(),
22490
+ email: external_exports.string().nullable(),
22491
+ productTenantId: external_exports.string().nullable()
22492
+ }),
22493
+ executions: external_exports.number().int().nonnegative(),
22494
+ costPerExecutionDollars: external_exports.number().nonnegative().nullable(),
22495
+ lastSeenAt: external_exports.string()
22496
+ }).merge(endUserUsageMoneySchema)
22497
+ ),
22498
+ unattributed: external_exports.object({
22499
+ executions: external_exports.number().int().nonnegative()
22500
+ }).merge(endUserUsageMoneySchema)
22501
+ });
22502
+ var DEFAULT_BEDROCK_REGION = "us-east-1";
22503
+ var DEFAULT_VERTEX_LOCATION = "us-central1";
22376
22504
  var PROVIDER_SECRET_SPECS = [
22377
22505
  {
22378
22506
  providerId: "mock",
@@ -22384,13 +22512,15 @@ var PROVIDER_SECRET_SPECS = [
22384
22512
  providerId: "google-vertex-anthropic",
22385
22513
  // Must come before google-vertex (shares vertex prefix) and anthropic (matches */claude-*).
22386
22514
  matches: (m2) => m2.startsWith("vertex-anthropic/"),
22387
- secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_VERTEX_CREDENTIALS"]
22515
+ secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_CREDENTIALS"],
22516
+ optionalSettings: [{ name: "GOOGLE_VERTEX_LOCATION", defaultValue: DEFAULT_VERTEX_LOCATION }]
22388
22517
  },
22389
22518
  {
22390
22519
  providerId: "google-vertex",
22391
22520
  // Must come before google (matches */gemini-*).
22392
22521
  matches: (m2) => m2.startsWith("vertex/"),
22393
- secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_VERTEX_CREDENTIALS"]
22522
+ secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_CREDENTIALS"],
22523
+ optionalSettings: [{ name: "GOOGLE_VERTEX_LOCATION", defaultValue: DEFAULT_VERTEX_LOCATION }]
22394
22524
  },
22395
22525
  {
22396
22526
  providerId: "vercel-gateway",
@@ -22407,7 +22537,8 @@ var PROVIDER_SECRET_SPECS = [
22407
22537
  {
22408
22538
  providerId: "bedrock",
22409
22539
  matches: (m2) => m2.startsWith("bedrock/"),
22410
- secretNames: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"]
22540
+ secretNames: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
22541
+ optionalSettings: [{ name: "AWS_REGION", defaultValue: DEFAULT_BEDROCK_REGION }]
22411
22542
  },
22412
22543
  {
22413
22544
  providerId: "tinfoil",
@@ -22420,15 +22551,6 @@ var PROVIDER_SECRET_SPECS = [
22420
22551
  matches: (m2) => m2.startsWith("generic-openai/") || m2.startsWith("generic-openai:"),
22421
22552
  secretNames: ["GENERIC_OPENAI_API_KEY", "GENERIC_OPENAI_BASE_URL"]
22422
22553
  },
22423
- {
22424
- providerId: "general-compute",
22425
- // General Compute (https://api.generalcompute.com/v1) is an OpenAI-compatible
22426
- // host. Models are addressed only with the explicit `general-compute/` prefix
22427
- // (e.g. `general-compute/minimax-m2.7`) so they never collide with the same
22428
- // bare model id served by another gateway (Vercel already routes `minimax-m2.7`).
22429
- matches: (m2) => m2.startsWith("general-compute/") || m2.startsWith("general-compute:"),
22430
- secretNames: ["GENERAL_COMPUTE_API_KEY"]
22431
- },
22432
22554
  {
22433
22555
  providerId: "workers-ai",
22434
22556
  // Uses a CF platform binding, not a secret — secretNames is intentionally empty.
@@ -22478,6 +22600,13 @@ function resolveModelSecretNames(model) {
22478
22600
  }
22479
22601
  return [];
22480
22602
  }
22603
+ function resolveModelOptionalSettings(model) {
22604
+ const lower = model.toLowerCase();
22605
+ for (const spec of PROVIDER_SECRET_SPECS) {
22606
+ if (spec.matches(lower)) return [...spec.optionalSettings ?? []];
22607
+ }
22608
+ return [];
22609
+ }
22481
22610
  var RUNTIME_ARTIFACT_MANIFEST_VERSION = "2026-06-08";
22482
22611
  var runtimeArtifactResourceTypeSchema = external_exports.enum(["flow", "agent"]);
22483
22612
  var runtimeArtifactEntrypointSchema = external_exports.enum(["flow", "agent"]);
@@ -22585,6 +22714,92 @@ var runtimeArtifactManifestSchema = external_exports.object({
22585
22714
  reasons: external_exports.array(runtimeArtifactEligibilityReasonSchema)
22586
22715
  })
22587
22716
  });
22717
+ var KNOWN_FLOW_STEP_TYPES = new Set(FLOW_STEP_TYPES);
22718
+ var API_INPROCESS_CAPABILITY_MATRIX = {
22719
+ target: "api-inprocess",
22720
+ // Bumped 2026-07-31: adds the §A1 `unmaterializedPromptToolRefs` fold (prompt
22721
+ // `toolIds` classes with no runtime lane). Carries forward 2026-07-30: the
22722
+ // IMPLICIT platform-default fallback candidate no longer folds (see
22723
+ // `implicitPlatformFallback` below). Carries forward
22724
+ // 2026-07-29.4: api-hosted runtime fulfills managed fetch methods through
22725
+ // ManagedFetchExecutor (the managed-fetch fact remains for attribution). The
22726
+ // EXPLICIT Layer-2 fallback fold and the remaining parity-audit folds are
22727
+ // unchanged.
22728
+ version: "2026-07-31.1",
22729
+ unsupportedStepTypes: ["wait-until", "crawl"],
22730
+ unsupportedFeatures: {
22731
+ approvalSteps: true,
22732
+ batchInputMode: true,
22733
+ claudeManagedAgent: true,
22734
+ inexpressibleVectorStep: true,
22735
+ unresolvableAgentRef: true,
22736
+ conditionalNestedPromptStep: true,
22737
+ conditionalNestedExecuteAgentStep: true,
22738
+ // SUPPORTED as of 2026-07-23 (slice 6 activation): the runtime flow lane
22739
+ // now PAUSES on definition-embedded client-executed (local / webmcp) tools
22740
+ // — `ClientToolRequiredError` → `step_await` / `flow_await` → durable KV
22741
+ // ResumeState → the runtime continuation leg — instead of failing the call
22742
+ // in-band. The `hasClientExecutedTools` FACT is still computed (for
22743
+ // decision-attribution logs), but it no longer folds the flow to legacy.
22744
+ // Rollback lever after retiring the flow request override: revert this bit
22745
+ // to `true` (the agent lane retains its separate rollout gate).
22746
+ clientExecutedTools: false,
22747
+ advisorTools: true,
22748
+ // G2 SUPPORTED: api-hosted runtime delegates Firecrawl / Massive fetch-url
22749
+ // methods through ManagedFetchExecutor to the same API implementations the
22750
+ // legacy executor uses. Keep the fact computed for attribution, like
22751
+ // clientExecutedTools above.
22752
+ unsupportedFetchMethod: false,
22753
+ // Remaining 2026-07-29 parity-audit BRIDGE folds (G4/G5/G10/G14): feature
22754
+ // classes the runtime flow lane still cannot faithfully run.
22755
+ transformDataCodeModeTools: true,
22756
+ unsupportedTransformExecution: true,
22757
+ promptMcpServers: true,
22758
+ promptArtifacts: true,
22759
+ // SUPPORTED as of the fallback-chain port: the runtime flow engine now
22760
+ // executes EXPLICIT author-configured Layer-2 chains and synthesizes their
22761
+ // `usedFallback` / `fallbackModel` / `fallbackExecutions` attribution, so
22762
+ // such a flow stays on the runtime lane instead of folding to legacy. The
22763
+ // `hasFallbackErrorHandling` fact is still computed — it gates the stricter
22764
+ // durable-continuation path (`runtime-durable-continuation.ts`) and provides
22765
+ // decision attribution. Rollback lever: flip this bit to `true` (plus its
22766
+ // test) to restore the fold.
22767
+ fallbackErrorHandling: false,
22768
+ // SUPPORTED as of 2026-07-30: the IMPLICIT platform-default chain (the
22769
+ // orchestrator's synthesized same-model-next-provider + cross-model rungs
22770
+ // for a prompt with NO explicit `errorHandling`) does not fold the flow to
22771
+ // legacy. Rationale: a prompt step without `errorHandling` is the DEFAULT
22772
+ // shape of nearly every hosted flow, so folding on it reverted the hosted
22773
+ // flow lane to legacy for the common case — the opposite of runtime-primary.
22774
+ // The runtime lane already carries Layer-1 resilience natively
22775
+ // (`withModelCallResilience`: TTFT + idle watchdog + bounded same-model
22776
+ // retry — packages/runtime prompt-executor.ts), so the residual delta is
22777
+ // narrow: on a retryable platform-key failure that survives Layer 1 with no
22778
+ // partial output, the runtime surfaces the step error where legacy would
22779
+ // additionally swap upstream/model. That is an availability nicety, not a
22780
+ // semantic difference — and unlike the folds above it cannot silently
22781
+ // produce a WRONG result. `hasImplicitPlatformFallbackCandidate` is still
22782
+ // computed for decision attribution. Rollback lever: flip this bit to `true`
22783
+ // (plus its test) to restore the fold.
22784
+ implicitPlatformFallback: false,
22785
+ // §A1 parity-audit BRIDGE fold: a prompt step's `toolIds` carrying a
22786
+ // reference class the runtime lane can neither materialize at export nor
22787
+ // late-resolve at the prompt seam (DB typeids, `tool:<name>` named refs,
22788
+ // `dc:` data connections). The runtime filters those out of the model
22789
+ // request silently, so the fold is what keeps a configured tool from
22790
+ // vanishing. Rollback/graduation lever: as each class gains a lane the fact
22791
+ // stops firing on its own (it reads the post-export definition); flip this
22792
+ // bit to `false` only once EVERY class has one.
22793
+ unmaterializedPromptToolRefs: true
22794
+ }
22795
+ };
22796
+ var DURABLE_HOSTED_STEP_TYPES = /* @__PURE__ */ new Set(["wait-until", "crawl"]);
22797
+ var API_DURABLE_RESUME_CAPABILITY_MATRIX = {
22798
+ ...API_INPROCESS_CAPABILITY_MATRIX,
22799
+ unsupportedStepTypes: API_INPROCESS_CAPABILITY_MATRIX.unsupportedStepTypes.filter(
22800
+ (stepType) => !DURABLE_HOSTED_STEP_TYPES.has(stepType)
22801
+ )
22802
+ };
22588
22803
  var edgeAuthSnapshotSchema = external_exports.object({
22589
22804
  /**
22590
22805
  * Schema version. A plain positive int (not a literal) so a consumer pinned
@@ -39239,6 +39454,9 @@ var userProfileFeaturesSchema = external_exports.object({
39239
39454
  // rule enables it). When false the dashboard renders byte-identical to today
39240
39455
  // (personal sentinel, personal/team chooser, personal Schematic identify).
39241
39456
  enableWorkspaceModel: external_exports.boolean(),
39457
+ // Gates the End users subview in Settings → Usage. Driven by the
39458
+ // `enable-end-user-usage-analytics` Flagship rollout flag.
39459
+ enableEndUserUsageAnalytics: external_exports.boolean(),
39242
39460
  // Gates the "OAuth apps" settings tab in the dashboard (self-serve OAuth
39243
39461
  // client registration). Driven by the `enable-self-serve-oauth-clients`
39244
39462
  // boolean flag (fail-closed in production until a rule enables it; non-prod
@@ -40006,7 +40224,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
40006
40224
  "vercel": "xiaomi/mimo-v2.5-pro"
40007
40225
  },
40008
40226
  "minimax-m2-7": {
40009
- "general-compute": "general-compute/minimax-m2.7",
40010
40227
  "togetherai": "togetherai/MiniMaxAI/MiniMax-M2.7",
40011
40228
  "vercel": "minimax/minimax-m2.7"
40012
40229
  },
@@ -40014,7 +40231,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
40014
40231
  "vercel": "minimax/minimax-m2.7-highspeed"
40015
40232
  },
40016
40233
  "minimax-m2.7": {
40017
- "general-compute": "general-compute/minimax-m2.7",
40018
40234
  "vercel": "minimax/minimax-m2.7"
40019
40235
  },
40020
40236
  "minimax-m2.7-highspeed": {
@@ -40390,7 +40606,6 @@ var PLATFORM_KEY_PROVIDER_MAP = {
40390
40606
  "vertex-anthropic": false,
40391
40607
  "tinfoil": false,
40392
40608
  "generic-openai": false,
40393
- "general-compute": true,
40394
40609
  // Keyless platform provider: there is no API key (user or platform) — the
40395
40610
  // Cloudflare `AI` binding IS the platform credential. Marking it true makes
40396
40611
  // the router's platform-spend gate apply and keeps keySource attribution
@@ -40464,13 +40679,8 @@ var MANUAL_PROVIDER_MAP_OVERRIDES = {
40464
40679
  "mixlayer": "z-ai/glm-5.2",
40465
40680
  "vercel": "zai/glm-5.2"
40466
40681
  },
40467
- // MiniMax M2.7: explicit provider IDs for the GC-primary / Vercel-fallback route.
40468
- // `general-compute` is NOT in PROVIDERS_WITHOUT_PREFIX, so resolveRoutedFamily
40469
- // prepends `general-compute/` itself — store the BARE id here to avoid a double
40470
- // prefix (`general-compute/general-compute/...`). Vercel IS prefixless, so its
40471
- // value is the gateway-form `minimax/minimax-m2.7` used as-is.
40682
+ // MiniMax M2.7: Vercel's gateway-form id.
40472
40683
  "minimax-m2.7": {
40473
- "general-compute": "minimax-m2.7",
40474
40684
  "vercel": "minimax/minimax-m2.7"
40475
40685
  }
40476
40686
  };
@@ -41388,7 +41598,55 @@ var sandboxConfigSchema = external_exports.object({
41388
41598
  instanceType: external_exports.enum(["standard-1", "standard-2", "standard-3", "standard-4"]).optional(),
41389
41599
  networkAccess: sandboxNetworkAccessSchema.optional(),
41390
41600
  ttl: external_exports.enum(["5m", "1h", "24h", "unlimited"]).optional(),
41391
- sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional()
41601
+ sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional(),
41602
+ // Operator-authored bootstrap commands. The API runs this batch once after
41603
+ // enforcing the sandbox's network policy and before the first model-authored
41604
+ // sandbox verb. Commands run in order from /workspace and must be foreground,
41605
+ // self-contained, and safe to retry after an interrupted container runtime;
41606
+ // the credential-bearing exec supervisor deliberately reaps every descendant
41607
+ // before a command returns, so setup cannot launch a daemon meant to outlive
41608
+ // it. Trusted Durable Object state plus a run-scoped memo prevents the batch
41609
+ // from being repeated for the same provisioned workspace. Changing the
41610
+ // commands or managed-secret KEY bindings creates a fresh sandbox identity;
41611
+ // rotating a value under the same key does not rerun setup.
41612
+ setupCommands: external_exports.array(external_exports.string().min(1, "setup commands must not be empty")).optional(),
41613
+ // Credential environment available ONLY to the operator-authored setup batch
41614
+ // above — never to a model-authored `bash` command. Keys are env var names;
41615
+ // values are MANAGED SECRET KEYS (e.g. `GITHUB_CLONE_TOKEN`), never raw
41616
+ // credential values. The API resolves them immediately before setup and
41617
+ // delivers them out-of-band over `cloudflareSandboxExecWithSecretEnv`, so the
41618
+ // values never appear in command strings, model-facing tool schemas, logs, or
41619
+ // spill files. Like `networkAccess`, both fields are operator Definition: the
41620
+ // model cannot author setup, name a managed secret, or grant itself one.
41621
+ //
41622
+ // TRUST BOUNDARY — read before configuring this. Every process started by a
41623
+ // credentialed setup batch can read the injected values. Keep setup authored
41624
+ // and reviewed by the operator; do not run model-, attacker-, or
41625
+ // supply-chain-authored code (for example an install script) while credentials
41626
+ // are present, and never persist a raw credential into /workspace for later
41627
+ // model access. The secret supervisor freezes pre-existing processes, reaps
41628
+ // every setup descendant, and destroys the sandbox fail-closed if cleanup
41629
+ // fails, but output redaction remains defense-in-depth rather than permission
41630
+ // to echo or transform a credential.
41631
+ // Therefore:
41632
+ // - Prefer `credentialProxies` (phantom tokens, swapped at the egress
41633
+ // proxy) for any HTTP(S) protocol it supports — the real credential
41634
+ // never enters the container at all.
41635
+ // - Scope the secret as narrowly as the provider allows (read-only,
41636
+ // single-repo) and pair it with a tight `networkAccess` profile.
41637
+ // - Keep credentialed setup separate from later uncredentialed dependency
41638
+ // installation and model-authored work.
41639
+ // Name shape and the 32-entry cap mirror the sandbox worker's
41640
+ // `validateSecretEnv`; `RUNTYPE_SECRET_COMMAND` is the worker's reserved
41641
+ // control-channel variable.
41642
+ secretEnv: external_exports.record(
41643
+ external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a valid environment variable name").refine((name) => name !== "RUNTYPE_SECRET_COMMAND", {
41644
+ message: "RUNTYPE_SECRET_COMMAND is reserved"
41645
+ }),
41646
+ external_exports.string().min(1, "must be a managed secret key")
41647
+ ).refine((record2) => Object.keys(record2).length <= 32, {
41648
+ message: "secretEnv supports at most 32 variables"
41649
+ }).optional()
41392
41650
  // NOTE: a `requireApprovalForBash` knob was forward-declared here for Phase 3
41393
41651
  // but never wired to any runtime gate, so it was REMOVED from the public
41394
41652
  // schema rather than ship a misleading, inert control (post-Fable handoff 05,
@@ -41707,7 +41965,7 @@ var identityProofSchema = external_exports.object({
41707
41965
  /** The customer-native proof (JWT / opaque session token). */
41708
41966
  token: external_exports.string().min(1).max(8192)
41709
41967
  }).describe(
41710
- "Customer-native auth proof for the Identity Exchange. When present and the surface has a matching integration, the verified tenant/end-user replace any body-asserted tenant/endUser (which are never trusted for web-embedded callers). Ignored until the Identity Exchange admission upgrade ships."
41968
+ "Customer-native auth proof for the Identity Exchange. When present and the surface has a matching integration, the verified tenant/end-user replace any body-asserted tenant/endUser (which are never trusted for web-embedded callers). When Identity Exchange admission is disabled for the caller, the proof is accepted but ignored and confers no trust."
41711
41969
  );
41712
41970
  function extractSecretReferences(template) {
41713
41971
  const keys = /* @__PURE__ */ new Set();
@@ -44774,6 +45032,27 @@ Only use a \`tool-call\` step when the tool must run deterministically at a fixe
44774
45032
  - Nullish fallback: \`{{count ?? 0}}\` \u2014 keeps 0 / "" / false (only null/undefined fall through)
44775
45033
  - Chains: \`{{a || b || "default"}}\` \u2014 supports paths and string/number/boolean/null literals; do NOT mix \`||\` and \`??\` in one expression
44776
45034
 
45035
+ ### Prompt Caching: Where Large Context Goes
45036
+
45037
+ Runtype caches the request prefix automatically on Claude models. **The part that gets REUSED across runs is the tools + \`systemPrompt\` prefix.** A second boundary is placed at the end of the last message, but a cache hit there needs the whole request \u2014 \`userPrompt\` included \u2014 to repeat byte-for-byte, which per-request task text does not. (Within one request it still helps: a multi-turn or tool-looping step re-sends the grown prompt each round-trip and reads that boundary warm.) This applies to ordinary single-shot \`prompt\` steps, not just multi-turn agents.
45038
+
45039
+ - **Large STABLE context goes in \`systemPrompt\`** \u2014 style guides, voice/tone corpora, exemplars and few-shot examples, JSON schemas, policy documents, canonical reference text. Anything identical from run to run.
45040
+ - **Per-request content goes in \`userPrompt\`** \u2014 the task, the user's input, records retrieved for this run, prior-step outputs. A 25,000-token reference corpus pasted into \`userPrompt\` sits behind per-request text, so it is re-billed as uncached input on every single run.
45041
+ - **Reuse requires a byte-identical prefix.** Two steps share a cache entry only when their tools AND their \`systemPrompt\` strings match exactly. When a flow calls the same role more than once (draft \u2192 review \u2192 redraft, or the same analysis over N items), give those steps the SAME \`systemPrompt\` and put the per-call difference in \`userPrompt\`. Two near-identical system prompts are two cache entries and zero reuse.
45042
+ - **Below the model's minimum, nothing is stamped.** The prefix must exceed the model's minimum cacheable prefix (~1,024 tokens on Sonnet/Opus-class, up to 4,096 on Haiku-class) or the request goes out uncached. Do not contort a short system prompt to chase caching \u2014 this only matters when the stable context is genuinely large or the step runs many times.
45043
+ - **Per-run variables in \`systemPrompt\` kill the prefix.** \`{{_now.*}}\`, \`{{_execution.*}}\`, and \`{{_schedule.*}}\` re-render the system prompt on every execution, so it can never produce a cross-run hit; \`validate_flow\` reports this as \`CACHE_VOLATILE_SYSTEM_PROMPT\` (recommendation). Move the changing value into \`userPrompt\` or a later step. Other variables (\`{{_user.id}}\`, step outputs) do not disable caching, but they fork the cache per distinct substituted value \u2014 keep them out of a prefix you intend several steps or runs to share.
45044
+
45045
+ \`\`\`json
45046
+ // BEFORE \u2014 the corpus rides in userPrompt and is re-sent uncached on every run,
45047
+ // and the two steps have different system prompts, so neither shares a prefix
45048
+ { "type": "prompt", "name": "Draft", "config": { "model": "claude-opus-5", "systemPrompt": "You are a copywriter.", "userPrompt": "STYLE GUIDE: <25,000 tokens of client style corpus> --- Write a launch email about {{topic}}.", "outputVariable": "draft" } }
45049
+ { "type": "prompt", "name": "Revise", "config": { "model": "claude-opus-5", "systemPrompt": "You revise copy.", "userPrompt": "STYLE GUIDE: <the same 25,000 tokens again> --- Revise this draft: {{draft}}", "outputVariable": "final" } }
45050
+
45051
+ // AFTER \u2014 one byte-identical prefix; the second step and every later run read it warm
45052
+ { "type": "prompt", "name": "Draft", "config": { "model": "claude-opus-5", "systemPrompt": "You write and revise copy for this client. STYLE GUIDE: <25,000 tokens of client style corpus>", "userPrompt": "Write a launch email about {{topic}}.", "outputVariable": "draft" } }
45053
+ { "type": "prompt", "name": "Revise", "config": { "model": "claude-opus-5", "systemPrompt": "You write and revise copy for this client. STYLE GUIDE: <25,000 tokens of client style corpus>", "userPrompt": "Revise this draft: {{draft}}", "outputVariable": "final" } }
45054
+ \`\`\`
45055
+
44777
45056
  ### Model Selection
44778
45057
 
44779
45058
  Use ONLY routed model IDs from the list below (platform-key compatible). Never
@@ -45605,6 +45884,7 @@ var AgentInputSchema = external_exports.object({
45605
45884
  frequencyPenalty: external_exports.number().min(-2).max(2).optional(),
45606
45885
  presencePenalty: external_exports.number().min(-2).max(2).optional(),
45607
45886
  seed: external_exports.number().int().optional(),
45887
+ maxTokens: agentRuntimeConfigSchema.shape.maxTokens,
45608
45888
  tools: external_exports.object({
45609
45889
  toolIds: external_exports.array(external_exports.string()).optional(),
45610
45890
  toolConfigs: external_exports.record(external_exports.string(), external_exports.record(external_exports.string(), external_exports.any())).optional(),
@@ -45638,7 +45918,8 @@ var AgentInputSchema = external_exports.object({
45638
45918
  toolPool: external_exports.array(external_exports.string()),
45639
45919
  description: external_exports.string().optional(),
45640
45920
  timeoutMs: external_exports.number().int().min(1e3).max(6e5).optional()
45641
- }).optional()
45921
+ }).optional(),
45922
+ toolSearch: toolSearchConfigSchema.optional()
45642
45923
  }).optional(),
45643
45924
  artifacts: VirtualAgentArtifactConfigSchema.optional(),
45644
45925
  loopConfig: AgentLoopConfigSchema.optional(),
@@ -45646,13 +45927,29 @@ var AgentInputSchema = external_exports.object({
45646
45927
  model: external_exports.string(),
45647
45928
  systemPrompt: external_exports.string().optional()
45648
45929
  }).optional().nullable(),
45930
+ reasoning: agentRuntimeConfigSchema.shape.reasoning,
45931
+ voice: agentRuntimeConfigSchema.shape.voice,
45932
+ errorHandling: agentRuntimeConfigSchema.shape.errorHandling,
45933
+ loggingPolicy: agentRuntimeConfigSchema.shape.loggingPolicy,
45934
+ piiRedaction: agentRuntimeConfigSchema.shape.piiRedaction,
45935
+ temporal: agentRuntimeConfigSchema.shape.temporal,
45649
45936
  memory: memoryConfigSchema.optional(),
45650
45937
  // Agent Sandbox (Linux computer). When enabled (and the enable-agent-sandbox
45651
45938
  // flag is on), dispatch injects the sandbox builtin tools + system-prompt
45652
45939
  // frame — mirroring the saved-agent execute route so the two hosted-agent
45653
45940
  // entry points stay in lockstep.
45654
- sandbox: sandboxConfigSchema.optional()
45941
+ sandbox: sandboxConfigSchema.optional(),
45942
+ tenancyStrategy: agentRuntimeConfigSchema.shape.tenancyStrategy
45655
45943
  }).superRefine((val, ctx) => {
45944
+ const unsupported = val.tenancyStrategy !== void 0 ? [["tenancyStrategy"], "tenancyStrategy is server-authored; save it on an agent"] : val.voice !== void 0 ? [["voice"], "voice is unsupported by agent dispatch"] : val.tools?.toolSearch !== void 0 ? [["tools", "toolSearch"], "toolSearch is unsupported by quick-agent dispatch"] : Object.keys(val.temporal ?? {}).some((key) => key !== "timezone") ? [["temporal"], "Only temporal.timezone is supported by agent dispatch"] : void 0;
45945
+ if (unsupported) {
45946
+ const [path20, message] = unsupported;
45947
+ ctx.addIssue({
45948
+ code: "custom",
45949
+ path: path20,
45950
+ message
45951
+ });
45952
+ }
45656
45953
  if (val.agentId) {
45657
45954
  return;
45658
45955
  }
@@ -45722,7 +46019,7 @@ var InlineClientToolSchema = external_exports.object({
45722
46019
  var ClientToolsPolicySchema = external_exports.object({
45723
46020
  allowlist: external_exports.array(external_exports.string()).optional()
45724
46021
  });
45725
- var DispatchRequestSchema = external_exports.object({
46022
+ var DispatchRequestEnvelopeSchema = external_exports.object({
45726
46023
  record: RecordInputSchema.optional(),
45727
46024
  flow: FlowInputSchema.optional(),
45728
46025
  agent: AgentInputSchema.optional(),
@@ -45759,7 +46056,9 @@ var DispatchRequestSchema = external_exports.object({
45759
46056
  * every submitted webmcp tool. See {@link ClientToolsPolicySchema}.
45760
46057
  */
45761
46058
  clientToolsPolicy: ClientToolsPolicySchema.optional(),
45762
- secrets: external_exports.record(external_exports.string(), external_exports.string()).optional(),
46059
+ secrets: external_exports.record(external_exports.string(), external_exports.string()).optional().describe(
46060
+ "Per-request credentials for agent/external-tool execution. Ignored when `flow` is the hosted target; FLOW credentials must use managed {{secret:NAME}} references."
46061
+ ),
45763
46062
  credentialProxies: external_exports.array(credentialProxyConfigSchema).max(10).optional(),
45764
46063
  inputs: external_exports.record(external_exports.string(), external_exports.any()).optional().refine(
45765
46064
  (data) => {
@@ -45785,10 +46084,11 @@ var DispatchRequestSchema = external_exports.object({
45785
46084
  id: external_exports.string().min(1)
45786
46085
  }).passthrough().optional(),
45787
46086
  // Identity Exchange proof (design §4.1): a customer-native auth token the
45788
- // broker will verify server-side and admit as `verified` tenant/end-user.
45789
- // Wire contract only for now — parsed here, consumed by NOTHING until the
45790
- // admission slice wires verification into the tenancy seam. The token is a
45791
- // live credential: never log or persist it (see identityProofSchema docs).
46087
+ // broker verifies server-side and admits as `verified` tenant/end-user when
46088
+ // Identity Exchange admission is enabled for the caller. With the rollout
46089
+ // gate disabled it remains accepted-but-ignored and confers no trust. The
46090
+ // token is a live credential: never log or persist it (see
46091
+ // identityProofSchema docs).
45792
46092
  identityProof: identityProofSchema.optional(),
45793
46093
  options: external_exports.object({
45794
46094
  streamResponse: external_exports.boolean().optional().default(true),
@@ -45800,7 +46100,7 @@ var DispatchRequestSchema = external_exports.object({
45800
46100
  debugMode: external_exports.boolean().optional().default(false),
45801
46101
  loggingPolicy: external_exports.enum(["default", "on", "off"]).optional(),
45802
46102
  useRuntimePackage: external_exports.boolean().optional().describe(
45803
- "Selects the execution engine for a streaming FLOW dispatch (two controls, A4-3). `true` forces the @runtypelabs/runtime lane (subject only to eligibility \u2014 an ineligible flow still folds to legacy silently); `false` forces the legacy engine. When omitted, the `use-runtime-package-flows` rollout flag sets the default engine for this caller. An explicit value always wins over the flag. Left undefined on purpose \u2014 do NOT default it, or the flag-as-default case becomes unreachable."
46103
+ "For FLOW dispatches this compatibility field is accepted but ignored: eligible flows always use the @runtypelabs/runtime lane, while ineligible flows still fold to legacy silently. Agent dispatches still require an explicit `true` and remain subject to their separate runtime-agent rollout gate."
45804
46104
  ),
45805
46105
  /** Route prompt model calls through an attached dashboard browser. */
45806
46106
  localInference: LocalInferenceSelectionSchema.optional(),
@@ -45867,20 +46167,23 @@ var DispatchRequestSchema = external_exports.object({
45867
46167
  storeResults: true,
45868
46168
  autoAppendMetadata: false,
45869
46169
  debugMode: false,
45870
- // useRuntimePackage intentionally omitted — absent = silent request, so
45871
- // the `use-runtime-package-flows` flag decides the default engine (A4-3).
46170
+ // useRuntimePackage intentionally omitted. Flow dispatch ignores the
46171
+ // compatibility field; agent dispatch still requires explicit true.
45872
46172
  environment: "development",
45873
46173
  createVersion: false
45874
46174
  })
45875
- }).refine((data) => data.flow || data.agent, {
45876
- message: "Either 'flow' or 'agent' configuration must be provided"
45877
- }).superRefine((data, ctx) => {
46175
+ });
46176
+ var DispatchRequestSchema = external_exports.union([
46177
+ DispatchRequestEnvelopeSchema.extend({ flow: FlowInputSchema }),
46178
+ DispatchRequestEnvelopeSchema.extend({ agent: AgentInputSchema })
46179
+ ]).superRefine((data, ctx) => {
45878
46180
  if (!data.options.localInference) return;
45879
- if (!data.options.useRuntimePackage) {
46181
+ const runtimeLaneDisabled = data.agent != null && data.options.useRuntimePackage !== true;
46182
+ if (runtimeLaneDisabled) {
45880
46183
  ctx.addIssue({
45881
46184
  code: "custom",
45882
46185
  path: ["options", "useRuntimePackage"],
45883
- message: "Local inference requires useRuntimePackage to be enabled"
46186
+ message: data.agent != null ? "Local agent inference requires useRuntimePackage to be enabled" : "Local flow inference cannot use the legacy engine"
45884
46187
  });
45885
46188
  }
45886
46189
  if (data.options.modelOverride) {
@@ -46405,6 +46708,8 @@ function normalizeCategoryToken(value) {
46405
46708
  return value.toLowerCase().replace(/[^a-z0-9]/g, "");
46406
46709
  }
46407
46710
  var HARD_BLOCK_NEEDLES = SKILL_SCAN_HARD_BLOCK_CATEGORIES.map(normalizeCategoryToken);
46711
+ var DEFAULT_STEP_TIMEOUT_MS = 5 * 60 * 1e3;
46712
+ var DEFAULT_FLOW_TIMEOUT_MS = 15 * 60 * 1e3;
46408
46713
 
46409
46714
  // src/config/env.ts
46410
46715
  function getApiUrl() {
@@ -47968,7 +48273,8 @@ flowsCommand.command("run <id>").description("Execute a flow via dispatch").opti
47968
48273
  if (!apiKey) return;
47969
48274
  const client = createCliClient(apiKey);
47970
48275
  const payload = {
47971
- flow: { id: flowId }
48276
+ flow: { id: flowId },
48277
+ options: { streamResponse: options.stream }
47972
48278
  };
47973
48279
  if (options.record) {
47974
48280
  payload.record = { id: options.record };
@@ -48009,10 +48315,7 @@ Error: ${err.message}`));
48009
48315
  } else {
48010
48316
  console.log(chalk5.gray("Executing flow..."));
48011
48317
  try {
48012
- const result = await client.dispatch.execute({
48013
- ...payload,
48014
- options: { streamResponse: false }
48015
- });
48318
+ const result = await client.dispatch.execute(payload);
48016
48319
  console.log(chalk5.green("Flow execution complete"));
48017
48320
  printJson(result);
48018
48321
  } catch (error51) {
@@ -49645,7 +49948,8 @@ promptsCommand.command("test <id>").description("Test a prompt with input").opti
49645
49948
  }
49646
49949
  }
49647
49950
  ]
49648
- }
49951
+ },
49952
+ options: { streamResponse: options.stream }
49649
49953
  };
49650
49954
  if (options.input) {
49651
49955
  payload.messages = [{ role: "user", content: options.input }];
@@ -49677,7 +49981,6 @@ Error: ${err.message}`));
49677
49981
  } else {
49678
49982
  console.log(chalk8.gray("Testing prompt..."));
49679
49983
  try {
49680
- payload.streamResponse = false;
49681
49984
  const result = await client.post("/dispatch", payload);
49682
49985
  console.log(chalk8.green("Prompt test complete"));
49683
49986
  if (options.json) {
@@ -53216,7 +53519,9 @@ import React14 from "react";
53216
53519
  import { render as render14 } from "ink";
53217
53520
  import { useState as useState15, useEffect as useEffect16 } from "react";
53218
53521
  import { readFileSync as readFileSync5 } from "fs";
53219
- import { processStream as processStream3 } from "@runtypelabs/sdk";
53522
+ import {
53523
+ processStream as processStream3
53524
+ } from "@runtypelabs/sdk";
53220
53525
  var dispatchCommand = new Command15("dispatch").description("Execute a flow or agent via the dispatch API").option("-f, --flow <id>", "Flow ID to execute").option("-a, --agent <id>", "Agent ID to execute").option("-r, --record <id>", "Existing record ID").option("--record-json <file>", "JSON file with record data").option("-m, --message <text>", "Message to send").option("-v, --variable <key=value>", "Set a variable (repeatable)", collectVariables, []).option("--stream", "Stream the response (default)", true).option("--no-stream", "Wait for complete response").option("--json", "Output as JSON").option("--debug", "Show step-level details").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
53221
53526
  if (!options.flow && !options.agent) {
53222
53527
  console.error(chalk17.red("Error: Either --flow or --agent is required"));
@@ -53225,44 +53530,50 @@ var dispatchCommand = new Command15("dispatch").description("Execute a flow or a
53225
53530
  const apiKey = await ensureAuth();
53226
53531
  if (!apiKey) return;
53227
53532
  const client = createCliClient(apiKey);
53228
- const payload = {};
53229
- if (options.flow) {
53230
- payload.flow = { id: options.flow };
53533
+ let payload;
53534
+ try {
53535
+ payload = buildDispatchRequest(options);
53536
+ } catch (error51) {
53537
+ const message = error51 instanceof Error ? error51.message : "Unknown error";
53538
+ console.error(chalk17.red(`Failed to read record JSON: ${message}`));
53539
+ process.exit(1);
53540
+ }
53541
+ if (options.stream) {
53542
+ await handleStreaming(client, payload, options);
53543
+ } else {
53544
+ await handleNonStreaming(client, payload, options);
53231
53545
  }
53546
+ });
53547
+ function collectVariables(value, previous) {
53548
+ return previous.concat([value]);
53549
+ }
53550
+ function buildDispatchRequest(options) {
53551
+ if (!options.flow && !options.agent) {
53552
+ throw new Error("Either --flow or --agent is required");
53553
+ }
53554
+ const payload = options.flow ? { flow: { id: options.flow } } : { agent: { agentId: options.agent } };
53232
53555
  if (options.agent) {
53233
- payload.agent = { id: options.agent };
53556
+ payload.agent = { agentId: options.agent };
53234
53557
  }
53235
53558
  if (options.record) {
53236
53559
  payload.record = { id: options.record };
53237
53560
  } else if (options.recordJson) {
53238
- try {
53239
- const data = JSON.parse(readFileSync5(options.recordJson, "utf-8"));
53240
- payload.record = { metadata: data };
53241
- } catch (error51) {
53242
- const message = error51 instanceof Error ? error51.message : "Unknown error";
53243
- console.error(chalk17.red(`Failed to read record JSON: ${message}`));
53244
- process.exit(1);
53245
- }
53561
+ const data = JSON.parse(readFileSync5(options.recordJson, "utf-8"));
53562
+ payload.record = { metadata: data };
53246
53563
  }
53247
53564
  if (options.message) {
53248
53565
  payload.messages = [{ role: "user", content: options.message }];
53249
53566
  }
53250
53567
  if (options.variable && options.variable.length > 0) {
53251
- const variables = {};
53252
- for (const v2 of options.variable) {
53253
- const [key, ...rest] = v2.split("=");
53254
- variables[key] = rest.join("=");
53568
+ const inputs = {};
53569
+ for (const variable of options.variable) {
53570
+ const [key, ...rest] = variable.split("=");
53571
+ inputs[key] = rest.join("=");
53255
53572
  }
53256
- payload.variables = variables;
53573
+ payload.inputs = inputs;
53257
53574
  }
53258
- if (options.stream) {
53259
- await handleStreaming(client, payload, options);
53260
- } else {
53261
- await handleNonStreaming(client, payload, options);
53262
- }
53263
- });
53264
- function collectVariables(value, previous) {
53265
- return previous.concat([value]);
53575
+ payload.options = { streamResponse: options.stream };
53576
+ return payload;
53266
53577
  }
53267
53578
  async function handleStreaming(client, payload, options) {
53268
53579
  console.log(chalk17.gray("Starting execution..."));
@@ -53316,7 +53627,6 @@ Error: ${err.message}`));
53316
53627
  async function handleNonStreaming(client, payload, options) {
53317
53628
  if (!isTTY(options)) {
53318
53629
  try {
53319
- payload.streamResponse = false;
53320
53630
  const result = await client.post("/dispatch", payload);
53321
53631
  if (options.json) {
53322
53632
  printJson(result);
@@ -53351,7 +53661,6 @@ async function handleNonStreaming(client, payload, options) {
53351
53661
  useEffect16(() => {
53352
53662
  const run2 = async () => {
53353
53663
  try {
53354
- payload.streamResponse = false;
53355
53664
  const result = await client.post("/dispatch", payload);
53356
53665
  setLoading(false);
53357
53666
  setSuccess(true);
@@ -66287,7 +66596,8 @@ agentsCommand.command("execute <id>").description("Execute an agent").requiredOp
66287
66596
  if (!apiKey) return;
66288
66597
  const client = createCliClient(apiKey);
66289
66598
  const payload = {
66290
- messages: [{ role: "user", content: options.message }]
66599
+ messages: [{ role: "user", content: options.message }],
66600
+ streamResponse: options.stream
66291
66601
  };
66292
66602
  if (options.stream) {
66293
66603
  console.log(chalk25.gray("Starting agent..."));
@@ -68562,8 +68872,8 @@ import { execFileSync } from "child_process";
68562
68872
  // src/lib/persona-init.ts
68563
68873
  init_credential_store();
68564
68874
 
68565
- // ../../node_modules/.pnpm/@runtypelabs+persona@4.13.0/node_modules/@runtypelabs/persona/dist/codegen.js
68566
- var w = "4.13.0";
68875
+ // ../../node_modules/.pnpm/@runtypelabs+persona@4.14.0/node_modules/@runtypelabs/persona/dist/codegen.js
68876
+ var w = "4.14.0";
68567
68877
  var S = w;
68568
68878
  function b(e) {
68569
68879
  return e?.cdnBase?.trim().replace(/\/+$/, "").replace(/[\\'"<>`]/g, (r) => `%${r.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`) || `https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${S}/dist`;
@@ -71946,7 +72256,20 @@ echo " npm run build \u2014 compile TypeScript"
71946
72256
  echo " gcloud run deploy --source . --region us-central1 --allow-unauthenticated --port 8080"
71947
72257
  `;
71948
72258
  }
71949
- function readme(agentNames, secretNames) {
72259
+ function formatOptionalProviderSettings(settings) {
72260
+ return settings.map((setting) => `- \`${setting.name}\` (default: \`${setting.defaultValue}\`)`).join("\n");
72261
+ }
72262
+ function optionalProviderSettingsSection(settings) {
72263
+ if (settings.length === 0) return "";
72264
+ return `
72265
+ ## Optional provider settings
72266
+
72267
+ These environment variables override runtime defaults and are not required:
72268
+
72269
+ ${formatOptionalProviderSettings(settings)}
72270
+ `;
72271
+ }
72272
+ function readme(agentNames, secretNames, optionalSettings) {
71950
72273
  const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
71951
72274
  const secretList = secretNames.length > 0 ? secretNames.map((s) => ` gcloud secrets create ${s} --data-file=-`).join("\n") : " (none detected)";
71952
72275
  return `# Runtype Deployment
@@ -71983,6 +72306,8 @@ Set these before deploying to Cloud Run:
71983
72306
 
71984
72307
  ${secretList}
71985
72308
 
72309
+ ${optionalProviderSettingsSection(optionalSettings)}
72310
+
71986
72311
  ## Deploy to Cloud Run
71987
72312
 
71988
72313
  \`\`\`bash
@@ -72280,7 +72605,7 @@ echo " wrangler dev \u2014 preview locally"
72280
72605
  echo " wrangler deploy \u2014 deploy to Cloudflare Workers"
72281
72606
  `;
72282
72607
  }
72283
- function workerReadme(agentNames, secretNames) {
72608
+ function workerReadme(agentNames, secretNames, optionalSettings) {
72284
72609
  const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
72285
72610
  const secretList = secretNames.length > 0 ? secretNames.map((s) => ` wrangler secret put ${s}`).join("\n") : " (none detected)";
72286
72611
  return `# Runtype Cloudflare Workers Deployment
@@ -72303,6 +72628,8 @@ Set each API key your agents use:
72303
72628
  ${secretList}
72304
72629
  \`\`\`
72305
72630
 
72631
+ ${optionalProviderSettingsSection(optionalSettings)}
72632
+
72306
72633
  ## Run locally
72307
72634
 
72308
72635
  \`\`\`bash
@@ -72557,7 +72884,7 @@ echo " vercel dev \u2014 preview locally"
72557
72884
  echo " vercel deploy \u2014 deploy to Vercel Functions"
72558
72885
  `;
72559
72886
  }
72560
- function vercelReadme(agentNames, secretNames) {
72887
+ function vercelReadme(agentNames, secretNames, optionalSettings) {
72561
72888
  const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
72562
72889
  const secretList = secretNames.length > 0 ? secretNames.map((s) => ` vercel env add ${s}`).join("\n") : " (none detected)";
72563
72890
  return `# Runtype Vercel Functions Deployment
@@ -72580,6 +72907,8 @@ Set each API key your agents use via the Vercel dashboard or CLI:
72580
72907
  ${secretList}
72581
72908
  \`\`\`
72582
72909
 
72910
+ ${optionalProviderSettingsSection(optionalSettings)}
72911
+
72583
72912
  ## Run locally
72584
72913
 
72585
72914
  \`\`\`bash
@@ -72605,24 +72934,113 @@ curl https://<your-project>.vercel.app/agent/<name> \\
72605
72934
  \`\`\`
72606
72935
  `;
72607
72936
  }
72608
- function collectSecretNames(agentDef) {
72609
- const names = /* @__PURE__ */ new Set();
72610
- const model = agentDef.config?.model?.toLowerCase();
72611
- if (model) {
72612
- for (const s of resolveModelSecretNames(model)) names.add(s);
72937
+ function collectExportedExecutionInventory(definition) {
72938
+ const models = /* @__PURE__ */ new Set();
72939
+ const namedSecrets = /* @__PURE__ */ new Set();
72940
+ const visited = /* @__PURE__ */ new WeakSet();
72941
+ const isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
72942
+ const addModel = (value) => {
72943
+ if (typeof value === "string" && value) models.add(value);
72944
+ };
72945
+ const walkMcpServers = (servers) => {
72946
+ if (!Array.isArray(servers)) return;
72947
+ for (const server of servers) {
72948
+ if (!isObject2(server) || !isObject2(server.auth)) continue;
72949
+ for (const key of ["tokenSecretName", "usernameSecretName", "passwordSecretName"]) {
72950
+ const value = server.auth[key];
72951
+ if (typeof value === "string" && value) namedSecrets.add(value);
72952
+ }
72953
+ }
72954
+ };
72955
+ function walkRuntimeTools(runtimeTools) {
72956
+ if (!Array.isArray(runtimeTools)) return;
72957
+ for (const tool of runtimeTools) {
72958
+ if (!isObject2(tool) || !isObject2(tool.config)) continue;
72959
+ if (isObject2(tool.config.flow)) walkFlow(tool.config.flow);
72960
+ if (isObject2(tool.config.agent)) walkAgent(tool.config.agent);
72961
+ if (isObject2(tool.config.skill)) walkRuntimeTools(tool.config.skill.resolvedTools);
72962
+ }
72963
+ }
72964
+ function walkTools(tools) {
72965
+ if (!isObject2(tools)) return;
72966
+ walkMcpServers(tools.mcpServers);
72967
+ walkRuntimeTools(tools.runtimeTools);
72968
+ }
72969
+ function walkFallbackModels(config3) {
72970
+ if (!isObject2(config3.errorHandling) || !Array.isArray(config3.errorHandling.fallbacks)) return;
72971
+ for (const fallback of config3.errorHandling.fallbacks) {
72972
+ if (isObject2(fallback) && fallback.type === "model") addModel(fallback.model);
72973
+ }
72974
+ }
72975
+ function walkSteps(steps) {
72976
+ if (!Array.isArray(steps)) return;
72977
+ for (const step of steps) {
72978
+ if (!isObject2(step) || !isObject2(step.config)) continue;
72979
+ if (step.type === "prompt") addModel(step.config.model);
72980
+ walkFallbackModels(step.config);
72981
+ walkTools(step.config.tools);
72982
+ if (step.type !== "conditional") continue;
72983
+ for (const key of ["trueSteps", "falseSteps", "otherwiseSteps"]) walkSteps(step.config[key]);
72984
+ if (Array.isArray(step.config.branches)) {
72985
+ for (const branch of step.config.branches) {
72986
+ if (isObject2(branch)) walkSteps(branch.steps);
72987
+ }
72988
+ }
72989
+ }
72613
72990
  }
72614
- const toolsCfg = agentDef.config?.tools;
72615
- const mcpServers = toolsCfg?.mcpServers;
72616
- if (mcpServers) {
72617
- for (const srv of mcpServers) {
72618
- const auth = srv.auth;
72619
- if (auth?.tokenSecretName) names.add(String(auth.tokenSecretName));
72620
- if (auth?.usernameSecretName) names.add(String(auth.usernameSecretName));
72621
- if (auth?.passwordSecretName) names.add(String(auth.passwordSecretName));
72991
+ function walkFlow(flow) {
72992
+ if (visited.has(flow)) return;
72993
+ visited.add(flow);
72994
+ walkSteps(flow.steps);
72995
+ if (isObject2(flow.agents)) {
72996
+ for (const agent of Object.values(flow.agents)) {
72997
+ if (isObject2(agent)) walkAgent(agent);
72998
+ }
72622
72999
  }
72623
73000
  }
72624
- for (const s of extractSecretReferencesFromAnyValue(agentDef)) names.add(s);
72625
- return Array.from(names);
73001
+ function walkAgent(agent) {
73002
+ if (visited.has(agent)) return;
73003
+ visited.add(agent);
73004
+ if (isObject2(agent.config)) {
73005
+ addModel(agent.config.model);
73006
+ walkTools(agent.config.tools);
73007
+ }
73008
+ if (isObject2(agent.claudeManagedConfig)) addModel(agent.claudeManagedConfig.model);
73009
+ if (isObject2(agent.primaryFlow)) walkFlow(agent.primaryFlow);
73010
+ if (Array.isArray(agent.capabilities)) {
73011
+ for (const capability of agent.capabilities) {
73012
+ if (!isObject2(capability)) continue;
73013
+ if (isObject2(capability.flow)) walkFlow(capability.flow);
73014
+ if (isObject2(capability.subAgent)) walkAgent(capability.subAgent);
73015
+ }
73016
+ }
73017
+ }
73018
+ if (isObject2(definition)) {
73019
+ if (Array.isArray(definition.steps) && !isObject2(definition.config)) walkFlow(definition);
73020
+ else walkAgent(definition);
73021
+ }
73022
+ return {
73023
+ models: Array.from(models),
73024
+ namedSecrets: Array.from(namedSecrets)
73025
+ };
73026
+ }
73027
+ function collectDeploymentSecretInventory(agentDef) {
73028
+ const requiredNames = /* @__PURE__ */ new Set();
73029
+ const optionalSettings = /* @__PURE__ */ new Map();
73030
+ const executionInventory = collectExportedExecutionInventory(agentDef);
73031
+ for (const model of executionInventory.models) {
73032
+ for (const name of resolveModelSecretNames(model)) requiredNames.add(name);
73033
+ for (const setting of resolveModelOptionalSettings(model)) {
73034
+ optionalSettings.set(setting.name, setting);
73035
+ }
73036
+ }
73037
+ for (const name of executionInventory.namedSecrets) requiredNames.add(name);
73038
+ for (const name of extractSecretReferencesFromAnyValue(agentDef, 512)) requiredNames.add(name);
73039
+ for (const name of requiredNames) optionalSettings.delete(name);
73040
+ return {
73041
+ requiredNames: Array.from(requiredNames),
73042
+ optionalSettings: Array.from(optionalSettings.values())
73043
+ };
72626
73044
  }
72627
73045
  function slugify2(s) {
72628
73046
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
@@ -72731,10 +73149,17 @@ Scaffolding ${target} deployment to ${outDir}
72731
73149
  monorepoRoot = parent;
72732
73150
  }
72733
73151
  const allSecrets = /* @__PURE__ */ new Set();
73152
+ const allOptionalSettings = /* @__PURE__ */ new Map();
72734
73153
  for (const { def } of agentDefs) {
72735
- for (const s of collectSecretNames(def)) allSecrets.add(s);
73154
+ const inventory = collectDeploymentSecretInventory(def);
73155
+ for (const name of inventory.requiredNames) allSecrets.add(name);
73156
+ for (const setting of inventory.optionalSettings) {
73157
+ allOptionalSettings.set(setting.name, setting);
73158
+ }
72736
73159
  }
73160
+ for (const name of allSecrets) allOptionalSettings.delete(name);
72737
73161
  const secretNames = Array.from(allSecrets);
73162
+ const optionalSettings = Array.from(allOptionalSettings.values());
72738
73163
  if (target === "cloudflare") {
72739
73164
  fs16.mkdirSync(path17.join(outDir, "src"), { recursive: true });
72740
73165
  fs16.writeFileSync(path17.join(outDir, "src", "index.ts"), workerIndexTs(agentSlugs));
@@ -72744,7 +73169,10 @@ Scaffolding ${target} deployment to ${outDir}
72744
73169
  const setupPath = path17.join(outDir, "setup.sh");
72745
73170
  fs16.writeFileSync(setupPath, workerSetupSh(monorepoRoot));
72746
73171
  fs16.chmodSync(setupPath, 493);
72747
- fs16.writeFileSync(path17.join(outDir, "README.md"), workerReadme(agentNames, secretNames));
73172
+ fs16.writeFileSync(
73173
+ path17.join(outDir, "README.md"),
73174
+ workerReadme(agentNames, secretNames, optionalSettings)
73175
+ );
72748
73176
  } else if (target === "vercel") {
72749
73177
  fs16.mkdirSync(path17.join(outDir, "api"), { recursive: true });
72750
73178
  fs16.writeFileSync(path17.join(outDir, "api", "[[...route]].ts"), vercelRouteTs(agentSlugs));
@@ -72754,7 +73182,10 @@ Scaffolding ${target} deployment to ${outDir}
72754
73182
  const setupPath = path17.join(outDir, "setup.sh");
72755
73183
  fs16.writeFileSync(setupPath, vercelSetupSh(monorepoRoot));
72756
73184
  fs16.chmodSync(setupPath, 493);
72757
- fs16.writeFileSync(path17.join(outDir, "README.md"), vercelReadme(agentNames, secretNames));
73185
+ fs16.writeFileSync(
73186
+ path17.join(outDir, "README.md"),
73187
+ vercelReadme(agentNames, secretNames, optionalSettings)
73188
+ );
72758
73189
  } else {
72759
73190
  fs16.writeFileSync(path17.join(outDir, "server.ts"), serverTs());
72760
73191
  fs16.writeFileSync(path17.join(outDir, "Dockerfile"), dockerfile());
@@ -72764,7 +73195,10 @@ Scaffolding ${target} deployment to ${outDir}
72764
73195
  const setupPath = path17.join(outDir, "setup.sh");
72765
73196
  fs16.writeFileSync(setupPath, setupSh(monorepoRoot));
72766
73197
  fs16.chmodSync(setupPath, 493);
72767
- fs16.writeFileSync(path17.join(outDir, "README.md"), readme(agentNames, secretNames));
73198
+ fs16.writeFileSync(
73199
+ path17.join(outDir, "README.md"),
73200
+ readme(agentNames, secretNames, optionalSettings)
73201
+ );
72768
73202
  }
72769
73203
  console.log("");
72770
73204
  console.log(chalk38.green(`\u2713 Scaffold written to ${outDir}`));
@@ -72772,6 +73206,15 @@ Scaffolding ${target} deployment to ${outDir}
72772
73206
  console.log(chalk38.bold("Next steps:"));
72773
73207
  console.log(` cd ${options.output}`);
72774
73208
  console.log(" chmod +x setup.sh && ./setup.sh # pack runtime + install deps");
73209
+ if (optionalSettings.length > 0) {
73210
+ console.log("");
73211
+ console.log(chalk38.yellow("Optional provider settings (defaults used when unset):"));
73212
+ for (const setting of optionalSettings) {
73213
+ console.log(
73214
+ ` ${chalk38.cyan(setting.name)} (default: ${chalk38.cyan(setting.defaultValue)})`
73215
+ );
73216
+ }
73217
+ }
72775
73218
  if (target === "cloudflare") {
72776
73219
  console.log(" wrangler dev # test locally");
72777
73220
  console.log("");