@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.
- package/dist/index.js +3525 -63
- 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-
|
|
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
|
|
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(
|
|
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:
|
|
15510
|
+
variable: lookupKey,
|
|
15423
15511
|
defaultValue: parsed.defaultValue
|
|
15424
15512
|
});
|
|
15425
15513
|
return parsed.defaultValue;
|
|
15426
15514
|
}
|
|
15427
|
-
tracking.missingVariables.push(
|
|
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"
|
|
15435
|
-
|
|
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")
|
|
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
|
|
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 =
|
|
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
|
|
37376
|
-
|
|
37377
|
-
|
|
37378
|
-
|
|
37379
|
-
|
|
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
|
-
|
|
41537
|
-
|
|
44885
|
+
const text = neutralizeCsvFormula(value);
|
|
44886
|
+
if (text.includes(",") || text.includes('"') || text.includes("\n")) {
|
|
44887
|
+
return `"${text.replace(/"/g, '""')}"`;
|
|
41538
44888
|
}
|
|
41539
|
-
return
|
|
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
|
|
47421
|
+
function isObjectRecord2(value) {
|
|
44072
47422
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
44073
47423
|
}
|
|
44074
47424
|
function isQuickStartValidationResponse(value) {
|
|
44075
|
-
if (!
|
|
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" &&
|
|
47431
|
+
return typeof value.templateId === "string" && isObjectRecord2(value.agentCard);
|
|
44082
47432
|
}
|
|
44083
47433
|
function isQuickStartCreateResponse(value) {
|
|
44084
|
-
if (!
|
|
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
|
|
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
|
|
48909
|
-
|
|
48910
|
-
|
|
48911
|
-
|
|
48912
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
60040
|
-
var S =
|
|
60041
|
-
var c = S
|
|
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" ?
|
|
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
|
|
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, "'");
|
|
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
|
|
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}",`);
|