@runtypelabs/cli 2.19.0 → 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 +3525 -63
  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-3V2W6XMX.mjs
15167
+ // ../shared/dist/chunk-7Y2SRVP7.mjs
15168
15168
  function getNestedValue(obj, path18) {
15169
15169
  let normalizedPath = path18;
15170
15170
  normalizedPath = normalizedPath.replace(/^\$\.?/, "");
@@ -15200,6 +15200,63 @@ function getNestedValue(obj, path18) {
15200
15200
  return current;
15201
15201
  }
15202
15202
  var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
15203
+ var SYSTEM_VARIABLES = /* @__PURE__ */ new Set([
15204
+ "_flow",
15205
+ "_user",
15206
+ "_execution",
15207
+ "_record",
15208
+ "_now",
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",
15218
+ "messages",
15219
+ "userMessage",
15220
+ "lastMessage",
15221
+ "messageCount"
15222
+ ]);
15223
+ var SECRET_REF_PATTERN = /\{\{secret:([A-Z][A-Z0-9_]*[A-Z0-9])\}\}/g;
15224
+ var RUNTIME_PREFIXES = {
15225
+ "secret:": {
15226
+ prefix: "secret:",
15227
+ namespace: "secret",
15228
+ resolvedBy: "the secret pre-pass (substituteSecretReferences) before the template engine runs \u2014 never the template engine itself",
15229
+ mayReachModelUnresolved: false
15230
+ },
15231
+ "flow:": {
15232
+ prefix: "flow:",
15233
+ namespace: "flow",
15234
+ resolvedBy: "the template engine, which treats it as an alias for the bare flow variable of the same name",
15235
+ mayReachModelUnresolved: false
15236
+ }
15237
+ };
15238
+ var PREFIX_PATTERN = /^([A-Za-z][A-Za-z0-9_-]*):(.*)$/s;
15239
+ function classifyVariableReference(token) {
15240
+ const trimmed = token.trim();
15241
+ const prefixMatch = PREFIX_PATTERN.exec(trimmed);
15242
+ if (prefixMatch) {
15243
+ const prefix = `${prefixMatch[1]}:`;
15244
+ const rest = prefixMatch[2] ?? "";
15245
+ const spec = RUNTIME_PREFIXES[prefix];
15246
+ if (spec) {
15247
+ return { namespace: spec.namespace, baseName: rest.trim() };
15248
+ }
15249
+ return { namespace: "unknown", raw: trimmed };
15250
+ }
15251
+ if (isSystemVariable(trimmed)) {
15252
+ return { namespace: "system", baseName: trimmed };
15253
+ }
15254
+ return { namespace: "plain", baseName: trimmed };
15255
+ }
15256
+ function isSystemVariable(varName) {
15257
+ const rootSegment = varName.split(".")[0] || "";
15258
+ return SYSTEM_VARIABLES.has(rootSegment);
15259
+ }
15203
15260
  var TEMPLATE_EXPRESSION_PATTERN = /\{\{([^{}]+)\}\}/g;
15204
15261
  function parseTemplateExpression(expr) {
15205
15262
  const tokens = tokenizeFallbackExpression(expr);
@@ -15286,7 +15343,7 @@ function parseOperand(raw) {
15286
15343
  }
15287
15344
  function evaluateOperand(operand, context) {
15288
15345
  if (operand.kind === "literal") return operand.value;
15289
- return getNestedValue(context, operand.path);
15346
+ return getNestedValue(context, classifiedLookupKey(operand.path));
15290
15347
  }
15291
15348
  function countTrailingBackslashes(s, i) {
15292
15349
  let n = 0;
@@ -15306,11 +15363,24 @@ function stringifyValue(value) {
15306
15363
  if (typeof value === "object") return JSON.stringify(value);
15307
15364
  return String(value);
15308
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
+ }
15309
15378
  var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
15310
15379
  substitute(template, context = {}) {
15311
15380
  const usedVariables = [];
15312
15381
  const usedDefaults = [];
15313
15382
  const missingVariables = [];
15383
+ const unknownNamespaceVariables = [];
15314
15384
  const result = template.replace(_SimpleTemplateEngine2.EXPRESSION_PATTERN, (match, expr) => {
15315
15385
  let parsed;
15316
15386
  try {
@@ -15323,12 +15393,14 @@ var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
15323
15393
  usedVariables,
15324
15394
  usedDefaults,
15325
15395
  missingVariables,
15396
+ unknownNamespaceVariables,
15326
15397
  match
15327
15398
  });
15328
15399
  }
15329
15400
  return resolveFallback(parsed, context, {
15330
15401
  usedVariables,
15331
15402
  missingVariables,
15403
+ unknownNamespaceVariables,
15332
15404
  match
15333
15405
  });
15334
15406
  });
@@ -15336,7 +15408,8 @@ var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
15336
15408
  result,
15337
15409
  usedVariables,
15338
15410
  usedDefaults,
15339
- missingVariables
15411
+ missingVariables,
15412
+ unknownNamespaceVariables
15340
15413
  };
15341
15414
  }
15342
15415
  /**
@@ -15411,28 +15484,49 @@ var _SimpleTemplateEngine = class _SimpleTemplateEngine2 {
15411
15484
  };
15412
15485
  _SimpleTemplateEngine.EXPRESSION_PATTERN = TEMPLATE_EXPRESSION_PATTERN;
15413
15486
  var SimpleTemplateEngine = _SimpleTemplateEngine;
15487
+ function classifiedLookupKey(rawKey, onUnknown) {
15488
+ const classification = classifyVariableReference(rawKey);
15489
+ if (classification.namespace === "flow") {
15490
+ return classification.baseName;
15491
+ }
15492
+ if (classification.namespace === "unknown") {
15493
+ onUnknown?.(classification.raw);
15494
+ return rawKey;
15495
+ }
15496
+ return rawKey;
15497
+ }
15414
15498
  function resolveLegacy(parsed, context, tracking) {
15415
- const value = getNestedValue(context, parsed.variable);
15499
+ const lookupKey = classifiedLookupKey(
15500
+ parsed.variable,
15501
+ (raw) => tracking.unknownNamespaceVariables.push(raw)
15502
+ );
15503
+ const value = getNestedValue(context, lookupKey);
15416
15504
  if (value !== void 0 && value !== null) {
15417
- tracking.usedVariables.push(parsed.variable);
15505
+ tracking.usedVariables.push(lookupKey);
15418
15506
  return stringifyValue(value);
15419
15507
  }
15420
15508
  if (parsed.defaultValue !== void 0) {
15421
15509
  tracking.usedDefaults.push({
15422
- variable: parsed.variable,
15510
+ variable: lookupKey,
15423
15511
  defaultValue: parsed.defaultValue
15424
15512
  });
15425
15513
  return parsed.defaultValue;
15426
15514
  }
15427
- tracking.missingVariables.push(parsed.variable);
15515
+ tracking.missingVariables.push(lookupKey);
15428
15516
  return tracking.match;
15429
15517
  }
15430
15518
  function resolveFallback(parsed, context, tracking) {
15431
15519
  let chosen = null;
15432
15520
  for (const operand of parsed.operands) {
15433
15521
  const value = evaluateOperand(operand, context);
15434
- if (operand.kind === "path" && value !== void 0) {
15435
- tracking.usedVariables.push(operand.path);
15522
+ if (operand.kind === "path") {
15523
+ const key = classifiedLookupKey(
15524
+ operand.path,
15525
+ (raw) => tracking.unknownNamespaceVariables.push(raw)
15526
+ );
15527
+ if (value !== void 0) {
15528
+ tracking.usedVariables.push(key);
15529
+ }
15436
15530
  }
15437
15531
  if (chosen === null && passesOperator(value, parsed.operator)) {
15438
15532
  chosen = { value, isPath: operand.kind === "path" };
@@ -15444,13 +15538,18 @@ function resolveFallback(parsed, context, tracking) {
15444
15538
  return stringifyValue(last.value);
15445
15539
  }
15446
15540
  for (const operand of parsed.operands) {
15447
- if (operand.kind === "path") tracking.missingVariables.push(operand.path);
15541
+ if (operand.kind === "path") {
15542
+ tracking.missingVariables.push(classifiedLookupKey(operand.path));
15543
+ }
15448
15544
  }
15449
15545
  return tracking.match;
15450
15546
  }
15451
15547
  var templateEngine = new SimpleTemplateEngine();
15452
15548
 
15453
15549
  // ../shared/dist/index.mjs
15550
+ function neutralizeCsvFormula(value) {
15551
+ return /^[=+\-@\t\r\n]/.test(value) ? `'${value}` : value;
15552
+ }
15454
15553
  var mediaAnnotationsSchema = external_exports.object({
15455
15554
  audience: external_exports.array(external_exports.enum(["user", "assistant"])).optional()
15456
15555
  });
@@ -15907,7 +16006,15 @@ var stepCompleteEventSchema = external_exports.object({
15907
16006
  stopReason: wireStopReasonSchema.optional(),
15908
16007
  stepId: external_exports.string().optional(),
15909
16008
  stepName: external_exports.string().optional(),
15910
- 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()
15911
16018
  });
15912
16019
  var stepErrorEventSchema = external_exports.object({
15913
16020
  ...baseFlowEvent,
@@ -16362,6 +16469,79 @@ var ExecuteToolSchema = external_exports.object({
16362
16469
  userId: external_exports.string()
16363
16470
  }).optional()
16364
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
+ }
16365
16545
  var contextFallbackSchema = external_exports.union([
16366
16546
  external_exports.object({ type: external_exports.literal("retry"), delay: external_exports.number().optional() }),
16367
16547
  external_exports.object({
@@ -17168,6 +17348,1923 @@ var CONTEXT_STEP_TYPES = [
17168
17348
  "memory-summary"
17169
17349
  ];
17170
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
+ }
17171
19268
  var flowStepValidationSchema = external_exports.object({
17172
19269
  // Optional stable client-supplied identifier. Preserved across saves so that
17173
19270
  // `flow_step_results.stepId` references stay valid and dashboard UI state
@@ -17227,6 +19324,1102 @@ var KNOWN_TOOL_KEYS = /* @__PURE__ */ new Set([
17227
19324
  ...Object.keys(CAMEL_CASE_TOOL_KEYS),
17228
19325
  ...Object.keys(SNAKE_CASE_TOOL_KEYS)
17229
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
+ }
17230
20423
  var SERIALIZED_HELPERS_SOURCE = `
17231
20424
  // Transform helper functions (from packages/shared/src/transform-helpers.ts)
17232
20425
  const helpers = (function createHelpers() {
@@ -30449,7 +33642,7 @@ var CORE_BUILTIN_TOOLS_REGISTRY = [
30449
33642
  {
30450
33643
  id: "publish_page",
30451
33644
  name: "Publish Page",
30452
- description: "Publish an HTML page on Runtype's CDN and get back a shareable URL that renders the page inline in the browser. Two source modes: (1) pass `url` to download an HTML file from an HTTP(S) URL, or (2) pass base64-encoded `content` (defaults to `contentType: text/html`) to upload inline HTML directly \u2014 useful when running inside a sandboxed code-execution environment with restricted outbound network. Exactly one of `url` or `content` must be provided. Served inline from a `/preview/` path under a locked-down CSP that blocks scripts, network requests, and form submissions. Page URLs are public and expire after 7 days. Accepts only HTML content. 25 MB max. To host a non-HTML file, or HTML as a permanent downloadable file, use `store_asset` instead.",
33645
+ description: "Publish an HTML page on Runtype's CDN and get back a shareable URL that renders the page inline in the browser. Two source modes: (1) pass `url` to download an HTML file from an HTTP(S) URL, or (2) pass base64-encoded `content` (defaults to `contentType: text/html`) to upload inline HTML directly \u2014 useful when running inside a sandboxed code-execution environment with restricted outbound network. Exactly one of `url` or `content` must be provided. Served inline from a `/preview/` path under a locked-down CSP that blocks scripts, network requests, and form submissions. Page URLs are public and expire based on the account's plan (7 days on the default plan; longer or permanent on higher tiers \u2014 check `expiresAt` in the result). Pass `expiresInSeconds` to choose a shorter lifetime; the plan TTL is a hard ceiling. A page can be re-upped to the current plan TTL at the same URL via `POST /v1/assets/:assetId/extend`. Accepts only HTML content. 25 MB max. To host a non-HTML file, or HTML as a permanent downloadable file, use `store_asset` instead.",
30453
33646
  category: BuiltInToolCategory.FILE_OPERATIONS,
30454
33647
  toolGroup: BuiltInToolGroup.FILE_OUTPUTS,
30455
33648
  providers: [BuiltInToolProvider.MULTI],
@@ -30471,6 +33664,10 @@ var CORE_BUILTIN_TOOLS_REGISTRY = [
30471
33664
  filename: {
30472
33665
  type: "string",
30473
33666
  description: "Optional filename for the stored page"
33667
+ },
33668
+ expiresInSeconds: {
33669
+ type: "number",
33670
+ description: "Optional page lifetime in seconds (positive integer). Capped at the account plan's preview TTL \u2014 a shorter lifetime is honored, a longer one is clamped to the plan ceiling. Omit to use the plan default."
30474
33671
  }
30475
33672
  },
30476
33673
  required: []
@@ -33524,7 +36721,11 @@ var userProfileFeaturesSchema = external_exports.object({
33524
36721
  // Gates the chrome_extension surface type in the dashboard (surface picker
33525
36722
  // and downstream config/ship UI). Driven by the `CHROME_SURFACE` boolean
33526
36723
  // flag.
33527
- enableChromeSurface: external_exports.boolean()
36724
+ enableChromeSurface: external_exports.boolean(),
36725
+ // Gates the Runtype Apps nav entry + routes in the dashboard. Driven by the
36726
+ // `enable-runtype-apps` boolean flag (fail-closed in production until the
36727
+ // prod ops set lands). The whole /v1/apps surface 404s when this is off.
36728
+ enableRuntypeApps: external_exports.boolean()
33528
36729
  });
33529
36730
  var MODEL_FAMILY_PROVIDER_IDS = {
33530
36731
  "claude-fable-5": {
@@ -36160,7 +39361,6 @@ var agentRuntimeConfigSchema = external_exports.object({
36160
39361
  // mirroring how `temporalConfigSchema` is shared.
36161
39362
  memory: memoryConfigSchema.optional()
36162
39363
  });
36163
- var SECRET_REF_PATTERN = /\{\{secret:([A-Z][A-Z0-9_]*[A-Z0-9])\}\}/g;
36164
39364
  function extractSecretReferences(template) {
36165
39365
  const keys = /* @__PURE__ */ new Set();
36166
39366
  let match;
@@ -36651,6 +39851,7 @@ function mergeResults(...results) {
36651
39851
  merged.valid = merged.errors.length === 0;
36652
39852
  return merged;
36653
39853
  }
39854
+ var NAMESPACE_VARIABLE_CODES = /* @__PURE__ */ new Set(["UNDECLARED_VARIABLE_REFERENCE", "UNKNOWN_VARIABLE_NAMESPACE"]);
36654
39855
  function validateFlowDefinition(flow, capIndex, context) {
36655
39856
  const result = emptyResult();
36656
39857
  const base = `capabilities[${capIndex}].flow`;
@@ -36711,8 +39912,25 @@ function validateFlowDefinition(flow, capIndex, context) {
36711
39912
  }
36712
39913
  }
36713
39914
  }
39915
+ appendNamespaceVariableIssues(flow, base, result);
36714
39916
  return finalize2(result);
36715
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
+ }
36716
39934
  function finalize2(r) {
36717
39935
  r.valid = r.errors.length === 0;
36718
39936
  return r;
@@ -37340,8 +40558,10 @@ var fullProductObjectTemplateSchema = external_exports.object({
37340
40558
  });
37341
40559
  }
37342
40560
  });
37343
- var FLOW_PREFIX = "flow:";
37344
- 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;
37345
40565
  function collectStringLeafPaths(value, path18 = []) {
37346
40566
  if (typeof value === "string") {
37347
40567
  return [{ path: path18, value }];
@@ -37372,12 +40592,16 @@ function extractTemplateReferences(value) {
37372
40592
  const inner = value.slice(start + 2, end);
37373
40593
  const separatorIndex = inner.indexOf("|");
37374
40594
  const key = (separatorIndex === -1 ? inner : inner.slice(0, separatorIndex)).trim();
37375
- if (key.length > 0 && !key.startsWith(SECRET_PREFIX) && !key.startsWith(FLOW_PREFIX)) {
37376
- references.push({
37377
- key,
37378
- defaultValue: separatorIndex === -1 ? void 0 : inner.slice(separatorIndex + 1).trim(),
37379
- raw
37380
- });
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
+ }
37381
40605
  }
37382
40606
  cursor = end + 2;
37383
40607
  }
@@ -41126,6 +44350,131 @@ recordsCommand.command("get <id>").description("Get record details").option("--j
41126
44350
  const { waitUntilExit } = render3(React3.createElement(App));
41127
44351
  await waitUntilExit();
41128
44352
  });
44353
+ recordsCommand.command("results <id>").description("Get step-level execution results for a record").option("--flow-id <flowId>", "Filter by flow ID").option("--batch-id <batchId>", "Filter by batch ID").option("--status <status>", "Filter by status").option("--limit <n>", "Limit number of results").option("--offset <n>", "Offset for pagination").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(
44354
+ async (id, options) => {
44355
+ const apiKey = await ensureAuth();
44356
+ if (!apiKey) return;
44357
+ const client = createCliClient(apiKey);
44358
+ const params = {
44359
+ ...options.flowId ? { flowId: options.flowId } : {},
44360
+ ...options.batchId ? { batchId: options.batchId } : {},
44361
+ ...options.status ? { status: options.status } : {},
44362
+ ...options.limit ? { limit: parseInt(options.limit, 10) } : {},
44363
+ ...options.offset ? { offset: parseInt(options.offset, 10) } : {}
44364
+ };
44365
+ if (!isTTY(options) || options.json) {
44366
+ try {
44367
+ const data = await client.records.getStepResults(id, params);
44368
+ if (options.json) {
44369
+ printJson(data);
44370
+ return;
44371
+ }
44372
+ const results = data.data ?? [];
44373
+ if (results.length === 0) {
44374
+ console.log(chalk6.yellow("No step results found"));
44375
+ return;
44376
+ }
44377
+ for (const r of results) {
44378
+ console.log(
44379
+ ` ${chalk6.green(r.id)} ${r.stepName} (${r.stepType}) ${r.status}` + (r.modelUsed ? ` ${r.modelUsed}` : "")
44380
+ );
44381
+ }
44382
+ } catch (error51) {
44383
+ const message = error51 instanceof Error ? error51.message : "Unknown error";
44384
+ console.error(chalk6.red(`Failed to fetch step results: ${message}`));
44385
+ process.exit(1);
44386
+ }
44387
+ return;
44388
+ }
44389
+ const App = () => {
44390
+ const [items, setItems] = useState4(null);
44391
+ const [error51, setError] = useState4(null);
44392
+ useEffect5(() => {
44393
+ client.records.getStepResults(id, params).then((res) => setItems(res.data ?? [])).catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
44394
+ }, []);
44395
+ return React3.createElement(DataList, {
44396
+ title: "Step results",
44397
+ items,
44398
+ error: error51,
44399
+ loading: items === null && error51 === null,
44400
+ renderCard: (item) => {
44401
+ const r = item;
44402
+ return React3.createElement(EntityCard, {
44403
+ fields: [
44404
+ { label: "ID", value: r.id, color: "green" },
44405
+ { label: "Step", value: `${r.stepName} (${r.stepType})` },
44406
+ { label: "Status", value: r.status },
44407
+ { label: "Model", value: r.modelUsed ?? null },
44408
+ {
44409
+ label: "Duration",
44410
+ value: r.durationMs !== null ? `${r.durationMs}ms` : null
44411
+ }
44412
+ ]
44413
+ });
44414
+ }
44415
+ });
44416
+ };
44417
+ const { waitUntilExit } = render3(React3.createElement(App));
44418
+ await waitUntilExit();
44419
+ }
44420
+ );
44421
+ recordsCommand.command("costs <id>").description("Get aggregated cost breakdown for a record").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (id, options) => {
44422
+ const apiKey = await ensureAuth();
44423
+ if (!apiKey) return;
44424
+ const client = createCliClient(apiKey);
44425
+ if (!isTTY(options) || options.json) {
44426
+ try {
44427
+ const data = await client.records.getCosts(id);
44428
+ if (options.json) {
44429
+ printJson(data);
44430
+ return;
44431
+ }
44432
+ console.log(` Total cost: $${data.totalCost}`);
44433
+ console.log(` Total tokens: ${data.totalTokens}`);
44434
+ console.log(` Executions: ${data.executionCount}`);
44435
+ if (data.modelBreakdown.length > 0) {
44436
+ console.log(" By model:");
44437
+ for (const m2 of data.modelBreakdown) {
44438
+ console.log(` ${m2.model}: $${m2.cost} ${m2.tokens} tokens ${m2.count} calls`);
44439
+ }
44440
+ }
44441
+ } catch (error51) {
44442
+ const message = error51 instanceof Error ? error51.message : "Unknown error";
44443
+ console.error(chalk6.red(`Failed to fetch record costs: ${message}`));
44444
+ process.exit(1);
44445
+ }
44446
+ return;
44447
+ }
44448
+ const App = () => {
44449
+ const [items, setItems] = useState4(null);
44450
+ const [error51, setError] = useState4(null);
44451
+ useEffect5(() => {
44452
+ client.records.getCosts(id).then((res) => setItems([res])).catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
44453
+ }, []);
44454
+ return React3.createElement(DataList, {
44455
+ title: "Record costs",
44456
+ items,
44457
+ error: error51,
44458
+ loading: items === null && error51 === null,
44459
+ renderCard: (item) => {
44460
+ const c2 = item;
44461
+ return React3.createElement(EntityCard, {
44462
+ fields: [
44463
+ { label: "Total cost", value: `$${c2.totalCost}`, color: "green" },
44464
+ { label: "Total tokens", value: String(c2.totalTokens) },
44465
+ { label: "Executions", value: String(c2.executionCount) },
44466
+ {
44467
+ label: "Models",
44468
+ value: c2.modelBreakdown.map((m2) => `${m2.model} ($${m2.cost})`).join(", ") || null
44469
+ }
44470
+ ]
44471
+ });
44472
+ }
44473
+ });
44474
+ };
44475
+ const { waitUntilExit } = render3(React3.createElement(App));
44476
+ await waitUntilExit();
44477
+ });
41129
44478
  recordsCommand.command("create").description("Create a new record").requiredOption("-n, --name <name>", "Record name").requiredOption("-t, --type <type>", "Record type").option("-m, --metadata <json>", "Metadata as JSON string").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(
41130
44479
  async (options) => {
41131
44480
  const apiKey = await ensureAuth();
@@ -41533,10 +44882,11 @@ recordsCommand.command("export").description("Export records to a file").option(
41533
44882
  }
41534
44883
  });
41535
44884
  function csvEscape(value) {
41536
- if (value.includes(",") || value.includes('"') || value.includes("\n")) {
41537
- return `"${value.replace(/"/g, '""')}"`;
44885
+ const text = neutralizeCsvFormula(value);
44886
+ if (text.includes(",") || text.includes('"') || text.includes("\n")) {
44887
+ return `"${text.replace(/"/g, '""')}"`;
41538
44888
  }
41539
- return value;
44889
+ return text;
41540
44890
  }
41541
44891
 
41542
44892
  // src/commands/prompts.ts
@@ -44068,26 +47418,26 @@ async function getCurrentAccountId() {
44068
47418
 
44069
47419
  // src/lib/quick-start-api.ts
44070
47420
  import { RuntypeApiError as RuntypeApiError2 } from "@runtypelabs/sdk";
44071
- function isObjectRecord(value) {
47421
+ function isObjectRecord2(value) {
44072
47422
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
44073
47423
  }
44074
47424
  function isQuickStartValidationResponse(value) {
44075
- if (!isObjectRecord(value) || typeof value.valid !== "boolean") {
47425
+ if (!isObjectRecord2(value) || typeof value.valid !== "boolean") {
44076
47426
  return false;
44077
47427
  }
44078
47428
  if (value.valid === false) {
44079
47429
  return typeof value.error === "string" && typeof value.code === "string";
44080
47430
  }
44081
- return typeof value.templateId === "string" && isObjectRecord(value.agentCard);
47431
+ return typeof value.templateId === "string" && isObjectRecord2(value.agentCard);
44082
47432
  }
44083
47433
  function isQuickStartCreateResponse(value) {
44084
- if (!isObjectRecord(value) || typeof value.success !== "boolean") {
47434
+ if (!isObjectRecord2(value) || typeof value.success !== "boolean") {
44085
47435
  return false;
44086
47436
  }
44087
47437
  if (value.success === false) {
44088
47438
  return typeof value.error === "string" && typeof value.code === "string";
44089
47439
  }
44090
- 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";
44091
47441
  }
44092
47442
  function getApiErrorData(error51) {
44093
47443
  return error51 instanceof RuntypeApiError2 ? error51.data : void 0;
@@ -48903,29 +52253,40 @@ function primeTreeLogSyncFromState(stateFilePath2, log, state) {
48903
52253
  lastCheckpointJson: JSON.stringify(toCheckpoint(state))
48904
52254
  });
48905
52255
  }
52256
+ function ensureTreeLogSync(stateFilePath2, seed) {
52257
+ const logPath = treeLogPathForStateFile(stateFilePath2);
52258
+ let sync = syncStates.get(stateFilePath2);
52259
+ if (!sync || sync.log.filePath !== logPath) {
52260
+ const existing = loadTreeLog(logPath);
52261
+ if (existing) {
52262
+ const materialized = materializeAtHead(existing);
52263
+ sync = {
52264
+ log: existing,
52265
+ lastMessages: materialized?.messages ?? [],
52266
+ lastCheckpointJson: JSON.stringify(materialized?.state ?? null)
52267
+ };
52268
+ } else {
52269
+ const log = createTreeLog(logPath, {
52270
+ taskName: seed.taskName,
52271
+ agentId: seed.agentId,
52272
+ ...seed.originalMessage ? { originalMessage: seed.originalMessage } : {}
52273
+ });
52274
+ sync = { log, lastMessages: [], lastCheckpointJson: "null" };
52275
+ }
52276
+ syncStates.set(stateFilePath2, sync);
52277
+ }
52278
+ return sync;
52279
+ }
52280
+ function getOrLoadTreeLogSync(stateFilePath2, seed) {
52281
+ return ensureTreeLogSync(stateFilePath2, seed).log;
52282
+ }
48906
52283
  function syncTreeLogWithState(stateFilePath2, state) {
48907
52284
  try {
48908
- const logPath = treeLogPathForStateFile(stateFilePath2);
48909
- let sync = syncStates.get(stateFilePath2);
48910
- if (!sync || sync.log.filePath !== logPath) {
48911
- const existing = loadTreeLog(logPath);
48912
- if (existing) {
48913
- const materialized = materializeAtHead(existing);
48914
- sync = {
48915
- log: existing,
48916
- lastMessages: materialized?.messages ?? [],
48917
- lastCheckpointJson: JSON.stringify(materialized?.state ?? null)
48918
- };
48919
- } else {
48920
- const log = createTreeLog(logPath, {
48921
- taskName: state.taskName,
48922
- agentId: state.agentId,
48923
- ...state.originalMessage ? { originalMessage: state.originalMessage } : {}
48924
- });
48925
- sync = { log, lastMessages: [], lastCheckpointJson: "null" };
48926
- }
48927
- syncStates.set(stateFilePath2, sync);
48928
- }
52285
+ const sync = ensureTreeLogSync(stateFilePath2, {
52286
+ taskName: state.taskName,
52287
+ agentId: state.agentId,
52288
+ ...state.originalMessage ? { originalMessage: state.originalMessage } : {}
52289
+ });
48929
52290
  const nextMessages = state.messages ?? sync.lastMessages;
48930
52291
  const messagesDelta = computeMessagesDelta(sync.lastMessages, nextMessages);
48931
52292
  const checkpoint = toCheckpoint(state);
@@ -55472,9 +58833,8 @@ function stateFilePathForTask(taskName, stateDir) {
55472
58833
  }
55473
58834
  function recordOffloadedArtifact(details) {
55474
58835
  const stateFilePath2 = details.options.ledger?.stateFilePath || stateFilePathForTask(details.taskName, details.stateDir);
55475
- const logPath = treeLogPathForStateFile(stateFilePath2);
55476
58836
  try {
55477
- const log = loadTreeLog(logPath) || createTreeLog(logPath, {
58837
+ const log = getOrLoadTreeLogSync(stateFilePath2, {
55478
58838
  taskName: details.taskName,
55479
58839
  agentId: details.options.ledger?.agentId || "unknown",
55480
58840
  ...details.options.ledger?.originalMessage ? { originalMessage: details.options.ledger.originalMessage } : {}
@@ -56101,6 +59461,11 @@ function buildResumeHistoryWarning(state) {
56101
59461
  function canUseMarathonStartupShell(options) {
56102
59462
  return process.stdin.isTTY === true && process.stdout.isTTY === true && !options.json;
56103
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
+ }
56104
59469
  function normalizeStartupModelOptionValue(value) {
56105
59470
  const trimmed = value?.trim().toLowerCase().replace(/^model\//, "") ?? "";
56106
59471
  if (!trimmed) return "";
@@ -56681,6 +60046,18 @@ async function taskAction(agent, options) {
56681
60046
  const sandboxWorkflowSelection = playbookWorkflow ? void 0 : resolveSandboxWorkflowSelection(baseMessage, parsedSandbox, resumeState);
56682
60047
  parsedSandbox = sandboxWorkflowSelection?.sandboxProvider ?? parsedSandbox;
56683
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
+ }
56684
60061
  const DEFAULT_MILESTONE_NAMES = ["research", "planning", "execution"];
56685
60062
  const EXTERNAL_MILESTONE_NAMES = ["research", "report"];
56686
60063
  const detectedVariant = resumeState?.workflowVariant ?? defaultWorkflow.classifyVariant?.(baseMessage);
@@ -56803,6 +60180,30 @@ ${rulesContext}`;
56803
60180
  return tools;
56804
60181
  };
56805
60182
  localTools = applyOffloadWrapping(localTools);
60183
+ const ledgerOffloadRecorder = offloadOptions ? (details) => {
60184
+ const result = offloadToolOutput(
60185
+ taskName,
60186
+ details.toolName,
60187
+ details.content,
60188
+ {
60189
+ ...offloadOptions,
60190
+ threshold: 0,
60191
+ ledger: { stateFilePath: filePath, agentId, originalMessage: baseMessage },
60192
+ onEvent: (event) => {
60193
+ if (event.kind !== "offloaded") return;
60194
+ reportContextNotice({
60195
+ kind: "tool_output_offloaded",
60196
+ message: `${event.toolName} returned ${Math.ceil(event.outputLength / 4).toLocaleString()} estimated tokens and was offloaded to the context ledger to protect the context window.`,
60197
+ toolName: event.toolName,
60198
+ outputLength: event.outputLength,
60199
+ filePath: event.filePath
60200
+ });
60201
+ }
60202
+ },
60203
+ options.stateDir
60204
+ );
60205
+ return result.offloaded ? { reference: result.content } : void 0;
60206
+ } : void 0;
56806
60207
  let toolsEnabled = true;
56807
60208
  const checkpointHasConfigChanges = (result) => Boolean(result.model) || result.tools === true || result.sandbox !== void 0;
56808
60209
  const rebuildCheckpointTools = () => applyOffloadWrapping(
@@ -56992,6 +60393,11 @@ Saving state... done. Session saved to ${filePath}`);
56992
60393
  let accumulatedCost = 0;
56993
60394
  let accumulatedTokens = { input: 0, output: 0 };
56994
60395
  let accumulatedToolCalls = 0;
60396
+ let indexedChunks = 0;
60397
+ let indexedBytes = 0;
60398
+ let indexingFailures = 0;
60399
+ let indexingFailureNoticed = false;
60400
+ const indexingRequests = [];
56995
60401
  let lastResult = null;
56996
60402
  let lastSessionMessages = [];
56997
60403
  let undeliveredSteering = [];
@@ -57053,6 +60459,7 @@ Saving state... done. Session saved to ${filePath}`);
57053
60459
  stream: true,
57054
60460
  streamCallbacks: currentStreamCallbacks,
57055
60461
  localTools,
60462
+ ...ledgerOffloadRecorder ? { offloadRecorder: ledgerOffloadRecorder } : {},
57056
60463
  trackProgress: options.track ? taskName : void 0,
57057
60464
  // Mid-run steering queue (Enter while streaming): the UI owns the
57058
60465
  // queue; the SDK drains it at session boundaries and ends in-flight
@@ -57162,12 +60569,35 @@ Saving state... done. Session saved to ${filePath}`);
57162
60569
  });
57163
60570
  if (chunks.length > 0) {
57164
60571
  const sessionIdx = currentSessionOffset + state.sessionCount - 1;
57165
- 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", {
57166
60586
  taskName,
57167
60587
  sessionIndex: sessionIdx,
57168
60588
  chunks
57169
- }).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
+ }
57170
60599
  });
60600
+ indexingRequests.push(indexingRequest);
57171
60601
  }
57172
60602
  }
57173
60603
  }
@@ -57481,11 +60911,26 @@ Saving state... done. Session saved to ${filePath}`);
57481
60911
  saveState(filePath, finalState, { stripSnapshotEvents: !!eventLogWriter });
57482
60912
  await waitForUiExit?.();
57483
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
+ }
57484
60924
  console.log();
57485
60925
  const statusColor = result.status === "complete" ? chalk23.green : result.status === "budget_exceeded" || result.status === "error" ? chalk23.red : chalk23.yellow;
57486
60926
  console.log(`Status: ${statusColor(result.status)}`);
57487
60927
  console.log(`Sessions: ${finalState.sessionCount}`);
57488
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
+ }
57489
60934
  console.log(`State: ${chalk23.gray(filePath)}`);
57490
60935
  if (typeof finalState.lastError === "string" && finalState.lastError.trim()) {
57491
60936
  console.log(`Last error: ${chalk23.red(finalState.lastError)}`);
@@ -57641,7 +61086,20 @@ ${details}`);
57641
61086
  }
57642
61087
  return resolved;
57643
61088
  }
57644
- 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) {
57645
61103
  if (resumeState?.workflowVariant === "game") return gameWorkflow;
57646
61104
  if (resumeState?.workflowPhase === "design" || resumeState?.workflowPhase === "build" || resumeState?.workflowPhase === "verify") {
57647
61105
  return gameWorkflow;
@@ -57650,10 +61108,14 @@ function detectDeployWorkflow(_message, _sandboxProvider, resumeState) {
57650
61108
  if (resumeState?.workflowPhase === "scaffold" || resumeState?.workflowPhase === "deploy") {
57651
61109
  return deployWorkflow;
57652
61110
  }
61111
+ if (isDeployCapableSandbox(sandboxProvider)) {
61112
+ if (isGameIntent(message)) return gameWorkflow;
61113
+ if (isDeployIntent(message)) return deployWorkflow;
61114
+ }
57653
61115
  return void 0;
57654
61116
  }
57655
61117
  function resolveSandboxWorkflowSelection(message, sandboxProvider, resumeState) {
57656
- if (sandboxProvider && sandboxProvider !== "daytona") {
61118
+ if (sandboxProvider && !isDeployCapableSandbox(sandboxProvider)) {
57657
61119
  return {
57658
61120
  workflow: void 0,
57659
61121
  sandboxProvider
@@ -60036,9 +63498,9 @@ import { execFileSync } from "child_process";
60036
63498
  // src/lib/persona-init.ts
60037
63499
  init_credential_store();
60038
63500
 
60039
- // ../../node_modules/.pnpm/@runtypelabs+persona@3.31.0/node_modules/@runtypelabs/persona/dist/codegen.js
60040
- var S = { name: "@runtypelabs/persona", version: "3.31.0", description: "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.", type: "module", main: "dist/index.cjs", module: "dist/index.js", types: "dist/index.d.ts", exports: { ".": { types: "./dist/index.d.ts", import: "./dist/index.js", require: "./dist/index.cjs" }, "./theme-reference": { types: "./dist/theme-reference.d.ts", import: "./dist/theme-reference.js", require: "./dist/theme-reference.cjs" }, "./codegen": { types: "./dist/codegen.d.ts", import: "./dist/codegen.js", require: "./dist/codegen.cjs" }, "./theme-editor": { types: "./dist/theme-editor.d.ts", import: "./dist/theme-editor.js", require: "./dist/theme-editor.cjs" }, "./testing": { types: "./dist/testing.d.ts", import: "./dist/testing.js", require: "./dist/testing.cjs" }, "./smart-dom-reader": { types: "./dist/smart-dom-reader.d.ts", import: "./dist/smart-dom-reader.js", require: "./dist/smart-dom-reader.cjs" }, "./plugin-kit": { types: "./dist/plugin-kit.d.ts", import: "./dist/plugin-kit.js", require: "./dist/plugin-kit.cjs" }, "./animations/glyph-cycle": { types: "./dist/animations/glyph-cycle.d.ts", import: "./dist/animations/glyph-cycle.js", require: "./dist/animations/glyph-cycle.cjs" }, "./animations/wipe": { types: "./dist/animations/wipe.d.ts", import: "./dist/animations/wipe.js", require: "./dist/animations/wipe.cjs" }, "./widget.css": "./dist/widget.css" }, files: ["dist", "src"], scripts: { build: "rimraf dist && pnpm run build:styles && pnpm run build:client && pnpm run build:installer && pnpm run build:launcher && pnpm run build:theme-ref && pnpm run build:codegen && pnpm run build:theme-editor && pnpm run build:testing && pnpm run build:smart-dom-reader && pnpm run build:plugin-kit && pnpm run build:animations", "build:plugin-kit": "tsup src/plugin-kit.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting", "build:theme-editor": "tsup src/theme-editor.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting", "build:testing": "tsup src/testing.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting", "build:smart-dom-reader": "tsup src/smart-dom-reader.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting", "build:animations": "tsup src/animations/glyph-cycle.ts src/animations/wipe.ts --format esm,cjs --minify --dts --out-dir dist/animations --no-splitting", "build:theme-ref": "tsup src/theme-reference.ts --format esm,cjs --minify --dts", "build:codegen": "tsup src/codegen.ts --format esm,cjs --minify --dts", "build:styles": `node -e "const fs=require('fs');fs.mkdirSync('dist',{recursive:true});fs.copyFileSync('src/styles/widget.css','dist/widget.css');"`, "build:client": `tsup src/index.ts --format esm,cjs --minify --sourcemap --splitting false --dts --loader ".css=text" && tsup src/index-global.ts --format iife --global-name AgentWidget --minify --sourcemap --splitting false --out-dir dist --loader ".css=text" && node -e "const fs=require('fs');for(const ext of ['.global.js','.global.js.map']){const from='dist/index-global'+ext;if(fs.existsSync(from))fs.renameSync(from,'dist/index'+ext);}"`, "build:installer": "tsup src/install.ts --format iife --global-name SiteAgentInstaller --out-dir dist --minify --sourcemap --no-splitting", "build:launcher": `tsup src/launcher-global.ts --format iife --global-name AgentWidgetLauncher --minify --sourcemap --splitting false --out-dir dist && node -e "const fs=require('fs');for(const ext of ['.global.js','.global.js.map']){const from='dist/launcher-global'+ext;if(fs.existsSync(from))fs.renameSync(from,'dist/launcher'+ext);}"`, lint: "eslint . --ext .ts", typecheck: "pnpm run check:runtype-types && tsc --noEmit", test: "vitest", "test:ui": "vitest --ui", "test:run": "vitest run", size: "size-limit", "fetch:runtype-openapi": "node scripts/fetch-runtype-openapi.mjs", "generate:runtype-types": "pnpm run fetch:runtype-openapi && node scripts/generate-runtype-openapi-types.mjs", "check:runtype-types": "pnpm run fetch:runtype-openapi && node scripts/generate-runtype-openapi-types.mjs --check" }, dependencies: { "@mcp-b/webmcp-polyfill": "^3.0.0", dompurify: "^3.3.3", idiomorph: "^0.7.4", lucide: "^0.552.0", marked: "^12.0.2", "partial-json": "^0.1.7", zod: "^3.22.4" }, devDependencies: { "@size-limit/file": "^12.1.0", "@types/node": "^20.12.7", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", "@vitest/ui": "^4.0.9", eslint: "^8.57.0", "eslint-config-prettier": "^9.1.0", "fake-indexeddb": "^6.2.5", rimraf: "^5.0.5", "size-limit": "^12.1.0", tsup: "^8.0.1", typescript: "^5.4.5", vitest: "^4.0.9" }, engines: { node: ">=20.0.0" }, author: "Runtype", license: "MIT", keywords: ["ai", "chat", "widget", "streaming", "typescript", "persona", "agent"], repository: { type: "git", url: "git+https://github.com/runtypelabs/persona.git", directory: "packages/widget" }, bugs: { url: "https://github.com/runtypelabs/persona/issues" }, homepage: "https://github.com/runtypelabs/persona/tree/main/packages/widget#readme", publishConfig: { access: "public" } };
60041
- var c = S.version;
63501
+ // ../../node_modules/.pnpm/@runtypelabs+persona@3.34.1/node_modules/@runtypelabs/persona/dist/codegen.js
63502
+ var S = "3.34.1";
63503
+ var c = S;
60042
63504
  function u(e) {
60043
63505
  if (e !== void 0) return typeof e == "string" ? e : Array.isArray(e) ? `[${e.map((r) => r.toString()).join(", ")}]` : e.toString();
60044
63506
  }
@@ -60200,7 +63662,7 @@ function I(e, r = "esm", n) {
60200
63662
  let s = { ...e };
60201
63663
  delete s.postprocessMessage, delete s.initialMessages;
60202
63664
  let o = n ? { ...n, hooks: T(n.hooks) } : void 0;
60203
- return r === "esm" ? W(s, o) : r === "script-installer" ? k(s, o) : r === "script-advanced" ? F(s, o) : r === "react-component" ? H(s, o) : r === "react-advanced" ? N(s, o) : D(s, o);
63665
+ return r === "esm" ? W(s, o) : r === "script-installer" ? D(s, o) : r === "script-advanced" ? F(s, o) : r === "react-component" ? H(s, o) : r === "react-advanced" ? N(s, o) : k(s, o);
60204
63666
  }
60205
63667
  function W(e, r) {
60206
63668
  let n = r == null ? void 0 : r.hooks, s = h(e), o = s !== "plain", t = ["import '@runtypelabs/persona/widget.css';", "import { initAgentWidget, markdownPostprocessor } from '@runtypelabs/persona';", "", "initAgentWidget({", ` target: '${g(r)}',`, " config: {"];
@@ -60296,11 +63758,11 @@ function P(e) {
60296
63758
  }
60297
63759
  return s;
60298
63760
  }
60299
- function k(e, r) {
63761
+ function D(e, r) {
60300
63762
  let n = P(e), o = !!(r != null && r.windowKey || r != null && r.target) ? { config: n, ...r != null && r.windowKey ? { windowKey: r.windowKey } : {}, ...r != null && r.target ? { target: r.target } : {} } : n, t = JSON.stringify(o, null, 0).replace(/'/g, "&#39;");
60301
63763
  return `<script src="https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${c}/dist/install.global.js" data-config='${t}'></script>`;
60302
63764
  }
60303
- function D(e, r) {
63765
+ function k(e, r) {
60304
63766
  let n = r == null ? void 0 : r.hooks, s = h(e), o = s !== "plain", t = ["<!-- Load CSS -->", `<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${c}/dist/widget.css" />`, "", "<!-- Load JavaScript -->", `<script src="https://cdn.jsdelivr.net/npm/@runtypelabs/persona@${c}/dist/index.global.js"></script>`, "", "<!-- Initialize widget -->", "<script>", " var handle = window.AgentWidget.initAgentWidget({", ` target: '${g(r)}',`, ...r != null && r.windowKey ? [` windowKey: '${r.windowKey}',`] : [], " config: {"];
60305
63767
  return e.apiUrl && t.push(` apiUrl: "${e.apiUrl}",`), e.clientToken && t.push(` clientToken: "${e.clientToken}",`), e.flowId && t.push(` flowId: "${e.flowId}",`), o && t.push(` parserType: "${s}",`), e.theme && typeof e.theme == "object" && Object.keys(e.theme).length > 0 && l(t, "theme", e.theme, " "), e.launcher && l(t, "launcher", e.launcher, " "), e.copy && (t.push(" copy: {"), Object.entries(e.copy).forEach(([i, a]) => {
60306
63768
  t.push(` ${i}: "${a}",`);