@runtypelabs/cli 2.32.1 → 2.32.3

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 +864 -500
  2. package/package.json +6 -6
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,141 +15395,6 @@ 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
15398
  // ../shared/dist/chunk-UB6BK3TZ.mjs
15399
15399
  function getNestedValue(obj, path20) {
15400
15400
  let normalizedPath = path20;
@@ -15786,7 +15786,7 @@ 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-MN4NECP7.mjs
15790
15790
  var tokensSchema = external_exports.object({ input: external_exports.number(), output: external_exports.number() });
15791
15791
  var wireStopReasonSchema = external_exports.enum([
15792
15792
  "end_turn",
@@ -16412,6 +16412,7 @@ var agentToolStartEventSchema = external_exports.object({
16412
16412
  "local"
16413
16413
  ]),
16414
16414
  parameters: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
16415
+ hiddenParameterNames: external_exports.array(external_exports.string()).optional(),
16415
16416
  origin: external_exports.enum(["webmcp", "sdk"]).optional(),
16416
16417
  pageOrigin: external_exports.string().optional()
16417
16418
  });
@@ -17017,6 +17018,353 @@ var artifactSSEEventSchema = external_exports.discriminatedUnion("type", [
17017
17018
  ]);
17018
17019
  var UNIFIED_SSE_EVENT_TYPE_SET = new Set(UNIFIED_SSE_EVENT_TYPES);
17019
17020
 
17021
+ // ../shared/dist/chunk-UG3J37K4.mjs
17022
+ function parseHTMLWithRegex(html) {
17023
+ if (typeof html !== "string") {
17024
+ throw new Error("parseHTML: input must be a string");
17025
+ }
17026
+ try {
17027
+ const parser = {
17028
+ stripTags(value) {
17029
+ return value.replace(/<[^>]*>/g, " ").replace(/<(\/?[a-zA-Z][^>]*)$/, "&lt;$1").replace(/\s+/g, " ").trim();
17030
+ },
17031
+ querySelector(selector) {
17032
+ try {
17033
+ const tag = selector.replace(/[^a-zA-Z0-9-]/g, "");
17034
+ const match = html.match(new RegExp("<" + tag + "[^>]*>(.*?)<\\/" + tag + ">", "is"));
17035
+ return match ? parser.stripTags(match[1]).trim() || null : null;
17036
+ } catch {
17037
+ return null;
17038
+ }
17039
+ },
17040
+ querySelectorAll(selector) {
17041
+ try {
17042
+ const tag = selector.replace(/[^a-zA-Z0-9-]/g, "");
17043
+ const regex = new RegExp("<" + tag + "[^>]*>(.*?)<\\/" + tag + ">", "gis");
17044
+ const results = [];
17045
+ let match;
17046
+ while ((match = regex.exec(html)) !== null) {
17047
+ const value = parser.stripTags(match[1]).trim();
17048
+ if (value) results.push(value);
17049
+ }
17050
+ return results;
17051
+ } catch {
17052
+ return [];
17053
+ }
17054
+ }
17055
+ };
17056
+ const titleMatch = html.match(/<title[^>]*>(.*?)<\/title>/is);
17057
+ const title = titleMatch ? parser.stripTags(titleMatch[1]).trim() || void 0 : void 0;
17058
+ const headingRegex = /<h[1-6][^>]*>(.*?)<\/h[1-6]>/gis;
17059
+ const headings = [];
17060
+ let headingMatch;
17061
+ while ((headingMatch = headingRegex.exec(html)) !== null) {
17062
+ const text2 = parser.stripTags(headingMatch[1]).trim();
17063
+ if (text2) headings.push(text2);
17064
+ }
17065
+ const linkRegex = /<a\s[^>]*href=["']([^"']*)["'][^>]*>(.*?)<\/a>/gis;
17066
+ const links = [];
17067
+ let linkMatch;
17068
+ while ((linkMatch = linkRegex.exec(html)) !== null) {
17069
+ const href = linkMatch[1];
17070
+ const text2 = parser.stripTags(linkMatch[2]).trim();
17071
+ if (href) links.push({ href, text: text2 });
17072
+ }
17073
+ const text = parser.stripTags(html);
17074
+ return {
17075
+ title,
17076
+ headings,
17077
+ links,
17078
+ text,
17079
+ querySelector: parser.querySelector,
17080
+ querySelectorAll: parser.querySelectorAll
17081
+ };
17082
+ } catch (error51) {
17083
+ throw new Error(
17084
+ `parseHTML failed: ${error51 instanceof Error ? error51.message : "Unknown error"}`,
17085
+ {
17086
+ cause: error51
17087
+ }
17088
+ );
17089
+ }
17090
+ }
17091
+ function createPortableHelpers(parseHTML) {
17092
+ return {
17093
+ parseHTML,
17094
+ /**
17095
+ * Extract email addresses from text
17096
+ * @param text Text to search for emails
17097
+ * @returns Array of found email addresses
17098
+ */
17099
+ extractEmails(text) {
17100
+ if (typeof text !== "string") {
17101
+ return [];
17102
+ }
17103
+ const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
17104
+ const matches = text.match(emailRegex);
17105
+ return matches ? [...new Set(matches)] : [];
17106
+ },
17107
+ /**
17108
+ * Extract URLs from text
17109
+ * @param text Text to search for URLs
17110
+ * @returns Array of found URLs
17111
+ */
17112
+ extractURLs(text) {
17113
+ if (typeof text !== "string") {
17114
+ return [];
17115
+ }
17116
+ const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/g;
17117
+ const matches = text.match(urlRegex);
17118
+ return matches ? [...new Set(matches)] : [];
17119
+ },
17120
+ /**
17121
+ * Extract phone numbers from text
17122
+ * @param text Text to search for phone numbers
17123
+ * @returns Array of found phone numbers
17124
+ */
17125
+ extractPhoneNumbers(text) {
17126
+ if (typeof text !== "string") {
17127
+ return [];
17128
+ }
17129
+ const phoneRegex = /(?:\+?1[-.\s]?)?(?:\([0-9]{3}\)|[0-9]{3})[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}/g;
17130
+ const matches = text.match(phoneRegex);
17131
+ return matches ? [...new Set(matches)] : [];
17132
+ },
17133
+ /**
17134
+ * Truncate text to specified length with ellipsis
17135
+ * @param text Text to truncate
17136
+ * @param length Maximum length
17137
+ * @returns Truncated text
17138
+ */
17139
+ truncate(text, length) {
17140
+ if (typeof text !== "string" || typeof length !== "number") {
17141
+ return text || "";
17142
+ }
17143
+ if (text.length <= length) {
17144
+ return text;
17145
+ }
17146
+ return text.substring(0, length).trim() + "...";
17147
+ },
17148
+ /**
17149
+ * Create URL-friendly slug from text
17150
+ * @param text Text to slugify
17151
+ * @returns URL-friendly slug
17152
+ */
17153
+ slugify(text) {
17154
+ if (typeof text !== "string") {
17155
+ return "";
17156
+ }
17157
+ return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
17158
+ },
17159
+ /**
17160
+ * Convert Markdown to HTML (basic conversion)
17161
+ * @param markdown Markdown text
17162
+ * @returns HTML string
17163
+ */
17164
+ markdown2html(markdown) {
17165
+ if (typeof markdown !== "string") {
17166
+ return "";
17167
+ }
17168
+ return markdown.replace(/^### (.*$)/gim, "<h3>$1</h3>").replace(/^## (.*$)/gim, "<h2>$1</h2>").replace(/^# (.*$)/gim, "<h1>$1</h1>").replace(/\*\*(.*?)\*\*/gim, "<strong>$1</strong>").replace(/__(.*?)__/gim, "<strong>$1</strong>").replace(/\*(.*?)\*/gim, "<em>$1</em>").replace(/_(.*?)_/gim, "<em>$1</em>").replace(/`(.*?)`/gim, "<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim, '<a href="$2">$1</a>').replace(/\n\n/gim, "</p><p>").replace(/\n/gim, "<br>").replace(/^(?!<[h|u|o|l])/gim, "<p>").replace(/$/gim, "</p>").replace(/<p><\/p>/gim, "").replace(/<p>(<h[1-6]>.*<\/h[1-6]>)<\/p>/gim, "$1");
17169
+ },
17170
+ /**
17171
+ * Convert HTML to Markdown (basic conversion)
17172
+ * @param html HTML string
17173
+ * @returns Markdown text
17174
+ */
17175
+ html2markdown(html) {
17176
+ if (typeof html !== "string") {
17177
+ return "";
17178
+ }
17179
+ 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();
17180
+ },
17181
+ /**
17182
+ * Parse date from various string formats
17183
+ * @param dateStr Date string to parse
17184
+ * @returns Date object or null if invalid
17185
+ */
17186
+ parseDate(dateStr) {
17187
+ if (typeof dateStr !== "string") {
17188
+ return null;
17189
+ }
17190
+ try {
17191
+ const date5 = new Date(dateStr);
17192
+ return isNaN(date5.getTime()) ? null : date5;
17193
+ } catch {
17194
+ return null;
17195
+ }
17196
+ },
17197
+ /**
17198
+ * Format date according to specified format
17199
+ * @param date Date object or string
17200
+ * @param format Format string (simple patterns)
17201
+ * @returns Formatted date string
17202
+ */
17203
+ formatDate(date5, format) {
17204
+ const defaultFormat = format || "YYYY-MM-DD";
17205
+ let dateObj;
17206
+ if (typeof date5 === "string") {
17207
+ dateObj = new Date(date5);
17208
+ } else if (date5 instanceof Date) {
17209
+ dateObj = date5;
17210
+ } else {
17211
+ return "";
17212
+ }
17213
+ if (isNaN(dateObj.getTime())) {
17214
+ return "";
17215
+ }
17216
+ const year = dateObj.getFullYear();
17217
+ const month = String(dateObj.getMonth() + 1).padStart(2, "0");
17218
+ const day = String(dateObj.getDate()).padStart(2, "0");
17219
+ const hours = String(dateObj.getHours()).padStart(2, "0");
17220
+ const minutes = String(dateObj.getMinutes()).padStart(2, "0");
17221
+ const seconds = String(dateObj.getSeconds()).padStart(2, "0");
17222
+ return defaultFormat.replace(/YYYY/g, String(year)).replace(/MM/g, month).replace(/DD/g, day).replace(/HH/g, hours).replace(/mm/g, minutes).replace(/ss/g, seconds);
17223
+ },
17224
+ /**
17225
+ * Add days to a date
17226
+ * @param date Date object or string
17227
+ * @param days Number of days to add (can be negative)
17228
+ * @returns New Date object
17229
+ */
17230
+ addDays(date5, days) {
17231
+ let dateObj;
17232
+ if (typeof date5 === "string") {
17233
+ dateObj = new Date(date5);
17234
+ } else if (date5 instanceof Date) {
17235
+ dateObj = new Date(date5.getTime());
17236
+ } else {
17237
+ return null;
17238
+ }
17239
+ if (isNaN(dateObj.getTime()) || typeof days !== "number") {
17240
+ return null;
17241
+ }
17242
+ dateObj.setDate(dateObj.getDate() + days);
17243
+ return dateObj;
17244
+ },
17245
+ /**
17246
+ * Validate email address format
17247
+ * @param email Email address to validate
17248
+ * @returns True if valid email format
17249
+ */
17250
+ isValidEmail(email3) {
17251
+ if (typeof email3 !== "string") {
17252
+ return false;
17253
+ }
17254
+ const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
17255
+ return emailRegex.test(email3);
17256
+ },
17257
+ /**
17258
+ * Validate URL format
17259
+ * @param url URL to validate
17260
+ * @returns True if valid URL format
17261
+ */
17262
+ isValidURL(url2) {
17263
+ if (typeof url2 !== "string") {
17264
+ return false;
17265
+ }
17266
+ try {
17267
+ new URL(url2);
17268
+ return true;
17269
+ } catch {
17270
+ return false;
17271
+ }
17272
+ },
17273
+ /**
17274
+ * Validate JSON string
17275
+ * @param str String to validate as JSON
17276
+ * @returns True if valid JSON
17277
+ */
17278
+ isValidJSON(str) {
17279
+ if (typeof str !== "string") {
17280
+ return false;
17281
+ }
17282
+ try {
17283
+ JSON.parse(str);
17284
+ return true;
17285
+ } catch {
17286
+ return false;
17287
+ }
17288
+ },
17289
+ /**
17290
+ * Encode string to base64
17291
+ * @param str String to encode
17292
+ * @returns Base64 encoded string
17293
+ */
17294
+ base64Encode(str) {
17295
+ if (typeof str !== "string") {
17296
+ return "";
17297
+ }
17298
+ try {
17299
+ return btoa(str);
17300
+ } catch {
17301
+ return btoa(unescape(encodeURIComponent(str)));
17302
+ }
17303
+ },
17304
+ /**
17305
+ * Decode base64 string
17306
+ * @param str Base64 string to decode
17307
+ * @returns Decoded string
17308
+ */
17309
+ base64Decode(str) {
17310
+ if (typeof str !== "string") {
17311
+ return "";
17312
+ }
17313
+ try {
17314
+ return atob(str);
17315
+ } catch {
17316
+ try {
17317
+ return decodeURIComponent(escape(atob(str)));
17318
+ } catch {
17319
+ return "";
17320
+ }
17321
+ }
17322
+ },
17323
+ /**
17324
+ * URL encode string
17325
+ * @param str String to encode
17326
+ * @returns URL encoded string
17327
+ */
17328
+ urlEncode(str) {
17329
+ if (typeof str !== "string") {
17330
+ return "";
17331
+ }
17332
+ return encodeURIComponent(str);
17333
+ },
17334
+ /**
17335
+ * URL decode string
17336
+ * @param str URL encoded string to decode
17337
+ * @returns Decoded string
17338
+ */
17339
+ urlDecode(str) {
17340
+ if (typeof str !== "string") {
17341
+ return "";
17342
+ }
17343
+ try {
17344
+ return decodeURIComponent(str);
17345
+ } catch {
17346
+ return str;
17347
+ }
17348
+ },
17349
+ /**
17350
+ * Return the first argument that is neither null nor undefined (a named
17351
+ * first-non-null / nullish coalesce). The script-side counterpart of the
17352
+ * `{{a ?? b}}` template operator — in templates prefer `{{a ?? b}}`; use
17353
+ * `helpers.coalesce(a, b)` inside transform-data scripts.
17354
+ * @param values Candidate values in priority order
17355
+ * @returns The first non-null/undefined value, or null if all are null/undefined
17356
+ */
17357
+ coalesce(...values) {
17358
+ for (const value of values) {
17359
+ if (value !== null && value !== void 0) {
17360
+ return value;
17361
+ }
17362
+ }
17363
+ return null;
17364
+ }
17365
+ };
17366
+ }
17367
+
17020
17368
  // ../shared/dist/index.mjs
17021
17369
  var FORMULA_TRIGGER = /^[=+\-@\t\r\n]/;
17022
17370
  var STRICT_NUMBER = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
@@ -17573,7 +17921,15 @@ function isBuiltInToolId(toolId) {
17573
17921
  function isPlatformToolId(toolId) {
17574
17922
  return toolId.startsWith("platform:");
17575
17923
  }
17576
- var INTEGRATION_SERVER_IDS = /* @__PURE__ */ new Set(["slack", "google", "linear", "github", "telegram"]);
17924
+ var INTEGRATION_SERVER_IDS = /* @__PURE__ */ new Set([
17925
+ "slack",
17926
+ "google",
17927
+ "linear",
17928
+ "github",
17929
+ "telegram",
17930
+ "imessage",
17931
+ "granola"
17932
+ ]);
17577
17933
  function isBuiltInIntegrationToolId(toolId) {
17578
17934
  if (!toolId.startsWith("builtin:")) return false;
17579
17935
  const { baseId } = parseToolInstanceId(toolId);
@@ -22013,280 +22369,8 @@ function parseCreateFlowValidationInput(payload) {
22013
22369
  };
22014
22370
  }
22015
22371
  var SERIALIZED_HELPERS_SOURCE = `
22016
- // Transform helper functions (from packages/shared/src/transform-helpers.ts)
22017
- const helpers = (function createHelpers() {
22018
- // Regex-based HTML tag stripper for extracting text content
22019
- const stripTags = (html) => html.replace(/<[^>]*>/g, ' ').replace(/\\s+/g, ' ').trim()
22020
-
22021
- return {
22022
- parseHTML: (html) => {
22023
- if (typeof html !== 'string') throw new Error('parseHTML: input must be a string')
22024
- try {
22025
- // Extract title
22026
- const titleMatch = html.match(/<title[^>]*>(.*?)<\\/title>/is)
22027
- const title = titleMatch ? stripTags(titleMatch[1]).trim() || undefined : undefined
22028
-
22029
- // Extract headings (h1-h6)
22030
- const headingRegex = /<h[1-6][^>]*>(.*?)<\\/h[1-6]>/gis
22031
- const headings = []
22032
- let hMatch
22033
- while ((hMatch = headingRegex.exec(html)) !== null) {
22034
- const text = stripTags(hMatch[1]).trim()
22035
- if (text) headings.push(text)
22036
- }
22037
-
22038
- // Extract links
22039
- const linkRegex = /<a\\s[^>]*href=["']([^"']*)["'][^>]*>(.*?)<\\/a>/gis
22040
- const links = []
22041
- let lMatch
22042
- while ((lMatch = linkRegex.exec(html)) !== null) {
22043
- const href = lMatch[1]
22044
- const text = stripTags(lMatch[2]).trim()
22045
- if (href) links.push({ href, text })
22046
- }
22047
-
22048
- // Extract all text content
22049
- const text = stripTags(html)
22050
-
22051
- // Simple querySelector (CSS element selectors only)
22052
- const querySelector = (selector) => {
22053
- try {
22054
- const tag = selector.replace(/[^a-zA-Z0-9-]/g, '')
22055
- const match = html.match(new RegExp('<' + tag + '[^>]*>(.*?)<\\\\/' + tag + '>', 'is'))
22056
- return match ? stripTags(match[1]).trim() || null : null
22057
- } catch (error) {
22058
- return null
22059
- }
22060
- }
22061
-
22062
- // Simple querySelectorAll (CSS element selectors only)
22063
- const querySelectorAll = (selector) => {
22064
- try {
22065
- const tag = selector.replace(/[^a-zA-Z0-9-]/g, '')
22066
- const regex = new RegExp('<' + tag + '[^>]*>(.*?)<\\\\/' + tag + '>', 'gis')
22067
- const results = []
22068
- let m
22069
- while ((m = regex.exec(html)) !== null) {
22070
- const t = stripTags(m[1]).trim()
22071
- if (t) results.push(t)
22072
- }
22073
- return results
22074
- } catch (error) {
22075
- return []
22076
- }
22077
- }
22078
-
22079
- return { title, headings, links, text, querySelector, querySelectorAll }
22080
- } catch (error) {
22081
- throw new Error('parseHTML failed: ' + (error instanceof Error ? error.message : 'Unknown error'))
22082
- }
22083
- },
22084
-
22085
- extractEmails: (text) => {
22086
- if (typeof text !== 'string') return []
22087
- const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g
22088
- const matches = text.match(emailRegex)
22089
- return matches ? [...new Set(matches)] : []
22090
- },
22091
-
22092
- extractURLs: (text) => {
22093
- if (typeof text !== 'string') return []
22094
- const urlRegex = /https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&/=]*)/g
22095
- const matches = text.match(urlRegex)
22096
- return matches ? [...new Set(matches)] : []
22097
- },
22098
-
22099
- extractPhoneNumbers: (text) => {
22100
- if (typeof text !== 'string') return []
22101
- const phoneRegex = /(?:\\+?1[-.\\s]?)?(?:\\([0-9]{3}\\)|[0-9]{3})[-.\\s]?[0-9]{3}[-.\\s]?[0-9]{4}/g
22102
- const matches = text.match(phoneRegex)
22103
- return matches ? [...new Set(matches)] : []
22104
- },
22105
-
22106
- truncate: (text, length) => {
22107
- if (typeof text !== 'string' || typeof length !== 'number') return text || ''
22108
- if (text.length <= length) return text
22109
- return text.substring(0, length).trim() + '...'
22110
- },
22111
-
22112
- slugify: (text) => {
22113
- if (typeof text !== 'string') return ''
22114
- return text
22115
- .toLowerCase()
22116
- .trim()
22117
- .replace(/[^\\w\\s-]/g, '')
22118
- .replace(/[\\s_-]+/g, '-')
22119
- .replace(/^-+|-+$/g, '')
22120
- },
22121
-
22122
- markdown2html: (markdown) => {
22123
- if (typeof markdown !== 'string') return ''
22124
- return markdown
22125
- .replace(/^### (.*$)/gim, '<h3>$1</h3>')
22126
- .replace(/^## (.*$)/gim, '<h2>$1</h2>')
22127
- .replace(/^# (.*$)/gim, '<h1>$1</h1>')
22128
- .replace(/\\*\\*(.*?)\\*\\*/gim, '<strong>$1</strong>')
22129
- .replace(/__(.*?)__/gim, '<strong>$1</strong>')
22130
- .replace(/\\*(.*?)\\*/gim, '<em>$1</em>')
22131
- .replace(/_(.*?)_/gim, '<em>$1</em>')
22132
- .replace(/\`(.*?)\`/gim, '<code>$1</code>')
22133
- .replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/gim, '<a href="$2">$1</a>')
22134
- .replace(/\\n\\n/gim, '</p><p>')
22135
- .replace(/\\n/gim, '<br>')
22136
- .replace(/^(?!<[h|u|o|l])/gim, '<p>')
22137
- .replace(/$/gim, '</p>')
22138
- .replace(/<p><\\/p>/gim, '')
22139
- .replace(/<p>(<h[1-6]>.*<\\/h[1-6]>)<\\/p>/gim, '$1')
22140
- },
22141
-
22142
- html2markdown: (html) => {
22143
- if (typeof html !== 'string') return ''
22144
- return html
22145
- .replace(/<h1[^>]*>(.*?)<\\/h1>/gim, '# $1\\n\\n')
22146
- .replace(/<h2[^>]*>(.*?)<\\/h2>/gim, '## $1\\n\\n')
22147
- .replace(/<h3[^>]*>(.*?)<\\/h3>/gim, '### $1\\n\\n')
22148
- .replace(/<h4[^>]*>(.*?)<\\/h4>/gim, '#### $1\\n\\n')
22149
- .replace(/<h5[^>]*>(.*?)<\\/h5>/gim, '##### $1\\n\\n')
22150
- .replace(/<h6[^>]*>(.*?)<\\/h6>/gim, '###### $1\\n\\n')
22151
- .replace(/<strong[^>]*>(.*?)<\\/strong>/gim, '**$1**')
22152
- .replace(/<b[^>]*>(.*?)<\\/b>/gim, '**$1**')
22153
- .replace(/<em[^>]*>(.*?)<\\/em>/gim, '*$1*')
22154
- .replace(/<i[^>]*>(.*?)<\\/i>/gim, '*$1*')
22155
- .replace(/<code[^>]*>(.*?)<\\/code>/gim, '\`$1\`')
22156
- .replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\\/a>/gim, '[$2]($1)')
22157
- .replace(/<br[^>]*>/gim, '\\n')
22158
- .replace(/<\\/p>/gim, '\\n\\n')
22159
- .replace(/<p[^>]*>/gim, '')
22160
- .replace(/<li[^>]*>(.*?)<\\/li>/gim, '- $1\\n')
22161
- .replace(/<ul[^>]*>/gim, '\\n')
22162
- .replace(/<\\/ul>/gim, '\\n')
22163
- .replace(/<ol[^>]*>/gim, '\\n')
22164
- .replace(/<\\/ol>/gim, '\\n')
22165
- .replace(/<[^>]+>/gim, '')
22166
- .replace(/\\n\\s*\\n\\s*\\n/gim, '\\n\\n')
22167
- .trim()
22168
- },
22169
-
22170
- parseDate: (dateStr) => {
22171
- if (typeof dateStr !== 'string') return null
22172
- try {
22173
- const date = new Date(dateStr)
22174
- return isNaN(date.getTime()) ? null : date
22175
- } catch {
22176
- return null
22177
- }
22178
- },
22179
-
22180
- formatDate: (date, format) => {
22181
- const defaultFormat = format || 'YYYY-MM-DD'
22182
- let dateObj
22183
- if (typeof date === 'string') {
22184
- dateObj = new Date(date)
22185
- } else if (date instanceof Date) {
22186
- dateObj = date
22187
- } else {
22188
- return ''
22189
- }
22190
- if (isNaN(dateObj.getTime())) return ''
22191
- const year = dateObj.getFullYear()
22192
- const month = String(dateObj.getMonth() + 1).padStart(2, '0')
22193
- const day = String(dateObj.getDate()).padStart(2, '0')
22194
- const hours = String(dateObj.getHours()).padStart(2, '0')
22195
- const minutes = String(dateObj.getMinutes()).padStart(2, '0')
22196
- const seconds = String(dateObj.getSeconds()).padStart(2, '0')
22197
- return defaultFormat
22198
- .replace(/YYYY/g, String(year))
22199
- .replace(/MM/g, month)
22200
- .replace(/DD/g, day)
22201
- .replace(/HH/g, hours)
22202
- .replace(/mm/g, minutes)
22203
- .replace(/ss/g, seconds)
22204
- },
22205
-
22206
- addDays: (date, days) => {
22207
- let dateObj
22208
- if (typeof date === 'string') {
22209
- dateObj = new Date(date)
22210
- } else if (date instanceof Date) {
22211
- dateObj = new Date(date.getTime())
22212
- } else {
22213
- return null
22214
- }
22215
- if (isNaN(dateObj.getTime()) || typeof days !== 'number') return null
22216
- dateObj.setDate(dateObj.getDate() + days)
22217
- return dateObj
22218
- },
22219
-
22220
- isValidEmail: (email) => {
22221
- if (typeof email !== 'string') return false
22222
- const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/
22223
- return emailRegex.test(email)
22224
- },
22225
-
22226
- isValidURL: (url) => {
22227
- if (typeof url !== 'string') return false
22228
- try {
22229
- new URL(url)
22230
- return true
22231
- } catch {
22232
- return false
22233
- }
22234
- },
22235
-
22236
- isValidJSON: (str) => {
22237
- if (typeof str !== 'string') return false
22238
- try {
22239
- JSON.parse(str)
22240
- return true
22241
- } catch {
22242
- return false
22243
- }
22244
- },
22245
-
22246
- base64Encode: (str) => {
22247
- if (typeof str !== 'string') return ''
22248
- try {
22249
- return btoa(str)
22250
- } catch {
22251
- return btoa(unescape(encodeURIComponent(str)))
22252
- }
22253
- },
22254
-
22255
- base64Decode: (str) => {
22256
- if (typeof str !== 'string') return ''
22257
- try {
22258
- return atob(str)
22259
- } catch {
22260
- try {
22261
- return decodeURIComponent(escape(atob(str)))
22262
- } catch {
22263
- return ''
22264
- }
22265
- }
22266
- },
22267
-
22268
- urlEncode: (str) => {
22269
- if (typeof str !== 'string') return ''
22270
- return encodeURIComponent(str)
22271
- },
22272
-
22273
- urlDecode: (str) => {
22274
- if (typeof str !== 'string') return ''
22275
- try {
22276
- return decodeURIComponent(str)
22277
- } catch {
22278
- return str
22279
- }
22280
- },
22281
-
22282
- coalesce: (...values) => {
22283
- for (const value of values) {
22284
- if (value !== null && value !== undefined) return value
22285
- }
22286
- return null
22287
- },
22288
- }
22289
- })()
22372
+ // Transform helper functions generated from the canonical portable factory.
22373
+ const helpers = (${createPortableHelpers.toString()})(${parseHTMLWithRegex.toString()})
22290
22374
  `.trim();
22291
22375
  var AGENT_EXECUTION_STATUSES = [
22292
22376
  "queued",
@@ -22298,6 +22382,8 @@ var AGENT_EXECUTION_STATUSES = [
22298
22382
  "interrupted"
22299
22383
  ];
22300
22384
  var agentExecutionStatusSchema = external_exports.enum(AGENT_EXECUTION_STATUSES);
22385
+ var DEFAULT_BEDROCK_REGION = "us-east-1";
22386
+ var DEFAULT_VERTEX_LOCATION = "us-central1";
22301
22387
  var PROVIDER_SECRET_SPECS = [
22302
22388
  {
22303
22389
  providerId: "mock",
@@ -22309,13 +22395,15 @@ var PROVIDER_SECRET_SPECS = [
22309
22395
  providerId: "google-vertex-anthropic",
22310
22396
  // Must come before google-vertex (shares vertex prefix) and anthropic (matches */claude-*).
22311
22397
  matches: (m2) => m2.startsWith("vertex-anthropic/"),
22312
- secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_VERTEX_CREDENTIALS"]
22398
+ secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_CREDENTIALS"],
22399
+ optionalSettings: [{ name: "GOOGLE_VERTEX_LOCATION", defaultValue: DEFAULT_VERTEX_LOCATION }]
22313
22400
  },
22314
22401
  {
22315
22402
  providerId: "google-vertex",
22316
22403
  // Must come before google (matches */gemini-*).
22317
22404
  matches: (m2) => m2.startsWith("vertex/"),
22318
- secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_LOCATION", "GOOGLE_VERTEX_CREDENTIALS"]
22405
+ secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_CREDENTIALS"],
22406
+ optionalSettings: [{ name: "GOOGLE_VERTEX_LOCATION", defaultValue: DEFAULT_VERTEX_LOCATION }]
22319
22407
  },
22320
22408
  {
22321
22409
  providerId: "vercel-gateway",
@@ -22332,7 +22420,8 @@ var PROVIDER_SECRET_SPECS = [
22332
22420
  {
22333
22421
  providerId: "bedrock",
22334
22422
  matches: (m2) => m2.startsWith("bedrock/"),
22335
- secretNames: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"]
22423
+ secretNames: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
22424
+ optionalSettings: [{ name: "AWS_REGION", defaultValue: DEFAULT_BEDROCK_REGION }]
22336
22425
  },
22337
22426
  {
22338
22427
  providerId: "tinfoil",
@@ -22345,15 +22434,6 @@ var PROVIDER_SECRET_SPECS = [
22345
22434
  matches: (m2) => m2.startsWith("generic-openai/") || m2.startsWith("generic-openai:"),
22346
22435
  secretNames: ["GENERIC_OPENAI_API_KEY", "GENERIC_OPENAI_BASE_URL"]
22347
22436
  },
22348
- {
22349
- providerId: "general-compute",
22350
- // General Compute (https://api.generalcompute.com/v1) is an OpenAI-compatible
22351
- // host. Models are addressed only with the explicit `general-compute/` prefix
22352
- // (e.g. `general-compute/minimax-m2.7`) so they never collide with the same
22353
- // bare model id served by another gateway (Vercel already routes `minimax-m2.7`).
22354
- matches: (m2) => m2.startsWith("general-compute/") || m2.startsWith("general-compute:"),
22355
- secretNames: ["GENERAL_COMPUTE_API_KEY"]
22356
- },
22357
22437
  {
22358
22438
  providerId: "workers-ai",
22359
22439
  // Uses a CF platform binding, not a secret — secretNames is intentionally empty.
@@ -22403,6 +22483,13 @@ function resolveModelSecretNames(model) {
22403
22483
  }
22404
22484
  return [];
22405
22485
  }
22486
+ function resolveModelOptionalSettings(model) {
22487
+ const lower = model.toLowerCase();
22488
+ for (const spec of PROVIDER_SECRET_SPECS) {
22489
+ if (spec.matches(lower)) return [...spec.optionalSettings ?? []];
22490
+ }
22491
+ return [];
22492
+ }
22406
22493
  var RUNTIME_ARTIFACT_MANIFEST_VERSION = "2026-06-08";
22407
22494
  var runtimeArtifactResourceTypeSchema = external_exports.enum(["flow", "agent"]);
22408
22495
  var runtimeArtifactEntrypointSchema = external_exports.enum(["flow", "agent"]);
@@ -22510,6 +22597,77 @@ var runtimeArtifactManifestSchema = external_exports.object({
22510
22597
  reasons: external_exports.array(runtimeArtifactEligibilityReasonSchema)
22511
22598
  })
22512
22599
  });
22600
+ var KNOWN_FLOW_STEP_TYPES = new Set(FLOW_STEP_TYPES);
22601
+ var API_INPROCESS_CAPABILITY_MATRIX = {
22602
+ target: "api-inprocess",
22603
+ // Bumped 2026-07-30: the IMPLICIT platform-default fallback candidate no
22604
+ // longer folds (see `implicitPlatformFallback` below). Carries forward
22605
+ // 2026-07-29.4: api-hosted runtime fulfills managed fetch methods through
22606
+ // ManagedFetchExecutor (the managed-fetch fact remains for attribution). The
22607
+ // EXPLICIT Layer-2 fallback fold and the remaining parity-audit folds are
22608
+ // unchanged.
22609
+ version: "2026-07-30.1",
22610
+ unsupportedStepTypes: ["wait-until", "crawl"],
22611
+ unsupportedFeatures: {
22612
+ approvalSteps: true,
22613
+ batchInputMode: true,
22614
+ claudeManagedAgent: true,
22615
+ inexpressibleVectorStep: true,
22616
+ unresolvableAgentRef: true,
22617
+ conditionalNestedPromptStep: true,
22618
+ conditionalNestedExecuteAgentStep: true,
22619
+ // SUPPORTED as of 2026-07-23 (slice 6 activation): the runtime flow lane
22620
+ // now PAUSES on definition-embedded client-executed (local / webmcp) tools
22621
+ // — `ClientToolRequiredError` → `step_await` / `flow_await` → durable KV
22622
+ // ResumeState → the runtime continuation leg — instead of failing the call
22623
+ // in-band. The `hasClientExecutedTools` FACT is still computed (for
22624
+ // decision-attribution logs), but it no longer folds the flow to legacy.
22625
+ // Rollback lever after retiring the flow request override: revert this bit
22626
+ // to `true` (the agent lane retains its separate rollout gate).
22627
+ clientExecutedTools: false,
22628
+ advisorTools: true,
22629
+ // G2 SUPPORTED: api-hosted runtime delegates Firecrawl / Massive fetch-url
22630
+ // methods through ManagedFetchExecutor to the same API implementations the
22631
+ // legacy executor uses. Keep the fact computed for attribution, like
22632
+ // clientExecutedTools above.
22633
+ unsupportedFetchMethod: false,
22634
+ // Remaining 2026-07-29 parity-audit BRIDGE folds (G4/G5/G10/G14): feature
22635
+ // classes the runtime flow lane still cannot faithfully run.
22636
+ transformDataCodeModeTools: true,
22637
+ unsupportedTransformExecution: true,
22638
+ promptMcpServers: true,
22639
+ promptArtifacts: true,
22640
+ // EXPLICIT author-configured Layer-2 chains stay unsupported: the runtime
22641
+ // flow engine cannot run them and cannot synthesize their `usedFallback` /
22642
+ // `fallbackModel` / `fallbackExecutions` attribution, so a folded flow would
22643
+ // both change behavior and undercount fallback usage.
22644
+ fallbackErrorHandling: true,
22645
+ // SUPPORTED as of 2026-07-30: the IMPLICIT platform-default chain (the
22646
+ // orchestrator's synthesized same-model-next-provider + cross-model rungs
22647
+ // for a prompt with NO explicit `errorHandling`) does not fold the flow to
22648
+ // legacy. Rationale: a prompt step without `errorHandling` is the DEFAULT
22649
+ // shape of nearly every hosted flow, so folding on it reverted the hosted
22650
+ // flow lane to legacy for the common case — the opposite of runtime-primary.
22651
+ // The runtime lane already carries Layer-1 resilience natively
22652
+ // (`withModelCallResilience`: TTFT + idle watchdog + bounded same-model
22653
+ // retry — packages/runtime prompt-executor.ts), so the residual delta is
22654
+ // narrow: on a retryable platform-key failure that survives Layer 1 with no
22655
+ // partial output, the runtime surfaces the step error where legacy would
22656
+ // additionally swap upstream/model. That is an availability nicety, not a
22657
+ // semantic difference — and unlike the folds above it cannot silently
22658
+ // produce a WRONG result. `hasImplicitPlatformFallbackCandidate` is still
22659
+ // computed for decision attribution. Rollback lever: flip this bit to `true`
22660
+ // (plus its test) to restore the fold.
22661
+ implicitPlatformFallback: false
22662
+ }
22663
+ };
22664
+ var DURABLE_HOSTED_STEP_TYPES = /* @__PURE__ */ new Set(["wait-until", "crawl"]);
22665
+ var API_DURABLE_RESUME_CAPABILITY_MATRIX = {
22666
+ ...API_INPROCESS_CAPABILITY_MATRIX,
22667
+ unsupportedStepTypes: API_INPROCESS_CAPABILITY_MATRIX.unsupportedStepTypes.filter(
22668
+ (stepType) => !DURABLE_HOSTED_STEP_TYPES.has(stepType)
22669
+ )
22670
+ };
22513
22671
  var edgeAuthSnapshotSchema = external_exports.object({
22514
22672
  /**
22515
22673
  * Schema version. A plain positive int (not a literal) so a consumer pinned
@@ -39931,7 +40089,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
39931
40089
  "vercel": "xiaomi/mimo-v2.5-pro"
39932
40090
  },
39933
40091
  "minimax-m2-7": {
39934
- "general-compute": "general-compute/minimax-m2.7",
39935
40092
  "togetherai": "togetherai/MiniMaxAI/MiniMax-M2.7",
39936
40093
  "vercel": "minimax/minimax-m2.7"
39937
40094
  },
@@ -39939,7 +40096,6 @@ var MODEL_FAMILY_PROVIDER_IDS = {
39939
40096
  "vercel": "minimax/minimax-m2.7-highspeed"
39940
40097
  },
39941
40098
  "minimax-m2.7": {
39942
- "general-compute": "general-compute/minimax-m2.7",
39943
40099
  "vercel": "minimax/minimax-m2.7"
39944
40100
  },
39945
40101
  "minimax-m2.7-highspeed": {
@@ -40315,7 +40471,6 @@ var PLATFORM_KEY_PROVIDER_MAP = {
40315
40471
  "vertex-anthropic": false,
40316
40472
  "tinfoil": false,
40317
40473
  "generic-openai": false,
40318
- "general-compute": true,
40319
40474
  // Keyless platform provider: there is no API key (user or platform) — the
40320
40475
  // Cloudflare `AI` binding IS the platform credential. Marking it true makes
40321
40476
  // the router's platform-spend gate apply and keeps keySource attribution
@@ -40389,13 +40544,8 @@ var MANUAL_PROVIDER_MAP_OVERRIDES = {
40389
40544
  "mixlayer": "z-ai/glm-5.2",
40390
40545
  "vercel": "zai/glm-5.2"
40391
40546
  },
40392
- // MiniMax M2.7: explicit provider IDs for the GC-primary / Vercel-fallback route.
40393
- // `general-compute` is NOT in PROVIDERS_WITHOUT_PREFIX, so resolveRoutedFamily
40394
- // prepends `general-compute/` itself — store the BARE id here to avoid a double
40395
- // prefix (`general-compute/general-compute/...`). Vercel IS prefixless, so its
40396
- // value is the gateway-form `minimax/minimax-m2.7` used as-is.
40547
+ // MiniMax M2.7: Vercel's gateway-form id.
40397
40548
  "minimax-m2.7": {
40398
- "general-compute": "minimax-m2.7",
40399
40549
  "vercel": "minimax/minimax-m2.7"
40400
40550
  }
40401
40551
  };
@@ -41313,7 +41463,55 @@ var sandboxConfigSchema = external_exports.object({
41313
41463
  instanceType: external_exports.enum(["standard-1", "standard-2", "standard-3", "standard-4"]).optional(),
41314
41464
  networkAccess: sandboxNetworkAccessSchema.optional(),
41315
41465
  ttl: external_exports.enum(["5m", "1h", "24h", "unlimited"]).optional(),
41316
- sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional()
41466
+ sleepAfter: external_exports.enum(["5m", "15m", "30m", "1h"]).optional(),
41467
+ // Operator-authored bootstrap commands. The API runs this batch once after
41468
+ // enforcing the sandbox's network policy and before the first model-authored
41469
+ // sandbox verb. Commands run in order from /workspace and must be foreground,
41470
+ // self-contained, and safe to retry after an interrupted container runtime;
41471
+ // the credential-bearing exec supervisor deliberately reaps every descendant
41472
+ // before a command returns, so setup cannot launch a daemon meant to outlive
41473
+ // it. Trusted Durable Object state plus a run-scoped memo prevents the batch
41474
+ // from being repeated for the same provisioned workspace. Changing the
41475
+ // commands or managed-secret KEY bindings creates a fresh sandbox identity;
41476
+ // rotating a value under the same key does not rerun setup.
41477
+ setupCommands: external_exports.array(external_exports.string().min(1, "setup commands must not be empty")).optional(),
41478
+ // Credential environment available ONLY to the operator-authored setup batch
41479
+ // above — never to a model-authored `bash` command. Keys are env var names;
41480
+ // values are MANAGED SECRET KEYS (e.g. `GITHUB_CLONE_TOKEN`), never raw
41481
+ // credential values. The API resolves them immediately before setup and
41482
+ // delivers them out-of-band over `cloudflareSandboxExecWithSecretEnv`, so the
41483
+ // values never appear in command strings, model-facing tool schemas, logs, or
41484
+ // spill files. Like `networkAccess`, both fields are operator Definition: the
41485
+ // model cannot author setup, name a managed secret, or grant itself one.
41486
+ //
41487
+ // TRUST BOUNDARY — read before configuring this. Every process started by a
41488
+ // credentialed setup batch can read the injected values. Keep setup authored
41489
+ // and reviewed by the operator; do not run model-, attacker-, or
41490
+ // supply-chain-authored code (for example an install script) while credentials
41491
+ // are present, and never persist a raw credential into /workspace for later
41492
+ // model access. The secret supervisor freezes pre-existing processes, reaps
41493
+ // every setup descendant, and destroys the sandbox fail-closed if cleanup
41494
+ // fails, but output redaction remains defense-in-depth rather than permission
41495
+ // to echo or transform a credential.
41496
+ // Therefore:
41497
+ // - Prefer `credentialProxies` (phantom tokens, swapped at the egress
41498
+ // proxy) for any HTTP(S) protocol it supports — the real credential
41499
+ // never enters the container at all.
41500
+ // - Scope the secret as narrowly as the provider allows (read-only,
41501
+ // single-repo) and pair it with a tight `networkAccess` profile.
41502
+ // - Keep credentialed setup separate from later uncredentialed dependency
41503
+ // installation and model-authored work.
41504
+ // Name shape and the 32-entry cap mirror the sandbox worker's
41505
+ // `validateSecretEnv`; `RUNTYPE_SECRET_COMMAND` is the worker's reserved
41506
+ // control-channel variable.
41507
+ secretEnv: external_exports.record(
41508
+ external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a valid environment variable name").refine((name) => name !== "RUNTYPE_SECRET_COMMAND", {
41509
+ message: "RUNTYPE_SECRET_COMMAND is reserved"
41510
+ }),
41511
+ external_exports.string().min(1, "must be a managed secret key")
41512
+ ).refine((record2) => Object.keys(record2).length <= 32, {
41513
+ message: "secretEnv supports at most 32 variables"
41514
+ }).optional()
41317
41515
  // NOTE: a `requireApprovalForBash` knob was forward-declared here for Phase 3
41318
41516
  // but never wired to any runtime gate, so it was REMOVED from the public
41319
41517
  // schema rather than ship a misleading, inert control (post-Fable handoff 05,
@@ -41632,7 +41830,7 @@ var identityProofSchema = external_exports.object({
41632
41830
  /** The customer-native proof (JWT / opaque session token). */
41633
41831
  token: external_exports.string().min(1).max(8192)
41634
41832
  }).describe(
41635
- "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."
41833
+ "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."
41636
41834
  );
41637
41835
  function extractSecretReferences(template) {
41638
41836
  const keys = /* @__PURE__ */ new Set();
@@ -44699,6 +44897,27 @@ Only use a \`tool-call\` step when the tool must run deterministically at a fixe
44699
44897
  - Nullish fallback: \`{{count ?? 0}}\` \u2014 keeps 0 / "" / false (only null/undefined fall through)
44700
44898
  - Chains: \`{{a || b || "default"}}\` \u2014 supports paths and string/number/boolean/null literals; do NOT mix \`||\` and \`??\` in one expression
44701
44899
 
44900
+ ### Prompt Caching: Where Large Context Goes
44901
+
44902
+ 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.
44903
+
44904
+ - **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.
44905
+ - **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.
44906
+ - **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.
44907
+ - **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.
44908
+ - **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.
44909
+
44910
+ \`\`\`json
44911
+ // BEFORE \u2014 the corpus rides in userPrompt and is re-sent uncached on every run,
44912
+ // and the two steps have different system prompts, so neither shares a prefix
44913
+ { "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" } }
44914
+ { "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" } }
44915
+
44916
+ // AFTER \u2014 one byte-identical prefix; the second step and every later run read it warm
44917
+ { "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" } }
44918
+ { "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" } }
44919
+ \`\`\`
44920
+
44702
44921
  ### Model Selection
44703
44922
 
44704
44923
  Use ONLY routed model IDs from the list below (platform-key compatible). Never
@@ -45647,7 +45866,7 @@ var InlineClientToolSchema = external_exports.object({
45647
45866
  var ClientToolsPolicySchema = external_exports.object({
45648
45867
  allowlist: external_exports.array(external_exports.string()).optional()
45649
45868
  });
45650
- var DispatchRequestSchema = external_exports.object({
45869
+ var DispatchRequestEnvelopeSchema = external_exports.object({
45651
45870
  record: RecordInputSchema.optional(),
45652
45871
  flow: FlowInputSchema.optional(),
45653
45872
  agent: AgentInputSchema.optional(),
@@ -45684,7 +45903,9 @@ var DispatchRequestSchema = external_exports.object({
45684
45903
  * every submitted webmcp tool. See {@link ClientToolsPolicySchema}.
45685
45904
  */
45686
45905
  clientToolsPolicy: ClientToolsPolicySchema.optional(),
45687
- secrets: external_exports.record(external_exports.string(), external_exports.string()).optional(),
45906
+ secrets: external_exports.record(external_exports.string(), external_exports.string()).optional().describe(
45907
+ "Per-request credentials for agent/external-tool execution. Ignored when `flow` is the hosted target; FLOW credentials must use managed {{secret:NAME}} references."
45908
+ ),
45688
45909
  credentialProxies: external_exports.array(credentialProxyConfigSchema).max(10).optional(),
45689
45910
  inputs: external_exports.record(external_exports.string(), external_exports.any()).optional().refine(
45690
45911
  (data) => {
@@ -45710,10 +45931,11 @@ var DispatchRequestSchema = external_exports.object({
45710
45931
  id: external_exports.string().min(1)
45711
45932
  }).passthrough().optional(),
45712
45933
  // Identity Exchange proof (design §4.1): a customer-native auth token the
45713
- // broker will verify server-side and admit as `verified` tenant/end-user.
45714
- // Wire contract only for now — parsed here, consumed by NOTHING until the
45715
- // admission slice wires verification into the tenancy seam. The token is a
45716
- // live credential: never log or persist it (see identityProofSchema docs).
45934
+ // broker verifies server-side and admits as `verified` tenant/end-user when
45935
+ // Identity Exchange admission is enabled for the caller. With the rollout
45936
+ // gate disabled it remains accepted-but-ignored and confers no trust. The
45937
+ // token is a live credential: never log or persist it (see
45938
+ // identityProofSchema docs).
45717
45939
  identityProof: identityProofSchema.optional(),
45718
45940
  options: external_exports.object({
45719
45941
  streamResponse: external_exports.boolean().optional().default(true),
@@ -45725,7 +45947,7 @@ var DispatchRequestSchema = external_exports.object({
45725
45947
  debugMode: external_exports.boolean().optional().default(false),
45726
45948
  loggingPolicy: external_exports.enum(["default", "on", "off"]).optional(),
45727
45949
  useRuntimePackage: external_exports.boolean().optional().describe(
45728
- "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."
45950
+ "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."
45729
45951
  ),
45730
45952
  /** Route prompt model calls through an attached dashboard browser. */
45731
45953
  localInference: LocalInferenceSelectionSchema.optional(),
@@ -45792,20 +46014,23 @@ var DispatchRequestSchema = external_exports.object({
45792
46014
  storeResults: true,
45793
46015
  autoAppendMetadata: false,
45794
46016
  debugMode: false,
45795
- // useRuntimePackage intentionally omitted — absent = silent request, so
45796
- // the `use-runtime-package-flows` flag decides the default engine (A4-3).
46017
+ // useRuntimePackage intentionally omitted. Flow dispatch ignores the
46018
+ // compatibility field; agent dispatch still requires explicit true.
45797
46019
  environment: "development",
45798
46020
  createVersion: false
45799
46021
  })
45800
- }).refine((data) => data.flow || data.agent, {
45801
- message: "Either 'flow' or 'agent' configuration must be provided"
45802
- }).superRefine((data, ctx) => {
46022
+ });
46023
+ var DispatchRequestSchema = external_exports.union([
46024
+ DispatchRequestEnvelopeSchema.extend({ flow: FlowInputSchema }),
46025
+ DispatchRequestEnvelopeSchema.extend({ agent: AgentInputSchema })
46026
+ ]).superRefine((data, ctx) => {
45803
46027
  if (!data.options.localInference) return;
45804
- if (!data.options.useRuntimePackage) {
46028
+ const runtimeLaneDisabled = data.agent != null && data.options.useRuntimePackage !== true;
46029
+ if (runtimeLaneDisabled) {
45805
46030
  ctx.addIssue({
45806
46031
  code: "custom",
45807
46032
  path: ["options", "useRuntimePackage"],
45808
- message: "Local inference requires useRuntimePackage to be enabled"
46033
+ message: data.agent != null ? "Local agent inference requires useRuntimePackage to be enabled" : "Local flow inference cannot use the legacy engine"
45809
46034
  });
45810
46035
  }
45811
46036
  if (data.options.modelOverride) {
@@ -53141,7 +53366,9 @@ import React14 from "react";
53141
53366
  import { render as render14 } from "ink";
53142
53367
  import { useState as useState15, useEffect as useEffect16 } from "react";
53143
53368
  import { readFileSync as readFileSync5 } from "fs";
53144
- import { processStream as processStream3 } from "@runtypelabs/sdk";
53369
+ import {
53370
+ processStream as processStream3
53371
+ } from "@runtypelabs/sdk";
53145
53372
  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) => {
53146
53373
  if (!options.flow && !options.agent) {
53147
53374
  console.error(chalk17.red("Error: Either --flow or --agent is required"));
@@ -53150,44 +53377,50 @@ var dispatchCommand = new Command15("dispatch").description("Execute a flow or a
53150
53377
  const apiKey = await ensureAuth();
53151
53378
  if (!apiKey) return;
53152
53379
  const client = createCliClient(apiKey);
53153
- const payload = {};
53154
- if (options.flow) {
53155
- payload.flow = { id: options.flow };
53380
+ let payload;
53381
+ try {
53382
+ payload = buildDispatchRequest(options);
53383
+ } catch (error51) {
53384
+ const message = error51 instanceof Error ? error51.message : "Unknown error";
53385
+ console.error(chalk17.red(`Failed to read record JSON: ${message}`));
53386
+ process.exit(1);
53387
+ }
53388
+ if (options.stream) {
53389
+ await handleStreaming(client, payload, options);
53390
+ } else {
53391
+ await handleNonStreaming(client, payload, options);
53156
53392
  }
53393
+ });
53394
+ function collectVariables(value, previous) {
53395
+ return previous.concat([value]);
53396
+ }
53397
+ function buildDispatchRequest(options) {
53398
+ if (!options.flow && !options.agent) {
53399
+ throw new Error("Either --flow or --agent is required");
53400
+ }
53401
+ const payload = options.flow ? { flow: { id: options.flow } } : { agent: { agentId: options.agent } };
53157
53402
  if (options.agent) {
53158
- payload.agent = { id: options.agent };
53403
+ payload.agent = { agentId: options.agent };
53159
53404
  }
53160
53405
  if (options.record) {
53161
53406
  payload.record = { id: options.record };
53162
53407
  } else if (options.recordJson) {
53163
- try {
53164
- const data = JSON.parse(readFileSync5(options.recordJson, "utf-8"));
53165
- payload.record = { metadata: data };
53166
- } catch (error51) {
53167
- const message = error51 instanceof Error ? error51.message : "Unknown error";
53168
- console.error(chalk17.red(`Failed to read record JSON: ${message}`));
53169
- process.exit(1);
53170
- }
53408
+ const data = JSON.parse(readFileSync5(options.recordJson, "utf-8"));
53409
+ payload.record = { metadata: data };
53171
53410
  }
53172
53411
  if (options.message) {
53173
53412
  payload.messages = [{ role: "user", content: options.message }];
53174
53413
  }
53175
53414
  if (options.variable && options.variable.length > 0) {
53176
- const variables = {};
53177
- for (const v2 of options.variable) {
53178
- const [key, ...rest] = v2.split("=");
53179
- variables[key] = rest.join("=");
53415
+ const inputs = {};
53416
+ for (const variable of options.variable) {
53417
+ const [key, ...rest] = variable.split("=");
53418
+ inputs[key] = rest.join("=");
53180
53419
  }
53181
- payload.variables = variables;
53420
+ payload.inputs = inputs;
53182
53421
  }
53183
- if (options.stream) {
53184
- await handleStreaming(client, payload, options);
53185
- } else {
53186
- await handleNonStreaming(client, payload, options);
53187
- }
53188
- });
53189
- function collectVariables(value, previous) {
53190
- return previous.concat([value]);
53422
+ payload.options = { streamResponse: options.stream };
53423
+ return payload;
53191
53424
  }
53192
53425
  async function handleStreaming(client, payload, options) {
53193
53426
  console.log(chalk17.gray("Starting execution..."));
@@ -53241,7 +53474,6 @@ Error: ${err.message}`));
53241
53474
  async function handleNonStreaming(client, payload, options) {
53242
53475
  if (!isTTY(options)) {
53243
53476
  try {
53244
- payload.streamResponse = false;
53245
53477
  const result = await client.post("/dispatch", payload);
53246
53478
  if (options.json) {
53247
53479
  printJson(result);
@@ -53276,7 +53508,6 @@ async function handleNonStreaming(client, payload, options) {
53276
53508
  useEffect16(() => {
53277
53509
  const run2 = async () => {
53278
53510
  try {
53279
- payload.streamResponse = false;
53280
53511
  const result = await client.post("/dispatch", payload);
53281
53512
  setLoading(false);
53282
53513
  setSuccess(true);
@@ -68487,8 +68718,8 @@ import { execFileSync } from "child_process";
68487
68718
  // src/lib/persona-init.ts
68488
68719
  init_credential_store();
68489
68720
 
68490
- // ../../node_modules/.pnpm/@runtypelabs+persona@4.13.0/node_modules/@runtypelabs/persona/dist/codegen.js
68491
- var w = "4.13.0";
68721
+ // ../../node_modules/.pnpm/@runtypelabs+persona@4.14.0/node_modules/@runtypelabs/persona/dist/codegen.js
68722
+ var w = "4.14.0";
68492
68723
  var S = w;
68493
68724
  function b(e) {
68494
68725
  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`;
@@ -71871,7 +72102,20 @@ echo " npm run build \u2014 compile TypeScript"
71871
72102
  echo " gcloud run deploy --source . --region us-central1 --allow-unauthenticated --port 8080"
71872
72103
  `;
71873
72104
  }
71874
- function readme(agentNames, secretNames) {
72105
+ function formatOptionalProviderSettings(settings) {
72106
+ return settings.map((setting) => `- \`${setting.name}\` (default: \`${setting.defaultValue}\`)`).join("\n");
72107
+ }
72108
+ function optionalProviderSettingsSection(settings) {
72109
+ if (settings.length === 0) return "";
72110
+ return `
72111
+ ## Optional provider settings
72112
+
72113
+ These environment variables override runtime defaults and are not required:
72114
+
72115
+ ${formatOptionalProviderSettings(settings)}
72116
+ `;
72117
+ }
72118
+ function readme(agentNames, secretNames, optionalSettings) {
71875
72119
  const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
71876
72120
  const secretList = secretNames.length > 0 ? secretNames.map((s) => ` gcloud secrets create ${s} --data-file=-`).join("\n") : " (none detected)";
71877
72121
  return `# Runtype Deployment
@@ -71908,6 +72152,8 @@ Set these before deploying to Cloud Run:
71908
72152
 
71909
72153
  ${secretList}
71910
72154
 
72155
+ ${optionalProviderSettingsSection(optionalSettings)}
72156
+
71911
72157
  ## Deploy to Cloud Run
71912
72158
 
71913
72159
  \`\`\`bash
@@ -72205,7 +72451,7 @@ echo " wrangler dev \u2014 preview locally"
72205
72451
  echo " wrangler deploy \u2014 deploy to Cloudflare Workers"
72206
72452
  `;
72207
72453
  }
72208
- function workerReadme(agentNames, secretNames) {
72454
+ function workerReadme(agentNames, secretNames, optionalSettings) {
72209
72455
  const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
72210
72456
  const secretList = secretNames.length > 0 ? secretNames.map((s) => ` wrangler secret put ${s}`).join("\n") : " (none detected)";
72211
72457
  return `# Runtype Cloudflare Workers Deployment
@@ -72228,6 +72474,8 @@ Set each API key your agents use:
72228
72474
  ${secretList}
72229
72475
  \`\`\`
72230
72476
 
72477
+ ${optionalProviderSettingsSection(optionalSettings)}
72478
+
72231
72479
  ## Run locally
72232
72480
 
72233
72481
  \`\`\`bash
@@ -72482,7 +72730,7 @@ echo " vercel dev \u2014 preview locally"
72482
72730
  echo " vercel deploy \u2014 deploy to Vercel Functions"
72483
72731
  `;
72484
72732
  }
72485
- function vercelReadme(agentNames, secretNames) {
72733
+ function vercelReadme(agentNames, secretNames, optionalSettings) {
72486
72734
  const agentList = agentNames.map((n) => ` - ${n}`).join("\n");
72487
72735
  const secretList = secretNames.length > 0 ? secretNames.map((s) => ` vercel env add ${s}`).join("\n") : " (none detected)";
72488
72736
  return `# Runtype Vercel Functions Deployment
@@ -72505,6 +72753,8 @@ Set each API key your agents use via the Vercel dashboard or CLI:
72505
72753
  ${secretList}
72506
72754
  \`\`\`
72507
72755
 
72756
+ ${optionalProviderSettingsSection(optionalSettings)}
72757
+
72508
72758
  ## Run locally
72509
72759
 
72510
72760
  \`\`\`bash
@@ -72530,24 +72780,113 @@ curl https://<your-project>.vercel.app/agent/<name> \\
72530
72780
  \`\`\`
72531
72781
  `;
72532
72782
  }
72533
- function collectSecretNames(agentDef) {
72534
- const names = /* @__PURE__ */ new Set();
72535
- const model = agentDef.config?.model?.toLowerCase();
72536
- if (model) {
72537
- for (const s of resolveModelSecretNames(model)) names.add(s);
72783
+ function collectExportedExecutionInventory(definition) {
72784
+ const models = /* @__PURE__ */ new Set();
72785
+ const namedSecrets = /* @__PURE__ */ new Set();
72786
+ const visited = /* @__PURE__ */ new WeakSet();
72787
+ const isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
72788
+ const addModel = (value) => {
72789
+ if (typeof value === "string" && value) models.add(value);
72790
+ };
72791
+ const walkMcpServers = (servers) => {
72792
+ if (!Array.isArray(servers)) return;
72793
+ for (const server of servers) {
72794
+ if (!isObject2(server) || !isObject2(server.auth)) continue;
72795
+ for (const key of ["tokenSecretName", "usernameSecretName", "passwordSecretName"]) {
72796
+ const value = server.auth[key];
72797
+ if (typeof value === "string" && value) namedSecrets.add(value);
72798
+ }
72799
+ }
72800
+ };
72801
+ function walkRuntimeTools(runtimeTools) {
72802
+ if (!Array.isArray(runtimeTools)) return;
72803
+ for (const tool of runtimeTools) {
72804
+ if (!isObject2(tool) || !isObject2(tool.config)) continue;
72805
+ if (isObject2(tool.config.flow)) walkFlow(tool.config.flow);
72806
+ if (isObject2(tool.config.agent)) walkAgent(tool.config.agent);
72807
+ if (isObject2(tool.config.skill)) walkRuntimeTools(tool.config.skill.resolvedTools);
72808
+ }
72538
72809
  }
72539
- const toolsCfg = agentDef.config?.tools;
72540
- const mcpServers = toolsCfg?.mcpServers;
72541
- if (mcpServers) {
72542
- for (const srv of mcpServers) {
72543
- const auth = srv.auth;
72544
- if (auth?.tokenSecretName) names.add(String(auth.tokenSecretName));
72545
- if (auth?.usernameSecretName) names.add(String(auth.usernameSecretName));
72546
- if (auth?.passwordSecretName) names.add(String(auth.passwordSecretName));
72810
+ function walkTools(tools) {
72811
+ if (!isObject2(tools)) return;
72812
+ walkMcpServers(tools.mcpServers);
72813
+ walkRuntimeTools(tools.runtimeTools);
72814
+ }
72815
+ function walkFallbackModels(config3) {
72816
+ if (!isObject2(config3.errorHandling) || !Array.isArray(config3.errorHandling.fallbacks)) return;
72817
+ for (const fallback of config3.errorHandling.fallbacks) {
72818
+ if (isObject2(fallback) && fallback.type === "model") addModel(fallback.model);
72819
+ }
72820
+ }
72821
+ function walkSteps(steps) {
72822
+ if (!Array.isArray(steps)) return;
72823
+ for (const step of steps) {
72824
+ if (!isObject2(step) || !isObject2(step.config)) continue;
72825
+ if (step.type === "prompt") addModel(step.config.model);
72826
+ walkFallbackModels(step.config);
72827
+ walkTools(step.config.tools);
72828
+ if (step.type !== "conditional") continue;
72829
+ for (const key of ["trueSteps", "falseSteps", "otherwiseSteps"]) walkSteps(step.config[key]);
72830
+ if (Array.isArray(step.config.branches)) {
72831
+ for (const branch of step.config.branches) {
72832
+ if (isObject2(branch)) walkSteps(branch.steps);
72833
+ }
72834
+ }
72547
72835
  }
72548
72836
  }
72549
- for (const s of extractSecretReferencesFromAnyValue(agentDef)) names.add(s);
72550
- return Array.from(names);
72837
+ function walkFlow(flow) {
72838
+ if (visited.has(flow)) return;
72839
+ visited.add(flow);
72840
+ walkSteps(flow.steps);
72841
+ if (isObject2(flow.agents)) {
72842
+ for (const agent of Object.values(flow.agents)) {
72843
+ if (isObject2(agent)) walkAgent(agent);
72844
+ }
72845
+ }
72846
+ }
72847
+ function walkAgent(agent) {
72848
+ if (visited.has(agent)) return;
72849
+ visited.add(agent);
72850
+ if (isObject2(agent.config)) {
72851
+ addModel(agent.config.model);
72852
+ walkTools(agent.config.tools);
72853
+ }
72854
+ if (isObject2(agent.claudeManagedConfig)) addModel(agent.claudeManagedConfig.model);
72855
+ if (isObject2(agent.primaryFlow)) walkFlow(agent.primaryFlow);
72856
+ if (Array.isArray(agent.capabilities)) {
72857
+ for (const capability of agent.capabilities) {
72858
+ if (!isObject2(capability)) continue;
72859
+ if (isObject2(capability.flow)) walkFlow(capability.flow);
72860
+ if (isObject2(capability.subAgent)) walkAgent(capability.subAgent);
72861
+ }
72862
+ }
72863
+ }
72864
+ if (isObject2(definition)) {
72865
+ if (Array.isArray(definition.steps) && !isObject2(definition.config)) walkFlow(definition);
72866
+ else walkAgent(definition);
72867
+ }
72868
+ return {
72869
+ models: Array.from(models),
72870
+ namedSecrets: Array.from(namedSecrets)
72871
+ };
72872
+ }
72873
+ function collectDeploymentSecretInventory(agentDef) {
72874
+ const requiredNames = /* @__PURE__ */ new Set();
72875
+ const optionalSettings = /* @__PURE__ */ new Map();
72876
+ const executionInventory = collectExportedExecutionInventory(agentDef);
72877
+ for (const model of executionInventory.models) {
72878
+ for (const name of resolveModelSecretNames(model)) requiredNames.add(name);
72879
+ for (const setting of resolveModelOptionalSettings(model)) {
72880
+ optionalSettings.set(setting.name, setting);
72881
+ }
72882
+ }
72883
+ for (const name of executionInventory.namedSecrets) requiredNames.add(name);
72884
+ for (const name of extractSecretReferencesFromAnyValue(agentDef, 512)) requiredNames.add(name);
72885
+ for (const name of requiredNames) optionalSettings.delete(name);
72886
+ return {
72887
+ requiredNames: Array.from(requiredNames),
72888
+ optionalSettings: Array.from(optionalSettings.values())
72889
+ };
72551
72890
  }
72552
72891
  function slugify2(s) {
72553
72892
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 63);
@@ -72656,10 +72995,17 @@ Scaffolding ${target} deployment to ${outDir}
72656
72995
  monorepoRoot = parent;
72657
72996
  }
72658
72997
  const allSecrets = /* @__PURE__ */ new Set();
72998
+ const allOptionalSettings = /* @__PURE__ */ new Map();
72659
72999
  for (const { def } of agentDefs) {
72660
- for (const s of collectSecretNames(def)) allSecrets.add(s);
73000
+ const inventory = collectDeploymentSecretInventory(def);
73001
+ for (const name of inventory.requiredNames) allSecrets.add(name);
73002
+ for (const setting of inventory.optionalSettings) {
73003
+ allOptionalSettings.set(setting.name, setting);
73004
+ }
72661
73005
  }
73006
+ for (const name of allSecrets) allOptionalSettings.delete(name);
72662
73007
  const secretNames = Array.from(allSecrets);
73008
+ const optionalSettings = Array.from(allOptionalSettings.values());
72663
73009
  if (target === "cloudflare") {
72664
73010
  fs16.mkdirSync(path17.join(outDir, "src"), { recursive: true });
72665
73011
  fs16.writeFileSync(path17.join(outDir, "src", "index.ts"), workerIndexTs(agentSlugs));
@@ -72669,7 +73015,10 @@ Scaffolding ${target} deployment to ${outDir}
72669
73015
  const setupPath = path17.join(outDir, "setup.sh");
72670
73016
  fs16.writeFileSync(setupPath, workerSetupSh(monorepoRoot));
72671
73017
  fs16.chmodSync(setupPath, 493);
72672
- fs16.writeFileSync(path17.join(outDir, "README.md"), workerReadme(agentNames, secretNames));
73018
+ fs16.writeFileSync(
73019
+ path17.join(outDir, "README.md"),
73020
+ workerReadme(agentNames, secretNames, optionalSettings)
73021
+ );
72673
73022
  } else if (target === "vercel") {
72674
73023
  fs16.mkdirSync(path17.join(outDir, "api"), { recursive: true });
72675
73024
  fs16.writeFileSync(path17.join(outDir, "api", "[[...route]].ts"), vercelRouteTs(agentSlugs));
@@ -72679,7 +73028,10 @@ Scaffolding ${target} deployment to ${outDir}
72679
73028
  const setupPath = path17.join(outDir, "setup.sh");
72680
73029
  fs16.writeFileSync(setupPath, vercelSetupSh(monorepoRoot));
72681
73030
  fs16.chmodSync(setupPath, 493);
72682
- fs16.writeFileSync(path17.join(outDir, "README.md"), vercelReadme(agentNames, secretNames));
73031
+ fs16.writeFileSync(
73032
+ path17.join(outDir, "README.md"),
73033
+ vercelReadme(agentNames, secretNames, optionalSettings)
73034
+ );
72683
73035
  } else {
72684
73036
  fs16.writeFileSync(path17.join(outDir, "server.ts"), serverTs());
72685
73037
  fs16.writeFileSync(path17.join(outDir, "Dockerfile"), dockerfile());
@@ -72689,7 +73041,10 @@ Scaffolding ${target} deployment to ${outDir}
72689
73041
  const setupPath = path17.join(outDir, "setup.sh");
72690
73042
  fs16.writeFileSync(setupPath, setupSh(monorepoRoot));
72691
73043
  fs16.chmodSync(setupPath, 493);
72692
- fs16.writeFileSync(path17.join(outDir, "README.md"), readme(agentNames, secretNames));
73044
+ fs16.writeFileSync(
73045
+ path17.join(outDir, "README.md"),
73046
+ readme(agentNames, secretNames, optionalSettings)
73047
+ );
72693
73048
  }
72694
73049
  console.log("");
72695
73050
  console.log(chalk38.green(`\u2713 Scaffold written to ${outDir}`));
@@ -72697,6 +73052,15 @@ Scaffolding ${target} deployment to ${outDir}
72697
73052
  console.log(chalk38.bold("Next steps:"));
72698
73053
  console.log(` cd ${options.output}`);
72699
73054
  console.log(" chmod +x setup.sh && ./setup.sh # pack runtime + install deps");
73055
+ if (optionalSettings.length > 0) {
73056
+ console.log("");
73057
+ console.log(chalk38.yellow("Optional provider settings (defaults used when unset):"));
73058
+ for (const setting of optionalSettings) {
73059
+ console.log(
73060
+ ` ${chalk38.cyan(setting.name)} (default: ${chalk38.cyan(setting.defaultValue)})`
73061
+ );
73062
+ }
73063
+ }
72700
73064
  if (target === "cloudflare") {
72701
73065
  console.log(" wrangler dev # test locally");
72702
73066
  console.log("");