lua-cli 3.32.2 → 3.32.4
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 +87 -11
- package/dist/api-exports.js +1554 -756
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +3512 -1459
- package/dist/index.js.map +1 -1
- package/dist/workflow-builder.d.ts +16 -10
- package/dist/workflow-builder.js +1216 -702
- package/dist/workflow-builder.js.map +1 -1
- package/docs/CLI_REFERENCE.md +126 -4
- package/docs/README.md +2 -2
- package/docs/api/LuaWorkflow.md +1 -1
- package/docs/workflows/approvals.md +26 -6
- package/docs/workflows/goals.md +2 -2
- package/docs/workflows/recovery.md +1 -1
- package/docs/workflows/replay-local.md +9 -3
- package/docs/workflows/schedules.md +13 -4
- 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/examples/workflows/research-brief.ts +29 -16
- package/template/package.json +1 -1
package/dist/workflow-builder.js
CHANGED
|
@@ -647,6 +647,94 @@ function isDesktopFileSessionId(value3) {
|
|
|
647
647
|
}
|
|
648
648
|
__name(isDesktopFileSessionId, "isDesktopFileSessionId");
|
|
649
649
|
__name2(isDesktopFileSessionId, "isDesktopFileSessionId");
|
|
650
|
+
var MODEL_ID_BYOK_PROVIDERS = [
|
|
651
|
+
"azure",
|
|
652
|
+
"bedrock"
|
|
653
|
+
];
|
|
654
|
+
function isModelIdSentinel(input) {
|
|
655
|
+
const lower = (input ?? "").trim().toLowerCase();
|
|
656
|
+
return lower === "auto" || lower.startsWith("auto/");
|
|
657
|
+
}
|
|
658
|
+
__name(isModelIdSentinel, "isModelIdSentinel");
|
|
659
|
+
__name2(isModelIdSentinel, "isModelIdSentinel");
|
|
660
|
+
function normalizeModelId(input, registry) {
|
|
661
|
+
const requested = typeof input === "string" ? input.trim() : "";
|
|
662
|
+
if (!requested) return {
|
|
663
|
+
ok: false,
|
|
664
|
+
reason: "empty",
|
|
665
|
+
requested,
|
|
666
|
+
candidates: []
|
|
667
|
+
};
|
|
668
|
+
const lower = requested.toLowerCase();
|
|
669
|
+
if (isModelIdSentinel(lower)) return {
|
|
670
|
+
ok: true,
|
|
671
|
+
id: lower,
|
|
672
|
+
form: "sentinel"
|
|
673
|
+
};
|
|
674
|
+
const slash = requested.indexOf("/");
|
|
675
|
+
const malformed = slash === 0;
|
|
676
|
+
const provider = slash > 0 ? lower.slice(0, slash) : void 0;
|
|
677
|
+
if (provider && MODEL_ID_BYOK_PROVIDERS.includes(provider)) {
|
|
678
|
+
return {
|
|
679
|
+
ok: true,
|
|
680
|
+
id: requested,
|
|
681
|
+
form: "byok"
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
const bareId = slash >= 0 ? lower.slice(slash + 1) : lower;
|
|
685
|
+
const lastSegment = bareId.slice(bareId.lastIndexOf("/") + 1);
|
|
686
|
+
const exact = /* @__PURE__ */ new Set();
|
|
687
|
+
const hints = /* @__PURE__ */ new Set();
|
|
688
|
+
for (const code of registry) {
|
|
689
|
+
if (typeof code !== "string" || !code) continue;
|
|
690
|
+
const codeLower = code.toLowerCase();
|
|
691
|
+
if (!malformed && codeLower === lower) return {
|
|
692
|
+
ok: true,
|
|
693
|
+
id: code,
|
|
694
|
+
form: provider ? "canonical" : "bare"
|
|
695
|
+
};
|
|
696
|
+
const i = codeLower.indexOf("/");
|
|
697
|
+
if (i < 0) continue;
|
|
698
|
+
const codeBare = codeLower.slice(i + 1);
|
|
699
|
+
if (bareId && codeBare === bareId) exact.add(code);
|
|
700
|
+
else if (lastSegment && codeBare.slice(codeBare.lastIndexOf("/") + 1) === lastSegment) hints.add(code);
|
|
701
|
+
}
|
|
702
|
+
const sorted = [
|
|
703
|
+
...exact
|
|
704
|
+
].sort();
|
|
705
|
+
if (!provider && !malformed && sorted.length === 1) return {
|
|
706
|
+
ok: true,
|
|
707
|
+
id: sorted[0],
|
|
708
|
+
form: "bare"
|
|
709
|
+
};
|
|
710
|
+
if (!provider && !malformed && sorted.length > 1) {
|
|
711
|
+
return {
|
|
712
|
+
ok: false,
|
|
713
|
+
reason: "ambiguous",
|
|
714
|
+
requested,
|
|
715
|
+
candidates: sorted
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
ok: false,
|
|
720
|
+
reason: "unknown",
|
|
721
|
+
requested,
|
|
722
|
+
candidates: sorted.length ? sorted : [
|
|
723
|
+
...hints
|
|
724
|
+
].sort()
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
__name(normalizeModelId, "normalizeModelId");
|
|
728
|
+
__name2(normalizeModelId, "normalizeModelId");
|
|
729
|
+
function modelUnresolvedMessage(r) {
|
|
730
|
+
if (r.reason === "empty") return "model pin is empty \u2014 pin an approved model (provider/model) or omit `model`";
|
|
731
|
+
if (r.reason === "ambiguous") {
|
|
732
|
+
return `model "${r.requested}" does not resolve to one approved model \u2014 it names ${r.candidates.length}; pin one of: ${r.candidates.join(", ")}`;
|
|
733
|
+
}
|
|
734
|
+
return r.candidates.length ? `model "${r.requested}" does not resolve to an approved model \u2014 accepted forms: ${r.candidates.join(", ")}` : `model "${r.requested}" does not resolve to an approved model \u2014 accepted forms are the registry's provider-prefixed ids (provider/model) or a bare id that names exactly one of them`;
|
|
735
|
+
}
|
|
736
|
+
__name(modelUnresolvedMessage, "modelUnresolvedMessage");
|
|
737
|
+
__name2(modelUnresolvedMessage, "modelUnresolvedMessage");
|
|
650
738
|
var IMPLICIT_MODEL_SELECTION_SOURCES = [
|
|
651
739
|
"workspace-default",
|
|
652
740
|
"platform-default"
|
|
@@ -1709,6 +1797,79 @@ var WORKFLOW_RETRY_BACKOFFS = [
|
|
|
1709
1797
|
"fixed",
|
|
1710
1798
|
"exponential"
|
|
1711
1799
|
];
|
|
1800
|
+
var WORKFLOW_RETRY_MIN_ATTEMPTS = 1;
|
|
1801
|
+
var WORKFLOW_RETRY_POLICY_KEYS = [
|
|
1802
|
+
"maxAttempts",
|
|
1803
|
+
"backoffSeconds",
|
|
1804
|
+
"backoff",
|
|
1805
|
+
"maxBackoffSeconds"
|
|
1806
|
+
];
|
|
1807
|
+
var WORKFLOW_RETRY_MAX_ATTEMPTS = 20;
|
|
1808
|
+
function workflowRetryMaxAttemptsMessage(got) {
|
|
1809
|
+
const tail = got === void 0 ? "" : ` (got ${JSON.stringify(got)})`;
|
|
1810
|
+
return `\`retry.maxAttempts\` must be an integer ${WORKFLOW_RETRY_MIN_ATTEMPTS}..${WORKFLOW_RETRY_MAX_ATTEMPTS}${tail}`;
|
|
1811
|
+
}
|
|
1812
|
+
__name(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
|
|
1813
|
+
__name2(workflowRetryMaxAttemptsMessage, "workflowRetryMaxAttemptsMessage");
|
|
1814
|
+
function isWithinWorkflowRetryAttempts(value3) {
|
|
1815
|
+
return typeof value3 === "number" && Number.isInteger(value3) && value3 >= WORKFLOW_RETRY_MIN_ATTEMPTS && value3 <= WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
1816
|
+
}
|
|
1817
|
+
__name(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
|
|
1818
|
+
__name2(isWithinWorkflowRetryAttempts, "isWithinWorkflowRetryAttempts");
|
|
1819
|
+
var WORKFLOW_RETRY_ENGINE_KEYS = [
|
|
1820
|
+
"budgetBaseAttempt"
|
|
1821
|
+
];
|
|
1822
|
+
function workflowRetryUnknownMembersMessage(keys) {
|
|
1823
|
+
const named = keys.map((k) => {
|
|
1824
|
+
const engine = WORKFLOW_RETRY_ENGINE_KEYS.includes(k);
|
|
1825
|
+
return `\`${k}\`${engine ? " (engine-owned \u2014 stamped by resetAttempts, never authored)" : ""}`;
|
|
1826
|
+
});
|
|
1827
|
+
return `\`retry\` has no member ${named.join(", ")}; members: ${WORKFLOW_RETRY_POLICY_KEYS.join(", ")}`;
|
|
1828
|
+
}
|
|
1829
|
+
__name(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
|
|
1830
|
+
__name2(workflowRetryUnknownMembersMessage, "workflowRetryUnknownMembersMessage");
|
|
1831
|
+
function unknownWorkflowRetryMembers(retry) {
|
|
1832
|
+
if (!retry || typeof retry !== "object" || Array.isArray(retry)) return [];
|
|
1833
|
+
return Object.keys(retry).filter((k) => !WORKFLOW_RETRY_POLICY_KEYS.includes(k));
|
|
1834
|
+
}
|
|
1835
|
+
__name(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
|
|
1836
|
+
__name2(unknownWorkflowRetryMembers, "unknownWorkflowRetryMembers");
|
|
1837
|
+
function authoredRetryPolicy(retry) {
|
|
1838
|
+
if (!retry || typeof retry !== "object" || Array.isArray(retry)) return void 0;
|
|
1839
|
+
const src = retry;
|
|
1840
|
+
const out = {};
|
|
1841
|
+
for (const k of WORKFLOW_RETRY_POLICY_KEYS) if (src[k] !== void 0) out[k] = src[k];
|
|
1842
|
+
return Object.keys(out).length ? out : void 0;
|
|
1843
|
+
}
|
|
1844
|
+
__name(authoredRetryPolicy, "authoredRetryPolicy");
|
|
1845
|
+
__name2(authoredRetryPolicy, "authoredRetryPolicy");
|
|
1846
|
+
function retryBudgetBaseAttempt(row) {
|
|
1847
|
+
const base = row.retry?.budgetBaseAttempt;
|
|
1848
|
+
return typeof base === "number" && Number.isSafeInteger(base) && base > 0 ? base : 0;
|
|
1849
|
+
}
|
|
1850
|
+
__name(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
|
|
1851
|
+
__name2(retryBudgetBaseAttempt, "retryBudgetBaseAttempt");
|
|
1852
|
+
function retryBudgetAttempt(row) {
|
|
1853
|
+
return Math.max(0, row.attempt - retryBudgetBaseAttempt(row));
|
|
1854
|
+
}
|
|
1855
|
+
__name(retryBudgetAttempt, "retryBudgetAttempt");
|
|
1856
|
+
__name2(retryBudgetAttempt, "retryBudgetAttempt");
|
|
1857
|
+
function retryBudgetMaxAttempts(row) {
|
|
1858
|
+
const max = row.retry?.maxAttempts;
|
|
1859
|
+
return typeof max === "number" && Number.isFinite(max) && max >= 1 ? max : 1;
|
|
1860
|
+
}
|
|
1861
|
+
__name(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
|
|
1862
|
+
__name2(retryBudgetMaxAttempts, "retryBudgetMaxAttempts");
|
|
1863
|
+
function retryBudgetRemaining(row) {
|
|
1864
|
+
return retryBudgetAttempt(row) < retryBudgetMaxAttempts(row);
|
|
1865
|
+
}
|
|
1866
|
+
__name(retryBudgetRemaining, "retryBudgetRemaining");
|
|
1867
|
+
__name2(retryBudgetRemaining, "retryBudgetRemaining");
|
|
1868
|
+
function retriesRemaining(row) {
|
|
1869
|
+
return Math.max(0, retryBudgetMaxAttempts(row) - retryBudgetAttempt(row));
|
|
1870
|
+
}
|
|
1871
|
+
__name(retriesRemaining, "retriesRemaining");
|
|
1872
|
+
__name2(retriesRemaining, "retriesRemaining");
|
|
1712
1873
|
var WORKFLOW_JOB_RESOURCES = [
|
|
1713
1874
|
"small",
|
|
1714
1875
|
"medium",
|
|
@@ -2074,6 +2235,8 @@ var WORKFLOW_AUDIT_EVENTS = [
|
|
|
2074
2235
|
"workflow.goal.resumed",
|
|
2075
2236
|
"workflow.goal.done",
|
|
2076
2237
|
"workflow.goal.closed",
|
|
2238
|
+
// LUA-760: an ended goal's cadence Job retired (deleted) — inline on done / closed, by R21 / R28, or by sweep #30
|
|
2239
|
+
"workflow.goal.job_retired",
|
|
2077
2240
|
// --- org policy (02 §2.10 / 09 R23) ---
|
|
2078
2241
|
"workflow.policy.retention_changed",
|
|
2079
2242
|
"workflow.policy.pacing_changed",
|
|
@@ -2217,6 +2380,138 @@ ${items.join("\n\n")}`;
|
|
|
2217
2380
|
}
|
|
2218
2381
|
__name(renderTargetsBlock, "renderTargetsBlock");
|
|
2219
2382
|
__name2(renderTargetsBlock, "renderTargetsBlock");
|
|
2383
|
+
var WORKFLOW_APPROVAL_OUTPUT_DECISIONS = [
|
|
2384
|
+
"approved",
|
|
2385
|
+
"denied",
|
|
2386
|
+
"timed_out"
|
|
2387
|
+
];
|
|
2388
|
+
var WORKFLOW_APPROVAL_OUTPUT_SCHEMA = {
|
|
2389
|
+
type: "object",
|
|
2390
|
+
properties: {
|
|
2391
|
+
approved: {
|
|
2392
|
+
type: "boolean"
|
|
2393
|
+
},
|
|
2394
|
+
decision: {
|
|
2395
|
+
type: "string",
|
|
2396
|
+
enum: [
|
|
2397
|
+
...WORKFLOW_APPROVAL_OUTPUT_DECISIONS
|
|
2398
|
+
]
|
|
2399
|
+
},
|
|
2400
|
+
/** the approver's note when given, else the decision word — what `${stepResults.<id>.text}` reads */
|
|
2401
|
+
text: {
|
|
2402
|
+
type: "string"
|
|
2403
|
+
},
|
|
2404
|
+
note: {
|
|
2405
|
+
type: "string"
|
|
2406
|
+
},
|
|
2407
|
+
editedPayload: {},
|
|
2408
|
+
editRevision: {
|
|
2409
|
+
type: "integer"
|
|
2410
|
+
},
|
|
2411
|
+
decidedBy: {
|
|
2412
|
+
type: "object",
|
|
2413
|
+
properties: {
|
|
2414
|
+
id: {
|
|
2415
|
+
type: "string"
|
|
2416
|
+
},
|
|
2417
|
+
kind: {
|
|
2418
|
+
type: "string"
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
},
|
|
2422
|
+
timedOut: {
|
|
2423
|
+
type: "boolean"
|
|
2424
|
+
},
|
|
2425
|
+
escalations: {
|
|
2426
|
+
type: "integer"
|
|
2427
|
+
},
|
|
2428
|
+
evidence: {
|
|
2429
|
+
type: "array",
|
|
2430
|
+
items: {
|
|
2431
|
+
type: "string"
|
|
2432
|
+
}
|
|
2433
|
+
},
|
|
2434
|
+
items: {
|
|
2435
|
+
type: "array",
|
|
2436
|
+
items: {
|
|
2437
|
+
type: "object"
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
},
|
|
2441
|
+
required: [
|
|
2442
|
+
"approved",
|
|
2443
|
+
"decision",
|
|
2444
|
+
"text"
|
|
2445
|
+
]
|
|
2446
|
+
};
|
|
2447
|
+
function workflowApprovalDecisionOf(resumeData) {
|
|
2448
|
+
if (resumeData.timedOut === true) return "timed_out";
|
|
2449
|
+
return resumeData.approved === true ? "approved" : "denied";
|
|
2450
|
+
}
|
|
2451
|
+
__name(workflowApprovalDecisionOf, "workflowApprovalDecisionOf");
|
|
2452
|
+
__name2(workflowApprovalDecisionOf, "workflowApprovalDecisionOf");
|
|
2453
|
+
function workflowApprovalOutput(resumeData) {
|
|
2454
|
+
const decision = typeof resumeData.decision === "string" ? resumeData.decision : workflowApprovalDecisionOf(resumeData);
|
|
2455
|
+
const note = typeof resumeData.note === "string" && resumeData.note.trim() !== "" ? resumeData.note : void 0;
|
|
2456
|
+
const text = typeof resumeData.text === "string" ? resumeData.text : note ?? decision;
|
|
2457
|
+
return {
|
|
2458
|
+
...resumeData,
|
|
2459
|
+
decision,
|
|
2460
|
+
text
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
__name(workflowApprovalOutput, "workflowApprovalOutput");
|
|
2464
|
+
__name2(workflowApprovalOutput, "workflowApprovalOutput");
|
|
2465
|
+
function isWorkflowApprovalOutput(value3) {
|
|
2466
|
+
if (typeof value3 !== "object" || value3 === null || Array.isArray(value3)) return false;
|
|
2467
|
+
const v = value3;
|
|
2468
|
+
return typeof v.approved === "boolean" && WORKFLOW_APPROVAL_OUTPUT_DECISIONS.includes(v.decision) && typeof v.text === "string";
|
|
2469
|
+
}
|
|
2470
|
+
__name(isWorkflowApprovalOutput, "isWorkflowApprovalOutput");
|
|
2471
|
+
__name2(isWorkflowApprovalOutput, "isWorkflowApprovalOutput");
|
|
2472
|
+
var JSON_FENCE_RE = /```(?:json)?[ \t]*\r?\n([\s\S]*?)\r?\n?```/g;
|
|
2473
|
+
function extractSingleJsonValue(text) {
|
|
2474
|
+
const trimmed = (text ?? "").trim();
|
|
2475
|
+
if (!trimmed) return {
|
|
2476
|
+
reason: "reply is empty"
|
|
2477
|
+
};
|
|
2478
|
+
const fenced = [
|
|
2479
|
+
...trimmed.matchAll(JSON_FENCE_RE)
|
|
2480
|
+
];
|
|
2481
|
+
if (fenced.length > 1) return {
|
|
2482
|
+
reason: "reply carries more than one fenced block"
|
|
2483
|
+
};
|
|
2484
|
+
const candidate = fenced.length === 1 ? fenced[0][1].trim() : trimmed;
|
|
2485
|
+
try {
|
|
2486
|
+
return {
|
|
2487
|
+
value: JSON.parse(candidate)
|
|
2488
|
+
};
|
|
2489
|
+
} catch {
|
|
2490
|
+
if (fenced.length === 1) return {
|
|
2491
|
+
reason: "fenced block is not valid JSON"
|
|
2492
|
+
};
|
|
2493
|
+
}
|
|
2494
|
+
const opens = [
|
|
2495
|
+
trimmed.indexOf("{"),
|
|
2496
|
+
trimmed.indexOf("[")
|
|
2497
|
+
].filter((i) => i !== -1);
|
|
2498
|
+
const start = opens.length ? Math.min(...opens) : -1;
|
|
2499
|
+
const end = Math.max(trimmed.lastIndexOf("}"), trimmed.lastIndexOf("]"));
|
|
2500
|
+
if (start === -1 || end <= start) return {
|
|
2501
|
+
reason: "reply is not JSON"
|
|
2502
|
+
};
|
|
2503
|
+
try {
|
|
2504
|
+
return {
|
|
2505
|
+
value: JSON.parse(trimmed.slice(start, end + 1))
|
|
2506
|
+
};
|
|
2507
|
+
} catch {
|
|
2508
|
+
return {
|
|
2509
|
+
reason: "reply does not contain a single JSON value"
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
__name(extractSingleJsonValue, "extractSingleJsonValue");
|
|
2514
|
+
__name2(extractSingleJsonValue, "extractSingleJsonValue");
|
|
2220
2515
|
|
|
2221
2516
|
// ../workflow-graph/dist/index.mjs
|
|
2222
2517
|
import { createHash } from "crypto";
|
|
@@ -2225,122 +2520,620 @@ import { z as z22 } from "zod";
|
|
|
2225
2520
|
import { createHash as createHash2 } from "crypto";
|
|
2226
2521
|
var __defProp3 = Object.defineProperty;
|
|
2227
2522
|
var __name3 = /* @__PURE__ */ __name((target, value22) => __defProp3(target, "name", { value: value22, configurable: true }), "__name");
|
|
2228
|
-
var
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2523
|
+
var WorkflowTemplateError = class extends Error {
|
|
2524
|
+
static {
|
|
2525
|
+
__name(this, "WorkflowTemplateError");
|
|
2526
|
+
}
|
|
2527
|
+
static {
|
|
2528
|
+
__name3(this, "WorkflowTemplateError");
|
|
2529
|
+
}
|
|
2530
|
+
placeholder;
|
|
2531
|
+
constructor(message, placeholder) {
|
|
2532
|
+
super(message), this.placeholder = placeholder;
|
|
2533
|
+
this.name = "WorkflowTemplateError";
|
|
2534
|
+
}
|
|
2535
|
+
};
|
|
2536
|
+
function isMapConfigObject(v) {
|
|
2537
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2238
2538
|
}
|
|
2239
|
-
__name(
|
|
2240
|
-
__name3(
|
|
2241
|
-
function
|
|
2242
|
-
if (
|
|
2243
|
-
|
|
2539
|
+
__name(isMapConfigObject, "isMapConfigObject");
|
|
2540
|
+
__name3(isMapConfigObject, "isMapConfigObject");
|
|
2541
|
+
function parseMapConfig(raw, stepId) {
|
|
2542
|
+
if (isMapConfigObject(raw)) return raw;
|
|
2543
|
+
if (typeof raw !== "string") {
|
|
2544
|
+
throw new Error(`Stored mapping step "${stepId}" has a mapConfig that is neither a JSON string nor an object.`);
|
|
2545
|
+
}
|
|
2546
|
+
try {
|
|
2547
|
+
return JSON.parse(raw);
|
|
2548
|
+
} catch (e) {
|
|
2549
|
+
throw new Error(`Stored mapping step "${stepId}" has invalid JSON mapConfig: ${e.message}`);
|
|
2244
2550
|
}
|
|
2245
|
-
return WORKFLOW_RETRY_BACKOFFS;
|
|
2246
2551
|
}
|
|
2247
|
-
__name(
|
|
2248
|
-
__name3(
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
function sleepUntilUnsupportedMessage(id) {
|
|
2254
|
-
return `the engine does not execute \`sleepUntil\` yet (node "${id}") \u2014 replace it with a \`sleep\` node with a \`duration\` in ms, e.g. { type: 'sleep', id: '${id}', duration: ${SLEEP_UNTIL_REPLACEMENT.duration} }`;
|
|
2552
|
+
__name(parseMapConfig, "parseMapConfig");
|
|
2553
|
+
__name3(parseMapConfig, "parseMapConfig");
|
|
2554
|
+
function mapConfigWire(raw) {
|
|
2555
|
+
if (typeof raw === "string") return raw;
|
|
2556
|
+
if (isMapConfigObject(raw)) return canonicalJson(raw);
|
|
2557
|
+
return void 0;
|
|
2255
2558
|
}
|
|
2256
|
-
__name(
|
|
2257
|
-
__name3(
|
|
2258
|
-
var
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
maxForeachRatePerSecond: 50,
|
|
2265
|
-
maxLoopIntervalSeconds: 86400,
|
|
2266
|
-
maxWorkerTimeoutSeconds: 600,
|
|
2267
|
-
maxJobTimeoutSeconds: 86400,
|
|
2268
|
-
maxJobSegmentSeconds: 14400
|
|
2269
|
-
});
|
|
2270
|
-
var WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS = 300;
|
|
2271
|
-
var WORKFLOW_AGENT_DEFAULT_TIMEOUT_SECONDS = 600;
|
|
2272
|
-
var WORKFLOW_JOB_DEFAULT_TIMEOUT_SECONDS = 3600;
|
|
2273
|
-
var WORKFLOW_FOREACH_DEFAULT_CONCURRENCY = 4;
|
|
2274
|
-
var WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS = 256;
|
|
2275
|
-
var WORKFLOW_LOOP_DEFAULT_MAX_ITERATIONS = 100;
|
|
2276
|
-
var WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS = 168;
|
|
2277
|
-
var WORKFLOW_SIGNAL_DEFAULT_SOURCES = [
|
|
2278
|
-
"webhook",
|
|
2279
|
-
"api",
|
|
2280
|
-
"user"
|
|
2559
|
+
__name(mapConfigWire, "mapConfigWire");
|
|
2560
|
+
__name3(mapConfigWire, "mapConfigWire");
|
|
2561
|
+
var TEMPLATE_PLACEHOLDER = /\$\{([^}]*)\}/g;
|
|
2562
|
+
var TEMPLATE_NAMESPACES = [
|
|
2563
|
+
"initData",
|
|
2564
|
+
"state",
|
|
2565
|
+
"requestContext",
|
|
2566
|
+
"stepResults"
|
|
2281
2567
|
];
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2568
|
+
function describeBadPlaceholder(template22, idx, rawExpr) {
|
|
2569
|
+
return `Template placeholder #${idx} (\${${rawExpr}}) in '${template22}'`;
|
|
2570
|
+
}
|
|
2571
|
+
__name(describeBadPlaceholder, "describeBadPlaceholder");
|
|
2572
|
+
__name3(describeBadPlaceholder, "describeBadPlaceholder");
|
|
2573
|
+
function parseTemplatePlaceholder(rawExpr) {
|
|
2574
|
+
const dot = rawExpr.indexOf(".");
|
|
2575
|
+
return {
|
|
2576
|
+
scope: dot === -1 ? rawExpr : rawExpr.slice(0, dot),
|
|
2577
|
+
rest: dot === -1 ? "" : rawExpr.slice(dot + 1)
|
|
2288
2578
|
};
|
|
2289
|
-
if (node.onError === void 0) node.onError = "fail";
|
|
2290
|
-
if ((node.type === "step" || node.type === "tool") && node.sideEffects === void 0) node.sideEffects = "none";
|
|
2291
2579
|
}
|
|
2292
|
-
__name(
|
|
2293
|
-
__name3(
|
|
2294
|
-
function
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
return;
|
|
2302
|
-
}
|
|
2303
|
-
case "agent":
|
|
2304
|
-
fillPolicy(node, WORKFLOW_AGENT_DEFAULT_TIMEOUT_SECONDS);
|
|
2305
|
-
return;
|
|
2306
|
-
case "tool":
|
|
2307
|
-
fillPolicy(node, WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS);
|
|
2308
|
-
return;
|
|
2309
|
-
case "workflow":
|
|
2310
|
-
if (node.workflowId === WORKFLOW_ARM_SUBRUN_ID && Array.isArray(node.graph) && node.graph[1]) fillSingle(node.graph[1]);
|
|
2311
|
-
return;
|
|
2580
|
+
__name(parseTemplatePlaceholder, "parseTemplatePlaceholder");
|
|
2581
|
+
__name3(parseTemplatePlaceholder, "parseTemplatePlaceholder");
|
|
2582
|
+
function traverseMappingPath(root, path, errorLabel) {
|
|
2583
|
+
if (path === "" || path === ".") return root;
|
|
2584
|
+
const parts = path.split(".");
|
|
2585
|
+
let value22 = root;
|
|
2586
|
+
for (const part of parts) {
|
|
2587
|
+
if (typeof value22 === "object" && value22 !== null) value22 = value22[part];
|
|
2588
|
+
else throw new WorkflowTemplateError(`Invalid path ${path} in ${errorLabel}`, path);
|
|
2312
2589
|
}
|
|
2590
|
+
return value22;
|
|
2313
2591
|
}
|
|
2314
|
-
__name(
|
|
2315
|
-
__name3(
|
|
2316
|
-
function
|
|
2317
|
-
if (
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
if (a.editable === void 0) a.editable = false;
|
|
2325
|
-
return;
|
|
2592
|
+
__name(traverseMappingPath, "traverseMappingPath");
|
|
2593
|
+
__name3(traverseMappingPath, "traverseMappingPath");
|
|
2594
|
+
function stringifyTemplateValue(v, template22, idx, rawExpr) {
|
|
2595
|
+
if (v === null || v === void 0) return "";
|
|
2596
|
+
if (typeof v === "object") {
|
|
2597
|
+
try {
|
|
2598
|
+
return JSON.stringify(v);
|
|
2599
|
+
} catch (err) {
|
|
2600
|
+
throw new WorkflowTemplateError(`${describeBadPlaceholder(template22, idx, rawExpr)} resolved to a value that could not be JSON-stringified (${err.message}).`, rawExpr);
|
|
2601
|
+
}
|
|
2326
2602
|
}
|
|
2327
|
-
|
|
2328
|
-
if (w.timeoutHours === void 0) w.timeoutHours = WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS;
|
|
2329
|
-
if (w.onTimeout === void 0) w.onTimeout = "fail";
|
|
2330
|
-
if (w.acceptedSources === void 0) w.acceptedSources = [
|
|
2331
|
-
...WORKFLOW_SIGNAL_DEFAULT_SOURCES
|
|
2332
|
-
];
|
|
2603
|
+
return String(v);
|
|
2333
2604
|
}
|
|
2334
|
-
__name(
|
|
2335
|
-
__name3(
|
|
2336
|
-
function
|
|
2337
|
-
|
|
2338
|
-
if (isHitlNode(arm)) fillHitl(arm);
|
|
2339
|
-
else fillSingle(arm);
|
|
2605
|
+
__name(stringifyTemplateValue, "stringifyTemplateValue");
|
|
2606
|
+
__name3(stringifyTemplateValue, "stringifyTemplateValue");
|
|
2607
|
+
function escapeFence(content) {
|
|
2608
|
+
return content.replace(/<\/lua-data/g, "<\\/lua-data");
|
|
2340
2609
|
}
|
|
2341
|
-
__name(
|
|
2342
|
-
__name3(
|
|
2343
|
-
function
|
|
2610
|
+
__name(escapeFence, "escapeFence");
|
|
2611
|
+
__name3(escapeFence, "escapeFence");
|
|
2612
|
+
function fenceBlock(name, source, content) {
|
|
2613
|
+
return `<lua-data name="${name}" source="${source}" untrusted="true">${escapeFence(content)}</lua-data>`;
|
|
2614
|
+
}
|
|
2615
|
+
__name(fenceBlock, "fenceBlock");
|
|
2616
|
+
__name3(fenceBlock, "fenceBlock");
|
|
2617
|
+
function renderTemplate(template22, ctx, opts) {
|
|
2618
|
+
let idx = 0;
|
|
2619
|
+
return template22.replace(TEMPLATE_PLACEHOLDER, (_match, rawExpr) => {
|
|
2620
|
+
idx += 1;
|
|
2621
|
+
const { scope, rest } = parseTemplatePlaceholder(rawExpr);
|
|
2622
|
+
const label = describeBadPlaceholder(template22, idx, rawExpr);
|
|
2623
|
+
let rendered;
|
|
2624
|
+
let source;
|
|
2625
|
+
switch (scope) {
|
|
2626
|
+
case "initData":
|
|
2627
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.initData, rest, label), template22, idx, rawExpr);
|
|
2628
|
+
source = "initData";
|
|
2629
|
+
break;
|
|
2630
|
+
case "state":
|
|
2631
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.state, rest, label), template22, idx, rawExpr);
|
|
2632
|
+
source = "state";
|
|
2633
|
+
break;
|
|
2634
|
+
case "requestContext":
|
|
2635
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.requestContext, rest, label), template22, idx, rawExpr);
|
|
2636
|
+
source = "requestContext";
|
|
2637
|
+
break;
|
|
2638
|
+
case "stepResults": {
|
|
2639
|
+
const innerDot = rest.indexOf(".");
|
|
2640
|
+
const stepId = innerDot === -1 ? rest : rest.slice(0, innerDot);
|
|
2641
|
+
const subPath = innerDot === -1 ? "" : rest.slice(innerDot + 1);
|
|
2642
|
+
if (!stepId) throw new WorkflowTemplateError(`${label} must name a step: \${stepResults.<stepId>.<path>}.`, rawExpr);
|
|
2643
|
+
if (!(stepId in ctx.stepResults) || ctx.stepResults[stepId] == null) {
|
|
2644
|
+
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);
|
|
2645
|
+
}
|
|
2646
|
+
rendered = stringifyTemplateValue(traverseMappingPath(ctx.stepResults[stepId], subPath, label), template22, idx, rawExpr);
|
|
2647
|
+
source = `step:${stepId}`;
|
|
2648
|
+
break;
|
|
2649
|
+
}
|
|
2650
|
+
default:
|
|
2651
|
+
throw new WorkflowTemplateError(`${label} references unknown namespace "${scope}". Use one of: ${TEMPLATE_NAMESPACES.join(", ")}.`, rawExpr);
|
|
2652
|
+
}
|
|
2653
|
+
return opts.fenced ? fenceBlock(rawExpr, source, rendered) : rendered;
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
__name(renderTemplate, "renderTemplate");
|
|
2657
|
+
__name3(renderTemplate, "renderTemplate");
|
|
2658
|
+
function isMapDescriptor(v) {
|
|
2659
|
+
if (v === null || typeof v !== "object" || Array.isArray(v)) return false;
|
|
2660
|
+
const d = v;
|
|
2661
|
+
const keys = Object.keys(d);
|
|
2662
|
+
const only = /* @__PURE__ */ __name3((...allowed) => keys.every((k) => allowed.includes(k)), "only");
|
|
2663
|
+
if ("value" in d) return keys.length === 1;
|
|
2664
|
+
if ("template" in d) return keys.length === 1 && typeof d.template === "string";
|
|
2665
|
+
if ("requestContextPath" in d) return keys.length === 1 && typeof d.requestContextPath === "string";
|
|
2666
|
+
if ("knowledge" in d) return keys.length === 1 && typeof d.knowledge === "object" && d.knowledge !== null;
|
|
2667
|
+
if ("initData" in d) return d.initData === true && typeof d.path === "string" && only("initData", "path");
|
|
2668
|
+
if ("step" in d) {
|
|
2669
|
+
const stepOk = typeof d.step === "string" || Array.isArray(d.step) && d.step.every((x) => typeof x === "string");
|
|
2670
|
+
return stepOk && typeof d.path === "string" && only("step", "path", "rows");
|
|
2671
|
+
}
|
|
2672
|
+
return false;
|
|
2673
|
+
}
|
|
2674
|
+
__name(isMapDescriptor, "isMapDescriptor");
|
|
2675
|
+
__name3(isMapDescriptor, "isMapDescriptor");
|
|
2676
|
+
var MAP_DESCRIPTOR_KEYS = [
|
|
2677
|
+
"step",
|
|
2678
|
+
"path",
|
|
2679
|
+
"initData",
|
|
2680
|
+
"value",
|
|
2681
|
+
"template",
|
|
2682
|
+
"requestContextPath",
|
|
2683
|
+
"knowledge"
|
|
2684
|
+
];
|
|
2685
|
+
var MAP_MEMBER_MALFORMED_CODE = "map-member-malformed";
|
|
2686
|
+
function malformedMapMembers(cfg) {
|
|
2687
|
+
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) return [];
|
|
2688
|
+
const out = [];
|
|
2689
|
+
for (const [member, v] of Object.entries(cfg)) {
|
|
2690
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || isMapDescriptor(v)) continue;
|
|
2691
|
+
const keys = Object.keys(v).filter((k) => MAP_DESCRIPTOR_KEYS.includes(k));
|
|
2692
|
+
if (keys.length > 0) out.push({
|
|
2693
|
+
member,
|
|
2694
|
+
keys
|
|
2695
|
+
});
|
|
2696
|
+
}
|
|
2697
|
+
return out;
|
|
2698
|
+
}
|
|
2699
|
+
__name(malformedMapMembers, "malformedMapMembers");
|
|
2700
|
+
__name3(malformedMapMembers, "malformedMapMembers");
|
|
2701
|
+
function mapMemberMalformedMessage(id, m) {
|
|
2702
|
+
const keys = m.keys.map((k) => `\`${k}\``).join(", ");
|
|
2703
|
+
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`;
|
|
2704
|
+
}
|
|
2705
|
+
__name(mapMemberMalformedMessage, "mapMemberMalformedMessage");
|
|
2706
|
+
__name3(mapMemberMalformedMessage, "mapMemberMalformedMessage");
|
|
2707
|
+
function resolveDescriptor(key, m, ctx) {
|
|
2708
|
+
if (!isMapDescriptor(m)) return {
|
|
2709
|
+
value: m
|
|
2710
|
+
};
|
|
2711
|
+
try {
|
|
2712
|
+
if ("value" in m) return {
|
|
2713
|
+
value: m.value
|
|
2714
|
+
};
|
|
2715
|
+
if ("template" in m && typeof m.template === "string") {
|
|
2716
|
+
return {
|
|
2717
|
+
value: renderTemplate(m.template, ctx, {
|
|
2718
|
+
fenced: false
|
|
2719
|
+
})
|
|
2720
|
+
};
|
|
2721
|
+
}
|
|
2722
|
+
if ("knowledge" in m || "rows" in m && m.rows !== void 0) {
|
|
2723
|
+
return {
|
|
2724
|
+
error: "binding_unresolved",
|
|
2725
|
+
key
|
|
2726
|
+
};
|
|
2727
|
+
}
|
|
2728
|
+
if ("requestContextPath" in m) {
|
|
2729
|
+
const label = `requestContext path for key "${key}"`;
|
|
2730
|
+
return {
|
|
2731
|
+
value: traverseMappingPath(ctx.requestContext, m.requestContextPath, label)
|
|
2732
|
+
};
|
|
2733
|
+
}
|
|
2734
|
+
if ("path" in m) {
|
|
2735
|
+
const source = "initData" in m && m.initData ? "initData" : "step";
|
|
2736
|
+
if (source === "initData") {
|
|
2737
|
+
return {
|
|
2738
|
+
value: traverseMappingPath(ctx.initData, m.path, `initData for key "${key}"`)
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
const stepRef = m.step;
|
|
2742
|
+
const candidates = Array.isArray(stepRef) ? stepRef : [
|
|
2743
|
+
stepRef
|
|
2744
|
+
];
|
|
2745
|
+
const stepId = candidates.find((s) => ctx.stepResults[s] !== void 0 && ctx.stepResults[s] !== null);
|
|
2746
|
+
if (stepId === void 0) return {
|
|
2747
|
+
error: "binding_unresolved",
|
|
2748
|
+
key
|
|
2749
|
+
};
|
|
2750
|
+
return {
|
|
2751
|
+
value: traverseMappingPath(ctx.stepResults[stepId], m.path, `step ${candidates.join("|")} for key "${key}"`)
|
|
2752
|
+
};
|
|
2753
|
+
}
|
|
2754
|
+
return {
|
|
2755
|
+
error: "binding_unresolved",
|
|
2756
|
+
key
|
|
2757
|
+
};
|
|
2758
|
+
} catch (err) {
|
|
2759
|
+
if (err instanceof WorkflowTemplateError) return {
|
|
2760
|
+
error: "binding_unresolved",
|
|
2761
|
+
key
|
|
2762
|
+
};
|
|
2763
|
+
throw err;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
__name(resolveDescriptor, "resolveDescriptor");
|
|
2767
|
+
__name3(resolveDescriptor, "resolveDescriptor");
|
|
2768
|
+
function resolveMapping(cfg, ctx) {
|
|
2769
|
+
const keys = Object.keys(cfg);
|
|
2770
|
+
if (keys.length === 1 && keys[0] === "") {
|
|
2771
|
+
return resolveDescriptor("", cfg[""], ctx);
|
|
2772
|
+
}
|
|
2773
|
+
const result = {};
|
|
2774
|
+
for (const key of keys) {
|
|
2775
|
+
const resolved = resolveDescriptor(key, cfg[key], ctx);
|
|
2776
|
+
if ("error" in resolved) return resolved;
|
|
2777
|
+
result[key] = resolved.value;
|
|
2778
|
+
}
|
|
2779
|
+
return {
|
|
2780
|
+
value: result
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
__name(resolveMapping, "resolveMapping");
|
|
2784
|
+
__name3(resolveMapping, "resolveMapping");
|
|
2785
|
+
var fromInit = /* @__PURE__ */ __name3((path) => ({
|
|
2786
|
+
initData: true,
|
|
2787
|
+
path
|
|
2788
|
+
}), "fromInit");
|
|
2789
|
+
var fromStep = /* @__PURE__ */ __name3((s, path = "") => {
|
|
2790
|
+
const idOf = /* @__PURE__ */ __name3((x) => typeof x === "string" ? x : x.id, "idOf");
|
|
2791
|
+
return {
|
|
2792
|
+
step: Array.isArray(s) ? s.map(idOf) : idOf(s),
|
|
2793
|
+
path
|
|
2794
|
+
};
|
|
2795
|
+
}, "fromStep");
|
|
2796
|
+
var value = /* @__PURE__ */ __name3((v) => ({
|
|
2797
|
+
value: v
|
|
2798
|
+
}), "value");
|
|
2799
|
+
var template = /* @__PURE__ */ __name3((s) => ({
|
|
2800
|
+
template: s
|
|
2801
|
+
}), "template");
|
|
2802
|
+
var fromRequest = /* @__PURE__ */ __name3((path) => ({
|
|
2803
|
+
requestContextPath: path
|
|
2804
|
+
}), "fromRequest");
|
|
2805
|
+
var rows = /* @__PURE__ */ __name3((s, path, page) => ({
|
|
2806
|
+
step: typeof s === "string" ? s : s.id,
|
|
2807
|
+
path,
|
|
2808
|
+
rows: page
|
|
2809
|
+
}), "rows");
|
|
2810
|
+
var fromKnowledge = /* @__PURE__ */ __name3((k) => ({
|
|
2811
|
+
knowledge: k
|
|
2812
|
+
}), "fromKnowledge");
|
|
2813
|
+
var SideEffectsSchema = z4.enum(WORKFLOW_SIDE_EFFECTS);
|
|
2814
|
+
var JobResourcesSchema = z4.enum(WORKFLOW_JOB_RESOURCES);
|
|
2815
|
+
var APPROVER_SPEC_MAX_USERS = 20;
|
|
2816
|
+
var ESCALATION_MAX_HOPS = 3;
|
|
2817
|
+
var TemplateBindingSchema = z22.object({
|
|
2818
|
+
template: z22.string().min(1).max(2048)
|
|
2819
|
+
}).strict();
|
|
2820
|
+
var ApproverSpecSchema = z22.union([
|
|
2821
|
+
z22.literal("creator"),
|
|
2822
|
+
z22.literal("org-admins"),
|
|
2823
|
+
z22.object({
|
|
2824
|
+
users: z22.union([
|
|
2825
|
+
z22.array(z22.string().min(1).max(128)).min(1).max(APPROVER_SPEC_MAX_USERS),
|
|
2826
|
+
TemplateBindingSchema
|
|
2827
|
+
])
|
|
2828
|
+
}).strict(),
|
|
2829
|
+
z22.object({
|
|
2830
|
+
role: z22.union([
|
|
2831
|
+
z22.string().min(1).max(128),
|
|
2832
|
+
TemplateBindingSchema
|
|
2833
|
+
])
|
|
2834
|
+
}).strict(),
|
|
2835
|
+
z22.object({
|
|
2836
|
+
group: z22.union([
|
|
2837
|
+
z22.string().min(1).max(128),
|
|
2838
|
+
TemplateBindingSchema
|
|
2839
|
+
])
|
|
2840
|
+
}).strict(),
|
|
2841
|
+
z22.object({
|
|
2842
|
+
governance: z22.object({
|
|
2843
|
+
policyId: z22.string().min(1).max(128)
|
|
2844
|
+
}).strict()
|
|
2845
|
+
}).strict()
|
|
2846
|
+
]);
|
|
2847
|
+
var FourEyesSchema = z22.object({
|
|
2848
|
+
edit: ApproverSpecSchema,
|
|
2849
|
+
approve: ApproverSpecSchema
|
|
2850
|
+
}).strict();
|
|
2851
|
+
var EscalationHopSchema = z22.object({
|
|
2852
|
+
escalateTo: ApproverSpecSchema,
|
|
2853
|
+
timeoutHours: z22.number().finite().min(1).max(720)
|
|
2854
|
+
}).strict();
|
|
2855
|
+
var TerminalOutcomeSchema = z22.enum([
|
|
2856
|
+
"deny",
|
|
2857
|
+
"cancel-run",
|
|
2858
|
+
"fail",
|
|
2859
|
+
"continue"
|
|
2860
|
+
]);
|
|
2861
|
+
var ApprovalOnTimeoutSchema = z22.union([
|
|
2862
|
+
TerminalOutcomeSchema,
|
|
2863
|
+
EscalationHopSchema,
|
|
2864
|
+
z22.array(z22.union([
|
|
2865
|
+
TerminalOutcomeSchema,
|
|
2866
|
+
EscalationHopSchema
|
|
2867
|
+
])).min(1).max(ESCALATION_MAX_HOPS + 1)
|
|
2868
|
+
]);
|
|
2869
|
+
var APPROVER_SPEC_SHAPES = [
|
|
2870
|
+
"'creator'",
|
|
2871
|
+
"'org-admins'",
|
|
2872
|
+
"{users:[userId, \u2026]}",
|
|
2873
|
+
"{role:roleName}",
|
|
2874
|
+
"{group:groupName}",
|
|
2875
|
+
"{governance:{policyId}}"
|
|
2876
|
+
];
|
|
2877
|
+
var APPROVER_WRITTEN_MAX = 120;
|
|
2878
|
+
var USER_ID_SHAPED_RE = /^[^\s@]{1,128}$/;
|
|
2879
|
+
function describeApproverSpecRefusal(spec) {
|
|
2880
|
+
const raw = spec === void 0 ? "undefined" : JSON.stringify(spec) ?? String(spec);
|
|
2881
|
+
const written = raw.length > APPROVER_WRITTEN_MAX ? `${raw.slice(0, APPROVER_WRITTEN_MAX - 1)}\u2026` : raw;
|
|
2882
|
+
const users = typeof spec === "object" && spec !== null ? spec.users : void 0;
|
|
2883
|
+
const approver = typeof users === "string" && USER_ID_SHAPED_RE.test(users) ? {
|
|
2884
|
+
users: [
|
|
2885
|
+
users
|
|
2886
|
+
]
|
|
2887
|
+
} : "creator";
|
|
2888
|
+
const message = `approver ${written} is not an approver \u2014 legal: ${APPROVER_SPEC_SHAPES.join(" | ")}. 'creator' is the person who started the run: write approver:'creator' for "ask me" / "I approve"; {users:[\u2026]} takes user ids, never emails, names or {type:'user'}` + (approver === "creator" ? "" : `; here: approver:${JSON.stringify(approver)}`);
|
|
2889
|
+
return {
|
|
2890
|
+
approver,
|
|
2891
|
+
written,
|
|
2892
|
+
message
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2895
|
+
__name(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
2896
|
+
__name3(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
2897
|
+
var BINDING_ROOTS = [
|
|
2898
|
+
"initData",
|
|
2899
|
+
"stepResults",
|
|
2900
|
+
"requestContext",
|
|
2901
|
+
"state"
|
|
2902
|
+
];
|
|
2903
|
+
function bindingRootsOk(template22) {
|
|
2904
|
+
const refs = [
|
|
2905
|
+
...template22.matchAll(/\$\{\s*([A-Za-z_$][\w$]*)/g)
|
|
2906
|
+
].map((m) => m[1]);
|
|
2907
|
+
return refs.length > 0 && refs.every((r) => BINDING_ROOTS.includes(r));
|
|
2908
|
+
}
|
|
2909
|
+
__name(bindingRootsOk, "bindingRootsOk");
|
|
2910
|
+
__name3(bindingRootsOk, "bindingRootsOk");
|
|
2911
|
+
function isTemplateBinding(v) {
|
|
2912
|
+
return typeof v === "object" && v !== null && typeof v.template === "string";
|
|
2913
|
+
}
|
|
2914
|
+
__name(isTemplateBinding, "isTemplateBinding");
|
|
2915
|
+
__name3(isTemplateBinding, "isTemplateBinding");
|
|
2916
|
+
function approvalEditable(node) {
|
|
2917
|
+
if (node.editable === true) return true;
|
|
2918
|
+
if (node.editable === false) return false;
|
|
2919
|
+
return Array.isArray(node.editablePaths) && node.editablePaths.length > 0;
|
|
2920
|
+
}
|
|
2921
|
+
__name(approvalEditable, "approvalEditable");
|
|
2922
|
+
__name3(approvalEditable, "approvalEditable");
|
|
2923
|
+
function validateApproverBlock(node, opts = {
|
|
2924
|
+
path: "approval"
|
|
2925
|
+
}) {
|
|
2926
|
+
const issues = [];
|
|
2927
|
+
const push = /* @__PURE__ */ __name3((code, path, message, severity = "error") => issues.push({
|
|
2928
|
+
code,
|
|
2929
|
+
path,
|
|
2930
|
+
severity,
|
|
2931
|
+
message
|
|
2932
|
+
}), "push");
|
|
2933
|
+
const checkSpec = /* @__PURE__ */ __name3((spec, path) => {
|
|
2934
|
+
const r = ApproverSpecSchema.safeParse(spec);
|
|
2935
|
+
if (!r.success) {
|
|
2936
|
+
const users = spec?.users;
|
|
2937
|
+
if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path, `at most ${APPROVER_SPEC_MAX_USERS} users`);
|
|
2938
|
+
else {
|
|
2939
|
+
const refusal = describeApproverSpecRefusal(spec);
|
|
2940
|
+
issues.push({
|
|
2941
|
+
code: "approver-invalid",
|
|
2942
|
+
path,
|
|
2943
|
+
severity: "error",
|
|
2944
|
+
message: refusal.message,
|
|
2945
|
+
repair: {
|
|
2946
|
+
approver: refusal.approver,
|
|
2947
|
+
written: refusal.written
|
|
2948
|
+
}
|
|
2949
|
+
});
|
|
2950
|
+
}
|
|
2951
|
+
return;
|
|
2952
|
+
}
|
|
2953
|
+
const s = r.data;
|
|
2954
|
+
if (typeof s === "object") {
|
|
2955
|
+
if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path, "governance reviewer routing is not enabled for this deployment");
|
|
2956
|
+
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path, "IdP-group approvers are not enabled for this deployment");
|
|
2957
|
+
const binding = "users" in s ? s.users : "role" in s ? s.role : "group" in s ? s.group : void 0;
|
|
2958
|
+
if (isTemplateBinding(binding)) {
|
|
2959
|
+
if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path}.template`, "binding root must be initData / stepResults / requestContext / state");
|
|
2960
|
+
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path}.users`, "a customer-reachable workflow may not bind its approver list");
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
}, "checkSpec");
|
|
2964
|
+
if (node.approver !== void 0) checkSpec(node.approver, `${opts.path}.approver`);
|
|
2965
|
+
if (node.fourEyes !== void 0) {
|
|
2966
|
+
const r = FourEyesSchema.safeParse(node.fourEyes);
|
|
2967
|
+
if (!r.success) push("approver-invalid", `${opts.path}.fourEyes`, "fourEyes needs { edit, approve } approver specs");
|
|
2968
|
+
else {
|
|
2969
|
+
checkSpec(r.data.edit, `${opts.path}.fourEyes.edit`);
|
|
2970
|
+
checkSpec(r.data.approve, `${opts.path}.fourEyes.approve`);
|
|
2971
|
+
}
|
|
2972
|
+
if (!approvalEditable(node)) push("four-eyes-requires-editable", `${opts.path}.fourEyes`, "fourEyes requires editable:true");
|
|
2973
|
+
if (node.approver !== void 0) push("four-eyes-overrides-approver", `${opts.path}.approver`, "fourEyes replaces approver", "warning");
|
|
2974
|
+
if (node.itemsPath) push("four-eyes-items-unsupported", `${opts.path}.fourEyes`, "fourEyes cannot combine with itemsPath");
|
|
2975
|
+
}
|
|
2976
|
+
if (node.excludeInitiator && (node.approver === void 0 || node.approver === "creator") && !node.fourEyes) push("approver-excludes-only-candidate", `${opts.path}.excludeInitiator`, "'creator' with excludeInitiator leaves no approver");
|
|
2977
|
+
if (Array.isArray(node.onTimeout)) {
|
|
2978
|
+
const chain = node.onTimeout;
|
|
2979
|
+
const hops = chain.filter((m) => typeof m === "object" && m !== null && "escalateTo" in m);
|
|
2980
|
+
if (hops.length > ESCALATION_MAX_HOPS) push("escalation-chain-too-long", `${opts.path}.onTimeout`, `at most ${ESCALATION_MAX_HOPS} hops`);
|
|
2981
|
+
const last = chain[chain.length - 1];
|
|
2982
|
+
if (typeof last === "object" && last !== null) push("escalation-chain-not-terminal", `${opts.path}.onTimeout`, "a chain must end in deny | cancel-run | fail");
|
|
2983
|
+
hops.forEach((h, i) => checkSpec(h.escalateTo, `${opts.path}.onTimeout[${i}].escalateTo`));
|
|
2984
|
+
} else if (typeof node.onTimeout === "object" && node.onTimeout !== null) {
|
|
2985
|
+
checkSpec(node.onTimeout.escalateTo, `${opts.path}.onTimeout.escalateTo`);
|
|
2986
|
+
}
|
|
2987
|
+
return issues;
|
|
2988
|
+
}
|
|
2989
|
+
__name(validateApproverBlock, "validateApproverBlock");
|
|
2990
|
+
__name3(validateApproverBlock, "validateApproverBlock");
|
|
2991
|
+
function liftRenderedApprover(row, rendered) {
|
|
2992
|
+
const text = (rendered ?? "").trim();
|
|
2993
|
+
if (!text) return null;
|
|
2994
|
+
if (row === "users") {
|
|
2995
|
+
let members = null;
|
|
2996
|
+
if (text.startsWith("[")) {
|
|
2997
|
+
try {
|
|
2998
|
+
members = JSON.parse(text);
|
|
2999
|
+
} catch {
|
|
3000
|
+
return null;
|
|
3001
|
+
}
|
|
3002
|
+
} else members = text.split(",").map((s) => s.trim());
|
|
3003
|
+
if (!Array.isArray(members) || members.length === 0 || members.length > APPROVER_SPEC_MAX_USERS) return null;
|
|
3004
|
+
if (!members.every((m) => typeof m === "string" && m.length > 0 && m.length <= 128)) return null;
|
|
3005
|
+
return {
|
|
3006
|
+
users: [
|
|
3007
|
+
...new Set(members)
|
|
3008
|
+
].sort()
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
3011
|
+
if (text.length > 128 || text.startsWith("[") || text.startsWith("{")) return null;
|
|
3012
|
+
return row === "role" ? {
|
|
3013
|
+
role: text
|
|
3014
|
+
} : {
|
|
3015
|
+
group: text
|
|
3016
|
+
};
|
|
3017
|
+
}
|
|
3018
|
+
__name(liftRenderedApprover, "liftRenderedApprover");
|
|
3019
|
+
__name3(liftRenderedApprover, "liftRenderedApprover");
|
|
3020
|
+
var WORKSPACE_TEMPLATE_EXPR_RE = /^\$\{\s*(?:initData|input)\.([^}]+?)\s*\}$/;
|
|
3021
|
+
function workspaceTemplatePath(template22) {
|
|
3022
|
+
const key = template22.trim();
|
|
3023
|
+
const expr = WORKSPACE_TEMPLATE_EXPR_RE.exec(key);
|
|
3024
|
+
if (expr) return expr[1].split(".");
|
|
3025
|
+
if (key.includes("${")) return void 0;
|
|
3026
|
+
return key.replace(/^(?:input|initData)\./, "").split(".");
|
|
3027
|
+
}
|
|
3028
|
+
__name(workspaceTemplatePath, "workspaceTemplatePath");
|
|
3029
|
+
__name3(workspaceTemplatePath, "workspaceTemplatePath");
|
|
3030
|
+
function retryBackoffs() {
|
|
3031
|
+
if (!Array.isArray(WORKFLOW_RETRY_BACKOFFS)) {
|
|
3032
|
+
throw new Error("@lua/shared-types.WORKFLOW_RETRY_BACKOFFS is not a tuple \u2014 a jest.mock('@lua/shared-types') must spread jest.requireActual('@lua/shared-types')");
|
|
3033
|
+
}
|
|
3034
|
+
return WORKFLOW_RETRY_BACKOFFS;
|
|
3035
|
+
}
|
|
3036
|
+
__name(retryBackoffs, "retryBackoffs");
|
|
3037
|
+
__name3(retryBackoffs, "retryBackoffs");
|
|
3038
|
+
var SLEEP_UNTIL_REPLACEMENT = Object.freeze({
|
|
3039
|
+
type: "sleep",
|
|
3040
|
+
duration: 6e4
|
|
3041
|
+
});
|
|
3042
|
+
function sleepUntilUnsupportedMessage(id) {
|
|
3043
|
+
return `the engine does not execute \`sleepUntil\` yet (node "${id}") \u2014 replace it with a \`sleep\` node with a \`duration\` in ms, e.g. { type: 'sleep', id: '${id}', duration: ${SLEEP_UNTIL_REPLACEMENT.duration} }`;
|
|
3044
|
+
}
|
|
3045
|
+
__name(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
|
|
3046
|
+
__name3(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
|
|
3047
|
+
function armSubrunUnsupportedMessage(id, workflowId) {
|
|
3048
|
+
return `the engine does not execute the implicit \`${workflowId}\` arm subrun (node "${id}") \u2014 a [map, step] container arm is the step itself with the map as its \`input\` since lua-cli 3.32.4; re-run \`lua compile\` with the current CLI (a hand-written artifact: put the map on the arm node's \`input\` and drop the \`workflow\` wrapper)`;
|
|
3049
|
+
}
|
|
3050
|
+
__name(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
|
|
3051
|
+
__name3(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
|
|
3052
|
+
var WORKFLOW_CAPS_DEFAULT = Object.freeze({
|
|
3053
|
+
maxParallelArms: 16,
|
|
3054
|
+
maxForeachConcurrency: 16,
|
|
3055
|
+
maxForeachItems: 2e4,
|
|
3056
|
+
maxNodes: 200,
|
|
3057
|
+
maxNestingDepth: 3,
|
|
3058
|
+
maxForeachRatePerSecond: 50,
|
|
3059
|
+
maxLoopIntervalSeconds: 86400,
|
|
3060
|
+
maxWorkerTimeoutSeconds: 600,
|
|
3061
|
+
maxJobTimeoutSeconds: 86400,
|
|
3062
|
+
maxJobSegmentSeconds: 14400
|
|
3063
|
+
});
|
|
3064
|
+
var WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS = 300;
|
|
3065
|
+
var WORKFLOW_AGENT_DEFAULT_TIMEOUT_SECONDS = 600;
|
|
3066
|
+
var WORKFLOW_JOB_DEFAULT_TIMEOUT_SECONDS = 3600;
|
|
3067
|
+
var WORKFLOW_FOREACH_DEFAULT_CONCURRENCY = 4;
|
|
3068
|
+
var WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS = 256;
|
|
3069
|
+
var WORKFLOW_LOOP_DEFAULT_MAX_ITERATIONS = 100;
|
|
3070
|
+
var WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS = 168;
|
|
3071
|
+
var WORKFLOW_SIGNAL_DEFAULT_SOURCES = [
|
|
3072
|
+
"webhook",
|
|
3073
|
+
"api",
|
|
3074
|
+
"user"
|
|
3075
|
+
];
|
|
3076
|
+
var clone = /* @__PURE__ */ __name3((v) => JSON.parse(JSON.stringify(v)), "clone");
|
|
3077
|
+
function fillPolicy(node, defaultTimeout) {
|
|
3078
|
+
if (node.tier === void 0 && node.workspace !== void 0 && node.workspace !== "inherit") node.tier = "job";
|
|
3079
|
+
if (node.timeoutSeconds === void 0) node.timeoutSeconds = node.tier === "job" ? WORKFLOW_JOB_DEFAULT_TIMEOUT_SECONDS : defaultTimeout;
|
|
3080
|
+
if (node.retry === void 0) node.retry = {
|
|
3081
|
+
maxAttempts: 1
|
|
3082
|
+
};
|
|
3083
|
+
if (node.onError === void 0) node.onError = "fail";
|
|
3084
|
+
if ((node.type === "step" || node.type === "tool") && node.sideEffects === void 0) node.sideEffects = "none";
|
|
3085
|
+
}
|
|
3086
|
+
__name(fillPolicy, "fillPolicy");
|
|
3087
|
+
__name3(fillPolicy, "fillPolicy");
|
|
3088
|
+
function fillSingle(node) {
|
|
3089
|
+
switch (node.type) {
|
|
3090
|
+
case "step": {
|
|
3091
|
+
fillPolicy(node, WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS);
|
|
3092
|
+
const s = node;
|
|
3093
|
+
if (s.resumeTimeoutHours === void 0) s.resumeTimeoutHours = WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS;
|
|
3094
|
+
if (s.onSuspendTimeout === void 0) s.onSuspendTimeout = "fail";
|
|
3095
|
+
return;
|
|
3096
|
+
}
|
|
3097
|
+
case "agent":
|
|
3098
|
+
fillPolicy(node, WORKFLOW_AGENT_DEFAULT_TIMEOUT_SECONDS);
|
|
3099
|
+
return;
|
|
3100
|
+
case "tool":
|
|
3101
|
+
fillPolicy(node, WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS);
|
|
3102
|
+
return;
|
|
3103
|
+
case "workflow":
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
__name(fillSingle, "fillSingle");
|
|
3108
|
+
__name3(fillSingle, "fillSingle");
|
|
3109
|
+
function fillHitl(node) {
|
|
3110
|
+
if (node.type === "approval") {
|
|
3111
|
+
const a = node;
|
|
3112
|
+
if (a.approver === void 0) a.approver = "creator";
|
|
3113
|
+
if (a.timeoutHours === void 0) a.timeoutHours = WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS;
|
|
3114
|
+
if (a.onTimeout === void 0) a.onTimeout = "deny";
|
|
3115
|
+
if (a.onDeny === void 0) a.onDeny = "continue";
|
|
3116
|
+
if (a.excludeInitiator === void 0) a.excludeInitiator = false;
|
|
3117
|
+
if (a.editable === void 0) a.editable = false;
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
const w = node;
|
|
3121
|
+
if (w.timeoutHours === void 0) w.timeoutHours = WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS;
|
|
3122
|
+
if (w.onTimeout === void 0) w.onTimeout = "fail";
|
|
3123
|
+
if (w.acceptedSources === void 0) w.acceptedSources = [
|
|
3124
|
+
...WORKFLOW_SIGNAL_DEFAULT_SOURCES
|
|
3125
|
+
];
|
|
3126
|
+
}
|
|
3127
|
+
__name(fillHitl, "fillHitl");
|
|
3128
|
+
__name3(fillHitl, "fillHitl");
|
|
3129
|
+
function fillArm(arm) {
|
|
3130
|
+
if (arm.type === "mapping") return;
|
|
3131
|
+
if (isHitlNode(arm)) fillHitl(arm);
|
|
3132
|
+
else fillSingle(arm);
|
|
3133
|
+
}
|
|
3134
|
+
__name(fillArm, "fillArm");
|
|
3135
|
+
__name3(fillArm, "fillArm");
|
|
3136
|
+
function fillEntry(entry) {
|
|
2344
3137
|
switch (entry.type) {
|
|
2345
3138
|
case "step":
|
|
2346
3139
|
case "agent":
|
|
@@ -2482,12 +3275,11 @@ function mapConfigStepRefs(raw) {
|
|
|
2482
3275
|
if (!cfg) return [];
|
|
2483
3276
|
const ids = [];
|
|
2484
3277
|
for (const d of Object.values(cfg)) {
|
|
2485
|
-
if (!d
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
desc.step
|
|
3278
|
+
if (!isMapDescriptor(d)) continue;
|
|
3279
|
+
if ("step" in d) ids.push(...Array.isArray(d.step) ? d.step : [
|
|
3280
|
+
d.step
|
|
2489
3281
|
]);
|
|
2490
|
-
if (
|
|
3282
|
+
if ("template" in d) ids.push(...templateStepRefs(d.template));
|
|
2491
3283
|
}
|
|
2492
3284
|
return ids;
|
|
2493
3285
|
}
|
|
@@ -2498,8 +3290,14 @@ function nodeStepRefs(entry) {
|
|
|
2498
3290
|
case "agent": {
|
|
2499
3291
|
const a = entry;
|
|
2500
3292
|
const p = a.promptTemplate;
|
|
2501
|
-
|
|
3293
|
+
const prompt = typeof p === "string" ? templateStepRefs(p) : p && "template" in p ? templateStepRefs(p.template) : [];
|
|
3294
|
+
return [
|
|
3295
|
+
...prompt,
|
|
3296
|
+
...mapConfigStepRefs(a.input)
|
|
3297
|
+
];
|
|
2502
3298
|
}
|
|
3299
|
+
case "step":
|
|
3300
|
+
return mapConfigStepRefs(entry.input);
|
|
2503
3301
|
case "tool":
|
|
2504
3302
|
return mapConfigStepRefs(entry.input);
|
|
2505
3303
|
case "workflow":
|
|
@@ -2616,6 +3414,12 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2616
3414
|
const r = node.retry;
|
|
2617
3415
|
if (!r) return;
|
|
2618
3416
|
const id = singleId(node);
|
|
3417
|
+
const unknown = unknownWorkflowRetryMembers(r);
|
|
3418
|
+
if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path}.retry`, id);
|
|
3419
|
+
if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
3420
|
+
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
3421
|
+
err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path}.retry.maxAttempts`, id);
|
|
3422
|
+
}
|
|
2619
3423
|
const backoffs = retryBackoffs();
|
|
2620
3424
|
if (r.backoff !== void 0 && !backoffs.includes(r.backoff)) {
|
|
2621
3425
|
const list = backoffs.map((b) => `'${b}'`).join(" | ");
|
|
@@ -2712,6 +3516,21 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2712
3516
|
err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path}.model`, id);
|
|
2713
3517
|
}
|
|
2714
3518
|
}, "checkTier");
|
|
3519
|
+
const checkModel = /* @__PURE__ */ __name3((node, path) => {
|
|
3520
|
+
if (node.type !== "agent" || typeof node.model !== "string") return;
|
|
3521
|
+
const registry = opts.approvedModels;
|
|
3522
|
+
if (registry === void 0) return;
|
|
3523
|
+
const id = singleId(node);
|
|
3524
|
+
if (registry === "unavailable") {
|
|
3525
|
+
const pin = node.model.trim();
|
|
3526
|
+
if (pin && !normalizeModelId(pin, []).ok) {
|
|
3527
|
+
warn("model-unresolved", `model "${pin}" could not be checked against the approved-model registry (unavailable at push) \u2014 it dispatches only if it resolves there (a provider/model registry code, or a bare id exactly one approved model carries)`, `${path}.model`, id);
|
|
3528
|
+
}
|
|
3529
|
+
return;
|
|
3530
|
+
}
|
|
3531
|
+
const resolved = normalizeModelId(node.model, registry);
|
|
3532
|
+
if (!resolved.ok) err("model-unresolved", modelUnresolvedMessage(resolved), `${path}.model`, id);
|
|
3533
|
+
}, "checkModel");
|
|
2715
3534
|
const checkWorkspace = /* @__PURE__ */ __name3((node, path) => {
|
|
2716
3535
|
const id = singleId(node);
|
|
2717
3536
|
const ws = workspaceOf(node);
|
|
@@ -2758,35 +3577,43 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2758
3577
|
const schema = node.type === "step" ? node.step.outputSchema : node.type === "agent" ? node.outputSchema : void 0;
|
|
2759
3578
|
if (schema !== void 0) outputSchemas.set(singleId(node), schema);
|
|
2760
3579
|
}, "recordOutputSchema");
|
|
3580
|
+
const checkMapMembers = /* @__PURE__ */ __name3((cfg, basePath, id) => {
|
|
3581
|
+
for (const m of malformedMapMembers(cfg)) {
|
|
3582
|
+
warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id, m), `${basePath}.${m.member}`, id);
|
|
3583
|
+
}
|
|
3584
|
+
}, "checkMapMembers");
|
|
3585
|
+
const checkInputShape = /* @__PURE__ */ __name3((node, path) => {
|
|
3586
|
+
const input = node.input;
|
|
3587
|
+
if (input === void 0) return;
|
|
3588
|
+
const id = singleId(node);
|
|
3589
|
+
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
3590
|
+
checkMapMembers(input, `${path}.input`, id);
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3593
|
+
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`, id);
|
|
3594
|
+
}, "checkInputShape");
|
|
3595
|
+
const checkBodyInput = /* @__PURE__ */ __name3((body, path, container) => {
|
|
3596
|
+
if (body.type === "workflow" || body.input === void 0) return;
|
|
3597
|
+
err("arm-input-unsupported", container === "foreach" ? `a foreach body receives each item as its input \u2014 drop \`input\` on "${singleId(body)}" and map the items before the foreach instead` : `a loop body receives the previous output as its input \u2014 drop \`input\` on "${singleId(body)}" and put the map before the loop instead`, `${path}.input`, singleId(body));
|
|
3598
|
+
}, "checkBodyInput");
|
|
2761
3599
|
const checkSingle = /* @__PURE__ */ __name3((node, path, depth) => {
|
|
2762
3600
|
recordOutputSchema(node);
|
|
2763
|
-
if (node.type === "workflow" && node.workflowId ===
|
|
3601
|
+
if (node.type === "workflow" && (typeof node.workflowId !== "string" || node.workflowId.length === 0)) {
|
|
2764
3602
|
checkId(node.id, path);
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
err("container-arm-empty", "a bare mapping arm has nothing to run", `${path}.graph.1`, node.id);
|
|
2772
|
-
return;
|
|
2773
|
-
}
|
|
2774
|
-
const inner = body[1];
|
|
2775
|
-
if (isHitlNode(inner)) {
|
|
2776
|
-
err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(inner.type, inner.id, "mapped-arm"), `${path}.graph.1`, inner.id);
|
|
2777
|
-
return;
|
|
2778
|
-
}
|
|
2779
|
-
upstream.add(singleId(body[1]));
|
|
2780
|
-
checkArm(body[0], `${path}.graph.0`, depth, "parallel");
|
|
2781
|
-
checkSingle(body[1], `${path}.graph.1`, depth);
|
|
2782
|
-
upstream.add(body[0].id);
|
|
2783
|
-
upstream.add(singleId(body[1]));
|
|
3603
|
+
err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${path}.workflowId`, node.id);
|
|
3604
|
+
return;
|
|
3605
|
+
}
|
|
3606
|
+
if (node.type === "workflow" && (node.workflowId.startsWith("$") || Array.isArray(node.graph))) {
|
|
3607
|
+
checkId(node.id, path);
|
|
3608
|
+
err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId), path, node.id);
|
|
2784
3609
|
return;
|
|
2785
3610
|
}
|
|
2786
3611
|
checkId(singleId(node), path);
|
|
2787
3612
|
checkPolicyEnums(node, path);
|
|
3613
|
+
checkInputShape(node, path);
|
|
2788
3614
|
checkTimeout(node, path);
|
|
2789
3615
|
checkTier(node, path);
|
|
3616
|
+
checkModel(node, path);
|
|
2790
3617
|
checkRetry(node, path);
|
|
2791
3618
|
checkWorkspace(node, path);
|
|
2792
3619
|
if (!opts.static) {
|
|
@@ -2809,7 +3636,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2809
3636
|
if (node.type === "workflow" && node.kind === "subrun" && depth > caps.maxNestingDepth) {
|
|
2810
3637
|
err("cap-exceeded", `nesting depth ${depth} exceeds ${caps.maxNestingDepth}`, path, node.id);
|
|
2811
3638
|
}
|
|
2812
|
-
if (node.type === "workflow" &&
|
|
3639
|
+
if (node.type === "workflow" && typeof g.definition?.id === "string" && node.workflowId === g.definition.id) {
|
|
2813
3640
|
err("subrun-cycle", `"${node.id}" starts "${node.workflowId}", which is this workflow itself`, path, node.id);
|
|
2814
3641
|
}
|
|
2815
3642
|
for (const ref of nodeStepRefs(node)) {
|
|
@@ -2830,11 +3657,14 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2830
3657
|
if (a.approver === "creator" && a.excludeInitiator === true) {
|
|
2831
3658
|
err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path, a.id);
|
|
2832
3659
|
}
|
|
2833
|
-
|
|
3660
|
+
const editable = approvalEditable(a);
|
|
3661
|
+
if (a.fourEyes !== void 0 && !editable) {
|
|
2834
3662
|
err("four-eyes-requires-editable", "`fourEyes` requires editable:true", `${path}.fourEyes`, a.id);
|
|
2835
3663
|
}
|
|
2836
|
-
if (
|
|
2837
|
-
err("editable-path-invalid", "`editablePaths`
|
|
3664
|
+
if (a.editable === false && Array.isArray(a.editablePaths) && a.editablePaths.length > 0) {
|
|
3665
|
+
err("editable-path-invalid", "`editablePaths` beside editable:false is contradictory \u2014 drop the paths or set editable:true", `${path}.editablePaths`, a.id);
|
|
3666
|
+
} else if ((a.editablePaths !== void 0 || a.editedPayloadSchema !== void 0) && !editable) {
|
|
3667
|
+
err("editable-path-invalid", "`editablePaths` / `editedPayloadSchema` require editable:true (a non-empty editablePaths implies it)", `${path}.editablePaths`, a.id);
|
|
2838
3668
|
}
|
|
2839
3669
|
for (const p of a.editablePaths ?? []) {
|
|
2840
3670
|
if (!EDITABLE_PATH_RE.test(p)) err("editable-path-invalid", `editablePaths entry "${p}" is outside the seg(.seg)*[*]/[n] grammar`, `${path}.editablePaths`, a.id);
|
|
@@ -2865,6 +3695,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2865
3695
|
const checkArm = /* @__PURE__ */ __name3((arm, path, depth, container) => {
|
|
2866
3696
|
if (arm.type === "mapping") {
|
|
2867
3697
|
checkId(arm.id, path);
|
|
3698
|
+
checkMapMembers(readMapConfig(arm.mapConfig), `${path}.mapConfig`, arm.id);
|
|
2868
3699
|
for (const ref of nodeStepRefs(arm)) {
|
|
2869
3700
|
if (!upstream.has(ref)) err("template-reference-unresolved", `"${arm.id}" references stepResults.${ref}, which is not upstream`, path, arm.id);
|
|
2870
3701
|
}
|
|
@@ -2889,6 +3720,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
2889
3720
|
break;
|
|
2890
3721
|
case "mapping":
|
|
2891
3722
|
checkId(entry.id, path);
|
|
3723
|
+
checkMapMembers(readMapConfig(entry.mapConfig), `${path}.mapConfig`, entry.id);
|
|
2892
3724
|
for (const ref of nodeStepRefs(entry)) {
|
|
2893
3725
|
if (!upstream.has(ref)) err("template-reference-unresolved", `"${entry.id}" references stepResults.${ref}, which is not upstream`, path, entry.id);
|
|
2894
3726
|
}
|
|
@@ -3013,6 +3845,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3013
3845
|
} else checkHitlArm(f.step, `${path}.step`, "foreach");
|
|
3014
3846
|
declared.push(f.step.id);
|
|
3015
3847
|
} else {
|
|
3848
|
+
checkBodyInput(f.step, `${path}.step`, "foreach");
|
|
3016
3849
|
checkSingle(f.step, `${path}.step`, o.chunk ? 2 : 1);
|
|
3017
3850
|
declared.push(singleId(f.step));
|
|
3018
3851
|
}
|
|
@@ -3033,6 +3866,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3033
3866
|
checkHitlArm(l.step, `${path}.step`, "loop");
|
|
3034
3867
|
declared.push(l.step.id);
|
|
3035
3868
|
} else {
|
|
3869
|
+
checkBodyInput(l.step, `${path}.step`, "loop");
|
|
3036
3870
|
checkSingle(l.step, `${path}.step`, 1);
|
|
3037
3871
|
declared.push(singleId(l.step));
|
|
3038
3872
|
}
|
|
@@ -3512,361 +4346,123 @@ __name3(renderPredicate, "renderPredicate");
|
|
|
3512
4346
|
function wrapLabel(child, rendered) {
|
|
3513
4347
|
return child.op === "and" || child.op === "or" || child.op === "not" ? `(${rendered})` : rendered;
|
|
3514
4348
|
}
|
|
3515
|
-
__name(wrapLabel, "wrapLabel");
|
|
3516
|
-
__name3(wrapLabel, "wrapLabel");
|
|
3517
|
-
function renderRef(ref) {
|
|
3518
|
-
if ("literal" in ref) return JSON.stringify(ref.literal);
|
|
3519
|
-
return ref.path;
|
|
3520
|
-
}
|
|
3521
|
-
__name(renderRef, "renderRef");
|
|
3522
|
-
__name3(renderRef, "renderRef");
|
|
3523
|
-
var stepIdOf = /* @__PURE__ */ __name3((s) => typeof s === "string" ? s : s.id, "stepIdOf");
|
|
3524
|
-
function step(s) {
|
|
3525
|
-
const id = stepIdOf(s);
|
|
3526
|
-
return {
|
|
3527
|
-
path: /* @__PURE__ */ __name3((p) => ({
|
|
3528
|
-
path: p === "" ? `stepResults.${id}` : `stepResults.${id}.${p}`
|
|
3529
|
-
}), "path")
|
|
3530
|
-
};
|
|
3531
|
-
}
|
|
3532
|
-
__name(step, "step");
|
|
3533
|
-
__name3(step, "step");
|
|
3534
|
-
function stepOf(id) {
|
|
3535
|
-
return step(id);
|
|
3536
|
-
}
|
|
3537
|
-
__name(stepOf, "stepOf");
|
|
3538
|
-
__name3(stepOf, "stepOf");
|
|
3539
|
-
function init(path) {
|
|
3540
|
-
return {
|
|
3541
|
-
path: path === "" ? "initData" : `initData.${path}`
|
|
3542
|
-
};
|
|
3543
|
-
}
|
|
3544
|
-
__name(init, "init");
|
|
3545
|
-
__name3(init, "init");
|
|
3546
|
-
function state(path) {
|
|
3547
|
-
return {
|
|
3548
|
-
path: path === "" ? "state" : `state.${path}`
|
|
3549
|
-
};
|
|
3550
|
-
}
|
|
3551
|
-
__name(state, "state");
|
|
3552
|
-
__name3(state, "state");
|
|
3553
|
-
function lit(v) {
|
|
3554
|
-
return {
|
|
3555
|
-
literal: v
|
|
3556
|
-
};
|
|
3557
|
-
}
|
|
3558
|
-
__name(lit, "lit");
|
|
3559
|
-
__name3(lit, "lit");
|
|
3560
|
-
function toPathOrLiteral(v) {
|
|
3561
|
-
if (typeof v === "object" && v !== null) {
|
|
3562
|
-
if ("path" in v) return {
|
|
3563
|
-
path: v.path
|
|
3564
|
-
};
|
|
3565
|
-
if ("literal" in v) return {
|
|
3566
|
-
literal: v.literal
|
|
3567
|
-
};
|
|
3568
|
-
}
|
|
3569
|
-
return {
|
|
3570
|
-
literal: v
|
|
3571
|
-
};
|
|
3572
|
-
}
|
|
3573
|
-
__name(toPathOrLiteral, "toPathOrLiteral");
|
|
3574
|
-
__name3(toPathOrLiteral, "toPathOrLiteral");
|
|
3575
|
-
var cmp = /* @__PURE__ */ __name3((op) => (l, r) => ({
|
|
3576
|
-
op,
|
|
3577
|
-
left: toPathOrLiteral(l),
|
|
3578
|
-
right: toPathOrLiteral(r)
|
|
3579
|
-
}), "cmp");
|
|
3580
|
-
var eq = cmp("eq");
|
|
3581
|
-
var ne = cmp("ne");
|
|
3582
|
-
var gt = cmp("gt");
|
|
3583
|
-
var gte = cmp("gte");
|
|
3584
|
-
var lt = cmp("lt");
|
|
3585
|
-
var lte = cmp("lte");
|
|
3586
|
-
var inSet = /* @__PURE__ */ __name3((v, set) => ({
|
|
3587
|
-
op: "in",
|
|
3588
|
-
value: {
|
|
3589
|
-
path: v.path
|
|
3590
|
-
},
|
|
3591
|
-
set
|
|
3592
|
-
}), "inSet");
|
|
3593
|
-
var notIn = /* @__PURE__ */ __name3((v, set) => ({
|
|
3594
|
-
op: "notIn",
|
|
3595
|
-
value: {
|
|
3596
|
-
path: v.path
|
|
3597
|
-
},
|
|
3598
|
-
set
|
|
3599
|
-
}), "notIn");
|
|
3600
|
-
var exists = /* @__PURE__ */ __name3((ref) => ({
|
|
3601
|
-
op: "exists",
|
|
3602
|
-
path: ref.path
|
|
3603
|
-
}), "exists");
|
|
3604
|
-
var notExists = /* @__PURE__ */ __name3((ref) => ({
|
|
3605
|
-
op: "notExists",
|
|
3606
|
-
path: ref.path
|
|
3607
|
-
}), "notExists");
|
|
3608
|
-
var truthy = /* @__PURE__ */ __name3((ref) => ({
|
|
3609
|
-
op: "truthy",
|
|
3610
|
-
value: {
|
|
3611
|
-
path: ref.path
|
|
3612
|
-
}
|
|
3613
|
-
}), "truthy");
|
|
3614
|
-
var falsy = /* @__PURE__ */ __name3((ref) => ({
|
|
3615
|
-
op: "falsy",
|
|
3616
|
-
value: {
|
|
3617
|
-
path: ref.path
|
|
3618
|
-
}
|
|
3619
|
-
}), "falsy");
|
|
3620
|
-
var and = /* @__PURE__ */ __name3((...args) => ({
|
|
3621
|
-
op: "and",
|
|
3622
|
-
args
|
|
3623
|
-
}), "and");
|
|
3624
|
-
var or = /* @__PURE__ */ __name3((...args) => ({
|
|
3625
|
-
op: "or",
|
|
3626
|
-
args
|
|
3627
|
-
}), "or");
|
|
3628
|
-
var not = /* @__PURE__ */ __name3((arg) => ({
|
|
3629
|
-
op: "not",
|
|
3630
|
-
arg
|
|
3631
|
-
}), "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(".");
|
|
4349
|
+
__name(wrapLabel, "wrapLabel");
|
|
4350
|
+
__name3(wrapLabel, "wrapLabel");
|
|
4351
|
+
function renderRef(ref) {
|
|
4352
|
+
if ("literal" in ref) return JSON.stringify(ref.literal);
|
|
4353
|
+
return ref.path;
|
|
4354
|
+
}
|
|
4355
|
+
__name(renderRef, "renderRef");
|
|
4356
|
+
__name3(renderRef, "renderRef");
|
|
4357
|
+
var stepIdOf = /* @__PURE__ */ __name3((s) => typeof s === "string" ? s : s.id, "stepIdOf");
|
|
4358
|
+
function step(s) {
|
|
4359
|
+
const id = stepIdOf(s);
|
|
3684
4360
|
return {
|
|
3685
|
-
|
|
3686
|
-
|
|
4361
|
+
path: /* @__PURE__ */ __name3((p) => ({
|
|
4362
|
+
path: p === "" ? `stepResults.${id}` : `stepResults.${id}.${p}`
|
|
4363
|
+
}), "path")
|
|
3687
4364
|
};
|
|
3688
4365
|
}
|
|
3689
|
-
__name(
|
|
3690
|
-
__name3(
|
|
3691
|
-
function
|
|
3692
|
-
|
|
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);
|
|
4366
|
+
__name(step, "step");
|
|
4367
|
+
__name3(step, "step");
|
|
4368
|
+
function stepOf(id) {
|
|
4369
|
+
return step(id);
|
|
3713
4370
|
}
|
|
3714
|
-
__name(
|
|
3715
|
-
__name3(
|
|
3716
|
-
function
|
|
3717
|
-
return
|
|
4371
|
+
__name(stepOf, "stepOf");
|
|
4372
|
+
__name3(stepOf, "stepOf");
|
|
4373
|
+
function init(path) {
|
|
4374
|
+
return {
|
|
4375
|
+
path: path === "" ? "initData" : `initData.${path}`
|
|
4376
|
+
};
|
|
3718
4377
|
}
|
|
3719
|
-
__name(
|
|
3720
|
-
__name3(
|
|
3721
|
-
function
|
|
3722
|
-
return
|
|
4378
|
+
__name(init, "init");
|
|
4379
|
+
__name3(init, "init");
|
|
4380
|
+
function state(path) {
|
|
4381
|
+
return {
|
|
4382
|
+
path: path === "" ? "state" : `state.${path}`
|
|
4383
|
+
};
|
|
3723
4384
|
}
|
|
3724
|
-
__name(
|
|
3725
|
-
__name3(
|
|
3726
|
-
function
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
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
|
-
});
|
|
4385
|
+
__name(state, "state");
|
|
4386
|
+
__name3(state, "state");
|
|
4387
|
+
function lit(v) {
|
|
4388
|
+
return {
|
|
4389
|
+
literal: v
|
|
4390
|
+
};
|
|
3764
4391
|
}
|
|
3765
|
-
__name(
|
|
3766
|
-
__name3(
|
|
3767
|
-
function
|
|
3768
|
-
|
|
3769
|
-
if ("
|
|
3770
|
-
|
|
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
|
|
4392
|
+
__name(lit, "lit");
|
|
4393
|
+
__name3(lit, "lit");
|
|
4394
|
+
function toPathOrLiteral(v) {
|
|
4395
|
+
if (typeof v === "object" && v !== null) {
|
|
4396
|
+
if ("path" in v) return {
|
|
4397
|
+
path: v.path
|
|
3814
4398
|
};
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
error: "binding_unresolved",
|
|
3818
|
-
key
|
|
4399
|
+
if ("literal" in v) return {
|
|
4400
|
+
literal: v.literal
|
|
3819
4401
|
};
|
|
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
4402
|
}
|
|
3836
4403
|
return {
|
|
3837
|
-
|
|
4404
|
+
literal: v
|
|
3838
4405
|
};
|
|
3839
4406
|
}
|
|
3840
|
-
__name(
|
|
3841
|
-
__name3(
|
|
3842
|
-
var
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
var
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
}), "
|
|
3867
|
-
var
|
|
3868
|
-
|
|
3869
|
-
|
|
4407
|
+
__name(toPathOrLiteral, "toPathOrLiteral");
|
|
4408
|
+
__name3(toPathOrLiteral, "toPathOrLiteral");
|
|
4409
|
+
var cmp = /* @__PURE__ */ __name3((op) => (l, r) => ({
|
|
4410
|
+
op,
|
|
4411
|
+
left: toPathOrLiteral(l),
|
|
4412
|
+
right: toPathOrLiteral(r)
|
|
4413
|
+
}), "cmp");
|
|
4414
|
+
var eq = cmp("eq");
|
|
4415
|
+
var ne = cmp("ne");
|
|
4416
|
+
var gt = cmp("gt");
|
|
4417
|
+
var gte = cmp("gte");
|
|
4418
|
+
var lt = cmp("lt");
|
|
4419
|
+
var lte = cmp("lte");
|
|
4420
|
+
var inSet = /* @__PURE__ */ __name3((v, set) => ({
|
|
4421
|
+
op: "in",
|
|
4422
|
+
value: {
|
|
4423
|
+
path: v.path
|
|
4424
|
+
},
|
|
4425
|
+
set
|
|
4426
|
+
}), "inSet");
|
|
4427
|
+
var notIn = /* @__PURE__ */ __name3((v, set) => ({
|
|
4428
|
+
op: "notIn",
|
|
4429
|
+
value: {
|
|
4430
|
+
path: v.path
|
|
4431
|
+
},
|
|
4432
|
+
set
|
|
4433
|
+
}), "notIn");
|
|
4434
|
+
var exists = /* @__PURE__ */ __name3((ref) => ({
|
|
4435
|
+
op: "exists",
|
|
4436
|
+
path: ref.path
|
|
4437
|
+
}), "exists");
|
|
4438
|
+
var notExists = /* @__PURE__ */ __name3((ref) => ({
|
|
4439
|
+
op: "notExists",
|
|
4440
|
+
path: ref.path
|
|
4441
|
+
}), "notExists");
|
|
4442
|
+
var truthy = /* @__PURE__ */ __name3((ref) => ({
|
|
4443
|
+
op: "truthy",
|
|
4444
|
+
value: {
|
|
4445
|
+
path: ref.path
|
|
4446
|
+
}
|
|
4447
|
+
}), "truthy");
|
|
4448
|
+
var falsy = /* @__PURE__ */ __name3((ref) => ({
|
|
4449
|
+
op: "falsy",
|
|
4450
|
+
value: {
|
|
4451
|
+
path: ref.path
|
|
4452
|
+
}
|
|
4453
|
+
}), "falsy");
|
|
4454
|
+
var and = /* @__PURE__ */ __name3((...args) => ({
|
|
4455
|
+
op: "and",
|
|
4456
|
+
args
|
|
4457
|
+
}), "and");
|
|
4458
|
+
var or = /* @__PURE__ */ __name3((...args) => ({
|
|
4459
|
+
op: "or",
|
|
4460
|
+
args
|
|
4461
|
+
}), "or");
|
|
4462
|
+
var not = /* @__PURE__ */ __name3((arg) => ({
|
|
4463
|
+
op: "not",
|
|
4464
|
+
arg
|
|
4465
|
+
}), "not");
|
|
3870
4466
|
var CONTINUED_FAILURE_TAG = "continued_failure";
|
|
3871
4467
|
var CONTINUED_FAILURE_DEFAULT_CODE = "step_failed";
|
|
3872
4468
|
var CONTINUED_FAILURE_OUTPUT_SCHEMA = Object.freeze({
|
|
@@ -3938,21 +4534,14 @@ function isContinuedFailureValue(v) {
|
|
|
3938
4534
|
__name(isContinuedFailureValue, "isContinuedFailureValue");
|
|
3939
4535
|
__name3(isContinuedFailureValue, "isContinuedFailureValue");
|
|
3940
4536
|
var isHitlNode2 = /* @__PURE__ */ __name3((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
|
|
3941
|
-
function
|
|
3942
|
-
const stepId = nodeIdOf(step22);
|
|
4537
|
+
function inlineContainerArm(mapping, step22) {
|
|
3943
4538
|
return {
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
workflowId: WORKFLOW_ARM_SUBRUN_ID,
|
|
3947
|
-
kind: "subrun",
|
|
3948
|
-
graph: [
|
|
3949
|
-
mapping,
|
|
3950
|
-
step22
|
|
3951
|
-
]
|
|
4539
|
+
...step22,
|
|
4540
|
+
input: parseMapConfig(mapping.mapConfig, mapping.id)
|
|
3952
4541
|
};
|
|
3953
4542
|
}
|
|
3954
|
-
__name(
|
|
3955
|
-
__name3(
|
|
4543
|
+
__name(inlineContainerArm, "inlineContainerArm");
|
|
4544
|
+
__name3(inlineContainerArm, "inlineContainerArm");
|
|
3956
4545
|
var nodeIdOf = /* @__PURE__ */ __name3((n2) => n2.type === "step" ? n2.step.id : n2.id, "nodeIdOf");
|
|
3957
4546
|
function entryIds(entry) {
|
|
3958
4547
|
switch (entry.type) {
|
|
@@ -4023,6 +4612,27 @@ function resolvePlacements(calls) {
|
|
|
4023
4612
|
break;
|
|
4024
4613
|
}
|
|
4025
4614
|
});
|
|
4615
|
+
const armMapPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
|
|
4616
|
+
if (!ref.armMap || node.type === "mapping" || isHitlNode2(node)) return void 0;
|
|
4617
|
+
const id = nodeIdOf(node);
|
|
4618
|
+
if ((container === "foreach" || container === "loop") && node.type !== "workflow") {
|
|
4619
|
+
return {
|
|
4620
|
+
code: "mapping-placement",
|
|
4621
|
+
message: container === "foreach" ? `foreach body "${id}": a [map, step] body is not supported \u2014 the body receives each item as its input; map the items before the foreach instead (foreach(step, { items: \u2026 }) or a .map() before it)` : `loop body "${id}": a [map, step] body is not supported \u2014 the body receives the previous output as its input; put the .map() before the loop instead`,
|
|
4622
|
+
callIndex: i,
|
|
4623
|
+
stepId: id
|
|
4624
|
+
};
|
|
4625
|
+
}
|
|
4626
|
+
if (node.input !== void 0) {
|
|
4627
|
+
return {
|
|
4628
|
+
code: "mapping-placement",
|
|
4629
|
+
message: `"${id}": the [map, step] arm mapping and the node's own input map would both bind its input \u2014 keep one (drop the arm map, or the \`input\` on the declaration)`,
|
|
4630
|
+
callIndex: i,
|
|
4631
|
+
stepId: id
|
|
4632
|
+
};
|
|
4633
|
+
}
|
|
4634
|
+
return void 0;
|
|
4635
|
+
}, "armMapPlacementIssue");
|
|
4026
4636
|
const hitlPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
|
|
4027
4637
|
if (!isHitlNode2(node)) return void 0;
|
|
4028
4638
|
const id = node.id;
|
|
@@ -4049,7 +4659,7 @@ function resolvePlacements(calls) {
|
|
|
4049
4659
|
if (ref.node.type === "mapping" && !allowMapping) {
|
|
4050
4660
|
issues.push({
|
|
4051
4661
|
code: "mapping-placement",
|
|
4052
|
-
message: `mapping "${ref.node.id}" cannot be a container arm \u2014 chain it as [map, step]`,
|
|
4662
|
+
message: `mapping "${ref.node.id}" cannot be a container arm \u2014 chain it as [map, step] in a parallel / conditional arm, or place the .map() before the container`,
|
|
4053
4663
|
callIndex: i,
|
|
4054
4664
|
stepId: ref.node.id
|
|
4055
4665
|
});
|
|
@@ -4070,7 +4680,7 @@ function resolvePlacements(calls) {
|
|
|
4070
4680
|
if (d.node.type === "mapping" && !allowMapping) {
|
|
4071
4681
|
issues.push({
|
|
4072
4682
|
code: "mapping-placement",
|
|
4073
|
-
message: `map "${ref.ref}" cannot be a parallel/foreach/loop arm \u2014 chain it as [map, step]`,
|
|
4683
|
+
message: `map "${ref.ref}" cannot be a parallel/foreach/loop arm \u2014 chain it as [map, step] in a parallel arm, or place the .map() before the container`,
|
|
4074
4684
|
callIndex: i,
|
|
4075
4685
|
stepId: ref.ref
|
|
4076
4686
|
});
|
|
@@ -4081,6 +4691,11 @@ function resolvePlacements(calls) {
|
|
|
4081
4691
|
issues.push(hitl);
|
|
4082
4692
|
return void 0;
|
|
4083
4693
|
}
|
|
4694
|
+
const mapped = armMapPlacementIssue(d.node, ref, i, container);
|
|
4695
|
+
if (mapped) {
|
|
4696
|
+
issues.push(mapped);
|
|
4697
|
+
return void 0;
|
|
4698
|
+
}
|
|
4084
4699
|
const prior = placedBy.get(ref.ref);
|
|
4085
4700
|
if (prior !== void 0 && prior !== i) {
|
|
4086
4701
|
issues.push({
|
|
@@ -4101,6 +4716,10 @@ function resolvePlacements(calls) {
|
|
|
4101
4716
|
}
|
|
4102
4717
|
const hitl = hitlPlacementIssue(ref.node, ref, i, container);
|
|
4103
4718
|
if (hitl) issues.push(hitl);
|
|
4719
|
+
else {
|
|
4720
|
+
const mapped = armMapPlacementIssue(ref.node, ref, i, container);
|
|
4721
|
+
if (mapped) issues.push(mapped);
|
|
4722
|
+
}
|
|
4104
4723
|
}, "claim");
|
|
4105
4724
|
calls.forEach((call, i) => {
|
|
4106
4725
|
switch (call.kind) {
|
|
@@ -4128,7 +4747,7 @@ function resolvePlacements(calls) {
|
|
|
4128
4747
|
const lookup = /* @__PURE__ */ __name3((ref) => {
|
|
4129
4748
|
const n2 = "node" in ref ? ref.node : declared.get(ref.ref)?.node;
|
|
4130
4749
|
if (!n2 || !ref.armMap || n2.type === "mapping" || isHitlNode2(n2)) return n2;
|
|
4131
|
-
return
|
|
4750
|
+
return inlineContainerArm(ref.armMap, n2);
|
|
4132
4751
|
}, "lookup");
|
|
4133
4752
|
calls.forEach((call, i) => {
|
|
4134
4753
|
switch (call.kind) {
|
|
@@ -4569,6 +5188,33 @@ function pruneUndefined(o) {
|
|
|
4569
5188
|
}
|
|
4570
5189
|
__name(pruneUndefined, "pruneUndefined");
|
|
4571
5190
|
__name3(pruneUndefined, "pruneUndefined");
|
|
5191
|
+
var WORKFLOW_INLINE_RUN_TAG = "inline";
|
|
5192
|
+
function runOrigin(run) {
|
|
5193
|
+
if (run.goalId) return "goal";
|
|
5194
|
+
if (run.jobId || run.trigger === "schedule") return "schedule";
|
|
5195
|
+
if (run.dynamic === true) return run.tags?.includes(WORKFLOW_INLINE_RUN_TAG) ? "inline" : "compose";
|
|
5196
|
+
return "definition";
|
|
5197
|
+
}
|
|
5198
|
+
__name(runOrigin, "runOrigin");
|
|
5199
|
+
__name3(runOrigin, "runOrigin");
|
|
5200
|
+
var RUN_ERROR_ISSUES_MAX = 20;
|
|
5201
|
+
function runErrorIssues(issues) {
|
|
5202
|
+
if (!Array.isArray(issues)) return void 0;
|
|
5203
|
+
const out = [];
|
|
5204
|
+
for (const raw of issues.slice(0, RUN_ERROR_ISSUES_MAX)) {
|
|
5205
|
+
if (!raw || typeof raw !== "object") continue;
|
|
5206
|
+
const o = raw;
|
|
5207
|
+
if (typeof o.code !== "string" || !o.code) continue;
|
|
5208
|
+
out.push(pruneUndefined({
|
|
5209
|
+
code: o.code,
|
|
5210
|
+
path: typeof o.path === "string" ? o.path : void 0,
|
|
5211
|
+
message: typeof o.message === "string" ? o.message : void 0
|
|
5212
|
+
}));
|
|
5213
|
+
}
|
|
5214
|
+
return out.length ? out : void 0;
|
|
5215
|
+
}
|
|
5216
|
+
__name(runErrorIssues, "runErrorIssues");
|
|
5217
|
+
__name3(runErrorIssues, "runErrorIssues");
|
|
4572
5218
|
function runNextAction(run) {
|
|
4573
5219
|
if (isTerminalRunStatus(run.status)) return "none";
|
|
4574
5220
|
if (run.status === "suspended" && run.gate?.kind === "budget") return "raise_budget";
|
|
@@ -4626,10 +5272,57 @@ function runCounts(counts) {
|
|
|
4626
5272
|
}
|
|
4627
5273
|
__name(runCounts, "runCounts");
|
|
4628
5274
|
__name3(runCounts, "runCounts");
|
|
4629
|
-
function
|
|
5275
|
+
function isPricedStepReceipt(receipt) {
|
|
5276
|
+
return typeof receipt?.multiplier === "number" && Number.isFinite(receipt.multiplier);
|
|
5277
|
+
}
|
|
5278
|
+
__name(isPricedStepReceipt, "isPricedStepReceipt");
|
|
5279
|
+
__name3(isPricedStepReceipt, "isPricedStepReceipt");
|
|
5280
|
+
function receiptEngine(engine) {
|
|
5281
|
+
if (engine === "actions") return "seat";
|
|
5282
|
+
if (engine === "credits") return "legacy";
|
|
5283
|
+
return void 0;
|
|
5284
|
+
}
|
|
5285
|
+
__name(receiptEngine, "receiptEngine");
|
|
5286
|
+
__name3(receiptEngine, "receiptEngine");
|
|
5287
|
+
function receiptTier(tier) {
|
|
5288
|
+
return tier === "light" || tier === "standard" || tier === "heavy" ? tier : void 0;
|
|
5289
|
+
}
|
|
5290
|
+
__name(receiptTier, "receiptTier");
|
|
5291
|
+
__name3(receiptTier, "receiptTier");
|
|
5292
|
+
function stepBillingView(receipt) {
|
|
5293
|
+
const engine = receiptEngine(receipt?.engine);
|
|
5294
|
+
if (!receipt || engine === void 0) return void 0;
|
|
5295
|
+
return pruneUndefined({
|
|
5296
|
+
engine,
|
|
5297
|
+
attempt: typeof receipt.attempt === "number" ? receipt.attempt : void 0,
|
|
5298
|
+
credits: typeof receipt.credits === "number" ? receipt.credits : void 0,
|
|
5299
|
+
actions: typeof receipt.actionsEstimate === "number" ? receipt.actionsEstimate : void 0,
|
|
5300
|
+
model: typeof receipt.model === "string" ? receipt.model : void 0,
|
|
5301
|
+
tier: receiptTier(receipt.tier),
|
|
5302
|
+
multiplier: typeof receipt.multiplier === "number" ? receipt.multiplier : void 0,
|
|
5303
|
+
byok: typeof receipt.byok === "boolean" ? receipt.byok : void 0,
|
|
5304
|
+
calibrated: typeof receipt.calibrated === "boolean" ? receipt.calibrated : void 0
|
|
5305
|
+
});
|
|
5306
|
+
}
|
|
5307
|
+
__name(stepBillingView, "stepBillingView");
|
|
5308
|
+
__name3(stepBillingView, "stepBillingView");
|
|
5309
|
+
function runUsage(run, receipts) {
|
|
5310
|
+
const actions = n(run.budget?.spent?.actionsEstimate);
|
|
5311
|
+
const stamped = run.budget?.engine;
|
|
5312
|
+
const priced = (receipts ?? []).filter(isPricedStepReceipt);
|
|
5313
|
+
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;
|
|
5314
|
+
const seat = engine === "seat";
|
|
5315
|
+
const metering = engine ? "priced" : "flat";
|
|
4630
5316
|
return {
|
|
4631
5317
|
creditsUsed: run.budget?.spent?.credits ?? 0,
|
|
4632
5318
|
actionsEstimate: run.budget?.spent?.actionsEstimate ?? 0,
|
|
5319
|
+
...seat ? {
|
|
5320
|
+
actionsUsed: actions
|
|
5321
|
+
} : {},
|
|
5322
|
+
metering,
|
|
5323
|
+
...engine ? {
|
|
5324
|
+
engine
|
|
5325
|
+
} : {},
|
|
4633
5326
|
steps: run.budget?.spent?.steps ?? 0,
|
|
4634
5327
|
inputTokens: run.usage?.inputTokens ?? 0,
|
|
4635
5328
|
outputTokens: run.usage?.outputTokens ?? 0
|
|
@@ -4637,6 +5330,20 @@ function runUsage(run) {
|
|
|
4637
5330
|
}
|
|
4638
5331
|
__name(runUsage, "runUsage");
|
|
4639
5332
|
__name3(runUsage, "runUsage");
|
|
5333
|
+
function runBudgetCap(budget) {
|
|
5334
|
+
const cap = budget?.maxCredits;
|
|
5335
|
+
return typeof cap === "number" && Number.isFinite(cap) && cap > 0 ? cap : void 0;
|
|
5336
|
+
}
|
|
5337
|
+
__name(runBudgetCap, "runBudgetCap");
|
|
5338
|
+
__name3(runBudgetCap, "runBudgetCap");
|
|
5339
|
+
function runBudgetRemaining(budget) {
|
|
5340
|
+
const cap = runBudgetCap(budget);
|
|
5341
|
+
if (cap === void 0) return void 0;
|
|
5342
|
+
const spent = budget?.spent;
|
|
5343
|
+
return Math.max(0, cap - n(spent?.credits) - n(spent?.actionsEstimate) - n(budget?.reserved));
|
|
5344
|
+
}
|
|
5345
|
+
__name(runBudgetRemaining, "runBudgetRemaining");
|
|
5346
|
+
__name3(runBudgetRemaining, "runBudgetRemaining");
|
|
4640
5347
|
function runCancelView(cancel) {
|
|
4641
5348
|
if (!cancel) return void 0;
|
|
4642
5349
|
return {
|
|
@@ -4707,6 +5414,7 @@ function toWorkflowRunSummary(run) {
|
|
|
4707
5414
|
repairOf: run.repairOf,
|
|
4708
5415
|
repairRunIds: run.repairRunIds,
|
|
4709
5416
|
trigger: run.trigger ?? "api",
|
|
5417
|
+
origin: runOrigin(run),
|
|
4710
5418
|
createdBy: {
|
|
4711
5419
|
subjectType: principal?.subjectType ?? "system",
|
|
4712
5420
|
subjectId: principal?.subjectId ?? run.userId ?? ""
|
|
@@ -4724,11 +5432,13 @@ function toWorkflowRunSummary(run) {
|
|
|
4724
5432
|
usage: runUsage(run),
|
|
4725
5433
|
// LUA-697: a row persisted before the write seams (#2406 / #2465 / the script tier) leaves scrubbed here too —
|
|
4726
5434
|
// idempotent on a scrubbed message, bounded input; an empty message falls back to the code.
|
|
4727
|
-
error: run.error ? {
|
|
5435
|
+
error: run.error ? pruneUndefined({
|
|
4728
5436
|
code: run.error.code ?? "error",
|
|
4729
5437
|
message: scrubStepErrorMessage(run.error.message) ?? run.error.code ?? "error",
|
|
4730
|
-
stepId: run.error.stepId
|
|
4731
|
-
|
|
5438
|
+
stepId: run.error.stepId,
|
|
5439
|
+
// LUA-784 (item 3): the unattended pre-start failure's refusal rows (`input_schema_invalid` and kin).
|
|
5440
|
+
issues: runErrorIssues(run.error.issues)
|
|
5441
|
+
}) : void 0,
|
|
4732
5442
|
kind: "run",
|
|
4733
5443
|
aclHash: run.aclHash,
|
|
4734
5444
|
migration: run.migration,
|
|
@@ -5381,204 +6091,6 @@ function rebaseItemPointer(pointer, itemsPath, index) {
|
|
|
5381
6091
|
}
|
|
5382
6092
|
__name(rebaseItemPointer, "rebaseItemPointer");
|
|
5383
6093
|
__name3(rebaseItemPointer, "rebaseItemPointer");
|
|
5384
|
-
var APPROVER_SPEC_MAX_USERS = 20;
|
|
5385
|
-
var ESCALATION_MAX_HOPS = 3;
|
|
5386
|
-
var TemplateBindingSchema = z22.object({
|
|
5387
|
-
template: z22.string().min(1).max(2048)
|
|
5388
|
-
}).strict();
|
|
5389
|
-
var ApproverSpecSchema = z22.union([
|
|
5390
|
-
z22.literal("creator"),
|
|
5391
|
-
z22.literal("org-admins"),
|
|
5392
|
-
z22.object({
|
|
5393
|
-
users: z22.union([
|
|
5394
|
-
z22.array(z22.string().min(1).max(128)).min(1).max(APPROVER_SPEC_MAX_USERS),
|
|
5395
|
-
TemplateBindingSchema
|
|
5396
|
-
])
|
|
5397
|
-
}).strict(),
|
|
5398
|
-
z22.object({
|
|
5399
|
-
role: z22.union([
|
|
5400
|
-
z22.string().min(1).max(128),
|
|
5401
|
-
TemplateBindingSchema
|
|
5402
|
-
])
|
|
5403
|
-
}).strict(),
|
|
5404
|
-
z22.object({
|
|
5405
|
-
group: z22.union([
|
|
5406
|
-
z22.string().min(1).max(128),
|
|
5407
|
-
TemplateBindingSchema
|
|
5408
|
-
])
|
|
5409
|
-
}).strict(),
|
|
5410
|
-
z22.object({
|
|
5411
|
-
governance: z22.object({
|
|
5412
|
-
policyId: z22.string().min(1).max(128)
|
|
5413
|
-
}).strict()
|
|
5414
|
-
}).strict()
|
|
5415
|
-
]);
|
|
5416
|
-
var FourEyesSchema = z22.object({
|
|
5417
|
-
edit: ApproverSpecSchema,
|
|
5418
|
-
approve: ApproverSpecSchema
|
|
5419
|
-
}).strict();
|
|
5420
|
-
var EscalationHopSchema = z22.object({
|
|
5421
|
-
escalateTo: ApproverSpecSchema,
|
|
5422
|
-
timeoutHours: z22.number().finite().min(1).max(720)
|
|
5423
|
-
}).strict();
|
|
5424
|
-
var TerminalOutcomeSchema = z22.enum([
|
|
5425
|
-
"deny",
|
|
5426
|
-
"cancel-run",
|
|
5427
|
-
"fail",
|
|
5428
|
-
"continue"
|
|
5429
|
-
]);
|
|
5430
|
-
var ApprovalOnTimeoutSchema = z22.union([
|
|
5431
|
-
TerminalOutcomeSchema,
|
|
5432
|
-
EscalationHopSchema,
|
|
5433
|
-
z22.array(z22.union([
|
|
5434
|
-
TerminalOutcomeSchema,
|
|
5435
|
-
EscalationHopSchema
|
|
5436
|
-
])).min(1).max(ESCALATION_MAX_HOPS + 1)
|
|
5437
|
-
]);
|
|
5438
|
-
var APPROVER_SPEC_SHAPES = [
|
|
5439
|
-
"'creator'",
|
|
5440
|
-
"'org-admins'",
|
|
5441
|
-
"{users:[userId, \u2026]}",
|
|
5442
|
-
"{role:roleName}",
|
|
5443
|
-
"{group:groupName}",
|
|
5444
|
-
"{governance:{policyId}}"
|
|
5445
|
-
];
|
|
5446
|
-
var APPROVER_WRITTEN_MAX = 120;
|
|
5447
|
-
var USER_ID_SHAPED_RE = /^[^\s@]{1,128}$/;
|
|
5448
|
-
function describeApproverSpecRefusal(spec) {
|
|
5449
|
-
const raw = spec === void 0 ? "undefined" : JSON.stringify(spec) ?? String(spec);
|
|
5450
|
-
const written = raw.length > APPROVER_WRITTEN_MAX ? `${raw.slice(0, APPROVER_WRITTEN_MAX - 1)}\u2026` : raw;
|
|
5451
|
-
const users = typeof spec === "object" && spec !== null ? spec.users : void 0;
|
|
5452
|
-
const approver = typeof users === "string" && USER_ID_SHAPED_RE.test(users) ? {
|
|
5453
|
-
users: [
|
|
5454
|
-
users
|
|
5455
|
-
]
|
|
5456
|
-
} : "creator";
|
|
5457
|
-
const message = `approver ${written} is not an approver \u2014 legal: ${APPROVER_SPEC_SHAPES.join(" | ")}. 'creator' is the person who started the run: write approver:'creator' for "ask me" / "I approve"; {users:[\u2026]} takes user ids, never emails, names or {type:'user'}` + (approver === "creator" ? "" : `; here: approver:${JSON.stringify(approver)}`);
|
|
5458
|
-
return {
|
|
5459
|
-
approver,
|
|
5460
|
-
written,
|
|
5461
|
-
message
|
|
5462
|
-
};
|
|
5463
|
-
}
|
|
5464
|
-
__name(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
5465
|
-
__name3(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
5466
|
-
var BINDING_ROOTS = [
|
|
5467
|
-
"initData",
|
|
5468
|
-
"stepResults",
|
|
5469
|
-
"requestContext",
|
|
5470
|
-
"state"
|
|
5471
|
-
];
|
|
5472
|
-
function bindingRootsOk(template22) {
|
|
5473
|
-
const refs = [
|
|
5474
|
-
...template22.matchAll(/\$\{\s*([A-Za-z_$][\w$]*)/g)
|
|
5475
|
-
].map((m) => m[1]);
|
|
5476
|
-
return refs.length > 0 && refs.every((r) => BINDING_ROOTS.includes(r));
|
|
5477
|
-
}
|
|
5478
|
-
__name(bindingRootsOk, "bindingRootsOk");
|
|
5479
|
-
__name3(bindingRootsOk, "bindingRootsOk");
|
|
5480
|
-
function isTemplateBinding(v) {
|
|
5481
|
-
return typeof v === "object" && v !== null && typeof v.template === "string";
|
|
5482
|
-
}
|
|
5483
|
-
__name(isTemplateBinding, "isTemplateBinding");
|
|
5484
|
-
__name3(isTemplateBinding, "isTemplateBinding");
|
|
5485
|
-
function validateApproverBlock(node, opts = {
|
|
5486
|
-
path: "approval"
|
|
5487
|
-
}) {
|
|
5488
|
-
const issues = [];
|
|
5489
|
-
const push = /* @__PURE__ */ __name3((code, path, message, severity = "error") => issues.push({
|
|
5490
|
-
code,
|
|
5491
|
-
path,
|
|
5492
|
-
severity,
|
|
5493
|
-
message
|
|
5494
|
-
}), "push");
|
|
5495
|
-
const checkSpec = /* @__PURE__ */ __name3((spec, path) => {
|
|
5496
|
-
const r = ApproverSpecSchema.safeParse(spec);
|
|
5497
|
-
if (!r.success) {
|
|
5498
|
-
const users = spec?.users;
|
|
5499
|
-
if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path, `at most ${APPROVER_SPEC_MAX_USERS} users`);
|
|
5500
|
-
else {
|
|
5501
|
-
const refusal = describeApproverSpecRefusal(spec);
|
|
5502
|
-
issues.push({
|
|
5503
|
-
code: "approver-invalid",
|
|
5504
|
-
path,
|
|
5505
|
-
severity: "error",
|
|
5506
|
-
message: refusal.message,
|
|
5507
|
-
repair: {
|
|
5508
|
-
approver: refusal.approver,
|
|
5509
|
-
written: refusal.written
|
|
5510
|
-
}
|
|
5511
|
-
});
|
|
5512
|
-
}
|
|
5513
|
-
return;
|
|
5514
|
-
}
|
|
5515
|
-
const s = r.data;
|
|
5516
|
-
if (typeof s === "object") {
|
|
5517
|
-
if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path, "governance reviewer routing is not enabled for this deployment");
|
|
5518
|
-
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path, "IdP-group approvers are not enabled for this deployment");
|
|
5519
|
-
const binding = "users" in s ? s.users : "role" in s ? s.role : "group" in s ? s.group : void 0;
|
|
5520
|
-
if (isTemplateBinding(binding)) {
|
|
5521
|
-
if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path}.template`, "binding root must be initData / stepResults / requestContext / state");
|
|
5522
|
-
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path}.users`, "a customer-reachable workflow may not bind its approver list");
|
|
5523
|
-
}
|
|
5524
|
-
}
|
|
5525
|
-
}, "checkSpec");
|
|
5526
|
-
if (node.approver !== void 0) checkSpec(node.approver, `${opts.path}.approver`);
|
|
5527
|
-
if (node.fourEyes !== void 0) {
|
|
5528
|
-
const r = FourEyesSchema.safeParse(node.fourEyes);
|
|
5529
|
-
if (!r.success) push("approver-invalid", `${opts.path}.fourEyes`, "fourEyes needs { edit, approve } approver specs");
|
|
5530
|
-
else {
|
|
5531
|
-
checkSpec(r.data.edit, `${opts.path}.fourEyes.edit`);
|
|
5532
|
-
checkSpec(r.data.approve, `${opts.path}.fourEyes.approve`);
|
|
5533
|
-
}
|
|
5534
|
-
if (!node.editable) push("four-eyes-requires-editable", `${opts.path}.fourEyes`, "fourEyes requires editable:true");
|
|
5535
|
-
if (node.approver !== void 0) push("four-eyes-overrides-approver", `${opts.path}.approver`, "fourEyes replaces approver", "warning");
|
|
5536
|
-
if (node.itemsPath) push("four-eyes-items-unsupported", `${opts.path}.fourEyes`, "fourEyes cannot combine with itemsPath");
|
|
5537
|
-
}
|
|
5538
|
-
if (node.excludeInitiator && (node.approver === void 0 || node.approver === "creator") && !node.fourEyes) push("approver-excludes-only-candidate", `${opts.path}.excludeInitiator`, "'creator' with excludeInitiator leaves no approver");
|
|
5539
|
-
if (Array.isArray(node.onTimeout)) {
|
|
5540
|
-
const chain = node.onTimeout;
|
|
5541
|
-
const hops = chain.filter((m) => typeof m === "object" && m !== null && "escalateTo" in m);
|
|
5542
|
-
if (hops.length > ESCALATION_MAX_HOPS) push("escalation-chain-too-long", `${opts.path}.onTimeout`, `at most ${ESCALATION_MAX_HOPS} hops`);
|
|
5543
|
-
const last = chain[chain.length - 1];
|
|
5544
|
-
if (typeof last === "object" && last !== null) push("escalation-chain-not-terminal", `${opts.path}.onTimeout`, "a chain must end in deny | cancel-run | fail");
|
|
5545
|
-
hops.forEach((h, i) => checkSpec(h.escalateTo, `${opts.path}.onTimeout[${i}].escalateTo`));
|
|
5546
|
-
} else if (typeof node.onTimeout === "object" && node.onTimeout !== null) {
|
|
5547
|
-
checkSpec(node.onTimeout.escalateTo, `${opts.path}.onTimeout.escalateTo`);
|
|
5548
|
-
}
|
|
5549
|
-
return issues;
|
|
5550
|
-
}
|
|
5551
|
-
__name(validateApproverBlock, "validateApproverBlock");
|
|
5552
|
-
__name3(validateApproverBlock, "validateApproverBlock");
|
|
5553
|
-
function liftRenderedApprover(row, rendered) {
|
|
5554
|
-
const text = (rendered ?? "").trim();
|
|
5555
|
-
if (!text) return null;
|
|
5556
|
-
if (row === "users") {
|
|
5557
|
-
let members = null;
|
|
5558
|
-
if (text.startsWith("[")) {
|
|
5559
|
-
try {
|
|
5560
|
-
members = JSON.parse(text);
|
|
5561
|
-
} catch {
|
|
5562
|
-
return null;
|
|
5563
|
-
}
|
|
5564
|
-
} else members = text.split(",").map((s) => s.trim());
|
|
5565
|
-
if (!Array.isArray(members) || members.length === 0 || members.length > APPROVER_SPEC_MAX_USERS) return null;
|
|
5566
|
-
if (!members.every((m) => typeof m === "string" && m.length > 0 && m.length <= 128)) return null;
|
|
5567
|
-
return {
|
|
5568
|
-
users: [
|
|
5569
|
-
...new Set(members)
|
|
5570
|
-
].sort()
|
|
5571
|
-
};
|
|
5572
|
-
}
|
|
5573
|
-
if (text.length > 128 || text.startsWith("[") || text.startsWith("{")) return null;
|
|
5574
|
-
return row === "role" ? {
|
|
5575
|
-
role: text
|
|
5576
|
-
} : {
|
|
5577
|
-
group: text
|
|
5578
|
-
};
|
|
5579
|
-
}
|
|
5580
|
-
__name(liftRenderedApprover, "liftRenderedApprover");
|
|
5581
|
-
__name3(liftRenderedApprover, "liftRenderedApprover");
|
|
5582
6094
|
var WORKFLOW_ENV_OVERLAY_MAX_KEYS = 64;
|
|
5583
6095
|
var WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES = 4096;
|
|
5584
6096
|
var WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
|
|
@@ -5862,7 +6374,6 @@ function* singleStepsOf(entry) {
|
|
|
5862
6374
|
return;
|
|
5863
6375
|
case "workflow":
|
|
5864
6376
|
yield entry;
|
|
5865
|
-
if (Array.isArray(entry.graph)) yield* singleStepsOf(entry.graph[1]);
|
|
5866
6377
|
return;
|
|
5867
6378
|
case "parallel":
|
|
5868
6379
|
case "conditional":
|
|
@@ -6021,6 +6532,10 @@ var assertPredicate = /* @__PURE__ */ __name((p, where) => {
|
|
|
6021
6532
|
}, "assertPredicate");
|
|
6022
6533
|
var assertRetry = /* @__PURE__ */ __name((r, id) => {
|
|
6023
6534
|
if (!r) return;
|
|
6535
|
+
if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
6536
|
+
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
6537
|
+
throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
|
|
6538
|
+
}
|
|
6024
6539
|
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
6540
|
if (r.maxBackoffSeconds !== void 0) {
|
|
6026
6541
|
if (r.backoff !== "exponential") throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.maxBackoffSeconds is only meaningful with backoff:'exponential'`);
|
|
@@ -6170,14 +6685,13 @@ function stepNodeOf(s) {
|
|
|
6170
6685
|
__name(stepNodeOf, "stepNodeOf");
|
|
6171
6686
|
function materializeEntry(entry, steps) {
|
|
6172
6687
|
const single = /* @__PURE__ */ __name((n2) => {
|
|
6173
|
-
if (n2.type === "step" && steps[n2.step.id])
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
n2.
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
};
|
|
6688
|
+
if (n2.type === "step" && steps[n2.step.id]) {
|
|
6689
|
+
const node = stepNodeOf(steps[n2.step.id]);
|
|
6690
|
+
return n2.input !== void 0 ? {
|
|
6691
|
+
...node,
|
|
6692
|
+
input: n2.input
|
|
6693
|
+
} : node;
|
|
6694
|
+
}
|
|
6181
6695
|
return n2;
|
|
6182
6696
|
}, "single");
|
|
6183
6697
|
switch (entry.type) {
|