@runtypelabs/cli 2.19.1 → 2.19.2

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 +3236 -21
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -15164,7 +15164,7 @@ var apiRoutingDocSchema = external_exports.object({
15164
15164
  path: ["api", "activeScript"]
15165
15165
  });
15166
15166
 
15167
- // ../shared/dist/chunk-R66POVE6.mjs
15167
+ // ../shared/dist/chunk-7Y2SRVP7.mjs
15168
15168
  function getNestedValue(obj, path18) {
15169
15169
  let normalizedPath = path18;
15170
15170
  normalizedPath = normalizedPath.replace(/^\$\.?/, "");
@@ -15207,6 +15207,14 @@ var SYSTEM_VARIABLES = /* @__PURE__ */ new Set([
15207
15207
  "_record",
15208
15208
  "_now",
15209
15209
  "_schedule",
15210
+ // `_tools` is engine-populated, but LATER than the other system vars: it is
15211
+ // injected after tool resolution, just before dispatch (see
15212
+ // `injectToolsSystemVariable` in the api prompt-executor), so a prompt may
15213
+ // reference `{{_tools.interfaces}}` / `{{_tools.count}}` / `{{_tools.names}}`.
15214
+ // It belongs to the system namespace so the validator / FPO gate don't flag
15215
+ // it as undeclared and the executors don't report it as "unresolved" before
15216
+ // injection runs.
15217
+ "_tools",
15210
15218
  "messages",
15211
15219
  "userMessage",
15212
15220
  "lastMessage",
@@ -15355,6 +15363,18 @@ function stringifyValue(value) {
15355
15363
  if (typeof value === "object") return JSON.stringify(value);
15356
15364
  return String(value);
15357
15365
  }
15366
+ function extractTemplateExpressionPaths(expr) {
15367
+ let parsed;
15368
+ try {
15369
+ parsed = parseTemplateExpression(expr);
15370
+ } catch {
15371
+ return [];
15372
+ }
15373
+ if (parsed.kind === "legacy") {
15374
+ return parsed.variable ? [parsed.variable] : [];
15375
+ }
15376
+ return parsed.operands.filter((o) => o.kind === "path").map((o) => o.path);
15377
+ }
15358
15378
  var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
15359
15379
  substitute(template, context = {}) {
15360
15380
  const usedVariables = [];
@@ -15986,7 +16006,15 @@ var stepCompleteEventSchema = external_exports.object({
15986
16006
  stopReason: wireStopReasonSchema.optional(),
15987
16007
  stepId: external_exports.string().optional(),
15988
16008
  stepName: external_exports.string().optional(),
15989
- toolContext: toolContextSchema.optional()
16009
+ toolContext: toolContextSchema.optional(),
16010
+ // Template variables that were still unresolved (`{{...}}` left intact) when
16011
+ // the prompt was dispatched to the model — the catch-all observability signal
16012
+ // for a surviving token (a missing flow input, an undeclared variable, or an
16013
+ // unknown-namespace typo). Only prompt steps populate it, and only when
16014
+ // non-empty; absence means every reference resolved. Non-fatal: the step still
16015
+ // ran. Sourced from the template engine's `missingVariables`, which already
16016
+ // includes unknown-namespace tokens (see `TemplateSubstitutionResult`).
16017
+ unresolvedVariables: external_exports.array(external_exports.string()).optional()
15990
16018
  });
15991
16019
  var stepErrorEventSchema = external_exports.object({
15992
16020
  ...baseFlowEvent,
@@ -16441,6 +16469,79 @@ var ExecuteToolSchema = external_exports.object({
16441
16469
  userId: external_exports.string()
16442
16470
  }).optional()
16443
16471
  });
16472
+ function parseToolInstanceId(toolId) {
16473
+ const hashIndex = toolId.indexOf("#");
16474
+ if (hashIndex === -1) {
16475
+ return { baseId: toolId, instanceId: "" };
16476
+ }
16477
+ return {
16478
+ baseId: toolId.substring(0, hashIndex),
16479
+ instanceId: toolId.substring(hashIndex + 1)
16480
+ };
16481
+ }
16482
+ function isBuiltInToolId(toolId) {
16483
+ return toolId.startsWith("builtin:");
16484
+ }
16485
+ function isPlatformToolId(toolId) {
16486
+ return toolId.startsWith("platform:");
16487
+ }
16488
+ var INTEGRATION_SERVER_IDS = /* @__PURE__ */ new Set(["slack", "google", "linear", "github", "telegram"]);
16489
+ function isBuiltInIntegrationToolId(toolId) {
16490
+ if (!toolId.startsWith("builtin:")) return false;
16491
+ const { baseId } = parseToolInstanceId(toolId);
16492
+ const parts = baseId.split(":");
16493
+ if (parts.length < 3) return false;
16494
+ return INTEGRATION_SERVER_IDS.has(parts[1]);
16495
+ }
16496
+ function isMCPToolId(toolId) {
16497
+ return toolId.startsWith("mcp:");
16498
+ }
16499
+ var NAMED_TOOL_REF_PREFIX = "tool:";
16500
+ function isNamedToolRef(toolId) {
16501
+ return toolId.startsWith(NAMED_TOOL_REF_PREFIX) && toolId.length > NAMED_TOOL_REF_PREFIX.length;
16502
+ }
16503
+ function parseNamedToolRef(toolId) {
16504
+ if (!isNamedToolRef(toolId)) return null;
16505
+ return { name: toolId.slice(NAMED_TOOL_REF_PREFIX.length) };
16506
+ }
16507
+ function separateToolIds(toolIds) {
16508
+ const builtInToolIds = [];
16509
+ const platformToolIds = [];
16510
+ const integrationToolIds = [];
16511
+ const mcpToolIds = [];
16512
+ const dataConnectionToolIds = [];
16513
+ const namedToolIds = [];
16514
+ const customToolIds = [];
16515
+ for (const toolId of toolIds) {
16516
+ if (isDataConnectionToolId(toolId)) {
16517
+ dataConnectionToolIds.push(toolId);
16518
+ } else if (isPlatformToolId(toolId)) {
16519
+ platformToolIds.push(toolId);
16520
+ } else if (isBuiltInIntegrationToolId(toolId)) {
16521
+ integrationToolIds.push(toolId);
16522
+ } else if (isBuiltInToolId(toolId)) {
16523
+ builtInToolIds.push(toolId);
16524
+ } else if (isMCPToolId(toolId)) {
16525
+ mcpToolIds.push(toolId);
16526
+ } else if (isNamedToolRef(toolId)) {
16527
+ namedToolIds.push(toolId);
16528
+ } else {
16529
+ customToolIds.push(toolId);
16530
+ }
16531
+ }
16532
+ return {
16533
+ builtInToolIds,
16534
+ platformToolIds,
16535
+ integrationToolIds,
16536
+ mcpToolIds,
16537
+ dataConnectionToolIds,
16538
+ namedToolIds,
16539
+ customToolIds
16540
+ };
16541
+ }
16542
+ function isDataConnectionToolId(toolId) {
16543
+ return toolId.startsWith("dc:");
16544
+ }
16444
16545
  var contextFallbackSchema = external_exports.union([
16445
16546
  external_exports.object({ type: external_exports.literal("retry"), delay: external_exports.number().optional() }),
16446
16547
  external_exports.object({
@@ -17247,6 +17348,1923 @@ var CONTEXT_STEP_TYPES = [
17247
17348
  "memory-summary"
17248
17349
  ];
17249
17350
  var FLOW_STEP_TYPES = ["prompt", ...CONTEXT_STEP_TYPES];
17351
+ var DEFAULT_MANAGED_SEND_FROM_DOMAIN = "runtype.email";
17352
+ var STAGING_MANAGED_SEND_FROM_DOMAIN = "runtype-staging.email";
17353
+ var MANAGED_SEND_FROM_DOMAINS = [
17354
+ DEFAULT_MANAGED_SEND_FROM_DOMAIN,
17355
+ STAGING_MANAGED_SEND_FROM_DOMAIN
17356
+ ];
17357
+ var MANAGED_TEMPLATE_SEND_FROM_ADDRESS_REGEX = /^{{\s*_flow\.id\s*}}@([^@\s]+)$/i;
17358
+ var LEGACY_MANAGED_SEND_FROM_ADDRESS_REGEX = /^[^@\s]+@messages\.runtype\.(com|ai)$/i;
17359
+ function normalizeFromAddress(configuredFrom) {
17360
+ return configuredFrom?.trim() ?? "";
17361
+ }
17362
+ function normalizeDomain(domain2) {
17363
+ return domain2?.trim().toLowerCase() ?? "";
17364
+ }
17365
+ function extractDomainFromAddress(fromAddress) {
17366
+ const normalizedFrom = normalizeFromAddress(fromAddress);
17367
+ const atIndex = normalizedFrom.lastIndexOf("@");
17368
+ if (atIndex === -1) {
17369
+ return void 0;
17370
+ }
17371
+ const domain2 = normalizedFrom.slice(atIndex + 1);
17372
+ return normalizeDomain(domain2) || void 0;
17373
+ }
17374
+ function getReservedManagedSendFromDomains(preferredManagedDomain) {
17375
+ const preferredDomain = normalizeDomain(preferredManagedDomain);
17376
+ const reservedDomains = preferredDomain ? [preferredDomain, ...MANAGED_SEND_FROM_DOMAINS] : [...MANAGED_SEND_FROM_DOMAINS];
17377
+ return Array.from(new Set(reservedDomains));
17378
+ }
17379
+ function isReservedManagedSendFromDomain(domain2, preferredManagedDomain) {
17380
+ const normalizedDomain = normalizeDomain(domain2);
17381
+ if (!normalizedDomain) {
17382
+ return false;
17383
+ }
17384
+ return getReservedManagedSendFromDomains(preferredManagedDomain).includes(normalizedDomain);
17385
+ }
17386
+ function extractManagedTemplateDomain(configuredFrom) {
17387
+ const normalizedFrom = normalizeFromAddress(configuredFrom);
17388
+ const managedTemplateMatch = normalizedFrom.match(MANAGED_TEMPLATE_SEND_FROM_ADDRESS_REGEX);
17389
+ return normalizeDomain(managedTemplateMatch?.[1]) || void 0;
17390
+ }
17391
+ function isManagedTemplateSendFromAddress(configuredFrom, preferredManagedDomain) {
17392
+ return isReservedManagedSendFromDomain(
17393
+ extractManagedTemplateDomain(configuredFrom),
17394
+ preferredManagedDomain
17395
+ );
17396
+ }
17397
+ function isLegacyManagedSendFromAddress(configuredFrom) {
17398
+ return LEGACY_MANAGED_SEND_FROM_ADDRESS_REGEX.test(normalizeFromAddress(configuredFrom));
17399
+ }
17400
+ function shouldUseManagedSendFromAddress(configuredFrom, preferredManagedDomain) {
17401
+ if (!normalizeFromAddress(configuredFrom)) {
17402
+ return true;
17403
+ }
17404
+ return isManagedTemplateSendFromAddress(configuredFrom, preferredManagedDomain) || isLegacyManagedSendFromAddress(configuredFrom);
17405
+ }
17406
+ function isCustomSendFromAddressOnManagedDomain(configuredFrom, preferredManagedDomain) {
17407
+ if (shouldUseManagedSendFromAddress(configuredFrom, preferredManagedDomain)) {
17408
+ return false;
17409
+ }
17410
+ return isReservedManagedSendFromDomain(
17411
+ extractDomainFromAddress(configuredFrom),
17412
+ preferredManagedDomain
17413
+ );
17414
+ }
17415
+ var NormalizationError = class extends Error {
17416
+ constructor(message, stepType, fieldName, expectedType, actualValue) {
17417
+ super(message);
17418
+ this.stepType = stepType;
17419
+ this.fieldName = fieldName;
17420
+ this.expectedType = expectedType;
17421
+ this.actualValue = actualValue;
17422
+ this.name = "NormalizationError";
17423
+ }
17424
+ };
17425
+ function validateRequired(value, fieldName, stepType) {
17426
+ if (value === null || value === void 0 || value === "") {
17427
+ throw new NormalizationError(
17428
+ `Missing required field '${fieldName}' for ${stepType} step`,
17429
+ stepType,
17430
+ fieldName,
17431
+ "non-null value",
17432
+ value
17433
+ );
17434
+ }
17435
+ }
17436
+ function validateString(value, fieldName, stepType, required2 = false) {
17437
+ if (required2) {
17438
+ validateRequired(value, fieldName, stepType);
17439
+ }
17440
+ if (value !== void 0 && value !== null && typeof value !== "string") {
17441
+ throw new NormalizationError(
17442
+ `Field '${fieldName}' must be a string for ${stepType} step`,
17443
+ stepType,
17444
+ fieldName,
17445
+ "string",
17446
+ typeof value
17447
+ );
17448
+ }
17449
+ }
17450
+ function validateNumber(value, fieldName, stepType, required2 = false) {
17451
+ if (required2) {
17452
+ validateRequired(value, fieldName, stepType);
17453
+ }
17454
+ if (value !== void 0 && value !== null) {
17455
+ const num = Number(value);
17456
+ if (isNaN(num)) {
17457
+ throw new NormalizationError(
17458
+ `Field '${fieldName}' must be a number for ${stepType} step`,
17459
+ stepType,
17460
+ fieldName,
17461
+ "number",
17462
+ typeof value
17463
+ );
17464
+ }
17465
+ }
17466
+ }
17467
+ function normalizeOptionalNumber(value) {
17468
+ if (value === void 0 || value === null) {
17469
+ return void 0;
17470
+ }
17471
+ return Number(value);
17472
+ }
17473
+ function validateBoolean(value, fieldName, stepType, required2 = false) {
17474
+ if (required2) {
17475
+ validateRequired(value, fieldName, stepType);
17476
+ }
17477
+ if (value !== void 0 && value !== null && typeof value !== "boolean") {
17478
+ throw new NormalizationError(
17479
+ `Field '${fieldName}' must be a boolean for ${stepType} step`,
17480
+ stepType,
17481
+ fieldName,
17482
+ "boolean",
17483
+ typeof value
17484
+ );
17485
+ }
17486
+ }
17487
+ function validateEnum(value, allowedValues, fieldName, stepType, required2 = false) {
17488
+ if (required2) {
17489
+ validateRequired(value, fieldName, stepType);
17490
+ }
17491
+ if (value !== void 0 && value !== null && !allowedValues.includes(value)) {
17492
+ throw new NormalizationError(
17493
+ `Field '${fieldName}' must be one of [${allowedValues.join(", ")}] for ${stepType} step, got: ${value}`,
17494
+ stepType,
17495
+ fieldName,
17496
+ `one of [${allowedValues.join(", ")}]`,
17497
+ value
17498
+ );
17499
+ }
17500
+ }
17501
+ function validateObject(value, fieldName, stepType, required2 = false) {
17502
+ if (required2) {
17503
+ validateRequired(value, fieldName, stepType);
17504
+ }
17505
+ if (value !== void 0 && value !== null) {
17506
+ if (typeof value !== "object" || Array.isArray(value)) {
17507
+ throw new NormalizationError(
17508
+ `Field '${fieldName}' must be an object for ${stepType} step`,
17509
+ stepType,
17510
+ fieldName,
17511
+ "object",
17512
+ Array.isArray(value) ? "array" : typeof value
17513
+ );
17514
+ }
17515
+ }
17516
+ }
17517
+ function validateArray(value, fieldName, stepType, required2 = false) {
17518
+ if (required2) {
17519
+ validateRequired(value, fieldName, stepType);
17520
+ }
17521
+ if (value !== void 0 && value !== null && !Array.isArray(value)) {
17522
+ throw new NormalizationError(
17523
+ `Field '${fieldName}' must be an array for ${stepType} step`,
17524
+ stepType,
17525
+ fieldName,
17526
+ "array",
17527
+ typeof value
17528
+ );
17529
+ }
17530
+ }
17531
+ function validateConfig(config3, stepType) {
17532
+ if (!config3 || typeof config3 !== "object" || Array.isArray(config3)) {
17533
+ throw new NormalizationError(
17534
+ `Config must be a valid object for ${stepType} step`,
17535
+ stepType,
17536
+ "config",
17537
+ "object",
17538
+ typeof config3
17539
+ );
17540
+ }
17541
+ }
17542
+ function normalizeErrorHandling(value) {
17543
+ if (!value) return void 0;
17544
+ if (typeof value === "object" && value !== null) {
17545
+ const objectValue = value;
17546
+ const onError = objectValue.onError || objectValue.on_error || "continue";
17547
+ return {
17548
+ onError: onError === "default" ? "continue" : onError,
17549
+ fallbacks: objectValue.fallbacks
17550
+ };
17551
+ }
17552
+ if (typeof value === "string") {
17553
+ const validModes = ["fail", "continue", "fallback", "default"];
17554
+ if (!validModes.includes(value)) {
17555
+ return { onError: "continue" };
17556
+ }
17557
+ return {
17558
+ onError: value === "default" ? "continue" : value
17559
+ };
17560
+ }
17561
+ return void 0;
17562
+ }
17563
+ function validateAndNormalizeErrorHandling(value, fieldName, stepType) {
17564
+ if (value === void 0 || value === null) return void 0;
17565
+ if (typeof value === "string") {
17566
+ const validModes = ["fail", "continue", "fallback", "default"];
17567
+ if (!validModes.includes(value)) {
17568
+ throw new NormalizationError(
17569
+ `Field '${fieldName}' must be one of [${validModes.join(", ")}] or an error handling object for ${stepType} step, got: ${value}`,
17570
+ stepType,
17571
+ fieldName,
17572
+ `one of [${validModes.join(", ")}] or object`,
17573
+ value
17574
+ );
17575
+ }
17576
+ }
17577
+ if (typeof value === "object" && value !== null) {
17578
+ const objectValue = value;
17579
+ const onError = objectValue.onError || objectValue.on_error;
17580
+ if (onError) {
17581
+ const validModes = ["fail", "continue", "fallback", "default"];
17582
+ if (!validModes.includes(onError)) {
17583
+ throw new NormalizationError(
17584
+ `Field '${fieldName}.onError' must be one of [${validModes.join(", ")}] for ${stepType} step, got: ${onError}`,
17585
+ stepType,
17586
+ `${fieldName}.onError`,
17587
+ `one of [${validModes.join(", ")}]`,
17588
+ onError
17589
+ );
17590
+ }
17591
+ }
17592
+ }
17593
+ return normalizeErrorHandling(value);
17594
+ }
17595
+ function normalizeContextStep(apiStep, options = {}) {
17596
+ if (!apiStep || typeof apiStep !== "object") {
17597
+ throw new NormalizationError(
17598
+ "Step must be a valid object",
17599
+ "unknown",
17600
+ "apiStep",
17601
+ "object",
17602
+ typeof apiStep
17603
+ );
17604
+ }
17605
+ validateRequired(apiStep.id, "id", apiStep.type || "unknown");
17606
+ validateRequired(apiStep.type, "type", "step");
17607
+ validateRequired(apiStep.name, "name", apiStep.type || "unknown");
17608
+ validateRequired(apiStep.order, "order", apiStep.type || "unknown");
17609
+ validateString(apiStep.id, "id", apiStep.type, true);
17610
+ validateString(apiStep.type, "type", "step", true);
17611
+ validateString(apiStep.name, "name", apiStep.type, true);
17612
+ validateNumber(apiStep.order, "order", apiStep.type, true);
17613
+ const validStepTypes = [
17614
+ "crawl",
17615
+ "fetch-url",
17616
+ "retrieve-record",
17617
+ "fetch-github",
17618
+ "api-call",
17619
+ "transform-data",
17620
+ "template",
17621
+ "conditional",
17622
+ "set-variable",
17623
+ "upsert-record",
17624
+ "send-email",
17625
+ "send-text",
17626
+ "send-event",
17627
+ "send-stream",
17628
+ "update-record",
17629
+ "search",
17630
+ "generate-embedding",
17631
+ "vector-search",
17632
+ "tool-call",
17633
+ "wait-until",
17634
+ "paginate-api",
17635
+ "store-vector",
17636
+ "execute-agent",
17637
+ "store-asset",
17638
+ "generate-pdf",
17639
+ "save-memory",
17640
+ "recall-memory",
17641
+ "memory-summary"
17642
+ ];
17643
+ if (!validStepTypes.includes(apiStep.type)) {
17644
+ throw new NormalizationError(
17645
+ `Unknown context step type: ${apiStep.type}. Must be one of: ${validStepTypes.join(", ")}`,
17646
+ apiStep.type,
17647
+ "type",
17648
+ `one of [${validStepTypes.join(", ")}]`,
17649
+ apiStep.type
17650
+ );
17651
+ }
17652
+ const baseStep = {
17653
+ id: apiStep.id,
17654
+ type: apiStep.type,
17655
+ name: apiStep.name,
17656
+ order: apiStep.order,
17657
+ enabled: apiStep.enabled ?? true
17658
+ };
17659
+ try {
17660
+ switch (apiStep.type) {
17661
+ case "crawl":
17662
+ return {
17663
+ ...baseStep,
17664
+ type: "crawl",
17665
+ config: normalizeCrawlConfig(apiStep.config)
17666
+ };
17667
+ case "fetch-url":
17668
+ return {
17669
+ ...baseStep,
17670
+ type: "fetch-url",
17671
+ config: normalizeFetchUrlConfig(apiStep.config)
17672
+ };
17673
+ case "retrieve-record":
17674
+ return {
17675
+ ...baseStep,
17676
+ type: "retrieve-record",
17677
+ config: normalizeRetrieveRecordConfig(apiStep.config)
17678
+ };
17679
+ case "fetch-github":
17680
+ return {
17681
+ ...baseStep,
17682
+ type: "fetch-github",
17683
+ config: normalizeFetchGithubConfig(apiStep.config)
17684
+ };
17685
+ case "api-call":
17686
+ return {
17687
+ ...baseStep,
17688
+ type: "api-call",
17689
+ config: normalizeApiCallConfig(apiStep.config)
17690
+ };
17691
+ case "transform-data":
17692
+ return {
17693
+ ...baseStep,
17694
+ type: "transform-data",
17695
+ config: normalizeTransformDataConfig(apiStep.config)
17696
+ };
17697
+ case "template":
17698
+ return {
17699
+ ...baseStep,
17700
+ type: "template",
17701
+ config: normalizeTemplateConfig(apiStep.config)
17702
+ };
17703
+ case "conditional":
17704
+ return {
17705
+ ...baseStep,
17706
+ type: "conditional",
17707
+ config: normalizeConditionalConfig(apiStep.config)
17708
+ };
17709
+ case "set-variable":
17710
+ return {
17711
+ ...baseStep,
17712
+ type: "set-variable",
17713
+ config: normalizeSetVariableConfig(apiStep.config)
17714
+ };
17715
+ case "upsert-record":
17716
+ return {
17717
+ ...baseStep,
17718
+ type: "upsert-record",
17719
+ config: normalizeUpsertRecordConfig(apiStep.config)
17720
+ };
17721
+ case "send-email":
17722
+ return {
17723
+ ...baseStep,
17724
+ type: "send-email",
17725
+ config: normalizeSendEmailConfig(apiStep.config, options)
17726
+ };
17727
+ case "send-text":
17728
+ return {
17729
+ ...baseStep,
17730
+ type: "send-text",
17731
+ config: normalizeSendTextConfig(apiStep.config)
17732
+ };
17733
+ case "send-event":
17734
+ return {
17735
+ ...baseStep,
17736
+ type: "send-event",
17737
+ config: normalizeSendEventConfig(apiStep.config)
17738
+ };
17739
+ case "send-stream":
17740
+ return {
17741
+ ...baseStep,
17742
+ type: "send-stream",
17743
+ config: normalizeSendStreamConfig(apiStep.config)
17744
+ };
17745
+ case "update-record":
17746
+ return {
17747
+ ...baseStep,
17748
+ type: "update-record",
17749
+ config: normalizeUpdateRecordConfig(apiStep.config)
17750
+ };
17751
+ case "search":
17752
+ return {
17753
+ ...baseStep,
17754
+ type: "search",
17755
+ config: normalizeSearchConfig(apiStep.config)
17756
+ };
17757
+ case "generate-embedding":
17758
+ return {
17759
+ ...baseStep,
17760
+ type: "generate-embedding",
17761
+ config: normalizeGenerateEmbeddingConfig(apiStep.config)
17762
+ };
17763
+ case "vector-search":
17764
+ return {
17765
+ ...baseStep,
17766
+ type: "vector-search",
17767
+ config: normalizeVectorSearchConfig(apiStep.config)
17768
+ };
17769
+ case "paginate-api":
17770
+ return {
17771
+ ...baseStep,
17772
+ type: "paginate-api",
17773
+ config: normalizePaginateApiConfig(apiStep.config)
17774
+ };
17775
+ case "store-vector":
17776
+ return {
17777
+ ...baseStep,
17778
+ type: "store-vector",
17779
+ config: normalizeStoreVectorConfig(apiStep.config)
17780
+ };
17781
+ case "tool-call":
17782
+ return {
17783
+ ...baseStep,
17784
+ type: "tool-call",
17785
+ config: normalizeToolCallConfig(apiStep.config)
17786
+ };
17787
+ case "wait-until":
17788
+ return {
17789
+ ...baseStep,
17790
+ type: "wait-until",
17791
+ config: normalizeWaitUntilConfig(apiStep.config)
17792
+ };
17793
+ case "execute-agent":
17794
+ return {
17795
+ ...baseStep,
17796
+ type: "execute-agent",
17797
+ config: normalizeExecuteAgentConfig(apiStep.config)
17798
+ };
17799
+ case "store-asset":
17800
+ return {
17801
+ ...baseStep,
17802
+ type: "store-asset",
17803
+ config: normalizeStoreAssetConfig(apiStep.config)
17804
+ };
17805
+ case "generate-pdf":
17806
+ return {
17807
+ ...baseStep,
17808
+ type: "generate-pdf",
17809
+ config: normalizeGeneratePdfConfig(apiStep.config)
17810
+ };
17811
+ case "save-memory":
17812
+ return {
17813
+ ...baseStep,
17814
+ type: "save-memory",
17815
+ config: normalizeSaveMemoryConfig(apiStep.config)
17816
+ };
17817
+ case "recall-memory":
17818
+ return {
17819
+ ...baseStep,
17820
+ type: "recall-memory",
17821
+ config: normalizeRecallMemoryConfig(apiStep.config)
17822
+ };
17823
+ case "memory-summary":
17824
+ return {
17825
+ ...baseStep,
17826
+ type: "memory-summary",
17827
+ config: normalizeMemorySummaryConfig(apiStep.config)
17828
+ };
17829
+ default:
17830
+ throw new NormalizationError(
17831
+ `Unknown context step type: ${apiStep.type}`,
17832
+ apiStep.type,
17833
+ "type",
17834
+ "valid step type",
17835
+ apiStep.type
17836
+ );
17837
+ }
17838
+ } catch (error51) {
17839
+ if (error51 instanceof NormalizationError) {
17840
+ throw error51;
17841
+ }
17842
+ throw new NormalizationError(
17843
+ `Failed to normalize ${apiStep.type} step: ${error51 instanceof Error ? error51.message : String(error51)}`,
17844
+ apiStep.type,
17845
+ void 0,
17846
+ void 0,
17847
+ error51
17848
+ );
17849
+ }
17850
+ }
17851
+ function normalizeHttpConfig(config3) {
17852
+ validateObject(config3, "http", "http-config", true);
17853
+ validateString(config3.url, "http.url", "http-config", true);
17854
+ if (config3.method) {
17855
+ validateEnum(
17856
+ config3.method,
17857
+ ["GET", "POST", "PUT", "DELETE", "PATCH"],
17858
+ "http.method",
17859
+ "http-config"
17860
+ );
17861
+ }
17862
+ if (config3.headers !== void 0 && config3.headers !== null) {
17863
+ validateObject(config3.headers, "http.headers", "http-config");
17864
+ }
17865
+ if (config3.timeout !== void 0 && config3.timeout !== null) {
17866
+ validateNumber(config3.timeout, "http.timeout", "http-config");
17867
+ }
17868
+ return {
17869
+ url: config3.url,
17870
+ method: config3.method,
17871
+ headers: config3.headers,
17872
+ // Preserve user headers as-is
17873
+ body: config3.body,
17874
+ timeout: config3.timeout
17875
+ };
17876
+ }
17877
+ function normalizeCrawlConfig(config3) {
17878
+ validateConfig(config3, "crawl");
17879
+ const url2 = config3.url;
17880
+ validateString(url2, "url", "crawl", true);
17881
+ validateString(config3.outputVariable ?? config3.output_variable, "outputVariable", "crawl", true);
17882
+ const limitRaw = config3.limit;
17883
+ const depthRaw = config3.depth;
17884
+ const maxAgeRaw = config3.maxAge ?? config3.max_age;
17885
+ const modifiedSince = config3.modifiedSince ?? config3.modified_since;
17886
+ const setExtraHTTPHeaders = config3.setExtraHTTPHeaders ?? config3.set_extra_http_headers;
17887
+ const gotoOptions = config3.gotoOptions ?? config3.goto_options;
17888
+ const waitForSelector = config3.waitForSelector ?? config3.wait_for_selector;
17889
+ const rejectResourceTypes = config3.rejectResourceTypes ?? config3.reject_resource_types;
17890
+ const rejectRequestPattern = config3.rejectRequestPattern ?? config3.reject_request_pattern;
17891
+ const userAgent = config3.userAgent ?? config3.user_agent;
17892
+ const jsonOptions = config3.jsonOptions ?? config3.json_options;
17893
+ const pollIntervalMsRaw = config3.pollIntervalMs ?? config3.poll_interval_ms;
17894
+ const completionTimeoutMsRaw = config3.completionTimeoutMs ?? config3.completion_timeout_ms;
17895
+ if (limitRaw !== void 0 && limitRaw !== null) validateNumber(limitRaw, "limit", "crawl");
17896
+ if (depthRaw !== void 0 && depthRaw !== null) validateNumber(depthRaw, "depth", "crawl");
17897
+ if (config3.source !== void 0) validateString(config3.source, "source", "crawl");
17898
+ if (config3.formats !== void 0) validateArray(config3.formats, "formats", "crawl");
17899
+ if (config3.render !== void 0) validateBoolean(config3.render, "render", "crawl");
17900
+ if (maxAgeRaw !== void 0 && maxAgeRaw !== null) validateNumber(maxAgeRaw, "maxAge", "crawl");
17901
+ if (modifiedSince !== void 0) validateString(modifiedSince, "modifiedSince", "crawl");
17902
+ if (config3.options !== void 0) validateObject(config3.options, "options", "crawl");
17903
+ if (config3.authenticate !== void 0) validateObject(config3.authenticate, "authenticate", "crawl");
17904
+ if (config3.cookies !== void 0) validateArray(config3.cookies, "cookies", "crawl");
17905
+ if (setExtraHTTPHeaders !== void 0) {
17906
+ validateObject(setExtraHTTPHeaders, "setExtraHTTPHeaders", "crawl");
17907
+ }
17908
+ if (gotoOptions !== void 0) validateObject(gotoOptions, "gotoOptions", "crawl");
17909
+ if (waitForSelector !== void 0) validateString(waitForSelector, "waitForSelector", "crawl");
17910
+ if (rejectResourceTypes !== void 0) {
17911
+ validateArray(rejectResourceTypes, "rejectResourceTypes", "crawl");
17912
+ }
17913
+ if (rejectRequestPattern !== void 0) {
17914
+ if (typeof rejectRequestPattern !== "string" && !Array.isArray(rejectRequestPattern)) {
17915
+ throw new NormalizationError(
17916
+ "Field 'rejectRequestPattern' must be a string or array for crawl step",
17917
+ "crawl",
17918
+ "rejectRequestPattern",
17919
+ "string | array",
17920
+ typeof rejectRequestPattern
17921
+ );
17922
+ }
17923
+ }
17924
+ if (userAgent !== void 0) validateString(userAgent, "userAgent", "crawl");
17925
+ if (jsonOptions !== void 0) validateObject(jsonOptions, "jsonOptions", "crawl");
17926
+ if (config3.streamOutput !== void 0) validateBoolean(config3.streamOutput, "streamOutput", "crawl");
17927
+ if (pollIntervalMsRaw !== void 0 && pollIntervalMsRaw !== null) {
17928
+ validateNumber(pollIntervalMsRaw, "pollIntervalMs", "crawl");
17929
+ }
17930
+ if (completionTimeoutMsRaw !== void 0 && completionTimeoutMsRaw !== null) {
17931
+ validateNumber(completionTimeoutMsRaw, "completionTimeoutMs", "crawl");
17932
+ }
17933
+ const errorHandling = validateAndNormalizeErrorHandling(
17934
+ config3.errorHandling ?? config3.error_handling,
17935
+ "errorHandling",
17936
+ "crawl"
17937
+ );
17938
+ const limit = normalizeOptionalNumber(limitRaw);
17939
+ const depth = normalizeOptionalNumber(depthRaw);
17940
+ const maxAge = normalizeOptionalNumber(maxAgeRaw);
17941
+ const pollIntervalMs = normalizeOptionalNumber(pollIntervalMsRaw);
17942
+ const completionTimeoutMs = normalizeOptionalNumber(completionTimeoutMsRaw);
17943
+ return {
17944
+ url: url2,
17945
+ limit,
17946
+ depth,
17947
+ source: config3.source,
17948
+ formats: config3.formats,
17949
+ render: config3.render,
17950
+ maxAge,
17951
+ modifiedSince,
17952
+ options: config3.options,
17953
+ authenticate: config3.authenticate,
17954
+ cookies: config3.cookies,
17955
+ setExtraHTTPHeaders,
17956
+ gotoOptions,
17957
+ waitForSelector,
17958
+ rejectResourceTypes,
17959
+ rejectRequestPattern,
17960
+ userAgent,
17961
+ jsonOptions,
17962
+ outputVariable: config3.outputVariable ?? config3.output_variable,
17963
+ streamOutput: config3.streamOutput ?? config3.stream_output,
17964
+ errorHandling,
17965
+ defaultValue: config3.defaultValue ?? config3.default_value,
17966
+ pollIntervalMs,
17967
+ completionTimeoutMs,
17968
+ asyncCrawl: config3.asyncCrawl
17969
+ };
17970
+ }
17971
+ function normalizeAuthConfig(config3) {
17972
+ if (!config3) return void 0;
17973
+ validateObject(config3, "auth", "auth-config", true);
17974
+ validateEnum(
17975
+ config3.type,
17976
+ ["none", "bearer", "basic", "api-key", "custom"],
17977
+ "auth.type",
17978
+ "auth-config",
17979
+ true
17980
+ );
17981
+ if (config3.token) validateString(config3.token, "auth.token", "auth-config");
17982
+ if (config3.username) validateString(config3.username, "auth.username", "auth-config");
17983
+ if (config3.password) validateString(config3.password, "auth.password", "auth-config");
17984
+ if (config3.apiKey) validateString(config3.apiKey, "auth.apiKey", "auth-config");
17985
+ if (config3.headerName) validateString(config3.headerName, "auth.headerName", "auth-config");
17986
+ if (config3.customHeaders !== void 0 && config3.customHeaders !== null) {
17987
+ validateObject(config3.customHeaders, "auth.customHeaders", "auth-config");
17988
+ }
17989
+ return {
17990
+ type: config3.type,
17991
+ token: config3.token,
17992
+ username: config3.username,
17993
+ password: config3.password,
17994
+ apiKey: config3.apiKey,
17995
+ headerName: config3.headerName,
17996
+ customHeaders: config3.customHeaders
17997
+ };
17998
+ }
17999
+ function normalizeFirecrawlConfig(config3) {
18000
+ if (!config3) return void 0;
18001
+ return {
18002
+ formats: config3.formats,
18003
+ actions: config3.actions,
18004
+ location: config3.location,
18005
+ maxAge: config3.maxAge,
18006
+ storeInCache: config3.storeInCache,
18007
+ onlyMainContent: config3.onlyMainContent,
18008
+ jsonSchema: config3.jsonSchema,
18009
+ jsonPrompt: config3.jsonPrompt
18010
+ };
18011
+ }
18012
+ function normalizeFetchUrlConfig(config3) {
18013
+ validateConfig(config3, "fetch-url");
18014
+ validateObject(config3.http, "http", "fetch-url", true);
18015
+ validateString(config3.outputVariable, "outputVariable", "fetch-url", true);
18016
+ if (config3.responseType) {
18017
+ validateEnum(config3.responseType, ["json", "text", "xml"], "responseType", "fetch-url");
18018
+ }
18019
+ if (config3.markdownIfAvailable !== void 0) {
18020
+ validateBoolean(config3.markdownIfAvailable, "markdownIfAvailable", "fetch-url");
18021
+ }
18022
+ const errorHandling = validateAndNormalizeErrorHandling(
18023
+ config3.errorHandling,
18024
+ "errorHandling",
18025
+ "fetch-url"
18026
+ );
18027
+ if (config3.fetchMethod) {
18028
+ validateEnum(config3.fetchMethod, ["standard", "firecrawl"], "fetchMethod", "fetch-url");
18029
+ }
18030
+ return {
18031
+ http: normalizeHttpConfig(config3.http),
18032
+ auth: normalizeAuthConfig(config3.auth),
18033
+ responseType: config3.responseType,
18034
+ markdownIfAvailable: config3.markdownIfAvailable,
18035
+ outputVariable: config3.outputVariable,
18036
+ streamOutput: config3.streamOutput,
18037
+ errorHandling,
18038
+ defaultValue: config3.defaultValue,
18039
+ fetchMethod: config3.fetchMethod,
18040
+ firecrawl: normalizeFirecrawlConfig(config3.firecrawl)
18041
+ };
18042
+ }
18043
+ function normalizeRetrieveRecordConfig(config3) {
18044
+ validateConfig(config3, "retrieve-record");
18045
+ const filter = config3.recordFilter;
18046
+ const hasFilter = filter && typeof filter === "object" && typeof filter.type === "string" && filter.type.length > 0;
18047
+ if (!config3.recordId && !config3.recordType && !config3.recordName && !hasFilter) {
18048
+ throw new NormalizationError(
18049
+ `retrieve-record step requires at least one of 'recordId', 'recordType', 'recordName', or 'recordFilter'`,
18050
+ "retrieve-record",
18051
+ "recordId/recordType/recordName/recordFilter",
18052
+ "at least one identification field",
18053
+ void 0
18054
+ );
18055
+ }
18056
+ validateString(config3.outputVariable, "outputVariable", "retrieve-record", true);
18057
+ if (config3.fieldsToInclude)
18058
+ validateString(config3.fieldsToInclude, "fieldsToInclude", "retrieve-record");
18059
+ if (config3.fieldsToExclude)
18060
+ validateString(config3.fieldsToExclude, "fieldsToExclude", "retrieve-record");
18061
+ if (config3.availableFields)
18062
+ validateArray(config3.availableFields, "availableFields", "retrieve-record");
18063
+ return {
18064
+ retrievalMode: config3.retrievalMode,
18065
+ recordType: config3.recordType,
18066
+ recordName: config3.recordName,
18067
+ recordId: config3.recordId,
18068
+ recordFilter: config3.recordFilter,
18069
+ fieldsToInclude: config3.fieldsToInclude,
18070
+ fieldsToExclude: config3.fieldsToExclude,
18071
+ availableFields: config3.availableFields,
18072
+ outputVariable: config3.outputVariable
18073
+ };
18074
+ }
18075
+ function normalizeFetchGithubConfig(config3) {
18076
+ validateConfig(config3, "fetch-github");
18077
+ validateString(config3.repository, "repository", "fetch-github", true);
18078
+ validateString(config3.outputVariable, "outputVariable", "fetch-github", true);
18079
+ if (config3.path) validateString(config3.path, "path", "fetch-github");
18080
+ if (config3.branch) validateString(config3.branch, "branch", "fetch-github");
18081
+ if (config3.token) validateString(config3.token, "token", "fetch-github");
18082
+ if (config3.contentType) {
18083
+ validateEnum(config3.contentType, ["raw", "metadata", "both"], "contentType", "fetch-github");
18084
+ }
18085
+ if (config3.includePatterns)
18086
+ validateArray(config3.includePatterns, "includePatterns", "fetch-github");
18087
+ if (config3.excludePatterns)
18088
+ validateArray(config3.excludePatterns, "excludePatterns", "fetch-github");
18089
+ if (config3.compress !== void 0 && config3.compress !== null) {
18090
+ validateBoolean(config3.compress, "compress", "fetch-github");
18091
+ }
18092
+ if (config3.style) {
18093
+ validateEnum(config3.style, ["xml", "json", "markdown"], "style", "fetch-github");
18094
+ }
18095
+ return {
18096
+ repository: config3.repository,
18097
+ path: config3.path,
18098
+ branch: config3.branch,
18099
+ token: config3.token,
18100
+ outputVariable: config3.outputVariable,
18101
+ contentType: config3.contentType,
18102
+ includePatterns: config3.includePatterns,
18103
+ excludePatterns: config3.excludePatterns,
18104
+ compress: config3.compress,
18105
+ style: config3.style
18106
+ };
18107
+ }
18108
+ function normalizeApiCallConfig(config3) {
18109
+ validateConfig(config3, "api-call");
18110
+ validateObject(config3.http, "http", "api-call", true);
18111
+ validateString(config3.outputVariable, "outputVariable", "api-call", true);
18112
+ if (config3.requestTemplate !== void 0 && config3.requestTemplate !== null) {
18113
+ validateString(config3.requestTemplate, "requestTemplate", "api-call");
18114
+ }
18115
+ if (config3.responseMapping !== void 0 && config3.responseMapping !== null) {
18116
+ validateObject(config3.responseMapping, "responseMapping", "api-call");
18117
+ }
18118
+ const errorHandling = validateAndNormalizeErrorHandling(
18119
+ config3.errorHandling,
18120
+ "errorHandling",
18121
+ "api-call"
18122
+ );
18123
+ return {
18124
+ http: normalizeHttpConfig(config3.http),
18125
+ auth: normalizeAuthConfig(config3.auth),
18126
+ requestTemplate: config3.requestTemplate,
18127
+ responseMapping: config3.responseMapping,
18128
+ // Preserve user mapping keys
18129
+ outputVariable: config3.outputVariable,
18130
+ errorHandling,
18131
+ defaultValue: config3.defaultValue
18132
+ };
18133
+ }
18134
+ function normalizeTransformDataConfig(config3) {
18135
+ validateConfig(config3, "transform-data");
18136
+ validateString(config3.script, "script", "transform-data", true);
18137
+ const outputVariable = config3.outputVariable ?? config3.output_variable;
18138
+ validateString(outputVariable, "outputVariable", "transform-data", true);
18139
+ if (config3.sandboxProvider) {
18140
+ validateEnum(
18141
+ config3.sandboxProvider,
18142
+ ["quickjs", "daytona", "cloudflare-worker", "runtype-sandbox", "cloudflare-sandbox"],
18143
+ "sandboxProvider",
18144
+ "transform-data"
18145
+ );
18146
+ if (config3.sandboxProvider === "cloudflare-sandbox") {
18147
+ config3.sandboxProvider = "runtype-sandbox";
18148
+ }
18149
+ }
18150
+ if (config3.language) {
18151
+ validateEnum(
18152
+ config3.language,
18153
+ ["javascript", "typescript", "python"],
18154
+ "language",
18155
+ "transform-data"
18156
+ );
18157
+ }
18158
+ if (config3.persistSandbox !== void 0 && typeof config3.persistSandbox !== "boolean") {
18159
+ throw new NormalizationError(
18160
+ "persistSandbox must be a boolean",
18161
+ "transform-data",
18162
+ "persistSandbox",
18163
+ "boolean",
18164
+ config3.persistSandbox
18165
+ );
18166
+ }
18167
+ if (config3.streamOutput !== void 0) {
18168
+ validateBoolean(config3.streamOutput, "streamOutput", "transform-data");
18169
+ }
18170
+ if (config3.reuseSandboxId !== void 0) {
18171
+ validateString(config3.reuseSandboxId, "reuseSandboxId", "transform-data", false);
18172
+ }
18173
+ if (config3.inputMode) {
18174
+ validateEnum(config3.inputMode, ["code", "variable"], "inputMode", "transform-data");
18175
+ }
18176
+ if (config3.packageJson && typeof config3.packageJson !== "string") {
18177
+ throw new NormalizationError("packageJson must be a string", "transform-data");
18178
+ }
18179
+ if (config3.networkAccess !== void 0) {
18180
+ if (config3.networkAccess !== "on" && config3.networkAccess !== "off") {
18181
+ if (typeof config3.networkAccess !== "object" || config3.networkAccess === null || !Array.isArray(config3.networkAccess.allowedHostnames)) {
18182
+ throw new NormalizationError(
18183
+ "networkAccess must be 'on', 'off', or { allowedHostnames: string[] }",
18184
+ "transform-data",
18185
+ "networkAccess"
18186
+ );
18187
+ }
18188
+ if (config3.networkAccess.allowedHostnames.length === 0) {
18189
+ throw new NormalizationError(
18190
+ "allowedHostnames must contain at least one entry",
18191
+ "transform-data",
18192
+ "networkAccess"
18193
+ );
18194
+ }
18195
+ for (const h2 of config3.networkAccess.allowedHostnames) {
18196
+ if (typeof h2 !== "string") {
18197
+ throw new NormalizationError(
18198
+ "allowedHostnames entries must be strings",
18199
+ "transform-data",
18200
+ "networkAccess"
18201
+ );
18202
+ }
18203
+ }
18204
+ }
18205
+ }
18206
+ const errorHandling = validateAndNormalizeErrorHandling(
18207
+ config3.errorHandling,
18208
+ "errorHandling",
18209
+ "transform-data"
18210
+ );
18211
+ return {
18212
+ script: config3.script,
18213
+ outputVariable,
18214
+ streamOutput: config3.streamOutput,
18215
+ sandboxProvider: config3.sandboxProvider,
18216
+ language: config3.language,
18217
+ inputMode: config3.inputMode,
18218
+ packageJson: config3.packageJson,
18219
+ persistSandbox: config3.persistSandbox,
18220
+ reuseSandboxId: config3.reuseSandboxId,
18221
+ networkAccess: config3.networkAccess,
18222
+ errorHandling,
18223
+ defaultValue: config3.defaultValue,
18224
+ ...config3.tools ? { tools: config3.tools } : {}
18225
+ };
18226
+ }
18227
+ function normalizeTemplateConfig(config3) {
18228
+ validateConfig(config3, "template");
18229
+ validateString(config3.template, "template", "template", true);
18230
+ validateString(config3.outputVariable, "outputVariable", "template", true);
18231
+ validateEnum(
18232
+ config3.outputFormat,
18233
+ ["html", "email-html", "markdown", "pdf", "text"],
18234
+ "outputFormat",
18235
+ "template"
18236
+ );
18237
+ if (config3.inputs !== void 0) {
18238
+ if (typeof config3.inputs !== "object" || config3.inputs === null || Array.isArray(config3.inputs)) {
18239
+ throw new NormalizationError("inputs must be an object", "template", "inputs");
18240
+ }
18241
+ for (const [key, value] of Object.entries(config3.inputs)) {
18242
+ if (typeof value !== "string") {
18243
+ throw new NormalizationError(
18244
+ `inputs.${key} must be a string expression`,
18245
+ "template",
18246
+ `inputs.${key}`
18247
+ );
18248
+ }
18249
+ }
18250
+ }
18251
+ if (config3.partials !== void 0) {
18252
+ if (typeof config3.partials !== "object" || config3.partials === null || Array.isArray(config3.partials)) {
18253
+ throw new NormalizationError("partials must be an object", "template", "partials");
18254
+ }
18255
+ for (const [key, value] of Object.entries(config3.partials)) {
18256
+ if (!/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(key)) {
18257
+ throw new NormalizationError(
18258
+ `partials.${key} key must be a simple identifier`,
18259
+ "template",
18260
+ `partials.${key}`
18261
+ );
18262
+ }
18263
+ if (typeof value !== "string") {
18264
+ throw new NormalizationError(
18265
+ `partials.${key} must be a string template`,
18266
+ "template",
18267
+ `partials.${key}`
18268
+ );
18269
+ }
18270
+ }
18271
+ }
18272
+ if (config3.pdfOptions !== void 0 && config3.outputFormat !== "pdf") {
18273
+ throw new NormalizationError(
18274
+ 'pdfOptions is only allowed when outputFormat is "pdf"',
18275
+ "template",
18276
+ "pdfOptions"
18277
+ );
18278
+ }
18279
+ if (config3.asArtifact !== void 0 && typeof config3.asArtifact !== "boolean") {
18280
+ throw new NormalizationError("asArtifact must be a boolean", "template", "asArtifact");
18281
+ }
18282
+ if (config3.sampleData !== void 0) {
18283
+ validateArray(config3.sampleData, "sampleData", "template");
18284
+ for (const [i, scenario] of config3.sampleData.entries()) {
18285
+ if (typeof scenario !== "object" || scenario === null || Array.isArray(scenario)) {
18286
+ throw new NormalizationError(`sampleData[${i}] must be an object`, "template", `sampleData[${i}]`);
18287
+ }
18288
+ validateString(scenario.name, `sampleData[${i}].name`, "template", true);
18289
+ if (typeof scenario.data !== "object" || scenario.data === null || Array.isArray(scenario.data)) {
18290
+ throw new NormalizationError(`sampleData[${i}].data must be an object`, "template", `sampleData[${i}].data`);
18291
+ }
18292
+ }
18293
+ }
18294
+ const errorHandling = validateAndNormalizeErrorHandling(
18295
+ config3.errorHandling,
18296
+ "errorHandling",
18297
+ "template"
18298
+ );
18299
+ return {
18300
+ template: config3.template,
18301
+ inputs: config3.inputs,
18302
+ outputFormat: config3.outputFormat,
18303
+ outputVariable: config3.outputVariable,
18304
+ partials: config3.partials,
18305
+ pdfOptions: config3.pdfOptions,
18306
+ asArtifact: config3.asArtifact,
18307
+ streamOutput: config3.streamOutput,
18308
+ errorHandling,
18309
+ defaultValue: config3.defaultValue,
18310
+ sampleData: config3.sampleData
18311
+ };
18312
+ }
18313
+ function normalizeConditionalConfig(config3) {
18314
+ validateConfig(config3, "conditional");
18315
+ validateString(config3.condition, "condition", "conditional", true);
18316
+ const trueSteps = config3.trueSteps ?? config3.true_steps;
18317
+ const falseSteps = config3.falseSteps ?? config3.false_steps;
18318
+ if (trueSteps) {
18319
+ validateArray(trueSteps, "trueSteps", "conditional");
18320
+ }
18321
+ if (falseSteps) {
18322
+ validateArray(falseSteps, "falseSteps", "conditional");
18323
+ }
18324
+ const normalizeNestedSteps = (steps, parentStepId = "conditional") => {
18325
+ return steps.map((step, index) => {
18326
+ const stepWithDefaults = {
18327
+ ...step,
18328
+ id: step.id || `${parentStepId}-nested-${index}-${Date.now()}`,
18329
+ order: step.order ?? index
18330
+ };
18331
+ if (step.type === "prompt") {
18332
+ return stepWithDefaults;
18333
+ }
18334
+ return normalizeContextStep(stepWithDefaults);
18335
+ });
18336
+ };
18337
+ return {
18338
+ condition: config3.condition,
18339
+ trueSteps: trueSteps ? normalizeNestedSteps(trueSteps, "conditional-true") : [],
18340
+ falseSteps: falseSteps ? normalizeNestedSteps(falseSteps, "conditional-false") : void 0
18341
+ };
18342
+ }
18343
+ function normalizeSetVariableConfig(config3) {
18344
+ validateConfig(config3, "set-variable");
18345
+ const variableName = config3.variableName ?? config3.variable_name;
18346
+ validateString(variableName, "variableName", "set-variable", true);
18347
+ if (config3.value === void 0) {
18348
+ throw new NormalizationError(
18349
+ `Missing required field 'value' for set-variable step`,
18350
+ "set-variable",
18351
+ "value",
18352
+ "any value",
18353
+ void 0
18354
+ );
18355
+ }
18356
+ if (config3.valueTemplate !== void 0 && config3.valueTemplate !== null) {
18357
+ validateString(config3.valueTemplate, "valueTemplate", "set-variable");
18358
+ }
18359
+ return {
18360
+ variableName,
18361
+ value: config3.value,
18362
+ valueTemplate: config3.valueTemplate
18363
+ };
18364
+ }
18365
+ function normalizeUpsertRecordConfig(config3) {
18366
+ validateConfig(config3, "upsert-record");
18367
+ validateString(config3.recordType, "recordType", "upsert-record", true);
18368
+ validateString(config3.sourceVariable, "sourceVariable", "upsert-record", true);
18369
+ validateString(config3.outputVariable, "outputVariable", "upsert-record", true);
18370
+ if (config3.recordName !== void 0 && config3.recordName !== null) {
18371
+ validateString(config3.recordName, "recordName", "upsert-record");
18372
+ }
18373
+ if (config3.mergeStrategy) {
18374
+ validateEnum(config3.mergeStrategy, ["merge", "replace"], "mergeStrategy", "upsert-record");
18375
+ }
18376
+ const errorHandling = validateAndNormalizeErrorHandling(
18377
+ config3.errorHandling,
18378
+ "errorHandling",
18379
+ "upsert-record"
18380
+ );
18381
+ if (config3.inputMode) {
18382
+ validateEnum(config3.inputMode, ["single", "batch"], "inputMode", "upsert-record");
18383
+ }
18384
+ return {
18385
+ recordType: config3.recordType,
18386
+ recordName: config3.recordName,
18387
+ sourceVariable: config3.sourceVariable,
18388
+ outputVariable: config3.outputVariable,
18389
+ mergeStrategy: config3.mergeStrategy,
18390
+ errorHandling,
18391
+ defaultValue: config3.defaultValue,
18392
+ // Batch mode
18393
+ inputMode: config3.inputMode,
18394
+ inputVariable: config3.inputVariable,
18395
+ itemAlias: config3.itemAlias,
18396
+ metadataMapping: config3.metadataMapping,
18397
+ batchSize: config3.batchSize
18398
+ };
18399
+ }
18400
+ function normalizeSendEmailConfig(config3, options = {}) {
18401
+ validateConfig(config3, "send-email");
18402
+ validateString(config3.from, "from", "send-email");
18403
+ validateString(config3.to, "to", "send-email", true);
18404
+ validateString(config3.subject, "subject", "send-email", true);
18405
+ if (isCustomSendFromAddressOnManagedDomain(config3.from, options.managedSendFromDomain)) {
18406
+ throw new NormalizationError(
18407
+ "Field 'from' cannot use the platform-managed email domain for a custom sender",
18408
+ "send-email",
18409
+ "from",
18410
+ "custom email address on a non-managed domain",
18411
+ config3.from
18412
+ );
18413
+ }
18414
+ validateString(config3.outputVariable, "outputVariable", "send-email", true);
18415
+ if (config3.replyTo) validateString(config3.replyTo, "replyTo", "send-email");
18416
+ if (config3.cc) validateString(config3.cc, "cc", "send-email");
18417
+ if (config3.bcc) validateString(config3.bcc, "bcc", "send-email");
18418
+ if (config3.html) validateString(config3.html, "html", "send-email");
18419
+ if (config3.text) validateString(config3.text, "text", "send-email");
18420
+ if (config3.attachments) {
18421
+ validateArray(config3.attachments, "attachments", "send-email");
18422
+ }
18423
+ const errorHandling = validateAndNormalizeErrorHandling(
18424
+ config3.errorHandling,
18425
+ "errorHandling",
18426
+ "send-email"
18427
+ );
18428
+ return {
18429
+ from: config3.from,
18430
+ to: config3.to,
18431
+ subject: config3.subject,
18432
+ replyTo: config3.replyTo,
18433
+ cc: config3.cc,
18434
+ bcc: config3.bcc,
18435
+ html: config3.html,
18436
+ text: config3.text,
18437
+ attachments: config3.attachments,
18438
+ outputVariable: config3.outputVariable,
18439
+ errorHandling,
18440
+ defaultValue: config3.defaultValue
18441
+ };
18442
+ }
18443
+ function normalizeSendTextConfig(config3) {
18444
+ validateConfig(config3, "send-text");
18445
+ validateString(config3.from, "from", "send-text", true);
18446
+ validateString(config3.to, "to", "send-text", true);
18447
+ validateString(config3.message, "message", "send-text", true);
18448
+ validateString(config3.outputVariable, "outputVariable", "send-text", true);
18449
+ const errorHandling = validateAndNormalizeErrorHandling(
18450
+ config3.errorHandling,
18451
+ "errorHandling",
18452
+ "send-text"
18453
+ );
18454
+ return {
18455
+ from: config3.from,
18456
+ to: config3.to,
18457
+ message: config3.message,
18458
+ outputVariable: config3.outputVariable,
18459
+ errorHandling,
18460
+ defaultValue: config3.defaultValue
18461
+ };
18462
+ }
18463
+ function normalizeSendEventConfig(config3) {
18464
+ validateConfig(config3, "send-event");
18465
+ validateEnum(
18466
+ config3.provider,
18467
+ ["posthog", "google-analytics", "amplitude", "segment"],
18468
+ "provider",
18469
+ "send-event",
18470
+ true
18471
+ );
18472
+ validateString(config3.eventName, "eventName", "send-event", true);
18473
+ validateString(config3.outputVariable, "outputVariable", "send-event", true);
18474
+ if (config3.properties !== void 0 && config3.properties !== null) {
18475
+ validateObject(config3.properties, "properties", "send-event");
18476
+ }
18477
+ const errorHandling = validateAndNormalizeErrorHandling(
18478
+ config3.errorHandling,
18479
+ "errorHandling",
18480
+ "send-event"
18481
+ );
18482
+ return {
18483
+ provider: config3.provider,
18484
+ eventName: config3.eventName,
18485
+ properties: config3.properties,
18486
+ // Preserve user property keys as-is
18487
+ outputVariable: config3.outputVariable,
18488
+ errorHandling,
18489
+ defaultValue: config3.defaultValue
18490
+ };
18491
+ }
18492
+ function normalizeSendStreamConfig(config3) {
18493
+ validateConfig(config3, "send-stream");
18494
+ validateString(config3.message, "message", "send-stream", true);
18495
+ return {
18496
+ message: config3.message
18497
+ };
18498
+ }
18499
+ function normalizeUpdateRecordConfig(config3) {
18500
+ validateConfig(config3, "update-record");
18501
+ const filter = config3.recordFilter;
18502
+ const hasFilter = filter && typeof filter === "object" && typeof filter.type === "string" && filter.type.length > 0;
18503
+ if (!config3.recordId && !(config3.recordType && config3.recordName) && !hasFilter) {
18504
+ throw new NormalizationError(
18505
+ `update-record step requires either 'recordId', both 'recordType' and 'recordName', or 'recordFilter'`,
18506
+ "update-record",
18507
+ "recordId/recordType/recordName/recordFilter",
18508
+ "at least one identification method",
18509
+ void 0
18510
+ );
18511
+ }
18512
+ validateObject(config3.updates, "updates", "update-record", true);
18513
+ validateString(config3.outputVariable, "outputVariable", "update-record", true);
18514
+ validateEnum(
18515
+ config3.mergeStrategy,
18516
+ ["merge", "replace", "deep-merge"],
18517
+ "mergeStrategy",
18518
+ "update-record",
18519
+ true
18520
+ );
18521
+ if (config3.updatesTemplate !== void 0 && config3.updatesTemplate !== null) {
18522
+ validateString(config3.updatesTemplate, "updatesTemplate", "update-record");
18523
+ }
18524
+ if (config3.includeFullRecord !== void 0 && config3.includeFullRecord !== null) {
18525
+ validateBoolean(config3.includeFullRecord, "includeFullRecord", "update-record");
18526
+ }
18527
+ const errorHandling = validateAndNormalizeErrorHandling(
18528
+ config3.errorHandling,
18529
+ "errorHandling",
18530
+ "update-record"
18531
+ );
18532
+ return {
18533
+ recordId: config3.recordId,
18534
+ recordType: config3.recordType,
18535
+ recordName: config3.recordName,
18536
+ recordFilter: config3.recordFilter,
18537
+ updates: config3.updates,
18538
+ // Preserve user metadata keys as-is
18539
+ updatesTemplate: config3.updatesTemplate,
18540
+ mergeStrategy: config3.mergeStrategy,
18541
+ outputVariable: config3.outputVariable,
18542
+ includeFullRecord: config3.includeFullRecord,
18543
+ errorHandling,
18544
+ defaultValue: config3.defaultValue
18545
+ };
18546
+ }
18547
+ function normalizeSearchConfig(config3) {
18548
+ validateConfig(config3, "search");
18549
+ validateString(config3.provider, "provider", "search", true);
18550
+ validateString(config3.query, "query", "search", true);
18551
+ validateString(config3.outputVariable, "outputVariable", "search", true);
18552
+ if (config3.maxResults !== void 0 && config3.maxResults !== null) {
18553
+ validateNumber(config3.maxResults, "maxResults", "search");
18554
+ }
18555
+ if (config3.maxTokens !== void 0 && config3.maxTokens !== null) {
18556
+ validateNumber(config3.maxTokens, "maxTokens", "search");
18557
+ }
18558
+ if (config3.temperature !== void 0 && config3.temperature !== null) {
18559
+ validateNumber(config3.temperature, "temperature", "search");
18560
+ }
18561
+ if (config3.returnCitations !== void 0 && config3.returnCitations !== null) {
18562
+ validateBoolean(config3.returnCitations, "returnCitations", "search");
18563
+ }
18564
+ if (config3.allowedDomains) validateArray(config3.allowedDomains, "allowedDomains", "search");
18565
+ if (config3.blockedDomains) validateArray(config3.blockedDomains, "blockedDomains", "search");
18566
+ if (config3.sources) validateArray(config3.sources, "sources", "search");
18567
+ const errorHandling = validateAndNormalizeErrorHandling(
18568
+ config3.errorHandling,
18569
+ "errorHandling",
18570
+ "search"
18571
+ );
18572
+ return {
18573
+ provider: config3.provider,
18574
+ query: config3.query,
18575
+ maxResults: config3.maxResults,
18576
+ returnCitations: config3.returnCitations,
18577
+ dateRange: config3.dateRange,
18578
+ allowedDomains: config3.allowedDomains,
18579
+ blockedDomains: config3.blockedDomains,
18580
+ userLocation: config3.userLocation,
18581
+ sources: config3.sources,
18582
+ temperature: config3.temperature,
18583
+ maxTokens: config3.maxTokens,
18584
+ // Exa-specific options
18585
+ exaSearchType: config3.exaSearchType,
18586
+ exaContents: config3.exaContents,
18587
+ exaCategory: config3.exaCategory,
18588
+ outputVariable: config3.outputVariable,
18589
+ errorHandling,
18590
+ defaultValue: config3.defaultValue
18591
+ };
18592
+ }
18593
+ function normalizeGenerateEmbeddingConfig(config3) {
18594
+ validateConfig(config3, "generate-embedding");
18595
+ const isBatchMode = config3.inputMode === "batch";
18596
+ validateString(config3.outputVariable, "outputVariable", "generate-embedding", true);
18597
+ if (isBatchMode) {
18598
+ validateString(config3.inputVariable, "inputVariable", "generate-embedding", true);
18599
+ if (config3.textTemplate)
18600
+ validateString(config3.textTemplate, "textTemplate", "generate-embedding");
18601
+ if (config3.itemAlias) validateString(config3.itemAlias, "itemAlias", "generate-embedding");
18602
+ if (config3.batchSize !== void 0 && config3.batchSize !== null) {
18603
+ validateNumber(config3.batchSize, "batchSize", "generate-embedding");
18604
+ }
18605
+ } else {
18606
+ validateEnum(
18607
+ config3.inputSource,
18608
+ ["text", "variable", "record"],
18609
+ "inputSource",
18610
+ "generate-embedding",
18611
+ true
18612
+ );
18613
+ if (config3.inputSource === "text") {
18614
+ if (config3.text !== void 0 && config3.text !== null) {
18615
+ validateString(config3.text, "text", "generate-embedding");
18616
+ }
18617
+ } else if (config3.inputSource === "variable") {
18618
+ validateString(config3.variableName, "variableName", "generate-embedding", true);
18619
+ } else if (config3.inputSource === "record") {
18620
+ if (!config3.recordId && !(config3.recordType && config3.recordName)) {
18621
+ throw new NormalizationError(
18622
+ `generate-embedding step with inputSource='record' requires either 'recordId' or both 'recordType' and 'recordName'`,
18623
+ "generate-embedding",
18624
+ "recordId/recordType/recordName",
18625
+ "at least one identification method",
18626
+ void 0
18627
+ );
18628
+ }
18629
+ }
18630
+ }
18631
+ if (config3.embeddingModel)
18632
+ validateString(config3.embeddingModel, "embeddingModel", "generate-embedding");
18633
+ if (config3.textField) validateString(config3.textField, "textField", "generate-embedding");
18634
+ if (config3.maxLength !== void 0 && config3.maxLength !== null) {
18635
+ validateNumber(config3.maxLength, "maxLength", "generate-embedding");
18636
+ }
18637
+ if (config3.storeInRecord !== void 0 && config3.storeInRecord !== null) {
18638
+ validateBoolean(config3.storeInRecord, "storeInRecord", "generate-embedding");
18639
+ }
18640
+ return {
18641
+ inputSource: config3.inputSource,
18642
+ text: config3.text,
18643
+ variableName: config3.variableName,
18644
+ recordId: config3.recordId,
18645
+ recordType: config3.recordType,
18646
+ recordName: config3.recordName,
18647
+ textField: config3.textField,
18648
+ storeInRecord: config3.storeInRecord,
18649
+ embeddingModel: config3.embeddingModel,
18650
+ maxLength: config3.maxLength,
18651
+ outputVariable: config3.outputVariable,
18652
+ streamOutput: config3.streamOutput,
18653
+ // Batch mode fields
18654
+ inputMode: config3.inputMode,
18655
+ inputVariable: config3.inputVariable,
18656
+ textTemplate: config3.textTemplate,
18657
+ itemAlias: config3.itemAlias,
18658
+ batchSize: config3.batchSize
18659
+ };
18660
+ }
18661
+ function normalizeVectorSearchConfig(config3) {
18662
+ validateConfig(config3, "vector-search");
18663
+ validateString(config3.query, "query", "vector-search", true);
18664
+ validateString(config3.outputVariable, "outputVariable", "vector-search", true);
18665
+ if (config3.embeddingModel)
18666
+ validateString(config3.embeddingModel, "embeddingModel", "vector-search");
18667
+ if (config3.limit !== void 0 && config3.limit !== null) {
18668
+ validateNumber(config3.limit, "limit", "vector-search");
18669
+ }
18670
+ if (config3.threshold !== void 0 && config3.threshold !== null) {
18671
+ validateNumber(config3.threshold, "threshold", "vector-search");
18672
+ }
18673
+ if (config3.recordType) validateString(config3.recordType, "recordType", "vector-search");
18674
+ if (config3.metadataFilters !== void 0 && config3.metadataFilters !== null) {
18675
+ validateObject(config3.metadataFilters, "metadataFilters", "vector-search");
18676
+ }
18677
+ if (config3.includeEmbedding !== void 0 && config3.includeEmbedding !== null) {
18678
+ validateBoolean(config3.includeEmbedding, "includeEmbedding", "vector-search");
18679
+ }
18680
+ const providerInput = config3.provider || config3.vectorStore || "record";
18681
+ const vectorStore = providerInput === "record" ? "pgvector" : providerInput;
18682
+ const vectorizeConfig = config3.vectorizeConfigId || config3.vectorizeNamespace ? {
18683
+ configId: config3.vectorizeConfigId,
18684
+ namespace: config3.vectorizeNamespace
18685
+ } : void 0;
18686
+ const weaviateConfig = config3.weaviateClassName || config3.weaviateConfigId ? {
18687
+ configId: config3.weaviateConfigId,
18688
+ className: config3.weaviateClassName || ""
18689
+ } : void 0;
18690
+ return {
18691
+ query: config3.query,
18692
+ embeddingModel: config3.embeddingModel,
18693
+ limit: config3.limit,
18694
+ threshold: config3.threshold,
18695
+ recordType: config3.recordType,
18696
+ metadataFilters: config3.metadataFilters,
18697
+ // Preserve user filter keys
18698
+ outputVariable: config3.outputVariable,
18699
+ includeEmbedding: config3.includeEmbedding,
18700
+ streamOutput: config3.streamOutput,
18701
+ // Provider selection and provider-specific config (typed fields)
18702
+ vectorStore,
18703
+ vectorizeConfig,
18704
+ weaviateConfig,
18705
+ // Also pass through flat fields for executor compatibility
18706
+ // These are used by the executor which checks both patterns
18707
+ provider: providerInput,
18708
+ // Keep original for executor
18709
+ vectorizeConfigId: config3.vectorizeConfigId,
18710
+ vectorizeNamespace: config3.vectorizeNamespace,
18711
+ weaviateClassName: config3.weaviateClassName,
18712
+ hybridSearch: config3.hybridSearch,
18713
+ hybridAlpha: config3.hybridAlpha,
18714
+ weaviateProperties: config3.weaviateProperties
18715
+ };
18716
+ }
18717
+ function normalizePaginateApiConfig(config3) {
18718
+ validateConfig(config3, "paginate-api");
18719
+ const url2 = config3.http?.url || config3.url;
18720
+ validateString(url2, "url", "paginate-api", true);
18721
+ const method = config3.http?.method || config3.method || "GET";
18722
+ validateEnum(method, ["GET", "POST"], "method", "paginate-api");
18723
+ const headers = config3.http?.headers ?? config3.headers;
18724
+ if (headers !== void 0 && headers !== null) {
18725
+ validateObject(headers, "headers", "paginate-api");
18726
+ }
18727
+ const body = config3.http?.body ?? config3.body;
18728
+ if (body !== void 0 && body !== null) {
18729
+ validateString(body, "body", "paginate-api");
18730
+ }
18731
+ const paginationType = config3.paginationType || "offset";
18732
+ validateEnum(
18733
+ paginationType,
18734
+ ["cursor", "offset", "page", "link_header"],
18735
+ "paginationType",
18736
+ "paginate-api",
18737
+ true
18738
+ );
18739
+ const pageSizeRaw = config3.pageSize;
18740
+ const pageSize = pageSizeRaw !== void 0 && pageSizeRaw !== null ? Number(pageSizeRaw) : 100;
18741
+ if (pageSizeRaw !== void 0 && pageSizeRaw !== null) {
18742
+ validateNumber(pageSizeRaw, "pageSize", "paginate-api");
18743
+ }
18744
+ const paginationConfigInput = config3.paginationConfig || {};
18745
+ if (paginationConfigInput !== void 0 && paginationConfigInput !== null) {
18746
+ validateObject(paginationConfigInput, "paginationConfig", "paginate-api");
18747
+ }
18748
+ const paginationConfig = { ...paginationConfigInput };
18749
+ if (paginationType === "cursor") {
18750
+ paginationConfig.cursorParam = paginationConfig.cursorParam || config3.cursorParam || "cursor";
18751
+ paginationConfig.cursorPath = paginationConfig.cursorPath || config3.cursorPath;
18752
+ } else if (paginationType === "offset") {
18753
+ paginationConfig.offsetParam = paginationConfig.offsetParam || config3.offsetParam || "offset";
18754
+ paginationConfig.limitParam = paginationConfig.limitParam || config3.limitParam || "limit";
18755
+ paginationConfig.limit = paginationConfig.limit ?? pageSize;
18756
+ paginationConfig.totalPath = paginationConfig.totalPath || config3.totalPath;
18757
+ } else if (paginationType === "page") {
18758
+ paginationConfig.pageParam = paginationConfig.pageParam || config3.pageParam || "page";
18759
+ paginationConfig.perPageParam = paginationConfig.perPageParam || config3.perPageParam || "per_page";
18760
+ paginationConfig.perPage = paginationConfig.perPage ?? pageSize;
18761
+ paginationConfig.totalPagesPath = paginationConfig.totalPagesPath || config3.totalPagesPath;
18762
+ }
18763
+ const entitiesPath = config3.entitiesPath || config3.entityPath || "$[*]";
18764
+ validateString(entitiesPath, "entitiesPath", "paginate-api", true);
18765
+ const outputVariable = config3.outputVariable || "entities";
18766
+ validateString(outputVariable, "outputVariable", "paginate-api", true);
18767
+ if (config3.maxPages !== void 0 && config3.maxPages !== null) {
18768
+ validateNumber(config3.maxPages, "maxPages", "paginate-api");
18769
+ }
18770
+ if (config3.maxEntities !== void 0 && config3.maxEntities !== null) {
18771
+ validateNumber(config3.maxEntities, "maxEntities", "paginate-api");
18772
+ }
18773
+ if (config3.requestDelayMs !== void 0 && config3.requestDelayMs !== null) {
18774
+ validateNumber(config3.requestDelayMs, "requestDelayMs", "paginate-api");
18775
+ }
18776
+ if (config3.retryOnRateLimit !== void 0 && config3.retryOnRateLimit !== null) {
18777
+ validateBoolean(config3.retryOnRateLimit, "retryOnRateLimit", "paginate-api");
18778
+ }
18779
+ if (config3.maxRetries !== void 0 && config3.maxRetries !== null) {
18780
+ validateNumber(config3.maxRetries, "maxRetries", "paginate-api");
18781
+ }
18782
+ if (config3.includeMetadata !== void 0 && config3.includeMetadata !== null) {
18783
+ validateBoolean(config3.includeMetadata, "includeMetadata", "paginate-api");
18784
+ }
18785
+ if (config3.streamOutput !== void 0 && config3.streamOutput !== null) {
18786
+ validateBoolean(config3.streamOutput, "streamOutput", "paginate-api");
18787
+ }
18788
+ const errorHandling = validateAndNormalizeErrorHandling(
18789
+ config3.errorHandling,
18790
+ "errorHandling",
18791
+ "paginate-api"
18792
+ );
18793
+ return {
18794
+ url: url2,
18795
+ method,
18796
+ headers,
18797
+ body,
18798
+ authType: config3.authType || "none",
18799
+ authConfig: config3.authConfig,
18800
+ paginationType,
18801
+ paginationConfig,
18802
+ pageSize,
18803
+ maxPages: config3.maxPages,
18804
+ offsetParam: config3.offsetParam,
18805
+ limitParam: config3.limitParam,
18806
+ cursorParam: config3.cursorParam,
18807
+ cursorPath: config3.cursorPath,
18808
+ pageParam: config3.pageParam,
18809
+ startPage: config3.startPage,
18810
+ entitiesPath,
18811
+ entityPath: config3.entityPath,
18812
+ entityIdPath: config3.entityIdPath,
18813
+ maxEntities: config3.maxEntities,
18814
+ requestDelayMs: config3.requestDelayMs,
18815
+ retryOnRateLimit: config3.retryOnRateLimit,
18816
+ maxRetries: config3.maxRetries,
18817
+ outputVariable,
18818
+ includeMetadata: config3.includeMetadata,
18819
+ streamOutput: config3.streamOutput,
18820
+ errorHandling,
18821
+ defaultValue: config3.defaultValue
18822
+ };
18823
+ }
18824
+ function normalizeStoreVectorConfig(config3) {
18825
+ validateConfig(config3, "store-vector");
18826
+ const destination = config3.destination;
18827
+ validateEnum(
18828
+ destination,
18829
+ ["pgvector", "weaviate", "vectorize", "pinecone"],
18830
+ "destination",
18831
+ "store-vector",
18832
+ true
18833
+ );
18834
+ if (config3.vectorsSource) {
18835
+ validateString(config3.vectorsSource, "vectorsSource", "store-vector");
18836
+ }
18837
+ if (config3.inputMode) {
18838
+ validateEnum(config3.inputMode, ["single", "batch"], "inputMode", "store-vector");
18839
+ }
18840
+ if (config3.outputVariable) {
18841
+ validateString(config3.outputVariable, "outputVariable", "store-vector");
18842
+ }
18843
+ if (config3.streamOutput !== void 0 && config3.streamOutput !== null) {
18844
+ validateBoolean(config3.streamOutput, "streamOutput", "store-vector");
18845
+ }
18846
+ const errorHandling = validateAndNormalizeErrorHandling(
18847
+ config3.errorHandling,
18848
+ "errorHandling",
18849
+ "store-vector"
18850
+ );
18851
+ const idTemplate = config3.idTemplate;
18852
+ const metadata = config3.metadata;
18853
+ const weaviateConfigInput = config3.weaviateConfig;
18854
+ const vectorizeConfigInput = config3.vectorizeConfig;
18855
+ const pineconeConfig = config3.pineconeConfig;
18856
+ const weaviateConfigId = config3.weaviateConfigId;
18857
+ const weaviateClassName = config3.weaviateClassName;
18858
+ const vectorizeConfigId = config3.vectorizeConfigId;
18859
+ const vectorizeNamespace = config3.vectorizeNamespace;
18860
+ const normalizedWeaviateConfig = weaviateConfigInput || (weaviateConfigId || weaviateClassName || metadata || idTemplate ? {
18861
+ configId: weaviateConfigId,
18862
+ className: weaviateClassName,
18863
+ uuid: idTemplate,
18864
+ properties: metadata
18865
+ } : void 0);
18866
+ const normalizedVectorizeConfig = vectorizeConfigInput || (vectorizeConfigId || vectorizeNamespace || metadata || idTemplate ? {
18867
+ configId: vectorizeConfigId,
18868
+ id: idTemplate,
18869
+ namespace: vectorizeNamespace,
18870
+ metadata
18871
+ } : void 0);
18872
+ return {
18873
+ vectorsSource: config3.vectorsSource,
18874
+ inputMode: config3.inputMode,
18875
+ inputVariable: config3.inputVariable,
18876
+ itemAlias: config3.itemAlias,
18877
+ batchSize: config3.batchSize,
18878
+ destination,
18879
+ weaviateConfig: normalizedWeaviateConfig,
18880
+ vectorizeConfig: normalizedVectorizeConfig,
18881
+ pineconeConfig,
18882
+ weaviateConfigId,
18883
+ weaviateClassName,
18884
+ vectorizeConfigId,
18885
+ vectorizeNamespace,
18886
+ pineconeConfigId: config3.pineconeConfigId,
18887
+ pineconeNamespace: config3.pineconeNamespace,
18888
+ idTemplate,
18889
+ metadata,
18890
+ outputVariable: config3.outputVariable,
18891
+ streamOutput: config3.streamOutput,
18892
+ errorHandling,
18893
+ defaultValue: config3.defaultValue
18894
+ };
18895
+ }
18896
+ function normalizeToolCallConfig(config3) {
18897
+ validateConfig(config3, "tool-call");
18898
+ validateString(config3.toolId, "toolId", "tool-call", true);
18899
+ validateObject(config3.parameters, "parameters", "tool-call", true);
18900
+ validateString(config3.outputVariable, "outputVariable", "tool-call", true);
18901
+ if (config3.maxRetries !== void 0 && config3.maxRetries !== null) {
18902
+ validateNumber(config3.maxRetries, "maxRetries", "tool-call");
18903
+ }
18904
+ if (config3.timeout !== void 0 && config3.timeout !== null) {
18905
+ validateNumber(config3.timeout, "timeout", "tool-call");
18906
+ }
18907
+ if (config3.onError) {
18908
+ validateEnum(config3.onError, ["fail", "continue", "retry"], "onError", "tool-call");
18909
+ }
18910
+ return {
18911
+ toolId: config3.toolId,
18912
+ parameters: config3.parameters,
18913
+ // Preserve user parameter keys as-is
18914
+ outputVariable: config3.outputVariable,
18915
+ maxRetries: config3.maxRetries,
18916
+ timeout: config3.timeout,
18917
+ onError: config3.onError
18918
+ };
18919
+ }
18920
+ function normalizeSuccessCriteria(criteria) {
18921
+ if (!criteria) return void 0;
18922
+ validateObject(criteria, "poll.success", "wait-until", true);
18923
+ if (criteria.type) {
18924
+ validateEnum(
18925
+ criteria.type,
18926
+ ["status", "json_path", "body_contains", "expression"],
18927
+ "poll.success.type",
18928
+ "wait-until"
18929
+ );
18930
+ }
18931
+ if (criteria.status !== void 0 && criteria.status !== null) {
18932
+ validateNumber(criteria.status, "poll.success.status", "wait-until");
18933
+ }
18934
+ if (criteria.jsonPath) validateString(criteria.jsonPath, "poll.success.jsonPath", "wait-until");
18935
+ if (criteria.bodyContains)
18936
+ validateString(criteria.bodyContains, "poll.success.bodyContains", "wait-until");
18937
+ if (criteria.expression)
18938
+ validateString(criteria.expression, "poll.success.expression", "wait-until");
18939
+ return {
18940
+ type: criteria.type,
18941
+ status: criteria.status,
18942
+ jsonPath: criteria.jsonPath,
18943
+ expectedValue: criteria.expectedValue,
18944
+ operator: criteria.operator,
18945
+ bodyContains: criteria.bodyContains,
18946
+ expression: criteria.expression
18947
+ };
18948
+ }
18949
+ function normalizePollConfig(poll) {
18950
+ if (!poll) return void 0;
18951
+ validateObject(poll, "poll", "wait-until", true);
18952
+ if (poll.enabled === false) {
18953
+ const httpConfig = poll.http ? {
18954
+ url: poll.http.url || "",
18955
+ method: poll.http.method,
18956
+ headers: poll.http.headers,
18957
+ body: poll.http.body,
18958
+ timeout: poll.http.timeout
18959
+ } : { url: "" };
18960
+ return {
18961
+ enabled: false,
18962
+ http: httpConfig,
18963
+ auth: poll.auth ? normalizeAuthConfig(poll.auth) : void 0,
18964
+ intervalMs: poll.intervalMs,
18965
+ maxAttempts: poll.maxAttempts,
18966
+ responseType: poll.responseType,
18967
+ success: normalizeSuccessCriteria(poll.success)
18968
+ };
18969
+ }
18970
+ validateObject(poll.http, "poll.http", "wait-until", true);
18971
+ if (poll.intervalMs !== void 0 && poll.intervalMs !== null) {
18972
+ if (typeof poll.intervalMs !== "string") {
18973
+ validateNumber(poll.intervalMs, "poll.intervalMs", "wait-until");
18974
+ }
18975
+ }
18976
+ if (poll.maxAttempts !== void 0 && poll.maxAttempts !== null) {
18977
+ validateNumber(poll.maxAttempts, "poll.maxAttempts", "wait-until");
18978
+ }
18979
+ if (poll.responseType) {
18980
+ validateEnum(poll.responseType, ["json", "text"], "poll.responseType", "wait-until");
18981
+ }
18982
+ if (poll.enabled !== void 0 && poll.enabled !== null) {
18983
+ validateBoolean(poll.enabled, "poll.enabled", "wait-until");
18984
+ }
18985
+ return {
18986
+ enabled: poll.enabled,
18987
+ http: normalizeHttpConfig(poll.http),
18988
+ auth: normalizeAuthConfig(poll.auth),
18989
+ intervalMs: poll.intervalMs,
18990
+ maxAttempts: poll.maxAttempts,
18991
+ responseType: poll.responseType,
18992
+ success: normalizeSuccessCriteria(poll.success)
18993
+ };
18994
+ }
18995
+ function normalizeWaitUntilConfig(config3) {
18996
+ validateConfig(config3, "wait-until");
18997
+ validateString(config3.outputVariable, "outputVariable", "wait-until", true);
18998
+ if (config3.delayMs === void 0 && !config3.poll) {
18999
+ throw new NormalizationError(
19000
+ `wait-until step requires either 'delayMs' or 'poll' configuration`,
19001
+ "wait-until",
19002
+ "delayMs/poll",
19003
+ "at least one wait mechanism",
19004
+ void 0
19005
+ );
19006
+ }
19007
+ if (config3.delayMs !== void 0 && config3.delayMs !== null) {
19008
+ if (typeof config3.delayMs !== "string") {
19009
+ validateNumber(config3.delayMs, "delayMs", "wait-until");
19010
+ }
19011
+ }
19012
+ if (config3.continueOnTimeout !== void 0 && config3.continueOnTimeout !== null) {
19013
+ validateBoolean(config3.continueOnTimeout, "continueOnTimeout", "wait-until");
19014
+ }
19015
+ const errorHandling = validateAndNormalizeErrorHandling(
19016
+ config3.errorHandling,
19017
+ "errorHandling",
19018
+ "wait-until"
19019
+ );
19020
+ return {
19021
+ delayMs: config3.delayMs,
19022
+ poll: normalizePollConfig(config3.poll),
19023
+ continueOnTimeout: config3.continueOnTimeout,
19024
+ errorHandling,
19025
+ defaultValue: config3.defaultValue,
19026
+ outputVariable: config3.outputVariable
19027
+ };
19028
+ }
19029
+ function normalizeExecuteAgentConfig(config3) {
19030
+ validateConfig(config3, "execute-agent");
19031
+ const agentId = config3.agentId ?? config3.agent_id;
19032
+ validateString(agentId, "agentId", "execute-agent", true);
19033
+ const message = config3.message;
19034
+ validateString(message, "message", "execute-agent", true);
19035
+ const outputVariable = config3.outputVariable ?? config3.output_variable ?? "agent_response";
19036
+ validateString(outputVariable, "outputVariable", "execute-agent");
19037
+ const maxTurns = config3.maxTurns ?? config3.max_turns;
19038
+ if (maxTurns !== void 0 && maxTurns !== null) {
19039
+ validateNumber(maxTurns, "maxTurns", "execute-agent");
19040
+ }
19041
+ if (config3.timeout !== void 0 && config3.timeout !== null) {
19042
+ validateNumber(config3.timeout, "timeout", "execute-agent");
19043
+ }
19044
+ const errorHandling = validateAndNormalizeErrorHandling(
19045
+ config3.errorHandling ?? config3.error_handling,
19046
+ "errorHandling",
19047
+ "execute-agent"
19048
+ );
19049
+ return {
19050
+ agentId,
19051
+ message,
19052
+ outputVariable,
19053
+ variables: config3.variables,
19054
+ maxTurns,
19055
+ timeout: config3.timeout,
19056
+ errorHandling,
19057
+ defaultValue: config3.defaultValue ?? config3.default_value
19058
+ };
19059
+ }
19060
+ function normalizeStoreAssetConfig(config3) {
19061
+ validateConfig(config3, "store-asset");
19062
+ const url2 = config3.url;
19063
+ const content = config3.content;
19064
+ if ((url2 === void 0 || url2 === null) && (content === void 0 || content === null)) {
19065
+ throw new NormalizationError(
19066
+ 'store-asset requires either "url" or "content" (base64)',
19067
+ "store-asset",
19068
+ "url",
19069
+ "string",
19070
+ void 0
19071
+ );
19072
+ }
19073
+ if (url2 !== void 0 && url2 !== null && content !== void 0 && content !== null) {
19074
+ throw new NormalizationError(
19075
+ 'store-asset accepts exactly one of "url" or "content", not both',
19076
+ "store-asset",
19077
+ "url",
19078
+ "string",
19079
+ typeof url2
19080
+ );
19081
+ }
19082
+ if (url2 !== void 0 && url2 !== null) {
19083
+ validateString(url2, "url", "store-asset", true);
19084
+ }
19085
+ if (content !== void 0 && content !== null) {
19086
+ validateString(content, "content", "store-asset", true);
19087
+ }
19088
+ if (config3.filename !== void 0 && config3.filename !== null) {
19089
+ validateString(config3.filename, "filename", "store-asset");
19090
+ }
19091
+ if (config3.contentType !== void 0 && config3.contentType !== null) {
19092
+ validateString(config3.contentType, "contentType", "store-asset");
19093
+ }
19094
+ if (config3.visibility !== void 0 && config3.visibility !== null) {
19095
+ validateEnum(config3.visibility, ["public", "private"], "visibility", "store-asset");
19096
+ }
19097
+ validateString(config3.outputVariable, "outputVariable", "store-asset", true);
19098
+ const errorHandling = validateAndNormalizeErrorHandling(
19099
+ config3.errorHandling,
19100
+ "errorHandling",
19101
+ "store-asset"
19102
+ );
19103
+ return {
19104
+ url: url2,
19105
+ content,
19106
+ filename: config3.filename,
19107
+ contentType: config3.contentType,
19108
+ visibility: config3.visibility,
19109
+ outputVariable: config3.outputVariable,
19110
+ streamOutput: config3.streamOutput,
19111
+ errorHandling,
19112
+ defaultValue: config3.defaultValue
19113
+ };
19114
+ }
19115
+ function normalizeGeneratePdfConfig(config3) {
19116
+ validateConfig(config3, "generate-pdf");
19117
+ const html = config3.html;
19118
+ const markdown = config3.markdown;
19119
+ if ((html === void 0 || html === null) && (markdown === void 0 || markdown === null)) {
19120
+ throw new NormalizationError(
19121
+ 'generate-pdf requires either "html" or "markdown"',
19122
+ "generate-pdf",
19123
+ "html",
19124
+ "string",
19125
+ void 0
19126
+ );
19127
+ }
19128
+ if (html !== void 0 && html !== null && markdown !== void 0 && markdown !== null) {
19129
+ throw new NormalizationError(
19130
+ 'generate-pdf accepts exactly one of "html" or "markdown", not both',
19131
+ "generate-pdf",
19132
+ "html",
19133
+ "string",
19134
+ typeof html
19135
+ );
19136
+ }
19137
+ if (html !== void 0 && html !== null) {
19138
+ validateString(html, "html", "generate-pdf", true);
19139
+ }
19140
+ if (markdown !== void 0 && markdown !== null) {
19141
+ validateString(markdown, "markdown", "generate-pdf", true);
19142
+ }
19143
+ if (config3.filename !== void 0 && config3.filename !== null) {
19144
+ validateString(config3.filename, "filename", "generate-pdf");
19145
+ }
19146
+ if (config3.visibility !== void 0 && config3.visibility !== null) {
19147
+ validateEnum(config3.visibility, ["public", "private"], "visibility", "generate-pdf");
19148
+ }
19149
+ if (config3.pdfOptions !== void 0 && config3.pdfOptions !== null) {
19150
+ validateObject(config3.pdfOptions, "pdfOptions", "generate-pdf");
19151
+ const pdfOptions = config3.pdfOptions;
19152
+ if (pdfOptions.format !== void 0 && pdfOptions.format !== null) {
19153
+ validateEnum(pdfOptions.format, ["A4", "Letter"], "pdfOptions.format", "generate-pdf");
19154
+ }
19155
+ if (pdfOptions.landscape !== void 0 && pdfOptions.landscape !== null) {
19156
+ validateBoolean(pdfOptions.landscape, "pdfOptions.landscape", "generate-pdf");
19157
+ }
19158
+ }
19159
+ validateString(config3.outputVariable, "outputVariable", "generate-pdf", true);
19160
+ const errorHandling = validateAndNormalizeErrorHandling(
19161
+ config3.errorHandling,
19162
+ "errorHandling",
19163
+ "generate-pdf"
19164
+ );
19165
+ return {
19166
+ html,
19167
+ markdown,
19168
+ filename: config3.filename,
19169
+ visibility: config3.visibility,
19170
+ pdfOptions: config3.pdfOptions,
19171
+ outputVariable: config3.outputVariable,
19172
+ streamOutput: config3.streamOutput,
19173
+ errorHandling,
19174
+ defaultValue: config3.defaultValue
19175
+ };
19176
+ }
19177
+ function normalizeSaveMemoryConfig(config3) {
19178
+ validateConfig(config3, "save-memory");
19179
+ validateString(config3.profileTemplate, "profileTemplate", "save-memory", true);
19180
+ validateString(config3.contentVariable, "contentVariable", "save-memory", true);
19181
+ if (config3.sessionId !== void 0 && config3.sessionId !== null) {
19182
+ validateString(config3.sessionId, "sessionId", "save-memory");
19183
+ }
19184
+ if (config3.outputVariable !== void 0 && config3.outputVariable !== null) {
19185
+ validateString(config3.outputVariable, "outputVariable", "save-memory");
19186
+ }
19187
+ const errorHandling = validateAndNormalizeErrorHandling(
19188
+ config3.errorHandling ?? config3.error_handling,
19189
+ "errorHandling",
19190
+ "save-memory"
19191
+ );
19192
+ return {
19193
+ profileTemplate: config3.profileTemplate,
19194
+ contentVariable: config3.contentVariable,
19195
+ sessionId: config3.sessionId,
19196
+ outputVariable: config3.outputVariable,
19197
+ errorHandling,
19198
+ defaultValue: config3.defaultValue ?? config3.default_value
19199
+ };
19200
+ }
19201
+ function normalizeRecallMemoryConfig(config3) {
19202
+ validateConfig(config3, "recall-memory");
19203
+ validateString(config3.profileTemplate, "profileTemplate", "recall-memory", true);
19204
+ validateString(config3.queryTemplate, "queryTemplate", "recall-memory", true);
19205
+ validateString(config3.outputVariable, "outputVariable", "recall-memory", true);
19206
+ validateEnum(config3.thinkingLevel, ["low", "medium", "high"], "thinkingLevel", "recall-memory");
19207
+ validateEnum(
19208
+ config3.responseLength,
19209
+ ["short", "medium", "long"],
19210
+ "responseLength",
19211
+ "recall-memory"
19212
+ );
19213
+ const errorHandling = validateAndNormalizeErrorHandling(
19214
+ config3.errorHandling ?? config3.error_handling,
19215
+ "errorHandling",
19216
+ "recall-memory"
19217
+ );
19218
+ return {
19219
+ profileTemplate: config3.profileTemplate,
19220
+ queryTemplate: config3.queryTemplate,
19221
+ thinkingLevel: config3.thinkingLevel,
19222
+ responseLength: config3.responseLength,
19223
+ outputVariable: config3.outputVariable,
19224
+ errorHandling,
19225
+ defaultValue: config3.defaultValue ?? config3.default_value
19226
+ };
19227
+ }
19228
+ function normalizeMemorySummaryConfig(config3) {
19229
+ validateConfig(config3, "memory-summary");
19230
+ validateString(config3.profileTemplate, "profileTemplate", "memory-summary", true);
19231
+ validateString(config3.outputVariable, "outputVariable", "memory-summary", true);
19232
+ if (config3.sessionId !== void 0 && config3.sessionId !== null) {
19233
+ validateString(config3.sessionId, "sessionId", "memory-summary");
19234
+ }
19235
+ const errorHandling = validateAndNormalizeErrorHandling(
19236
+ config3.errorHandling ?? config3.error_handling,
19237
+ "errorHandling",
19238
+ "memory-summary"
19239
+ );
19240
+ return {
19241
+ profileTemplate: config3.profileTemplate,
19242
+ sessionId: config3.sessionId,
19243
+ outputVariable: config3.outputVariable,
19244
+ errorHandling,
19245
+ defaultValue: config3.defaultValue ?? config3.default_value
19246
+ };
19247
+ }
19248
+ var NAMED_AGENT_REF_PREFIX = "agent:";
19249
+ var NAMED_FLOW_REF_PREFIX = "flow:";
19250
+ function isNamedRef(value, prefix) {
19251
+ return value.startsWith(prefix) && value.length > prefix.length;
19252
+ }
19253
+ function parseNamedRef(value, prefix) {
19254
+ if (!isNamedRef(value, prefix)) return null;
19255
+ return { name: value.slice(prefix.length) };
19256
+ }
19257
+ function parseNamedAgentRef(value) {
19258
+ return parseNamedRef(value, NAMED_AGENT_REF_PREFIX);
19259
+ }
19260
+ function parseNamedFlowRef(value) {
19261
+ return parseNamedRef(value, NAMED_FLOW_REF_PREFIX);
19262
+ }
19263
+ function sanitizeCodeToolIdentifier(name) {
19264
+ let safe = name.replace(/[^a-zA-Z0-9_$]/g, "_");
19265
+ if (/^[0-9]/.test(safe)) safe = "_" + safe;
19266
+ return safe;
19267
+ }
17250
19268
  var flowStepValidationSchema = external_exports.object({
17251
19269
  // Optional stable client-supplied identifier. Preserved across saves so that
17252
19270
  // `flow_step_results.stepId` references stay valid and dashboard UI state
@@ -17306,6 +19324,1102 @@ var KNOWN_TOOL_KEYS = /* @__PURE__ */ new Set([
17306
19324
  ...Object.keys(CAMEL_CASE_TOOL_KEYS),
17307
19325
  ...Object.keys(SNAKE_CASE_TOOL_KEYS)
17308
19326
  ]);
19327
+ var LEGACY_TOOL_KEY_SUGGESTIONS = {
19328
+ builtinTools: "toolIds"
19329
+ };
19330
+ function isObjectRecord(value) {
19331
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19332
+ }
19333
+ var NETWORK_ISOLATED_SANDBOX_PROVIDERS = /* @__PURE__ */ new Set(["cloudflare-worker", "quickjs"]);
19334
+ var MAX_CONDITIONAL_NESTING_DEPTH = 10;
19335
+ var FETCH_CALL_PATTERN = /\bfetch\s*\(/;
19336
+ function validateSandboxNetworkAccess(config3, stepIndex, stepRef, buckets) {
19337
+ const rawProvider = typeof config3.sandboxProvider === "string" ? config3.sandboxProvider : "cloudflare-worker";
19338
+ if (!NETWORK_ISOLATED_SANDBOX_PROVIDERS.has(rawProvider)) {
19339
+ return;
19340
+ }
19341
+ const networkAccess = config3.networkAccess;
19342
+ if (networkAccess === "on") {
19343
+ return;
19344
+ }
19345
+ if (isObjectRecord(networkAccess) && Array.isArray(networkAccess.allowedHostnames) && networkAccess.allowedHostnames.length > 0) {
19346
+ return;
19347
+ }
19348
+ const code = typeof config3.script === "string" ? config3.script : "";
19349
+ if (!code || !FETCH_CALL_PATTERN.test(code)) {
19350
+ return;
19351
+ }
19352
+ addIssue(
19353
+ "warning",
19354
+ {
19355
+ code: "SANDBOX_NETWORK_ACCESS_DISABLED",
19356
+ message: "Step uses fetch() but network access is disabled for this sandbox; the request will be blocked at runtime. Set networkAccess to 'on' or an allowedHostnames allowlist, or use the daytona provider.",
19357
+ path: `flowSteps[${stepIndex}].config.networkAccess`,
19358
+ step: stepRef,
19359
+ details: {
19360
+ sandboxProvider: rawProvider,
19361
+ networkAccess: typeof networkAccess === "string" ? networkAccess : "off"
19362
+ }
19363
+ },
19364
+ buckets
19365
+ );
19366
+ }
19367
+ function validateCodeToolNameCollisions(toolNames, stepRef, code, preSeededCount = 0) {
19368
+ const seen = /* @__PURE__ */ new Map();
19369
+ for (const [i, tool] of toolNames.entries()) {
19370
+ const sanitized = sanitizeCodeToolIdentifier(tool.name);
19371
+ if (i < preSeededCount) {
19372
+ seen.set(sanitized, tool);
19373
+ continue;
19374
+ }
19375
+ const existing = seen.get(sanitized);
19376
+ if (existing) {
19377
+ return {
19378
+ code,
19379
+ message: `Tool names "${existing.name}" and "${tool.name}" both become "${sanitized}" in JavaScript. Rename or remove one before enabling code-mode execution.`,
19380
+ path: tool.path,
19381
+ step: stepRef,
19382
+ details: {
19383
+ firstPath: existing.path,
19384
+ secondPath: tool.path,
19385
+ sanitizedName: sanitized
19386
+ }
19387
+ };
19388
+ }
19389
+ seen.set(sanitized, tool);
19390
+ }
19391
+ return null;
19392
+ }
19393
+ function formatPath(path18) {
19394
+ return path18.reduce((acc, part) => {
19395
+ if (typeof part === "number") {
19396
+ return `${acc}[${part}]`;
19397
+ }
19398
+ const key = String(part);
19399
+ return acc ? `${acc}.${key}` : key;
19400
+ }, "");
19401
+ }
19402
+ function compareIssuePath(a, b) {
19403
+ if (!a && !b) return 0;
19404
+ if (!a) return 1;
19405
+ if (!b) return -1;
19406
+ return a.localeCompare(b);
19407
+ }
19408
+ function sortIssues(issues) {
19409
+ return [...issues].sort((a, b) => {
19410
+ const aStepIndex = a.step?.index ?? Number.MAX_SAFE_INTEGER;
19411
+ const bStepIndex = b.step?.index ?? Number.MAX_SAFE_INTEGER;
19412
+ if (aStepIndex !== bStepIndex) {
19413
+ return aStepIndex - bStepIndex;
19414
+ }
19415
+ const pathCompare = compareIssuePath(a.path, b.path);
19416
+ if (pathCompare !== 0) {
19417
+ return pathCompare;
19418
+ }
19419
+ const codeCompare = a.code.localeCompare(b.code);
19420
+ if (codeCompare !== 0) {
19421
+ return codeCompare;
19422
+ }
19423
+ return a.message.localeCompare(b.message);
19424
+ });
19425
+ }
19426
+ function addIssue(level, issue2, buckets) {
19427
+ switch (level) {
19428
+ case "error":
19429
+ buckets.errors.push(issue2);
19430
+ return;
19431
+ case "warning":
19432
+ buckets.warnings.push(issue2);
19433
+ return;
19434
+ default:
19435
+ buckets.recommendations.push(issue2);
19436
+ }
19437
+ }
19438
+ function buildIssueFromZod(issue2, resolvedPath, step) {
19439
+ return {
19440
+ code: "SCHEMA_VALIDATION_FAILED",
19441
+ message: issue2.message,
19442
+ path: resolvedPath,
19443
+ step,
19444
+ details: issue2
19445
+ };
19446
+ }
19447
+ function conditionalNestingDepth(config3) {
19448
+ let maxDepth = 0;
19449
+ const stack = [{ node: config3, depth: 1 }];
19450
+ while (stack.length > 0) {
19451
+ const { node, depth } = stack.pop();
19452
+ if (depth > maxDepth) maxDepth = depth;
19453
+ if (depth > MAX_CONDITIONAL_NESTING_DEPTH) break;
19454
+ if (!node || typeof node !== "object") continue;
19455
+ const cfg = node;
19456
+ for (const key of ["trueSteps", "falseSteps", "true_steps", "false_steps"]) {
19457
+ const branch = cfg[key];
19458
+ if (!Array.isArray(branch)) continue;
19459
+ for (const s of branch) {
19460
+ if (s && typeof s === "object" && s.type === "conditional") {
19461
+ const nestedCfg = s.config;
19462
+ if (nestedCfg && typeof nestedCfg === "object") {
19463
+ stack.push({ node: nestedCfg, depth: depth + 1 });
19464
+ }
19465
+ }
19466
+ }
19467
+ }
19468
+ }
19469
+ return maxDepth;
19470
+ }
19471
+ function registerReference(map2, id, reference) {
19472
+ const existing = map2.get(id) || [];
19473
+ existing.push(reference);
19474
+ map2.set(id, existing);
19475
+ }
19476
+ function collectRuntimeToolNameSelections(toolsConfig, stepIndex, selectedNames) {
19477
+ const runtimeTools = Array.isArray(toolsConfig.runtimeTools) ? toolsConfig.runtimeTools : [];
19478
+ const selections = [];
19479
+ for (const [runtimeToolIndex, runtimeTool] of runtimeTools.entries()) {
19480
+ if (!isObjectRecord(runtimeTool)) {
19481
+ continue;
19482
+ }
19483
+ const name = runtimeTool.name;
19484
+ if (typeof name !== "string") {
19485
+ continue;
19486
+ }
19487
+ if (selectedNames && !selectedNames.has(name)) {
19488
+ continue;
19489
+ }
19490
+ selections.push({
19491
+ name,
19492
+ path: `flowSteps[${stepIndex}].config.tools.runtimeTools[${runtimeToolIndex}].name`
19493
+ });
19494
+ }
19495
+ return selections;
19496
+ }
19497
+ function collectTransformDataCodeToolNameCheck(toolsConfig, stepIndex, stepRef, pendingChecks) {
19498
+ const toolIds = Array.isArray(toolsConfig.toolIds) ? toolsConfig.toolIds : [];
19499
+ const selectedToolIds = [];
19500
+ const selectedToolNames = [];
19501
+ for (const [toolIdIndex, toolId] of toolIds.entries()) {
19502
+ if (typeof toolId !== "string") {
19503
+ continue;
19504
+ }
19505
+ const path18 = `flowSteps[${stepIndex}].config.tools.toolIds[${toolIdIndex}]`;
19506
+ const named = parseNamedToolRef(toolId);
19507
+ if (named) {
19508
+ selectedToolNames.push({ name: named.name, path: path18 });
19509
+ continue;
19510
+ }
19511
+ const { customToolIds } = separateToolIds([toolId]);
19512
+ if (customToolIds.length === 0) {
19513
+ continue;
19514
+ }
19515
+ selectedToolIds.push({ toolId, path: path18 });
19516
+ }
19517
+ if (selectedToolIds.length > 0 || selectedToolNames.length > 0) {
19518
+ pendingChecks.hasAccountScopedReferences = true;
19519
+ pendingChecks.codeToolNameChecks.push({
19520
+ step: stepRef,
19521
+ collisionCode: "CODE_STEP_TOOL_NAME_COLLISION",
19522
+ runtimeToolNames: collectRuntimeToolNameSelections(toolsConfig, stepIndex),
19523
+ selectedToolIds,
19524
+ selectedToolNames
19525
+ });
19526
+ }
19527
+ }
19528
+ function collectCodeModeToolNameCheck(toolsConfig, stepIndex, stepRef, pendingChecks) {
19529
+ const codeModeConfig = toolsConfig.codeModeConfig;
19530
+ if (!isObjectRecord(codeModeConfig) || !Array.isArray(codeModeConfig.toolPool)) {
19531
+ return;
19532
+ }
19533
+ const runtimeTools = Array.isArray(toolsConfig.runtimeTools) ? toolsConfig.runtimeTools : [];
19534
+ const runtimeToolNames = /* @__PURE__ */ new Set();
19535
+ for (const runtimeTool of runtimeTools) {
19536
+ if (!isObjectRecord(runtimeTool) || typeof runtimeTool.name !== "string") {
19537
+ continue;
19538
+ }
19539
+ runtimeToolNames.add(runtimeTool.name);
19540
+ }
19541
+ const selectedRuntimeToolNames = /* @__PURE__ */ new Set();
19542
+ const selectedToolIds = [];
19543
+ const selectedToolNames = [];
19544
+ for (const [toolPoolIndex, entry] of codeModeConfig.toolPool.entries()) {
19545
+ if (typeof entry !== "string" || entry.length === 0 || entry.endsWith(":*")) {
19546
+ continue;
19547
+ }
19548
+ const path18 = `flowSteps[${stepIndex}].config.tools.codeModeConfig.toolPool[${toolPoolIndex}]`;
19549
+ const named = parseNamedToolRef(entry);
19550
+ if (named) {
19551
+ selectedToolNames.push({ name: named.name, path: path18 });
19552
+ continue;
19553
+ }
19554
+ if (runtimeToolNames.has(entry)) {
19555
+ selectedRuntimeToolNames.add(entry);
19556
+ continue;
19557
+ }
19558
+ const { customToolIds } = separateToolIds([entry]);
19559
+ if (customToolIds.length === 0) {
19560
+ continue;
19561
+ }
19562
+ selectedToolIds.push({ toolId: entry, path: path18 });
19563
+ }
19564
+ if (selectedToolIds.length > 0 || selectedToolNames.length > 0) {
19565
+ pendingChecks.hasAccountScopedReferences = true;
19566
+ pendingChecks.codeToolNameChecks.push({
19567
+ step: stepRef,
19568
+ collisionCode: "CODE_MODE_TOOL_NAME_COLLISION",
19569
+ runtimeToolNames: collectRuntimeToolNameSelections(
19570
+ toolsConfig,
19571
+ stepIndex,
19572
+ selectedRuntimeToolNames
19573
+ ),
19574
+ selectedToolIds,
19575
+ selectedToolNames
19576
+ });
19577
+ }
19578
+ }
19579
+ var SINGLE_BRACE_VARIABLE_PATTERN = /(?<!\{)\{([a-zA-Z_][a-zA-Z0-9_.]*)\}(?!\})/g;
19580
+ var DOUBLE_BRACE_VARIABLE_PATTERN = TEMPLATE_EXPRESSION_PATTERN;
19581
+ var TEMPLATE_STRING_FIELDS = /* @__PURE__ */ new Set([
19582
+ "text",
19583
+ "userPrompt",
19584
+ "systemPrompt",
19585
+ "url",
19586
+ "body",
19587
+ "query",
19588
+ "message",
19589
+ "valueTemplate",
19590
+ "value",
19591
+ "subject",
19592
+ "html",
19593
+ "from",
19594
+ "to",
19595
+ "cc",
19596
+ "bcc",
19597
+ "replyTo",
19598
+ "nameTemplate",
19599
+ "condition",
19600
+ "script",
19601
+ "requestTemplate"
19602
+ ]);
19603
+ var NON_FLOW_VARIABLE_SUBTREE_KEYS = /* @__PURE__ */ new Set(["tools"]);
19604
+ function extractTemplateStrings(config3, path18 = []) {
19605
+ const results = [];
19606
+ if (typeof config3 === "string") {
19607
+ const fieldName = path18[path18.length - 1];
19608
+ const parentFieldName = path18.length >= 2 ? path18[path18.length - 2] : void 0;
19609
+ if (fieldName && TEMPLATE_STRING_FIELDS.has(fieldName) || parentFieldName && TEMPLATE_STRING_FIELDS.has(parentFieldName)) {
19610
+ results.push({ value: config3, fieldPath: path18.join(".") });
19611
+ }
19612
+ return results;
19613
+ }
19614
+ if (Array.isArray(config3)) {
19615
+ for (const [index, item] of config3.entries()) {
19616
+ results.push(...extractTemplateStrings(item, [...path18, String(index)]));
19617
+ }
19618
+ return results;
19619
+ }
19620
+ if (isObjectRecord(config3)) {
19621
+ for (const [key, val] of Object.entries(config3)) {
19622
+ if (NON_FLOW_VARIABLE_SUBTREE_KEYS.has(key)) continue;
19623
+ if (typeof val === "string" && TEMPLATE_STRING_FIELDS.has(key)) {
19624
+ results.push({ value: val, fieldPath: [...path18, key].join(".") });
19625
+ } else if (typeof val === "object" && val !== null) {
19626
+ results.push(...extractTemplateStrings(val, [...path18, key]));
19627
+ }
19628
+ }
19629
+ }
19630
+ return results;
19631
+ }
19632
+ function detectMalformedVariableReferences(config3) {
19633
+ const malformed = [];
19634
+ const templateStrings = extractTemplateStrings(config3);
19635
+ for (const { value, fieldPath } of templateStrings) {
19636
+ let match;
19637
+ const pattern = new RegExp(SINGLE_BRACE_VARIABLE_PATTERN.source, "g");
19638
+ while ((match = pattern.exec(value)) !== null) {
19639
+ const varName = match[1];
19640
+ if (!varName) continue;
19641
+ const doublebraceForm = `{{${varName}}}`;
19642
+ if (value.includes(doublebraceForm)) continue;
19643
+ malformed.push({ variable: varName, fieldPath });
19644
+ }
19645
+ }
19646
+ return malformed;
19647
+ }
19648
+ function extractVariableReferences(config3) {
19649
+ const references = [];
19650
+ const templateStrings = extractTemplateStrings(config3);
19651
+ for (const { value, fieldPath } of templateStrings) {
19652
+ const pattern = new RegExp(DOUBLE_BRACE_VARIABLE_PATTERN.source, "g");
19653
+ let match;
19654
+ while ((match = pattern.exec(value)) !== null) {
19655
+ const expr = match[1];
19656
+ if (!expr) continue;
19657
+ for (const path18 of extractTemplateExpressionPaths(expr)) {
19658
+ references.push({ variable: path18, fieldPath });
19659
+ }
19660
+ }
19661
+ }
19662
+ return references;
19663
+ }
19664
+ function getStepOutputVariable(step) {
19665
+ if (!isObjectRecord(step.config)) return null;
19666
+ if (typeof step.config.outputVariable === "string" && step.config.outputVariable.length > 0) {
19667
+ return step.config.outputVariable;
19668
+ }
19669
+ if (step.type === "set-variable" && typeof step.config.variableName === "string" && step.config.variableName.length > 0) {
19670
+ return step.config.variableName;
19671
+ }
19672
+ return null;
19673
+ }
19674
+ function collectDeclaredFlowInputs(flowSteps, declaredFlowInputs) {
19675
+ const declared = /* @__PURE__ */ new Set();
19676
+ for (const key of declaredFlowInputs ?? []) {
19677
+ if (typeof key === "string" && key) declared.add(key);
19678
+ }
19679
+ for (const step of flowSteps) {
19680
+ const config3 = step.config;
19681
+ const inputVariables = config3?.inputVariables;
19682
+ if (Array.isArray(inputVariables)) {
19683
+ for (const name of inputVariables) {
19684
+ if (typeof name === "string" && name) declared.add(name);
19685
+ }
19686
+ }
19687
+ }
19688
+ return declared;
19689
+ }
19690
+ function validateVariableReferences(flowSteps, buckets, skipStepIndices, declaredFlowInputs) {
19691
+ const declaredVariables = collectDeclaredFlowInputs(flowSteps, declaredFlowInputs);
19692
+ for (const [stepIndex, step] of flowSteps.entries()) {
19693
+ if (skipStepIndices?.has(stepIndex)) continue;
19694
+ const stepRef = {
19695
+ index: stepIndex,
19696
+ name: step.name,
19697
+ type: step.type
19698
+ };
19699
+ const malformed = detectMalformedVariableReferences(step.config);
19700
+ for (const { variable, fieldPath } of malformed) {
19701
+ addIssue(
19702
+ "warning",
19703
+ {
19704
+ code: "MALFORMED_VARIABLE_REFERENCE",
19705
+ message: `Possible malformed variable reference "{${variable}}" \u2014 use "{{${variable}}}" for template variable substitution.`,
19706
+ path: `flowSteps[${stepIndex}].config.${fieldPath}`,
19707
+ step: stepRef,
19708
+ details: { variable, suggestion: `{{${variable}}}` }
19709
+ },
19710
+ buckets
19711
+ );
19712
+ }
19713
+ const references = extractVariableReferences(step.config);
19714
+ for (const { variable, fieldPath } of references) {
19715
+ const classification = classifyVariableReference(variable);
19716
+ if (classification.namespace === "system" || classification.namespace === "secret") {
19717
+ continue;
19718
+ }
19719
+ if (classification.namespace === "unknown") {
19720
+ addIssue(
19721
+ "warning",
19722
+ {
19723
+ code: "UNKNOWN_VARIABLE_NAMESPACE",
19724
+ message: `Variable "{{${variable}}}" uses an unrecognized namespace prefix. Recognized prefixes are "flow:" (a flow input) and "secret:" (a configured secret). Use a known prefix or a plain variable name.`,
19725
+ path: `flowSteps[${stepIndex}].config.${fieldPath}`,
19726
+ step: stepRef,
19727
+ details: { variable }
19728
+ },
19729
+ buckets
19730
+ );
19731
+ continue;
19732
+ }
19733
+ const baseName = classification.baseName;
19734
+ const rootVariable = baseName.split(".")[0] || "";
19735
+ if (!declaredVariables.has(rootVariable) && !declaredVariables.has(baseName)) {
19736
+ addIssue(
19737
+ "warning",
19738
+ {
19739
+ code: "UNDECLARED_VARIABLE_REFERENCE",
19740
+ message: `Variable "{{${variable}}}" is referenced but no earlier step declares an output variable "${rootVariable}". Check that a previous step sets outputVariable to "${rootVariable}", or declare "${rootVariable}" as a flow input.`,
19741
+ path: `flowSteps[${stepIndex}].config.${fieldPath}`,
19742
+ step: stepRef,
19743
+ details: {
19744
+ variable,
19745
+ availableVariables: [...declaredVariables]
19746
+ }
19747
+ },
19748
+ buckets
19749
+ );
19750
+ }
19751
+ }
19752
+ if (step.enabled !== false) {
19753
+ const outputVar = getStepOutputVariable(step);
19754
+ if (outputVar) {
19755
+ declaredVariables.add(outputVar);
19756
+ }
19757
+ }
19758
+ }
19759
+ }
19760
+ function promptResponseFormatIsNonJson(responseFormat) {
19761
+ if (typeof responseFormat !== "string") return true;
19762
+ return responseFormat.trim().toLowerCase() !== "json";
19763
+ }
19764
+ function validateUpsertRecordSourceShape(flowSteps, buckets) {
19765
+ const stringPromptOutputs = /* @__PURE__ */ new Map();
19766
+ for (const [stepIndex, step] of flowSteps.entries()) {
19767
+ if (step.enabled === false) continue;
19768
+ if (!isObjectRecord(step.config)) continue;
19769
+ const config3 = step.config;
19770
+ if (step.type === "upsert-record") {
19771
+ const inputMode = typeof config3.inputMode === "string" ? config3.inputMode : "single";
19772
+ const sourceVariable = typeof config3.sourceVariable === "string" ? config3.sourceVariable : "";
19773
+ const hasContentField = typeof config3.contentField === "string" && config3.contentField.length > 0;
19774
+ if (inputMode !== "batch" && sourceVariable && !hasContentField) {
19775
+ const origin = stringPromptOutputs.get(sourceVariable);
19776
+ if (origin) {
19777
+ addIssue(
19778
+ "warning",
19779
+ {
19780
+ code: "UPSERT_RECORD_SOURCE_NOT_JSON",
19781
+ message: `Source variable "${sourceVariable}" is set by prompt step "${origin.name}" (responseFormat "${origin.responseFormat}"), which outputs a string, but the record metadata column requires a JSON object. This will fail at runtime. Either: (1) set that prompt's responseFormat to "json", (2) add a transform-data step to wrap the string, or (3) set contentField on this upsert-record step to auto-wrap the string as { [contentField]: content }.`,
19782
+ path: `flowSteps[${stepIndex}].config.sourceVariable`,
19783
+ step: { index: stepIndex, name: step.name, type: step.type },
19784
+ details: {
19785
+ sourceVariable,
19786
+ originStepIndex: origin.index,
19787
+ originStepName: origin.name,
19788
+ responseFormat: origin.responseFormat
19789
+ }
19790
+ },
19791
+ buckets
19792
+ );
19793
+ }
19794
+ }
19795
+ }
19796
+ const outputVar = getStepOutputVariable(step);
19797
+ if (outputVar) {
19798
+ if (step.type === "prompt" && promptResponseFormatIsNonJson(config3.responseFormat)) {
19799
+ const responseFormat = typeof config3.responseFormat === "string" ? config3.responseFormat : "default";
19800
+ stringPromptOutputs.set(outputVar, { index: stepIndex, name: step.name, responseFormat });
19801
+ } else {
19802
+ stringPromptOutputs.delete(outputVar);
19803
+ }
19804
+ }
19805
+ }
19806
+ }
19807
+ function collectAccountScopedReferences(step, stepIndex, pendingChecks) {
19808
+ const stepRef = {
19809
+ index: stepIndex,
19810
+ name: step.name,
19811
+ type: step.type
19812
+ };
19813
+ if (!isObjectRecord(step.config)) {
19814
+ return;
19815
+ }
19816
+ if (step.type === "execute-agent") {
19817
+ const agentId = step.config.agentId;
19818
+ if (typeof agentId === "string" && !agentId.includes("{{")) {
19819
+ const path18 = `flowSteps[${stepIndex}].config.agentId`;
19820
+ registerAgentReference(agentId, path18, stepRef, pendingChecks);
19821
+ }
19822
+ return;
19823
+ }
19824
+ if (step.type === "tool-call") {
19825
+ const toolId = step.config.toolId;
19826
+ if (typeof toolId === "string") {
19827
+ const path18 = `flowSteps[${stepIndex}].config.toolId`;
19828
+ const named = parseNamedToolRef(toolId);
19829
+ if (named) {
19830
+ pendingChecks.hasAccountScopedReferences = true;
19831
+ registerReference(pendingChecks.toolReferencesByName, named.name, { path: path18, step: stepRef });
19832
+ } else {
19833
+ const { customToolIds } = separateToolIds([toolId]);
19834
+ if (customToolIds.length > 0) {
19835
+ pendingChecks.hasAccountScopedReferences = true;
19836
+ registerReference(pendingChecks.toolReferencesById, toolId, { path: path18, step: stepRef });
19837
+ }
19838
+ }
19839
+ }
19840
+ return;
19841
+ }
19842
+ if (step.type !== "prompt" && step.type !== "transform-data") {
19843
+ return;
19844
+ }
19845
+ const toolsConfig = step.config.tools;
19846
+ if (!isObjectRecord(toolsConfig)) {
19847
+ return;
19848
+ }
19849
+ const toolIds = toolsConfig.toolIds;
19850
+ if (Array.isArray(toolIds)) {
19851
+ for (const [toolIdIndex, toolId] of toolIds.entries()) {
19852
+ if (typeof toolId !== "string") {
19853
+ continue;
19854
+ }
19855
+ const path18 = `flowSteps[${stepIndex}].config.tools.toolIds[${toolIdIndex}]`;
19856
+ const named = parseNamedToolRef(toolId);
19857
+ if (named) {
19858
+ pendingChecks.hasAccountScopedReferences = true;
19859
+ registerReference(pendingChecks.toolReferencesByName, named.name, { path: path18, step: stepRef });
19860
+ continue;
19861
+ }
19862
+ const { customToolIds } = separateToolIds([toolId]);
19863
+ if (customToolIds.length > 0) {
19864
+ pendingChecks.hasAccountScopedReferences = true;
19865
+ registerReference(pendingChecks.toolReferencesById, toolId, { path: path18, step: stepRef });
19866
+ }
19867
+ }
19868
+ }
19869
+ if (step.type === "transform-data") {
19870
+ collectTransformDataCodeToolNameCheck(toolsConfig, stepIndex, stepRef, pendingChecks);
19871
+ } else {
19872
+ collectCodeModeToolNameCheck(toolsConfig, stepIndex, stepRef, pendingChecks);
19873
+ }
19874
+ const runtimeTools = toolsConfig.runtimeTools;
19875
+ if (!Array.isArray(runtimeTools)) {
19876
+ return;
19877
+ }
19878
+ for (const [runtimeToolIndex, runtimeTool] of runtimeTools.entries()) {
19879
+ if (!isObjectRecord(runtimeTool)) {
19880
+ continue;
19881
+ }
19882
+ const runtimeConfig = runtimeTool.config;
19883
+ if (!isObjectRecord(runtimeConfig)) {
19884
+ continue;
19885
+ }
19886
+ const basePath = `flowSteps[${stepIndex}].config.tools.runtimeTools[${runtimeToolIndex}].config`;
19887
+ if (runtimeTool.toolType === "flow") {
19888
+ const flowId = runtimeConfig.flowId;
19889
+ if (typeof flowId === "string") {
19890
+ registerFlowReference(flowId, `${basePath}.flowId`, stepRef, pendingChecks);
19891
+ }
19892
+ continue;
19893
+ }
19894
+ if (runtimeTool.toolType === "subagent") {
19895
+ const agentId = runtimeConfig.agentId;
19896
+ if (typeof agentId === "string" && !agentId.includes("{{")) {
19897
+ registerAgentReference(agentId, `${basePath}.agentId`, stepRef, pendingChecks);
19898
+ }
19899
+ continue;
19900
+ }
19901
+ }
19902
+ }
19903
+ function registerAgentReference(agentId, path18, stepRef, pendingChecks) {
19904
+ const named = parseNamedAgentRef(agentId);
19905
+ pendingChecks.hasAccountScopedReferences = true;
19906
+ if (named) {
19907
+ registerReference(pendingChecks.agentReferencesByName, named.name, { path: path18, step: stepRef });
19908
+ } else {
19909
+ registerReference(pendingChecks.agentReferencesById, agentId, { path: path18, step: stepRef });
19910
+ }
19911
+ }
19912
+ function registerFlowReference(flowId, path18, stepRef, pendingChecks) {
19913
+ const named = parseNamedFlowRef(flowId);
19914
+ pendingChecks.hasAccountScopedReferences = true;
19915
+ if (named) {
19916
+ registerReference(pendingChecks.flowReferencesByName, named.name, { path: path18, step: stepRef });
19917
+ } else {
19918
+ registerReference(pendingChecks.flowReferencesById, flowId, { path: path18, step: stepRef });
19919
+ }
19920
+ }
19921
+ function validateSubagentConfig(value, stepTools, stepIndex, stepRef) {
19922
+ const basePath = `flowSteps[${stepIndex}].config.tools.subagentConfig`;
19923
+ if (!isObjectRecord(value)) {
19924
+ return {
19925
+ code: "SUBAGENT_CONFIG_INVALID",
19926
+ message: "subagentConfig must be an object.",
19927
+ path: basePath,
19928
+ step: stepRef
19929
+ };
19930
+ }
19931
+ const cfg = value;
19932
+ if (!Array.isArray(cfg.toolPool)) {
19933
+ return {
19934
+ code: "SUBAGENT_CONFIG_INVALID",
19935
+ message: "subagentConfig.toolPool must be an array of tool IDs (wildcards allowed).",
19936
+ path: `${basePath}.toolPool`,
19937
+ step: stepRef
19938
+ };
19939
+ }
19940
+ const parentToolIds = new Set(
19941
+ Array.isArray(stepTools.toolIds) ? stepTools.toolIds.filter((x2) => typeof x2 === "string") : []
19942
+ );
19943
+ const parentRuntimeToolNames = new Set(
19944
+ Array.isArray(stepTools.runtimeTools) ? stepTools.runtimeTools.map((t) => t.name).filter((n) => typeof n === "string") : []
19945
+ );
19946
+ for (const entry of cfg.toolPool) {
19947
+ if (typeof entry !== "string" || entry.length === 0) {
19948
+ return {
19949
+ code: "SUBAGENT_CONFIG_INVALID",
19950
+ message: "subagentConfig.toolPool entries must be non-empty strings.",
19951
+ path: `${basePath}.toolPool`,
19952
+ step: stepRef
19953
+ };
19954
+ }
19955
+ const isWildcard2 = entry.endsWith(":*");
19956
+ if (isWildcard2) continue;
19957
+ if (!parentToolIds.has(entry) && !parentRuntimeToolNames.has(entry)) {
19958
+ return {
19959
+ code: "SUBAGENT_CONFIG_ESCALATION",
19960
+ message: `subagentConfig.toolPool entry "${entry}" is not granted to the parent step. Every pool entry must be a wildcard (\`foo:*\`) or appear in the parent step's toolIds or runtimeTools \u2014 otherwise the spawned subagent cannot actually call it.`,
19961
+ path: `${basePath}.toolPool`,
19962
+ step: stepRef
19963
+ };
19964
+ }
19965
+ }
19966
+ if (cfg.defaultMaxTurns !== void 0) {
19967
+ const n = cfg.defaultMaxTurns;
19968
+ if (typeof n !== "number" || !Number.isInteger(n) || n < 1) {
19969
+ return {
19970
+ code: "SUBAGENT_CONFIG_INVALID",
19971
+ message: "subagentConfig.defaultMaxTurns must be a positive integer.",
19972
+ path: `${basePath}.defaultMaxTurns`,
19973
+ step: stepRef
19974
+ };
19975
+ }
19976
+ }
19977
+ if (cfg.maxTurnsLimit !== void 0) {
19978
+ const n = cfg.maxTurnsLimit;
19979
+ if (typeof n !== "number" || !Number.isInteger(n) || n < 1) {
19980
+ return {
19981
+ code: "SUBAGENT_CONFIG_INVALID",
19982
+ message: "subagentConfig.maxTurnsLimit must be a positive integer.",
19983
+ path: `${basePath}.maxTurnsLimit`,
19984
+ step: stepRef
19985
+ };
19986
+ }
19987
+ }
19988
+ if (cfg.maxSpawnsPerRun !== void 0) {
19989
+ const n = cfg.maxSpawnsPerRun;
19990
+ if (typeof n !== "number" || !Number.isInteger(n) || n < 1) {
19991
+ return {
19992
+ code: "SUBAGENT_CONFIG_INVALID",
19993
+ message: "subagentConfig.maxSpawnsPerRun must be a positive integer.",
19994
+ path: `${basePath}.maxSpawnsPerRun`,
19995
+ step: stepRef
19996
+ };
19997
+ }
19998
+ }
19999
+ return null;
20000
+ }
20001
+ function validateCodeModeConfig(value, stepTools, stepIndex, stepRef) {
20002
+ const basePath = `flowSteps[${stepIndex}].config.tools.codeModeConfig`;
20003
+ if (!isObjectRecord(value)) {
20004
+ return {
20005
+ code: "CODE_MODE_CONFIG_INVALID",
20006
+ message: "codeModeConfig must be an object.",
20007
+ path: basePath,
20008
+ step: stepRef
20009
+ };
20010
+ }
20011
+ const cfg = value;
20012
+ if (!Array.isArray(cfg.toolPool)) {
20013
+ return {
20014
+ code: "CODE_MODE_CONFIG_INVALID",
20015
+ message: "codeModeConfig.toolPool must be an array of tool IDs (wildcards allowed).",
20016
+ path: `${basePath}.toolPool`,
20017
+ step: stepRef
20018
+ };
20019
+ }
20020
+ const parentToolIds = new Set(
20021
+ Array.isArray(stepTools.toolIds) ? stepTools.toolIds.filter((x2) => typeof x2 === "string") : []
20022
+ );
20023
+ const parentRuntimeTools = Array.isArray(stepTools.runtimeTools) ? stepTools.runtimeTools : [];
20024
+ const parentRuntimeToolNames = new Set(
20025
+ parentRuntimeTools.map((t) => t.name).filter((n) => typeof n === "string")
20026
+ );
20027
+ const runtimeToolByName = new Map(
20028
+ parentRuntimeTools.filter((t) => typeof t.name === "string").map((t) => [t.name, t])
20029
+ );
20030
+ const selectedRuntimeToolNames = [];
20031
+ for (const entry of cfg.toolPool) {
20032
+ if (typeof entry !== "string" || entry.length === 0) {
20033
+ return {
20034
+ code: "CODE_MODE_CONFIG_INVALID",
20035
+ message: "codeModeConfig.toolPool entries must be non-empty strings.",
20036
+ path: `${basePath}.toolPool`,
20037
+ step: stepRef
20038
+ };
20039
+ }
20040
+ const isWildcard2 = entry.endsWith(":*");
20041
+ if (isWildcard2) continue;
20042
+ const runtimeTool = runtimeToolByName.get(entry);
20043
+ if (runtimeTool) {
20044
+ if (runtimeTool.toolType === "local") {
20045
+ return {
20046
+ code: "CODE_MODE_CONFIG_INVALID",
20047
+ message: `codeModeConfig.toolPool entry "${entry}" is a local tool. Code mode cannot pause for client-side local tool callbacks.`,
20048
+ path: `${basePath}.toolPool`,
20049
+ step: stepRef
20050
+ };
20051
+ }
20052
+ selectedRuntimeToolNames.push({
20053
+ name: entry,
20054
+ path: `${basePath}.toolPool`
20055
+ });
20056
+ }
20057
+ if (!parentToolIds.has(entry) && !parentRuntimeToolNames.has(entry)) {
20058
+ return {
20059
+ code: "CODE_MODE_CONFIG_ESCALATION",
20060
+ message: `codeModeConfig.toolPool entry "${entry}" is not granted to the parent step. Every pool entry must be a wildcard (\`foo:*\`) or appear in the parent step's toolIds or runtimeTools \u2014 otherwise the sandbox code cannot actually call it.`,
20061
+ path: `${basePath}.toolPool`,
20062
+ step: stepRef
20063
+ };
20064
+ }
20065
+ }
20066
+ const collision = validateCodeToolNameCollisions(
20067
+ selectedRuntimeToolNames,
20068
+ stepRef,
20069
+ "CODE_MODE_TOOL_NAME_COLLISION"
20070
+ );
20071
+ if (collision) {
20072
+ return collision;
20073
+ }
20074
+ if (cfg.timeoutMs !== void 0) {
20075
+ const n = cfg.timeoutMs;
20076
+ if (typeof n !== "number" || !Number.isFinite(n) || n < 1e3 || n > 6e5) {
20077
+ return {
20078
+ code: "CODE_MODE_CONFIG_INVALID",
20079
+ message: "codeModeConfig.timeoutMs must be a number between 1000 and 600000.",
20080
+ path: `${basePath}.timeoutMs`,
20081
+ step: stepRef
20082
+ };
20083
+ }
20084
+ }
20085
+ return null;
20086
+ }
20087
+ function validateTransformDataCodeTools(toolsConfig, stepIndex, stepRef, buckets) {
20088
+ const runtimeTools = Array.isArray(toolsConfig.runtimeTools) ? toolsConfig.runtimeTools : [];
20089
+ const runtimeToolNames = [];
20090
+ for (const [runtimeToolIndex, runtimeTool] of runtimeTools.entries()) {
20091
+ if (!isObjectRecord(runtimeTool)) {
20092
+ continue;
20093
+ }
20094
+ const basePath = `flowSteps[${stepIndex}].config.tools.runtimeTools[${runtimeToolIndex}]`;
20095
+ const name = runtimeTool.name;
20096
+ if (typeof name === "string") {
20097
+ runtimeToolNames.push({ name, path: `${basePath}.name` });
20098
+ }
20099
+ if (runtimeTool.toolType === "local") {
20100
+ addIssue(
20101
+ "error",
20102
+ {
20103
+ code: "CODE_STEP_LOCAL_TOOL_UNSUPPORTED",
20104
+ message: "Transform-data code steps do not support local tools because code execution cannot pause for client-side callbacks.",
20105
+ path: `${basePath}.toolType`,
20106
+ step: stepRef
20107
+ },
20108
+ buckets
20109
+ );
20110
+ }
20111
+ }
20112
+ const collision = validateCodeToolNameCollisions(
20113
+ runtimeToolNames,
20114
+ stepRef,
20115
+ "CODE_STEP_TOOL_NAME_COLLISION"
20116
+ );
20117
+ if (collision) {
20118
+ addIssue("error", collision, buckets);
20119
+ }
20120
+ }
20121
+ function validateErrorHandlingTriggers(errorHandling, stepIndex, stepRef, buckets) {
20122
+ if (!isObjectRecord(errorHandling) || !Array.isArray(errorHandling.triggers)) {
20123
+ return;
20124
+ }
20125
+ for (const [triggerIndex, trigger] of errorHandling.triggers.entries()) {
20126
+ if (!isObjectRecord(trigger) || trigger.type !== "slow") continue;
20127
+ const afterMs = trigger.afterMs;
20128
+ if (typeof afterMs !== "number" || !Number.isFinite(afterMs) || afterMs <= 0) {
20129
+ addIssue(
20130
+ "error",
20131
+ {
20132
+ code: "SLOW_TRIGGER_INVALID_AFTER_MS",
20133
+ message: 'A "slow" fallback trigger requires a positive "afterMs" (the total-duration cap in milliseconds) before it can fire.',
20134
+ path: `flowSteps[${stepIndex}].config.errorHandling.triggers[${triggerIndex}].afterMs`,
20135
+ step: stepRef,
20136
+ details: { afterMs }
20137
+ },
20138
+ buckets
20139
+ );
20140
+ }
20141
+ }
20142
+ }
20143
+ function collectFlowStructureIssues(flowData, deps, buckets) {
20144
+ const pendingChecks = {
20145
+ hasAccountScopedReferences: false,
20146
+ toolReferencesById: /* @__PURE__ */ new Map(),
20147
+ toolReferencesByName: /* @__PURE__ */ new Map(),
20148
+ flowReferencesById: /* @__PURE__ */ new Map(),
20149
+ agentReferencesById: /* @__PURE__ */ new Map(),
20150
+ agentReferencesByName: /* @__PURE__ */ new Map(),
20151
+ flowReferencesByName: /* @__PURE__ */ new Map(),
20152
+ codeToolNameChecks: []
20153
+ };
20154
+ const orderToStepIndexes = /* @__PURE__ */ new Map();
20155
+ const normalizedOrders = flowData.flowSteps.map((step, index) => step.order ?? index);
20156
+ for (const [index, order] of normalizedOrders.entries()) {
20157
+ const existing = orderToStepIndexes.get(order) || [];
20158
+ existing.push(index);
20159
+ orderToStepIndexes.set(order, existing);
20160
+ }
20161
+ for (const [order, indexes] of orderToStepIndexes.entries()) {
20162
+ if (indexes.length <= 1) {
20163
+ continue;
20164
+ }
20165
+ addIssue(
20166
+ "warning",
20167
+ {
20168
+ code: "DUPLICATE_STEP_ORDER",
20169
+ message: `Multiple steps share order "${order}". Execution order may be ambiguous.`,
20170
+ details: { order, stepIndexes: indexes }
20171
+ },
20172
+ buckets
20173
+ );
20174
+ }
20175
+ const idToStepIndexes = /* @__PURE__ */ new Map();
20176
+ for (const [index, step] of flowData.flowSteps.entries()) {
20177
+ if (typeof step.id !== "string" || step.id.length === 0) continue;
20178
+ const existing = idToStepIndexes.get(step.id) || [];
20179
+ existing.push(index);
20180
+ idToStepIndexes.set(step.id, existing);
20181
+ }
20182
+ for (const [id, indexes] of idToStepIndexes.entries()) {
20183
+ if (indexes.length <= 1) continue;
20184
+ addIssue(
20185
+ "error",
20186
+ {
20187
+ code: "DUPLICATE_STEP_ID",
20188
+ message: `Multiple steps share id "${id}". Step ids must be unique within a flow.`,
20189
+ details: { id, stepIndexes: indexes }
20190
+ },
20191
+ buckets
20192
+ );
20193
+ }
20194
+ const enabledSteps = flowData.flowSteps.filter((step) => step.enabled !== false);
20195
+ if (enabledSteps.length === 0) {
20196
+ addIssue(
20197
+ "warning",
20198
+ {
20199
+ code: "NO_ENABLED_STEPS",
20200
+ message: "This flow has no enabled steps."
20201
+ },
20202
+ buckets
20203
+ );
20204
+ }
20205
+ if (!enabledSteps.some((step) => step.type === "prompt")) {
20206
+ addIssue(
20207
+ "recommendation",
20208
+ {
20209
+ code: "NO_PROMPT_STEPS",
20210
+ message: "No enabled prompt steps were found. Most flows require at least one prompt step."
20211
+ },
20212
+ buckets
20213
+ );
20214
+ }
20215
+ const conditionalStepsExceedingDepth = /* @__PURE__ */ new Set();
20216
+ const declaredVariables = /* @__PURE__ */ new Set();
20217
+ for (const [stepIndex, step] of flowData.flowSteps.entries()) {
20218
+ const stepRef = {
20219
+ index: stepIndex,
20220
+ name: step.name,
20221
+ type: step.type
20222
+ };
20223
+ if (step.type === "conditional" && conditionalNestingDepth(step.config) > MAX_CONDITIONAL_NESTING_DEPTH) {
20224
+ conditionalStepsExceedingDepth.add(stepIndex);
20225
+ addIssue(
20226
+ "error",
20227
+ {
20228
+ code: "CONDITIONAL_NESTING_TOO_DEEP",
20229
+ message: `Conditional steps may nest at most ${MAX_CONDITIONAL_NESTING_DEPTH} levels deep.`,
20230
+ path: `flowSteps[${stepIndex}].config`,
20231
+ step: stepRef
20232
+ },
20233
+ buckets
20234
+ );
20235
+ continue;
20236
+ }
20237
+ const configSchema = deps.configSchemas?.[step.type];
20238
+ if (configSchema) {
20239
+ const schemaResult = configSchema.safeParse(step.config);
20240
+ if (!schemaResult.success) {
20241
+ for (const issue2 of schemaResult.error.issues) {
20242
+ const issuePath = issue2.path.length > 0 ? `flowSteps[${stepIndex}].config.${formatPath(issue2.path)}` : `flowSteps[${stepIndex}].config`;
20243
+ addIssue("error", buildIssueFromZod(issue2, issuePath, stepRef), buckets);
20244
+ }
20245
+ }
20246
+ }
20247
+ if (isObjectRecord(step.config)) {
20248
+ validateErrorHandlingTriggers(step.config.errorHandling, stepIndex, stepRef, buckets);
20249
+ }
20250
+ if (isObjectRecord(step.config) && isObjectRecord(step.config.tools)) {
20251
+ for (const key of Object.keys(step.config.tools)) {
20252
+ if (KNOWN_TOOL_KEYS.has(key)) continue;
20253
+ const suggestion = LEGACY_TOOL_KEY_SUGGESTIONS[key];
20254
+ addIssue(
20255
+ "warning",
20256
+ {
20257
+ code: "UNKNOWN_PROMPT_TOOLS_FIELD",
20258
+ message: suggestion ? `Unknown field "${key}" under config.tools \u2014 did you mean "${suggestion}"? The runtime will ignore this value.` : `Unknown field "${key}" under config.tools \u2014 the runtime will ignore it. Expected keys: ${[...KNOWN_TOOL_KEYS].join(", ")}.`,
20259
+ path: `flowSteps[${stepIndex}].config.tools.${key}`,
20260
+ step: stepRef,
20261
+ details: suggestion ? { field: key, suggestion } : { field: key }
20262
+ },
20263
+ buckets
20264
+ );
20265
+ }
20266
+ if (deps.validateRuntimeTools) {
20267
+ const runtimeToolsValidation = deps.validateRuntimeTools(step.config.tools);
20268
+ if (!runtimeToolsValidation.valid) {
20269
+ addIssue(
20270
+ "error",
20271
+ {
20272
+ code: "RUNTIME_TOOLS_INVALID",
20273
+ message: runtimeToolsValidation.error || "Invalid runtime tools configuration",
20274
+ path: `flowSteps[${stepIndex}].config.tools`,
20275
+ step: stepRef
20276
+ },
20277
+ buckets
20278
+ );
20279
+ }
20280
+ }
20281
+ if (step.type === "transform-data") {
20282
+ validateTransformDataCodeTools(step.config.tools, stepIndex, stepRef, buckets);
20283
+ }
20284
+ const subagentCfg = step.config.tools.subagentConfig;
20285
+ if (subagentCfg !== void 0) {
20286
+ const issue2 = validateSubagentConfig(subagentCfg, step.config.tools, stepIndex, stepRef);
20287
+ if (issue2) addIssue("error", issue2, buckets);
20288
+ }
20289
+ const codeModeCfg = step.config.tools.codeModeConfig;
20290
+ if (codeModeCfg !== void 0) {
20291
+ const issue2 = validateCodeModeConfig(codeModeCfg, step.config.tools, stepIndex, stepRef);
20292
+ if (issue2) addIssue("error", issue2, buckets);
20293
+ }
20294
+ }
20295
+ if (step.type !== "prompt") {
20296
+ try {
20297
+ normalizeContextStep(
20298
+ {
20299
+ id: `step_validation_${stepIndex}`,
20300
+ type: step.type,
20301
+ name: step.name,
20302
+ order: step.order ?? stepIndex,
20303
+ enabled: step.enabled ?? true,
20304
+ config: step.config
20305
+ },
20306
+ {
20307
+ managedSendFromDomain: deps.managedSendFromDomain
20308
+ }
20309
+ );
20310
+ } catch (error51) {
20311
+ const normalizationError = error51 instanceof NormalizationError ? error51 : null;
20312
+ const fallbackMessage = error51 instanceof Error ? error51.message : String(error51);
20313
+ const fieldName = normalizationError?.fieldName;
20314
+ addIssue(
20315
+ "error",
20316
+ {
20317
+ code: "CONTEXT_STEP_INVALID",
20318
+ message: normalizationError?.message || fallbackMessage,
20319
+ path: fieldName ? `flowSteps[${stepIndex}].config.${fieldName}` : `flowSteps[${stepIndex}].config`,
20320
+ step: stepRef
20321
+ },
20322
+ buckets
20323
+ );
20324
+ }
20325
+ }
20326
+ if (step.type === "transform-data" && step.enabled !== false && isObjectRecord(step.config)) {
20327
+ const config3 = step.config;
20328
+ const sandboxProvider = config3.sandboxProvider || "cloudflare-worker";
20329
+ const resolvedProvider = sandboxProvider === "cloudflare-sandbox" ? "runtype-sandbox" : sandboxProvider;
20330
+ validateSandboxNetworkAccess(config3, stepIndex, stepRef, buckets);
20331
+ if (resolvedProvider === "runtype-sandbox" && !config3.language) {
20332
+ addIssue(
20333
+ "warning",
20334
+ {
20335
+ code: "MISSING_LANGUAGE",
20336
+ message: 'language is recommended when sandboxProvider is "runtype-sandbox" \u2014 defaults to "javascript" but you should specify "javascript", "typescript", or "python" explicitly',
20337
+ path: `flowSteps[${stepIndex}].config.language`,
20338
+ step: stepRef
20339
+ },
20340
+ buckets
20341
+ );
20342
+ }
20343
+ if (deps.validateScript && config3.inputMode !== "variable" && typeof config3.script === "string" && config3.script.trim()) {
20344
+ const codeResult = deps.validateScript(
20345
+ config3.script,
20346
+ {
20347
+ sandboxProvider,
20348
+ language: config3.language,
20349
+ availableVariables: [...declaredVariables]
20350
+ },
20351
+ { stepIndex }
20352
+ );
20353
+ for (const issue2 of codeResult.issues) {
20354
+ const location = issue2.line ? ` (line ${issue2.line}, column ${issue2.column})` : "";
20355
+ const issueCode = issue2.code === "SYNTAX_ERROR" ? "CODE_SYNTAX_ERROR" : `CODE_${issue2.code}`;
20356
+ addIssue(
20357
+ issue2.severity,
20358
+ {
20359
+ code: issueCode,
20360
+ message: `${issue2.message}${location}`,
20361
+ path: `flowSteps[${stepIndex}].config.script`,
20362
+ step: stepRef,
20363
+ details: {
20364
+ language: config3.language || "javascript",
20365
+ sandboxProvider,
20366
+ ...issue2.line !== void 0 ? { line: issue2.line } : {},
20367
+ ...issue2.column !== void 0 ? { column: issue2.column } : {}
20368
+ }
20369
+ },
20370
+ buckets
20371
+ );
20372
+ }
20373
+ }
20374
+ }
20375
+ collectAccountScopedReferences(step, stepIndex, pendingChecks);
20376
+ if (step.enabled !== false) {
20377
+ const outputVar = getStepOutputVariable(step);
20378
+ if (outputVar) declaredVariables.add(outputVar);
20379
+ }
20380
+ }
20381
+ validateVariableReferences(
20382
+ flowData.flowSteps,
20383
+ buckets,
20384
+ conditionalStepsExceedingDepth,
20385
+ deps.declaredFlowInputs
20386
+ );
20387
+ validateUpsertRecordSourceShape(flowData.flowSteps, buckets);
20388
+ return { pendingChecks };
20389
+ }
20390
+ function validateFlowStructure(flowData, deps = {}) {
20391
+ const buckets = { errors: [], warnings: [], recommendations: [] };
20392
+ collectFlowStructureIssues(flowData, deps, buckets);
20393
+ const errors = sortIssues(buckets.errors);
20394
+ return {
20395
+ valid: errors.length === 0,
20396
+ errors,
20397
+ warnings: sortIssues(buckets.warnings),
20398
+ recommendations: sortIssues(buckets.recommendations),
20399
+ context: {
20400
+ authenticated: false,
20401
+ accountChecksPerformed: false,
20402
+ accountChecksSkipped: false
20403
+ }
20404
+ };
20405
+ }
20406
+ function parseCreateFlowValidationInput(payload) {
20407
+ const parsed = createFlowValidationSchema.safeParse(payload);
20408
+ if (parsed.success) {
20409
+ return {
20410
+ success: true,
20411
+ data: parsed.data
20412
+ };
20413
+ }
20414
+ return {
20415
+ success: false,
20416
+ errors: sortIssues(
20417
+ parsed.error.issues.map(
20418
+ (issue2) => buildIssueFromZod(issue2, formatPath(issue2.path) || "root", void 0)
20419
+ )
20420
+ )
20421
+ };
20422
+ }
17309
20423
  var SERIALIZED_HELPERS_SOURCE = `
17310
20424
  // Transform helper functions (from packages/shared/src/transform-helpers.ts)
17311
20425
  const helpers = (function createHelpers() {
@@ -36737,6 +39851,7 @@ function mergeResults(...results) {
36737
39851
  merged.valid = merged.errors.length === 0;
36738
39852
  return merged;
36739
39853
  }
39854
+ var NAMESPACE_VARIABLE_CODES = /* @__PURE__ */ new Set(["UNDECLARED_VARIABLE_REFERENCE", "UNKNOWN_VARIABLE_NAMESPACE"]);
36740
39855
  function validateFlowDefinition(flow, capIndex, context) {
36741
39856
  const result = emptyResult();
36742
39857
  const base = `capabilities[${capIndex}].flow`;
@@ -36797,8 +39912,25 @@ function validateFlowDefinition(flow, capIndex, context) {
36797
39912
  }
36798
39913
  }
36799
39914
  }
39915
+ appendNamespaceVariableIssues(flow, base, result);
36800
39916
  return finalize2(result);
36801
39917
  }
39918
+ function reprefixCorePath(corePath, base) {
39919
+ if (!corePath) return `${base}.steps`;
39920
+ return corePath.replace(/^flowSteps\[/, `${base}.steps[`);
39921
+ }
39922
+ function appendNamespaceVariableIssues(flow, base, result) {
39923
+ const parsed = parseCreateFlowValidationInput({ name: flow.name, flowSteps: flow.steps });
39924
+ if (!parsed.success) return;
39925
+ const coreResult = validateFlowStructure(parsed.data);
39926
+ const push = (issue2, severity) => {
39927
+ if (!NAMESPACE_VARIABLE_CODES.has(issue2.code)) return;
39928
+ const bucket = severity === "error" ? result.errors : result.warnings;
39929
+ bucket.push(createIssue(severity, issue2.code, issue2.message, reprefixCorePath(issue2.path, base)));
39930
+ };
39931
+ for (const issue2 of coreResult.errors) push(issue2, "error");
39932
+ for (const issue2 of coreResult.warnings) push(issue2, "warning");
39933
+ }
36802
39934
  function finalize2(r) {
36803
39935
  r.valid = r.errors.length === 0;
36804
39936
  return r;
@@ -37426,8 +40558,10 @@ var fullProductObjectTemplateSchema = external_exports.object({
37426
40558
  });
37427
40559
  }
37428
40560
  });
37429
- var FLOW_PREFIX = "flow:";
37430
- var SECRET_PREFIX = "secret:";
40561
+ var FLOW_PREFIX = Object.values(RUNTIME_PREFIXES).find((spec) => spec.namespace === "flow").prefix;
40562
+ var SECRET_PREFIX = Object.values(RUNTIME_PREFIXES).find(
40563
+ (spec) => spec.namespace === "secret"
40564
+ ).prefix;
37431
40565
  function collectStringLeafPaths(value, path18 = []) {
37432
40566
  if (typeof value === "string") {
37433
40567
  return [{ path: path18, value }];
@@ -37458,12 +40592,16 @@ function extractTemplateReferences(value) {
37458
40592
  const inner = value.slice(start + 2, end);
37459
40593
  const separatorIndex = inner.indexOf("|");
37460
40594
  const key = (separatorIndex === -1 ? inner : inner.slice(0, separatorIndex)).trim();
37461
- if (key.length > 0 && !key.startsWith(SECRET_PREFIX) && !key.startsWith(FLOW_PREFIX)) {
37462
- references.push({
37463
- key,
37464
- defaultValue: separatorIndex === -1 ? void 0 : inner.slice(separatorIndex + 1).trim(),
37465
- raw
37466
- });
40595
+ if (key.length > 0) {
40596
+ const classification = classifyVariableReference(key);
40597
+ const ownedByRuntimeOrEngine = classification.namespace === "secret" || classification.namespace === "flow" || classification.namespace === "system";
40598
+ if (!ownedByRuntimeOrEngine) {
40599
+ references.push({
40600
+ key,
40601
+ defaultValue: separatorIndex === -1 ? void 0 : inner.slice(separatorIndex + 1).trim(),
40602
+ raw
40603
+ });
40604
+ }
37467
40605
  }
37468
40606
  cursor = end + 2;
37469
40607
  }
@@ -44280,26 +47418,26 @@ async function getCurrentAccountId() {
44280
47418
 
44281
47419
  // src/lib/quick-start-api.ts
44282
47420
  import { RuntypeApiError as RuntypeApiError2 } from "@runtypelabs/sdk";
44283
- function isObjectRecord(value) {
47421
+ function isObjectRecord2(value) {
44284
47422
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
44285
47423
  }
44286
47424
  function isQuickStartValidationResponse(value) {
44287
- if (!isObjectRecord(value) || typeof value.valid !== "boolean") {
47425
+ if (!isObjectRecord2(value) || typeof value.valid !== "boolean") {
44288
47426
  return false;
44289
47427
  }
44290
47428
  if (value.valid === false) {
44291
47429
  return typeof value.error === "string" && typeof value.code === "string";
44292
47430
  }
44293
- return typeof value.templateId === "string" && isObjectRecord(value.agentCard);
47431
+ return typeof value.templateId === "string" && isObjectRecord2(value.agentCard);
44294
47432
  }
44295
47433
  function isQuickStartCreateResponse(value) {
44296
- if (!isObjectRecord(value) || typeof value.success !== "boolean") {
47434
+ if (!isObjectRecord2(value) || typeof value.success !== "boolean") {
44297
47435
  return false;
44298
47436
  }
44299
47437
  if (value.success === false) {
44300
47438
  return typeof value.error === "string" && typeof value.code === "string";
44301
47439
  }
44302
- return isObjectRecord(value.product) && Array.isArray(value.capabilities) && typeof value.redirectUrl === "string";
47440
+ return isObjectRecord2(value.product) && Array.isArray(value.capabilities) && typeof value.redirectUrl === "string";
44303
47441
  }
44304
47442
  function getApiErrorData(error51) {
44305
47443
  return error51 instanceof RuntypeApiError2 ? error51.data : void 0;
@@ -56323,6 +59461,11 @@ function buildResumeHistoryWarning(state) {
56323
59461
  function canUseMarathonStartupShell(options) {
56324
59462
  return process.stdin.isTTY === true && process.stdout.isTTY === true && !options.json;
56325
59463
  }
59464
+ function formatBytes(bytes) {
59465
+ if (bytes < 1024) return `${bytes} B`;
59466
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
59467
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
59468
+ }
56326
59469
  function normalizeStartupModelOptionValue(value) {
56327
59470
  const trimmed = value?.trim().toLowerCase().replace(/^model\//, "") ?? "";
56328
59471
  if (!trimmed) return "";
@@ -56903,6 +60046,18 @@ async function taskAction(agent, options) {
56903
60046
  const sandboxWorkflowSelection = playbookWorkflow ? void 0 : resolveSandboxWorkflowSelection(baseMessage, parsedSandbox, resumeState);
56904
60047
  parsedSandbox = sandboxWorkflowSelection?.sandboxProvider ?? parsedSandbox;
56905
60048
  const resolvedWorkflow = playbookWorkflow ?? sandboxWorkflowSelection?.workflow;
60049
+ if (!resolvedWorkflow && !playbookWorkflow && !resumeState && !isDeployCapableSandbox(parsedSandbox) && (isGameIntent(baseMessage) || isDeployIntent(baseMessage))) {
60050
+ console.log(
60051
+ chalk23.yellow(
60052
+ "Hint: this goal looks like a build-and-deploy task, but no deploy-capable sandbox is enabled."
60053
+ )
60054
+ );
60055
+ console.log(
60056
+ chalk23.gray(
60057
+ " Re-run with --sandbox daytona to build and deploy to a live preview URL (enables the deploy_sandbox tool)."
60058
+ )
60059
+ );
60060
+ }
56906
60061
  const DEFAULT_MILESTONE_NAMES = ["research", "planning", "execution"];
56907
60062
  const EXTERNAL_MILESTONE_NAMES = ["research", "report"];
56908
60063
  const detectedVariant = resumeState?.workflowVariant ?? defaultWorkflow.classifyVariant?.(baseMessage);
@@ -57238,6 +60393,11 @@ Saving state... done. Session saved to ${filePath}`);
57238
60393
  let accumulatedCost = 0;
57239
60394
  let accumulatedTokens = { input: 0, output: 0 };
57240
60395
  let accumulatedToolCalls = 0;
60396
+ let indexedChunks = 0;
60397
+ let indexedBytes = 0;
60398
+ let indexingFailures = 0;
60399
+ let indexingFailureNoticed = false;
60400
+ const indexingRequests = [];
57241
60401
  let lastResult = null;
57242
60402
  let lastSessionMessages = [];
57243
60403
  let undeliveredSteering = [];
@@ -57409,12 +60569,35 @@ Saving state... done. Session saved to ${filePath}`);
57409
60569
  });
57410
60570
  if (chunks.length > 0) {
57411
60571
  const sessionIdx = currentSessionOffset + state.sessionCount - 1;
57412
- client.post("/session-context/index", {
60572
+ const payloadBytes = Buffer.byteLength(JSON.stringify(chunks), "utf-8");
60573
+ indexedChunks += chunks.length;
60574
+ indexedBytes += payloadBytes;
60575
+ const NOTICE_BYTES = 512 * 1024;
60576
+ if (payloadBytes >= NOTICE_BYTES) {
60577
+ reportContextNotice({
60578
+ kind: "session_indexed",
60579
+ message: `Session ${sessionIdx} indexed ${chunks.length.toLocaleString()} chunks (${formatBytes(payloadBytes)}) for semantic search.`,
60580
+ sessionIndex: sessionIdx,
60581
+ chunkCount: chunks.length,
60582
+ payloadBytes
60583
+ });
60584
+ }
60585
+ const indexingRequest = client.post("/session-context/index", {
57413
60586
  taskName,
57414
60587
  sessionIndex: sessionIdx,
57415
60588
  chunks
57416
- }).catch(() => {
60589
+ }).catch((error51) => {
60590
+ indexingFailures++;
60591
+ if (!indexingFailureNoticed) {
60592
+ indexingFailureNoticed = true;
60593
+ reportContextNotice({
60594
+ kind: "indexing_failed",
60595
+ message: `Session-search indexing failed; recall may be incomplete (${error51 instanceof Error ? error51.message : String(error51)}). Pass --no-session-search to disable indexing.`,
60596
+ sessionIndex: sessionIdx
60597
+ });
60598
+ }
57417
60599
  });
60600
+ indexingRequests.push(indexingRequest);
57418
60601
  }
57419
60602
  }
57420
60603
  }
@@ -57728,11 +60911,26 @@ Saving state... done. Session saved to ${filePath}`);
57728
60911
  saveState(filePath, finalState, { stripSnapshotEvents: !!eventLogWriter });
57729
60912
  await waitForUiExit?.();
57730
60913
  exitAltScreen();
60914
+ if (indexingRequests.length > 0) {
60915
+ const INDEXING_SETTLE_GRACE_MS = 5e3;
60916
+ await Promise.race([
60917
+ Promise.allSettled(indexingRequests),
60918
+ new Promise((resolve11) => {
60919
+ const timer = setTimeout(resolve11, INDEXING_SETTLE_GRACE_MS);
60920
+ timer.unref?.();
60921
+ })
60922
+ ]);
60923
+ }
57731
60924
  console.log();
57732
60925
  const statusColor = result.status === "complete" ? chalk23.green : result.status === "budget_exceeded" || result.status === "error" ? chalk23.red : chalk23.yellow;
57733
60926
  console.log(`Status: ${statusColor(result.status)}`);
57734
60927
  console.log(`Sessions: ${finalState.sessionCount}`);
57735
60928
  console.log(`Total cost: ${chalk23.yellow(`$${finalState.totalCost.toFixed(4)}`)}`);
60929
+ if (indexedChunks > 0 || indexingFailures > 0) {
60930
+ const indexedLine = `${indexedChunks.toLocaleString()} chunks (${formatBytes(indexedBytes)})`;
60931
+ const failureSuffix = indexingFailures > 0 ? chalk23.red(` \u2014 ${indexingFailures} indexing failure${indexingFailures === 1 ? "" : "s"}`) : "";
60932
+ console.log(`Indexed: ${chalk23.dim(indexedLine)}${failureSuffix}`);
60933
+ }
57736
60934
  console.log(`State: ${chalk23.gray(filePath)}`);
57737
60935
  if (typeof finalState.lastError === "string" && finalState.lastError.trim()) {
57738
60936
  console.log(`Last error: ${chalk23.red(finalState.lastError)}`);
@@ -57888,7 +61086,20 @@ ${details}`);
57888
61086
  }
57889
61087
  return resolved;
57890
61088
  }
57891
- function detectDeployWorkflow(_message, _sandboxProvider, resumeState) {
61089
+ function isDeployCapableSandbox(provider) {
61090
+ return provider === "daytona" || provider === "runtype-sandbox";
61091
+ }
61092
+ function isGameIntent(message) {
61093
+ const lower = message.toLowerCase();
61094
+ return /\b(game|gameplay|playable|racing|platformer|shooter|puzzle|arcade)\b/.test(lower) || /\b(three\.?js|webgl|phaser|babylon\.?js|pixi\.?js)\b/.test(lower);
61095
+ }
61096
+ function isDeployIntent(message) {
61097
+ const lower = message.toLowerCase();
61098
+ return /\b(deploy|deployed|deployment|publish|published|host|hosted|hosting|serve|served)\b/.test(
61099
+ lower
61100
+ ) || /\b(web ?app|web ?site|landing page|preview url|live url|public url)\b/.test(lower) || /\b(publicly|share with friends)\b/.test(lower);
61101
+ }
61102
+ function detectDeployWorkflow(message, sandboxProvider, resumeState) {
57892
61103
  if (resumeState?.workflowVariant === "game") return gameWorkflow;
57893
61104
  if (resumeState?.workflowPhase === "design" || resumeState?.workflowPhase === "build" || resumeState?.workflowPhase === "verify") {
57894
61105
  return gameWorkflow;
@@ -57897,10 +61108,14 @@ function detectDeployWorkflow(_message, _sandboxProvider, resumeState) {
57897
61108
  if (resumeState?.workflowPhase === "scaffold" || resumeState?.workflowPhase === "deploy") {
57898
61109
  return deployWorkflow;
57899
61110
  }
61111
+ if (isDeployCapableSandbox(sandboxProvider)) {
61112
+ if (isGameIntent(message)) return gameWorkflow;
61113
+ if (isDeployIntent(message)) return deployWorkflow;
61114
+ }
57900
61115
  return void 0;
57901
61116
  }
57902
61117
  function resolveSandboxWorkflowSelection(message, sandboxProvider, resumeState) {
57903
- if (sandboxProvider && sandboxProvider !== "daytona") {
61118
+ if (sandboxProvider && !isDeployCapableSandbox(sandboxProvider)) {
57904
61119
  return {
57905
61120
  workflow: void 0,
57906
61121
  sandboxProvider
@@ -60283,8 +63498,8 @@ import { execFileSync } from "child_process";
60283
63498
  // src/lib/persona-init.ts
60284
63499
  init_credential_store();
60285
63500
 
60286
- // ../../node_modules/.pnpm/@runtypelabs+persona@3.34.0/node_modules/@runtypelabs/persona/dist/codegen.js
60287
- var S = "3.34.0";
63501
+ // ../../node_modules/.pnpm/@runtypelabs+persona@3.34.1/node_modules/@runtypelabs/persona/dist/codegen.js
63502
+ var S = "3.34.1";
60288
63503
  var c = S;
60289
63504
  function u(e) {
60290
63505
  if (e !== void 0) return typeof e == "string" ? e : Array.isArray(e) ? `[${e.map((r) => r.toString()).join(", ")}]` : e.toString();