lua-cli 3.32.5 → 3.33.0

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.
@@ -431,6 +431,18 @@ function modelUnresolvedMessage(r) {
431
431
  }
432
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
433
  }
434
+ function providerModelId(code) {
435
+ const requested = typeof code === "string" ? code.trim() : "";
436
+ if (!requested || isModelIdSentinel(requested)) return requested;
437
+ const slash = requested.indexOf("/");
438
+ if (slash <= 0) return requested;
439
+ const provider = requested.slice(0, slash).toLowerCase();
440
+ if (MODEL_ID_BYOK_PROVIDERS.includes(provider)) return requested;
441
+ return requested.slice(slash + 1);
442
+ }
443
+ function providerModelFamily(code) {
444
+ return providerModelId(code).toLowerCase().replace(MODEL_SNAPSHOT_SUFFIX, "");
445
+ }
434
446
  function isImplicitModelSelectionSource(source) {
435
447
  return source !== void 0 && IMPLICIT_MODEL_SELECTION_SOURCES.includes(source);
436
448
  }
@@ -699,6 +711,9 @@ function creatorUserId(identity) {
699
711
  function actingUserId(identity) {
700
712
  return creatorUserId(identity);
701
713
  }
714
+ function isWorkflowSignalEventSite(value3) {
715
+ return typeof value3 === "string" && WORKFLOW_SIGNAL_EVENT_SITES.includes(value3);
716
+ }
702
717
  function shouldSkipArchive(run, manifestSha256, sinkSha256) {
703
718
  if (!run.completedAt || !run.exportedAt || run.exportedAt < run.completedAt) return false;
704
719
  return !!manifestSha256 && manifestSha256 === sinkSha256;
@@ -838,6 +853,23 @@ function workflowHitlArmUnsupportedMessage(type, id, container) {
838
853
  function workflowHitlArmShapeMessage(type, id, shape) {
839
854
  return shape === "mapped-arm" ? `\`${type}\` arm "${id}" takes the previous output as its payload \u2014 it cannot head a [mapping, step] chain; map before the container instead` : `a chunked foreach hands each child a slice of items, not one \u2014 \`${type}\` body "${id}" takes one item; drop \`chunk\``;
840
855
  }
856
+ function workflowGoalJudgeKind(judge) {
857
+ return judge && typeof judge === "object" && judge.predicate !== void 0 ? "predicate" : "agent";
858
+ }
859
+ function isWorkflowGoalJudgeComplete(judge) {
860
+ if (workflowGoalJudgeKind(judge) === "predicate") return true;
861
+ return typeof judge.agentId === "string" && judge.agentId.length > 0 && !!judge.schema && typeof judge.schema === "object" && !Array.isArray(judge.schema);
862
+ }
863
+ function normalizeWorkflowGoalJudge(judge) {
864
+ if (workflowGoalJudgeKind(judge) === "agent") return judge;
865
+ return {
866
+ agentId: judge.agentId ?? WORKFLOW_GOAL_JUDGE_SELF,
867
+ predicate: judge.predicate,
868
+ ...judge.schema ? {
869
+ schema: judge.schema
870
+ } : {}
871
+ };
872
+ }
841
873
  function groupCount(re) {
842
874
  let n2 = GROUP_COUNT.get(re);
843
875
  if (n2 === void 0) {
@@ -1077,19 +1109,27 @@ function resolveEffectiveFeature(row, catalogDefault) {
1077
1109
  default: catalogDefault
1078
1110
  };
1079
1111
  }
1080
- function isFeatureRow(value3) {
1081
- return typeof value3 === "object" && value3 !== null;
1112
+ function asFeatureRow(value3) {
1113
+ if (value3 === false) return {
1114
+ active: false
1115
+ };
1116
+ return typeof value3 === "object" && value3 !== null && !Array.isArray(value3) ? value3 : void 0;
1117
+ }
1118
+ function agentFeatureBagCarries(bag, name) {
1119
+ return bag != null && Object.prototype.hasOwnProperty.call(bag, name) && asFeatureRow(bag[name]) !== void 0;
1082
1120
  }
1083
1121
  function effectiveAgentFeatureRows(base, override) {
1084
1122
  const merged = /* @__PURE__ */ new Map();
1085
- for (const [name, row] of Object.entries(base ?? {})) {
1086
- if (isFeatureRow(row)) merged.set(name, {
1123
+ for (const [name, value3] of Object.entries(base ?? {})) {
1124
+ const row = asFeatureRow(value3);
1125
+ if (row) merged.set(name, {
1087
1126
  row,
1088
1127
  origin: "baseAgent"
1089
1128
  });
1090
1129
  }
1091
- for (const [name, row] of Object.entries(override ?? {})) {
1092
- if (isFeatureRow(row)) merged.set(name, {
1130
+ for (const [name, value3] of Object.entries(override ?? {})) {
1131
+ const row = asFeatureRow(value3);
1132
+ if (row) merged.set(name, {
1093
1133
  row,
1094
1134
  origin: "subAgent"
1095
1135
  });
@@ -1109,7 +1149,15 @@ function effectiveAgentFeatureRows(base, override) {
1109
1149
  ]))
1110
1150
  };
1111
1151
  }
1112
- 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, SESSION_AUTH_TIME_MAX_S, 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_SCHEDULE_KEY_MAX, WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_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, DEFAULT_ON_AGENT_FEATURES;
1152
+ function agentFeatureMergeRuleFromEnv(env2) {
1153
+ const raw = env2[SUBAGENT_PER_KEY_FLAG_ENV];
1154
+ return typeof raw === "string" && PER_KEY_FLAG_VALUES.has(raw.trim().toLowerCase()) ? "per-key" : "wholesale";
1155
+ }
1156
+ function effectiveAgentFeatures(base, override, rule) {
1157
+ if (rule === "wholesale") return override || base || void 0;
1158
+ return effectiveAgentFeatureRows(base, override).rows;
1159
+ }
1160
+ 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, MODEL_SNAPSHOT_SUFFIX, 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, TEMPLATE_INSTALL_POLICY_PER_WORKSPACE_VALUES, SUBJECT_TYPES, SubjectTypeSchema, CREDENTIAL_TYPES, CredentialTypeSchema, DEVICE_OPERATIONS, DeviceOperationSchema, DEVICE_SCOPE_BY_OPERATION, DeviceBindingSchema, IdSchema, SESSION_AUTH_TIME_MAX_S, 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, LUA_SESSION_ID_CLAIM, SESSION_REVOKED_CODE, 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_RUN_GATE_KINDS, WORKFLOW_STEP_STATUSES, WORKFLOW_STEP_IN_FLIGHT, WORKFLOW_SIGNAL_EVENT_SITES, 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_SCHEDULE_KEY_MAX, WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX, WORKFLOW_OPERATION_ID_PREFIX, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_SUSPEND_KINDS, WORKFLOW_RUN_NOTIFICATION_SUSPENDED_KINDS, 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, WORKFLOW_GOAL_JUDGE_SELF, 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, DEFAULT_ON_AGENT_FEATURES, SUBAGENT_PER_KEY_FLAG_ENV, PER_KEY_FLAG_VALUES;
1113
1161
  var init_dist = __esm({
1114
1162
  "../shared-types/dist/index.mjs"() {
1115
1163
  "use strict";
@@ -1436,6 +1484,11 @@ var init_dist = __esm({
1436
1484
  __name2(normalizeModelId, "normalizeModelId");
1437
1485
  __name(modelUnresolvedMessage, "modelUnresolvedMessage");
1438
1486
  __name2(modelUnresolvedMessage, "modelUnresolvedMessage");
1487
+ __name(providerModelId, "providerModelId");
1488
+ __name2(providerModelId, "providerModelId");
1489
+ MODEL_SNAPSHOT_SUFFIX = /(?:[-@](?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])|-(?:19|20)\d{2}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01]))$/;
1490
+ __name(providerModelFamily, "providerModelFamily");
1491
+ __name2(providerModelFamily, "providerModelFamily");
1439
1492
  REASONING_EFFORT_VALUES = [
1440
1493
  "off",
1441
1494
  "minimal",
@@ -1807,6 +1860,10 @@ This text is who you are for this person. As you learn them, their name, their w
1807
1860
  TEMPLATE_TRIGGER_URL_ENV_PREFIX = "LUA_TRIGGER_URL__";
1808
1861
  __name(triggerUrlEnvKey, "triggerUrlEnvKey");
1809
1862
  __name2(triggerUrlEnvKey, "triggerUrlEnvKey");
1863
+ TEMPLATE_INSTALL_POLICY_PER_WORKSPACE_VALUES = Object.freeze([
1864
+ "single",
1865
+ "multiple"
1866
+ ]);
1810
1867
  SUBJECT_TYPES = [
1811
1868
  "user",
1812
1869
  "apiKey",
@@ -1991,6 +2048,8 @@ This text is who you are for this person. As you learn them, their name, their w
1991
2048
  __name2(formatLuaClientHeader, "formatLuaClientHeader");
1992
2049
  __name(luaClientMetricLabels, "luaClientMetricLabels");
1993
2050
  __name2(luaClientMetricLabels, "luaClientMetricLabels");
2051
+ LUA_SESSION_ID_CLAIM = "luaSessionId";
2052
+ SESSION_REVOKED_CODE = "SESSION_REVOKED";
1994
2053
  AUTHZ_PROJECTION_VERSION = 1;
1995
2054
  ProjectedScopeSchema = z3.string().min(1).max(128);
1996
2055
  DisplayRoleSchema = z3.object({
@@ -2150,6 +2209,15 @@ This text is who you are for this person. As you learn them, their name, their w
2150
2209
  ...WORKFLOW_RUN_IDLE,
2151
2210
  ...WORKFLOW_RUN_TERMINAL
2152
2211
  ];
2212
+ WORKFLOW_RUN_GATE_KINDS = [
2213
+ "start-consent",
2214
+ "quota",
2215
+ "billing",
2216
+ "org_archived",
2217
+ "disabled",
2218
+ "exception",
2219
+ "budget"
2220
+ ];
2153
2221
  WORKFLOW_STEP_STATUSES = [
2154
2222
  "pending",
2155
2223
  "ready",
@@ -2171,6 +2239,13 @@ This text is who you are for this person. As you learn them, their name, their w
2171
2239
  "running",
2172
2240
  "cancellation_requested"
2173
2241
  ];
2242
+ WORKFLOW_SIGNAL_EVENT_SITES = [
2243
+ "webhook",
2244
+ "trigger",
2245
+ "device-trigger"
2246
+ ];
2247
+ __name(isWorkflowSignalEventSite, "isWorkflowSignalEventSite");
2248
+ __name2(isWorkflowSignalEventSite, "isWorkflowSignalEventSite");
2174
2249
  ARCHIVE_WINDOW_MARGIN_DAYS = 7;
2175
2250
  __name(shouldSkipArchive, "shouldSkipArchive");
2176
2251
  __name2(shouldSkipArchive, "shouldSkipArchive");
@@ -2213,6 +2288,16 @@ This text is who you are for this person. As you learn them, their name, their w
2213
2288
  __name2(scheduledTimeKey, "scheduledTimeKey");
2214
2289
  __name(scheduledWorkflowRunIdForTime, "scheduledWorkflowRunIdForTime");
2215
2290
  __name2(scheduledWorkflowRunIdForTime, "scheduledWorkflowRunIdForTime");
2291
+ WORKFLOW_SUSPEND_KINDS = [
2292
+ "input",
2293
+ "approval",
2294
+ "signal",
2295
+ "gate"
2296
+ ];
2297
+ WORKFLOW_RUN_NOTIFICATION_SUSPENDED_KINDS = [
2298
+ ...WORKFLOW_SUSPEND_KINDS,
2299
+ ...WORKFLOW_RUN_GATE_KINDS
2300
+ ];
2216
2301
  WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES = 64 * 1024;
2217
2302
  WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES = 256 * 1024;
2218
2303
  WORKFLOW_RETRY_BACKOFFS = [
@@ -2335,6 +2420,13 @@ This text is who you are for this person. As you learn them, their name, their w
2335
2420
  min: 60,
2336
2421
  max: 2592e3
2337
2422
  });
2423
+ WORKFLOW_GOAL_JUDGE_SELF = "$self";
2424
+ __name(workflowGoalJudgeKind, "workflowGoalJudgeKind");
2425
+ __name2(workflowGoalJudgeKind, "workflowGoalJudgeKind");
2426
+ __name(isWorkflowGoalJudgeComplete, "isWorkflowGoalJudgeComplete");
2427
+ __name2(isWorkflowGoalJudgeComplete, "isWorkflowGoalJudgeComplete");
2428
+ __name(normalizeWorkflowGoalJudge, "normalizeWorkflowGoalJudge");
2429
+ __name2(normalizeWorkflowGoalJudge, "normalizeWorkflowGoalJudge");
2338
2430
  REDACTED_PLACEHOLDER = "[REDACTED]";
2339
2431
  PROVIDER_MESSAGE_MAX_CHARS = 300;
2340
2432
  ERROR_MESSAGE_MAX_CHARS = 2e3;
@@ -2659,10 +2751,71 @@ listed here; never invent a target.`;
2659
2751
  __name2(effectiveFeatureActive, "effectiveFeatureActive");
2660
2752
  __name(resolveEffectiveFeature, "resolveEffectiveFeature");
2661
2753
  __name2(resolveEffectiveFeature, "resolveEffectiveFeature");
2662
- __name(isFeatureRow, "isFeatureRow");
2663
- __name2(isFeatureRow, "isFeatureRow");
2754
+ __name(asFeatureRow, "asFeatureRow");
2755
+ __name2(asFeatureRow, "asFeatureRow");
2756
+ __name(agentFeatureBagCarries, "agentFeatureBagCarries");
2757
+ __name2(agentFeatureBagCarries, "agentFeatureBagCarries");
2664
2758
  __name(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2665
2759
  __name2(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2760
+ SUBAGENT_PER_KEY_FLAG_ENV = "LUA_SUBAGENT_FEATURES_PER_KEY";
2761
+ PER_KEY_FLAG_VALUES = /* @__PURE__ */ new Set([
2762
+ "1",
2763
+ "true",
2764
+ "on",
2765
+ "yes"
2766
+ ]);
2767
+ __name(agentFeatureMergeRuleFromEnv, "agentFeatureMergeRuleFromEnv");
2768
+ __name2(agentFeatureMergeRuleFromEnv, "agentFeatureMergeRuleFromEnv");
2769
+ __name(effectiveAgentFeatures, "effectiveAgentFeatures");
2770
+ __name2(effectiveAgentFeatures, "effectiveAgentFeatures");
2771
+ }
2772
+ });
2773
+
2774
+ // ../shared-types/dist/workflow-job-tools.mjs
2775
+ function effectiveJobTools(jobTools, readOnly) {
2776
+ const base = jobTools?.length ? jobTools : WORKFLOW_JOB_DEFAULT_TOOLS;
2777
+ const out = [];
2778
+ for (const id of base) {
2779
+ if (readOnly && WORKFLOW_JOB_READ_ONLY_DROPPED.includes(id)) continue;
2780
+ if (!out.includes(id)) out.push(id);
2781
+ }
2782
+ return out;
2783
+ }
2784
+ var __defProp3, __name3, WORKFLOW_JOB_TOOLS, WORKFLOW_JOB_READ_ONLY_DROPPED, WORKFLOW_JOB_DEFAULT_TOOLS;
2785
+ var init_workflow_job_tools = __esm({
2786
+ "../shared-types/dist/workflow-job-tools.mjs"() {
2787
+ "use strict";
2788
+ __defProp3 = Object.defineProperty;
2789
+ __name3 = /* @__PURE__ */ __name((target, value3) => __defProp3(target, "name", { value: value3, configurable: true }), "__name");
2790
+ WORKFLOW_JOB_TOOLS = [
2791
+ "shell",
2792
+ "read",
2793
+ "write",
2794
+ "edit",
2795
+ "glob",
2796
+ "grep",
2797
+ "git",
2798
+ "gh",
2799
+ "fetch",
2800
+ "ripwire"
2801
+ ];
2802
+ WORKFLOW_JOB_READ_ONLY_DROPPED = [
2803
+ "write",
2804
+ "edit",
2805
+ "git",
2806
+ "shell"
2807
+ ];
2808
+ WORKFLOW_JOB_DEFAULT_TOOLS = [
2809
+ "shell",
2810
+ "read",
2811
+ "write",
2812
+ "edit",
2813
+ "glob",
2814
+ "grep",
2815
+ "git"
2816
+ ];
2817
+ __name(effectiveJobTools, "effectiveJobTools");
2818
+ __name3(effectiveJobTools, "effectiveJobTools");
2666
2819
  }
2667
2820
  });
2668
2821
 
@@ -2770,7 +2923,7 @@ function isMapDescriptor(v) {
2770
2923
  if (v === null || typeof v !== "object" || Array.isArray(v)) return false;
2771
2924
  const d = v;
2772
2925
  const keys = Object.keys(d);
2773
- const only = /* @__PURE__ */ __name3((...allowed) => keys.every((k) => allowed.includes(k)), "only");
2926
+ const only = /* @__PURE__ */ __name4((...allowed) => keys.every((k) => allowed.includes(k)), "only");
2774
2927
  if ("value" in d) return keys.length === 1;
2775
2928
  if ("template" in d) return keys.length === 1 && typeof d.template === "string";
2776
2929
  if ("requestContextPath" in d) return keys.length === 1 && typeof d.requestContextPath === "string";
@@ -2907,13 +3060,13 @@ function validateApproverBlock(node, opts = {
2907
3060
  path: "approval"
2908
3061
  }) {
2909
3062
  const issues = [];
2910
- const push = /* @__PURE__ */ __name3((code, path3, message, severity = "error") => issues.push({
3063
+ const push = /* @__PURE__ */ __name4((code, path3, message, severity = "error") => issues.push({
2911
3064
  code,
2912
3065
  path: path3,
2913
3066
  severity,
2914
3067
  message
2915
3068
  }), "push");
2916
- const checkSpec = /* @__PURE__ */ __name3((spec, path3) => {
3069
+ const checkSpec = /* @__PURE__ */ __name4((spec, path3) => {
2917
3070
  const r = ApproverSpecSchema.safeParse(spec);
2918
3071
  if (!r.success) {
2919
3072
  const users = spec?.users;
@@ -3051,7 +3204,7 @@ function fillHitl(node) {
3051
3204
  if (a.onTimeout === void 0) a.onTimeout = "deny";
3052
3205
  if (a.onDeny === void 0) a.onDeny = "continue";
3053
3206
  if (a.excludeInitiator === void 0) a.excludeInitiator = false;
3054
- if (a.editable === void 0) a.editable = false;
3207
+ if (a.editable === void 0) a.editable = approvalEditable(a);
3055
3208
  return;
3056
3209
  }
3057
3210
  const w = node;
@@ -3197,7 +3350,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3197
3350
  static: true
3198
3351
  }) {
3199
3352
  const issues = [];
3200
- const err = /* @__PURE__ */ __name3((code, message, path3, stepId) => {
3353
+ const err = /* @__PURE__ */ __name4((code, message, path3, stepId) => {
3201
3354
  issues.push({
3202
3355
  code,
3203
3356
  message,
@@ -3206,7 +3359,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3206
3359
  stepId
3207
3360
  });
3208
3361
  }, "err");
3209
- const warn = /* @__PURE__ */ __name3((code, message, path3, stepId) => {
3362
+ const warn = /* @__PURE__ */ __name4((code, message, path3, stepId) => {
3210
3363
  issues.push({
3211
3364
  code,
3212
3365
  message,
@@ -3263,7 +3416,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3263
3416
  }
3264
3417
  declaredKeys.add(key);
3265
3418
  });
3266
- const undeclaredKey = /* @__PURE__ */ __name3((ref) => typeof ref === "string" && !declaredKeys.has(ref) && isConnectionKeyShaped(ref) && opts.connectionIds?.has(ref) !== true, "undeclaredKey");
3419
+ const undeclaredKey = /* @__PURE__ */ __name4((ref) => typeof ref === "string" && !declaredKeys.has(ref) && isConnectionKeyShaped(ref) && opts.connectionIds?.has(ref) !== true, "undeclaredKey");
3267
3420
  const credentialsRef = envelopeWorkspace?.credentialsRef;
3268
3421
  if (undeclaredKey(credentialsRef)) {
3269
3422
  err("connection-key-undeclared", connectionKeyUndeclaredMessage("workspace.credentialsRef", credentialsRef), "workspace.credentialsRef");
@@ -3271,7 +3424,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3271
3424
  const seen = /* @__PURE__ */ new Map();
3272
3425
  let nodeCount = 0;
3273
3426
  const upstream = /* @__PURE__ */ new Set();
3274
- const checkId = /* @__PURE__ */ __name3((id, path3) => {
3427
+ const checkId = /* @__PURE__ */ __name4((id, path3) => {
3275
3428
  nodeCount += 1;
3276
3429
  if (seen.has(id)) {
3277
3430
  err("duplicate-step-id", `step id "${id}" is declared twice (first at ${seen.get(id)})`, path3, id);
@@ -3279,9 +3432,9 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3279
3432
  seen.set(id, path3);
3280
3433
  }
3281
3434
  }, "checkId");
3282
- const checkPolicyEnums = /* @__PURE__ */ __name3((node, path3) => {
3435
+ const checkPolicyEnums = /* @__PURE__ */ __name4((node, path3) => {
3283
3436
  const id = singleId(node);
3284
- const check = /* @__PURE__ */ __name3((member, allowed) => {
3437
+ const check = /* @__PURE__ */ __name4((member, allowed) => {
3285
3438
  const value22 = node[member];
3286
3439
  if (value22 === void 0 || typeof value22 === "string" && allowed.includes(value22)) return;
3287
3440
  err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path3}.${member}`, id);
@@ -3289,7 +3442,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3289
3442
  check("sideEffects", WORKFLOW_SIDE_EFFECTS);
3290
3443
  check("jobResources", WORKFLOW_JOB_RESOURCES);
3291
3444
  }, "checkPolicyEnums");
3292
- const checkRetry = /* @__PURE__ */ __name3((node, path3) => {
3445
+ const checkRetry = /* @__PURE__ */ __name4((node, path3) => {
3293
3446
  const r = node.retry;
3294
3447
  if (!r) return;
3295
3448
  const id = singleId(node);
@@ -3315,7 +3468,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3315
3468
  }
3316
3469
  }
3317
3470
  }, "checkRetry");
3318
- const checkTimeout = /* @__PURE__ */ __name3((node, path3) => {
3471
+ const checkTimeout = /* @__PURE__ */ __name4((node, path3) => {
3319
3472
  const t = node.timeoutSeconds;
3320
3473
  if (t === void 0) return;
3321
3474
  const id = singleId(node);
@@ -3334,7 +3487,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3334
3487
  err("timeout-exceeds-tier", `timeoutSeconds ${t} exceeds the worker tier's ${caps.maxWorkerTimeoutSeconds} s \u2014 steps longer than 10 min run on the Job tier: add tier:'job' (up to ${caps.maxJobSegmentSeconds} s)`, `${path3}.timeoutSeconds`, id);
3335
3488
  }
3336
3489
  }, "checkTimeout");
3337
- const checkSpecialistRole = /* @__PURE__ */ __name3((node, path3) => {
3490
+ const checkSpecialistRole = /* @__PURE__ */ __name4((node, path3) => {
3338
3491
  const role = node.role;
3339
3492
  const hasRef = typeof role.ref === "string";
3340
3493
  const hasInline = role.name !== void 0 || role.instructions !== void 0 || Array.isArray(role.tools) && role.tools.length > 0;
@@ -3366,7 +3519,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3366
3519
  }
3367
3520
  }
3368
3521
  }, "checkSpecialistRole");
3369
- const checkRequiredConnections = /* @__PURE__ */ __name3((node, path3) => {
3522
+ const checkRequiredConnections = /* @__PURE__ */ __name4((node, path3) => {
3370
3523
  const required = node.requiredConnections;
3371
3524
  if (!Array.isArray(required)) return;
3372
3525
  const undeclared = required.filter(undeclaredKey);
@@ -3379,7 +3532,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3379
3532
  err("required-connection-unknown", `requiredConnections ${JSON.stringify(unknown)} are neither declared connections[].key values nor connections the owner can mount`, `${path3}.requiredConnections`, singleId(node));
3380
3533
  }
3381
3534
  }, "checkRequiredConnections");
3382
- const checkTier = /* @__PURE__ */ __name3((node, path3) => {
3535
+ const checkTier = /* @__PURE__ */ __name4((node, path3) => {
3383
3536
  const id = singleId(node);
3384
3537
  if (node.workspace && node.workspace !== "inherit" && node.tier !== void 0 && node.tier !== "job") {
3385
3538
  err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path3}.workspace`, id);
@@ -3395,7 +3548,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3395
3548
  err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path3}.model`, id);
3396
3549
  }
3397
3550
  }, "checkTier");
3398
- const checkModel = /* @__PURE__ */ __name3((node, path3) => {
3551
+ const checkModel = /* @__PURE__ */ __name4((node, path3) => {
3399
3552
  if (node.type !== "agent" || typeof node.model !== "string") return;
3400
3553
  const registry = opts.approvedModels;
3401
3554
  if (registry === void 0) return;
@@ -3410,7 +3563,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3410
3563
  const resolved = normalizeModelId(node.model, registry);
3411
3564
  if (!resolved.ok) err("model-unresolved", modelUnresolvedMessage(resolved), `${path3}.model`, id);
3412
3565
  }, "checkModel");
3413
- const checkWorkspace = /* @__PURE__ */ __name3((node, path3) => {
3566
+ const checkWorkspace = /* @__PURE__ */ __name4((node, path3) => {
3414
3567
  const id = singleId(node);
3415
3568
  const ws = workspaceOf(node);
3416
3569
  if (isJobTier(node) && opts.policy && opts.policy.jobTier !== true) {
@@ -3433,6 +3586,9 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3433
3586
  warn("gh-on-coding-turn", `"${id}" grants the gh tool on a coding turn \u2014 the pod can open/merge PRs on the workspace repo (purpose:'gh' token, pull_requests:write + contents:write)`, `${path3}.jobTools`, id);
3434
3587
  }
3435
3588
  }
3589
+ if (node.type === "agent" && ws && ws !== "inherit" && ws.mount === "ro" && Array.isArray(tools) && effectiveJobTools(tools, true).length === 0) {
3590
+ warn("ro-step-has-no-tools", `"${id}" mounts the workspace read-only and every jobTool it declares (${JSON.stringify(tools)}) is one the ro mount drops [${WORKFLOW_JOB_READ_ONLY_DROPPED.join(", ")}] \u2014 the coding turn would run with no tools at all; keep a read-only tool (read/glob/grep, gh) or mount rw`, `${path3}.jobTools`, id);
3591
+ }
3436
3592
  if (ws && ws !== "inherit") {
3437
3593
  if (!envelopeWorkspace && !opts.mayInherit) {
3438
3594
  err("workspace-not-declared", `"${id}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path3}.workspace`, id);
@@ -3452,16 +3608,16 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3452
3608
  }
3453
3609
  }, "checkWorkspace");
3454
3610
  const outputSchemas = /* @__PURE__ */ new Map();
3455
- const recordOutputSchema = /* @__PURE__ */ __name3((node) => {
3611
+ const recordOutputSchema = /* @__PURE__ */ __name4((node) => {
3456
3612
  const schema = node.type === "step" ? node.step.outputSchema : node.type === "agent" ? node.outputSchema : void 0;
3457
3613
  if (schema !== void 0) outputSchemas.set(singleId(node), schema);
3458
3614
  }, "recordOutputSchema");
3459
- const checkMapMembers = /* @__PURE__ */ __name3((cfg, basePath, id) => {
3615
+ const checkMapMembers = /* @__PURE__ */ __name4((cfg, basePath, id) => {
3460
3616
  for (const m of malformedMapMembers(cfg)) {
3461
3617
  warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id, m), `${basePath}.${m.member}`, id);
3462
3618
  }
3463
3619
  }, "checkMapMembers");
3464
- const checkInputShape = /* @__PURE__ */ __name3((node, path3) => {
3620
+ const checkInputShape = /* @__PURE__ */ __name4((node, path3) => {
3465
3621
  const input = node.input;
3466
3622
  if (input === void 0) return;
3467
3623
  const id = singleId(node);
@@ -3471,11 +3627,11 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3471
3627
  }
3472
3628
  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);
3473
3629
  }, "checkInputShape");
3474
- const checkBodyInput = /* @__PURE__ */ __name3((body, path3, container) => {
3630
+ const checkBodyInput = /* @__PURE__ */ __name4((body, path3, container) => {
3475
3631
  if (body.type === "workflow" || body.input === void 0) return;
3476
3632
  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));
3477
3633
  }, "checkBodyInput");
3478
- const checkSingle = /* @__PURE__ */ __name3((node, path3, depth) => {
3634
+ const checkSingle = /* @__PURE__ */ __name4((node, path3, depth) => {
3479
3635
  recordOutputSchema(node);
3480
3636
  if (node.type === "workflow" && (typeof node.workflowId !== "string" || node.workflowId.length === 0)) {
3481
3637
  checkId(node.id, path3);
@@ -3524,7 +3680,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3524
3680
  }
3525
3681
  }
3526
3682
  }, "checkSingle");
3527
- const checkHitl = /* @__PURE__ */ __name3((node, path3) => {
3683
+ const checkHitl = /* @__PURE__ */ __name4((node, path3) => {
3528
3684
  if (node.type === "waitForSignal") {
3529
3685
  const w = node;
3530
3686
  checkId(w.id, path3);
@@ -3533,7 +3689,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3533
3689
  }
3534
3690
  const a = node;
3535
3691
  checkId(a.id, path3);
3536
- if (a.approver === "creator" && a.excludeInitiator === true) {
3692
+ if ((a.approver ?? "creator") === "creator" && a.excludeInitiator === true) {
3537
3693
  err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path3, a.id);
3538
3694
  }
3539
3695
  const editable = approvalEditable(a);
@@ -3563,7 +3719,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3563
3719
  }
3564
3720
  }
3565
3721
  }, "checkHitl");
3566
- const checkHitlArm = /* @__PURE__ */ __name3((node, path3, container) => {
3722
+ const checkHitlArm = /* @__PURE__ */ __name4((node, path3, container) => {
3567
3723
  if (!workflowContainerRunsHitlArm(container)) {
3568
3724
  checkId(node.id, path3);
3569
3725
  err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container), path3, node.id);
@@ -3571,7 +3727,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3571
3727
  }
3572
3728
  checkHitl(node, path3);
3573
3729
  }, "checkHitlArm");
3574
- const checkArm = /* @__PURE__ */ __name3((arm, path3, depth, container) => {
3730
+ const checkArm = /* @__PURE__ */ __name4((arm, path3, depth, container) => {
3575
3731
  if (arm.type === "mapping") {
3576
3732
  checkId(arm.id, path3);
3577
3733
  checkMapMembers(readMapConfig(arm.mapConfig), `${path3}.mapConfig`, arm.id);
@@ -3807,7 +3963,7 @@ function isWellFormedPredicate(p) {
3807
3963
  }
3808
3964
  function canonicalJson(value22) {
3809
3965
  const seen = /* @__PURE__ */ new WeakSet();
3810
- const encode = /* @__PURE__ */ __name3((v) => {
3966
+ const encode = /* @__PURE__ */ __name4((v) => {
3811
3967
  if (v === null || typeof v === "number" || typeof v === "boolean") return JSON.stringify(v);
3812
3968
  if (typeof v === "string") return JSON.stringify(v);
3813
3969
  if (typeof v === "bigint") return JSON.stringify(`${v}n`);
@@ -3834,7 +3990,7 @@ function hashGraph(g) {
3834
3990
  function compilePlan(g) {
3835
3991
  const steps = {};
3836
3992
  const order = [];
3837
- const addNode = /* @__PURE__ */ __name3((id, node) => {
3993
+ const addNode = /* @__PURE__ */ __name4((id, node) => {
3838
3994
  if (id in steps) {
3839
3995
  throw new WorkflowPlanError("duplicate-step-id", `Duplicate step id "${id}" in definition.graph`);
3840
3996
  }
@@ -4164,7 +4320,7 @@ function renderRef(ref) {
4164
4320
  function step(s) {
4165
4321
  const id = stepIdOf(s);
4166
4322
  return {
4167
- path: /* @__PURE__ */ __name3((p) => ({
4323
+ path: /* @__PURE__ */ __name4((p) => ({
4168
4324
  path: p === "" ? `stepResults.${id}` : `stepResults.${id}.${p}`
4169
4325
  }), "path")
4170
4326
  };
@@ -4252,7 +4408,7 @@ function resolvePlacements(calls) {
4252
4408
  const declared = /* @__PURE__ */ new Map();
4253
4409
  const placedBy = /* @__PURE__ */ new Map();
4254
4410
  const allIds = /* @__PURE__ */ new Map();
4255
- const claimId = /* @__PURE__ */ __name3((id, callIndex) => {
4411
+ const claimId = /* @__PURE__ */ __name4((id, callIndex) => {
4256
4412
  const first = allIds.get(id);
4257
4413
  if (first !== void 0 && first !== callIndex) {
4258
4414
  issues.push({
@@ -4292,7 +4448,7 @@ function resolvePlacements(calls) {
4292
4448
  break;
4293
4449
  }
4294
4450
  });
4295
- const armMapPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
4451
+ const armMapPlacementIssue = /* @__PURE__ */ __name4((node, ref, i, container) => {
4296
4452
  if (!ref.armMap || node.type === "mapping" || isHitlNode2(node)) return void 0;
4297
4453
  const id = nodeIdOf(node);
4298
4454
  if ((container === "foreach" || container === "loop") && node.type !== "workflow") {
@@ -4313,7 +4469,7 @@ function resolvePlacements(calls) {
4313
4469
  }
4314
4470
  return void 0;
4315
4471
  }, "armMapPlacementIssue");
4316
- const hitlPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
4472
+ const hitlPlacementIssue = /* @__PURE__ */ __name4((node, ref, i, container) => {
4317
4473
  if (!isHitlNode2(node)) return void 0;
4318
4474
  const id = node.id;
4319
4475
  if (ref.armMap) {
@@ -4334,7 +4490,7 @@ function resolvePlacements(calls) {
4334
4490
  }
4335
4491
  return void 0;
4336
4492
  }, "hitlPlacementIssue");
4337
- const resolve3 = /* @__PURE__ */ __name3((ref, i, allowMapping, container) => {
4493
+ const resolve3 = /* @__PURE__ */ __name4((ref, i, allowMapping, container) => {
4338
4494
  if ("node" in ref) {
4339
4495
  if (ref.node.type === "mapping" && !allowMapping) {
4340
4496
  issues.push({
@@ -4389,7 +4545,7 @@ function resolvePlacements(calls) {
4389
4545
  placedBy.set(ref.ref, i);
4390
4546
  return d.node;
4391
4547
  }, "resolve");
4392
- const claim = /* @__PURE__ */ __name3((ref, i, allowMapping, container) => {
4548
+ const claim = /* @__PURE__ */ __name4((ref, i, allowMapping, container) => {
4393
4549
  if ("ref" in ref) {
4394
4550
  resolve3(ref, i, allowMapping, container);
4395
4551
  return;
@@ -4424,7 +4580,7 @@ function resolvePlacements(calls) {
4424
4580
  }
4425
4581
  });
4426
4582
  const graph = [];
4427
- const lookup = /* @__PURE__ */ __name3((ref) => {
4583
+ const lookup = /* @__PURE__ */ __name4((ref) => {
4428
4584
  const n2 = "node" in ref ? ref.node : declared.get(ref.ref)?.node;
4429
4585
  if (!n2 || !ref.armMap || n2.type === "mapping" || isHitlNode2(n2)) return n2;
4430
4586
  return inlineContainerArm(ref.armMap, n2);
@@ -4567,11 +4723,11 @@ function seedLedgerFromRun(run, steps, targetPlan, opts = {}) {
4567
4723
  const seeded = [];
4568
4724
  const unseeded = [];
4569
4725
  const known = new Set(Object.keys(targetPlan.steps));
4570
- const parentOf = /* @__PURE__ */ __name3((id) => {
4726
+ const parentOf = /* @__PURE__ */ __name4((id) => {
4571
4727
  const m = /^(.*)(\[\d+\]|#\d+)$/.exec(id);
4572
4728
  return m ? m[1] : void 0;
4573
4729
  }, "parentOf");
4574
- const dependsOf = /* @__PURE__ */ __name3((id) => {
4730
+ const dependsOf = /* @__PURE__ */ __name4((id) => {
4575
4731
  const node = targetPlan.steps[id];
4576
4732
  if (node) return node.dependsOn;
4577
4733
  const parent = parentOf(id);
@@ -4658,7 +4814,7 @@ function replayLedger(g, ledger) {
4658
4814
  startedAt: 0,
4659
4815
  ...ledger.requestContext
4660
4816
  };
4661
- const ctxFor = /* @__PURE__ */ __name3((id) => ({
4817
+ const ctxFor = /* @__PURE__ */ __name4((id) => ({
4662
4818
  initData: ledger.initData,
4663
4819
  stepResults: ancestorResults(plan, id, rows22),
4664
4820
  state: ledger.state ?? {},
@@ -4740,7 +4896,7 @@ function ancestorResults(plan, id, rows22) {
4740
4896
  const out = {};
4741
4897
  const joinAliased = /* @__PURE__ */ new Set();
4742
4898
  const seen = /* @__PURE__ */ new Set();
4743
- const take = /* @__PURE__ */ __name3((rowId) => {
4899
+ const take = /* @__PURE__ */ __name4((rowId) => {
4744
4900
  const hit = replayResultOf(rows22.get(rowId), plan.steps[rowId]);
4745
4901
  if (!hit) return void 0;
4746
4902
  if (!joinAliased.has(rowId)) out[rowId] = hit.value;
@@ -4757,7 +4913,7 @@ function ancestorResults(plan, id, rows22) {
4757
4913
  }
4758
4914
  return hit;
4759
4915
  }, "take");
4760
- const walk22 = /* @__PURE__ */ __name3((ids) => {
4916
+ const walk22 = /* @__PURE__ */ __name4((ids) => {
4761
4917
  for (const dep of ids) {
4762
4918
  if (seen.has(dep)) continue;
4763
4919
  seen.add(dep);
@@ -5111,7 +5267,7 @@ function timeZoneSupported(tz) {
5111
5267
  }
5112
5268
  function validateBusinessHours(cal, path3 = "businessHours") {
5113
5269
  const issues = [];
5114
- const issue = /* @__PURE__ */ __name3((p, message) => issues.push({
5270
+ const issue = /* @__PURE__ */ __name4((p, message) => issues.push({
5115
5271
  code: "business-hours-invalid",
5116
5272
  path: p,
5117
5273
  message
@@ -5180,7 +5336,7 @@ function formatter(tz) {
5180
5336
  }
5181
5337
  function localParts(ms, tz) {
5182
5338
  const parts = formatter(tz).formatToParts(new Date(ms));
5183
- const get = /* @__PURE__ */ __name3((t) => parts.find((p) => p.type === t)?.value ?? "", "get");
5339
+ const get = /* @__PURE__ */ __name4((t) => parts.find((p) => p.type === t)?.value ?? "", "get");
5184
5340
  const hour = Number(get("hour")) % 24;
5185
5341
  return {
5186
5342
  year: Number(get("year")),
@@ -5350,7 +5506,7 @@ function matchesEditablePath(pointer, editablePaths, op = "replace") {
5350
5506
  }
5351
5507
  function changedPointers(before, after, base = "") {
5352
5508
  if (before === after) return [];
5353
- const isObj = /* @__PURE__ */ __name3((v) => typeof v === "object" && v !== null && !Array.isArray(v), "isObj");
5509
+ const isObj = /* @__PURE__ */ __name4((v) => typeof v === "object" && v !== null && !Array.isArray(v), "isObj");
5354
5510
  if (Array.isArray(before) && Array.isArray(after)) {
5355
5511
  if (before.length !== after.length) return [
5356
5512
  base || "/"
@@ -5556,9 +5712,59 @@ function rebaseItemPointer(pointer, itemsPath, index) {
5556
5712
  const base = `/${itemsPath.split(".").map(escapePointer).join("/")}/${index}`;
5557
5713
  return pointer === "/" || pointer === "" ? base : `${base}${pointer}`;
5558
5714
  }
5715
+ function validateWorkflowSchedule(schedule, path3 = "/schedule") {
5716
+ if (schedule === void 0 || schedule === null) return [];
5717
+ const issue = /* @__PURE__ */ __name4((at, detail) => [
5718
+ {
5719
+ code: WORKFLOW_SCHEDULE_SHAPE_ISSUE,
5720
+ severity: "error",
5721
+ path: at,
5722
+ message: `${detail} \u2014 ${WORKFLOW_SCHEDULE_SHAPES_HINT}`
5723
+ }
5724
+ ], "issue");
5725
+ if (!isObject(schedule)) {
5726
+ return issue(path3, `\`schedule\` is ${Array.isArray(schedule) ? "an array" : `a ${typeof schedule}`}, not a typed schedule object`);
5727
+ }
5728
+ const type = schedule.type;
5729
+ if (type === void 0) {
5730
+ const keys = Object.keys(schedule);
5731
+ const seen = keys.length ? ` (got { ${keys.join(", ")} })` : " (got {})";
5732
+ return issue(path3, `\`schedule\` carries no \`type\` discriminator${seen}`);
5733
+ }
5734
+ if (typeof type !== "string" || !WORKFLOW_SCHEDULE_TYPES.includes(type)) {
5735
+ return issue(path3, `\`schedule.type\` ${JSON.stringify(type)} is not one of ${WORKFLOW_SCHEDULE_TYPES.map((t) => `'${t}'`).join(" | ")}`);
5736
+ }
5737
+ if (schedule.runAs !== void 0 && !WORKFLOW_SCHEDULE_RUN_AS.includes(schedule.runAs)) {
5738
+ return issue(`${path3}/runAs`, `\`schedule.runAs\` ${JSON.stringify(schedule.runAs)} is not one of ${WORKFLOW_SCHEDULE_RUN_AS.map((v) => `'${v}'`).join(" | ")}`);
5739
+ }
5740
+ switch (type) {
5741
+ case "cron": {
5742
+ if (typeof schedule.expression !== "string" || schedule.expression.trim().length === 0) {
5743
+ return issue(`${path3}/expression`, "a { type: 'cron' } schedule needs a non-empty string `expression`");
5744
+ }
5745
+ if (schedule.timezone !== void 0 && (typeof schedule.timezone !== "string" || schedule.timezone.length === 0)) {
5746
+ return issue(`${path3}/timezone`, "a { type: 'cron' } schedule's `timezone`, when given, is a non-empty IANA string");
5747
+ }
5748
+ return [];
5749
+ }
5750
+ case "interval": {
5751
+ const s = schedule.seconds;
5752
+ if (typeof s !== "number" || !Number.isFinite(s) || s <= 0) {
5753
+ return issue(`${path3}/seconds`, "a { type: 'interval' } schedule needs a positive number `seconds`");
5754
+ }
5755
+ return [];
5756
+ }
5757
+ case "once": {
5758
+ if (typeof schedule.executeAt !== "string" || Number.isNaN(Date.parse(schedule.executeAt))) {
5759
+ return issue(`${path3}/executeAt`, "a { type: 'once' } schedule needs an ISO-8601 string `executeAt`");
5760
+ }
5761
+ return [];
5762
+ }
5763
+ }
5764
+ }
5559
5765
  function collectEnvTemplateKeys(value22) {
5560
5766
  const keys = /* @__PURE__ */ new Set();
5561
- const walk22 = /* @__PURE__ */ __name3((v) => {
5767
+ const walk22 = /* @__PURE__ */ __name4((v) => {
5562
5768
  if (isEnvRef(v)) {
5563
5769
  keys.add(v.__envRef);
5564
5770
  return;
@@ -5585,7 +5791,7 @@ function collectEnvTemplateKeys(value22) {
5585
5791
  }
5586
5792
  function substituteEnvRefs(value22, overlay) {
5587
5793
  const missing = /* @__PURE__ */ new Set();
5588
- const walk22 = /* @__PURE__ */ __name3((v, slot = false) => {
5794
+ const walk22 = /* @__PURE__ */ __name4((v, slot = false) => {
5589
5795
  if (isEnvRef(v)) {
5590
5796
  if (Object.prototype.hasOwnProperty.call(overlay, v.__envRef)) {
5591
5797
  const s = overlay[v.__envRef];
@@ -5845,25 +6051,27 @@ function needsInheritedWorkspace(graph) {
5845
6051
  }
5846
6052
  return false;
5847
6053
  }
5848
- 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;
6054
+ var __defProp4, __name4, 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_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_SCHEDULE_TYPES, WORKFLOW_SCHEDULE_SHAPE_ISSUE, WORKFLOW_SCHEDULE_SHAPES_HINT, WORKFLOW_SCHEDULE_RUN_AS, isObject, WORKFLOW_ENV_OVERLAY_MAX_KEYS, WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES, WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE, isEnvRef, looksLikeEmbeddedJson, ZERO, isRecord2;
5849
6055
  var init_dist2 = __esm({
5850
6056
  "../workflow-graph/dist/index.mjs"() {
5851
6057
  "use strict";
5852
6058
  init_dist();
5853
6059
  init_dist();
5854
6060
  init_dist();
6061
+ init_workflow_job_tools();
6062
+ init_workflow_job_tools();
5855
6063
  init_dist();
5856
6064
  init_dist();
5857
6065
  init_dist();
5858
6066
  init_dist();
5859
- __defProp3 = Object.defineProperty;
5860
- __name3 = /* @__PURE__ */ __name((target, value22) => __defProp3(target, "name", { value: value22, configurable: true }), "__name");
6067
+ __defProp4 = Object.defineProperty;
6068
+ __name4 = /* @__PURE__ */ __name((target, value22) => __defProp4(target, "name", { value: value22, configurable: true }), "__name");
5861
6069
  WorkflowTemplateError = class extends Error {
5862
6070
  static {
5863
6071
  __name(this, "WorkflowTemplateError");
5864
6072
  }
5865
6073
  static {
5866
- __name3(this, "WorkflowTemplateError");
6074
+ __name4(this, "WorkflowTemplateError");
5867
6075
  }
5868
6076
  placeholder;
5869
6077
  constructor(message, placeholder) {
@@ -5872,11 +6080,11 @@ var init_dist2 = __esm({
5872
6080
  }
5873
6081
  };
5874
6082
  __name(isMapConfigObject, "isMapConfigObject");
5875
- __name3(isMapConfigObject, "isMapConfigObject");
6083
+ __name4(isMapConfigObject, "isMapConfigObject");
5876
6084
  __name(parseMapConfig, "parseMapConfig");
5877
- __name3(parseMapConfig, "parseMapConfig");
6085
+ __name4(parseMapConfig, "parseMapConfig");
5878
6086
  __name(mapConfigWire, "mapConfigWire");
5879
- __name3(mapConfigWire, "mapConfigWire");
6087
+ __name4(mapConfigWire, "mapConfigWire");
5880
6088
  TEMPLATE_PLACEHOLDER = /\$\{([^}]*)\}/g;
5881
6089
  TEMPLATE_NAMESPACES = [
5882
6090
  "initData",
@@ -5885,21 +6093,21 @@ var init_dist2 = __esm({
5885
6093
  "stepResults"
5886
6094
  ];
5887
6095
  __name(describeBadPlaceholder, "describeBadPlaceholder");
5888
- __name3(describeBadPlaceholder, "describeBadPlaceholder");
6096
+ __name4(describeBadPlaceholder, "describeBadPlaceholder");
5889
6097
  __name(parseTemplatePlaceholder, "parseTemplatePlaceholder");
5890
- __name3(parseTemplatePlaceholder, "parseTemplatePlaceholder");
6098
+ __name4(parseTemplatePlaceholder, "parseTemplatePlaceholder");
5891
6099
  __name(traverseMappingPath, "traverseMappingPath");
5892
- __name3(traverseMappingPath, "traverseMappingPath");
6100
+ __name4(traverseMappingPath, "traverseMappingPath");
5893
6101
  __name(stringifyTemplateValue, "stringifyTemplateValue");
5894
- __name3(stringifyTemplateValue, "stringifyTemplateValue");
6102
+ __name4(stringifyTemplateValue, "stringifyTemplateValue");
5895
6103
  __name(escapeFence, "escapeFence");
5896
- __name3(escapeFence, "escapeFence");
6104
+ __name4(escapeFence, "escapeFence");
5897
6105
  __name(fenceBlock, "fenceBlock");
5898
- __name3(fenceBlock, "fenceBlock");
6106
+ __name4(fenceBlock, "fenceBlock");
5899
6107
  __name(renderTemplate, "renderTemplate");
5900
- __name3(renderTemplate, "renderTemplate");
6108
+ __name4(renderTemplate, "renderTemplate");
5901
6109
  __name(isMapDescriptor, "isMapDescriptor");
5902
- __name3(isMapDescriptor, "isMapDescriptor");
6110
+ __name4(isMapDescriptor, "isMapDescriptor");
5903
6111
  MAP_DESCRIPTOR_KEYS = [
5904
6112
  "step",
5905
6113
  "path",
@@ -5911,39 +6119,39 @@ var init_dist2 = __esm({
5911
6119
  ];
5912
6120
  MAP_MEMBER_MALFORMED_CODE = "map-member-malformed";
5913
6121
  __name(malformedMapMembers, "malformedMapMembers");
5914
- __name3(malformedMapMembers, "malformedMapMembers");
6122
+ __name4(malformedMapMembers, "malformedMapMembers");
5915
6123
  __name(mapMemberMalformedMessage, "mapMemberMalformedMessage");
5916
- __name3(mapMemberMalformedMessage, "mapMemberMalformedMessage");
6124
+ __name4(mapMemberMalformedMessage, "mapMemberMalformedMessage");
5917
6125
  __name(resolveDescriptor, "resolveDescriptor");
5918
- __name3(resolveDescriptor, "resolveDescriptor");
6126
+ __name4(resolveDescriptor, "resolveDescriptor");
5919
6127
  __name(resolveMapping, "resolveMapping");
5920
- __name3(resolveMapping, "resolveMapping");
5921
- fromInit = /* @__PURE__ */ __name3((path3) => ({
6128
+ __name4(resolveMapping, "resolveMapping");
6129
+ fromInit = /* @__PURE__ */ __name4((path3) => ({
5922
6130
  initData: true,
5923
6131
  path: path3
5924
6132
  }), "fromInit");
5925
- fromStep = /* @__PURE__ */ __name3((s, path3 = "") => {
5926
- const idOf = /* @__PURE__ */ __name3((x) => typeof x === "string" ? x : x.id, "idOf");
6133
+ fromStep = /* @__PURE__ */ __name4((s, path3 = "") => {
6134
+ const idOf = /* @__PURE__ */ __name4((x) => typeof x === "string" ? x : x.id, "idOf");
5927
6135
  return {
5928
6136
  step: Array.isArray(s) ? s.map(idOf) : idOf(s),
5929
6137
  path: path3
5930
6138
  };
5931
6139
  }, "fromStep");
5932
- value = /* @__PURE__ */ __name3((v) => ({
6140
+ value = /* @__PURE__ */ __name4((v) => ({
5933
6141
  value: v
5934
6142
  }), "value");
5935
- template = /* @__PURE__ */ __name3((s) => ({
6143
+ template = /* @__PURE__ */ __name4((s) => ({
5936
6144
  template: s
5937
6145
  }), "template");
5938
- fromRequest = /* @__PURE__ */ __name3((path3) => ({
6146
+ fromRequest = /* @__PURE__ */ __name4((path3) => ({
5939
6147
  requestContextPath: path3
5940
6148
  }), "fromRequest");
5941
- rows = /* @__PURE__ */ __name3((s, path3, page) => ({
6149
+ rows = /* @__PURE__ */ __name4((s, path3, page) => ({
5942
6150
  step: typeof s === "string" ? s : s.id,
5943
6151
  path: path3,
5944
6152
  rows: page
5945
6153
  }), "rows");
5946
- fromKnowledge = /* @__PURE__ */ __name3((k) => ({
6154
+ fromKnowledge = /* @__PURE__ */ __name4((k) => ({
5947
6155
  knowledge: k
5948
6156
  }), "fromKnowledge");
5949
6157
  SideEffectsSchema = z4.enum(WORKFLOW_SIDE_EFFECTS);
@@ -6013,7 +6221,7 @@ var init_dist2 = __esm({
6013
6221
  APPROVER_WRITTEN_MAX = 120;
6014
6222
  USER_ID_SHAPED_RE = /^[^\s@]{1,128}$/;
6015
6223
  __name(describeApproverSpecRefusal, "describeApproverSpecRefusal");
6016
- __name3(describeApproverSpecRefusal, "describeApproverSpecRefusal");
6224
+ __name4(describeApproverSpecRefusal, "describeApproverSpecRefusal");
6017
6225
  BINDING_ROOTS = [
6018
6226
  "initData",
6019
6227
  "stepResults",
@@ -6021,28 +6229,28 @@ var init_dist2 = __esm({
6021
6229
  "state"
6022
6230
  ];
6023
6231
  __name(bindingRootsOk, "bindingRootsOk");
6024
- __name3(bindingRootsOk, "bindingRootsOk");
6232
+ __name4(bindingRootsOk, "bindingRootsOk");
6025
6233
  __name(isTemplateBinding, "isTemplateBinding");
6026
- __name3(isTemplateBinding, "isTemplateBinding");
6234
+ __name4(isTemplateBinding, "isTemplateBinding");
6027
6235
  __name(approvalEditable, "approvalEditable");
6028
- __name3(approvalEditable, "approvalEditable");
6236
+ __name4(approvalEditable, "approvalEditable");
6029
6237
  __name(validateApproverBlock, "validateApproverBlock");
6030
- __name3(validateApproverBlock, "validateApproverBlock");
6238
+ __name4(validateApproverBlock, "validateApproverBlock");
6031
6239
  __name(liftRenderedApprover, "liftRenderedApprover");
6032
- __name3(liftRenderedApprover, "liftRenderedApprover");
6240
+ __name4(liftRenderedApprover, "liftRenderedApprover");
6033
6241
  WORKSPACE_TEMPLATE_EXPR_RE = /^\$\{\s*(?:initData|input)\.([^}]+?)\s*\}$/;
6034
6242
  __name(workspaceTemplatePath, "workspaceTemplatePath");
6035
- __name3(workspaceTemplatePath, "workspaceTemplatePath");
6243
+ __name4(workspaceTemplatePath, "workspaceTemplatePath");
6036
6244
  __name(retryBackoffs, "retryBackoffs");
6037
- __name3(retryBackoffs, "retryBackoffs");
6245
+ __name4(retryBackoffs, "retryBackoffs");
6038
6246
  SLEEP_UNTIL_REPLACEMENT = Object.freeze({
6039
6247
  type: "sleep",
6040
6248
  duration: 6e4
6041
6249
  });
6042
6250
  __name(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
6043
- __name3(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
6251
+ __name4(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
6044
6252
  __name(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
6045
- __name3(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
6253
+ __name4(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
6046
6254
  WORKFLOW_CAPS_DEFAULT = Object.freeze({
6047
6255
  maxParallelArms: 16,
6048
6256
  maxForeachConcurrency: 16,
@@ -6067,71 +6275,60 @@ var init_dist2 = __esm({
6067
6275
  "api",
6068
6276
  "user"
6069
6277
  ];
6070
- clone = /* @__PURE__ */ __name3((v) => JSON.parse(JSON.stringify(v)), "clone");
6278
+ clone = /* @__PURE__ */ __name4((v) => JSON.parse(JSON.stringify(v)), "clone");
6071
6279
  __name(fillPolicy, "fillPolicy");
6072
- __name3(fillPolicy, "fillPolicy");
6280
+ __name4(fillPolicy, "fillPolicy");
6073
6281
  __name(fillSingle, "fillSingle");
6074
- __name3(fillSingle, "fillSingle");
6282
+ __name4(fillSingle, "fillSingle");
6075
6283
  __name(fillHitl, "fillHitl");
6076
- __name3(fillHitl, "fillHitl");
6284
+ __name4(fillHitl, "fillHitl");
6077
6285
  __name(fillArm, "fillArm");
6078
- __name3(fillArm, "fillArm");
6286
+ __name4(fillArm, "fillArm");
6079
6287
  __name(fillEntry, "fillEntry");
6080
- __name3(fillEntry, "fillEntry");
6288
+ __name4(fillEntry, "fillEntry");
6081
6289
  __name(withDefaultsFilled, "withDefaultsFilled");
6082
- __name3(withDefaultsFilled, "withDefaultsFilled");
6290
+ __name4(withDefaultsFilled, "withDefaultsFilled");
6083
6291
  CONNECTION_ID_HEX_RE = /^[0-9a-f]{24}$/;
6084
6292
  __name(isConnectionKeyShaped, "isConnectionKeyShaped");
6085
- __name3(isConnectionKeyShaped, "isConnectionKeyShaped");
6293
+ __name4(isConnectionKeyShaped, "isConnectionKeyShaped");
6086
6294
  __name(connectionKeyUndeclaredMessage, "connectionKeyUndeclaredMessage");
6087
- __name3(connectionKeyUndeclaredMessage, "connectionKeyUndeclaredMessage");
6088
- WORKFLOW_JOB_TOOLS = [
6089
- "shell",
6090
- "read",
6091
- "write",
6092
- "edit",
6093
- "glob",
6094
- "grep",
6095
- "git",
6096
- "gh",
6097
- "fetch"
6098
- ];
6295
+ __name4(connectionKeyUndeclaredMessage, "connectionKeyUndeclaredMessage");
6099
6296
  WORKFLOW_JOB_MAX_WORKTREE_ARMS = 8;
6100
6297
  __name(classifyModelProvider, "classifyModelProvider");
6101
- __name3(classifyModelProvider, "classifyModelProvider");
6102
- workspaceOf = /* @__PURE__ */ __name3((node) => node.workspace, "workspaceOf");
6103
- mountsWorkspace = /* @__PURE__ */ __name3((node) => {
6298
+ __name4(classifyModelProvider, "classifyModelProvider");
6299
+ workspaceOf = /* @__PURE__ */ __name4((node) => node.workspace, "workspaceOf");
6300
+ mountsWorkspace = /* @__PURE__ */ __name4((node) => {
6104
6301
  const w = workspaceOf(node);
6105
6302
  return w !== void 0 && w !== "inherit";
6106
6303
  }, "mountsWorkspace");
6107
- isJobTier = /* @__PURE__ */ __name3((node) => node.tier === "job" || mountsWorkspace(node), "isJobTier");
6108
- jobToolsOf = /* @__PURE__ */ __name3((node) => {
6304
+ isJobTier = /* @__PURE__ */ __name4((node) => node.tier === "job" || mountsWorkspace(node), "isJobTier");
6305
+ jobToolsOf = /* @__PURE__ */ __name4((node) => {
6109
6306
  if (node.type === "agent") return node.toolScope?.jobTools;
6110
6307
  return node.jobTools;
6111
6308
  }, "jobToolsOf");
6112
6309
  __name(schemaAtPath, "schemaAtPath");
6113
- __name3(schemaAtPath, "schemaAtPath");
6114
- schemaIsArray = /* @__PURE__ */ __name3((schema) => {
6310
+ __name4(schemaAtPath, "schemaAtPath");
6311
+ schemaIsArray = /* @__PURE__ */ __name4((schema) => {
6115
6312
  if (!schema) return void 0;
6116
6313
  const t = schema.type;
6117
6314
  if (t === void 0) return void 0;
6118
6315
  return Array.isArray(t) ? t.includes("array") : t === "array";
6119
6316
  }, "schemaIsArray");
6120
- isHitlNode = /* @__PURE__ */ __name3((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6121
- isSingleStep = /* @__PURE__ */ __name3((n2) => !isHitlNode(n2), "isSingleStep");
6122
- singleId = /* @__PURE__ */ __name3((s) => s.type === "step" ? s.step.id : s.id, "singleId");
6123
- armId = /* @__PURE__ */ __name3((a) => a.type === "mapping" ? a.id : singleId(a), "armId");
6317
+ isHitlNode = /* @__PURE__ */ __name4((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6318
+ isSingleStep = /* @__PURE__ */ __name4((n2) => !isHitlNode(n2), "isSingleStep");
6319
+ singleId = /* @__PURE__ */ __name4((s) => s.type === "step" ? s.step.id : s.id, "singleId");
6320
+ armId = /* @__PURE__ */ __name4((a) => a.type === "mapping" ? a.id : singleId(a), "armId");
6124
6321
  TEMPLATE_STEP_REF = /\$\{\s*stepResults\.([A-Za-z0-9_\-]+)/g;
6125
6322
  __name(templateStepRefs, "templateStepRefs");
6126
- __name3(templateStepRefs, "templateStepRefs");
6323
+ __name4(templateStepRefs, "templateStepRefs");
6127
6324
  __name(readMapConfig, "readMapConfig");
6128
- __name3(readMapConfig, "readMapConfig");
6325
+ __name4(readMapConfig, "readMapConfig");
6129
6326
  __name(mapConfigStepRefs, "mapConfigStepRefs");
6130
- __name3(mapConfigStepRefs, "mapConfigStepRefs");
6327
+ __name4(mapConfigStepRefs, "mapConfigStepRefs");
6131
6328
  __name(nodeStepRefs, "nodeStepRefs");
6132
- __name3(nodeStepRefs, "nodeStepRefs");
6329
+ __name4(nodeStepRefs, "nodeStepRefs");
6133
6330
  __name(validateLuaExtensions, "validateLuaExtensions");
6134
- __name3(validateLuaExtensions, "validateLuaExtensions");
6331
+ __name4(validateLuaExtensions, "validateLuaExtensions");
6135
6332
  EDITABLE_PATH_RE = /^[A-Za-z_][A-Za-z0-9_]*(\[(\*|\d+)\])?(\.[A-Za-z_][A-Za-z0-9_]*(\[(\*|\d+)\])?)*$/;
6136
6333
  PREDICATE_OPS = /* @__PURE__ */ new Set([
6137
6334
  "eq",
@@ -6151,23 +6348,23 @@ var init_dist2 = __esm({
6151
6348
  "not"
6152
6349
  ]);
6153
6350
  __name(isPredicate, "isPredicate");
6154
- __name3(isPredicate, "isPredicate");
6155
- isPredicateScalar = /* @__PURE__ */ __name3((v) => v === null || typeof v === "string" || typeof v === "number" || typeof v === "boolean", "isPredicateScalar");
6351
+ __name4(isPredicate, "isPredicate");
6352
+ isPredicateScalar = /* @__PURE__ */ __name4((v) => v === null || typeof v === "string" || typeof v === "number" || typeof v === "boolean", "isPredicateScalar");
6156
6353
  __name(isPathOrLiteral, "isPathOrLiteral");
6157
- __name3(isPathOrLiteral, "isPathOrLiteral");
6354
+ __name4(isPathOrLiteral, "isPathOrLiteral");
6158
6355
  __name(isWellFormedPredicate, "isWellFormedPredicate");
6159
- __name3(isWellFormedPredicate, "isWellFormedPredicate");
6356
+ __name4(isWellFormedPredicate, "isWellFormedPredicate");
6160
6357
  GRAPH_HASH_PREFIX = "sha256-cj1:";
6161
6358
  __name(canonicalJson, "canonicalJson");
6162
- __name3(canonicalJson, "canonicalJson");
6359
+ __name4(canonicalJson, "canonicalJson");
6163
6360
  __name(hashGraph, "hashGraph");
6164
- __name3(hashGraph, "hashGraph");
6361
+ __name4(hashGraph, "hashGraph");
6165
6362
  WorkflowPlanError = class extends Error {
6166
6363
  static {
6167
6364
  __name(this, "WorkflowPlanError");
6168
6365
  }
6169
6366
  static {
6170
- __name3(this, "WorkflowPlanError");
6367
+ __name4(this, "WorkflowPlanError");
6171
6368
  }
6172
6369
  code;
6173
6370
  constructor(code, message) {
@@ -6175,47 +6372,47 @@ var init_dist2 = __esm({
6175
6372
  this.name = "WorkflowPlanError";
6176
6373
  }
6177
6374
  };
6178
- isArmStep = /* @__PURE__ */ __name3((e) => isWorkflowArmEntryType(e.type), "isArmStep");
6179
- armStepId = /* @__PURE__ */ __name3((e) => e.type === "step" ? e.step.id : e.id, "armStepId");
6180
- armStepKind = /* @__PURE__ */ __name3((e) => WORKFLOW_ARM_ENTRY_STEP_KINDS[e.type], "armStepKind");
6181
- joinIdOf = /* @__PURE__ */ __name3((entryId) => `${entryId}.join`, "joinIdOf");
6182
- containerIdOf = /* @__PURE__ */ __name3((type, entryIndex) => `${type}@${entryIndex}`, "containerIdOf");
6375
+ isArmStep = /* @__PURE__ */ __name4((e) => isWorkflowArmEntryType(e.type), "isArmStep");
6376
+ armStepId = /* @__PURE__ */ __name4((e) => e.type === "step" ? e.step.id : e.id, "armStepId");
6377
+ armStepKind = /* @__PURE__ */ __name4((e) => WORKFLOW_ARM_ENTRY_STEP_KINDS[e.type], "armStepKind");
6378
+ joinIdOf = /* @__PURE__ */ __name4((entryId) => `${entryId}.join`, "joinIdOf");
6379
+ containerIdOf = /* @__PURE__ */ __name4((type, entryIndex) => `${type}@${entryIndex}`, "containerIdOf");
6183
6380
  __name(compilePlan, "compilePlan");
6184
- __name3(compilePlan, "compilePlan");
6381
+ __name4(compilePlan, "compilePlan");
6185
6382
  PATH_PLACEHOLDER = /^\$\{([^}]+)\}$/;
6186
6383
  MISSING = /* @__PURE__ */ Symbol("predicate.missing");
6187
6384
  __name(resolvePath, "resolvePath");
6188
- __name3(resolvePath, "resolvePath");
6385
+ __name4(resolvePath, "resolvePath");
6189
6386
  __name(walk, "walk");
6190
- __name3(walk, "walk");
6387
+ __name4(walk, "walk");
6191
6388
  __name(resolveValue, "resolveValue");
6192
- __name3(resolveValue, "resolveValue");
6389
+ __name4(resolveValue, "resolveValue");
6193
6390
  __name(evaluatePredicate, "evaluatePredicate");
6194
- __name3(evaluatePredicate, "evaluatePredicate");
6391
+ __name4(evaluatePredicate, "evaluatePredicate");
6195
6392
  __name(compare, "compare");
6196
- __name3(compare, "compare");
6393
+ __name4(compare, "compare");
6197
6394
  __name(derivePredicateLabel, "derivePredicateLabel");
6198
- __name3(derivePredicateLabel, "derivePredicateLabel");
6395
+ __name4(derivePredicateLabel, "derivePredicateLabel");
6199
6396
  __name(renderPredicate, "renderPredicate");
6200
- __name3(renderPredicate, "renderPredicate");
6397
+ __name4(renderPredicate, "renderPredicate");
6201
6398
  __name(wrapLabel, "wrapLabel");
6202
- __name3(wrapLabel, "wrapLabel");
6399
+ __name4(wrapLabel, "wrapLabel");
6203
6400
  __name(renderRef, "renderRef");
6204
- __name3(renderRef, "renderRef");
6205
- stepIdOf = /* @__PURE__ */ __name3((s) => typeof s === "string" ? s : s.id, "stepIdOf");
6401
+ __name4(renderRef, "renderRef");
6402
+ stepIdOf = /* @__PURE__ */ __name4((s) => typeof s === "string" ? s : s.id, "stepIdOf");
6206
6403
  __name(step, "step");
6207
- __name3(step, "step");
6404
+ __name4(step, "step");
6208
6405
  __name(stepOf, "stepOf");
6209
- __name3(stepOf, "stepOf");
6406
+ __name4(stepOf, "stepOf");
6210
6407
  __name(init, "init");
6211
- __name3(init, "init");
6408
+ __name4(init, "init");
6212
6409
  __name(state, "state");
6213
- __name3(state, "state");
6410
+ __name4(state, "state");
6214
6411
  __name(lit, "lit");
6215
- __name3(lit, "lit");
6412
+ __name4(lit, "lit");
6216
6413
  __name(toPathOrLiteral, "toPathOrLiteral");
6217
- __name3(toPathOrLiteral, "toPathOrLiteral");
6218
- cmp = /* @__PURE__ */ __name3((op) => (l, r) => ({
6414
+ __name4(toPathOrLiteral, "toPathOrLiteral");
6415
+ cmp = /* @__PURE__ */ __name4((op) => (l, r) => ({
6219
6416
  op,
6220
6417
  left: toPathOrLiteral(l),
6221
6418
  right: toPathOrLiteral(r)
@@ -6226,49 +6423,49 @@ var init_dist2 = __esm({
6226
6423
  gte = cmp("gte");
6227
6424
  lt = cmp("lt");
6228
6425
  lte = cmp("lte");
6229
- inSet = /* @__PURE__ */ __name3((v, set) => ({
6426
+ inSet = /* @__PURE__ */ __name4((v, set) => ({
6230
6427
  op: "in",
6231
6428
  value: {
6232
6429
  path: v.path
6233
6430
  },
6234
6431
  set
6235
6432
  }), "inSet");
6236
- notIn = /* @__PURE__ */ __name3((v, set) => ({
6433
+ notIn = /* @__PURE__ */ __name4((v, set) => ({
6237
6434
  op: "notIn",
6238
6435
  value: {
6239
6436
  path: v.path
6240
6437
  },
6241
6438
  set
6242
6439
  }), "notIn");
6243
- exists = /* @__PURE__ */ __name3((ref) => ({
6440
+ exists = /* @__PURE__ */ __name4((ref) => ({
6244
6441
  op: "exists",
6245
6442
  path: ref.path
6246
6443
  }), "exists");
6247
- notExists = /* @__PURE__ */ __name3((ref) => ({
6444
+ notExists = /* @__PURE__ */ __name4((ref) => ({
6248
6445
  op: "notExists",
6249
6446
  path: ref.path
6250
6447
  }), "notExists");
6251
- truthy = /* @__PURE__ */ __name3((ref) => ({
6448
+ truthy = /* @__PURE__ */ __name4((ref) => ({
6252
6449
  op: "truthy",
6253
6450
  value: {
6254
6451
  path: ref.path
6255
6452
  }
6256
6453
  }), "truthy");
6257
- falsy = /* @__PURE__ */ __name3((ref) => ({
6454
+ falsy = /* @__PURE__ */ __name4((ref) => ({
6258
6455
  op: "falsy",
6259
6456
  value: {
6260
6457
  path: ref.path
6261
6458
  }
6262
6459
  }), "falsy");
6263
- and = /* @__PURE__ */ __name3((...args) => ({
6460
+ and = /* @__PURE__ */ __name4((...args) => ({
6264
6461
  op: "and",
6265
6462
  args
6266
6463
  }), "and");
6267
- or = /* @__PURE__ */ __name3((...args) => ({
6464
+ or = /* @__PURE__ */ __name4((...args) => ({
6268
6465
  op: "or",
6269
6466
  args
6270
6467
  }), "or");
6271
- not = /* @__PURE__ */ __name3((arg) => ({
6468
+ not = /* @__PURE__ */ __name4((arg) => ({
6272
6469
  op: "not",
6273
6470
  arg
6274
6471
  }), "not");
@@ -6320,17 +6517,17 @@ var init_dist2 = __esm({
6320
6517
  "text"
6321
6518
  ]);
6322
6519
  __name(continuedFailureValue, "continuedFailureValue");
6323
- __name3(continuedFailureValue, "continuedFailureValue");
6520
+ __name4(continuedFailureValue, "continuedFailureValue");
6324
6521
  __name(isContinuedFailureValue, "isContinuedFailureValue");
6325
- __name3(isContinuedFailureValue, "isContinuedFailureValue");
6326
- isHitlNode2 = /* @__PURE__ */ __name3((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6522
+ __name4(isContinuedFailureValue, "isContinuedFailureValue");
6523
+ isHitlNode2 = /* @__PURE__ */ __name4((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6327
6524
  __name(inlineContainerArm, "inlineContainerArm");
6328
- __name3(inlineContainerArm, "inlineContainerArm");
6329
- nodeIdOf = /* @__PURE__ */ __name3((n2) => n2.type === "step" ? n2.step.id : n2.id, "nodeIdOf");
6525
+ __name4(inlineContainerArm, "inlineContainerArm");
6526
+ nodeIdOf = /* @__PURE__ */ __name4((n2) => n2.type === "step" ? n2.step.id : n2.id, "nodeIdOf");
6330
6527
  __name(entryIds, "entryIds");
6331
- __name3(entryIds, "entryIds");
6528
+ __name4(entryIds, "entryIds");
6332
6529
  __name(resolvePlacements, "resolvePlacements");
6333
- __name3(resolvePlacements, "resolvePlacements");
6530
+ __name4(resolvePlacements, "resolvePlacements");
6334
6531
  GOAL_JUDGE_STEP_ID = "__goal_judge";
6335
6532
  NON_LEAF_KINDS = /* @__PURE__ */ new Set([
6336
6533
  "foreach",
@@ -6338,26 +6535,26 @@ var init_dist2 = __esm({
6338
6535
  ]);
6339
6536
  CONDITIONAL_JOIN_ID = /^conditional@\d+\.join$/;
6340
6537
  __name(isConditionalJoinId, "isConditionalJoinId");
6341
- __name3(isConditionalJoinId, "isConditionalJoinId");
6538
+ __name4(isConditionalJoinId, "isConditionalJoinId");
6342
6539
  __name(isPlainObject, "isPlainObject");
6343
- __name3(isPlainObject, "isPlainObject");
6540
+ __name4(isPlainObject, "isPlainObject");
6344
6541
  __name(leafValue, "leafValue");
6345
- __name3(leafValue, "leafValue");
6542
+ __name4(leafValue, "leafValue");
6346
6543
  __name(runOutputLeaves, "runOutputLeaves");
6347
- __name3(runOutputLeaves, "runOutputLeaves");
6544
+ __name4(runOutputLeaves, "runOutputLeaves");
6348
6545
  __name(deriveRunOutput, "deriveRunOutput");
6349
- __name3(deriveRunOutput, "deriveRunOutput");
6546
+ __name4(deriveRunOutput, "deriveRunOutput");
6350
6547
  __name(subrunSettledOutput, "subrunSettledOutput");
6351
- __name3(subrunSettledOutput, "subrunSettledOutput");
6548
+ __name4(subrunSettledOutput, "subrunSettledOutput");
6352
6549
  __name(seedLedgerFromRun, "seedLedgerFromRun");
6353
- __name3(seedLedgerFromRun, "seedLedgerFromRun");
6354
- branchArmId = /* @__PURE__ */ __name3((arm) => arm.type === "step" ? arm.step.id : arm.id, "branchArmId");
6550
+ __name4(seedLedgerFromRun, "seedLedgerFromRun");
6551
+ branchArmId = /* @__PURE__ */ __name4((arm) => arm.type === "step" ? arm.step.id : arm.id, "branchArmId");
6355
6552
  __name(branchSpecFromConditional, "branchSpecFromConditional");
6356
- __name3(branchSpecFromConditional, "branchSpecFromConditional");
6553
+ __name4(branchSpecFromConditional, "branchSpecFromConditional");
6357
6554
  __name(selectBranchArms, "selectBranchArms");
6358
- __name3(selectBranchArms, "selectBranchArms");
6359
- canonical = /* @__PURE__ */ __name3((v) => JSON.stringify(sortKeys(v)), "canonical");
6360
- sortKeys = /* @__PURE__ */ __name3((v) => {
6555
+ __name4(selectBranchArms, "selectBranchArms");
6556
+ canonical = /* @__PURE__ */ __name4((v) => JSON.stringify(sortKeys(v)), "canonical");
6557
+ sortKeys = /* @__PURE__ */ __name4((v) => {
6361
6558
  if (Array.isArray(v)) return v.map(sortKeys);
6362
6559
  if (v && typeof v === "object") {
6363
6560
  return Object.fromEntries(Object.keys(v).sort().map((k) => [
@@ -6368,65 +6565,65 @@ var init_dist2 = __esm({
6368
6565
  return v;
6369
6566
  }, "sortKeys");
6370
6567
  __name(replayLedger, "replayLedger");
6371
- __name3(replayLedger, "replayLedger");
6568
+ __name4(replayLedger, "replayLedger");
6372
6569
  JOIN = ".join";
6373
- entryOfJoin = /* @__PURE__ */ __name3((id) => id.endsWith(JOIN) ? id.slice(0, -JOIN.length) : void 0, "entryOfJoin");
6570
+ entryOfJoin = /* @__PURE__ */ __name4((id) => id.endsWith(JOIN) ? id.slice(0, -JOIN.length) : void 0, "entryOfJoin");
6374
6571
  __name(replayResultOf, "replayResultOf");
6375
- __name3(replayResultOf, "replayResultOf");
6572
+ __name4(replayResultOf, "replayResultOf");
6376
6573
  __name(ancestorResults, "ancestorResults");
6377
- __name3(ancestorResults, "ancestorResults");
6574
+ __name4(ancestorResults, "ancestorResults");
6378
6575
  __name(inferTaken, "inferTaken");
6379
- __name3(inferTaken, "inferTaken");
6576
+ __name4(inferTaken, "inferTaken");
6380
6577
  __name(countChildren, "countChildren");
6381
- __name3(countChildren, "countChildren");
6578
+ __name4(countChildren, "countChildren");
6382
6579
  FORCE_CANCEL_STALE_MS = 10 * 60 * 1e3;
6383
6580
  TERMINAL = new Set(WORKFLOW_RUN_TERMINAL);
6384
6581
  __name(isTerminalRunStatus, "isTerminalRunStatus");
6385
- __name3(isTerminalRunStatus, "isTerminalRunStatus");
6582
+ __name4(isTerminalRunStatus, "isTerminalRunStatus");
6386
6583
  __name(pruneUndefined, "pruneUndefined");
6387
- __name3(pruneUndefined, "pruneUndefined");
6584
+ __name4(pruneUndefined, "pruneUndefined");
6388
6585
  WORKFLOW_INLINE_RUN_TAG = "inline";
6389
6586
  __name(runOrigin, "runOrigin");
6390
- __name3(runOrigin, "runOrigin");
6587
+ __name4(runOrigin, "runOrigin");
6391
6588
  RUN_ERROR_ISSUES_MAX = 20;
6392
6589
  __name(runErrorIssues, "runErrorIssues");
6393
- __name3(runErrorIssues, "runErrorIssues");
6590
+ __name4(runErrorIssues, "runErrorIssues");
6394
6591
  __name(runNextAction, "runNextAction");
6395
- __name3(runNextAction, "runNextAction");
6592
+ __name4(runNextAction, "runNextAction");
6396
6593
  IN_FLIGHT = new Set(WORKFLOW_STEP_IN_FLIGHT);
6397
6594
  __name(emptyRunCounts, "emptyRunCounts");
6398
- __name3(emptyRunCounts, "emptyRunCounts");
6595
+ __name4(emptyRunCounts, "emptyRunCounts");
6399
6596
  __name(runCountsFromStatusTally, "runCountsFromStatusTally");
6400
- __name3(runCountsFromStatusTally, "runCountsFromStatusTally");
6597
+ __name4(runCountsFromStatusTally, "runCountsFromStatusTally");
6401
6598
  __name(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6402
- __name3(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6599
+ __name4(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6403
6600
  __name(isBillingHeldStep, "isBillingHeldStep");
6404
- __name3(isBillingHeldStep, "isBillingHeldStep");
6601
+ __name4(isBillingHeldStep, "isBillingHeldStep");
6405
6602
  __name(stepEffectiveStatus, "stepEffectiveStatus");
6406
- __name3(stepEffectiveStatus, "stepEffectiveStatus");
6407
- n = /* @__PURE__ */ __name3((v) => typeof v === "number" && Number.isFinite(v) ? v : 0, "n");
6603
+ __name4(stepEffectiveStatus, "stepEffectiveStatus");
6604
+ n = /* @__PURE__ */ __name4((v) => typeof v === "number" && Number.isFinite(v) ? v : 0, "n");
6408
6605
  __name(runCounts, "runCounts");
6409
- __name3(runCounts, "runCounts");
6606
+ __name4(runCounts, "runCounts");
6410
6607
  __name(isPricedStepReceipt, "isPricedStepReceipt");
6411
- __name3(isPricedStepReceipt, "isPricedStepReceipt");
6608
+ __name4(isPricedStepReceipt, "isPricedStepReceipt");
6412
6609
  __name(receiptEngine, "receiptEngine");
6413
- __name3(receiptEngine, "receiptEngine");
6610
+ __name4(receiptEngine, "receiptEngine");
6414
6611
  __name(receiptTier, "receiptTier");
6415
- __name3(receiptTier, "receiptTier");
6612
+ __name4(receiptTier, "receiptTier");
6416
6613
  __name(stepBillingView, "stepBillingView");
6417
- __name3(stepBillingView, "stepBillingView");
6614
+ __name4(stepBillingView, "stepBillingView");
6418
6615
  __name(runUsage, "runUsage");
6419
- __name3(runUsage, "runUsage");
6616
+ __name4(runUsage, "runUsage");
6420
6617
  __name(runBudgetCap, "runBudgetCap");
6421
- __name3(runBudgetCap, "runBudgetCap");
6618
+ __name4(runBudgetCap, "runBudgetCap");
6422
6619
  __name(runBudgetRemaining, "runBudgetRemaining");
6423
- __name3(runBudgetRemaining, "runBudgetRemaining");
6620
+ __name4(runBudgetRemaining, "runBudgetRemaining");
6424
6621
  __name(runCancelView, "runCancelView");
6425
- __name3(runCancelView, "runCancelView");
6622
+ __name4(runCancelView, "runCancelView");
6426
6623
  __name(runWorkspaceView, "runWorkspaceView");
6427
- __name3(runWorkspaceView, "runWorkspaceView");
6624
+ __name4(runWorkspaceView, "runWorkspaceView");
6428
6625
  __name(toWorkflowRunSummary, "toWorkflowRunSummary");
6429
- __name3(toWorkflowRunSummary, "toWorkflowRunSummary");
6626
+ __name4(toWorkflowRunSummary, "toWorkflowRunSummary");
6430
6627
  STEP_ERROR_DETAIL_KEYS = [
6431
6628
  "reason",
6432
6629
  "key",
@@ -6455,15 +6652,25 @@ var init_dist2 = __esm({
6455
6652
  "workflowId",
6456
6653
  // LUA-696 (review 2): the `ctx.once` key of an `effect_in_doubt` park — the step site stamps it here (scrubbed)
6457
6654
  // beside `park.effectKey`; a key is user text and leaves scrubbed like every other string leaf.
6458
- "effectKey"
6655
+ "effectKey",
6656
+ // LUA-833: the Job tier's `job_auth_rejected{reason}` evidence — the pod that exited and its code, the Secret the
6657
+ // row named (a k8s object NAME, `wfs-<hash12>-a<n>`, never a value), the execution the pod was spawned for, the
6658
+ // one its credential was minted for, and whether that credential had expired. The LUA-716 / LUA-748 spawn
6659
+ // refusals name `secretName` too.
6660
+ "podName",
6661
+ "exitCode",
6662
+ "secretName",
6663
+ "executionId",
6664
+ "credentialsExecutionId",
6665
+ "expired"
6459
6666
  ];
6460
6667
  STEP_ERROR_DETAIL_MAX_BYTES = 8 * 1024;
6461
6668
  DETAIL_MAX_DEPTH = 4;
6462
6669
  DETAIL_MAX_ITEMS = 100;
6463
6670
  __name(scrubDetailValue, "scrubDetailValue");
6464
- __name3(scrubDetailValue, "scrubDetailValue");
6671
+ __name4(scrubDetailValue, "scrubDetailValue");
6465
6672
  __name(stepErrorDetail, "stepErrorDetail");
6466
- __name3(stepErrorDetail, "stepErrorDetail");
6673
+ __name4(stepErrorDetail, "stepErrorDetail");
6467
6674
  MAX_HOLIDAYS = 366;
6468
6675
  MAX_WALK_DAYS = 400;
6469
6676
  HHMM = /^([01]\d|2[0-3]):([0-5]\d)$/;
@@ -6483,18 +6690,18 @@ var init_dist2 = __esm({
6483
6690
  };
6484
6691
  supportedTz = null;
6485
6692
  __name(timeZoneSupported, "timeZoneSupported");
6486
- __name3(timeZoneSupported, "timeZoneSupported");
6693
+ __name4(timeZoneSupported, "timeZoneSupported");
6487
6694
  __name(validateBusinessHours, "validateBusinessHours");
6488
- __name3(validateBusinessHours, "validateBusinessHours");
6695
+ __name4(validateBusinessHours, "validateBusinessHours");
6489
6696
  __name(toMinutes, "toMinutes");
6490
- __name3(toMinutes, "toMinutes");
6697
+ __name4(toMinutes, "toMinutes");
6491
6698
  __name(resolveCalendar, "resolveCalendar");
6492
- __name3(resolveCalendar, "resolveCalendar");
6699
+ __name4(resolveCalendar, "resolveCalendar");
6493
6700
  __name(assertValid, "assertValid");
6494
- __name3(assertValid, "assertValid");
6701
+ __name4(assertValid, "assertValid");
6495
6702
  fmtCache = /* @__PURE__ */ new Map();
6496
6703
  __name(formatter, "formatter");
6497
- __name3(formatter, "formatter");
6704
+ __name4(formatter, "formatter");
6498
6705
  WEEKDAYS = {
6499
6706
  Sun: 0,
6500
6707
  Mon: 1,
@@ -6505,25 +6712,25 @@ var init_dist2 = __esm({
6505
6712
  Sat: 6
6506
6713
  };
6507
6714
  __name(localParts, "localParts");
6508
- __name3(localParts, "localParts");
6715
+ __name4(localParts, "localParts");
6509
6716
  __name(offsetAt, "offsetAt");
6510
- __name3(offsetAt, "offsetAt");
6717
+ __name4(offsetAt, "offsetAt");
6511
6718
  __name(localToUtc, "localToUtc");
6512
- __name3(localToUtc, "localToUtc");
6719
+ __name4(localToUtc, "localToUtc");
6513
6720
  __name(sameWall, "sameWall");
6514
- __name3(sameWall, "sameWall");
6721
+ __name4(sameWall, "sameWall");
6515
6722
  __name(ymd, "ymd");
6516
- __name3(ymd, "ymd");
6723
+ __name4(ymd, "ymd");
6517
6724
  __name(windowOf, "windowOf");
6518
- __name3(windowOf, "windowOf");
6725
+ __name4(windowOf, "windowOf");
6519
6726
  __name(nextDayAnchor, "nextDayAnchor");
6520
- __name3(nextDayAnchor, "nextDayAnchor");
6727
+ __name4(nextDayAnchor, "nextDayAnchor");
6521
6728
  __name(addBusinessTime, "addBusinessTime");
6522
- __name3(addBusinessTime, "addBusinessTime");
6729
+ __name4(addBusinessTime, "addBusinessTime");
6523
6730
  __name(roundToBusinessTime, "roundToBusinessTime");
6524
- __name3(roundToBusinessTime, "roundToBusinessTime");
6731
+ __name4(roundToBusinessTime, "roundToBusinessTime");
6525
6732
  __name(isBusinessTime, "isBusinessTime");
6526
- __name3(isBusinessTime, "isBusinessTime");
6733
+ __name4(isBusinessTime, "isBusinessTime");
6527
6734
  JSON_PATCH_OPS = [
6528
6735
  "replace",
6529
6736
  "add",
@@ -6534,40 +6741,54 @@ var init_dist2 = __esm({
6534
6741
  JSON_PATCH_MAX_TOTAL_BYTES = 1024 * 1024;
6535
6742
  SEGMENT_RE = /^([A-Za-z_$][\w$-]*)((?:\[(?:\*|\d+)\])*)$/;
6536
6743
  __name(parseEditablePath, "parseEditablePath");
6537
- __name3(parseEditablePath, "parseEditablePath");
6744
+ __name4(parseEditablePath, "parseEditablePath");
6538
6745
  __name(isEditablePathEntry, "isEditablePathEntry");
6539
- __name3(isEditablePathEntry, "isEditablePathEntry");
6746
+ __name4(isEditablePathEntry, "isEditablePathEntry");
6540
6747
  __name(pointerToSegments, "pointerToSegments");
6541
- __name3(pointerToSegments, "pointerToSegments");
6748
+ __name4(pointerToSegments, "pointerToSegments");
6542
6749
  __name(pointerToDotPath, "pointerToDotPath");
6543
- __name3(pointerToDotPath, "pointerToDotPath");
6750
+ __name4(pointerToDotPath, "pointerToDotPath");
6544
6751
  __name(coveredBy, "coveredBy");
6545
- __name3(coveredBy, "coveredBy");
6752
+ __name4(coveredBy, "coveredBy");
6546
6753
  __name(matchesEditablePath, "matchesEditablePath");
6547
- __name3(matchesEditablePath, "matchesEditablePath");
6754
+ __name4(matchesEditablePath, "matchesEditablePath");
6548
6755
  __name(changedPointers, "changedPointers");
6549
- __name3(changedPointers, "changedPointers");
6756
+ __name4(changedPointers, "changedPointers");
6550
6757
  __name(escapePointer, "escapePointer");
6551
- __name3(escapePointer, "escapePointer");
6758
+ __name4(escapePointer, "escapePointer");
6552
6759
  __name(validateJsonPatch, "validateJsonPatch");
6553
- __name3(validateJsonPatch, "validateJsonPatch");
6760
+ __name4(validateJsonPatch, "validateJsonPatch");
6554
6761
  __name(applyJsonPatch, "applyJsonPatch");
6555
- __name3(applyJsonPatch, "applyJsonPatch");
6762
+ __name4(applyJsonPatch, "applyJsonPatch");
6556
6763
  __name(rebaseItemPointer, "rebaseItemPointer");
6557
- __name3(rebaseItemPointer, "rebaseItemPointer");
6764
+ __name4(rebaseItemPointer, "rebaseItemPointer");
6765
+ WORKFLOW_SCHEDULE_TYPES = [
6766
+ "cron",
6767
+ "interval",
6768
+ "once"
6769
+ ];
6770
+ WORKFLOW_SCHEDULE_SHAPE_ISSUE = "schedule-shape-invalid";
6771
+ WORKFLOW_SCHEDULE_SHAPES_HINT = "`schedule` must be one of { type: 'cron', expression: '<5-field cron>', timezone?: '<IANA tz>' } | { type: 'interval', seconds: <n> } | { type: 'once', executeAt: '<ISO-8601>' }";
6772
+ WORKFLOW_SCHEDULE_RUN_AS = [
6773
+ "installer",
6774
+ "system"
6775
+ ];
6776
+ isObject = /* @__PURE__ */ __name4((v) => typeof v === "object" && v !== null && !Array.isArray(v), "isObject");
6777
+ __name(validateWorkflowSchedule, "validateWorkflowSchedule");
6778
+ __name4(validateWorkflowSchedule, "validateWorkflowSchedule");
6558
6779
  WORKFLOW_ENV_OVERLAY_MAX_KEYS = 64;
6559
6780
  WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES = 4096;
6560
6781
  WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
6561
- isEnvRef = /* @__PURE__ */ __name3((v) => typeof v === "object" && v !== null && !Array.isArray(v) && typeof v.__envRef === "string" && Object.keys(v).length === 1, "isEnvRef");
6562
- looksLikeEmbeddedJson = /* @__PURE__ */ __name3((s) => s.length > 1 && s[0] === "{" && s.includes("__envRef"), "looksLikeEmbeddedJson");
6782
+ isEnvRef = /* @__PURE__ */ __name4((v) => typeof v === "object" && v !== null && !Array.isArray(v) && typeof v.__envRef === "string" && Object.keys(v).length === 1, "isEnvRef");
6783
+ looksLikeEmbeddedJson = /* @__PURE__ */ __name4((s) => s.length > 1 && s[0] === "{" && s.includes("__envRef"), "looksLikeEmbeddedJson");
6563
6784
  __name(collectEnvTemplateKeys, "collectEnvTemplateKeys");
6564
- __name3(collectEnvTemplateKeys, "collectEnvTemplateKeys");
6785
+ __name4(collectEnvTemplateKeys, "collectEnvTemplateKeys");
6565
6786
  __name(substituteEnvRefs, "substituteEnvRefs");
6566
- __name3(substituteEnvRefs, "substituteEnvRefs");
6787
+ __name4(substituteEnvRefs, "substituteEnvRefs");
6567
6788
  __name(hashEnvOverlay, "hashEnvOverlay");
6568
- __name3(hashEnvOverlay, "hashEnvOverlay");
6789
+ __name4(hashEnvOverlay, "hashEnvOverlay");
6569
6790
  __name(validateEnvOverlay, "validateEnvOverlay");
6570
- __name3(validateEnvOverlay, "validateEnvOverlay");
6791
+ __name4(validateEnvOverlay, "validateEnvOverlay");
6571
6792
  ZERO = {
6572
6793
  steps: {
6573
6794
  min: 0,
@@ -6580,24 +6801,24 @@ var init_dist2 = __esm({
6580
6801
  agentCalls: 0
6581
6802
  };
6582
6803
  __name(add, "add");
6583
- __name3(add, "add");
6804
+ __name4(add, "add");
6584
6805
  __name(scale, "scale");
6585
- __name3(scale, "scale");
6806
+ __name4(scale, "scale");
6586
6807
  __name(armEntry, "armEntry");
6587
- __name3(armEntry, "armEntry");
6808
+ __name4(armEntry, "armEntry");
6588
6809
  __name(ofEntry, "ofEntry");
6589
- __name3(ofEntry, "ofEntry");
6810
+ __name4(ofEntry, "ofEntry");
6590
6811
  __name(estimateGraph, "estimateGraph");
6591
- __name3(estimateGraph, "estimateGraph");
6592
- isRecord2 = /* @__PURE__ */ __name3((v) => !!v && typeof v === "object" && !Array.isArray(v), "isRecord");
6812
+ __name4(estimateGraph, "estimateGraph");
6813
+ isRecord2 = /* @__PURE__ */ __name4((v) => !!v && typeof v === "object" && !Array.isArray(v), "isRecord");
6593
6814
  __name(singleStepsOf, "singleStepsOf");
6594
- __name3(singleStepsOf, "singleStepsOf");
6815
+ __name4(singleStepsOf, "singleStepsOf");
6595
6816
  __name(entriesOf, "entriesOf");
6596
- __name3(entriesOf, "entriesOf");
6817
+ __name4(entriesOf, "entriesOf");
6597
6818
  __name(inheritTargets, "inheritTargets");
6598
- __name3(inheritTargets, "inheritTargets");
6819
+ __name4(inheritTargets, "inheritTargets");
6599
6820
  __name(needsInheritedWorkspace, "needsInheritedWorkspace");
6600
- __name3(needsInheritedWorkspace, "needsInheritedWorkspace");
6821
+ __name4(needsInheritedWorkspace, "needsInheritedWorkspace");
6601
6822
  }
6602
6823
  });
6603
6824
 
@@ -6734,7 +6955,7 @@ function defineWorkflow(cfg, build) {
6734
6955
  if (!(wf instanceof LuaWorkflow)) throw new LuaWorkflowBuildError("invalid-envelope", "defineWorkflow: the build callback must return `wf\u2026.commit()`");
6735
6956
  return wf;
6736
6957
  }
6737
- var init2, state2, lit2, eq2, ne2, gt2, gte2, lt2, lte2, inSet2, notIn2, exists2, notExists2, truthy2, falsy2, and2, or2, not2, fromInit2, fromStep2, value2, template2, fromRequest2, rows2, fromKnowledge2, LuaWorkflowBuildError, STEP_ID_RE, WORKFLOW_NAME_RE, WORKFLOW_MAX_PARALLEL_ARMS, WORKFLOW_MAX_FOREACH_CONCURRENCY, WORKFLOW_MAX_FOREACH_ITEMS, WORKFLOW_WORKER_MAX_TIMEOUT_SECONDS, WORKFLOW_JOB_SEGMENT_MAX_SECONDS, WORKFLOW_JOB_MAX_TIMEOUT_SECONDS, WORKFLOW_LOOP_INTERVAL_MAX_SECONDS, WORKFLOW_FOREACH_RATE_MAX_PER_SECOND, WORKFLOW_SPECIALIST_ROLE_MAX_INSTRUCTIONS, WORKFLOW_DEFAULT_MAX_DURATION_SECONDS, WORKFLOW_HITL_MAX_DURATION_SECONDS, SECRET_KEY_RE, isZod, defined, templateText, assertNoClosure, assertPredicate, assertRetry, assertTimeout, envRefKeys, refToDescriptor, __workflowCommitHook, LuaWorkflow, isHitlEntry, WorkflowBuilderImpl, EDITABLE_PATH_RE2;
6958
+ var init2, state2, lit2, eq2, ne2, gt2, gte2, lt2, lte2, inSet2, notIn2, exists2, notExists2, truthy2, falsy2, and2, or2, not2, fromInit2, fromStep2, value2, template2, fromRequest2, rows2, fromKnowledge2, LuaWorkflowBuildError, STEP_ID_RE, WORKFLOW_NAME_RE, WORKFLOW_MAX_PARALLEL_ARMS, WORKFLOW_MAX_FOREACH_CONCURRENCY, WORKFLOW_MAX_FOREACH_ITEMS, WORKFLOW_WORKER_MAX_TIMEOUT_SECONDS, WORKFLOW_JOB_SEGMENT_MAX_SECONDS, WORKFLOW_JOB_MAX_TIMEOUT_SECONDS, WORKFLOW_LOOP_INTERVAL_MAX_SECONDS, WORKFLOW_FOREACH_RATE_MAX_PER_SECOND, WORKFLOW_SPECIALIST_ROLE_MAX_INSTRUCTIONS, WORKFLOW_DEFAULT_MAX_DURATION_SECONDS, WORKFLOW_HITL_MAX_DURATION_SECONDS, SECRET_KEY_RE, isZod, defined, templateText, assertNoClosure, assertPredicate, assertRetry, assertTimeout, envRefKeys, foreachItemsNotLowered, refToDescriptor, __workflowCommitHook, LuaWorkflow, isHitlEntry, WorkflowBuilderImpl, EDITABLE_PATH_RE2;
6738
6959
  var init_workflow = __esm({
6739
6960
  "src/types/workflow.ts"() {
6740
6961
  "use strict";
@@ -6853,6 +7074,7 @@ var init_workflow = __esm({
6853
7074
  }
6854
7075
  for (const inner of Object.values(v)) envRefKeys(inner, into);
6855
7076
  }, "envRefKeys");
7077
+ foreachItemsNotLowered = /* @__PURE__ */ __name((what) => new LuaWorkflowBuildError("invalid-envelope", `foreach.items takes fromInit(path) / fromStep(step, path) or an initData.* / stepResults.* ref \u2014 ${what} is not a foreach source; .map({ '': \u2026 }, { id }) before the foreach instead`), "foreachItemsNotLowered");
6856
7078
  refToDescriptor = /* @__PURE__ */ __name((items) => {
6857
7079
  if (!items) throw new LuaWorkflowBuildError("invalid-envelope", "foreach.items needs a ref");
6858
7080
  if ("initData" in items && items.initData === true) {
@@ -6862,11 +7084,14 @@ var init_workflow = __esm({
6862
7084
  };
6863
7085
  }
6864
7086
  if ("step" in items && typeof items.step === "string" && !("path" in items && items.path.startsWith("stepResults"))) {
7087
+ if ("rows" in items) throw foreachItemsNotLowered("rows(\u2026) (a paged dataset)");
6865
7088
  return {
6866
7089
  step: items.step,
6867
7090
  path: items.path
6868
7091
  };
6869
7092
  }
7093
+ if ("step" in items && Array.isArray(items.step)) throw foreachItemsNotLowered("a fan-in fromStep([\u2026])");
7094
+ if (typeof items.path !== "string") throw foreachItemsNotLowered("value(\u2026) / template(\u2026) / fromRequest(\u2026) / fromKnowledge(\u2026)");
6870
7095
  const path3 = items.path;
6871
7096
  if (path3.startsWith("initData")) return {
6872
7097
  initData: true,
@@ -7342,9 +7567,12 @@ var init_workflow = __esm({
7342
7567
  if (opts.approver === "creator" && opts.excludeInitiator === true) {
7343
7568
  throw new LuaWorkflowBuildError("approver-excludes-only-candidate", `"${id}": approver:'creator' with excludeInitiator:true always excludes the only candidate`);
7344
7569
  }
7345
- if (opts.fourEyes !== void 0 && opts.editable !== true) throw new LuaWorkflowBuildError("four-eyes-requires-editable", `"${id}": fourEyes requires editable:true`);
7346
- if ((opts.editablePaths !== void 0 || opts.editedPayloadSchema !== void 0) && opts.editable !== true) {
7347
- throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": editablePaths / editedPayloadSchema require editable:true`);
7570
+ const editable = approvalEditable(opts);
7571
+ if (opts.fourEyes !== void 0 && !editable) throw new LuaWorkflowBuildError("four-eyes-requires-editable", `"${id}": \`fourEyes\` requires editable:true`);
7572
+ if (opts.editable === false && Array.isArray(opts.editablePaths) && opts.editablePaths.length > 0) {
7573
+ throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": \`editablePaths\` beside editable:false is contradictory \u2014 drop the paths or set editable:true`);
7574
+ } else if ((opts.editablePaths !== void 0 || opts.editedPayloadSchema !== void 0) && !editable) {
7575
+ throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": \`editablePaths\` / \`editedPayloadSchema\` require editable:true (a non-empty editablePaths implies it)`);
7348
7576
  }
7349
7577
  for (const p of opts.editablePaths ?? []) {
7350
7578
  if (!EDITABLE_PATH_RE2.test(p)) throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": editablePaths entry "${p}" is outside the grammar seg(.seg)* with [*]/[n] selectors`);
@@ -7594,328 +7822,130 @@ var init_auth_error = __esm({
7594
7822
  }
7595
7823
  });
7596
7824
 
7597
- // src/errors/cli.error.ts
7598
- function isAccessDeniedError(error) {
7599
- if (CliError.isCliError(error)) return error.statusCode === 403;
7600
- return error instanceof Error && error.message.startsWith("Access denied (403)");
7825
+ // src/utils/package-root.ts
7826
+ import { readFileSync, existsSync } from "fs";
7827
+ import { fileURLToPath, pathToFileURL } from "url";
7828
+ import { dirname, join as join2 } from "path";
7829
+ function locate() {
7830
+ if (cachedRoot && cachedPkg) return {
7831
+ root: cachedRoot,
7832
+ pkg: cachedPkg
7833
+ };
7834
+ let dir = dirname(fileURLToPath(import.meta.url));
7835
+ while (true) {
7836
+ const candidate = join2(dir, "package.json");
7837
+ if (existsSync(candidate)) {
7838
+ try {
7839
+ const parsed = JSON.parse(readFileSync(candidate, "utf8"));
7840
+ if (parsed?.name === "lua-cli") {
7841
+ cachedRoot = dir;
7842
+ cachedPkg = parsed;
7843
+ return {
7844
+ root: dir,
7845
+ pkg: parsed
7846
+ };
7847
+ }
7848
+ } catch {
7849
+ }
7850
+ }
7851
+ const parent = dirname(dir);
7852
+ if (parent === dir) break;
7853
+ dir = parent;
7854
+ }
7855
+ throw new Error("Could not locate lua-cli package root from " + fileURLToPath(import.meta.url));
7601
7856
  }
7602
- function authHint(error) {
7603
- if (error.suppressDefaultRemediation) return void 0;
7604
- if (error.reason === "no_agent_access") {
7605
- return [
7606
- "Your API key is valid, but it does not have access to the agentId in lua.skill.yaml \u2014 the agent belongs",
7607
- "to another account or organization, was deleted or transferred, or the yaml was copied from another project.",
7608
- "Check the configured agent and switch if needed:",
7609
- " lua agents (list agents you have access to)",
7610
- " lua init (re-select the agent for this project)"
7611
- ].join("\n");
7857
+ function getCliVersion() {
7858
+ try {
7859
+ return locate().pkg.version;
7860
+ } catch {
7861
+ return "0.0.0";
7612
7862
  }
7613
- return "Re-authenticate or check your API key: lua auth configure \xB7 https://admin.heylua.ai";
7614
7863
  }
7615
- function numericStatus(error) {
7616
- const candidate = error.statusCode ?? error.status;
7617
- return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : void 0;
7864
+ var cachedRoot, cachedPkg;
7865
+ var init_package_root = __esm({
7866
+ "src/utils/package-root.ts"() {
7867
+ "use strict";
7868
+ cachedRoot = null;
7869
+ cachedPkg = null;
7870
+ __name(locate, "locate");
7871
+ __name(getCliVersion, "getCliVersion");
7872
+ }
7873
+ });
7874
+
7875
+ // src/utils/lua-fetch.ts
7876
+ function luaClientHeaderValue() {
7877
+ return formatLuaClientHeader("cli", getCliVersion());
7618
7878
  }
7619
- function classifyCliError(error) {
7620
- if (CliError.isCliError(error)) {
7621
- return {
7622
- code: error.code,
7623
- exitCode: error.exitCode,
7624
- message: error.message,
7625
- hint: error.hint,
7626
- statusCode: error.statusCode,
7627
- serverCode: error.serverCode,
7628
- issues: error.issues
7629
- };
7879
+ function headerRecord(headers) {
7880
+ if (!headers) return {};
7881
+ if (headers instanceof Headers) return Object.fromEntries(headers.entries());
7882
+ if (Array.isArray(headers)) return Object.fromEntries(headers);
7883
+ const record = {};
7884
+ for (const [name, value3] of Object.entries(headers)) {
7885
+ if (typeof value3 === "string") record[name] = value3;
7630
7886
  }
7631
- if (AuthenticationError.isAuthenticationError(error)) {
7632
- return {
7633
- code: "auth",
7634
- exitCode: CLI_EXIT.AUTH,
7635
- message: error.message,
7636
- hint: authHint(error)
7637
- };
7887
+ return record;
7888
+ }
7889
+ function luaFetch(input, init3 = {}) {
7890
+ const headers = headerRecord(init3.headers);
7891
+ for (const name of Object.keys(headers)) {
7892
+ if (name.toLowerCase() === LUA_CLIENT_HEADER.toLowerCase()) delete headers[name];
7638
7893
  }
7639
- const e = typeof error === "object" && error !== null ? error : {};
7640
- const message = typeof e.message === "string" && e.message.length > 0 ? e.message : error instanceof Error ? error.name : String(error ?? "Unknown error");
7641
- if (e.name === "WorkflowLocalUsageError" || typeof e.code === "string" && e.code.startsWith("commander.")) {
7894
+ headers[LUA_CLIENT_HEADER] = luaClientHeaderValue();
7895
+ return fetch(input, {
7896
+ ...init3,
7897
+ headers
7898
+ });
7899
+ }
7900
+ var init_lua_fetch = __esm({
7901
+ "src/utils/lua-fetch.ts"() {
7902
+ "use strict";
7903
+ init_dist();
7904
+ init_package_root();
7905
+ __name(luaClientHeaderValue, "luaClientHeaderValue");
7906
+ __name(headerRecord, "headerRecord");
7907
+ __name(luaFetch, "luaFetch");
7908
+ }
7909
+ });
7910
+
7911
+ // src/services/firebase-session.ts
7912
+ import { z as z5 } from "zod";
7913
+ function rejectedRefreshReason(message) {
7914
+ const normalised = message.toUpperCase();
7915
+ return REJECTED_REFRESH_REASONS.find((reason) => normalised.includes(reason));
7916
+ }
7917
+ function requireFirebaseWebApiKey() {
7918
+ if (!FIREBASE_WEB_API_KEY) {
7919
+ throw new Error("Firebase sign-in is not configured for this CLI build.");
7920
+ }
7921
+ return FIREBASE_WEB_API_KEY;
7922
+ }
7923
+ function claimsOfFirebaseIdToken(idToken) {
7924
+ const segments = idToken.split(".");
7925
+ if (segments.length !== 3 || !segments[1]) throw new Error(INVALID_FIREBASE_SESSION);
7926
+ try {
7927
+ const payload = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf8"));
7928
+ if (typeof payload !== "object" || payload === null) throw new Error(INVALID_FIREBASE_SESSION);
7929
+ return payload;
7930
+ } catch {
7931
+ throw new Error(INVALID_FIREBASE_SESSION);
7932
+ }
7933
+ }
7934
+ function uidFromFirebaseIdToken(idToken) {
7935
+ const payload = claimsOfFirebaseIdToken(idToken);
7936
+ const parsed = firebaseIdTokenPayloadSchema.safeParse(payload);
7937
+ if (parsed.success) return parsed.data.sub;
7938
+ throw new Error(INVALID_FIREBASE_SESSION);
7939
+ }
7940
+ function parseFirebaseSession(json, now = Date.now()) {
7941
+ const customTokenResponse = customTokenResponseSchema.safeParse(json);
7942
+ if (customTokenResponse.success) {
7943
+ const { idToken: idToken2, refreshToken: refreshToken2, expiresIn: expiresIn2, localId } = customTokenResponse.data;
7642
7944
  return {
7643
- code: "usage",
7644
- exitCode: CLI_EXIT.USAGE,
7645
- message
7646
- };
7647
- }
7648
- const status = numericStatus(e);
7649
- if (status !== void 0) {
7650
- const statusCode = status;
7651
- if (status === 401) return {
7652
- code: "auth",
7653
- exitCode: CLI_EXIT.AUTH,
7654
- message,
7655
- statusCode
7656
- };
7657
- if (status === 403) return {
7658
- code: "forbidden",
7659
- exitCode: CLI_EXIT.FORBIDDEN,
7660
- message,
7661
- statusCode
7662
- };
7663
- if (status === 404) return {
7664
- code: "not_found",
7665
- exitCode: CLI_EXIT.NOT_FOUND,
7666
- message,
7667
- statusCode
7668
- };
7669
- if (status >= 400 && status < 500) return {
7670
- code: `http_${status}`,
7671
- exitCode: CLI_EXIT.FORBIDDEN,
7672
- message,
7673
- statusCode
7674
- };
7675
- if (status >= 500 || status === 0) return {
7676
- code: "unavailable",
7677
- exitCode: CLI_EXIT.UNAVAILABLE,
7678
- message,
7679
- statusCode
7680
- };
7681
- }
7682
- const causeCode = e.cause?.code;
7683
- 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)) {
7684
- return {
7685
- code: "unavailable",
7686
- exitCode: CLI_EXIT.UNAVAILABLE,
7687
- message,
7688
- hint: UNAVAILABLE_HINT
7689
- };
7690
- }
7691
- return {
7692
- code: "error",
7693
- exitCode: CLI_EXIT.ERROR,
7694
- message
7695
- };
7696
- }
7697
- var CLI_EXIT, CliError, NETWORK_ERRNO, NETWORK_MESSAGE, UNAVAILABLE_HINT;
7698
- var init_cli_error = __esm({
7699
- "src/errors/cli.error.ts"() {
7700
- "use strict";
7701
- init_auth_error();
7702
- CLI_EXIT = {
7703
- OK: 0,
7704
- ERROR: 1,
7705
- USAGE: 2,
7706
- NOT_FOUND: 3,
7707
- AUTH: 9,
7708
- FORBIDDEN: 10,
7709
- UNAVAILABLE: 11
7710
- };
7711
- CliError = class _CliError extends Error {
7712
- static {
7713
- __name(this, "CliError");
7714
- }
7715
- isCliError = true;
7716
- code;
7717
- exitCode;
7718
- hint;
7719
- statusCode;
7720
- serverCode;
7721
- issues;
7722
- constructor(code, message, options = {}) {
7723
- super(message);
7724
- this.name = "CliError";
7725
- this.code = code;
7726
- this.exitCode = options.exitCode ?? CLI_EXIT.ERROR;
7727
- this.hint = options.hint;
7728
- this.statusCode = options.statusCode;
7729
- this.serverCode = options.serverCode;
7730
- this.issues = options.issues?.length ? options.issues : void 0;
7731
- if (Error.captureStackTrace) Error.captureStackTrace(this, _CliError);
7732
- }
7733
- /** Bad arguments, an unknown action, no project — exit 2. */
7734
- static usage(message, hint) {
7735
- return new _CliError("usage", message, {
7736
- exitCode: CLI_EXIT.USAGE,
7737
- hint
7738
- });
7739
- }
7740
- /** The named thing does not exist — exit 3. */
7741
- static notFound(message, hint) {
7742
- return new _CliError("not_found", message, {
7743
- exitCode: CLI_EXIT.NOT_FOUND,
7744
- hint,
7745
- statusCode: 404
7746
- });
7747
- }
7748
- /** The credential may not do this — exit 10. */
7749
- static forbidden(message, hint) {
7750
- return new _CliError("forbidden", message, {
7751
- exitCode: CLI_EXIT.FORBIDDEN,
7752
- hint,
7753
- statusCode: 403
7754
- });
7755
- }
7756
- /**
7757
- * An API refusal the site already holds the status of (LUA-766) — classified by the same table the top-level
7758
- * classifier applies to an untyped error: 401 auth · 403 forbidden · 404 not_found · other 4xx `http_<status>`
7759
- * (10) · 5xx / 0 unavailable (11, with the network hint unless the site gives its own) · no status `error` (1).
7760
- * A command that reads `response.error.statusCode` throws through here, so `lua logs` on a 503 exits 11 like
7761
- * every other verb instead of printing the message itself and then throwing an exit-1 `Error`.
7762
- */
7763
- static fromStatus(statusCode, message, hint, detail = {}) {
7764
- const reported = classifyCliError(Object.assign(new Error(message), {
7765
- statusCode
7766
- }));
7767
- const classHint = reported.exitCode === CLI_EXIT.UNAVAILABLE ? UNAVAILABLE_HINT : reported.hint;
7768
- return new _CliError(reported.code, message, {
7769
- exitCode: reported.exitCode,
7770
- hint: hint ?? classHint,
7771
- statusCode,
7772
- serverCode: detail.serverCode,
7773
- issues: detail.issues
7774
- });
7775
- }
7776
- static isCliError(error) {
7777
- return error instanceof _CliError || typeof error === "object" && error !== null && error.isCliError === true;
7778
- }
7779
- };
7780
- __name(isAccessDeniedError, "isAccessDeniedError");
7781
- NETWORK_ERRNO = /* @__PURE__ */ new Set([
7782
- "ECONNREFUSED",
7783
- "ECONNRESET",
7784
- "ENOTFOUND",
7785
- "ETIMEDOUT",
7786
- "EAI_AGAIN",
7787
- "EPIPE",
7788
- "EHOSTUNREACH",
7789
- "ENETUNREACH",
7790
- "UND_ERR_CONNECT_TIMEOUT",
7791
- "UND_ERR_HEADERS_TIMEOUT",
7792
- "UND_ERR_BODY_TIMEOUT",
7793
- "UND_ERR_SOCKET"
7794
- ]);
7795
- NETWORK_MESSAGE = /fetch failed|socket hang up|network request failed|request timeout|ECONNREFUSED|ENOTFOUND/i;
7796
- UNAVAILABLE_HINT = "The Lua API could not be reached \u2014 check your network and https://status.heylua.ai, then retry.";
7797
- __name(authHint, "authHint");
7798
- __name(numericStatus, "numericStatus");
7799
- __name(classifyCliError, "classifyCliError");
7800
- }
7801
- });
7802
-
7803
- // src/utils/package-root.ts
7804
- import { readFileSync, existsSync } from "fs";
7805
- import { fileURLToPath, pathToFileURL } from "url";
7806
- import { dirname, join as join2 } from "path";
7807
- function locate() {
7808
- if (cachedRoot && cachedPkg) return {
7809
- root: cachedRoot,
7810
- pkg: cachedPkg
7811
- };
7812
- let dir = dirname(fileURLToPath(import.meta.url));
7813
- while (true) {
7814
- const candidate = join2(dir, "package.json");
7815
- if (existsSync(candidate)) {
7816
- try {
7817
- const parsed = JSON.parse(readFileSync(candidate, "utf8"));
7818
- if (parsed?.name === "lua-cli") {
7819
- cachedRoot = dir;
7820
- cachedPkg = parsed;
7821
- return {
7822
- root: dir,
7823
- pkg: parsed
7824
- };
7825
- }
7826
- } catch {
7827
- }
7828
- }
7829
- const parent = dirname(dir);
7830
- if (parent === dir) break;
7831
- dir = parent;
7832
- }
7833
- throw new Error("Could not locate lua-cli package root from " + fileURLToPath(import.meta.url));
7834
- }
7835
- function getCliVersion() {
7836
- try {
7837
- return locate().pkg.version;
7838
- } catch {
7839
- return "0.0.0";
7840
- }
7841
- }
7842
- var cachedRoot, cachedPkg;
7843
- var init_package_root = __esm({
7844
- "src/utils/package-root.ts"() {
7845
- "use strict";
7846
- cachedRoot = null;
7847
- cachedPkg = null;
7848
- __name(locate, "locate");
7849
- __name(getCliVersion, "getCliVersion");
7850
- }
7851
- });
7852
-
7853
- // src/utils/lua-fetch.ts
7854
- function luaClientHeaderValue() {
7855
- return formatLuaClientHeader("cli", getCliVersion());
7856
- }
7857
- function headerRecord(headers) {
7858
- if (!headers) return {};
7859
- if (headers instanceof Headers) return Object.fromEntries(headers.entries());
7860
- if (Array.isArray(headers)) return Object.fromEntries(headers);
7861
- const record = {};
7862
- for (const [name, value3] of Object.entries(headers)) {
7863
- if (typeof value3 === "string") record[name] = value3;
7864
- }
7865
- return record;
7866
- }
7867
- function luaFetch(input, init3 = {}) {
7868
- const headers = headerRecord(init3.headers);
7869
- for (const name of Object.keys(headers)) {
7870
- if (name.toLowerCase() === LUA_CLIENT_HEADER.toLowerCase()) delete headers[name];
7871
- }
7872
- headers[LUA_CLIENT_HEADER] = luaClientHeaderValue();
7873
- return fetch(input, {
7874
- ...init3,
7875
- headers
7876
- });
7877
- }
7878
- var init_lua_fetch = __esm({
7879
- "src/utils/lua-fetch.ts"() {
7880
- "use strict";
7881
- init_dist();
7882
- init_package_root();
7883
- __name(luaClientHeaderValue, "luaClientHeaderValue");
7884
- __name(headerRecord, "headerRecord");
7885
- __name(luaFetch, "luaFetch");
7886
- }
7887
- });
7888
-
7889
- // src/services/firebase-session.ts
7890
- import { z as z5 } from "zod";
7891
- function requireFirebaseWebApiKey() {
7892
- if (!FIREBASE_WEB_API_KEY) {
7893
- throw new Error("Firebase sign-in is not configured for this CLI build.");
7894
- }
7895
- return FIREBASE_WEB_API_KEY;
7896
- }
7897
- function uidFromFirebaseIdToken(idToken) {
7898
- const segments = idToken.split(".");
7899
- if (segments.length !== 3 || !segments[1]) throw new Error(INVALID_FIREBASE_SESSION);
7900
- let payload;
7901
- try {
7902
- payload = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf8"));
7903
- } catch {
7904
- throw new Error(INVALID_FIREBASE_SESSION);
7905
- }
7906
- const parsed = firebaseIdTokenPayloadSchema.safeParse(payload);
7907
- if (parsed.success) return parsed.data.sub;
7908
- throw new Error(INVALID_FIREBASE_SESSION);
7909
- }
7910
- function parseFirebaseSession(json, now = Date.now()) {
7911
- const customTokenResponse = customTokenResponseSchema.safeParse(json);
7912
- if (customTokenResponse.success) {
7913
- const { idToken: idToken2, refreshToken: refreshToken2, expiresIn: expiresIn2, localId } = customTokenResponse.data;
7914
- return {
7915
- idToken: idToken2,
7916
- refreshToken: refreshToken2,
7917
- expiresAt: now + expiresIn2 * 1e3,
7918
- uid: localId ?? uidFromFirebaseIdToken(idToken2)
7945
+ idToken: idToken2,
7946
+ refreshToken: refreshToken2,
7947
+ expiresAt: now + expiresIn2 * 1e3,
7948
+ uid: localId ?? uidFromFirebaseIdToken(idToken2)
7919
7949
  };
7920
7950
  }
7921
7951
  const refreshResponse = refreshResponseSchema.safeParse(json);
@@ -7958,6 +7988,23 @@ async function fetchFirebase(url, init3, timeoutMessage) {
7958
7988
  if (timeoutId !== void 0) clearTimeout(timeoutId);
7959
7989
  }
7960
7990
  }
7991
+ async function exchangeFirebaseCustomToken(signInToken) {
7992
+ const key = requireFirebaseWebApiKey();
7993
+ const response = await fetchFirebase(`${FIREBASE_CUSTOM_TOKEN_URL}?key=${encodeURIComponent(key)}`, {
7994
+ method: "POST",
7995
+ headers: {
7996
+ "Content-Type": "application/json"
7997
+ },
7998
+ body: JSON.stringify({
7999
+ token: signInToken,
8000
+ returnSecureToken: true
8001
+ })
8002
+ }, "Firebase sign-in timed out after 15 seconds.");
8003
+ if (!response.ok) {
8004
+ throw new Error(`Firebase sign-in failed: ${await parseFirebaseError(response)}`);
8005
+ }
8006
+ return parseFirebaseSession(await response.json());
8007
+ }
7961
8008
  async function refreshFirebaseSession(session) {
7962
8009
  const key = requireFirebaseWebApiKey();
7963
8010
  const response = await fetchFirebase(`${FIREBASE_REFRESH_URL}?key=${encodeURIComponent(key)}`, {
@@ -7971,20 +8018,43 @@ async function refreshFirebaseSession(session) {
7971
8018
  }).toString()
7972
8019
  }, "Firebase session refresh timed out after 15 seconds.");
7973
8020
  if (!response.ok) {
7974
- throw new Error(`Firebase session refresh failed: ${await parseFirebaseError(response)}`);
8021
+ const reason = await parseFirebaseError(response);
8022
+ const rejected = response.status < 500 ? rejectedRefreshReason(reason) : void 0;
8023
+ if (rejected) throw new FirebaseSessionRejectedError(rejected);
8024
+ throw new Error(`Firebase session refresh failed: ${reason}`);
7975
8025
  }
7976
8026
  const refreshed = parseFirebaseSession(await response.json());
7977
8027
  if (refreshed.uid !== session.uid) throw new Error("Firebase session refresh returned a different identity.");
7978
8028
  return refreshed;
7979
8029
  }
7980
- var FIREBASE_REFRESH_URL, FIREBASE_REQUEST_TIMEOUT_MS, INVALID_FIREBASE_SESSION, customTokenResponseSchema, refreshResponseSchema, firebaseIdTokenPayloadSchema;
8030
+ var FIREBASE_CUSTOM_TOKEN_URL, FIREBASE_REFRESH_URL, FIREBASE_REQUEST_TIMEOUT_MS, INVALID_FIREBASE_SESSION, REJECTED_REFRESH_REASONS, FirebaseSessionRejectedError, customTokenResponseSchema, refreshResponseSchema, firebaseIdTokenPayloadSchema;
7981
8031
  var init_firebase_session = __esm({
7982
8032
  "src/services/firebase-session.ts"() {
7983
8033
  "use strict";
7984
8034
  init_constants();
8035
+ FIREBASE_CUSTOM_TOKEN_URL = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken";
7985
8036
  FIREBASE_REFRESH_URL = "https://securetoken.googleapis.com/v1/token";
7986
8037
  FIREBASE_REQUEST_TIMEOUT_MS = 15e3;
7987
8038
  INVALID_FIREBASE_SESSION = "Sign-in failed because Firebase returned an invalid session.";
8039
+ REJECTED_REFRESH_REASONS = [
8040
+ "TOKEN_EXPIRED",
8041
+ "USER_DISABLED",
8042
+ "USER_NOT_FOUND",
8043
+ "INVALID_REFRESH_TOKEN",
8044
+ "INVALID_GRANT_TYPE",
8045
+ "MISSING_REFRESH_TOKEN"
8046
+ ];
8047
+ __name(rejectedRefreshReason, "rejectedRefreshReason");
8048
+ FirebaseSessionRejectedError = class extends Error {
8049
+ static {
8050
+ __name(this, "FirebaseSessionRejectedError");
8051
+ }
8052
+ reason;
8053
+ constructor(reason) {
8054
+ super(`Firebase session refresh rejected: ${reason}`), this.reason = reason;
8055
+ this.name = "FirebaseSessionRejectedError";
8056
+ }
8057
+ };
7988
8058
  customTokenResponseSchema = z5.object({
7989
8059
  idToken: z5.string().min(1),
7990
8060
  refreshToken: z5.string().min(1),
@@ -8001,17 +8071,19 @@ var init_firebase_session = __esm({
8001
8071
  sub: z5.string().min(1)
8002
8072
  });
8003
8073
  __name(requireFirebaseWebApiKey, "requireFirebaseWebApiKey");
8074
+ __name(claimsOfFirebaseIdToken, "claimsOfFirebaseIdToken");
8004
8075
  __name(uidFromFirebaseIdToken, "uidFromFirebaseIdToken");
8005
8076
  __name(parseFirebaseSession, "parseFirebaseSession");
8006
8077
  __name(parseFirebaseError, "parseFirebaseError");
8007
8078
  __name(fetchFirebase, "fetchFirebase");
8079
+ __name(exchangeFirebaseCustomToken, "exchangeFirebaseCustomToken");
8008
8080
  __name(refreshFirebaseSession, "refreshFirebaseSession");
8009
8081
  }
8010
8082
  });
8011
8083
 
8012
8084
  // src/services/firebase-session-store.ts
8013
8085
  import { createHash as createHash3, randomUUID } from "crypto";
8014
- import { mkdir, open, readFile, rename, unlink } from "fs/promises";
8086
+ import { mkdir, open, readFile, rename, rm, stat, unlink, writeFile } from "fs/promises";
8015
8087
  import { join as join3 } from "path";
8016
8088
  import { z as z6 } from "zod";
8017
8089
  function environmentKey(environment) {
@@ -8022,7 +8094,10 @@ ${environment.firebaseWebApiKey}`).digest("hex").slice(0, 16);
8022
8094
  function isMissing(error) {
8023
8095
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
8024
8096
  }
8025
- var storedFirebaseSessionSchema, currentFirebaseSessionEnvironment, wait, FirebaseSessionStore;
8097
+ function errorCode(error) {
8098
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
8099
+ }
8100
+ var storedFirebaseSessionSchema, currentFirebaseSessionEnvironment, wait, LOCK_STALE_MS, LOCK_TIMEOUT_MS, FirebaseSessionStore;
8026
8101
  var init_firebase_session_store = __esm({
8027
8102
  "src/services/firebase-session-store.ts"() {
8028
8103
  "use strict";
@@ -8045,6 +8120,9 @@ var init_firebase_session_store = __esm({
8045
8120
  __name(environmentKey, "environmentKey");
8046
8121
  __name(isMissing, "isMissing");
8047
8122
  wait = /* @__PURE__ */ __name((milliseconds) => new Promise((resolve3) => setTimeout(resolve3, milliseconds)), "wait");
8123
+ LOCK_STALE_MS = 3e4;
8124
+ LOCK_TIMEOUT_MS = LOCK_STALE_MS + 5e3;
8125
+ __name(errorCode, "errorCode");
8048
8126
  FirebaseSessionStore = class {
8049
8127
  static {
8050
8128
  __name(this, "FirebaseSessionStore");
@@ -8126,27 +8204,39 @@ var init_firebase_session_store = __esm({
8126
8204
  if (!isMissing(error)) throw error;
8127
8205
  }
8128
8206
  }
8207
+ /**
8208
+ * A lock DIRECTORY, not a file: `mkdir` is atomic on every platform Node runs on, where an exclusive `open`
8209
+ * answered EPERM on Windows. The owner id inside lets a process release only its own lock, and a lock older
8210
+ * than any operation could take is treated as left behind by a crashed process and removed.
8211
+ */
8129
8212
  async withLock(operation) {
8130
8213
  await mkdir(this.directory, {
8131
8214
  recursive: true,
8132
8215
  mode: 448
8133
8216
  });
8134
8217
  const lockPath = `${this.path()}.lock`;
8218
+ const ownerPath = join3(lockPath, "owner");
8135
8219
  const lockOwner = randomUUID();
8136
- const deadline = Date.now() + 2e4;
8220
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
8137
8221
  while (true) {
8138
8222
  try {
8139
- const handle = await open(lockPath, "wx", 384);
8140
- try {
8141
- await handle.writeFile(lockOwner, "utf8");
8142
- await handle.sync();
8143
- } finally {
8144
- await handle.close();
8145
- }
8146
- break;
8223
+ await mkdir(lockPath, {
8224
+ mode: 448
8225
+ });
8226
+ await writeFile(ownerPath, lockOwner, {
8227
+ encoding: "utf8",
8228
+ mode: 384
8229
+ });
8230
+ if (await readFile(ownerPath, "utf8") === lockOwner) break;
8147
8231
  } catch (error) {
8148
- const code = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
8149
- if (code !== "EEXIST") throw error;
8232
+ if (errorCode(error) !== "EEXIST") throw error;
8233
+ if (await this.isStaleLock(lockPath)) {
8234
+ await rm(lockPath, {
8235
+ recursive: true,
8236
+ force: true
8237
+ });
8238
+ continue;
8239
+ }
8150
8240
  if (Date.now() >= deadline) {
8151
8241
  throw new Error("Timed out waiting for another Lua CLI process to finish updating the session.");
8152
8242
  }
@@ -8157,12 +8247,22 @@ var init_firebase_session_store = __esm({
8157
8247
  return await operation();
8158
8248
  } finally {
8159
8249
  try {
8160
- if (await readFile(lockPath, "utf8") === lockOwner) await unlink(lockPath);
8250
+ if (await readFile(ownerPath, "utf8") === lockOwner) await rm(lockPath, {
8251
+ recursive: true,
8252
+ force: true
8253
+ });
8161
8254
  } catch (error) {
8162
8255
  if (!isMissing(error)) throw error;
8163
8256
  }
8164
8257
  }
8165
8258
  }
8259
+ async isStaleLock(lockPath) {
8260
+ try {
8261
+ return Date.now() - (await stat(lockPath)).mtimeMs > LOCK_STALE_MS;
8262
+ } catch (error) {
8263
+ return isMissing(error);
8264
+ }
8265
+ }
8166
8266
  };
8167
8267
  }
8168
8268
  });
@@ -8170,6 +8270,9 @@ var init_firebase_session_store = __esm({
8170
8270
  // src/services/request-credential.ts
8171
8271
  import "dotenv/config";
8172
8272
  import { readFileSync as readFileSync2, unlinkSync } from "fs";
8273
+ function sessionSignedOutError() {
8274
+ return new AuthenticationError("Your Lua CLI session was signed out.\n\n Signing out of the Lua dashboard, desktop or mobile app also ends CLI sessions.\n Run `lua auth configure` to sign in again.", "invalid_credentials", void 0, true);
8275
+ }
8173
8276
  function loadStoredApiKey() {
8174
8277
  try {
8175
8278
  return readFileSync2(CREDENTIALS_FILE, "utf8").trim() || null;
@@ -8183,6 +8286,24 @@ function isRequestCredential(value3) {
8183
8286
  async function bearerFor(credential) {
8184
8287
  return isRequestCredential(credential) ? credential.bearer() : credential;
8185
8288
  }
8289
+ async function registerSessionIfNeeded(live, authUrl) {
8290
+ try {
8291
+ if (typeof claimsOfFirebaseIdToken(live.idToken)[LUA_SESSION_ID_CLAIM] === "string") return void 0;
8292
+ const response = await luaFetch(`${authUrl}/auth/sessions/register`, {
8293
+ method: "POST",
8294
+ headers: {
8295
+ Authorization: `Bearer ${live.idToken}`
8296
+ }
8297
+ });
8298
+ if (!response.ok) return void 0;
8299
+ const registered = await response.json().catch(() => null);
8300
+ if (typeof registered?.token !== "string") return void 0;
8301
+ const exchanged = await exchangeFirebaseCustomToken(registered.token);
8302
+ return exchanged.uid === live.uid ? exchanged : void 0;
8303
+ } catch {
8304
+ return void 0;
8305
+ }
8306
+ }
8186
8307
  async function resolveRequestCredential() {
8187
8308
  if (process.env.LUA_API_KEY) return new StaticRequestCredential(process.env.LUA_API_KEY, "environment");
8188
8309
  const store = new FirebaseSessionStore();
@@ -8192,15 +8313,22 @@ async function resolveRequestCredential() {
8192
8313
  if (storedApiKey) return new StaticRequestCredential(storedApiKey, "stored");
8193
8314
  throw new AuthenticationError("No Lua CLI authentication found. Run `lua auth configure` or set LUA_API_KEY.", "invalid_credentials", void 0, true);
8194
8315
  }
8316
+ async function clearStoredFirebaseSession() {
8317
+ const store = new FirebaseSessionStore();
8318
+ const session = await store.read();
8319
+ return session ? store.clearIfGeneration(session.generation) : false;
8320
+ }
8195
8321
  var StaticRequestCredential, FirebaseRequestCredential;
8196
8322
  var init_request_credential = __esm({
8197
8323
  "src/services/request-credential.ts"() {
8198
8324
  "use strict";
8325
+ init_dist();
8199
8326
  init_constants();
8200
8327
  init_auth_error();
8201
8328
  init_lua_fetch();
8202
8329
  init_firebase_session();
8203
8330
  init_firebase_session_store();
8331
+ __name(sessionSignedOutError, "sessionSignedOutError");
8204
8332
  __name(loadStoredApiKey, "loadStoredApiKey");
8205
8333
  __name(isRequestCredential, "isRequestCredential");
8206
8334
  __name(bearerFor, "bearerFor");
@@ -8244,28 +8372,355 @@ var init_request_credential = __esm({
8244
8372
  }
8245
8373
  async refreshBearer() {
8246
8374
  let live;
8375
+ let rejected = false;
8247
8376
  await this.store.update(async (stored) => {
8248
- if (!stored) {
8249
- throw new AuthenticationError("Your Lua CLI session has expired. Run `lua auth configure`.", "invalid_credentials");
8377
+ if (!stored) throw sessionSignedOutError();
8378
+ try {
8379
+ live = await refreshFirebaseSession({
8380
+ idToken: "",
8381
+ refreshToken: stored.refreshToken,
8382
+ expiresAt: 0,
8383
+ uid: stored.firebaseUid
8384
+ });
8385
+ } catch (error) {
8386
+ if (!(error instanceof FirebaseSessionRejectedError)) throw error;
8387
+ rejected = true;
8388
+ return null;
8250
8389
  }
8251
- live = await refreshFirebaseSession({
8252
- idToken: "",
8253
- refreshToken: stored.refreshToken,
8254
- expiresAt: 0,
8255
- uid: stored.firebaseUid
8256
- });
8390
+ live = await registerSessionIfNeeded(live, stored.authUrl) ?? live;
8257
8391
  return {
8258
8392
  ...stored,
8259
8393
  refreshToken: live.refreshToken,
8260
8394
  firebaseUid: live.uid
8261
8395
  };
8262
8396
  });
8397
+ if (rejected) throw sessionSignedOutError();
8263
8398
  if (!live) throw new Error("Firebase session refresh did not return a session.");
8264
8399
  this.liveSession = live;
8265
8400
  return live.idToken;
8266
8401
  }
8267
8402
  };
8403
+ __name(registerSessionIfNeeded, "registerSessionIfNeeded");
8268
8404
  __name(resolveRequestCredential, "resolveRequestCredential");
8405
+ __name(clearStoredFirebaseSession, "clearStoredFirebaseSession");
8406
+ }
8407
+ });
8408
+
8409
+ // src/errors/cli.error.ts
8410
+ function apiErrorDetail(error) {
8411
+ return {
8412
+ serverCode: error?.code,
8413
+ issues: error?.issues,
8414
+ upstream: error?.upstream,
8415
+ requestId: error?.requestId,
8416
+ vendor: error?.vendor,
8417
+ retryAfterSeconds: error?.retryAfterSeconds,
8418
+ reason: error?.reason,
8419
+ providerStatus: error?.providerStatus,
8420
+ keyOwner: error?.keyOwner
8421
+ };
8422
+ }
8423
+ function isAccessDeniedError(error) {
8424
+ if (CliError.isCliError(error)) return error.statusCode === 403;
8425
+ return error instanceof Error && error.message.startsWith("Access denied (403)");
8426
+ }
8427
+ function upstreamUnavailableHint(upstream, requestId) {
8428
+ const service = typeof upstream === "string" && upstream ? `its ${upstream} service` : "a service behind it";
8429
+ const ref = typeof requestId === "string" && requestId ? ` If it persists, quote request ${requestId}.` : "";
8430
+ return `The Lua API is up, but ${service} is temporarily unavailable (503 UPSTREAM_UNAVAILABLE) \u2014 retry in a moment.${ref}`;
8431
+ }
8432
+ function vendorUnavailableHint(vendor, requestId, retryAfterSeconds) {
8433
+ const name = typeof vendor === "string" && vendor ? VENDOR_LABELS[vendor] ?? vendor : "a vendor it depends on";
8434
+ const ref = typeof requestId === "string" && requestId ? ` If it persists, quote request ${requestId}.` : "";
8435
+ const retry = typeof retryAfterSeconds === "number" ? retryAfterSeconds > VENDOR_RETRY_SOON_SECONDS ? `retry in about ${Math.ceil(retryAfterSeconds)} s` : "retry in a moment" : "the request may have applied at the vendor \u2014 check before retrying";
8436
+ return `The Lua API is up, but ${name} is temporarily unavailable (503 VENDOR_UNAVAILABLE) \u2014 ${retry}.${ref}`;
8437
+ }
8438
+ function providerRejectionReasonOf(reason) {
8439
+ return typeof reason === "string" && PROVIDER_REJECTION_REASONS.has(reason) ? reason : void 0;
8440
+ }
8441
+ function providerKeyOwnerOf(keyOwner) {
8442
+ return keyOwner === "byok" || keyOwner === "platform" ? keyOwner : void 0;
8443
+ }
8444
+ function providerStatusOf(status) {
8445
+ return typeof status === "number" && Number.isInteger(status) && status >= 100 && status <= 599 ? status : void 0;
8446
+ }
8447
+ function providerRejectedHint(reason, providerStatus, keyOwner) {
8448
+ const owner = providerKeyOwnerOf(keyOwner);
8449
+ const status = providerStatusOf(providerStatus);
8450
+ const at = status !== void 0 ? ` (the provider answered HTTP ${status})` : "";
8451
+ switch (providerRejectionReasonOf(reason)) {
8452
+ case "invalid_api_key":
8453
+ if (owner === "platform") return `The provider refused Lua's platform key${at} \u2014 ${PROVIDER_REJECTED_LUA_SIDE}.`;
8454
+ return `The provider refused ${owner === "byok" ? "your organization's own API key" : "the API key behind this agent"}${at} \u2014 check the provider key in the agent's model settings at ${MODEL_SETTINGS_URL}. ${PROVIDER_REJECTED_NO_RETRY}`;
8455
+ case "forbidden":
8456
+ if (owner === "platform") return `Lua's platform key is not permitted to use this model${at} \u2014 ${PROVIDER_REJECTED_LUA_SIDE}.`;
8457
+ return `${owner === "byok" ? "Your organization's provider key" : "The provider key behind this agent"} is not permitted to use this model${at} \u2014 check the key's access with the provider, or change the agent's model. ${PROVIDER_REJECTED_NO_RETRY}`;
8458
+ case "model_not_found":
8459
+ if (owner === "platform") return `The provider does not know the model id Lua configured${at} \u2014 ${PROVIDER_REJECTED_LUA_SIDE}.`;
8460
+ return `The provider does not know this model id${at} \u2014 change the agent's model in its settings at ${MODEL_SETTINGS_URL} to one the provider serves. ${PROVIDER_REJECTED_NO_RETRY}`;
8461
+ case "quota_exhausted":
8462
+ if (owner === "platform") return `Lua's quota or billing allowance with this provider is exhausted${at} \u2014 ${PROVIDER_REJECTED_LUA_SIDE}.`;
8463
+ return `The provider's quota or billing allowance for ${owner === "byok" ? "your organization's key" : "this key"} is exhausted${at} \u2014 top up or raise the limit with the provider. ${PROVIDER_REJECTED_NO_RETRY}`;
8464
+ case "content_refused":
8465
+ return `The provider's content policy declined this request as written${at} \u2014 adjust the request and send it again.`;
8466
+ case "bad_request":
8467
+ return `The provider could not accept the request as sent${at} \u2014 adjust the request (shorter input, fewer or smaller attachments, a supported format) and send it again.`;
8468
+ default:
8469
+ return `The model provider behind this agent refused the request${at} \u2014 ${owner === "platform" ? PROVIDER_REJECTED_LUA_SIDE : owner === "byok" ? `check the agent's model settings and the provider key at ${MODEL_SETTINGS_URL}` : `check the agent's model settings, or contact Lua support if the agent uses Lua's platform key`}. ${PROVIDER_REJECTED_NO_RETRY}`;
8470
+ }
8471
+ }
8472
+ function authHint(error) {
8473
+ if (error.suppressDefaultRemediation) return void 0;
8474
+ if (error.reason === "no_agent_access") {
8475
+ return [
8476
+ "Your API key is valid, but it does not have access to the agentId in lua.skill.yaml \u2014 the agent belongs",
8477
+ "to another account or organization, was deleted or transferred, or the yaml was copied from another project.",
8478
+ "Check the configured agent and switch if needed:",
8479
+ " lua agents (list agents you have access to)",
8480
+ " lua init (re-select the agent for this project)"
8481
+ ].join("\n");
8482
+ }
8483
+ return "Re-authenticate or check your API key: lua auth configure \xB7 https://admin.heylua.ai";
8484
+ }
8485
+ function numericStatus(error) {
8486
+ const candidate = error.statusCode ?? error.status;
8487
+ return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : void 0;
8488
+ }
8489
+ function classifyCliError(error) {
8490
+ if (CliError.isCliError(error)) {
8491
+ return {
8492
+ code: error.code,
8493
+ exitCode: error.exitCode,
8494
+ message: error.message,
8495
+ hint: error.hint,
8496
+ statusCode: error.statusCode,
8497
+ serverCode: error.serverCode,
8498
+ issues: error.issues
8499
+ };
8500
+ }
8501
+ if (AuthenticationError.isAuthenticationError(error)) {
8502
+ return {
8503
+ code: "auth",
8504
+ exitCode: CLI_EXIT.AUTH,
8505
+ message: error.message,
8506
+ hint: authHint(error)
8507
+ };
8508
+ }
8509
+ const e = typeof error === "object" && error !== null ? error : {};
8510
+ const message = typeof e.message === "string" && e.message.length > 0 ? e.message : error instanceof Error ? error.name : String(error ?? "Unknown error");
8511
+ if (e.name === "WorkflowLocalUsageError" || typeof e.code === "string" && e.code.startsWith("commander.")) {
8512
+ return {
8513
+ code: "usage",
8514
+ exitCode: CLI_EXIT.USAGE,
8515
+ message
8516
+ };
8517
+ }
8518
+ const status = numericStatus(e);
8519
+ if (status !== void 0) {
8520
+ const statusCode = status;
8521
+ if (status === 401) return {
8522
+ code: "auth",
8523
+ exitCode: CLI_EXIT.AUTH,
8524
+ message,
8525
+ statusCode
8526
+ };
8527
+ if (status === 403) return {
8528
+ code: "forbidden",
8529
+ exitCode: CLI_EXIT.FORBIDDEN,
8530
+ message,
8531
+ statusCode
8532
+ };
8533
+ if (status === 404) return {
8534
+ code: "not_found",
8535
+ exitCode: CLI_EXIT.NOT_FOUND,
8536
+ message,
8537
+ statusCode
8538
+ };
8539
+ if (status >= 400 && status < 500) return {
8540
+ code: `http_${status}`,
8541
+ exitCode: CLI_EXIT.FORBIDDEN,
8542
+ message,
8543
+ statusCode
8544
+ };
8545
+ if (status >= 500 || status === 0) return {
8546
+ code: "unavailable",
8547
+ exitCode: CLI_EXIT.UNAVAILABLE,
8548
+ message,
8549
+ statusCode
8550
+ };
8551
+ }
8552
+ const causeCode = e.cause?.code;
8553
+ 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)) {
8554
+ return {
8555
+ code: "unavailable",
8556
+ exitCode: CLI_EXIT.UNAVAILABLE,
8557
+ message,
8558
+ hint: UNAVAILABLE_HINT
8559
+ };
8560
+ }
8561
+ return {
8562
+ code: "error",
8563
+ exitCode: CLI_EXIT.ERROR,
8564
+ message
8565
+ };
8566
+ }
8567
+ var CLI_EXIT, CliError, NETWORK_ERRNO, NETWORK_MESSAGE, UNAVAILABLE_HINT, VENDOR_RETRY_SOON_SECONDS, VENDOR_LABELS, PROVIDER_REJECTED_SERVER_CODE, PROVIDER_REJECTED_HTTP_STATUS, PROVIDER_REJECTION_REASONS, PROVIDER_REJECTED_NO_RETRY, PROVIDER_REJECTED_LUA_SIDE, MODEL_SETTINGS_URL;
8568
+ var init_cli_error = __esm({
8569
+ "src/errors/cli.error.ts"() {
8570
+ "use strict";
8571
+ init_auth_error();
8572
+ CLI_EXIT = {
8573
+ OK: 0,
8574
+ ERROR: 1,
8575
+ USAGE: 2,
8576
+ NOT_FOUND: 3,
8577
+ AUTH: 9,
8578
+ FORBIDDEN: 10,
8579
+ UNAVAILABLE: 11,
8580
+ PROVIDER_REJECTED: 12
8581
+ };
8582
+ __name(apiErrorDetail, "apiErrorDetail");
8583
+ CliError = class _CliError extends Error {
8584
+ static {
8585
+ __name(this, "CliError");
8586
+ }
8587
+ isCliError = true;
8588
+ code;
8589
+ exitCode;
8590
+ hint;
8591
+ statusCode;
8592
+ serverCode;
8593
+ issues;
8594
+ constructor(code, message, options = {}) {
8595
+ super(message);
8596
+ this.name = "CliError";
8597
+ this.code = code;
8598
+ this.exitCode = options.exitCode ?? CLI_EXIT.ERROR;
8599
+ this.hint = options.hint;
8600
+ this.statusCode = options.statusCode;
8601
+ this.serverCode = options.serverCode;
8602
+ this.issues = options.issues?.length ? options.issues : void 0;
8603
+ if (Error.captureStackTrace) Error.captureStackTrace(this, _CliError);
8604
+ }
8605
+ /** Bad arguments, an unknown action, no project — exit 2. */
8606
+ static usage(message, hint) {
8607
+ return new _CliError("usage", message, {
8608
+ exitCode: CLI_EXIT.USAGE,
8609
+ hint
8610
+ });
8611
+ }
8612
+ /** The named thing does not exist — exit 3. */
8613
+ static notFound(message, hint) {
8614
+ return new _CliError("not_found", message, {
8615
+ exitCode: CLI_EXIT.NOT_FOUND,
8616
+ hint,
8617
+ statusCode: 404
8618
+ });
8619
+ }
8620
+ /** The credential may not do this — exit 10. */
8621
+ static forbidden(message, hint) {
8622
+ return new _CliError("forbidden", message, {
8623
+ exitCode: CLI_EXIT.FORBIDDEN,
8624
+ hint,
8625
+ statusCode: 403
8626
+ });
8627
+ }
8628
+ /**
8629
+ * The model provider behind the agent refused the request (LUA-820) — a 424 `PROVIDER_REJECTED` body, or a chat
8630
+ * stream `error` chunk carrying that code — `provider_rejected`, exit 12, the hint picked by `reason` / `keyOwner`
8631
+ * (`providerRejectedHint`). The message is the server's typed line ("Your model provider rejected the request
8632
+ * (401 invalid_api_key): …"). Never a re-login or a network hint: the Lua session and the network are fine — the
8633
+ * provider ANSWERED and said no, and the same request fails identically on a retry.
8634
+ */
8635
+ static providerRejected(message, detail = {}, options = {}) {
8636
+ return new _CliError("provider_rejected", message, {
8637
+ exitCode: CLI_EXIT.PROVIDER_REJECTED,
8638
+ hint: options.hint ?? providerRejectedHint(detail.reason, detail.providerStatus, detail.keyOwner),
8639
+ statusCode: options.statusCode ?? PROVIDER_REJECTED_HTTP_STATUS,
8640
+ serverCode: PROVIDER_REJECTED_SERVER_CODE,
8641
+ issues: detail.issues
8642
+ });
8643
+ }
8644
+ /**
8645
+ * An API refusal the site already holds the status of (LUA-766) — classified by the same table the top-level
8646
+ * classifier applies to an untyped error: 401 auth · 403 forbidden · 404 not_found · other 4xx `http_<status>`
8647
+ * (10) · 5xx / 0 unavailable (11, with the network hint unless the site gives its own — or the body's code
8648
+ * picks one: a 503 UPSTREAM_UNAVAILABLE names the Lua service behind the API, LUA-810) · no status `error` (1).
8649
+ * The body's code can also pick the CLASS: a 424 `PROVIDER_REJECTED` is `provider_rejected` (12) with the
8650
+ * per-reason hint (LUA-820) — a 424 WITHOUT the code stays the opaque `http_424`. A command that reads
8651
+ * `response.error.statusCode` throws through here, so `lua logs` on a 503 exits 11 like every other verb instead
8652
+ * of printing the message itself and then throwing an exit-1 `Error`.
8653
+ */
8654
+ static fromStatus(statusCode, message, hint, detail = {}) {
8655
+ if (detail.serverCode === PROVIDER_REJECTED_SERVER_CODE) {
8656
+ return _CliError.providerRejected(message, detail, {
8657
+ hint,
8658
+ statusCode
8659
+ });
8660
+ }
8661
+ const reported = classifyCliError(Object.assign(new Error(message), {
8662
+ statusCode
8663
+ }));
8664
+ const codeHint = detail.serverCode === "UPSTREAM_UNAVAILABLE" ? upstreamUnavailableHint(detail.upstream, detail.requestId) : detail.serverCode === "VENDOR_UNAVAILABLE" ? vendorUnavailableHint(detail.vendor, detail.requestId, detail.retryAfterSeconds) : void 0;
8665
+ const classHint = reported.exitCode === CLI_EXIT.UNAVAILABLE ? UNAVAILABLE_HINT : reported.hint;
8666
+ return new _CliError(reported.code, message, {
8667
+ exitCode: reported.exitCode,
8668
+ hint: hint ?? codeHint ?? classHint,
8669
+ statusCode,
8670
+ serverCode: detail.serverCode,
8671
+ issues: detail.issues
8672
+ });
8673
+ }
8674
+ static isCliError(error) {
8675
+ return error instanceof _CliError || typeof error === "object" && error !== null && error.isCliError === true;
8676
+ }
8677
+ };
8678
+ __name(isAccessDeniedError, "isAccessDeniedError");
8679
+ NETWORK_ERRNO = /* @__PURE__ */ new Set([
8680
+ "ECONNREFUSED",
8681
+ "ECONNRESET",
8682
+ "ENOTFOUND",
8683
+ "ETIMEDOUT",
8684
+ "EAI_AGAIN",
8685
+ "EPIPE",
8686
+ "EHOSTUNREACH",
8687
+ "ENETUNREACH",
8688
+ "UND_ERR_CONNECT_TIMEOUT",
8689
+ "UND_ERR_HEADERS_TIMEOUT",
8690
+ "UND_ERR_BODY_TIMEOUT",
8691
+ "UND_ERR_SOCKET"
8692
+ ]);
8693
+ NETWORK_MESSAGE = /fetch failed|socket hang up|network request failed|request timeout|ECONNREFUSED|ENOTFOUND/i;
8694
+ UNAVAILABLE_HINT = "The Lua API could not be reached \u2014 check your network and https://status.heylua.ai, then retry.";
8695
+ __name(upstreamUnavailableHint, "upstreamUnavailableHint");
8696
+ VENDOR_RETRY_SOON_SECONDS = 5;
8697
+ VENDOR_LABELS = {
8698
+ unified: "Unified.to",
8699
+ github: "GitHub",
8700
+ pusher: "Pusher",
8701
+ google: "Google"
8702
+ };
8703
+ __name(vendorUnavailableHint, "vendorUnavailableHint");
8704
+ PROVIDER_REJECTED_SERVER_CODE = "PROVIDER_REJECTED";
8705
+ PROVIDER_REJECTED_HTTP_STATUS = 424;
8706
+ PROVIDER_REJECTION_REASONS = /* @__PURE__ */ new Set([
8707
+ "invalid_api_key",
8708
+ "forbidden",
8709
+ "model_not_found",
8710
+ "content_refused",
8711
+ "quota_exhausted",
8712
+ "bad_request"
8713
+ ]);
8714
+ __name(providerRejectionReasonOf, "providerRejectionReasonOf");
8715
+ __name(providerKeyOwnerOf, "providerKeyOwnerOf");
8716
+ __name(providerStatusOf, "providerStatusOf");
8717
+ PROVIDER_REJECTED_NO_RETRY = "Retrying the same request will fail identically.";
8718
+ PROVIDER_REJECTED_LUA_SIDE = "a Lua-side model configuration problem, not your request or settings \u2014 contact Lua support if it persists";
8719
+ MODEL_SETTINGS_URL = "https://admin.heylua.ai";
8720
+ __name(providerRejectedHint, "providerRejectedHint");
8721
+ __name(authHint, "authHint");
8722
+ __name(numericStatus, "numericStatus");
8723
+ __name(classifyCliError, "classifyCliError");
8269
8724
  }
8270
8725
  });
8271
8726
 
@@ -8279,6 +8734,10 @@ async function classifyErrorResponse(response) {
8279
8734
  errorData = {};
8280
8735
  }
8281
8736
  if (response.status === 401) {
8737
+ if (serverCodeOf(errorData.code, errorData.error) === SESSION_REVOKED_CODE) {
8738
+ await clearStoredFirebaseSession().catch(() => false);
8739
+ throw sessionSignedOutError();
8740
+ }
8282
8741
  const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
8283
8742
  if (serverMessage && /not an admin/i.test(serverMessage)) {
8284
8743
  throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
@@ -8404,6 +8863,7 @@ var init_http_client = __esm({
8404
8863
  "src/api/http.client.ts"() {
8405
8864
  "use strict";
8406
8865
  init_dist();
8866
+ init_dist();
8407
8867
  init_auth_error();
8408
8868
  init_cli_error();
8409
8869
  init_lua_fetch();
@@ -8521,6 +8981,21 @@ var init_http_client = __esm({
8521
8981
  return Math.max(100, Math.random() * exponential);
8522
8982
  }
8523
8983
  /**
8984
+ * The wait before the next attempt: the client's jittered exponential backoff, floored by the server's
8985
+ * `retryAfterSeconds` on a 429 (the limiter's word is final) and on an idempotent read (GET / HEAD). LUA-810: a
8986
+ * POST / PUT / PATCH / DELETE that met a 5xx keeps the client's own backoff — every 503 body carries
8987
+ * `retryAfterSeconds: 5` (`CONTROL_UNAVAILABLE`, `UPSTREAM_UNAVAILABLE`), which floored all three waits at 5 s:
8988
+ * a ≥15 s stall on a write that may already have landed, and retrying an ambiguous write harder does not make
8989
+ * it less ambiguous. The client's own schedule is ≤1 s + ≤2 s + ≤4 s.
8990
+ */
8991
+ retryDelayMs(attempt, error, method) {
8992
+ const own = this.calculateBackoff(attempt);
8993
+ const advised = Number(error?.retryAfterSeconds ?? 0) * 1e3;
8994
+ const verb = (method ?? "GET").toUpperCase();
8995
+ const honourAdvice = error?.statusCode === 429 || verb === "GET" || verb === "HEAD";
8996
+ return honourAdvice ? Math.max(own, advised) : own;
8997
+ }
8998
+ /**
8524
8999
  * Wraps request with retry logic for transient failures
8525
9000
  * @param url - The full URL to request
8526
9001
  * @param options - Fetch API request options
@@ -8554,8 +9029,7 @@ var init_http_client = __esm({
8554
9029
  throw error;
8555
9030
  }
8556
9031
  if (attempt < maxRetries) {
8557
- const serverDelay = Number(lastResult?.error?.retryAfterSeconds ?? 0) * 1e3;
8558
- const backoff = Math.max(this.calculateBackoff(attempt), serverDelay);
9032
+ const backoff = this.retryDelayMs(attempt, lastResult?.error, options.method);
8559
9033
  await new Promise((resolve3) => setTimeout(resolve3, backoff));
8560
9034
  }
8561
9035
  }
@@ -8714,23 +9188,25 @@ var init_http_client = __esm({
8714
9188
  }
8715
9189
  });
8716
9190
 
8717
- // src/api/auth.api.service.ts
8718
- var init_auth_api_service = __esm({
8719
- "src/api/auth.api.service.ts"() {
9191
+ // src/api/cli-credentials.api.service.ts
9192
+ var init_cli_credentials_api_service = __esm({
9193
+ "src/api/cli-credentials.api.service.ts"() {
8720
9194
  "use strict";
8721
9195
  init_http_client();
9196
+ init_dist();
8722
9197
  }
8723
9198
  });
8724
9199
 
8725
- // src/services/auth.ts
8726
- import "dotenv/config";
8727
- var init_auth = __esm({
8728
- "src/services/auth.ts"() {
9200
+ // src/services/credential-operational-context.ts
9201
+ var init_credential_operational_context = __esm({
9202
+ "src/services/credential-operational-context.ts"() {
8729
9203
  "use strict";
8730
- init_auth_api_service();
9204
+ init_dist();
9205
+ init_cli_credentials_api_service();
8731
9206
  init_constants();
8732
9207
  init_auth_error();
8733
9208
  init_cli_error();
9209
+ init_request_credential();
8734
9210
  }
8735
9211
  });
8736
9212
 
@@ -9029,7 +9505,7 @@ function walkWorkspace(rootDir, opts = {}) {
9029
9505
  const refs = [];
9030
9506
  const contentByHash = /* @__PURE__ */ new Map();
9031
9507
  let totalSize = 0;
9032
- const visit = /* @__PURE__ */ __name4((relPrefix) => {
9508
+ const visit = /* @__PURE__ */ __name5((relPrefix) => {
9033
9509
  const absDir = relPrefix ? join4(rootDir, relPrefix) : rootDir;
9034
9510
  let entries;
9035
9511
  try {
@@ -9323,21 +9799,21 @@ function walk2(root, prefix, out) {
9323
9799
  }
9324
9800
  }
9325
9801
  }
9326
- var __defProp4, __name4, FILE_HASH_LENGTH, SKIP_DIRECTORIES, ARCHIVE_ONLY_SKIP_DIRECTORIES, DEFAULT_MAX_FILE_BYTES, KIND_BY_EXT, CHECK_BLOBS_MAX_HASHES, BackupHttpError, BackupHttpClient, DEFAULT_CONCURRENCY, CREDENTIAL_PATHS, WINDOWS_ABSOLUTE_PATH, ARCHIVE_SCHEMA_VERSION;
9802
+ var __defProp5, __name5, FILE_HASH_LENGTH, SKIP_DIRECTORIES, ARCHIVE_ONLY_SKIP_DIRECTORIES, DEFAULT_MAX_FILE_BYTES, KIND_BY_EXT, CHECK_BLOBS_MAX_HASHES, BackupHttpError, BackupHttpClient, DEFAULT_CONCURRENCY, CREDENTIAL_PATHS, WINDOWS_ABSOLUTE_PATH, ARCHIVE_SCHEMA_VERSION;
9327
9803
  var init_dist3 = __esm({
9328
9804
  "../shared-source-sync/dist/index.mjs"() {
9329
9805
  "use strict";
9330
- __defProp4 = Object.defineProperty;
9331
- __name4 = /* @__PURE__ */ __name((target, value3) => __defProp4(target, "name", { value: value3, configurable: true }), "__name");
9806
+ __defProp5 = Object.defineProperty;
9807
+ __name5 = /* @__PURE__ */ __name((target, value3) => __defProp5(target, "name", { value: value3, configurable: true }), "__name");
9332
9808
  FILE_HASH_LENGTH = 16;
9333
9809
  __name(hashContentTruncated, "hashContentTruncated");
9334
- __name4(hashContentTruncated, "hashContentTruncated");
9810
+ __name5(hashContentTruncated, "hashContentTruncated");
9335
9811
  __name(sha256Hex, "sha256Hex");
9336
- __name4(sha256Hex, "sha256Hex");
9812
+ __name5(sha256Hex, "sha256Hex");
9337
9813
  __name(matchesFileHash, "matchesFileHash");
9338
- __name4(matchesFileHash, "matchesFileHash");
9814
+ __name5(matchesFileHash, "matchesFileHash");
9339
9815
  __name(combineFileHashes, "combineFileHashes");
9340
- __name4(combineFileHashes, "combineFileHashes");
9816
+ __name5(combineFileHashes, "combineFileHashes");
9341
9817
  SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
9342
9818
  "node_modules",
9343
9819
  "dist",
@@ -9354,9 +9830,9 @@ var init_dist3 = __esm({
9354
9830
  ]);
9355
9831
  DEFAULT_MAX_FILE_BYTES = 256 * 1024;
9356
9832
  __name(shouldSkipDirectory, "shouldSkipDirectory");
9357
- __name4(shouldSkipDirectory, "shouldSkipDirectory");
9833
+ __name5(shouldSkipDirectory, "shouldSkipDirectory");
9358
9834
  __name(shouldSkipFile, "shouldSkipFile");
9359
- __name4(shouldSkipFile, "shouldSkipFile");
9835
+ __name5(shouldSkipFile, "shouldSkipFile");
9360
9836
  KIND_BY_EXT = {
9361
9837
  ".ts": "source",
9362
9838
  ".tsx": "source",
@@ -9368,16 +9844,16 @@ var init_dist3 = __esm({
9368
9844
  ".toml": "config"
9369
9845
  };
9370
9846
  __name(classifyFile, "classifyFile");
9371
- __name4(classifyFile, "classifyFile");
9847
+ __name5(classifyFile, "classifyFile");
9372
9848
  __name(walkWorkspace, "walkWorkspace");
9373
- __name4(walkWorkspace, "walkWorkspace");
9849
+ __name5(walkWorkspace, "walkWorkspace");
9374
9850
  CHECK_BLOBS_MAX_HASHES = 500;
9375
9851
  BackupHttpError = class extends Error {
9376
9852
  static {
9377
9853
  __name(this, "BackupHttpError");
9378
9854
  }
9379
9855
  static {
9380
- __name4(this, "BackupHttpError");
9856
+ __name5(this, "BackupHttpError");
9381
9857
  }
9382
9858
  status;
9383
9859
  endpoint;
@@ -9392,7 +9868,7 @@ var init_dist3 = __esm({
9392
9868
  __name(this, "BackupHttpClient");
9393
9869
  }
9394
9870
  static {
9395
- __name4(this, "BackupHttpClient");
9871
+ __name5(this, "BackupHttpClient");
9396
9872
  }
9397
9873
  options;
9398
9874
  fetchFn;
@@ -9497,17 +9973,17 @@ var init_dist3 = __esm({
9497
9973
  };
9498
9974
  DEFAULT_CONCURRENCY = 10;
9499
9975
  __name(uploadBlobs, "uploadBlobs");
9500
- __name4(uploadBlobs, "uploadBlobs");
9976
+ __name5(uploadBlobs, "uploadBlobs");
9501
9977
  __name(decodeBlob, "decodeBlob");
9502
- __name4(decodeBlob, "decodeBlob");
9978
+ __name5(decodeBlob, "decodeBlob");
9503
9979
  __name(verifyDownloaded, "verifyDownloaded");
9504
- __name4(verifyDownloaded, "verifyDownloaded");
9980
+ __name5(verifyDownloaded, "verifyDownloaded");
9505
9981
  __name(downloadBlobs, "downloadBlobs");
9506
- __name4(downloadBlobs, "downloadBlobs");
9982
+ __name5(downloadBlobs, "downloadBlobs");
9507
9983
  __name(resolveBackupFileTarget, "resolveBackupFileTarget");
9508
- __name4(resolveBackupFileTarget, "resolveBackupFileTarget");
9984
+ __name5(resolveBackupFileTarget, "resolveBackupFileTarget");
9509
9985
  __name(restoreFromBlobs, "restoreFromBlobs");
9510
- __name4(restoreFromBlobs, "restoreFromBlobs");
9986
+ __name5(restoreFromBlobs, "restoreFromBlobs");
9511
9987
  CREDENTIAL_PATHS = /* @__PURE__ */ new Set([
9512
9988
  ".env",
9513
9989
  ".lua/config.json",
@@ -9515,22 +9991,22 @@ var init_dist3 = __esm({
9515
9991
  ]);
9516
9992
  WINDOWS_ABSOLUTE_PATH = /^[a-z]:\//i;
9517
9993
  __name(normalizeWorkspaceRelativePath, "normalizeWorkspaceRelativePath");
9518
- __name4(normalizeWorkspaceRelativePath, "normalizeWorkspaceRelativePath");
9994
+ __name5(normalizeWorkspaceRelativePath, "normalizeWorkspaceRelativePath");
9519
9995
  __name(isCredentialPersistencePath, "isCredentialPersistencePath");
9520
- __name4(isCredentialPersistencePath, "isCredentialPersistencePath");
9996
+ __name5(isCredentialPersistencePath, "isCredentialPersistencePath");
9521
9997
  __name(pushAgentBackup, "pushAgentBackup");
9522
- __name4(pushAgentBackup, "pushAgentBackup");
9998
+ __name5(pushAgentBackup, "pushAgentBackup");
9523
9999
  __name(pullAgentBackup, "pullAgentBackup");
9524
- __name4(pullAgentBackup, "pullAgentBackup");
10000
+ __name5(pullAgentBackup, "pullAgentBackup");
9525
10001
  ARCHIVE_SCHEMA_VERSION = 1;
9526
10002
  __name(encodeWorkspaceArchive, "encodeWorkspaceArchive");
9527
- __name4(encodeWorkspaceArchive, "encodeWorkspaceArchive");
10003
+ __name5(encodeWorkspaceArchive, "encodeWorkspaceArchive");
9528
10004
  __name(decodeWorkspaceArchive, "decodeWorkspaceArchive");
9529
- __name4(decodeWorkspaceArchive, "decodeWorkspaceArchive");
10005
+ __name5(decodeWorkspaceArchive, "decodeWorkspaceArchive");
9530
10006
  __name(writeArchiveToWorkspace, "writeArchiveToWorkspace");
9531
- __name4(writeArchiveToWorkspace, "writeArchiveToWorkspace");
10007
+ __name5(writeArchiveToWorkspace, "writeArchiveToWorkspace");
9532
10008
  __name(walk2, "walk");
9533
- __name4(walk2, "walk");
10009
+ __name5(walk2, "walk");
9534
10010
  }
9535
10011
  });
9536
10012
 
@@ -10415,8 +10891,8 @@ async function requireAuth() {
10415
10891
  var init_command_utils = __esm({
10416
10892
  "src/utils/command-utils.ts"() {
10417
10893
  "use strict";
10418
- init_auth();
10419
10894
  init_request_credential();
10895
+ init_credential_operational_context();
10420
10896
  init_files();
10421
10897
  init_cli();
10422
10898
  init_cli_error();
@@ -12822,7 +13298,7 @@ var init_job_api_service = __esm({
12822
13298
  if (response.success && response.data) {
12823
13299
  return new JobInstance(this, response.data);
12824
13300
  }
12825
- throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Failed to get job");
13301
+ throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Failed to get job", void 0, apiErrorDetail(response.error));
12826
13302
  }
12827
13303
  /**
12828
13304
  * Creates a new job for the agent.
@@ -13014,11 +13490,48 @@ var init_ai_api_service = __esm({
13014
13490
  });
13015
13491
 
13016
13492
  // src/api/integrations.api.service.ts
13017
- var IntegrationsApiService;
13493
+ function integrationPassthroughErrorFields(error) {
13494
+ const fields = {};
13495
+ if (!error) return fields;
13496
+ const strings = [
13497
+ "code",
13498
+ "legacyCode",
13499
+ "legacyMessage",
13500
+ "vendor",
13501
+ "requestId"
13502
+ ];
13503
+ for (const key of strings) {
13504
+ const value3 = error[key];
13505
+ if (typeof value3 === "string" && value3.length > 0) fields[key] = value3;
13506
+ }
13507
+ const numbers = [
13508
+ "statusCode",
13509
+ "retryAfterSeconds",
13510
+ "vendorStatus"
13511
+ ];
13512
+ for (const key of numbers) {
13513
+ const value3 = error[key];
13514
+ if (typeof value3 === "number" && Number.isFinite(value3)) fields[key] = value3;
13515
+ }
13516
+ if (fields.statusCode !== void 0) fields.status = fields.statusCode;
13517
+ return fields;
13518
+ }
13519
+ var IntegrationPassthroughError, IntegrationsApiService;
13018
13520
  var init_integrations_api_service = __esm({
13019
13521
  "src/api/integrations.api.service.ts"() {
13020
13522
  "use strict";
13021
13523
  init_http_client();
13524
+ IntegrationPassthroughError = class extends Error {
13525
+ static {
13526
+ __name(this, "IntegrationPassthroughError");
13527
+ }
13528
+ constructor(message, fields = {}) {
13529
+ super(message);
13530
+ this.name = "IntegrationPassthroughError";
13531
+ Object.assign(this, fields);
13532
+ }
13533
+ };
13534
+ __name(integrationPassthroughErrorFields, "integrationPassthroughErrorFields");
13022
13535
  IntegrationsApiService = class extends HttpClient {
13023
13536
  static {
13024
13537
  __name(this, "IntegrationsApiService");
@@ -13034,12 +13547,14 @@ var init_integrations_api_service = __esm({
13034
13547
  * Sandbox-facing wrapper: returns the raw provider envelope
13035
13548
  * `{ status, headers, data }` (provider error statuses relayed faithfully in
13036
13549
  * `status`), and throws only on route-level failures (no connection,
13037
- * passthrough disabled, rate limited, transport error).
13550
+ * passthrough disabled, rate limited, transport error) — as an
13551
+ * `IntegrationPassthroughError` carrying the server's typed fields (LUA-860);
13552
+ * `message` is the server's line, unchanged from the bare `Error` it used to be.
13038
13553
  */
13039
13554
  async passthroughForSandbox(integrationType, request) {
13040
13555
  const result = await this.passthrough(integrationType, request);
13041
13556
  if (!result.success || !result.data) {
13042
- throw new Error(result.error?.message || `Integration passthrough failed for '${integrationType}'`);
13557
+ throw new IntegrationPassthroughError(result.error?.message || `Integration passthrough failed for '${integrationType}'`, integrationPassthroughErrorFields(result.error));
13043
13558
  }
13044
13559
  return result.data;
13045
13560
  }