lua-cli 3.32.2 → 3.32.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-exports.d.ts +82 -8
- package/dist/api-exports.js +765 -304
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +2082 -549
- package/dist/index.js.map +1 -1
- package/dist/workflow-builder.d.ts +11 -7
- package/dist/workflow-builder.js +588 -244
- package/dist/workflow-builder.js.map +1 -1
- package/docs/CLI_REFERENCE.md +126 -4
- package/docs/README.md +2 -2
- package/docs/workflows/approvals.md +24 -6
- package/docs/workflows/goals.md +2 -2
- package/docs/workflows/replay-local.md +9 -3
- package/docs/workflows/schedules.md +1 -1
- package/docs/workflows/script-form.md +4 -4
- package/docs/workflows/testing-offline.md +33 -21
- package/package.json +4 -3
- package/template/examples/workflows/CLAUDE.md +17 -11
- package/template/examples/workflows/adversarial-verify.workflow.script.js +20 -16
- package/template/examples/workflows/outreach.ts +31 -15
- package/template/examples/workflows/refund-approval.ts +26 -12
- package/template/package.json +1 -1
package/dist/workflow-builder.js
CHANGED
|
@@ -1709,6 +1709,79 @@ var WORKFLOW_RETRY_BACKOFFS = [
|
|
|
1709
1709
|
"fixed",
|
|
1710
1710
|
"exponential"
|
|
1711
1711
|
];
|
|
1712
|
+
var WORKFLOW_RETRY_MIN_ATTEMPTS = 1;
|
|
1713
|
+
var WORKFLOW_RETRY_POLICY_KEYS = [
|
|
1714
|
+
"maxAttempts",
|
|
1715
|
+
"backoffSeconds",
|
|
1716
|
+
"backoff",
|
|
1717
|
+
"maxBackoffSeconds"
|
|
1718
|
+
];
|
|
1719
|
+
var WORKFLOW_RETRY_MAX_ATTEMPTS = 20;
|
|
1720
|
+
function workflowRetryMaxAttemptsMessage(got) {
|
|
1721
|
+
const tail = got === void 0 ? "" : ` (got ${JSON.stringify(got)})`;
|
|
1722
|
+
return `\`retry.maxAttempts\` must be an integer ${WORKFLOW_RETRY_MIN_ATTEMPTS}..${WORKFLOW_RETRY_MAX_ATTEMPTS}${tail}`;
|
|
1723
|
+
}
|
|
1724
|
+
__name(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
|
|
1725
|
+
__name2(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
|
|
1726
|
+
function isWithinWorkflowRetryAttempts(value3) {
|
|
1727
|
+
return typeof value3 === "number" && Number.isInteger(value3) && value3 >= WORKFLOW_RETRY_MIN_ATTEMPTS && value3 <= WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
1728
|
+
}
|
|
1729
|
+
__name(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
|
|
1730
|
+
__name2(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
|
|
1731
|
+
var WORKFLOW_RETRY_ENGINE_KEYS = [
|
|
1732
|
+
"budgetBaseAttempt"
|
|
1733
|
+
];
|
|
1734
|
+
function workflowRetryUnknownMembersMessage(keys) {
|
|
1735
|
+
const named = keys.map((k) => {
|
|
1736
|
+
const engine = WORKFLOW_RETRY_ENGINE_KEYS.includes(k);
|
|
1737
|
+
return `\`${k}\`${engine ? " (engine-owned \u2014 stamped by resetAttempts, never authored)" : ""}`;
|
|
1738
|
+
});
|
|
1739
|
+
return `\`retry\` has no member ${named.join(", ")}; members: ${WORKFLOW_RETRY_POLICY_KEYS.join(", ")}`;
|
|
1740
|
+
}
|
|
1741
|
+
__name(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
|
|
1742
|
+
__name2(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
|
|
1743
|
+
function unknownWorkflowRetryMembers(retry) {
|
|
1744
|
+
if (!retry || typeof retry !== "object" || Array.isArray(retry)) return [];
|
|
1745
|
+
return Object.keys(retry).filter((k) => !WORKFLOW_RETRY_POLICY_KEYS.includes(k));
|
|
1746
|
+
}
|
|
1747
|
+
__name(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
|
|
1748
|
+
__name2(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
|
|
1749
|
+
function authoredRetryPolicy(retry) {
|
|
1750
|
+
if (!retry || typeof retry !== "object" || Array.isArray(retry)) return void 0;
|
|
1751
|
+
const src = retry;
|
|
1752
|
+
const out = {};
|
|
1753
|
+
for (const k of WORKFLOW_RETRY_POLICY_KEYS) if (src[k] !== void 0) out[k] = src[k];
|
|
1754
|
+
return Object.keys(out).length ? out : void 0;
|
|
1755
|
+
}
|
|
1756
|
+
__name(authoredRetryPolicy, "authoredRetryPolicy");
|
|
1757
|
+
__name2(authoredRetryPolicy, "authoredRetryPolicy");
|
|
1758
|
+
function retryBudgetBaseAttempt(row) {
|
|
1759
|
+
const base = row.retry?.budgetBaseAttempt;
|
|
1760
|
+
return typeof base === "number" && Number.isSafeInteger(base) && base > 0 ? base : 0;
|
|
1761
|
+
}
|
|
1762
|
+
__name(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
|
|
1763
|
+
__name2(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
|
|
1764
|
+
function retryBudgetAttempt(row) {
|
|
1765
|
+
return Math.max(0, row.attempt - retryBudgetBaseAttempt(row));
|
|
1766
|
+
}
|
|
1767
|
+
__name(retryBudgetAttempt, "retryBudgetAttempt");
|
|
1768
|
+
__name2(retryBudgetAttempt, "retryBudgetAttempt");
|
|
1769
|
+
function retryBudgetMaxAttempts(row) {
|
|
1770
|
+
const max = row.retry?.maxAttempts;
|
|
1771
|
+
return typeof max === "number" && Number.isFinite(max) && max >= 1 ? max : 1;
|
|
1772
|
+
}
|
|
1773
|
+
__name(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
|
|
1774
|
+
__name2(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
|
|
1775
|
+
function retryBudgetRemaining(row) {
|
|
1776
|
+
return retryBudgetAttempt(row) < retryBudgetMaxAttempts(row);
|
|
1777
|
+
}
|
|
1778
|
+
__name(retryBudgetRemaining, "retryBudgetRemaining");
|
|
1779
|
+
__name2(retryBudgetRemaining, "retryBudgetRemaining");
|
|
1780
|
+
function retriesRemaining(row) {
|
|
1781
|
+
return Math.max(0, retryBudgetMaxAttempts(row) - retryBudgetAttempt(row));
|
|
1782
|
+
}
|
|
1783
|
+
__name(retriesRemaining, "retriesRemaining");
|
|
1784
|
+
__name2(retriesRemaining, "retriesRemaining");
|
|
1712
1785
|
var WORKFLOW_JOB_RESOURCES = [
|
|
1713
1786
|
"small",
|
|
1714
1787
|
"medium",
|
|
@@ -2074,6 +2147,8 @@ var WORKFLOW_AUDIT_EVENTS = [
|
|
|
2074
2147
|
"workflow.goal.resumed",
|
|
2075
2148
|
"workflow.goal.done",
|
|
2076
2149
|
"workflow.goal.closed",
|
|
2150
|
+
// LUA-760: an ended goal's cadence Job retired (deleted) — inline on done / closed, by R21 / R28, or by sweep #30
|
|
2151
|
+
"workflow.goal.job_retired",
|
|
2077
2152
|
// --- org policy (02 §2.10 / 09 R23) ---
|
|
2078
2153
|
"workflow.policy.retention_changed",
|
|
2079
2154
|
"workflow.policy.pacing_changed",
|
|
@@ -2217,6 +2292,138 @@ ${items.join("\n\n")}`;
|
|
|
2217
2292
|
}
|
|
2218
2293
|
__name(renderTargetsBlock, "renderTargetsBlock");
|
|
2219
2294
|
__name2(renderTargetsBlock, "renderTargetsBlock");
|
|
2295
|
+
var WORKFLOW_APPROVAL_OUTPUT_DECISIONS = [
|
|
2296
|
+
"approved",
|
|
2297
|
+
"denied",
|
|
2298
|
+
"timed_out"
|
|
2299
|
+
];
|
|
2300
|
+
var WORKFLOW_APPROVAL_OUTPUT_SCHEMA = {
|
|
2301
|
+
type: "object",
|
|
2302
|
+
properties: {
|
|
2303
|
+
approved: {
|
|
2304
|
+
type: "boolean"
|
|
2305
|
+
},
|
|
2306
|
+
decision: {
|
|
2307
|
+
type: "string",
|
|
2308
|
+
enum: [
|
|
2309
|
+
...WORKFLOW_APPROVAL_OUTPUT_DECISIONS
|
|
2310
|
+
]
|
|
2311
|
+
},
|
|
2312
|
+
/** the approver's note when given, else the decision word — what `${stepResults.<id>.text}` reads */
|
|
2313
|
+
text: {
|
|
2314
|
+
type: "string"
|
|
2315
|
+
},
|
|
2316
|
+
note: {
|
|
2317
|
+
type: "string"
|
|
2318
|
+
},
|
|
2319
|
+
editedPayload: {},
|
|
2320
|
+
editRevision: {
|
|
2321
|
+
type: "integer"
|
|
2322
|
+
},
|
|
2323
|
+
decidedBy: {
|
|
2324
|
+
type: "object",
|
|
2325
|
+
properties: {
|
|
2326
|
+
id: {
|
|
2327
|
+
type: "string"
|
|
2328
|
+
},
|
|
2329
|
+
kind: {
|
|
2330
|
+
type: "string"
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
},
|
|
2334
|
+
timedOut: {
|
|
2335
|
+
type: "boolean"
|
|
2336
|
+
},
|
|
2337
|
+
escalations: {
|
|
2338
|
+
type: "integer"
|
|
2339
|
+
},
|
|
2340
|
+
evidence: {
|
|
2341
|
+
type: "array",
|
|
2342
|
+
items: {
|
|
2343
|
+
type: "string"
|
|
2344
|
+
}
|
|
2345
|
+
},
|
|
2346
|
+
items: {
|
|
2347
|
+
type: "array",
|
|
2348
|
+
items: {
|
|
2349
|
+
type: "object"
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
},
|
|
2353
|
+
required: [
|
|
2354
|
+
"approved",
|
|
2355
|
+
"decision",
|
|
2356
|
+
"text"
|
|
2357
|
+
]
|
|
2358
|
+
};
|
|
2359
|
+
function workflowApprovalDecisionOf(resumeData) {
|
|
2360
|
+
if (resumeData.timedOut === true) return "timed_out";
|
|
2361
|
+
return resumeData.approved === true ? "approved" : "denied";
|
|
2362
|
+
}
|
|
2363
|
+
__name(workflowApprovalDecisionOf, "workflowApprovalDecisionOf");
|
|
2364
|
+
__name2(workflowApprovalDecisionOf, "workflowApprovalDecisionOf");
|
|
2365
|
+
function workflowApprovalOutput(resumeData) {
|
|
2366
|
+
const decision = typeof resumeData.decision === "string" ? resumeData.decision : workflowApprovalDecisionOf(resumeData);
|
|
2367
|
+
const note = typeof resumeData.note === "string" && resumeData.note.trim() !== "" ? resumeData.note : void 0;
|
|
2368
|
+
const text = typeof resumeData.text === "string" ? resumeData.text : note ?? decision;
|
|
2369
|
+
return {
|
|
2370
|
+
...resumeData,
|
|
2371
|
+
decision,
|
|
2372
|
+
text
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
__name(workflowApprovalOutput, "workflowApprovalOutput");
|
|
2376
|
+
__name2(workflowApprovalOutput, "workflowApprovalOutput");
|
|
2377
|
+
function isWorkflowApprovalOutput(value3) {
|
|
2378
|
+
if (typeof value3 !== "object" || value3 === null || Array.isArray(value3)) return false;
|
|
2379
|
+
const v = value3;
|
|
2380
|
+
return typeof v.approved === "boolean" && WORKFLOW_APPROVAL_OUTPUT_DECISIONS.includes(v.decision) && typeof v.text === "string";
|
|
2381
|
+
}
|
|
2382
|
+
__name(isWorkflowApprovalOutput, "isWorkflowApprovalOutput");
|
|
2383
|
+
__name2(isWorkflowApprovalOutput, "isWorkflowApprovalOutput");
|
|
2384
|
+
var JSON_FENCE_RE = /```(?:json)?[ \t]*\r?\n([\s\S]*?)\r?\n?```/g;
|
|
2385
|
+
function extractSingleJsonValue(text) {
|
|
2386
|
+
const trimmed = (text ?? "").trim();
|
|
2387
|
+
if (!trimmed) return {
|
|
2388
|
+
reason: "reply is empty"
|
|
2389
|
+
};
|
|
2390
|
+
const fenced = [
|
|
2391
|
+
...trimmed.matchAll(JSON_FENCE_RE)
|
|
2392
|
+
];
|
|
2393
|
+
if (fenced.length > 1) return {
|
|
2394
|
+
reason: "reply carries more than one fenced block"
|
|
2395
|
+
};
|
|
2396
|
+
const candidate = fenced.length === 1 ? fenced[0][1].trim() : trimmed;
|
|
2397
|
+
try {
|
|
2398
|
+
return {
|
|
2399
|
+
value: JSON.parse(candidate)
|
|
2400
|
+
};
|
|
2401
|
+
} catch {
|
|
2402
|
+
if (fenced.length === 1) return {
|
|
2403
|
+
reason: "fenced block is not valid JSON"
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
const opens = [
|
|
2407
|
+
trimmed.indexOf("{"),
|
|
2408
|
+
trimmed.indexOf("[")
|
|
2409
|
+
].filter((i) => i !== -1);
|
|
2410
|
+
const start = opens.length ? Math.min(...opens) : -1;
|
|
2411
|
+
const end = Math.max(trimmed.lastIndexOf("}"), trimmed.lastIndexOf("]"));
|
|
2412
|
+
if (start === -1 || end <= start) return {
|
|
2413
|
+
reason: "reply is not JSON"
|
|
2414
|
+
};
|
|
2415
|
+
try {
|
|
2416
|
+
return {
|
|
2417
|
+
value: JSON.parse(trimmed.slice(start, end + 1))
|
|
2418
|
+
};
|
|
2419
|
+
} catch {
|
|
2420
|
+
return {
|
|
2421
|
+
reason: "reply does not contain a single JSON value"
|
|
2422
|
+
};
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
__name(extractSingleJsonValue, "extractSingleJsonValue");
|
|
2426
|
+
__name2(extractSingleJsonValue, "extractSingleJsonValue");
|
|
2220
2427
|
|
|
2221
2428
|
// ../workflow-graph/dist/index.mjs
|
|
2222
2429
|
import { createHash } from "crypto";
|
|
@@ -2225,6 +2432,296 @@ import { z as z22 } from "zod";
|
|
|
2225
2432
|
import { createHash as createHash2 } from "crypto";
|
|
2226
2433
|
var __defProp3 = Object.defineProperty;
|
|
2227
2434
|
var __name3 = /* @__PURE__ */ __name((target, value22) => __defProp3(target, "name", { value: value22, configurable: true }), "__name");
|
|
2435
|
+
var WorkflowTemplateError = class extends Error {
|
|
2436
|
+
static {
|
|
2437
|
+
__name(this, "WorkflowTemplateError");
|
|
2438
|
+
}
|
|
2439
|
+
static {
|
|
2440
|
+
__name3(this, "WorkflowTemplateError");
|
|
2441
|
+
}
|
|
2442
|
+
placeholder;
|
|
2443
|
+
constructor(message, placeholder) {
|
|
2444
|
+
super(message), this.placeholder = placeholder;
|
|
2445
|
+
this.name = "WorkflowTemplateError";
|
|
2446
|
+
}
|
|
2447
|
+
};
|
|
2448
|
+
function isMapConfigObject(v) {
|
|
2449
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2450
|
+
}
|
|
2451
|
+
__name(isMapConfigObject, "isMapConfigObject");
|
|
2452
|
+
__name3(isMapConfigObject, "isMapConfigObject");
|
|
2453
|
+
function parseMapConfig(raw, stepId) {
|
|
2454
|
+
if (isMapConfigObject(raw)) return raw;
|
|
2455
|
+
if (typeof raw !== "string") {
|
|
2456
|
+
throw new Error(`Stored mapping step "${stepId}" has a mapConfig that is neither a JSON string nor an object.`);
|
|
2457
|
+
}
|
|
2458
|
+
try {
|
|
2459
|
+
return JSON.parse(raw);
|
|
2460
|
+
} catch (e) {
|
|
2461
|
+
throw new Error(`Stored mapping step "${stepId}" has invalid JSON mapConfig: ${e.message}`);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
__name(parseMapConfig, "parseMapConfig");
|
|
2465
|
+
__name3(parseMapConfig, "parseMapConfig");
|
|
2466
|
+
function mapConfigWire(raw) {
|
|
2467
|
+
if (typeof raw === "string") return raw;
|
|
2468
|
+
if (isMapConfigObject(raw)) return canonicalJson(raw);
|
|
2469
|
+
return void 0;
|
|
2470
|
+
}
|
|
2471
|
+
__name(mapConfigWire, "mapConfigWire");
|
|
2472
|
+
__name3(mapConfigWire, "mapConfigWire");
|
|
2473
|
+
var TEMPLATE_PLACEHOLDER = /\$\{([^}]*)\}/g;
|
|
2474
|
+
var TEMPLATE_NAMESPACES = [
|
|
2475
|
+
"initData",
|
|
2476
|
+
"state",
|
|
2477
|
+
"requestContext",
|
|
2478
|
+
"stepResults"
|
|
2479
|
+
];
|
|
2480
|
+
function describeBadPlaceholder(template22, idx, rawExpr) {
|
|
2481
|
+
return `Template placeholder #${idx} (\${${rawExpr}}) in '${template22}'`;
|
|
2482
|
+
}
|
|
2483
|
+
__name(describeBadPlaceholder, "describeBadPlaceholder");
|
|
2484
|
+
__name3(describeBadPlaceholder, "describeBadPlaceholder");
|
|
2485
|
+
function parseTemplatePlaceholder(rawExpr) {
|
|
2486
|
+
const dot = rawExpr.indexOf(".");
|
|
2487
|
+
return {
|
|
2488
|
+
scope: dot === -1 ? rawExpr : rawExpr.slice(0, dot),
|
|
2489
|
+
rest: dot === -1 ? "" : rawExpr.slice(dot + 1)
|
|
2490
|
+
};
|
|
2491
|
+
}
|
|
2492
|
+
__name(parseTemplatePlaceholder, "parseTemplatePlaceholder");
|
|
2493
|
+
__name3(parseTemplatePlaceholder, "parseTemplatePlaceholder");
|
|
2494
|
+
function traverseMappingPath(root, path, errorLabel) {
|
|
2495
|
+
if (path === "" || path === ".") return root;
|
|
2496
|
+
const parts = path.split(".");
|
|
2497
|
+
let value22 = root;
|
|
2498
|
+
for (const part of parts) {
|
|
2499
|
+
if (typeof value22 === "object" && value22 !== null) value22 = value22[part];
|
|
2500
|
+
else throw new WorkflowTemplateError(`Invalid path ${path} in ${errorLabel}`, path);
|
|
2501
|
+
}
|
|
2502
|
+
return value22;
|
|
2503
|
+
}
|
|
2504
|
+
__name(traverseMappingPath, "traverseMappingPath");
|
|
2505
|
+
__name3(traverseMappingPath, "traverseMappingPath");
|
|
2506
|
+
function stringifyTemplateValue(v, template22, idx, rawExpr) {
|
|
2507
|
+
if (v === null || v === void 0) return "";
|
|
2508
|
+
if (typeof v === "object") {
|
|
2509
|
+
try {
|
|
2510
|
+
return JSON.stringify(v);
|
|
2511
|
+
} catch (err) {
|
|
2512
|
+
throw new WorkflowTemplateError(`${describeBadPlaceholder(template22, idx, rawExpr)} resolved to a value that could not be JSON-stringified (${err.message}).`, rawExpr);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
return String(v);
|
|
2516
|
+
}
|
|
2517
|
+
__name(stringifyTemplateValue, "stringifyTemplateValue");
|
|
2518
|
+
__name3(stringifyTemplateValue, "stringifyTemplateValue");
|
|
2519
|
+
function escapeFence(content) {
|
|
2520
|
+
return content.replace(/<\/lua-data/g, "<\\/lua-data");
|
|
2521
|
+
}
|
|
2522
|
+
__name(escapeFence, "escapeFence");
|
|
2523
|
+
__name3(escapeFence, "escapeFence");
|
|
2524
|
+
function fenceBlock(name, source, content) {
|
|
2525
|
+
return `<lua-data name="${name}" source="${source}" untrusted="true">${escapeFence(content)}</lua-data>`;
|
|
2526
|
+
}
|
|
2527
|
+
__name(fenceBlock, "fenceBlock");
|
|
2528
|
+
__name3(fenceBlock, "fenceBlock");
|
|
2529
|
+
function renderTemplate(template22, ctx, opts) {
|
|
2530
|
+
let idx = 0;
|
|
2531
|
+
return template22.replace(TEMPLATE_PLACEHOLDER, (_match, rawExpr) => {
|
|
2532
|
+
idx += 1;
|
|
2533
|
+
const { scope, rest } = parseTemplatePlaceholder(rawExpr);
|
|
2534
|
+
const label = describeBadPlaceholder(template22, idx, rawExpr);
|
|
2535
|
+
let rendered;
|
|
2536
|
+
let source;
|
|
2537
|
+
switch (scope) {
|
|
2538
|
+
case "initData":
|
|
2539
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.initData, rest, label), template22, idx, rawExpr);
|
|
2540
|
+
source = "initData";
|
|
2541
|
+
break;
|
|
2542
|
+
case "state":
|
|
2543
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.state, rest, label), template22, idx, rawExpr);
|
|
2544
|
+
source = "state";
|
|
2545
|
+
break;
|
|
2546
|
+
case "requestContext":
|
|
2547
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.requestContext, rest, label), template22, idx, rawExpr);
|
|
2548
|
+
source = "requestContext";
|
|
2549
|
+
break;
|
|
2550
|
+
case "stepResults": {
|
|
2551
|
+
const innerDot = rest.indexOf(".");
|
|
2552
|
+
const stepId = innerDot === -1 ? rest : rest.slice(0, innerDot);
|
|
2553
|
+
const subPath = innerDot === -1 ? "" : rest.slice(innerDot + 1);
|
|
2554
|
+
if (!stepId) throw new WorkflowTemplateError(`${label} must name a step: \${stepResults.<stepId>.<path>}.`, rawExpr);
|
|
2555
|
+
if (!(stepId in ctx.stepResults) || ctx.stepResults[stepId] == null) {
|
|
2556
|
+
throw new WorkflowTemplateError(`${label} references stepResults.${stepId} but step "${stepId}" has no resolvable output (not an ancestor, not run, failed, or produced no output).`, rawExpr);
|
|
2557
|
+
}
|
|
2558
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.stepResults[stepId], subPath, label), template22, idx, rawExpr);
|
|
2559
|
+
source = `step:${stepId}`;
|
|
2560
|
+
break;
|
|
2561
|
+
}
|
|
2562
|
+
default:
|
|
2563
|
+
throw new WorkflowTemplateError(`${label} references unknown namespace "${scope}". Use one of: ${TEMPLATE_NAMESPACES.join(", ")}.`, rawExpr);
|
|
2564
|
+
}
|
|
2565
|
+
return opts.fenced ? fenceBlock(rawExpr, source, rendered) : rendered;
|
|
2566
|
+
});
|
|
2567
|
+
}
|
|
2568
|
+
__name(renderTemplate, "renderTemplate");
|
|
2569
|
+
__name3(renderTemplate, "renderTemplate");
|
|
2570
|
+
function isMapDescriptor(v) {
|
|
2571
|
+
if (v === null || typeof v !== "object" || Array.isArray(v)) return false;
|
|
2572
|
+
const d = v;
|
|
2573
|
+
const keys = Object.keys(d);
|
|
2574
|
+
const only = /* @__PURE__ */ __name3((...allowed) => keys.every((k) => allowed.includes(k)), "only");
|
|
2575
|
+
if ("value" in d) return keys.length === 1;
|
|
2576
|
+
if ("template" in d) return keys.length === 1 && typeof d.template === "string";
|
|
2577
|
+
if ("requestContextPath" in d) return keys.length === 1 && typeof d.requestContextPath === "string";
|
|
2578
|
+
if ("knowledge" in d) return keys.length === 1 && typeof d.knowledge === "object" && d.knowledge !== null;
|
|
2579
|
+
if ("initData" in d) return d.initData === true && typeof d.path === "string" && only("initData", "path");
|
|
2580
|
+
if ("step" in d) {
|
|
2581
|
+
const stepOk = typeof d.step === "string" || Array.isArray(d.step) && d.step.every((x) => typeof x === "string");
|
|
2582
|
+
return stepOk && typeof d.path === "string" && only("step", "path", "rows");
|
|
2583
|
+
}
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
__name(isMapDescriptor, "isMapDescriptor");
|
|
2587
|
+
__name3(isMapDescriptor, "isMapDescriptor");
|
|
2588
|
+
var MAP_DESCRIPTOR_KEYS = [
|
|
2589
|
+
"step",
|
|
2590
|
+
"path",
|
|
2591
|
+
"initData",
|
|
2592
|
+
"value",
|
|
2593
|
+
"template",
|
|
2594
|
+
"requestContextPath",
|
|
2595
|
+
"knowledge"
|
|
2596
|
+
];
|
|
2597
|
+
var MAP_MEMBER_MALFORMED_CODE = "map-member-malformed";
|
|
2598
|
+
function malformedMapMembers(cfg) {
|
|
2599
|
+
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) return [];
|
|
2600
|
+
const out = [];
|
|
2601
|
+
for (const [member, v] of Object.entries(cfg)) {
|
|
2602
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || isMapDescriptor(v)) continue;
|
|
2603
|
+
const keys = Object.keys(v).filter((k) => MAP_DESCRIPTOR_KEYS.includes(k));
|
|
2604
|
+
if (keys.length > 0) out.push({
|
|
2605
|
+
member,
|
|
2606
|
+
keys
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
return out;
|
|
2610
|
+
}
|
|
2611
|
+
__name(malformedMapMembers, "malformedMapMembers");
|
|
2612
|
+
__name3(malformedMapMembers, "malformedMapMembers");
|
|
2613
|
+
function mapMemberMalformedMessage(id, m) {
|
|
2614
|
+
const keys = m.keys.map((k) => `\`${k}\``).join(", ");
|
|
2615
|
+
return `"${id}".${m.member} carries descriptor key${m.keys.length === 1 ? "" : "s"} ${keys} but is not an exact binding form ({initData:true, path} | {step, path[, rows]} | {value} | {template} | {requestContextPath} | {knowledge}) \u2014 it is passed to the step verbatim as a literal; fix the descriptor, or wrap it in {value: \u2026} if the literal is intended`;
|
|
2616
|
+
}
|
|
2617
|
+
__name(mapMemberMalformedMessage, "mapMemberMalformedMessage");
|
|
2618
|
+
__name3(mapMemberMalformedMessage, "mapMemberMalformedMessage");
|
|
2619
|
+
function resolveDescriptor(key, m, ctx) {
|
|
2620
|
+
if (!isMapDescriptor(m)) return {
|
|
2621
|
+
value: m
|
|
2622
|
+
};
|
|
2623
|
+
try {
|
|
2624
|
+
if ("value" in m) return {
|
|
2625
|
+
value: m.value
|
|
2626
|
+
};
|
|
2627
|
+
if ("template" in m && typeof m.template === "string") {
|
|
2628
|
+
return {
|
|
2629
|
+
value: renderTemplate(m.template, ctx, {
|
|
2630
|
+
fenced: false
|
|
2631
|
+
})
|
|
2632
|
+
};
|
|
2633
|
+
}
|
|
2634
|
+
if ("knowledge" in m || "rows" in m && m.rows !== void 0) {
|
|
2635
|
+
return {
|
|
2636
|
+
error: "binding_unresolved",
|
|
2637
|
+
key
|
|
2638
|
+
};
|
|
2639
|
+
}
|
|
2640
|
+
if ("requestContextPath" in m) {
|
|
2641
|
+
const label = `requestContext path for key "${key}"`;
|
|
2642
|
+
return {
|
|
2643
|
+
value: traverseMappingPath(ctx.requestContext, m.requestContextPath, label)
|
|
2644
|
+
};
|
|
2645
|
+
}
|
|
2646
|
+
if ("path" in m) {
|
|
2647
|
+
const source = "initData" in m && m.initData ? "initData" : "step";
|
|
2648
|
+
if (source === "initData") {
|
|
2649
|
+
return {
|
|
2650
|
+
value: traverseMappingPath(ctx.initData, m.path, `initData for key "${key}"`)
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
const stepRef = m.step;
|
|
2654
|
+
const candidates = Array.isArray(stepRef) ? stepRef : [
|
|
2655
|
+
stepRef
|
|
2656
|
+
];
|
|
2657
|
+
const stepId = candidates.find((s) => ctx.stepResults[s] !== void 0 && ctx.stepResults[s] !== null);
|
|
2658
|
+
if (stepId === void 0) return {
|
|
2659
|
+
error: "binding_unresolved",
|
|
2660
|
+
key
|
|
2661
|
+
};
|
|
2662
|
+
return {
|
|
2663
|
+
value: traverseMappingPath(ctx.stepResults[stepId], m.path, `step ${candidates.join("|")} for key "${key}"`)
|
|
2664
|
+
};
|
|
2665
|
+
}
|
|
2666
|
+
return {
|
|
2667
|
+
error: "binding_unresolved",
|
|
2668
|
+
key
|
|
2669
|
+
};
|
|
2670
|
+
} catch (err) {
|
|
2671
|
+
if (err instanceof WorkflowTemplateError) return {
|
|
2672
|
+
error: "binding_unresolved",
|
|
2673
|
+
key
|
|
2674
|
+
};
|
|
2675
|
+
throw err;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
__name(resolveDescriptor, "resolveDescriptor");
|
|
2679
|
+
__name3(resolveDescriptor, "resolveDescriptor");
|
|
2680
|
+
function resolveMapping(cfg, ctx) {
|
|
2681
|
+
const keys = Object.keys(cfg);
|
|
2682
|
+
if (keys.length === 1 && keys[0] === "") {
|
|
2683
|
+
return resolveDescriptor("", cfg[""], ctx);
|
|
2684
|
+
}
|
|
2685
|
+
const result = {};
|
|
2686
|
+
for (const key of keys) {
|
|
2687
|
+
const resolved = resolveDescriptor(key, cfg[key], ctx);
|
|
2688
|
+
if ("error" in resolved) return resolved;
|
|
2689
|
+
result[key] = resolved.value;
|
|
2690
|
+
}
|
|
2691
|
+
return {
|
|
2692
|
+
value: result
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
__name(resolveMapping, "resolveMapping");
|
|
2696
|
+
__name3(resolveMapping, "resolveMapping");
|
|
2697
|
+
var fromInit = /* @__PURE__ */ __name3((path) => ({
|
|
2698
|
+
initData: true,
|
|
2699
|
+
path
|
|
2700
|
+
}), "fromInit");
|
|
2701
|
+
var fromStep = /* @__PURE__ */ __name3((s, path = "") => {
|
|
2702
|
+
const idOf = /* @__PURE__ */ __name3((x) => typeof x === "string" ? x : x.id, "idOf");
|
|
2703
|
+
return {
|
|
2704
|
+
step: Array.isArray(s) ? s.map(idOf) : idOf(s),
|
|
2705
|
+
path
|
|
2706
|
+
};
|
|
2707
|
+
}, "fromStep");
|
|
2708
|
+
var value = /* @__PURE__ */ __name3((v) => ({
|
|
2709
|
+
value: v
|
|
2710
|
+
}), "value");
|
|
2711
|
+
var template = /* @__PURE__ */ __name3((s) => ({
|
|
2712
|
+
template: s
|
|
2713
|
+
}), "template");
|
|
2714
|
+
var fromRequest = /* @__PURE__ */ __name3((path) => ({
|
|
2715
|
+
requestContextPath: path
|
|
2716
|
+
}), "fromRequest");
|
|
2717
|
+
var rows = /* @__PURE__ */ __name3((s, path, page) => ({
|
|
2718
|
+
step: typeof s === "string" ? s : s.id,
|
|
2719
|
+
path,
|
|
2720
|
+
rows: page
|
|
2721
|
+
}), "rows");
|
|
2722
|
+
var fromKnowledge = /* @__PURE__ */ __name3((k) => ({
|
|
2723
|
+
knowledge: k
|
|
2724
|
+
}), "fromKnowledge");
|
|
2228
2725
|
var SideEffectsSchema = z4.enum(WORKFLOW_SIDE_EFFECTS);
|
|
2229
2726
|
var JobResourcesSchema = z4.enum(WORKFLOW_JOB_RESOURCES);
|
|
2230
2727
|
var WORKFLOW_ARM_SUBRUN_ID = "$arm";
|
|
@@ -2482,12 +2979,11 @@ function mapConfigStepRefs(raw) {
|
|
|
2482
2979
|
if (!cfg) return [];
|
|
2483
2980
|
const ids = [];
|
|
2484
2981
|
for (const d of Object.values(cfg)) {
|
|
2485
|
-
if (!d
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
desc.step
|
|
2982
|
+
if (!isMapDescriptor(d)) continue;
|
|
2983
|
+
if ("step" in d) ids.push(...Array.isArray(d.step) ? d.step : [
|
|
2984
|
+
d.step
|
|
2489
2985
|
]);
|
|
2490
|
-
if (
|
|
2986
|
+
if ("template" in d) ids.push(...templateStepRefs(d.template));
|
|
2491
2987
|
}
|
|
2492
2988
|
return ids;
|
|
2493
2989
|
}
|
|
@@ -2616,6 +3112,12 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2616
3112
|
const r = node.retry;
|
|
2617
3113
|
if (!r) return;
|
|
2618
3114
|
const id = singleId(node);
|
|
3115
|
+
const unknown = unknownWorkflowRetryMembers(r);
|
|
3116
|
+
if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path}.retry`, id);
|
|
3117
|
+
if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
3118
|
+
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
3119
|
+
err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path}.retry.maxAttempts`, id);
|
|
3120
|
+
}
|
|
2619
3121
|
const backoffs = retryBackoffs();
|
|
2620
3122
|
if (r.backoff !== void 0 && !backoffs.includes(r.backoff)) {
|
|
2621
3123
|
const list = backoffs.map((b) => `'${b}'`).join(" | ");
|
|
@@ -2758,6 +3260,21 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2758
3260
|
const schema = node.type === "step" ? node.step.outputSchema : node.type === "agent" ? node.outputSchema : void 0;
|
|
2759
3261
|
if (schema !== void 0) outputSchemas.set(singleId(node), schema);
|
|
2760
3262
|
}, "recordOutputSchema");
|
|
3263
|
+
const checkMapMembers = /* @__PURE__ */ __name3((cfg, basePath, id) => {
|
|
3264
|
+
for (const m of malformedMapMembers(cfg)) {
|
|
3265
|
+
warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id, m), `${basePath}.${m.member}`, id);
|
|
3266
|
+
}
|
|
3267
|
+
}, "checkMapMembers");
|
|
3268
|
+
const checkInputShape = /* @__PURE__ */ __name3((node, path) => {
|
|
3269
|
+
if (node.type !== "tool" && node.type !== "workflow") return;
|
|
3270
|
+
const input = node.input;
|
|
3271
|
+
if (input === void 0) return;
|
|
3272
|
+
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
3273
|
+
checkMapMembers(input, `${path}.input`, node.id);
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
err("invalid-envelope", `\`input\` must be an object map \u2014 each member a binding descriptor ({initData:true, path} | {step, path} | {value} | {template} | {requestContextPath}) or a JSON literal (got ${JSON.stringify(input)})`, `${path}.input`, node.id);
|
|
3277
|
+
}, "checkInputShape");
|
|
2761
3278
|
const checkSingle = /* @__PURE__ */ __name3((node, path, depth) => {
|
|
2762
3279
|
recordOutputSchema(node);
|
|
2763
3280
|
if (node.type === "workflow" && node.workflowId === WORKFLOW_ARM_SUBRUN_ID) {
|
|
@@ -2785,6 +3302,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2785
3302
|
}
|
|
2786
3303
|
checkId(singleId(node), path);
|
|
2787
3304
|
checkPolicyEnums(node, path);
|
|
3305
|
+
checkInputShape(node, path);
|
|
2788
3306
|
checkTimeout(node, path);
|
|
2789
3307
|
checkTier(node, path);
|
|
2790
3308
|
checkRetry(node, path);
|
|
@@ -2865,6 +3383,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2865
3383
|
const checkArm = /* @__PURE__ */ __name3((arm, path, depth, container) => {
|
|
2866
3384
|
if (arm.type === "mapping") {
|
|
2867
3385
|
checkId(arm.id, path);
|
|
3386
|
+
checkMapMembers(readMapConfig(arm.mapConfig), `${path}.mapConfig`, arm.id);
|
|
2868
3387
|
for (const ref of nodeStepRefs(arm)) {
|
|
2869
3388
|
if (!upstream.has(ref)) err("template-reference-unresolved", `"${arm.id}" references stepResults.${ref}, which is not upstream`, path, arm.id);
|
|
2870
3389
|
}
|
|
@@ -2889,6 +3408,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2889
3408
|
break;
|
|
2890
3409
|
case "mapping":
|
|
2891
3410
|
checkId(entry.id, path);
|
|
3411
|
+
checkMapMembers(readMapConfig(entry.mapConfig), `${path}.mapConfig`, entry.id);
|
|
2892
3412
|
for (const ref of nodeStepRefs(entry)) {
|
|
2893
3413
|
if (!upstream.has(ref)) err("template-reference-unresolved", `"${entry.id}" references stepResults.${ref}, which is not upstream`, path, entry.id);
|
|
2894
3414
|
}
|
|
@@ -3629,244 +4149,6 @@ var not = /* @__PURE__ */ __name3((arg) => ({
|
|
|
3629
4149
|
op: "not",
|
|
3630
4150
|
arg
|
|
3631
4151
|
}), "not");
|
|
3632
|
-
var WorkflowTemplateError = class extends Error {
|
|
3633
|
-
static {
|
|
3634
|
-
__name(this, "WorkflowTemplateError");
|
|
3635
|
-
}
|
|
3636
|
-
static {
|
|
3637
|
-
__name3(this, "WorkflowTemplateError");
|
|
3638
|
-
}
|
|
3639
|
-
placeholder;
|
|
3640
|
-
constructor(message, placeholder) {
|
|
3641
|
-
super(message), this.placeholder = placeholder;
|
|
3642
|
-
this.name = "WorkflowTemplateError";
|
|
3643
|
-
}
|
|
3644
|
-
};
|
|
3645
|
-
function isMapConfigObject(v) {
|
|
3646
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3647
|
-
}
|
|
3648
|
-
__name(isMapConfigObject, "isMapConfigObject");
|
|
3649
|
-
__name3(isMapConfigObject, "isMapConfigObject");
|
|
3650
|
-
function parseMapConfig(raw, stepId) {
|
|
3651
|
-
if (isMapConfigObject(raw)) return raw;
|
|
3652
|
-
if (typeof raw !== "string") {
|
|
3653
|
-
throw new Error(`Stored mapping step "${stepId}" has a mapConfig that is neither a JSON string nor an object.`);
|
|
3654
|
-
}
|
|
3655
|
-
try {
|
|
3656
|
-
return JSON.parse(raw);
|
|
3657
|
-
} catch (e) {
|
|
3658
|
-
throw new Error(`Stored mapping step "${stepId}" has invalid JSON mapConfig: ${e.message}`);
|
|
3659
|
-
}
|
|
3660
|
-
}
|
|
3661
|
-
__name(parseMapConfig, "parseMapConfig");
|
|
3662
|
-
__name3(parseMapConfig, "parseMapConfig");
|
|
3663
|
-
function mapConfigWire(raw) {
|
|
3664
|
-
if (typeof raw === "string") return raw;
|
|
3665
|
-
if (isMapConfigObject(raw)) return canonicalJson(raw);
|
|
3666
|
-
return void 0;
|
|
3667
|
-
}
|
|
3668
|
-
__name(mapConfigWire, "mapConfigWire");
|
|
3669
|
-
__name3(mapConfigWire, "mapConfigWire");
|
|
3670
|
-
var TEMPLATE_PLACEHOLDER = /\$\{([^}]*)\}/g;
|
|
3671
|
-
var TEMPLATE_NAMESPACES = [
|
|
3672
|
-
"initData",
|
|
3673
|
-
"state",
|
|
3674
|
-
"requestContext",
|
|
3675
|
-
"stepResults"
|
|
3676
|
-
];
|
|
3677
|
-
function describeBadPlaceholder(template22, idx, rawExpr) {
|
|
3678
|
-
return `Template placeholder #${idx} (\${${rawExpr}}) in '${template22}'`;
|
|
3679
|
-
}
|
|
3680
|
-
__name(describeBadPlaceholder, "describeBadPlaceholder");
|
|
3681
|
-
__name3(describeBadPlaceholder, "describeBadPlaceholder");
|
|
3682
|
-
function parseTemplatePlaceholder(rawExpr) {
|
|
3683
|
-
const dot = rawExpr.indexOf(".");
|
|
3684
|
-
return {
|
|
3685
|
-
scope: dot === -1 ? rawExpr : rawExpr.slice(0, dot),
|
|
3686
|
-
rest: dot === -1 ? "" : rawExpr.slice(dot + 1)
|
|
3687
|
-
};
|
|
3688
|
-
}
|
|
3689
|
-
__name(parseTemplatePlaceholder, "parseTemplatePlaceholder");
|
|
3690
|
-
__name3(parseTemplatePlaceholder, "parseTemplatePlaceholder");
|
|
3691
|
-
function traverseMappingPath(root, path, errorLabel) {
|
|
3692
|
-
if (path === "" || path === ".") return root;
|
|
3693
|
-
const parts = path.split(".");
|
|
3694
|
-
let value22 = root;
|
|
3695
|
-
for (const part of parts) {
|
|
3696
|
-
if (typeof value22 === "object" && value22 !== null) value22 = value22[part];
|
|
3697
|
-
else throw new WorkflowTemplateError(`Invalid path ${path} in ${errorLabel}`, path);
|
|
3698
|
-
}
|
|
3699
|
-
return value22;
|
|
3700
|
-
}
|
|
3701
|
-
__name(traverseMappingPath, "traverseMappingPath");
|
|
3702
|
-
__name3(traverseMappingPath, "traverseMappingPath");
|
|
3703
|
-
function stringifyTemplateValue(v, template22, idx, rawExpr) {
|
|
3704
|
-
if (v === null || v === void 0) return "";
|
|
3705
|
-
if (typeof v === "object") {
|
|
3706
|
-
try {
|
|
3707
|
-
return JSON.stringify(v);
|
|
3708
|
-
} catch (err) {
|
|
3709
|
-
throw new WorkflowTemplateError(`${describeBadPlaceholder(template22, idx, rawExpr)} resolved to a value that could not be JSON-stringified (${err.message}).`, rawExpr);
|
|
3710
|
-
}
|
|
3711
|
-
}
|
|
3712
|
-
return String(v);
|
|
3713
|
-
}
|
|
3714
|
-
__name(stringifyTemplateValue, "stringifyTemplateValue");
|
|
3715
|
-
__name3(stringifyTemplateValue, "stringifyTemplateValue");
|
|
3716
|
-
function escapeFence(content) {
|
|
3717
|
-
return content.replace(/<\/lua-data/g, "<\\/lua-data");
|
|
3718
|
-
}
|
|
3719
|
-
__name(escapeFence, "escapeFence");
|
|
3720
|
-
__name3(escapeFence, "escapeFence");
|
|
3721
|
-
function fenceBlock(name, source, content) {
|
|
3722
|
-
return `<lua-data name="${name}" source="${source}" untrusted="true">${escapeFence(content)}</lua-data>`;
|
|
3723
|
-
}
|
|
3724
|
-
__name(fenceBlock, "fenceBlock");
|
|
3725
|
-
__name3(fenceBlock, "fenceBlock");
|
|
3726
|
-
function renderTemplate(template22, ctx, opts) {
|
|
3727
|
-
let idx = 0;
|
|
3728
|
-
return template22.replace(TEMPLATE_PLACEHOLDER, (_match, rawExpr) => {
|
|
3729
|
-
idx += 1;
|
|
3730
|
-
const { scope, rest } = parseTemplatePlaceholder(rawExpr);
|
|
3731
|
-
const label = describeBadPlaceholder(template22, idx, rawExpr);
|
|
3732
|
-
let rendered;
|
|
3733
|
-
let source;
|
|
3734
|
-
switch (scope) {
|
|
3735
|
-
case "initData":
|
|
3736
|
-
rendered = stringifyTemplateValue(traverseMappingPath(ctx.initData, rest, label), template22, idx, rawExpr);
|
|
3737
|
-
source = "initData";
|
|
3738
|
-
break;
|
|
3739
|
-
case "state":
|
|
3740
|
-
rendered = stringifyTemplateValue(traverseMappingPath(ctx.state, rest, label), template22, idx, rawExpr);
|
|
3741
|
-
source = "state";
|
|
3742
|
-
break;
|
|
3743
|
-
case "requestContext":
|
|
3744
|
-
rendered = stringifyTemplateValue(traverseMappingPath(ctx.requestContext, rest, label), template22, idx, rawExpr);
|
|
3745
|
-
source = "requestContext";
|
|
3746
|
-
break;
|
|
3747
|
-
case "stepResults": {
|
|
3748
|
-
const innerDot = rest.indexOf(".");
|
|
3749
|
-
const stepId = innerDot === -1 ? rest : rest.slice(0, innerDot);
|
|
3750
|
-
const subPath = innerDot === -1 ? "" : rest.slice(innerDot + 1);
|
|
3751
|
-
if (!stepId) throw new WorkflowTemplateError(`${label} must name a step: \${stepResults.<stepId>.<path>}.`, rawExpr);
|
|
3752
|
-
if (!(stepId in ctx.stepResults) || ctx.stepResults[stepId] == null) {
|
|
3753
|
-
throw new WorkflowTemplateError(`${label} references stepResults.${stepId} but step "${stepId}" has no resolvable output (not an ancestor, not run, failed, or produced no output).`, rawExpr);
|
|
3754
|
-
}
|
|
3755
|
-
rendered = stringifyTemplateValue(traverseMappingPath(ctx.stepResults[stepId], subPath, label), template22, idx, rawExpr);
|
|
3756
|
-
source = `step:${stepId}`;
|
|
3757
|
-
break;
|
|
3758
|
-
}
|
|
3759
|
-
default:
|
|
3760
|
-
throw new WorkflowTemplateError(`${label} references unknown namespace "${scope}". Use one of: ${TEMPLATE_NAMESPACES.join(", ")}.`, rawExpr);
|
|
3761
|
-
}
|
|
3762
|
-
return opts.fenced ? fenceBlock(rawExpr, source, rendered) : rendered;
|
|
3763
|
-
});
|
|
3764
|
-
}
|
|
3765
|
-
__name(renderTemplate, "renderTemplate");
|
|
3766
|
-
__name3(renderTemplate, "renderTemplate");
|
|
3767
|
-
function resolveDescriptor(key, m, ctx) {
|
|
3768
|
-
try {
|
|
3769
|
-
if ("value" in m) return {
|
|
3770
|
-
value: m.value
|
|
3771
|
-
};
|
|
3772
|
-
if ("template" in m && typeof m.template === "string") {
|
|
3773
|
-
return {
|
|
3774
|
-
value: renderTemplate(m.template, ctx, {
|
|
3775
|
-
fenced: false
|
|
3776
|
-
})
|
|
3777
|
-
};
|
|
3778
|
-
}
|
|
3779
|
-
if ("knowledge" in m || "rows" in m && m.rows !== void 0) {
|
|
3780
|
-
return {
|
|
3781
|
-
error: "binding_unresolved",
|
|
3782
|
-
key
|
|
3783
|
-
};
|
|
3784
|
-
}
|
|
3785
|
-
if ("requestContextPath" in m) {
|
|
3786
|
-
const label = `requestContext path for key "${key}"`;
|
|
3787
|
-
return {
|
|
3788
|
-
value: traverseMappingPath(ctx.requestContext, m.requestContextPath, label)
|
|
3789
|
-
};
|
|
3790
|
-
}
|
|
3791
|
-
if ("path" in m) {
|
|
3792
|
-
const source = "initData" in m && m.initData ? "initData" : "step";
|
|
3793
|
-
if (source === "initData") {
|
|
3794
|
-
return {
|
|
3795
|
-
value: traverseMappingPath(ctx.initData, m.path, `initData for key "${key}"`)
|
|
3796
|
-
};
|
|
3797
|
-
}
|
|
3798
|
-
const stepRef = m.step;
|
|
3799
|
-
const candidates = Array.isArray(stepRef) ? stepRef : [
|
|
3800
|
-
stepRef
|
|
3801
|
-
];
|
|
3802
|
-
const stepId = candidates.find((s) => ctx.stepResults[s] !== void 0 && ctx.stepResults[s] !== null);
|
|
3803
|
-
if (stepId === void 0) return {
|
|
3804
|
-
error: "binding_unresolved",
|
|
3805
|
-
key
|
|
3806
|
-
};
|
|
3807
|
-
return {
|
|
3808
|
-
value: traverseMappingPath(ctx.stepResults[stepId], m.path, `step ${candidates.join("|")} for key "${key}"`)
|
|
3809
|
-
};
|
|
3810
|
-
}
|
|
3811
|
-
return {
|
|
3812
|
-
error: "binding_unresolved",
|
|
3813
|
-
key
|
|
3814
|
-
};
|
|
3815
|
-
} catch (err) {
|
|
3816
|
-
if (err instanceof WorkflowTemplateError) return {
|
|
3817
|
-
error: "binding_unresolved",
|
|
3818
|
-
key
|
|
3819
|
-
};
|
|
3820
|
-
throw err;
|
|
3821
|
-
}
|
|
3822
|
-
}
|
|
3823
|
-
__name(resolveDescriptor, "resolveDescriptor");
|
|
3824
|
-
__name3(resolveDescriptor, "resolveDescriptor");
|
|
3825
|
-
function resolveMapping(cfg, ctx) {
|
|
3826
|
-
const keys = Object.keys(cfg);
|
|
3827
|
-
if (keys.length === 1 && keys[0] === "") {
|
|
3828
|
-
return resolveDescriptor("", cfg[""], ctx);
|
|
3829
|
-
}
|
|
3830
|
-
const result = {};
|
|
3831
|
-
for (const key of keys) {
|
|
3832
|
-
const resolved = resolveDescriptor(key, cfg[key], ctx);
|
|
3833
|
-
if ("error" in resolved) return resolved;
|
|
3834
|
-
result[key] = resolved.value;
|
|
3835
|
-
}
|
|
3836
|
-
return {
|
|
3837
|
-
value: result
|
|
3838
|
-
};
|
|
3839
|
-
}
|
|
3840
|
-
__name(resolveMapping, "resolveMapping");
|
|
3841
|
-
__name3(resolveMapping, "resolveMapping");
|
|
3842
|
-
var fromInit = /* @__PURE__ */ __name3((path) => ({
|
|
3843
|
-
initData: true,
|
|
3844
|
-
path
|
|
3845
|
-
}), "fromInit");
|
|
3846
|
-
var fromStep = /* @__PURE__ */ __name3((s, path = "") => {
|
|
3847
|
-
const idOf = /* @__PURE__ */ __name3((x) => typeof x === "string" ? x : x.id, "idOf");
|
|
3848
|
-
return {
|
|
3849
|
-
step: Array.isArray(s) ? s.map(idOf) : idOf(s),
|
|
3850
|
-
path
|
|
3851
|
-
};
|
|
3852
|
-
}, "fromStep");
|
|
3853
|
-
var value = /* @__PURE__ */ __name3((v) => ({
|
|
3854
|
-
value: v
|
|
3855
|
-
}), "value");
|
|
3856
|
-
var template = /* @__PURE__ */ __name3((s) => ({
|
|
3857
|
-
template: s
|
|
3858
|
-
}), "template");
|
|
3859
|
-
var fromRequest = /* @__PURE__ */ __name3((path) => ({
|
|
3860
|
-
requestContextPath: path
|
|
3861
|
-
}), "fromRequest");
|
|
3862
|
-
var rows = /* @__PURE__ */ __name3((s, path, page) => ({
|
|
3863
|
-
step: typeof s === "string" ? s : s.id,
|
|
3864
|
-
path,
|
|
3865
|
-
rows: page
|
|
3866
|
-
}), "rows");
|
|
3867
|
-
var fromKnowledge = /* @__PURE__ */ __name3((k) => ({
|
|
3868
|
-
knowledge: k
|
|
3869
|
-
}), "fromKnowledge");
|
|
3870
4152
|
var CONTINUED_FAILURE_TAG = "continued_failure";
|
|
3871
4153
|
var CONTINUED_FAILURE_DEFAULT_CODE = "step_failed";
|
|
3872
4154
|
var CONTINUED_FAILURE_OUTPUT_SCHEMA = Object.freeze({
|
|
@@ -4626,10 +4908,57 @@ function runCounts(counts) {
|
|
|
4626
4908
|
}
|
|
4627
4909
|
__name(runCounts, "runCounts");
|
|
4628
4910
|
__name3(runCounts, "runCounts");
|
|
4629
|
-
function
|
|
4911
|
+
function isPricedStepReceipt(receipt) {
|
|
4912
|
+
return typeof receipt?.multiplier === "number" && Number.isFinite(receipt.multiplier);
|
|
4913
|
+
}
|
|
4914
|
+
__name(isPricedStepReceipt, "isPricedStepReceipt");
|
|
4915
|
+
__name3(isPricedStepReceipt, "isPricedStepReceipt");
|
|
4916
|
+
function receiptEngine(engine) {
|
|
4917
|
+
if (engine === "actions") return "seat";
|
|
4918
|
+
if (engine === "credits") return "legacy";
|
|
4919
|
+
return void 0;
|
|
4920
|
+
}
|
|
4921
|
+
__name(receiptEngine, "receiptEngine");
|
|
4922
|
+
__name3(receiptEngine, "receiptEngine");
|
|
4923
|
+
function receiptTier(tier) {
|
|
4924
|
+
return tier === "light" || tier === "standard" || tier === "heavy" ? tier : void 0;
|
|
4925
|
+
}
|
|
4926
|
+
__name(receiptTier, "receiptTier");
|
|
4927
|
+
__name3(receiptTier, "receiptTier");
|
|
4928
|
+
function stepBillingView(receipt) {
|
|
4929
|
+
const engine = receiptEngine(receipt?.engine);
|
|
4930
|
+
if (!receipt || engine === void 0) return void 0;
|
|
4931
|
+
return pruneUndefined({
|
|
4932
|
+
engine,
|
|
4933
|
+
attempt: typeof receipt.attempt === "number" ? receipt.attempt : void 0,
|
|
4934
|
+
credits: typeof receipt.credits === "number" ? receipt.credits : void 0,
|
|
4935
|
+
actions: typeof receipt.actionsEstimate === "number" ? receipt.actionsEstimate : void 0,
|
|
4936
|
+
model: typeof receipt.model === "string" ? receipt.model : void 0,
|
|
4937
|
+
tier: receiptTier(receipt.tier),
|
|
4938
|
+
multiplier: typeof receipt.multiplier === "number" ? receipt.multiplier : void 0,
|
|
4939
|
+
byok: typeof receipt.byok === "boolean" ? receipt.byok : void 0,
|
|
4940
|
+
calibrated: typeof receipt.calibrated === "boolean" ? receipt.calibrated : void 0
|
|
4941
|
+
});
|
|
4942
|
+
}
|
|
4943
|
+
__name(stepBillingView, "stepBillingView");
|
|
4944
|
+
__name3(stepBillingView, "stepBillingView");
|
|
4945
|
+
function runUsage(run, receipts) {
|
|
4946
|
+
const actions = n(run.budget?.spent?.actionsEstimate);
|
|
4947
|
+
const stamped = run.budget?.engine;
|
|
4948
|
+
const priced = (receipts ?? []).filter(isPricedStepReceipt);
|
|
4949
|
+
const engine = stamped === "seat" || stamped === "legacy" ? stamped : actions > 0 || priced.some((r) => r.engine === "actions") ? "seat" : priced.some((r) => r.engine === "credits") ? "legacy" : void 0;
|
|
4950
|
+
const seat = engine === "seat";
|
|
4951
|
+
const metering = engine ? "priced" : "flat";
|
|
4630
4952
|
return {
|
|
4631
4953
|
creditsUsed: run.budget?.spent?.credits ?? 0,
|
|
4632
4954
|
actionsEstimate: run.budget?.spent?.actionsEstimate ?? 0,
|
|
4955
|
+
...seat ? {
|
|
4956
|
+
actionsUsed: actions
|
|
4957
|
+
} : {},
|
|
4958
|
+
metering,
|
|
4959
|
+
...engine ? {
|
|
4960
|
+
engine
|
|
4961
|
+
} : {},
|
|
4633
4962
|
steps: run.budget?.spent?.steps ?? 0,
|
|
4634
4963
|
inputTokens: run.usage?.inputTokens ?? 0,
|
|
4635
4964
|
outputTokens: run.usage?.outputTokens ?? 0
|
|
@@ -4637,6 +4966,20 @@ function runUsage(run) {
|
|
|
4637
4966
|
}
|
|
4638
4967
|
__name(runUsage, "runUsage");
|
|
4639
4968
|
__name3(runUsage, "runUsage");
|
|
4969
|
+
function runBudgetCap(budget) {
|
|
4970
|
+
const cap = budget?.maxCredits;
|
|
4971
|
+
return typeof cap === "number" && Number.isFinite(cap) && cap > 0 ? cap : void 0;
|
|
4972
|
+
}
|
|
4973
|
+
__name(runBudgetCap, "runBudgetCap");
|
|
4974
|
+
__name3(runBudgetCap, "runBudgetCap");
|
|
4975
|
+
function runBudgetRemaining(budget) {
|
|
4976
|
+
const cap = runBudgetCap(budget);
|
|
4977
|
+
if (cap === void 0) return void 0;
|
|
4978
|
+
const spent = budget?.spent;
|
|
4979
|
+
return Math.max(0, cap - n(spent?.credits) - n(spent?.actionsEstimate) - n(budget?.reserved));
|
|
4980
|
+
}
|
|
4981
|
+
__name(runBudgetRemaining, "runBudgetRemaining");
|
|
4982
|
+
__name3(runBudgetRemaining, "runBudgetRemaining");
|
|
4640
4983
|
function runCancelView(cancel) {
|
|
4641
4984
|
if (!cancel) return void 0;
|
|
4642
4985
|
return {
|
|
@@ -6021,6 +6364,7 @@ var assertPredicate = /* @__PURE__ */ __name((p, where) => {
|
|
|
6021
6364
|
}, "assertPredicate");
|
|
6022
6365
|
var assertRetry = /* @__PURE__ */ __name((r, id) => {
|
|
6023
6366
|
if (!r) return;
|
|
6367
|
+
if (typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS) throw new LuaWorkflowBuildError("cap-exceeded", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
|
|
6024
6368
|
if (r.backoff !== void 0 && !WORKFLOW_RETRY_BACKOFFS.includes(r.backoff)) throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.backoff must be ${WORKFLOW_RETRY_BACKOFFS.map((b) => `'${b}'`).join(" | ")}`);
|
|
6025
6369
|
if (r.maxBackoffSeconds !== void 0) {
|
|
6026
6370
|
if (r.backoff !== "exponential") throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.maxBackoffSeconds is only meaningful with backoff:'exponential'`);
|