lua-cli 3.32.3 → 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 +5 -3
- package/dist/api-exports.js +634 -297
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +1443 -923
- package/dist/index.js.map +1 -1
- package/dist/workflow-builder.d.ts +5 -3
- package/dist/workflow-builder.js +426 -256
- package/dist/workflow-builder.js.map +1 -1
- package/docs/README.md +2 -2
- package/docs/api/LuaWorkflow.md +1 -1
- package/docs/workflows/approvals.md +2 -0
- package/docs/workflows/recovery.md +1 -1
- package/docs/workflows/schedules.md +13 -4
- package/package.json +4 -4
- package/template/examples/workflows/research-brief.ts +29 -16
- package/template/package.json +1 -1
package/dist/api-exports.js
CHANGED
|
@@ -353,6 +353,84 @@ function isDesktopFileCommandName(value3) {
|
|
|
353
353
|
function isDesktopFileSessionId(value3) {
|
|
354
354
|
return typeof value3 === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value3);
|
|
355
355
|
}
|
|
356
|
+
function isModelIdSentinel(input) {
|
|
357
|
+
const lower = (input ?? "").trim().toLowerCase();
|
|
358
|
+
return lower === "auto" || lower.startsWith("auto/");
|
|
359
|
+
}
|
|
360
|
+
function normalizeModelId(input, registry) {
|
|
361
|
+
const requested = typeof input === "string" ? input.trim() : "";
|
|
362
|
+
if (!requested) return {
|
|
363
|
+
ok: false,
|
|
364
|
+
reason: "empty",
|
|
365
|
+
requested,
|
|
366
|
+
candidates: []
|
|
367
|
+
};
|
|
368
|
+
const lower = requested.toLowerCase();
|
|
369
|
+
if (isModelIdSentinel(lower)) return {
|
|
370
|
+
ok: true,
|
|
371
|
+
id: lower,
|
|
372
|
+
form: "sentinel"
|
|
373
|
+
};
|
|
374
|
+
const slash = requested.indexOf("/");
|
|
375
|
+
const malformed = slash === 0;
|
|
376
|
+
const provider = slash > 0 ? lower.slice(0, slash) : void 0;
|
|
377
|
+
if (provider && MODEL_ID_BYOK_PROVIDERS.includes(provider)) {
|
|
378
|
+
return {
|
|
379
|
+
ok: true,
|
|
380
|
+
id: requested,
|
|
381
|
+
form: "byok"
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const bareId = slash >= 0 ? lower.slice(slash + 1) : lower;
|
|
385
|
+
const lastSegment = bareId.slice(bareId.lastIndexOf("/") + 1);
|
|
386
|
+
const exact = /* @__PURE__ */ new Set();
|
|
387
|
+
const hints = /* @__PURE__ */ new Set();
|
|
388
|
+
for (const code of registry) {
|
|
389
|
+
if (typeof code !== "string" || !code) continue;
|
|
390
|
+
const codeLower = code.toLowerCase();
|
|
391
|
+
if (!malformed && codeLower === lower) return {
|
|
392
|
+
ok: true,
|
|
393
|
+
id: code,
|
|
394
|
+
form: provider ? "canonical" : "bare"
|
|
395
|
+
};
|
|
396
|
+
const i = codeLower.indexOf("/");
|
|
397
|
+
if (i < 0) continue;
|
|
398
|
+
const codeBare = codeLower.slice(i + 1);
|
|
399
|
+
if (bareId && codeBare === bareId) exact.add(code);
|
|
400
|
+
else if (lastSegment && codeBare.slice(codeBare.lastIndexOf("/") + 1) === lastSegment) hints.add(code);
|
|
401
|
+
}
|
|
402
|
+
const sorted = [
|
|
403
|
+
...exact
|
|
404
|
+
].sort();
|
|
405
|
+
if (!provider && !malformed && sorted.length === 1) return {
|
|
406
|
+
ok: true,
|
|
407
|
+
id: sorted[0],
|
|
408
|
+
form: "bare"
|
|
409
|
+
};
|
|
410
|
+
if (!provider && !malformed && sorted.length > 1) {
|
|
411
|
+
return {
|
|
412
|
+
ok: false,
|
|
413
|
+
reason: "ambiguous",
|
|
414
|
+
requested,
|
|
415
|
+
candidates: sorted
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
ok: false,
|
|
420
|
+
reason: "unknown",
|
|
421
|
+
requested,
|
|
422
|
+
candidates: sorted.length ? sorted : [
|
|
423
|
+
...hints
|
|
424
|
+
].sort()
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function modelUnresolvedMessage(r) {
|
|
428
|
+
if (r.reason === "empty") return "model pin is empty \u2014 pin an approved model (provider/model) or omit `model`";
|
|
429
|
+
if (r.reason === "ambiguous") {
|
|
430
|
+
return `model "${r.requested}" does not resolve to one approved model \u2014 it names ${r.candidates.length}; pin one of: ${r.candidates.join(", ")}`;
|
|
431
|
+
}
|
|
432
|
+
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`;
|
|
433
|
+
}
|
|
356
434
|
function isImplicitModelSelectionSource(source) {
|
|
357
435
|
return source !== void 0 && IMPLICIT_MODEL_SELECTION_SOURCES.includes(source);
|
|
358
436
|
}
|
|
@@ -941,7 +1019,7 @@ function extractSingleJsonValue(text) {
|
|
|
941
1019
|
};
|
|
942
1020
|
}
|
|
943
1021
|
}
|
|
944
|
-
var __defProp2, __name2, CHANNEL_SEND_CHANNELS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, CORE_DRAINING_CODE, CORE_DRAINING_DEFAULT_RETRY_MS, CORE_DRAINING_MAX_RETRY_MS, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS, TEMPLATE_TRIGGER_URL_ENV_PREFIX, SUBJECT_TYPES, SubjectTypeSchema, CREDENTIAL_TYPES, CredentialTypeSchema, DEVICE_OPERATIONS, DeviceOperationSchema, DEVICE_SCOPE_BY_OPERATION, DeviceBindingSchema, IdSchema, PrincipalDescriptorSchema, ActorDescriptorSchema, PrincipalOwnerSchema, CredentialLifecycleSchema, GeneralCredentialDescriptorSchema, DeviceCredentialDescriptorSchema, GeneralPrincipalContextSchema, DeviceCredentialPrincipalContextSchema, RawPrincipalContextSchema, PrincipalContextSchema, DeviceCredentialClaimSchema, LUA_CLIENT_HEADER, LUA_CLIENT_APPS, SEMVER_PATTERN, WEB_RELEASE_PATTERN, CLIENT_HEADER_PATTERN, AUTHZ_PROJECTION_VERSION, ProjectedScopeSchema, DisplayRoleSchema, AuthorizationPrincipalSchema, CredentialContextSchema, ProjectionAnomalySchema, ProjectedOrgSchema, ProjectedResourceSchema, CapabilityProfilesSchema, RoleCatalogSchema, EffectiveAuthorizationSchema, ResourcePageSchema, SYSTEM_USER_PREFIX, WORKFLOW_RUN_IN_FLIGHT, WORKFLOW_RUN_IDLE, WORKFLOW_RUN_TERMINAL, WORKFLOW_RUN_STATUSES, WORKFLOW_STEP_STATUSES, WORKFLOW_STEP_IN_FLIGHT, ARCHIVE_WINDOW_MARGIN_DAYS, WORKFLOW_ORG_PURGING_TTL_S, WORKFLOW_ORG_PURGE_FORCE_AFTER_MS, IDEMPOTENCY_HOLDING_STATUSES, WORKFLOW_SCHEDULED_RUN_ID_PREFIX, CLOUD_TASK_RUN_ID_PREFIX, WORKFLOW_OPERATION_ID_PREFIX, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, WORKFLOW_RETRY_BACKOFFS, WORKFLOW_RETRY_MIN_ATTEMPTS, WORKFLOW_RETRY_POLICY_KEYS, WORKFLOW_RETRY_MAX_ATTEMPTS, WORKFLOW_RETRY_ENGINE_KEYS, WORKFLOW_JOB_RESOURCES, WORKFLOW_SIDE_EFFECTS, WORKFLOW_JOB_RANGES, WORKFLOW_JOB_RANGE_MEMBERS, WORKFLOW_SINGLE_STEP_TYPES, WORKFLOW_HITL_ENTRY_TYPES, WORKFLOW_ARM_ENTRY_TYPES, WORKFLOW_HITL_ARM_CONTAINERS, WORKFLOW_GRAPH_ENTRY_STEP_KINDS, WORKFLOW_ARM_ENTRY_STEP_KINDS, WORKFLOW_BUDGET_MAX_DURATION_SECONDS, REDACTED_PLACEHOLDER, PROVIDER_MESSAGE_MAX_CHARS, ERROR_MESSAGE_MAX_CHARS, SECRET_LITERAL_PATTERNS, SECRET_NAME, SECRET_PAIR_PATTERNS, GROUP_COUNT, WORKFLOW_SECRET_KEY_RE, WORKFLOW_RESERVED_SECRET_KEYS, SCRUB_INPUT_MAX_CHARS, SCRUB_CUT_BACKOFF_CHARS, WORKFLOW_AUDIT_EVENTS, WORKFLOW_AUDIT_METADATA_MAX_BYTES, INDENT, WRAP_WIDTH, NOUNS, GET_TOOL_NAMES, PREAMBLE, WORKFLOW_APPROVAL_OUTPUT_DECISIONS, WORKFLOW_APPROVAL_OUTPUT_SCHEMA, JSON_FENCE_RE;
|
|
1022
|
+
var __defProp2, __name2, CHANNEL_SEND_CHANNELS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, MODEL_ID_BYOK_PROVIDERS, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, CORE_DRAINING_CODE, CORE_DRAINING_DEFAULT_RETRY_MS, CORE_DRAINING_MAX_RETRY_MS, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS, TEMPLATE_TRIGGER_URL_ENV_PREFIX, SUBJECT_TYPES, SubjectTypeSchema, CREDENTIAL_TYPES, CredentialTypeSchema, DEVICE_OPERATIONS, DeviceOperationSchema, DEVICE_SCOPE_BY_OPERATION, DeviceBindingSchema, IdSchema, PrincipalDescriptorSchema, ActorDescriptorSchema, PrincipalOwnerSchema, CredentialLifecycleSchema, GeneralCredentialDescriptorSchema, DeviceCredentialDescriptorSchema, GeneralPrincipalContextSchema, DeviceCredentialPrincipalContextSchema, RawPrincipalContextSchema, PrincipalContextSchema, DeviceCredentialClaimSchema, LUA_CLIENT_HEADER, LUA_CLIENT_APPS, SEMVER_PATTERN, WEB_RELEASE_PATTERN, CLIENT_HEADER_PATTERN, AUTHZ_PROJECTION_VERSION, ProjectedScopeSchema, DisplayRoleSchema, AuthorizationPrincipalSchema, CredentialContextSchema, ProjectionAnomalySchema, ProjectedOrgSchema, ProjectedResourceSchema, CapabilityProfilesSchema, RoleCatalogSchema, EffectiveAuthorizationSchema, ResourcePageSchema, SYSTEM_USER_PREFIX, WORKFLOW_RUN_IN_FLIGHT, WORKFLOW_RUN_IDLE, WORKFLOW_RUN_TERMINAL, WORKFLOW_RUN_STATUSES, WORKFLOW_STEP_STATUSES, WORKFLOW_STEP_IN_FLIGHT, ARCHIVE_WINDOW_MARGIN_DAYS, WORKFLOW_ORG_PURGING_TTL_S, WORKFLOW_ORG_PURGE_FORCE_AFTER_MS, IDEMPOTENCY_HOLDING_STATUSES, WORKFLOW_SCHEDULED_RUN_ID_PREFIX, CLOUD_TASK_RUN_ID_PREFIX, WORKFLOW_OPERATION_ID_PREFIX, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, WORKFLOW_RETRY_BACKOFFS, WORKFLOW_RETRY_MIN_ATTEMPTS, WORKFLOW_RETRY_POLICY_KEYS, WORKFLOW_RETRY_MAX_ATTEMPTS, WORKFLOW_RETRY_ENGINE_KEYS, WORKFLOW_JOB_RESOURCES, WORKFLOW_SIDE_EFFECTS, WORKFLOW_JOB_RANGES, WORKFLOW_JOB_RANGE_MEMBERS, WORKFLOW_SINGLE_STEP_TYPES, WORKFLOW_HITL_ENTRY_TYPES, WORKFLOW_ARM_ENTRY_TYPES, WORKFLOW_HITL_ARM_CONTAINERS, WORKFLOW_GRAPH_ENTRY_STEP_KINDS, WORKFLOW_ARM_ENTRY_STEP_KINDS, WORKFLOW_BUDGET_MAX_DURATION_SECONDS, REDACTED_PLACEHOLDER, PROVIDER_MESSAGE_MAX_CHARS, ERROR_MESSAGE_MAX_CHARS, SECRET_LITERAL_PATTERNS, SECRET_NAME, SECRET_PAIR_PATTERNS, GROUP_COUNT, WORKFLOW_SECRET_KEY_RE, WORKFLOW_RESERVED_SECRET_KEYS, SCRUB_INPUT_MAX_CHARS, SCRUB_CUT_BACKOFF_CHARS, WORKFLOW_AUDIT_EVENTS, WORKFLOW_AUDIT_METADATA_MAX_BYTES, INDENT, WRAP_WIDTH, NOUNS, GET_TOOL_NAMES, PREAMBLE, WORKFLOW_APPROVAL_OUTPUT_DECISIONS, WORKFLOW_APPROVAL_OUTPUT_SCHEMA, JSON_FENCE_RE;
|
|
945
1023
|
var init_dist = __esm({
|
|
946
1024
|
"../shared-types/dist/index.mjs"() {
|
|
947
1025
|
"use strict";
|
|
@@ -1258,6 +1336,16 @@ var init_dist = __esm({
|
|
|
1258
1336
|
__name2(isDesktopFileCommandName, "isDesktopFileCommandName");
|
|
1259
1337
|
__name(isDesktopFileSessionId, "isDesktopFileSessionId");
|
|
1260
1338
|
__name2(isDesktopFileSessionId, "isDesktopFileSessionId");
|
|
1339
|
+
MODEL_ID_BYOK_PROVIDERS = [
|
|
1340
|
+
"azure",
|
|
1341
|
+
"bedrock"
|
|
1342
|
+
];
|
|
1343
|
+
__name(isModelIdSentinel, "isModelIdSentinel");
|
|
1344
|
+
__name2(isModelIdSentinel, "isModelIdSentinel");
|
|
1345
|
+
__name(normalizeModelId, "normalizeModelId");
|
|
1346
|
+
__name2(normalizeModelId, "normalizeModelId");
|
|
1347
|
+
__name(modelUnresolvedMessage, "modelUnresolvedMessage");
|
|
1348
|
+
__name2(modelUnresolvedMessage, "modelUnresolvedMessage");
|
|
1261
1349
|
REASONING_EFFORT_VALUES = [
|
|
1262
1350
|
"off",
|
|
1263
1351
|
"minimal",
|
|
@@ -2666,6 +2754,129 @@ function resolveMapping(cfg, ctx) {
|
|
|
2666
2754
|
value: result
|
|
2667
2755
|
};
|
|
2668
2756
|
}
|
|
2757
|
+
function describeApproverSpecRefusal(spec) {
|
|
2758
|
+
const raw = spec === void 0 ? "undefined" : JSON.stringify(spec) ?? String(spec);
|
|
2759
|
+
const written = raw.length > APPROVER_WRITTEN_MAX ? `${raw.slice(0, APPROVER_WRITTEN_MAX - 1)}\u2026` : raw;
|
|
2760
|
+
const users = typeof spec === "object" && spec !== null ? spec.users : void 0;
|
|
2761
|
+
const approver = typeof users === "string" && USER_ID_SHAPED_RE.test(users) ? {
|
|
2762
|
+
users: [
|
|
2763
|
+
users
|
|
2764
|
+
]
|
|
2765
|
+
} : "creator";
|
|
2766
|
+
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)}`);
|
|
2767
|
+
return {
|
|
2768
|
+
approver,
|
|
2769
|
+
written,
|
|
2770
|
+
message
|
|
2771
|
+
};
|
|
2772
|
+
}
|
|
2773
|
+
function bindingRootsOk(template22) {
|
|
2774
|
+
const refs = [
|
|
2775
|
+
...template22.matchAll(/\$\{\s*([A-Za-z_$][\w$]*)/g)
|
|
2776
|
+
].map((m) => m[1]);
|
|
2777
|
+
return refs.length > 0 && refs.every((r) => BINDING_ROOTS.includes(r));
|
|
2778
|
+
}
|
|
2779
|
+
function isTemplateBinding(v) {
|
|
2780
|
+
return typeof v === "object" && v !== null && typeof v.template === "string";
|
|
2781
|
+
}
|
|
2782
|
+
function approvalEditable(node) {
|
|
2783
|
+
if (node.editable === true) return true;
|
|
2784
|
+
if (node.editable === false) return false;
|
|
2785
|
+
return Array.isArray(node.editablePaths) && node.editablePaths.length > 0;
|
|
2786
|
+
}
|
|
2787
|
+
function validateApproverBlock(node, opts = {
|
|
2788
|
+
path: "approval"
|
|
2789
|
+
}) {
|
|
2790
|
+
const issues = [];
|
|
2791
|
+
const push = /* @__PURE__ */ __name3((code, path3, message, severity = "error") => issues.push({
|
|
2792
|
+
code,
|
|
2793
|
+
path: path3,
|
|
2794
|
+
severity,
|
|
2795
|
+
message
|
|
2796
|
+
}), "push");
|
|
2797
|
+
const checkSpec = /* @__PURE__ */ __name3((spec, path3) => {
|
|
2798
|
+
const r = ApproverSpecSchema.safeParse(spec);
|
|
2799
|
+
if (!r.success) {
|
|
2800
|
+
const users = spec?.users;
|
|
2801
|
+
if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path3, `at most ${APPROVER_SPEC_MAX_USERS} users`);
|
|
2802
|
+
else {
|
|
2803
|
+
const refusal = describeApproverSpecRefusal(spec);
|
|
2804
|
+
issues.push({
|
|
2805
|
+
code: "approver-invalid",
|
|
2806
|
+
path: path3,
|
|
2807
|
+
severity: "error",
|
|
2808
|
+
message: refusal.message,
|
|
2809
|
+
repair: {
|
|
2810
|
+
approver: refusal.approver,
|
|
2811
|
+
written: refusal.written
|
|
2812
|
+
}
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
2815
|
+
return;
|
|
2816
|
+
}
|
|
2817
|
+
const s = r.data;
|
|
2818
|
+
if (typeof s === "object") {
|
|
2819
|
+
if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path3, "governance reviewer routing is not enabled for this deployment");
|
|
2820
|
+
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path3, "IdP-group approvers are not enabled for this deployment");
|
|
2821
|
+
const binding = "users" in s ? s.users : "role" in s ? s.role : "group" in s ? s.group : void 0;
|
|
2822
|
+
if (isTemplateBinding(binding)) {
|
|
2823
|
+
if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path3}.template`, "binding root must be initData / stepResults / requestContext / state");
|
|
2824
|
+
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path3}.users`, "a customer-reachable workflow may not bind its approver list");
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
}, "checkSpec");
|
|
2828
|
+
if (node.approver !== void 0) checkSpec(node.approver, `${opts.path}.approver`);
|
|
2829
|
+
if (node.fourEyes !== void 0) {
|
|
2830
|
+
const r = FourEyesSchema.safeParse(node.fourEyes);
|
|
2831
|
+
if (!r.success) push("approver-invalid", `${opts.path}.fourEyes`, "fourEyes needs { edit, approve } approver specs");
|
|
2832
|
+
else {
|
|
2833
|
+
checkSpec(r.data.edit, `${opts.path}.fourEyes.edit`);
|
|
2834
|
+
checkSpec(r.data.approve, `${opts.path}.fourEyes.approve`);
|
|
2835
|
+
}
|
|
2836
|
+
if (!approvalEditable(node)) push("four-eyes-requires-editable", `${opts.path}.fourEyes`, "fourEyes requires editable:true");
|
|
2837
|
+
if (node.approver !== void 0) push("four-eyes-overrides-approver", `${opts.path}.approver`, "fourEyes replaces approver", "warning");
|
|
2838
|
+
if (node.itemsPath) push("four-eyes-items-unsupported", `${opts.path}.fourEyes`, "fourEyes cannot combine with itemsPath");
|
|
2839
|
+
}
|
|
2840
|
+
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");
|
|
2841
|
+
if (Array.isArray(node.onTimeout)) {
|
|
2842
|
+
const chain = node.onTimeout;
|
|
2843
|
+
const hops = chain.filter((m) => typeof m === "object" && m !== null && "escalateTo" in m);
|
|
2844
|
+
if (hops.length > ESCALATION_MAX_HOPS) push("escalation-chain-too-long", `${opts.path}.onTimeout`, `at most ${ESCALATION_MAX_HOPS} hops`);
|
|
2845
|
+
const last = chain[chain.length - 1];
|
|
2846
|
+
if (typeof last === "object" && last !== null) push("escalation-chain-not-terminal", `${opts.path}.onTimeout`, "a chain must end in deny | cancel-run | fail");
|
|
2847
|
+
hops.forEach((h, i) => checkSpec(h.escalateTo, `${opts.path}.onTimeout[${i}].escalateTo`));
|
|
2848
|
+
} else if (typeof node.onTimeout === "object" && node.onTimeout !== null) {
|
|
2849
|
+
checkSpec(node.onTimeout.escalateTo, `${opts.path}.onTimeout.escalateTo`);
|
|
2850
|
+
}
|
|
2851
|
+
return issues;
|
|
2852
|
+
}
|
|
2853
|
+
function liftRenderedApprover(row, rendered) {
|
|
2854
|
+
const text = (rendered ?? "").trim();
|
|
2855
|
+
if (!text) return null;
|
|
2856
|
+
if (row === "users") {
|
|
2857
|
+
let members = null;
|
|
2858
|
+
if (text.startsWith("[")) {
|
|
2859
|
+
try {
|
|
2860
|
+
members = JSON.parse(text);
|
|
2861
|
+
} catch {
|
|
2862
|
+
return null;
|
|
2863
|
+
}
|
|
2864
|
+
} else members = text.split(",").map((s) => s.trim());
|
|
2865
|
+
if (!Array.isArray(members) || members.length === 0 || members.length > APPROVER_SPEC_MAX_USERS) return null;
|
|
2866
|
+
if (!members.every((m) => typeof m === "string" && m.length > 0 && m.length <= 128)) return null;
|
|
2867
|
+
return {
|
|
2868
|
+
users: [
|
|
2869
|
+
...new Set(members)
|
|
2870
|
+
].sort()
|
|
2871
|
+
};
|
|
2872
|
+
}
|
|
2873
|
+
if (text.length > 128 || text.startsWith("[") || text.startsWith("{")) return null;
|
|
2874
|
+
return row === "role" ? {
|
|
2875
|
+
role: text
|
|
2876
|
+
} : {
|
|
2877
|
+
group: text
|
|
2878
|
+
};
|
|
2879
|
+
}
|
|
2669
2880
|
function workspaceTemplatePath(template22) {
|
|
2670
2881
|
const key = template22.trim();
|
|
2671
2882
|
const expr = WORKSPACE_TEMPLATE_EXPR_RE.exec(key);
|
|
@@ -2682,6 +2893,9 @@ function retryBackoffs() {
|
|
|
2682
2893
|
function sleepUntilUnsupportedMessage(id) {
|
|
2683
2894
|
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} }`;
|
|
2684
2895
|
}
|
|
2896
|
+
function armSubrunUnsupportedMessage(id, workflowId) {
|
|
2897
|
+
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)`;
|
|
2898
|
+
}
|
|
2685
2899
|
function fillPolicy(node, defaultTimeout) {
|
|
2686
2900
|
if (node.tier === void 0 && node.workspace !== void 0 && node.workspace !== "inherit") node.tier = "job";
|
|
2687
2901
|
if (node.timeoutSeconds === void 0) node.timeoutSeconds = node.tier === "job" ? WORKFLOW_JOB_DEFAULT_TIMEOUT_SECONDS : defaultTimeout;
|
|
@@ -2707,7 +2921,6 @@ function fillSingle(node) {
|
|
|
2707
2921
|
fillPolicy(node, WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS);
|
|
2708
2922
|
return;
|
|
2709
2923
|
case "workflow":
|
|
2710
|
-
if (node.workflowId === WORKFLOW_ARM_SUBRUN_ID && Array.isArray(node.graph) && node.graph[1]) fillSingle(node.graph[1]);
|
|
2711
2924
|
return;
|
|
2712
2925
|
}
|
|
2713
2926
|
}
|
|
@@ -2839,8 +3052,14 @@ function nodeStepRefs(entry) {
|
|
|
2839
3052
|
case "agent": {
|
|
2840
3053
|
const a = entry;
|
|
2841
3054
|
const p = a.promptTemplate;
|
|
2842
|
-
|
|
3055
|
+
const prompt = typeof p === "string" ? templateStepRefs(p) : p && "template" in p ? templateStepRefs(p.template) : [];
|
|
3056
|
+
return [
|
|
3057
|
+
...prompt,
|
|
3058
|
+
...mapConfigStepRefs(a.input)
|
|
3059
|
+
];
|
|
2843
3060
|
}
|
|
3061
|
+
case "step":
|
|
3062
|
+
return mapConfigStepRefs(entry.input);
|
|
2844
3063
|
case "tool":
|
|
2845
3064
|
return mapConfigStepRefs(entry.input);
|
|
2846
3065
|
case "workflow":
|
|
@@ -3057,6 +3276,21 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3057
3276
|
err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path3}.model`, id);
|
|
3058
3277
|
}
|
|
3059
3278
|
}, "checkTier");
|
|
3279
|
+
const checkModel = /* @__PURE__ */ __name3((node, path3) => {
|
|
3280
|
+
if (node.type !== "agent" || typeof node.model !== "string") return;
|
|
3281
|
+
const registry = opts.approvedModels;
|
|
3282
|
+
if (registry === void 0) return;
|
|
3283
|
+
const id = singleId(node);
|
|
3284
|
+
if (registry === "unavailable") {
|
|
3285
|
+
const pin = node.model.trim();
|
|
3286
|
+
if (pin && !normalizeModelId(pin, []).ok) {
|
|
3287
|
+
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)`, `${path3}.model`, id);
|
|
3288
|
+
}
|
|
3289
|
+
return;
|
|
3290
|
+
}
|
|
3291
|
+
const resolved = normalizeModelId(node.model, registry);
|
|
3292
|
+
if (!resolved.ok) err("model-unresolved", modelUnresolvedMessage(resolved), `${path3}.model`, id);
|
|
3293
|
+
}, "checkModel");
|
|
3060
3294
|
const checkWorkspace = /* @__PURE__ */ __name3((node, path3) => {
|
|
3061
3295
|
const id = singleId(node);
|
|
3062
3296
|
const ws = workspaceOf(node);
|
|
@@ -3109,38 +3343,29 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3109
3343
|
}
|
|
3110
3344
|
}, "checkMapMembers");
|
|
3111
3345
|
const checkInputShape = /* @__PURE__ */ __name3((node, path3) => {
|
|
3112
|
-
if (node.type !== "tool" && node.type !== "workflow") return;
|
|
3113
3346
|
const input = node.input;
|
|
3114
3347
|
if (input === void 0) return;
|
|
3348
|
+
const id = singleId(node);
|
|
3115
3349
|
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
3116
|
-
checkMapMembers(input, `${path3}.input`,
|
|
3350
|
+
checkMapMembers(input, `${path3}.input`, id);
|
|
3117
3351
|
return;
|
|
3118
3352
|
}
|
|
3119
|
-
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)})`, `${path3}.input`,
|
|
3353
|
+
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)})`, `${path3}.input`, id);
|
|
3120
3354
|
}, "checkInputShape");
|
|
3355
|
+
const checkBodyInput = /* @__PURE__ */ __name3((body, path3, container) => {
|
|
3356
|
+
if (body.type === "workflow" || body.input === void 0) return;
|
|
3357
|
+
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`, `${path3}.input`, singleId(body));
|
|
3358
|
+
}, "checkBodyInput");
|
|
3121
3359
|
const checkSingle = /* @__PURE__ */ __name3((node, path3, depth) => {
|
|
3122
3360
|
recordOutputSchema(node);
|
|
3123
|
-
if (node.type === "workflow" && node.workflowId ===
|
|
3361
|
+
if (node.type === "workflow" && (typeof node.workflowId !== "string" || node.workflowId.length === 0)) {
|
|
3124
3362
|
checkId(node.id, path3);
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
err("container-arm-empty", "a bare mapping arm has nothing to run", `${path3}.graph.1`, node.id);
|
|
3132
|
-
return;
|
|
3133
|
-
}
|
|
3134
|
-
const inner = body[1];
|
|
3135
|
-
if (isHitlNode(inner)) {
|
|
3136
|
-
err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(inner.type, inner.id, "mapped-arm"), `${path3}.graph.1`, inner.id);
|
|
3137
|
-
return;
|
|
3138
|
-
}
|
|
3139
|
-
upstream.add(singleId(body[1]));
|
|
3140
|
-
checkArm(body[0], `${path3}.graph.0`, depth, "parallel");
|
|
3141
|
-
checkSingle(body[1], `${path3}.graph.1`, depth);
|
|
3142
|
-
upstream.add(body[0].id);
|
|
3143
|
-
upstream.add(singleId(body[1]));
|
|
3363
|
+
err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${path3}.workflowId`, node.id);
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3366
|
+
if (node.type === "workflow" && (node.workflowId.startsWith("$") || Array.isArray(node.graph))) {
|
|
3367
|
+
checkId(node.id, path3);
|
|
3368
|
+
err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId), path3, node.id);
|
|
3144
3369
|
return;
|
|
3145
3370
|
}
|
|
3146
3371
|
checkId(singleId(node), path3);
|
|
@@ -3148,6 +3373,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3148
3373
|
checkInputShape(node, path3);
|
|
3149
3374
|
checkTimeout(node, path3);
|
|
3150
3375
|
checkTier(node, path3);
|
|
3376
|
+
checkModel(node, path3);
|
|
3151
3377
|
checkRetry(node, path3);
|
|
3152
3378
|
checkWorkspace(node, path3);
|
|
3153
3379
|
if (!opts.static) {
|
|
@@ -3170,7 +3396,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3170
3396
|
if (node.type === "workflow" && node.kind === "subrun" && depth > caps.maxNestingDepth) {
|
|
3171
3397
|
err("cap-exceeded", `nesting depth ${depth} exceeds ${caps.maxNestingDepth}`, path3, node.id);
|
|
3172
3398
|
}
|
|
3173
|
-
if (node.type === "workflow" &&
|
|
3399
|
+
if (node.type === "workflow" && typeof g.definition?.id === "string" && node.workflowId === g.definition.id) {
|
|
3174
3400
|
err("subrun-cycle", `"${node.id}" starts "${node.workflowId}", which is this workflow itself`, path3, node.id);
|
|
3175
3401
|
}
|
|
3176
3402
|
for (const ref of nodeStepRefs(node)) {
|
|
@@ -3191,11 +3417,14 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3191
3417
|
if (a.approver === "creator" && a.excludeInitiator === true) {
|
|
3192
3418
|
err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path3, a.id);
|
|
3193
3419
|
}
|
|
3194
|
-
|
|
3420
|
+
const editable = approvalEditable(a);
|
|
3421
|
+
if (a.fourEyes !== void 0 && !editable) {
|
|
3195
3422
|
err("four-eyes-requires-editable", "`fourEyes` requires editable:true", `${path3}.fourEyes`, a.id);
|
|
3196
3423
|
}
|
|
3197
|
-
if (
|
|
3198
|
-
err("editable-path-invalid", "`editablePaths`
|
|
3424
|
+
if (a.editable === false && Array.isArray(a.editablePaths) && a.editablePaths.length > 0) {
|
|
3425
|
+
err("editable-path-invalid", "`editablePaths` beside editable:false is contradictory \u2014 drop the paths or set editable:true", `${path3}.editablePaths`, a.id);
|
|
3426
|
+
} else if ((a.editablePaths !== void 0 || a.editedPayloadSchema !== void 0) && !editable) {
|
|
3427
|
+
err("editable-path-invalid", "`editablePaths` / `editedPayloadSchema` require editable:true (a non-empty editablePaths implies it)", `${path3}.editablePaths`, a.id);
|
|
3199
3428
|
}
|
|
3200
3429
|
for (const p of a.editablePaths ?? []) {
|
|
3201
3430
|
if (!EDITABLE_PATH_RE.test(p)) err("editable-path-invalid", `editablePaths entry "${p}" is outside the seg(.seg)*[*]/[n] grammar`, `${path3}.editablePaths`, a.id);
|
|
@@ -3376,6 +3605,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3376
3605
|
} else checkHitlArm(f.step, `${path3}.step`, "foreach");
|
|
3377
3606
|
declared.push(f.step.id);
|
|
3378
3607
|
} else {
|
|
3608
|
+
checkBodyInput(f.step, `${path3}.step`, "foreach");
|
|
3379
3609
|
checkSingle(f.step, `${path3}.step`, o.chunk ? 2 : 1);
|
|
3380
3610
|
declared.push(singleId(f.step));
|
|
3381
3611
|
}
|
|
@@ -3396,6 +3626,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
3396
3626
|
checkHitlArm(l.step, `${path3}.step`, "loop");
|
|
3397
3627
|
declared.push(l.step.id);
|
|
3398
3628
|
} else {
|
|
3629
|
+
checkBodyInput(l.step, `${path3}.step`, "loop");
|
|
3399
3630
|
checkSingle(l.step, `${path3}.step`, 1);
|
|
3400
3631
|
declared.push(singleId(l.step));
|
|
3401
3632
|
}
|
|
@@ -3869,17 +4100,10 @@ function isContinuedFailureValue(v) {
|
|
|
3869
4100
|
const err = o.error;
|
|
3870
4101
|
return o.__lua_workflow === CONTINUED_FAILURE_TAG && o.failed === true && o.text === "" && err !== null && typeof err === "object" && typeof err.code === "string" && typeof err.message === "string";
|
|
3871
4102
|
}
|
|
3872
|
-
function
|
|
3873
|
-
const stepId = nodeIdOf(step22);
|
|
4103
|
+
function inlineContainerArm(mapping, step22) {
|
|
3874
4104
|
return {
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
workflowId: WORKFLOW_ARM_SUBRUN_ID,
|
|
3878
|
-
kind: "subrun",
|
|
3879
|
-
graph: [
|
|
3880
|
-
mapping,
|
|
3881
|
-
step22
|
|
3882
|
-
]
|
|
4105
|
+
...step22,
|
|
4106
|
+
input: parseMapConfig(mapping.mapConfig, mapping.id)
|
|
3883
4107
|
};
|
|
3884
4108
|
}
|
|
3885
4109
|
function entryIds(entry) {
|
|
@@ -3949,6 +4173,27 @@ function resolvePlacements(calls) {
|
|
|
3949
4173
|
break;
|
|
3950
4174
|
}
|
|
3951
4175
|
});
|
|
4176
|
+
const armMapPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
|
|
4177
|
+
if (!ref.armMap || node.type === "mapping" || isHitlNode2(node)) return void 0;
|
|
4178
|
+
const id = nodeIdOf(node);
|
|
4179
|
+
if ((container === "foreach" || container === "loop") && node.type !== "workflow") {
|
|
4180
|
+
return {
|
|
4181
|
+
code: "mapping-placement",
|
|
4182
|
+
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`,
|
|
4183
|
+
callIndex: i,
|
|
4184
|
+
stepId: id
|
|
4185
|
+
};
|
|
4186
|
+
}
|
|
4187
|
+
if (node.input !== void 0) {
|
|
4188
|
+
return {
|
|
4189
|
+
code: "mapping-placement",
|
|
4190
|
+
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)`,
|
|
4191
|
+
callIndex: i,
|
|
4192
|
+
stepId: id
|
|
4193
|
+
};
|
|
4194
|
+
}
|
|
4195
|
+
return void 0;
|
|
4196
|
+
}, "armMapPlacementIssue");
|
|
3952
4197
|
const hitlPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
|
|
3953
4198
|
if (!isHitlNode2(node)) return void 0;
|
|
3954
4199
|
const id = node.id;
|
|
@@ -3975,7 +4220,7 @@ function resolvePlacements(calls) {
|
|
|
3975
4220
|
if (ref.node.type === "mapping" && !allowMapping) {
|
|
3976
4221
|
issues.push({
|
|
3977
4222
|
code: "mapping-placement",
|
|
3978
|
-
message: `mapping "${ref.node.id}" cannot be a container arm \u2014 chain it as [map, step]`,
|
|
4223
|
+
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`,
|
|
3979
4224
|
callIndex: i,
|
|
3980
4225
|
stepId: ref.node.id
|
|
3981
4226
|
});
|
|
@@ -3996,7 +4241,7 @@ function resolvePlacements(calls) {
|
|
|
3996
4241
|
if (d.node.type === "mapping" && !allowMapping) {
|
|
3997
4242
|
issues.push({
|
|
3998
4243
|
code: "mapping-placement",
|
|
3999
|
-
message: `map "${ref.ref}" cannot be a parallel/foreach/loop arm \u2014 chain it as [map, step]`,
|
|
4244
|
+
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`,
|
|
4000
4245
|
callIndex: i,
|
|
4001
4246
|
stepId: ref.ref
|
|
4002
4247
|
});
|
|
@@ -4007,6 +4252,11 @@ function resolvePlacements(calls) {
|
|
|
4007
4252
|
issues.push(hitl);
|
|
4008
4253
|
return void 0;
|
|
4009
4254
|
}
|
|
4255
|
+
const mapped = armMapPlacementIssue(d.node, ref, i, container);
|
|
4256
|
+
if (mapped) {
|
|
4257
|
+
issues.push(mapped);
|
|
4258
|
+
return void 0;
|
|
4259
|
+
}
|
|
4010
4260
|
const prior = placedBy.get(ref.ref);
|
|
4011
4261
|
if (prior !== void 0 && prior !== i) {
|
|
4012
4262
|
issues.push({
|
|
@@ -4027,6 +4277,10 @@ function resolvePlacements(calls) {
|
|
|
4027
4277
|
}
|
|
4028
4278
|
const hitl = hitlPlacementIssue(ref.node, ref, i, container);
|
|
4029
4279
|
if (hitl) issues.push(hitl);
|
|
4280
|
+
else {
|
|
4281
|
+
const mapped = armMapPlacementIssue(ref.node, ref, i, container);
|
|
4282
|
+
if (mapped) issues.push(mapped);
|
|
4283
|
+
}
|
|
4030
4284
|
}, "claim");
|
|
4031
4285
|
calls.forEach((call, i) => {
|
|
4032
4286
|
switch (call.kind) {
|
|
@@ -4054,7 +4308,7 @@ function resolvePlacements(calls) {
|
|
|
4054
4308
|
const lookup = /* @__PURE__ */ __name3((ref) => {
|
|
4055
4309
|
const n2 = "node" in ref ? ref.node : declared.get(ref.ref)?.node;
|
|
4056
4310
|
if (!n2 || !ref.armMap || n2.type === "mapping" || isHitlNode2(n2)) return n2;
|
|
4057
|
-
return
|
|
4311
|
+
return inlineContainerArm(ref.armMap, n2);
|
|
4058
4312
|
}, "lookup");
|
|
4059
4313
|
calls.forEach((call, i) => {
|
|
4060
4314
|
switch (call.kind) {
|
|
@@ -4439,6 +4693,27 @@ function isTerminalRunStatus(status) {
|
|
|
4439
4693
|
function pruneUndefined(o) {
|
|
4440
4694
|
return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
4441
4695
|
}
|
|
4696
|
+
function runOrigin(run) {
|
|
4697
|
+
if (run.goalId) return "goal";
|
|
4698
|
+
if (run.jobId || run.trigger === "schedule") return "schedule";
|
|
4699
|
+
if (run.dynamic === true) return run.tags?.includes(WORKFLOW_INLINE_RUN_TAG) ? "inline" : "compose";
|
|
4700
|
+
return "definition";
|
|
4701
|
+
}
|
|
4702
|
+
function runErrorIssues(issues) {
|
|
4703
|
+
if (!Array.isArray(issues)) return void 0;
|
|
4704
|
+
const out = [];
|
|
4705
|
+
for (const raw of issues.slice(0, RUN_ERROR_ISSUES_MAX)) {
|
|
4706
|
+
if (!raw || typeof raw !== "object") continue;
|
|
4707
|
+
const o = raw;
|
|
4708
|
+
if (typeof o.code !== "string" || !o.code) continue;
|
|
4709
|
+
out.push(pruneUndefined({
|
|
4710
|
+
code: o.code,
|
|
4711
|
+
path: typeof o.path === "string" ? o.path : void 0,
|
|
4712
|
+
message: typeof o.message === "string" ? o.message : void 0
|
|
4713
|
+
}));
|
|
4714
|
+
}
|
|
4715
|
+
return out.length ? out : void 0;
|
|
4716
|
+
}
|
|
4442
4717
|
function runNextAction(run) {
|
|
4443
4718
|
if (isTerminalRunStatus(run.status)) return "none";
|
|
4444
4719
|
if (run.status === "suspended" && run.gate?.kind === "budget") return "raise_budget";
|
|
@@ -4608,6 +4883,7 @@ function toWorkflowRunSummary(run) {
|
|
|
4608
4883
|
repairOf: run.repairOf,
|
|
4609
4884
|
repairRunIds: run.repairRunIds,
|
|
4610
4885
|
trigger: run.trigger ?? "api",
|
|
4886
|
+
origin: runOrigin(run),
|
|
4611
4887
|
createdBy: {
|
|
4612
4888
|
subjectType: principal?.subjectType ?? "system",
|
|
4613
4889
|
subjectId: principal?.subjectId ?? run.userId ?? ""
|
|
@@ -4625,11 +4901,13 @@ function toWorkflowRunSummary(run) {
|
|
|
4625
4901
|
usage: runUsage(run),
|
|
4626
4902
|
// LUA-697: a row persisted before the write seams (#2406 / #2465 / the script tier) leaves scrubbed here too —
|
|
4627
4903
|
// idempotent on a scrubbed message, bounded input; an empty message falls back to the code.
|
|
4628
|
-
error: run.error ? {
|
|
4904
|
+
error: run.error ? pruneUndefined({
|
|
4629
4905
|
code: run.error.code ?? "error",
|
|
4630
4906
|
message: scrubStepErrorMessage(run.error.message) ?? run.error.code ?? "error",
|
|
4631
|
-
stepId: run.error.stepId
|
|
4632
|
-
|
|
4907
|
+
stepId: run.error.stepId,
|
|
4908
|
+
// LUA-784 (item 3): the unattended pre-start failure's refusal rows (`input_schema_invalid` and kin).
|
|
4909
|
+
issues: runErrorIssues(run.error.issues)
|
|
4910
|
+
}) : void 0,
|
|
4633
4911
|
kind: "run",
|
|
4634
4912
|
aclHash: run.aclHash,
|
|
4635
4913
|
migration: run.migration,
|
|
@@ -5110,166 +5388,48 @@ function applyJsonPatch(doc, ops) {
|
|
|
5110
5388
|
code: "PATH_NOT_FOUND",
|
|
5111
5389
|
index: i,
|
|
5112
5390
|
path: op.path,
|
|
5113
|
-
message: "index out of range"
|
|
5114
|
-
};
|
|
5115
|
-
} else if (op.op === "replace") parent[last] = structuredClone(op.value);
|
|
5116
|
-
else parent.splice(last, 1);
|
|
5117
|
-
continue;
|
|
5118
|
-
}
|
|
5119
|
-
if (typeof parent !== "object" || parent === null || typeof last !== "string" && typeof last !== "number") return {
|
|
5120
|
-
ok: false,
|
|
5121
|
-
code: "PATH_NOT_FOUND",
|
|
5122
|
-
index: i,
|
|
5123
|
-
path: op.path,
|
|
5124
|
-
message: "path not found"
|
|
5125
|
-
};
|
|
5126
|
-
const obj = parent;
|
|
5127
|
-
const key = String(last);
|
|
5128
|
-
if (key === "__proto__" || key === "constructor" || key === "prototype") return {
|
|
5129
|
-
ok: false,
|
|
5130
|
-
code: "PATCH_INVALID",
|
|
5131
|
-
index: i,
|
|
5132
|
-
path: op.path,
|
|
5133
|
-
message: "path not allowed"
|
|
5134
|
-
};
|
|
5135
|
-
if (op.op === "add") obj[key] = structuredClone(op.value);
|
|
5136
|
-
else if (!(key in obj)) return {
|
|
5137
|
-
ok: false,
|
|
5138
|
-
code: "PATH_NOT_FOUND",
|
|
5139
|
-
index: i,
|
|
5140
|
-
path: op.path,
|
|
5141
|
-
message: "path not found"
|
|
5142
|
-
};
|
|
5143
|
-
else if (op.op === "replace") obj[key] = structuredClone(op.value);
|
|
5144
|
-
else delete obj[key];
|
|
5145
|
-
}
|
|
5146
|
-
return {
|
|
5147
|
-
ok: true,
|
|
5148
|
-
value: value22
|
|
5149
|
-
};
|
|
5150
|
-
}
|
|
5151
|
-
function rebaseItemPointer(pointer, itemsPath, index) {
|
|
5152
|
-
const base = `/${itemsPath.split(".").map(escapePointer).join("/")}/${index}`;
|
|
5153
|
-
return pointer === "/" || pointer === "" ? base : `${base}${pointer}`;
|
|
5154
|
-
}
|
|
5155
|
-
function describeApproverSpecRefusal(spec) {
|
|
5156
|
-
const raw = spec === void 0 ? "undefined" : JSON.stringify(spec) ?? String(spec);
|
|
5157
|
-
const written = raw.length > APPROVER_WRITTEN_MAX ? `${raw.slice(0, APPROVER_WRITTEN_MAX - 1)}\u2026` : raw;
|
|
5158
|
-
const users = typeof spec === "object" && spec !== null ? spec.users : void 0;
|
|
5159
|
-
const approver = typeof users === "string" && USER_ID_SHAPED_RE.test(users) ? {
|
|
5160
|
-
users: [
|
|
5161
|
-
users
|
|
5162
|
-
]
|
|
5163
|
-
} : "creator";
|
|
5164
|
-
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)}`);
|
|
5165
|
-
return {
|
|
5166
|
-
approver,
|
|
5167
|
-
written,
|
|
5168
|
-
message
|
|
5169
|
-
};
|
|
5170
|
-
}
|
|
5171
|
-
function bindingRootsOk(template22) {
|
|
5172
|
-
const refs = [
|
|
5173
|
-
...template22.matchAll(/\$\{\s*([A-Za-z_$][\w$]*)/g)
|
|
5174
|
-
].map((m) => m[1]);
|
|
5175
|
-
return refs.length > 0 && refs.every((r) => BINDING_ROOTS.includes(r));
|
|
5176
|
-
}
|
|
5177
|
-
function isTemplateBinding(v) {
|
|
5178
|
-
return typeof v === "object" && v !== null && typeof v.template === "string";
|
|
5179
|
-
}
|
|
5180
|
-
function validateApproverBlock(node, opts = {
|
|
5181
|
-
path: "approval"
|
|
5182
|
-
}) {
|
|
5183
|
-
const issues = [];
|
|
5184
|
-
const push = /* @__PURE__ */ __name3((code, path3, message, severity = "error") => issues.push({
|
|
5185
|
-
code,
|
|
5186
|
-
path: path3,
|
|
5187
|
-
severity,
|
|
5188
|
-
message
|
|
5189
|
-
}), "push");
|
|
5190
|
-
const checkSpec = /* @__PURE__ */ __name3((spec, path3) => {
|
|
5191
|
-
const r = ApproverSpecSchema.safeParse(spec);
|
|
5192
|
-
if (!r.success) {
|
|
5193
|
-
const users = spec?.users;
|
|
5194
|
-
if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path3, `at most ${APPROVER_SPEC_MAX_USERS} users`);
|
|
5195
|
-
else {
|
|
5196
|
-
const refusal = describeApproverSpecRefusal(spec);
|
|
5197
|
-
issues.push({
|
|
5198
|
-
code: "approver-invalid",
|
|
5199
|
-
path: path3,
|
|
5200
|
-
severity: "error",
|
|
5201
|
-
message: refusal.message,
|
|
5202
|
-
repair: {
|
|
5203
|
-
approver: refusal.approver,
|
|
5204
|
-
written: refusal.written
|
|
5205
|
-
}
|
|
5206
|
-
});
|
|
5207
|
-
}
|
|
5208
|
-
return;
|
|
5209
|
-
}
|
|
5210
|
-
const s = r.data;
|
|
5211
|
-
if (typeof s === "object") {
|
|
5212
|
-
if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path3, "governance reviewer routing is not enabled for this deployment");
|
|
5213
|
-
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path3, "IdP-group approvers are not enabled for this deployment");
|
|
5214
|
-
const binding = "users" in s ? s.users : "role" in s ? s.role : "group" in s ? s.group : void 0;
|
|
5215
|
-
if (isTemplateBinding(binding)) {
|
|
5216
|
-
if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path3}.template`, "binding root must be initData / stepResults / requestContext / state");
|
|
5217
|
-
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path3}.users`, "a customer-reachable workflow may not bind its approver list");
|
|
5218
|
-
}
|
|
5219
|
-
}
|
|
5220
|
-
}, "checkSpec");
|
|
5221
|
-
if (node.approver !== void 0) checkSpec(node.approver, `${opts.path}.approver`);
|
|
5222
|
-
if (node.fourEyes !== void 0) {
|
|
5223
|
-
const r = FourEyesSchema.safeParse(node.fourEyes);
|
|
5224
|
-
if (!r.success) push("approver-invalid", `${opts.path}.fourEyes`, "fourEyes needs { edit, approve } approver specs");
|
|
5225
|
-
else {
|
|
5226
|
-
checkSpec(r.data.edit, `${opts.path}.fourEyes.edit`);
|
|
5227
|
-
checkSpec(r.data.approve, `${opts.path}.fourEyes.approve`);
|
|
5228
|
-
}
|
|
5229
|
-
if (!node.editable) push("four-eyes-requires-editable", `${opts.path}.fourEyes`, "fourEyes requires editable:true");
|
|
5230
|
-
if (node.approver !== void 0) push("four-eyes-overrides-approver", `${opts.path}.approver`, "fourEyes replaces approver", "warning");
|
|
5231
|
-
if (node.itemsPath) push("four-eyes-items-unsupported", `${opts.path}.fourEyes`, "fourEyes cannot combine with itemsPath");
|
|
5232
|
-
}
|
|
5233
|
-
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");
|
|
5234
|
-
if (Array.isArray(node.onTimeout)) {
|
|
5235
|
-
const chain = node.onTimeout;
|
|
5236
|
-
const hops = chain.filter((m) => typeof m === "object" && m !== null && "escalateTo" in m);
|
|
5237
|
-
if (hops.length > ESCALATION_MAX_HOPS) push("escalation-chain-too-long", `${opts.path}.onTimeout`, `at most ${ESCALATION_MAX_HOPS} hops`);
|
|
5238
|
-
const last = chain[chain.length - 1];
|
|
5239
|
-
if (typeof last === "object" && last !== null) push("escalation-chain-not-terminal", `${opts.path}.onTimeout`, "a chain must end in deny | cancel-run | fail");
|
|
5240
|
-
hops.forEach((h, i) => checkSpec(h.escalateTo, `${opts.path}.onTimeout[${i}].escalateTo`));
|
|
5241
|
-
} else if (typeof node.onTimeout === "object" && node.onTimeout !== null) {
|
|
5242
|
-
checkSpec(node.onTimeout.escalateTo, `${opts.path}.onTimeout.escalateTo`);
|
|
5243
|
-
}
|
|
5244
|
-
return issues;
|
|
5245
|
-
}
|
|
5246
|
-
function liftRenderedApprover(row, rendered) {
|
|
5247
|
-
const text = (rendered ?? "").trim();
|
|
5248
|
-
if (!text) return null;
|
|
5249
|
-
if (row === "users") {
|
|
5250
|
-
let members = null;
|
|
5251
|
-
if (text.startsWith("[")) {
|
|
5252
|
-
try {
|
|
5253
|
-
members = JSON.parse(text);
|
|
5254
|
-
} catch {
|
|
5255
|
-
return null;
|
|
5256
|
-
}
|
|
5257
|
-
} else members = text.split(",").map((s) => s.trim());
|
|
5258
|
-
if (!Array.isArray(members) || members.length === 0 || members.length > APPROVER_SPEC_MAX_USERS) return null;
|
|
5259
|
-
if (!members.every((m) => typeof m === "string" && m.length > 0 && m.length <= 128)) return null;
|
|
5260
|
-
return {
|
|
5261
|
-
users: [
|
|
5262
|
-
...new Set(members)
|
|
5263
|
-
].sort()
|
|
5391
|
+
message: "index out of range"
|
|
5392
|
+
};
|
|
5393
|
+
} else if (op.op === "replace") parent[last] = structuredClone(op.value);
|
|
5394
|
+
else parent.splice(last, 1);
|
|
5395
|
+
continue;
|
|
5396
|
+
}
|
|
5397
|
+
if (typeof parent !== "object" || parent === null || typeof last !== "string" && typeof last !== "number") return {
|
|
5398
|
+
ok: false,
|
|
5399
|
+
code: "PATH_NOT_FOUND",
|
|
5400
|
+
index: i,
|
|
5401
|
+
path: op.path,
|
|
5402
|
+
message: "path not found"
|
|
5403
|
+
};
|
|
5404
|
+
const obj = parent;
|
|
5405
|
+
const key = String(last);
|
|
5406
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") return {
|
|
5407
|
+
ok: false,
|
|
5408
|
+
code: "PATCH_INVALID",
|
|
5409
|
+
index: i,
|
|
5410
|
+
path: op.path,
|
|
5411
|
+
message: "path not allowed"
|
|
5412
|
+
};
|
|
5413
|
+
if (op.op === "add") obj[key] = structuredClone(op.value);
|
|
5414
|
+
else if (!(key in obj)) return {
|
|
5415
|
+
ok: false,
|
|
5416
|
+
code: "PATH_NOT_FOUND",
|
|
5417
|
+
index: i,
|
|
5418
|
+
path: op.path,
|
|
5419
|
+
message: "path not found"
|
|
5264
5420
|
};
|
|
5421
|
+
else if (op.op === "replace") obj[key] = structuredClone(op.value);
|
|
5422
|
+
else delete obj[key];
|
|
5265
5423
|
}
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
} : {
|
|
5270
|
-
group: text
|
|
5424
|
+
return {
|
|
5425
|
+
ok: true,
|
|
5426
|
+
value: value22
|
|
5271
5427
|
};
|
|
5272
5428
|
}
|
|
5429
|
+
function rebaseItemPointer(pointer, itemsPath, index) {
|
|
5430
|
+
const base = `/${itemsPath.split(".").map(escapePointer).join("/")}/${index}`;
|
|
5431
|
+
return pointer === "/" || pointer === "" ? base : `${base}${pointer}`;
|
|
5432
|
+
}
|
|
5273
5433
|
function collectEnvTemplateKeys(value22) {
|
|
5274
5434
|
const keys = /* @__PURE__ */ new Set();
|
|
5275
5435
|
const walk22 = /* @__PURE__ */ __name3((v) => {
|
|
@@ -5518,7 +5678,6 @@ function* singleStepsOf(entry) {
|
|
|
5518
5678
|
return;
|
|
5519
5679
|
case "workflow":
|
|
5520
5680
|
yield entry;
|
|
5521
|
-
if (Array.isArray(entry.graph)) yield* singleStepsOf(entry.graph[1]);
|
|
5522
5681
|
return;
|
|
5523
5682
|
case "parallel":
|
|
5524
5683
|
case "conditional":
|
|
@@ -5560,7 +5719,7 @@ function needsInheritedWorkspace(graph) {
|
|
|
5560
5719
|
}
|
|
5561
5720
|
return false;
|
|
5562
5721
|
}
|
|
5563
|
-
var __defProp3, __name3, WorkflowTemplateError, TEMPLATE_PLACEHOLDER, TEMPLATE_NAMESPACES, MAP_DESCRIPTOR_KEYS, MAP_MEMBER_MALFORMED_CODE, fromInit, fromStep, value, template, fromRequest, rows, fromKnowledge, SideEffectsSchema, JobResourcesSchema,
|
|
5722
|
+
var __defProp3, __name3, WorkflowTemplateError, TEMPLATE_PLACEHOLDER, TEMPLATE_NAMESPACES, MAP_DESCRIPTOR_KEYS, MAP_MEMBER_MALFORMED_CODE, fromInit, fromStep, value, template, fromRequest, rows, fromKnowledge, SideEffectsSchema, JobResourcesSchema, APPROVER_SPEC_MAX_USERS, ESCALATION_MAX_HOPS, TemplateBindingSchema, ApproverSpecSchema, FourEyesSchema, EscalationHopSchema, TerminalOutcomeSchema, ApprovalOnTimeoutSchema, APPROVER_SPEC_SHAPES, APPROVER_WRITTEN_MAX, USER_ID_SHAPED_RE, BINDING_ROOTS, WORKSPACE_TEMPLATE_EXPR_RE, SLEEP_UNTIL_REPLACEMENT, WORKFLOW_CAPS_DEFAULT, WORKFLOW_STEP_DEFAULT_TIMEOUT_SECONDS, WORKFLOW_AGENT_DEFAULT_TIMEOUT_SECONDS, WORKFLOW_JOB_DEFAULT_TIMEOUT_SECONDS, WORKFLOW_FOREACH_DEFAULT_CONCURRENCY, WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS, WORKFLOW_LOOP_DEFAULT_MAX_ITERATIONS, WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS, WORKFLOW_SIGNAL_DEFAULT_SOURCES, clone, CONNECTION_ID_HEX_RE, WORKFLOW_JOB_TOOLS, WORKFLOW_JOB_MAX_WORKTREE_ARMS, workspaceOf, mountsWorkspace, isJobTier, jobToolsOf, schemaIsArray, isHitlNode, isSingleStep, singleId, armId, TEMPLATE_STEP_REF, EDITABLE_PATH_RE, PREDICATE_OPS, isPredicateScalar, GRAPH_HASH_PREFIX, WorkflowPlanError, isArmStep, armStepId, armStepKind, joinIdOf, containerIdOf, PATH_PLACEHOLDER, MISSING, stepIdOf, cmp, eq, ne, gt, gte, lt, lte, inSet, notIn, exists, notExists, truthy, falsy, and, or, not, CONTINUED_FAILURE_TAG, CONTINUED_FAILURE_DEFAULT_CODE, CONTINUED_FAILURE_OUTPUT_SCHEMA, CONTINUED_FAILURE_LEAF_PATHS, isHitlNode2, nodeIdOf, GOAL_JUDGE_STEP_ID, NON_LEAF_KINDS, CONDITIONAL_JOIN_ID, branchArmId, canonical, sortKeys, JOIN, entryOfJoin, FORCE_CANCEL_STALE_MS, TERMINAL, WORKFLOW_INLINE_RUN_TAG, RUN_ERROR_ISSUES_MAX, IN_FLIGHT, n, STEP_ERROR_DETAIL_KEYS, STEP_ERROR_DETAIL_MAX_BYTES, DETAIL_MAX_DEPTH, DETAIL_MAX_ITEMS, MAX_HOLIDAYS, MAX_WALK_DAYS, HHMM, YMD, MS_PER_MIN, MS_PER_DAY, MON_FRI, supportedTz, fmtCache, WEEKDAYS, JSON_PATCH_OPS, JSON_PATCH_MAX_OPS, JSON_PATCH_MAX_VALUE_BYTES, JSON_PATCH_MAX_TOTAL_BYTES, SEGMENT_RE, WORKFLOW_ENV_OVERLAY_MAX_KEYS, WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES, WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE, isEnvRef, looksLikeEmbeddedJson, ZERO, isRecord2;
|
|
5564
5723
|
var init_dist2 = __esm({
|
|
5565
5724
|
"../workflow-graph/dist/index.mjs"() {
|
|
5566
5725
|
"use strict";
|
|
@@ -5663,7 +5822,88 @@ var init_dist2 = __esm({
|
|
|
5663
5822
|
}), "fromKnowledge");
|
|
5664
5823
|
SideEffectsSchema = z4.enum(WORKFLOW_SIDE_EFFECTS);
|
|
5665
5824
|
JobResourcesSchema = z4.enum(WORKFLOW_JOB_RESOURCES);
|
|
5666
|
-
|
|
5825
|
+
APPROVER_SPEC_MAX_USERS = 20;
|
|
5826
|
+
ESCALATION_MAX_HOPS = 3;
|
|
5827
|
+
TemplateBindingSchema = z22.object({
|
|
5828
|
+
template: z22.string().min(1).max(2048)
|
|
5829
|
+
}).strict();
|
|
5830
|
+
ApproverSpecSchema = z22.union([
|
|
5831
|
+
z22.literal("creator"),
|
|
5832
|
+
z22.literal("org-admins"),
|
|
5833
|
+
z22.object({
|
|
5834
|
+
users: z22.union([
|
|
5835
|
+
z22.array(z22.string().min(1).max(128)).min(1).max(APPROVER_SPEC_MAX_USERS),
|
|
5836
|
+
TemplateBindingSchema
|
|
5837
|
+
])
|
|
5838
|
+
}).strict(),
|
|
5839
|
+
z22.object({
|
|
5840
|
+
role: z22.union([
|
|
5841
|
+
z22.string().min(1).max(128),
|
|
5842
|
+
TemplateBindingSchema
|
|
5843
|
+
])
|
|
5844
|
+
}).strict(),
|
|
5845
|
+
z22.object({
|
|
5846
|
+
group: z22.union([
|
|
5847
|
+
z22.string().min(1).max(128),
|
|
5848
|
+
TemplateBindingSchema
|
|
5849
|
+
])
|
|
5850
|
+
}).strict(),
|
|
5851
|
+
z22.object({
|
|
5852
|
+
governance: z22.object({
|
|
5853
|
+
policyId: z22.string().min(1).max(128)
|
|
5854
|
+
}).strict()
|
|
5855
|
+
}).strict()
|
|
5856
|
+
]);
|
|
5857
|
+
FourEyesSchema = z22.object({
|
|
5858
|
+
edit: ApproverSpecSchema,
|
|
5859
|
+
approve: ApproverSpecSchema
|
|
5860
|
+
}).strict();
|
|
5861
|
+
EscalationHopSchema = z22.object({
|
|
5862
|
+
escalateTo: ApproverSpecSchema,
|
|
5863
|
+
timeoutHours: z22.number().finite().min(1).max(720)
|
|
5864
|
+
}).strict();
|
|
5865
|
+
TerminalOutcomeSchema = z22.enum([
|
|
5866
|
+
"deny",
|
|
5867
|
+
"cancel-run",
|
|
5868
|
+
"fail",
|
|
5869
|
+
"continue"
|
|
5870
|
+
]);
|
|
5871
|
+
ApprovalOnTimeoutSchema = z22.union([
|
|
5872
|
+
TerminalOutcomeSchema,
|
|
5873
|
+
EscalationHopSchema,
|
|
5874
|
+
z22.array(z22.union([
|
|
5875
|
+
TerminalOutcomeSchema,
|
|
5876
|
+
EscalationHopSchema
|
|
5877
|
+
])).min(1).max(ESCALATION_MAX_HOPS + 1)
|
|
5878
|
+
]);
|
|
5879
|
+
APPROVER_SPEC_SHAPES = [
|
|
5880
|
+
"'creator'",
|
|
5881
|
+
"'org-admins'",
|
|
5882
|
+
"{users:[userId, \u2026]}",
|
|
5883
|
+
"{role:roleName}",
|
|
5884
|
+
"{group:groupName}",
|
|
5885
|
+
"{governance:{policyId}}"
|
|
5886
|
+
];
|
|
5887
|
+
APPROVER_WRITTEN_MAX = 120;
|
|
5888
|
+
USER_ID_SHAPED_RE = /^[^\s@]{1,128}$/;
|
|
5889
|
+
__name(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
5890
|
+
__name3(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
5891
|
+
BINDING_ROOTS = [
|
|
5892
|
+
"initData",
|
|
5893
|
+
"stepResults",
|
|
5894
|
+
"requestContext",
|
|
5895
|
+
"state"
|
|
5896
|
+
];
|
|
5897
|
+
__name(bindingRootsOk, "bindingRootsOk");
|
|
5898
|
+
__name3(bindingRootsOk, "bindingRootsOk");
|
|
5899
|
+
__name(isTemplateBinding, "isTemplateBinding");
|
|
5900
|
+
__name3(isTemplateBinding, "isTemplateBinding");
|
|
5901
|
+
__name(approvalEditable, "approvalEditable");
|
|
5902
|
+
__name3(approvalEditable, "approvalEditable");
|
|
5903
|
+
__name(validateApproverBlock, "validateApproverBlock");
|
|
5904
|
+
__name3(validateApproverBlock, "validateApproverBlock");
|
|
5905
|
+
__name(liftRenderedApprover, "liftRenderedApprover");
|
|
5906
|
+
__name3(liftRenderedApprover, "liftRenderedApprover");
|
|
5667
5907
|
WORKSPACE_TEMPLATE_EXPR_RE = /^\$\{\s*(?:initData|input)\.([^}]+?)\s*\}$/;
|
|
5668
5908
|
__name(workspaceTemplatePath, "workspaceTemplatePath");
|
|
5669
5909
|
__name3(workspaceTemplatePath, "workspaceTemplatePath");
|
|
@@ -5675,6 +5915,8 @@ var init_dist2 = __esm({
|
|
|
5675
5915
|
});
|
|
5676
5916
|
__name(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
|
|
5677
5917
|
__name3(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
|
|
5918
|
+
__name(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
|
|
5919
|
+
__name3(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
|
|
5678
5920
|
WORKFLOW_CAPS_DEFAULT = Object.freeze({
|
|
5679
5921
|
maxParallelArms: 16,
|
|
5680
5922
|
maxForeachConcurrency: 16,
|
|
@@ -5956,8 +6198,8 @@ var init_dist2 = __esm({
|
|
|
5956
6198
|
__name(isContinuedFailureValue, "isContinuedFailureValue");
|
|
5957
6199
|
__name3(isContinuedFailureValue, "isContinuedFailureValue");
|
|
5958
6200
|
isHitlNode2 = /* @__PURE__ */ __name3((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
|
|
5959
|
-
__name(
|
|
5960
|
-
__name3(
|
|
6201
|
+
__name(inlineContainerArm, "inlineContainerArm");
|
|
6202
|
+
__name3(inlineContainerArm, "inlineContainerArm");
|
|
5961
6203
|
nodeIdOf = /* @__PURE__ */ __name3((n2) => n2.type === "step" ? n2.step.id : n2.id, "nodeIdOf");
|
|
5962
6204
|
__name(entryIds, "entryIds");
|
|
5963
6205
|
__name3(entryIds, "entryIds");
|
|
@@ -6017,6 +6259,12 @@ var init_dist2 = __esm({
|
|
|
6017
6259
|
__name3(isTerminalRunStatus, "isTerminalRunStatus");
|
|
6018
6260
|
__name(pruneUndefined, "pruneUndefined");
|
|
6019
6261
|
__name3(pruneUndefined, "pruneUndefined");
|
|
6262
|
+
WORKFLOW_INLINE_RUN_TAG = "inline";
|
|
6263
|
+
__name(runOrigin, "runOrigin");
|
|
6264
|
+
__name3(runOrigin, "runOrigin");
|
|
6265
|
+
RUN_ERROR_ISSUES_MAX = 20;
|
|
6266
|
+
__name(runErrorIssues, "runErrorIssues");
|
|
6267
|
+
__name3(runErrorIssues, "runErrorIssues");
|
|
6020
6268
|
__name(runNextAction, "runNextAction");
|
|
6021
6269
|
__name3(runNextAction, "runNextAction");
|
|
6022
6270
|
IN_FLIGHT = new Set(WORKFLOW_STEP_IN_FLIGHT);
|
|
@@ -6177,86 +6425,6 @@ var init_dist2 = __esm({
|
|
|
6177
6425
|
__name3(applyJsonPatch, "applyJsonPatch");
|
|
6178
6426
|
__name(rebaseItemPointer, "rebaseItemPointer");
|
|
6179
6427
|
__name3(rebaseItemPointer, "rebaseItemPointer");
|
|
6180
|
-
APPROVER_SPEC_MAX_USERS = 20;
|
|
6181
|
-
ESCALATION_MAX_HOPS = 3;
|
|
6182
|
-
TemplateBindingSchema = z22.object({
|
|
6183
|
-
template: z22.string().min(1).max(2048)
|
|
6184
|
-
}).strict();
|
|
6185
|
-
ApproverSpecSchema = z22.union([
|
|
6186
|
-
z22.literal("creator"),
|
|
6187
|
-
z22.literal("org-admins"),
|
|
6188
|
-
z22.object({
|
|
6189
|
-
users: z22.union([
|
|
6190
|
-
z22.array(z22.string().min(1).max(128)).min(1).max(APPROVER_SPEC_MAX_USERS),
|
|
6191
|
-
TemplateBindingSchema
|
|
6192
|
-
])
|
|
6193
|
-
}).strict(),
|
|
6194
|
-
z22.object({
|
|
6195
|
-
role: z22.union([
|
|
6196
|
-
z22.string().min(1).max(128),
|
|
6197
|
-
TemplateBindingSchema
|
|
6198
|
-
])
|
|
6199
|
-
}).strict(),
|
|
6200
|
-
z22.object({
|
|
6201
|
-
group: z22.union([
|
|
6202
|
-
z22.string().min(1).max(128),
|
|
6203
|
-
TemplateBindingSchema
|
|
6204
|
-
])
|
|
6205
|
-
}).strict(),
|
|
6206
|
-
z22.object({
|
|
6207
|
-
governance: z22.object({
|
|
6208
|
-
policyId: z22.string().min(1).max(128)
|
|
6209
|
-
}).strict()
|
|
6210
|
-
}).strict()
|
|
6211
|
-
]);
|
|
6212
|
-
FourEyesSchema = z22.object({
|
|
6213
|
-
edit: ApproverSpecSchema,
|
|
6214
|
-
approve: ApproverSpecSchema
|
|
6215
|
-
}).strict();
|
|
6216
|
-
EscalationHopSchema = z22.object({
|
|
6217
|
-
escalateTo: ApproverSpecSchema,
|
|
6218
|
-
timeoutHours: z22.number().finite().min(1).max(720)
|
|
6219
|
-
}).strict();
|
|
6220
|
-
TerminalOutcomeSchema = z22.enum([
|
|
6221
|
-
"deny",
|
|
6222
|
-
"cancel-run",
|
|
6223
|
-
"fail",
|
|
6224
|
-
"continue"
|
|
6225
|
-
]);
|
|
6226
|
-
ApprovalOnTimeoutSchema = z22.union([
|
|
6227
|
-
TerminalOutcomeSchema,
|
|
6228
|
-
EscalationHopSchema,
|
|
6229
|
-
z22.array(z22.union([
|
|
6230
|
-
TerminalOutcomeSchema,
|
|
6231
|
-
EscalationHopSchema
|
|
6232
|
-
])).min(1).max(ESCALATION_MAX_HOPS + 1)
|
|
6233
|
-
]);
|
|
6234
|
-
APPROVER_SPEC_SHAPES = [
|
|
6235
|
-
"'creator'",
|
|
6236
|
-
"'org-admins'",
|
|
6237
|
-
"{users:[userId, \u2026]}",
|
|
6238
|
-
"{role:roleName}",
|
|
6239
|
-
"{group:groupName}",
|
|
6240
|
-
"{governance:{policyId}}"
|
|
6241
|
-
];
|
|
6242
|
-
APPROVER_WRITTEN_MAX = 120;
|
|
6243
|
-
USER_ID_SHAPED_RE = /^[^\s@]{1,128}$/;
|
|
6244
|
-
__name(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
6245
|
-
__name3(describeApproverSpecRefusal, "describeApproverSpecRefusal");
|
|
6246
|
-
BINDING_ROOTS = [
|
|
6247
|
-
"initData",
|
|
6248
|
-
"stepResults",
|
|
6249
|
-
"requestContext",
|
|
6250
|
-
"state"
|
|
6251
|
-
];
|
|
6252
|
-
__name(bindingRootsOk, "bindingRootsOk");
|
|
6253
|
-
__name3(bindingRootsOk, "bindingRootsOk");
|
|
6254
|
-
__name(isTemplateBinding, "isTemplateBinding");
|
|
6255
|
-
__name3(isTemplateBinding, "isTemplateBinding");
|
|
6256
|
-
__name(validateApproverBlock, "validateApproverBlock");
|
|
6257
|
-
__name3(validateApproverBlock, "validateApproverBlock");
|
|
6258
|
-
__name(liftRenderedApprover, "liftRenderedApprover");
|
|
6259
|
-
__name3(liftRenderedApprover, "liftRenderedApprover");
|
|
6260
6428
|
WORKFLOW_ENV_OVERLAY_MAX_KEYS = 64;
|
|
6261
6429
|
WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES = 4096;
|
|
6262
6430
|
WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
|
|
@@ -6359,14 +6527,13 @@ function stepNodeOf(s) {
|
|
|
6359
6527
|
}
|
|
6360
6528
|
function materializeEntry(entry, steps) {
|
|
6361
6529
|
const single = /* @__PURE__ */ __name((n2) => {
|
|
6362
|
-
if (n2.type === "step" && steps[n2.step.id])
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
n2.
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
};
|
|
6530
|
+
if (n2.type === "step" && steps[n2.step.id]) {
|
|
6531
|
+
const node = stepNodeOf(steps[n2.step.id]);
|
|
6532
|
+
return n2.input !== void 0 ? {
|
|
6533
|
+
...node,
|
|
6534
|
+
input: n2.input
|
|
6535
|
+
} : node;
|
|
6536
|
+
}
|
|
6370
6537
|
return n2;
|
|
6371
6538
|
}, "single");
|
|
6372
6539
|
switch (entry.type) {
|
|
@@ -6524,7 +6691,10 @@ var init_workflow = __esm({
|
|
|
6524
6691
|
}, "assertPredicate");
|
|
6525
6692
|
assertRetry = /* @__PURE__ */ __name((r, id) => {
|
|
6526
6693
|
if (!r) return;
|
|
6527
|
-
if (
|
|
6694
|
+
if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
6695
|
+
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
6696
|
+
throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
|
|
6697
|
+
}
|
|
6528
6698
|
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(" | ")}`);
|
|
6529
6699
|
if (r.maxBackoffSeconds !== void 0) {
|
|
6530
6700
|
if (r.backoff !== "exponential") throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.maxBackoffSeconds is only meaningful with backoff:'exponential'`);
|
|
@@ -7299,7 +7469,93 @@ function isAccessDeniedError(error) {
|
|
|
7299
7469
|
if (CliError.isCliError(error)) return error.statusCode === 403;
|
|
7300
7470
|
return error instanceof Error && error.message.startsWith("Access denied (403)");
|
|
7301
7471
|
}
|
|
7302
|
-
|
|
7472
|
+
function authHint(error) {
|
|
7473
|
+
if (error.suppressDefaultRemediation) return void 0;
|
|
7474
|
+
if (error.reason === "no_agent_access") {
|
|
7475
|
+
return [
|
|
7476
|
+
"Your API key is valid, but it does not have access to the agentId in lua.skill.yaml \u2014 the agent belongs",
|
|
7477
|
+
"to another account or organization, was deleted or transferred, or the yaml was copied from another project.",
|
|
7478
|
+
"Check the configured agent and switch if needed:",
|
|
7479
|
+
" lua agents (list agents you have access to)",
|
|
7480
|
+
" lua init (re-select the agent for this project)"
|
|
7481
|
+
].join("\n");
|
|
7482
|
+
}
|
|
7483
|
+
return "Re-authenticate or check your API key: lua auth configure \xB7 https://admin.heylua.ai";
|
|
7484
|
+
}
|
|
7485
|
+
function numericStatus(error) {
|
|
7486
|
+
const candidate = error.statusCode ?? error.status;
|
|
7487
|
+
return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : void 0;
|
|
7488
|
+
}
|
|
7489
|
+
function classifyCliError(error) {
|
|
7490
|
+
if (CliError.isCliError(error)) {
|
|
7491
|
+
return {
|
|
7492
|
+
code: error.code,
|
|
7493
|
+
exitCode: error.exitCode,
|
|
7494
|
+
message: error.message,
|
|
7495
|
+
hint: error.hint
|
|
7496
|
+
};
|
|
7497
|
+
}
|
|
7498
|
+
if (AuthenticationError.isAuthenticationError(error)) {
|
|
7499
|
+
return {
|
|
7500
|
+
code: "auth",
|
|
7501
|
+
exitCode: CLI_EXIT.AUTH,
|
|
7502
|
+
message: error.message,
|
|
7503
|
+
hint: authHint(error)
|
|
7504
|
+
};
|
|
7505
|
+
}
|
|
7506
|
+
const e = typeof error === "object" && error !== null ? error : {};
|
|
7507
|
+
const message = typeof e.message === "string" && e.message.length > 0 ? e.message : error instanceof Error ? error.name : String(error ?? "Unknown error");
|
|
7508
|
+
if (e.name === "WorkflowLocalUsageError" || typeof e.code === "string" && e.code.startsWith("commander.")) {
|
|
7509
|
+
return {
|
|
7510
|
+
code: "usage",
|
|
7511
|
+
exitCode: CLI_EXIT.USAGE,
|
|
7512
|
+
message
|
|
7513
|
+
};
|
|
7514
|
+
}
|
|
7515
|
+
const status = numericStatus(e);
|
|
7516
|
+
if (status !== void 0) {
|
|
7517
|
+
if (status === 401) return {
|
|
7518
|
+
code: "auth",
|
|
7519
|
+
exitCode: CLI_EXIT.AUTH,
|
|
7520
|
+
message
|
|
7521
|
+
};
|
|
7522
|
+
if (status === 403) return {
|
|
7523
|
+
code: "forbidden",
|
|
7524
|
+
exitCode: CLI_EXIT.FORBIDDEN,
|
|
7525
|
+
message
|
|
7526
|
+
};
|
|
7527
|
+
if (status === 404) return {
|
|
7528
|
+
code: "not_found",
|
|
7529
|
+
exitCode: CLI_EXIT.NOT_FOUND,
|
|
7530
|
+
message
|
|
7531
|
+
};
|
|
7532
|
+
if (status >= 400 && status < 500) return {
|
|
7533
|
+
code: `http_${status}`,
|
|
7534
|
+
exitCode: CLI_EXIT.FORBIDDEN,
|
|
7535
|
+
message
|
|
7536
|
+
};
|
|
7537
|
+
if (status >= 500 || status === 0) return {
|
|
7538
|
+
code: "unavailable",
|
|
7539
|
+
exitCode: CLI_EXIT.UNAVAILABLE,
|
|
7540
|
+
message
|
|
7541
|
+
};
|
|
7542
|
+
}
|
|
7543
|
+
const causeCode = e.cause?.code;
|
|
7544
|
+
if (typeof e.code === "string" && NETWORK_ERRNO.has(e.code) || typeof causeCode === "string" && NETWORK_ERRNO.has(causeCode) || e.name === "AbortError" || e.name === "TimeoutError" || NETWORK_MESSAGE.test(message)) {
|
|
7545
|
+
return {
|
|
7546
|
+
code: "unavailable",
|
|
7547
|
+
exitCode: CLI_EXIT.UNAVAILABLE,
|
|
7548
|
+
message,
|
|
7549
|
+
hint: UNAVAILABLE_HINT
|
|
7550
|
+
};
|
|
7551
|
+
}
|
|
7552
|
+
return {
|
|
7553
|
+
code: "error",
|
|
7554
|
+
exitCode: CLI_EXIT.ERROR,
|
|
7555
|
+
message
|
|
7556
|
+
};
|
|
7557
|
+
}
|
|
7558
|
+
var CLI_EXIT, CliError, NETWORK_ERRNO, NETWORK_MESSAGE, UNAVAILABLE_HINT;
|
|
7303
7559
|
var init_cli_error = __esm({
|
|
7304
7560
|
"src/errors/cli.error.ts"() {
|
|
7305
7561
|
"use strict";
|
|
@@ -7354,11 +7610,48 @@ var init_cli_error = __esm({
|
|
|
7354
7610
|
statusCode: 403
|
|
7355
7611
|
});
|
|
7356
7612
|
}
|
|
7613
|
+
/**
|
|
7614
|
+
* An API refusal the site already holds the status of (LUA-766) — classified by the same table the top-level
|
|
7615
|
+
* classifier applies to an untyped error: 401 auth · 403 forbidden · 404 not_found · other 4xx `http_<status>`
|
|
7616
|
+
* (10) · 5xx / 0 unavailable (11, with the network hint unless the site gives its own) · no status `error` (1).
|
|
7617
|
+
* A command that reads `response.error.statusCode` throws through here, so `lua logs` on a 503 exits 11 like
|
|
7618
|
+
* every other verb instead of printing the message itself and then throwing an exit-1 `Error`.
|
|
7619
|
+
*/
|
|
7620
|
+
static fromStatus(statusCode, message, hint) {
|
|
7621
|
+
const reported = classifyCliError(Object.assign(new Error(message), {
|
|
7622
|
+
statusCode
|
|
7623
|
+
}));
|
|
7624
|
+
const classHint = reported.exitCode === CLI_EXIT.UNAVAILABLE ? UNAVAILABLE_HINT : reported.hint;
|
|
7625
|
+
return new _CliError(reported.code, message, {
|
|
7626
|
+
exitCode: reported.exitCode,
|
|
7627
|
+
hint: hint ?? classHint,
|
|
7628
|
+
statusCode
|
|
7629
|
+
});
|
|
7630
|
+
}
|
|
7357
7631
|
static isCliError(error) {
|
|
7358
7632
|
return error instanceof _CliError || typeof error === "object" && error !== null && error.isCliError === true;
|
|
7359
7633
|
}
|
|
7360
7634
|
};
|
|
7361
7635
|
__name(isAccessDeniedError, "isAccessDeniedError");
|
|
7636
|
+
NETWORK_ERRNO = /* @__PURE__ */ new Set([
|
|
7637
|
+
"ECONNREFUSED",
|
|
7638
|
+
"ECONNRESET",
|
|
7639
|
+
"ENOTFOUND",
|
|
7640
|
+
"ETIMEDOUT",
|
|
7641
|
+
"EAI_AGAIN",
|
|
7642
|
+
"EPIPE",
|
|
7643
|
+
"EHOSTUNREACH",
|
|
7644
|
+
"ENETUNREACH",
|
|
7645
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
7646
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
7647
|
+
"UND_ERR_BODY_TIMEOUT",
|
|
7648
|
+
"UND_ERR_SOCKET"
|
|
7649
|
+
]);
|
|
7650
|
+
NETWORK_MESSAGE = /fetch failed|socket hang up|network request failed|request timeout|ECONNREFUSED|ENOTFOUND/i;
|
|
7651
|
+
UNAVAILABLE_HINT = "The Lua API could not be reached \u2014 check your network and https://status.heylua.ai, then retry.";
|
|
7652
|
+
__name(authHint, "authHint");
|
|
7653
|
+
__name(numericStatus, "numericStatus");
|
|
7654
|
+
__name(classifyCliError, "classifyCliError");
|
|
7362
7655
|
}
|
|
7363
7656
|
});
|
|
7364
7657
|
|
|
@@ -13440,6 +13733,14 @@ var init_workflow_api_service = __esm({
|
|
|
13440
13733
|
async getVersionEnvOverlay(workflowId, version) {
|
|
13441
13734
|
return this.httpGet(`${this.base}/${workflowId}/versions/${encodeURIComponent(version)}/env-overlay`, await this.auth());
|
|
13442
13735
|
}
|
|
13736
|
+
/**
|
|
13737
|
+
* WF-403 (13 §13.14; LUA-752) — `GET …/:workflowId/export?version=`: the active (or named) version as pushable
|
|
13738
|
+
* files (`{ form, version, files:[{ path, contents }], warnings }`). `lua workflows export` writes them to disk.
|
|
13739
|
+
*/
|
|
13740
|
+
async exportWorkflowFiles(workflowId, version) {
|
|
13741
|
+
const qs = version ? `?version=${encodeURIComponent(version)}` : "";
|
|
13742
|
+
return this.httpGet(`${this.base}/${workflowId}/export${qs}`, await this.auth());
|
|
13743
|
+
}
|
|
13443
13744
|
async getWorkflowVersions(workflowId) {
|
|
13444
13745
|
return this.httpGet(`${this.base}/${workflowId}/versions`, await this.auth());
|
|
13445
13746
|
}
|
|
@@ -13536,6 +13837,34 @@ var init_workflow_api_service = __esm({
|
|
|
13536
13837
|
async retryStep(runId, stepId, data = {}) {
|
|
13537
13838
|
return this.httpPost(`${this.runs}/${runId}/steps/${pathId(stepId)}/retry`, data, await this.auth());
|
|
13538
13839
|
}
|
|
13840
|
+
/**
|
|
13841
|
+
* R37 (LUA-752) — a human decides a parked step: `skip` it, `complete` it with the output it would have produced,
|
|
13842
|
+
* or `fail` it (the step's onError policy applies). 400 `VALIDATION_FAILED{output-required}` / `RESOLVE_OUTPUT_INVALID`,
|
|
13843
|
+
* 403 `APPROVAL_REQUIRES_HUMAN` / `NOT_RUN_CREATOR`, 404 `RUN_NOT_FOUND` / `STEP_NOT_FOUND`, 409 `STEP_NOT_PARKED` /
|
|
13844
|
+
* `RUN_TERMINAL`, 413 `OUTPUT_TOO_LARGE`; the CAS loser is a 200 `{ resolved:false, reason, recorded }`.
|
|
13845
|
+
*/
|
|
13846
|
+
async resolveStep(runId, stepId, data) {
|
|
13847
|
+
return this.httpPost(`${this.runs}/${runId}/steps/${pathId(stepId)}/resolve`, data, await this.auth());
|
|
13848
|
+
}
|
|
13849
|
+
/**
|
|
13850
|
+
* R45 (LUA-752) — raise a parked run's budget (`maxCredits` / `maxSteps` / `maxJobSeconds` / `maxDurationSeconds`;
|
|
13851
|
+
* increases only). 400 `VALIDATION_FAILED` / `CAP_EXCEEDED`, 403 `NOT_RUN_CREATOR`, 409 `BUDGET_NOT_RAISABLE`.
|
|
13852
|
+
*/
|
|
13853
|
+
async raiseBudget(runId, data) {
|
|
13854
|
+
return this.httpPost(`${this.runs}/${runId}/budget`, data, await this.auth());
|
|
13855
|
+
}
|
|
13856
|
+
/**
|
|
13857
|
+
* R39 (LUA-752) — the current approval payload with its `payloadFingerprint` / `editRevision` (what
|
|
13858
|
+
* `approve --edit --fingerprint` echoes). `path` pages one array of a large payload.
|
|
13859
|
+
*/
|
|
13860
|
+
async getApprovalPayload(runId, approvalId, query = {}) {
|
|
13861
|
+
const q = new URLSearchParams();
|
|
13862
|
+
if (query.path) q.append("path", query.path);
|
|
13863
|
+
if (query.cursor) q.append("cursor", query.cursor);
|
|
13864
|
+
if (query.limit !== void 0) q.append("limit", String(query.limit));
|
|
13865
|
+
const qs = q.toString();
|
|
13866
|
+
return this.httpGet(`${this.runs}/${runId}/approvals/${pathId(approvalId)}/payload${qs ? `?${qs}` : ""}`, await this.auth());
|
|
13867
|
+
}
|
|
13539
13868
|
/** R13 — resolve an approval (human; `expectedFingerprint` guards against an edited payload — 409 `PAYLOAD_MISMATCH`). */
|
|
13540
13869
|
async resolveApproval(runId, approvalId, data) {
|
|
13541
13870
|
return this.httpPost(`${this.runs}/${runId}/approvals/${pathId(approvalId)}/resolve`, data, await this.auth());
|
|
@@ -13620,6 +13949,14 @@ var init_workflow_api_service = __esm({
|
|
|
13620
13949
|
async getSchedule(jobId) {
|
|
13621
13950
|
return this.httpGet(`${this.schedules}/${encodeURIComponent(jobId)}`, await this.auth());
|
|
13622
13951
|
}
|
|
13952
|
+
/** R27 (LUA-752) — create or replace the plain schedule Job of a workflow (201; 400 `VALIDATION_FAILED` / `WORKFLOW_NOT_ON_AGENT`, 404 `WORKFLOW_NOT_FOUND`, 409 `SCHEDULE_CAP`). */
|
|
13953
|
+
async createSchedule(data) {
|
|
13954
|
+
return this.httpPost(this.schedules, data, await this.auth());
|
|
13955
|
+
}
|
|
13956
|
+
/** R56 (LUA-752) — pause / resume a schedule, persist `backfillOnEnable`, one-shot `backfillNow` (404 `SCHEDULE_NOT_FOUND`, 400 `VALIDATION_FAILED{issues}`). */
|
|
13957
|
+
async updateSchedule(jobId, data) {
|
|
13958
|
+
return this.httpPatch(`${this.schedules}/${encodeURIComponent(jobId)}`, data, await this.auth());
|
|
13959
|
+
}
|
|
13623
13960
|
/** R28 — delete a schedule Job (404 `SCHEDULE_NOT_FOUND`). The CLI refuses a LIVE goal's job BEFORE this call (`goal_schedule`); an ended goal's lingering Job is retired here (LUA-760). */
|
|
13624
13961
|
async deleteSchedule(jobId) {
|
|
13625
13962
|
return this.httpDelete(`${this.schedules}/${encodeURIComponent(jobId)}`, await this.auth());
|