lua-cli 3.32.6 → 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.
@@ -711,6 +711,9 @@ function creatorUserId(identity) {
711
711
  function actingUserId(identity) {
712
712
  return creatorUserId(identity);
713
713
  }
714
+ function isWorkflowSignalEventSite(value3) {
715
+ return typeof value3 === "string" && WORKFLOW_SIGNAL_EVENT_SITES.includes(value3);
716
+ }
714
717
  function shouldSkipArchive(run, manifestSha256, sinkSha256) {
715
718
  if (!run.completedAt || !run.exportedAt || run.exportedAt < run.completedAt) return false;
716
719
  return !!manifestSha256 && manifestSha256 === sinkSha256;
@@ -850,6 +853,23 @@ function workflowHitlArmUnsupportedMessage(type, id, container) {
850
853
  function workflowHitlArmShapeMessage(type, id, shape) {
851
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\``;
852
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
+ }
853
873
  function groupCount(re) {
854
874
  let n2 = GROUP_COUNT.get(re);
855
875
  if (n2 === void 0) {
@@ -1089,19 +1109,27 @@ function resolveEffectiveFeature(row, catalogDefault) {
1089
1109
  default: catalogDefault
1090
1110
  };
1091
1111
  }
1092
- function isFeatureRow(value3) {
1093
- 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;
1094
1120
  }
1095
1121
  function effectiveAgentFeatureRows(base, override) {
1096
1122
  const merged = /* @__PURE__ */ new Map();
1097
- for (const [name, row] of Object.entries(base ?? {})) {
1098
- 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, {
1099
1126
  row,
1100
1127
  origin: "baseAgent"
1101
1128
  });
1102
1129
  }
1103
- for (const [name, row] of Object.entries(override ?? {})) {
1104
- 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, {
1105
1133
  row,
1106
1134
  origin: "subAgent"
1107
1135
  });
@@ -1121,7 +1149,15 @@ function effectiveAgentFeatureRows(base, override) {
1121
1149
  ]))
1122
1150
  };
1123
1151
  }
1124
- 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, 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;
1125
1161
  var init_dist = __esm({
1126
1162
  "../shared-types/dist/index.mjs"() {
1127
1163
  "use strict";
@@ -1824,6 +1860,10 @@ This text is who you are for this person. As you learn them, their name, their w
1824
1860
  TEMPLATE_TRIGGER_URL_ENV_PREFIX = "LUA_TRIGGER_URL__";
1825
1861
  __name(triggerUrlEnvKey, "triggerUrlEnvKey");
1826
1862
  __name2(triggerUrlEnvKey, "triggerUrlEnvKey");
1863
+ TEMPLATE_INSTALL_POLICY_PER_WORKSPACE_VALUES = Object.freeze([
1864
+ "single",
1865
+ "multiple"
1866
+ ]);
1827
1867
  SUBJECT_TYPES = [
1828
1868
  "user",
1829
1869
  "apiKey",
@@ -2008,6 +2048,8 @@ This text is who you are for this person. As you learn them, their name, their w
2008
2048
  __name2(formatLuaClientHeader, "formatLuaClientHeader");
2009
2049
  __name(luaClientMetricLabels, "luaClientMetricLabels");
2010
2050
  __name2(luaClientMetricLabels, "luaClientMetricLabels");
2051
+ LUA_SESSION_ID_CLAIM = "luaSessionId";
2052
+ SESSION_REVOKED_CODE = "SESSION_REVOKED";
2011
2053
  AUTHZ_PROJECTION_VERSION = 1;
2012
2054
  ProjectedScopeSchema = z3.string().min(1).max(128);
2013
2055
  DisplayRoleSchema = z3.object({
@@ -2167,6 +2209,15 @@ This text is who you are for this person. As you learn them, their name, their w
2167
2209
  ...WORKFLOW_RUN_IDLE,
2168
2210
  ...WORKFLOW_RUN_TERMINAL
2169
2211
  ];
2212
+ WORKFLOW_RUN_GATE_KINDS = [
2213
+ "start-consent",
2214
+ "quota",
2215
+ "billing",
2216
+ "org_archived",
2217
+ "disabled",
2218
+ "exception",
2219
+ "budget"
2220
+ ];
2170
2221
  WORKFLOW_STEP_STATUSES = [
2171
2222
  "pending",
2172
2223
  "ready",
@@ -2188,6 +2239,13 @@ This text is who you are for this person. As you learn them, their name, their w
2188
2239
  "running",
2189
2240
  "cancellation_requested"
2190
2241
  ];
2242
+ WORKFLOW_SIGNAL_EVENT_SITES = [
2243
+ "webhook",
2244
+ "trigger",
2245
+ "device-trigger"
2246
+ ];
2247
+ __name(isWorkflowSignalEventSite, "isWorkflowSignalEventSite");
2248
+ __name2(isWorkflowSignalEventSite, "isWorkflowSignalEventSite");
2191
2249
  ARCHIVE_WINDOW_MARGIN_DAYS = 7;
2192
2250
  __name(shouldSkipArchive, "shouldSkipArchive");
2193
2251
  __name2(shouldSkipArchive, "shouldSkipArchive");
@@ -2230,6 +2288,16 @@ This text is who you are for this person. As you learn them, their name, their w
2230
2288
  __name2(scheduledTimeKey, "scheduledTimeKey");
2231
2289
  __name(scheduledWorkflowRunIdForTime, "scheduledWorkflowRunIdForTime");
2232
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
+ ];
2233
2301
  WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES = 64 * 1024;
2234
2302
  WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES = 256 * 1024;
2235
2303
  WORKFLOW_RETRY_BACKOFFS = [
@@ -2352,6 +2420,13 @@ This text is who you are for this person. As you learn them, their name, their w
2352
2420
  min: 60,
2353
2421
  max: 2592e3
2354
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");
2355
2430
  REDACTED_PLACEHOLDER = "[REDACTED]";
2356
2431
  PROVIDER_MESSAGE_MAX_CHARS = 300;
2357
2432
  ERROR_MESSAGE_MAX_CHARS = 2e3;
@@ -2676,10 +2751,71 @@ listed here; never invent a target.`;
2676
2751
  __name2(effectiveFeatureActive, "effectiveFeatureActive");
2677
2752
  __name(resolveEffectiveFeature, "resolveEffectiveFeature");
2678
2753
  __name2(resolveEffectiveFeature, "resolveEffectiveFeature");
2679
- __name(isFeatureRow, "isFeatureRow");
2680
- __name2(isFeatureRow, "isFeatureRow");
2754
+ __name(asFeatureRow, "asFeatureRow");
2755
+ __name2(asFeatureRow, "asFeatureRow");
2756
+ __name(agentFeatureBagCarries, "agentFeatureBagCarries");
2757
+ __name2(agentFeatureBagCarries, "agentFeatureBagCarries");
2681
2758
  __name(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2682
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");
2683
2819
  }
2684
2820
  });
2685
2821
 
@@ -2787,7 +2923,7 @@ function isMapDescriptor(v) {
2787
2923
  if (v === null || typeof v !== "object" || Array.isArray(v)) return false;
2788
2924
  const d = v;
2789
2925
  const keys = Object.keys(d);
2790
- 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");
2791
2927
  if ("value" in d) return keys.length === 1;
2792
2928
  if ("template" in d) return keys.length === 1 && typeof d.template === "string";
2793
2929
  if ("requestContextPath" in d) return keys.length === 1 && typeof d.requestContextPath === "string";
@@ -2924,13 +3060,13 @@ function validateApproverBlock(node, opts = {
2924
3060
  path: "approval"
2925
3061
  }) {
2926
3062
  const issues = [];
2927
- const push = /* @__PURE__ */ __name3((code, path3, message, severity = "error") => issues.push({
3063
+ const push = /* @__PURE__ */ __name4((code, path3, message, severity = "error") => issues.push({
2928
3064
  code,
2929
3065
  path: path3,
2930
3066
  severity,
2931
3067
  message
2932
3068
  }), "push");
2933
- const checkSpec = /* @__PURE__ */ __name3((spec, path3) => {
3069
+ const checkSpec = /* @__PURE__ */ __name4((spec, path3) => {
2934
3070
  const r = ApproverSpecSchema.safeParse(spec);
2935
3071
  if (!r.success) {
2936
3072
  const users = spec?.users;
@@ -3214,7 +3350,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3214
3350
  static: true
3215
3351
  }) {
3216
3352
  const issues = [];
3217
- const err = /* @__PURE__ */ __name3((code, message, path3, stepId) => {
3353
+ const err = /* @__PURE__ */ __name4((code, message, path3, stepId) => {
3218
3354
  issues.push({
3219
3355
  code,
3220
3356
  message,
@@ -3223,7 +3359,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3223
3359
  stepId
3224
3360
  });
3225
3361
  }, "err");
3226
- const warn = /* @__PURE__ */ __name3((code, message, path3, stepId) => {
3362
+ const warn = /* @__PURE__ */ __name4((code, message, path3, stepId) => {
3227
3363
  issues.push({
3228
3364
  code,
3229
3365
  message,
@@ -3280,7 +3416,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3280
3416
  }
3281
3417
  declaredKeys.add(key);
3282
3418
  });
3283
- 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");
3284
3420
  const credentialsRef = envelopeWorkspace?.credentialsRef;
3285
3421
  if (undeclaredKey(credentialsRef)) {
3286
3422
  err("connection-key-undeclared", connectionKeyUndeclaredMessage("workspace.credentialsRef", credentialsRef), "workspace.credentialsRef");
@@ -3288,7 +3424,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3288
3424
  const seen = /* @__PURE__ */ new Map();
3289
3425
  let nodeCount = 0;
3290
3426
  const upstream = /* @__PURE__ */ new Set();
3291
- const checkId = /* @__PURE__ */ __name3((id, path3) => {
3427
+ const checkId = /* @__PURE__ */ __name4((id, path3) => {
3292
3428
  nodeCount += 1;
3293
3429
  if (seen.has(id)) {
3294
3430
  err("duplicate-step-id", `step id "${id}" is declared twice (first at ${seen.get(id)})`, path3, id);
@@ -3296,9 +3432,9 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3296
3432
  seen.set(id, path3);
3297
3433
  }
3298
3434
  }, "checkId");
3299
- const checkPolicyEnums = /* @__PURE__ */ __name3((node, path3) => {
3435
+ const checkPolicyEnums = /* @__PURE__ */ __name4((node, path3) => {
3300
3436
  const id = singleId(node);
3301
- const check = /* @__PURE__ */ __name3((member, allowed) => {
3437
+ const check = /* @__PURE__ */ __name4((member, allowed) => {
3302
3438
  const value22 = node[member];
3303
3439
  if (value22 === void 0 || typeof value22 === "string" && allowed.includes(value22)) return;
3304
3440
  err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path3}.${member}`, id);
@@ -3306,7 +3442,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3306
3442
  check("sideEffects", WORKFLOW_SIDE_EFFECTS);
3307
3443
  check("jobResources", WORKFLOW_JOB_RESOURCES);
3308
3444
  }, "checkPolicyEnums");
3309
- const checkRetry = /* @__PURE__ */ __name3((node, path3) => {
3445
+ const checkRetry = /* @__PURE__ */ __name4((node, path3) => {
3310
3446
  const r = node.retry;
3311
3447
  if (!r) return;
3312
3448
  const id = singleId(node);
@@ -3332,7 +3468,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3332
3468
  }
3333
3469
  }
3334
3470
  }, "checkRetry");
3335
- const checkTimeout = /* @__PURE__ */ __name3((node, path3) => {
3471
+ const checkTimeout = /* @__PURE__ */ __name4((node, path3) => {
3336
3472
  const t = node.timeoutSeconds;
3337
3473
  if (t === void 0) return;
3338
3474
  const id = singleId(node);
@@ -3351,7 +3487,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3351
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);
3352
3488
  }
3353
3489
  }, "checkTimeout");
3354
- const checkSpecialistRole = /* @__PURE__ */ __name3((node, path3) => {
3490
+ const checkSpecialistRole = /* @__PURE__ */ __name4((node, path3) => {
3355
3491
  const role = node.role;
3356
3492
  const hasRef = typeof role.ref === "string";
3357
3493
  const hasInline = role.name !== void 0 || role.instructions !== void 0 || Array.isArray(role.tools) && role.tools.length > 0;
@@ -3383,7 +3519,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3383
3519
  }
3384
3520
  }
3385
3521
  }, "checkSpecialistRole");
3386
- const checkRequiredConnections = /* @__PURE__ */ __name3((node, path3) => {
3522
+ const checkRequiredConnections = /* @__PURE__ */ __name4((node, path3) => {
3387
3523
  const required = node.requiredConnections;
3388
3524
  if (!Array.isArray(required)) return;
3389
3525
  const undeclared = required.filter(undeclaredKey);
@@ -3396,7 +3532,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3396
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));
3397
3533
  }
3398
3534
  }, "checkRequiredConnections");
3399
- const checkTier = /* @__PURE__ */ __name3((node, path3) => {
3535
+ const checkTier = /* @__PURE__ */ __name4((node, path3) => {
3400
3536
  const id = singleId(node);
3401
3537
  if (node.workspace && node.workspace !== "inherit" && node.tier !== void 0 && node.tier !== "job") {
3402
3538
  err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path3}.workspace`, id);
@@ -3412,7 +3548,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3412
3548
  err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path3}.model`, id);
3413
3549
  }
3414
3550
  }, "checkTier");
3415
- const checkModel = /* @__PURE__ */ __name3((node, path3) => {
3551
+ const checkModel = /* @__PURE__ */ __name4((node, path3) => {
3416
3552
  if (node.type !== "agent" || typeof node.model !== "string") return;
3417
3553
  const registry = opts.approvedModels;
3418
3554
  if (registry === void 0) return;
@@ -3427,7 +3563,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3427
3563
  const resolved = normalizeModelId(node.model, registry);
3428
3564
  if (!resolved.ok) err("model-unresolved", modelUnresolvedMessage(resolved), `${path3}.model`, id);
3429
3565
  }, "checkModel");
3430
- const checkWorkspace = /* @__PURE__ */ __name3((node, path3) => {
3566
+ const checkWorkspace = /* @__PURE__ */ __name4((node, path3) => {
3431
3567
  const id = singleId(node);
3432
3568
  const ws = workspaceOf(node);
3433
3569
  if (isJobTier(node) && opts.policy && opts.policy.jobTier !== true) {
@@ -3450,6 +3586,9 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3450
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);
3451
3587
  }
3452
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
+ }
3453
3592
  if (ws && ws !== "inherit") {
3454
3593
  if (!envelopeWorkspace && !opts.mayInherit) {
3455
3594
  err("workspace-not-declared", `"${id}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path3}.workspace`, id);
@@ -3469,16 +3608,16 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3469
3608
  }
3470
3609
  }, "checkWorkspace");
3471
3610
  const outputSchemas = /* @__PURE__ */ new Map();
3472
- const recordOutputSchema = /* @__PURE__ */ __name3((node) => {
3611
+ const recordOutputSchema = /* @__PURE__ */ __name4((node) => {
3473
3612
  const schema = node.type === "step" ? node.step.outputSchema : node.type === "agent" ? node.outputSchema : void 0;
3474
3613
  if (schema !== void 0) outputSchemas.set(singleId(node), schema);
3475
3614
  }, "recordOutputSchema");
3476
- const checkMapMembers = /* @__PURE__ */ __name3((cfg, basePath, id) => {
3615
+ const checkMapMembers = /* @__PURE__ */ __name4((cfg, basePath, id) => {
3477
3616
  for (const m of malformedMapMembers(cfg)) {
3478
3617
  warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id, m), `${basePath}.${m.member}`, id);
3479
3618
  }
3480
3619
  }, "checkMapMembers");
3481
- const checkInputShape = /* @__PURE__ */ __name3((node, path3) => {
3620
+ const checkInputShape = /* @__PURE__ */ __name4((node, path3) => {
3482
3621
  const input = node.input;
3483
3622
  if (input === void 0) return;
3484
3623
  const id = singleId(node);
@@ -3488,11 +3627,11 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3488
3627
  }
3489
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);
3490
3629
  }, "checkInputShape");
3491
- const checkBodyInput = /* @__PURE__ */ __name3((body, path3, container) => {
3630
+ const checkBodyInput = /* @__PURE__ */ __name4((body, path3, container) => {
3492
3631
  if (body.type === "workflow" || body.input === void 0) return;
3493
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));
3494
3633
  }, "checkBodyInput");
3495
- const checkSingle = /* @__PURE__ */ __name3((node, path3, depth) => {
3634
+ const checkSingle = /* @__PURE__ */ __name4((node, path3, depth) => {
3496
3635
  recordOutputSchema(node);
3497
3636
  if (node.type === "workflow" && (typeof node.workflowId !== "string" || node.workflowId.length === 0)) {
3498
3637
  checkId(node.id, path3);
@@ -3541,7 +3680,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3541
3680
  }
3542
3681
  }
3543
3682
  }, "checkSingle");
3544
- const checkHitl = /* @__PURE__ */ __name3((node, path3) => {
3683
+ const checkHitl = /* @__PURE__ */ __name4((node, path3) => {
3545
3684
  if (node.type === "waitForSignal") {
3546
3685
  const w = node;
3547
3686
  checkId(w.id, path3);
@@ -3580,7 +3719,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3580
3719
  }
3581
3720
  }
3582
3721
  }, "checkHitl");
3583
- const checkHitlArm = /* @__PURE__ */ __name3((node, path3, container) => {
3722
+ const checkHitlArm = /* @__PURE__ */ __name4((node, path3, container) => {
3584
3723
  if (!workflowContainerRunsHitlArm(container)) {
3585
3724
  checkId(node.id, path3);
3586
3725
  err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container), path3, node.id);
@@ -3588,7 +3727,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3588
3727
  }
3589
3728
  checkHitl(node, path3);
3590
3729
  }, "checkHitlArm");
3591
- const checkArm = /* @__PURE__ */ __name3((arm, path3, depth, container) => {
3730
+ const checkArm = /* @__PURE__ */ __name4((arm, path3, depth, container) => {
3592
3731
  if (arm.type === "mapping") {
3593
3732
  checkId(arm.id, path3);
3594
3733
  checkMapMembers(readMapConfig(arm.mapConfig), `${path3}.mapConfig`, arm.id);
@@ -3824,7 +3963,7 @@ function isWellFormedPredicate(p) {
3824
3963
  }
3825
3964
  function canonicalJson(value22) {
3826
3965
  const seen = /* @__PURE__ */ new WeakSet();
3827
- const encode = /* @__PURE__ */ __name3((v) => {
3966
+ const encode = /* @__PURE__ */ __name4((v) => {
3828
3967
  if (v === null || typeof v === "number" || typeof v === "boolean") return JSON.stringify(v);
3829
3968
  if (typeof v === "string") return JSON.stringify(v);
3830
3969
  if (typeof v === "bigint") return JSON.stringify(`${v}n`);
@@ -3851,7 +3990,7 @@ function hashGraph(g) {
3851
3990
  function compilePlan(g) {
3852
3991
  const steps = {};
3853
3992
  const order = [];
3854
- const addNode = /* @__PURE__ */ __name3((id, node) => {
3993
+ const addNode = /* @__PURE__ */ __name4((id, node) => {
3855
3994
  if (id in steps) {
3856
3995
  throw new WorkflowPlanError("duplicate-step-id", `Duplicate step id "${id}" in definition.graph`);
3857
3996
  }
@@ -4181,7 +4320,7 @@ function renderRef(ref) {
4181
4320
  function step(s) {
4182
4321
  const id = stepIdOf(s);
4183
4322
  return {
4184
- path: /* @__PURE__ */ __name3((p) => ({
4323
+ path: /* @__PURE__ */ __name4((p) => ({
4185
4324
  path: p === "" ? `stepResults.${id}` : `stepResults.${id}.${p}`
4186
4325
  }), "path")
4187
4326
  };
@@ -4269,7 +4408,7 @@ function resolvePlacements(calls) {
4269
4408
  const declared = /* @__PURE__ */ new Map();
4270
4409
  const placedBy = /* @__PURE__ */ new Map();
4271
4410
  const allIds = /* @__PURE__ */ new Map();
4272
- const claimId = /* @__PURE__ */ __name3((id, callIndex) => {
4411
+ const claimId = /* @__PURE__ */ __name4((id, callIndex) => {
4273
4412
  const first = allIds.get(id);
4274
4413
  if (first !== void 0 && first !== callIndex) {
4275
4414
  issues.push({
@@ -4309,7 +4448,7 @@ function resolvePlacements(calls) {
4309
4448
  break;
4310
4449
  }
4311
4450
  });
4312
- const armMapPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
4451
+ const armMapPlacementIssue = /* @__PURE__ */ __name4((node, ref, i, container) => {
4313
4452
  if (!ref.armMap || node.type === "mapping" || isHitlNode2(node)) return void 0;
4314
4453
  const id = nodeIdOf(node);
4315
4454
  if ((container === "foreach" || container === "loop") && node.type !== "workflow") {
@@ -4330,7 +4469,7 @@ function resolvePlacements(calls) {
4330
4469
  }
4331
4470
  return void 0;
4332
4471
  }, "armMapPlacementIssue");
4333
- const hitlPlacementIssue = /* @__PURE__ */ __name3((node, ref, i, container) => {
4472
+ const hitlPlacementIssue = /* @__PURE__ */ __name4((node, ref, i, container) => {
4334
4473
  if (!isHitlNode2(node)) return void 0;
4335
4474
  const id = node.id;
4336
4475
  if (ref.armMap) {
@@ -4351,7 +4490,7 @@ function resolvePlacements(calls) {
4351
4490
  }
4352
4491
  return void 0;
4353
4492
  }, "hitlPlacementIssue");
4354
- const resolve3 = /* @__PURE__ */ __name3((ref, i, allowMapping, container) => {
4493
+ const resolve3 = /* @__PURE__ */ __name4((ref, i, allowMapping, container) => {
4355
4494
  if ("node" in ref) {
4356
4495
  if (ref.node.type === "mapping" && !allowMapping) {
4357
4496
  issues.push({
@@ -4406,7 +4545,7 @@ function resolvePlacements(calls) {
4406
4545
  placedBy.set(ref.ref, i);
4407
4546
  return d.node;
4408
4547
  }, "resolve");
4409
- const claim = /* @__PURE__ */ __name3((ref, i, allowMapping, container) => {
4548
+ const claim = /* @__PURE__ */ __name4((ref, i, allowMapping, container) => {
4410
4549
  if ("ref" in ref) {
4411
4550
  resolve3(ref, i, allowMapping, container);
4412
4551
  return;
@@ -4441,7 +4580,7 @@ function resolvePlacements(calls) {
4441
4580
  }
4442
4581
  });
4443
4582
  const graph = [];
4444
- const lookup = /* @__PURE__ */ __name3((ref) => {
4583
+ const lookup = /* @__PURE__ */ __name4((ref) => {
4445
4584
  const n2 = "node" in ref ? ref.node : declared.get(ref.ref)?.node;
4446
4585
  if (!n2 || !ref.armMap || n2.type === "mapping" || isHitlNode2(n2)) return n2;
4447
4586
  return inlineContainerArm(ref.armMap, n2);
@@ -4584,11 +4723,11 @@ function seedLedgerFromRun(run, steps, targetPlan, opts = {}) {
4584
4723
  const seeded = [];
4585
4724
  const unseeded = [];
4586
4725
  const known = new Set(Object.keys(targetPlan.steps));
4587
- const parentOf = /* @__PURE__ */ __name3((id) => {
4726
+ const parentOf = /* @__PURE__ */ __name4((id) => {
4588
4727
  const m = /^(.*)(\[\d+\]|#\d+)$/.exec(id);
4589
4728
  return m ? m[1] : void 0;
4590
4729
  }, "parentOf");
4591
- const dependsOf = /* @__PURE__ */ __name3((id) => {
4730
+ const dependsOf = /* @__PURE__ */ __name4((id) => {
4592
4731
  const node = targetPlan.steps[id];
4593
4732
  if (node) return node.dependsOn;
4594
4733
  const parent = parentOf(id);
@@ -4675,7 +4814,7 @@ function replayLedger(g, ledger) {
4675
4814
  startedAt: 0,
4676
4815
  ...ledger.requestContext
4677
4816
  };
4678
- const ctxFor = /* @__PURE__ */ __name3((id) => ({
4817
+ const ctxFor = /* @__PURE__ */ __name4((id) => ({
4679
4818
  initData: ledger.initData,
4680
4819
  stepResults: ancestorResults(plan, id, rows22),
4681
4820
  state: ledger.state ?? {},
@@ -4757,7 +4896,7 @@ function ancestorResults(plan, id, rows22) {
4757
4896
  const out = {};
4758
4897
  const joinAliased = /* @__PURE__ */ new Set();
4759
4898
  const seen = /* @__PURE__ */ new Set();
4760
- const take = /* @__PURE__ */ __name3((rowId) => {
4899
+ const take = /* @__PURE__ */ __name4((rowId) => {
4761
4900
  const hit = replayResultOf(rows22.get(rowId), plan.steps[rowId]);
4762
4901
  if (!hit) return void 0;
4763
4902
  if (!joinAliased.has(rowId)) out[rowId] = hit.value;
@@ -4774,7 +4913,7 @@ function ancestorResults(plan, id, rows22) {
4774
4913
  }
4775
4914
  return hit;
4776
4915
  }, "take");
4777
- const walk22 = /* @__PURE__ */ __name3((ids) => {
4916
+ const walk22 = /* @__PURE__ */ __name4((ids) => {
4778
4917
  for (const dep of ids) {
4779
4918
  if (seen.has(dep)) continue;
4780
4919
  seen.add(dep);
@@ -5128,7 +5267,7 @@ function timeZoneSupported(tz) {
5128
5267
  }
5129
5268
  function validateBusinessHours(cal, path3 = "businessHours") {
5130
5269
  const issues = [];
5131
- const issue = /* @__PURE__ */ __name3((p, message) => issues.push({
5270
+ const issue = /* @__PURE__ */ __name4((p, message) => issues.push({
5132
5271
  code: "business-hours-invalid",
5133
5272
  path: p,
5134
5273
  message
@@ -5197,7 +5336,7 @@ function formatter(tz) {
5197
5336
  }
5198
5337
  function localParts(ms, tz) {
5199
5338
  const parts = formatter(tz).formatToParts(new Date(ms));
5200
- 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");
5201
5340
  const hour = Number(get("hour")) % 24;
5202
5341
  return {
5203
5342
  year: Number(get("year")),
@@ -5367,7 +5506,7 @@ function matchesEditablePath(pointer, editablePaths, op = "replace") {
5367
5506
  }
5368
5507
  function changedPointers(before, after, base = "") {
5369
5508
  if (before === after) return [];
5370
- 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");
5371
5510
  if (Array.isArray(before) && Array.isArray(after)) {
5372
5511
  if (before.length !== after.length) return [
5373
5512
  base || "/"
@@ -5575,7 +5714,7 @@ function rebaseItemPointer(pointer, itemsPath, index) {
5575
5714
  }
5576
5715
  function validateWorkflowSchedule(schedule, path3 = "/schedule") {
5577
5716
  if (schedule === void 0 || schedule === null) return [];
5578
- const issue = /* @__PURE__ */ __name3((at, detail) => [
5717
+ const issue = /* @__PURE__ */ __name4((at, detail) => [
5579
5718
  {
5580
5719
  code: WORKFLOW_SCHEDULE_SHAPE_ISSUE,
5581
5720
  severity: "error",
@@ -5595,6 +5734,9 @@ function validateWorkflowSchedule(schedule, path3 = "/schedule") {
5595
5734
  if (typeof type !== "string" || !WORKFLOW_SCHEDULE_TYPES.includes(type)) {
5596
5735
  return issue(path3, `\`schedule.type\` ${JSON.stringify(type)} is not one of ${WORKFLOW_SCHEDULE_TYPES.map((t) => `'${t}'`).join(" | ")}`);
5597
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
+ }
5598
5740
  switch (type) {
5599
5741
  case "cron": {
5600
5742
  if (typeof schedule.expression !== "string" || schedule.expression.trim().length === 0) {
@@ -5622,7 +5764,7 @@ function validateWorkflowSchedule(schedule, path3 = "/schedule") {
5622
5764
  }
5623
5765
  function collectEnvTemplateKeys(value22) {
5624
5766
  const keys = /* @__PURE__ */ new Set();
5625
- const walk22 = /* @__PURE__ */ __name3((v) => {
5767
+ const walk22 = /* @__PURE__ */ __name4((v) => {
5626
5768
  if (isEnvRef(v)) {
5627
5769
  keys.add(v.__envRef);
5628
5770
  return;
@@ -5649,7 +5791,7 @@ function collectEnvTemplateKeys(value22) {
5649
5791
  }
5650
5792
  function substituteEnvRefs(value22, overlay) {
5651
5793
  const missing = /* @__PURE__ */ new Set();
5652
- const walk22 = /* @__PURE__ */ __name3((v, slot = false) => {
5794
+ const walk22 = /* @__PURE__ */ __name4((v, slot = false) => {
5653
5795
  if (isEnvRef(v)) {
5654
5796
  if (Object.prototype.hasOwnProperty.call(overlay, v.__envRef)) {
5655
5797
  const s = overlay[v.__envRef];
@@ -5909,25 +6051,27 @@ function needsInheritedWorkspace(graph) {
5909
6051
  }
5910
6052
  return false;
5911
6053
  }
5912
- 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_SCHEDULE_TYPES, WORKFLOW_SCHEDULE_SHAPE_ISSUE, WORKFLOW_SCHEDULE_SHAPES_HINT, isObject, 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;
5913
6055
  var init_dist2 = __esm({
5914
6056
  "../workflow-graph/dist/index.mjs"() {
5915
6057
  "use strict";
5916
6058
  init_dist();
5917
6059
  init_dist();
5918
6060
  init_dist();
6061
+ init_workflow_job_tools();
6062
+ init_workflow_job_tools();
5919
6063
  init_dist();
5920
6064
  init_dist();
5921
6065
  init_dist();
5922
6066
  init_dist();
5923
- __defProp3 = Object.defineProperty;
5924
- __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");
5925
6069
  WorkflowTemplateError = class extends Error {
5926
6070
  static {
5927
6071
  __name(this, "WorkflowTemplateError");
5928
6072
  }
5929
6073
  static {
5930
- __name3(this, "WorkflowTemplateError");
6074
+ __name4(this, "WorkflowTemplateError");
5931
6075
  }
5932
6076
  placeholder;
5933
6077
  constructor(message, placeholder) {
@@ -5936,11 +6080,11 @@ var init_dist2 = __esm({
5936
6080
  }
5937
6081
  };
5938
6082
  __name(isMapConfigObject, "isMapConfigObject");
5939
- __name3(isMapConfigObject, "isMapConfigObject");
6083
+ __name4(isMapConfigObject, "isMapConfigObject");
5940
6084
  __name(parseMapConfig, "parseMapConfig");
5941
- __name3(parseMapConfig, "parseMapConfig");
6085
+ __name4(parseMapConfig, "parseMapConfig");
5942
6086
  __name(mapConfigWire, "mapConfigWire");
5943
- __name3(mapConfigWire, "mapConfigWire");
6087
+ __name4(mapConfigWire, "mapConfigWire");
5944
6088
  TEMPLATE_PLACEHOLDER = /\$\{([^}]*)\}/g;
5945
6089
  TEMPLATE_NAMESPACES = [
5946
6090
  "initData",
@@ -5949,21 +6093,21 @@ var init_dist2 = __esm({
5949
6093
  "stepResults"
5950
6094
  ];
5951
6095
  __name(describeBadPlaceholder, "describeBadPlaceholder");
5952
- __name3(describeBadPlaceholder, "describeBadPlaceholder");
6096
+ __name4(describeBadPlaceholder, "describeBadPlaceholder");
5953
6097
  __name(parseTemplatePlaceholder, "parseTemplatePlaceholder");
5954
- __name3(parseTemplatePlaceholder, "parseTemplatePlaceholder");
6098
+ __name4(parseTemplatePlaceholder, "parseTemplatePlaceholder");
5955
6099
  __name(traverseMappingPath, "traverseMappingPath");
5956
- __name3(traverseMappingPath, "traverseMappingPath");
6100
+ __name4(traverseMappingPath, "traverseMappingPath");
5957
6101
  __name(stringifyTemplateValue, "stringifyTemplateValue");
5958
- __name3(stringifyTemplateValue, "stringifyTemplateValue");
6102
+ __name4(stringifyTemplateValue, "stringifyTemplateValue");
5959
6103
  __name(escapeFence, "escapeFence");
5960
- __name3(escapeFence, "escapeFence");
6104
+ __name4(escapeFence, "escapeFence");
5961
6105
  __name(fenceBlock, "fenceBlock");
5962
- __name3(fenceBlock, "fenceBlock");
6106
+ __name4(fenceBlock, "fenceBlock");
5963
6107
  __name(renderTemplate, "renderTemplate");
5964
- __name3(renderTemplate, "renderTemplate");
6108
+ __name4(renderTemplate, "renderTemplate");
5965
6109
  __name(isMapDescriptor, "isMapDescriptor");
5966
- __name3(isMapDescriptor, "isMapDescriptor");
6110
+ __name4(isMapDescriptor, "isMapDescriptor");
5967
6111
  MAP_DESCRIPTOR_KEYS = [
5968
6112
  "step",
5969
6113
  "path",
@@ -5975,39 +6119,39 @@ var init_dist2 = __esm({
5975
6119
  ];
5976
6120
  MAP_MEMBER_MALFORMED_CODE = "map-member-malformed";
5977
6121
  __name(malformedMapMembers, "malformedMapMembers");
5978
- __name3(malformedMapMembers, "malformedMapMembers");
6122
+ __name4(malformedMapMembers, "malformedMapMembers");
5979
6123
  __name(mapMemberMalformedMessage, "mapMemberMalformedMessage");
5980
- __name3(mapMemberMalformedMessage, "mapMemberMalformedMessage");
6124
+ __name4(mapMemberMalformedMessage, "mapMemberMalformedMessage");
5981
6125
  __name(resolveDescriptor, "resolveDescriptor");
5982
- __name3(resolveDescriptor, "resolveDescriptor");
6126
+ __name4(resolveDescriptor, "resolveDescriptor");
5983
6127
  __name(resolveMapping, "resolveMapping");
5984
- __name3(resolveMapping, "resolveMapping");
5985
- fromInit = /* @__PURE__ */ __name3((path3) => ({
6128
+ __name4(resolveMapping, "resolveMapping");
6129
+ fromInit = /* @__PURE__ */ __name4((path3) => ({
5986
6130
  initData: true,
5987
6131
  path: path3
5988
6132
  }), "fromInit");
5989
- fromStep = /* @__PURE__ */ __name3((s, path3 = "") => {
5990
- 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");
5991
6135
  return {
5992
6136
  step: Array.isArray(s) ? s.map(idOf) : idOf(s),
5993
6137
  path: path3
5994
6138
  };
5995
6139
  }, "fromStep");
5996
- value = /* @__PURE__ */ __name3((v) => ({
6140
+ value = /* @__PURE__ */ __name4((v) => ({
5997
6141
  value: v
5998
6142
  }), "value");
5999
- template = /* @__PURE__ */ __name3((s) => ({
6143
+ template = /* @__PURE__ */ __name4((s) => ({
6000
6144
  template: s
6001
6145
  }), "template");
6002
- fromRequest = /* @__PURE__ */ __name3((path3) => ({
6146
+ fromRequest = /* @__PURE__ */ __name4((path3) => ({
6003
6147
  requestContextPath: path3
6004
6148
  }), "fromRequest");
6005
- rows = /* @__PURE__ */ __name3((s, path3, page) => ({
6149
+ rows = /* @__PURE__ */ __name4((s, path3, page) => ({
6006
6150
  step: typeof s === "string" ? s : s.id,
6007
6151
  path: path3,
6008
6152
  rows: page
6009
6153
  }), "rows");
6010
- fromKnowledge = /* @__PURE__ */ __name3((k) => ({
6154
+ fromKnowledge = /* @__PURE__ */ __name4((k) => ({
6011
6155
  knowledge: k
6012
6156
  }), "fromKnowledge");
6013
6157
  SideEffectsSchema = z4.enum(WORKFLOW_SIDE_EFFECTS);
@@ -6077,7 +6221,7 @@ var init_dist2 = __esm({
6077
6221
  APPROVER_WRITTEN_MAX = 120;
6078
6222
  USER_ID_SHAPED_RE = /^[^\s@]{1,128}$/;
6079
6223
  __name(describeApproverSpecRefusal, "describeApproverSpecRefusal");
6080
- __name3(describeApproverSpecRefusal, "describeApproverSpecRefusal");
6224
+ __name4(describeApproverSpecRefusal, "describeApproverSpecRefusal");
6081
6225
  BINDING_ROOTS = [
6082
6226
  "initData",
6083
6227
  "stepResults",
@@ -6085,28 +6229,28 @@ var init_dist2 = __esm({
6085
6229
  "state"
6086
6230
  ];
6087
6231
  __name(bindingRootsOk, "bindingRootsOk");
6088
- __name3(bindingRootsOk, "bindingRootsOk");
6232
+ __name4(bindingRootsOk, "bindingRootsOk");
6089
6233
  __name(isTemplateBinding, "isTemplateBinding");
6090
- __name3(isTemplateBinding, "isTemplateBinding");
6234
+ __name4(isTemplateBinding, "isTemplateBinding");
6091
6235
  __name(approvalEditable, "approvalEditable");
6092
- __name3(approvalEditable, "approvalEditable");
6236
+ __name4(approvalEditable, "approvalEditable");
6093
6237
  __name(validateApproverBlock, "validateApproverBlock");
6094
- __name3(validateApproverBlock, "validateApproverBlock");
6238
+ __name4(validateApproverBlock, "validateApproverBlock");
6095
6239
  __name(liftRenderedApprover, "liftRenderedApprover");
6096
- __name3(liftRenderedApprover, "liftRenderedApprover");
6240
+ __name4(liftRenderedApprover, "liftRenderedApprover");
6097
6241
  WORKSPACE_TEMPLATE_EXPR_RE = /^\$\{\s*(?:initData|input)\.([^}]+?)\s*\}$/;
6098
6242
  __name(workspaceTemplatePath, "workspaceTemplatePath");
6099
- __name3(workspaceTemplatePath, "workspaceTemplatePath");
6243
+ __name4(workspaceTemplatePath, "workspaceTemplatePath");
6100
6244
  __name(retryBackoffs, "retryBackoffs");
6101
- __name3(retryBackoffs, "retryBackoffs");
6245
+ __name4(retryBackoffs, "retryBackoffs");
6102
6246
  SLEEP_UNTIL_REPLACEMENT = Object.freeze({
6103
6247
  type: "sleep",
6104
6248
  duration: 6e4
6105
6249
  });
6106
6250
  __name(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
6107
- __name3(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
6251
+ __name4(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
6108
6252
  __name(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
6109
- __name3(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
6253
+ __name4(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
6110
6254
  WORKFLOW_CAPS_DEFAULT = Object.freeze({
6111
6255
  maxParallelArms: 16,
6112
6256
  maxForeachConcurrency: 16,
@@ -6131,71 +6275,60 @@ var init_dist2 = __esm({
6131
6275
  "api",
6132
6276
  "user"
6133
6277
  ];
6134
- clone = /* @__PURE__ */ __name3((v) => JSON.parse(JSON.stringify(v)), "clone");
6278
+ clone = /* @__PURE__ */ __name4((v) => JSON.parse(JSON.stringify(v)), "clone");
6135
6279
  __name(fillPolicy, "fillPolicy");
6136
- __name3(fillPolicy, "fillPolicy");
6280
+ __name4(fillPolicy, "fillPolicy");
6137
6281
  __name(fillSingle, "fillSingle");
6138
- __name3(fillSingle, "fillSingle");
6282
+ __name4(fillSingle, "fillSingle");
6139
6283
  __name(fillHitl, "fillHitl");
6140
- __name3(fillHitl, "fillHitl");
6284
+ __name4(fillHitl, "fillHitl");
6141
6285
  __name(fillArm, "fillArm");
6142
- __name3(fillArm, "fillArm");
6286
+ __name4(fillArm, "fillArm");
6143
6287
  __name(fillEntry, "fillEntry");
6144
- __name3(fillEntry, "fillEntry");
6288
+ __name4(fillEntry, "fillEntry");
6145
6289
  __name(withDefaultsFilled, "withDefaultsFilled");
6146
- __name3(withDefaultsFilled, "withDefaultsFilled");
6290
+ __name4(withDefaultsFilled, "withDefaultsFilled");
6147
6291
  CONNECTION_ID_HEX_RE = /^[0-9a-f]{24}$/;
6148
6292
  __name(isConnectionKeyShaped, "isConnectionKeyShaped");
6149
- __name3(isConnectionKeyShaped, "isConnectionKeyShaped");
6293
+ __name4(isConnectionKeyShaped, "isConnectionKeyShaped");
6150
6294
  __name(connectionKeyUndeclaredMessage, "connectionKeyUndeclaredMessage");
6151
- __name3(connectionKeyUndeclaredMessage, "connectionKeyUndeclaredMessage");
6152
- WORKFLOW_JOB_TOOLS = [
6153
- "shell",
6154
- "read",
6155
- "write",
6156
- "edit",
6157
- "glob",
6158
- "grep",
6159
- "git",
6160
- "gh",
6161
- "fetch"
6162
- ];
6295
+ __name4(connectionKeyUndeclaredMessage, "connectionKeyUndeclaredMessage");
6163
6296
  WORKFLOW_JOB_MAX_WORKTREE_ARMS = 8;
6164
6297
  __name(classifyModelProvider, "classifyModelProvider");
6165
- __name3(classifyModelProvider, "classifyModelProvider");
6166
- workspaceOf = /* @__PURE__ */ __name3((node) => node.workspace, "workspaceOf");
6167
- mountsWorkspace = /* @__PURE__ */ __name3((node) => {
6298
+ __name4(classifyModelProvider, "classifyModelProvider");
6299
+ workspaceOf = /* @__PURE__ */ __name4((node) => node.workspace, "workspaceOf");
6300
+ mountsWorkspace = /* @__PURE__ */ __name4((node) => {
6168
6301
  const w = workspaceOf(node);
6169
6302
  return w !== void 0 && w !== "inherit";
6170
6303
  }, "mountsWorkspace");
6171
- isJobTier = /* @__PURE__ */ __name3((node) => node.tier === "job" || mountsWorkspace(node), "isJobTier");
6172
- jobToolsOf = /* @__PURE__ */ __name3((node) => {
6304
+ isJobTier = /* @__PURE__ */ __name4((node) => node.tier === "job" || mountsWorkspace(node), "isJobTier");
6305
+ jobToolsOf = /* @__PURE__ */ __name4((node) => {
6173
6306
  if (node.type === "agent") return node.toolScope?.jobTools;
6174
6307
  return node.jobTools;
6175
6308
  }, "jobToolsOf");
6176
6309
  __name(schemaAtPath, "schemaAtPath");
6177
- __name3(schemaAtPath, "schemaAtPath");
6178
- schemaIsArray = /* @__PURE__ */ __name3((schema) => {
6310
+ __name4(schemaAtPath, "schemaAtPath");
6311
+ schemaIsArray = /* @__PURE__ */ __name4((schema) => {
6179
6312
  if (!schema) return void 0;
6180
6313
  const t = schema.type;
6181
6314
  if (t === void 0) return void 0;
6182
6315
  return Array.isArray(t) ? t.includes("array") : t === "array";
6183
6316
  }, "schemaIsArray");
6184
- isHitlNode = /* @__PURE__ */ __name3((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6185
- isSingleStep = /* @__PURE__ */ __name3((n2) => !isHitlNode(n2), "isSingleStep");
6186
- singleId = /* @__PURE__ */ __name3((s) => s.type === "step" ? s.step.id : s.id, "singleId");
6187
- 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");
6188
6321
  TEMPLATE_STEP_REF = /\$\{\s*stepResults\.([A-Za-z0-9_\-]+)/g;
6189
6322
  __name(templateStepRefs, "templateStepRefs");
6190
- __name3(templateStepRefs, "templateStepRefs");
6323
+ __name4(templateStepRefs, "templateStepRefs");
6191
6324
  __name(readMapConfig, "readMapConfig");
6192
- __name3(readMapConfig, "readMapConfig");
6325
+ __name4(readMapConfig, "readMapConfig");
6193
6326
  __name(mapConfigStepRefs, "mapConfigStepRefs");
6194
- __name3(mapConfigStepRefs, "mapConfigStepRefs");
6327
+ __name4(mapConfigStepRefs, "mapConfigStepRefs");
6195
6328
  __name(nodeStepRefs, "nodeStepRefs");
6196
- __name3(nodeStepRefs, "nodeStepRefs");
6329
+ __name4(nodeStepRefs, "nodeStepRefs");
6197
6330
  __name(validateLuaExtensions, "validateLuaExtensions");
6198
- __name3(validateLuaExtensions, "validateLuaExtensions");
6331
+ __name4(validateLuaExtensions, "validateLuaExtensions");
6199
6332
  EDITABLE_PATH_RE = /^[A-Za-z_][A-Za-z0-9_]*(\[(\*|\d+)\])?(\.[A-Za-z_][A-Za-z0-9_]*(\[(\*|\d+)\])?)*$/;
6200
6333
  PREDICATE_OPS = /* @__PURE__ */ new Set([
6201
6334
  "eq",
@@ -6215,23 +6348,23 @@ var init_dist2 = __esm({
6215
6348
  "not"
6216
6349
  ]);
6217
6350
  __name(isPredicate, "isPredicate");
6218
- __name3(isPredicate, "isPredicate");
6219
- 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");
6220
6353
  __name(isPathOrLiteral, "isPathOrLiteral");
6221
- __name3(isPathOrLiteral, "isPathOrLiteral");
6354
+ __name4(isPathOrLiteral, "isPathOrLiteral");
6222
6355
  __name(isWellFormedPredicate, "isWellFormedPredicate");
6223
- __name3(isWellFormedPredicate, "isWellFormedPredicate");
6356
+ __name4(isWellFormedPredicate, "isWellFormedPredicate");
6224
6357
  GRAPH_HASH_PREFIX = "sha256-cj1:";
6225
6358
  __name(canonicalJson, "canonicalJson");
6226
- __name3(canonicalJson, "canonicalJson");
6359
+ __name4(canonicalJson, "canonicalJson");
6227
6360
  __name(hashGraph, "hashGraph");
6228
- __name3(hashGraph, "hashGraph");
6361
+ __name4(hashGraph, "hashGraph");
6229
6362
  WorkflowPlanError = class extends Error {
6230
6363
  static {
6231
6364
  __name(this, "WorkflowPlanError");
6232
6365
  }
6233
6366
  static {
6234
- __name3(this, "WorkflowPlanError");
6367
+ __name4(this, "WorkflowPlanError");
6235
6368
  }
6236
6369
  code;
6237
6370
  constructor(code, message) {
@@ -6239,47 +6372,47 @@ var init_dist2 = __esm({
6239
6372
  this.name = "WorkflowPlanError";
6240
6373
  }
6241
6374
  };
6242
- isArmStep = /* @__PURE__ */ __name3((e) => isWorkflowArmEntryType(e.type), "isArmStep");
6243
- armStepId = /* @__PURE__ */ __name3((e) => e.type === "step" ? e.step.id : e.id, "armStepId");
6244
- armStepKind = /* @__PURE__ */ __name3((e) => WORKFLOW_ARM_ENTRY_STEP_KINDS[e.type], "armStepKind");
6245
- joinIdOf = /* @__PURE__ */ __name3((entryId) => `${entryId}.join`, "joinIdOf");
6246
- 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");
6247
6380
  __name(compilePlan, "compilePlan");
6248
- __name3(compilePlan, "compilePlan");
6381
+ __name4(compilePlan, "compilePlan");
6249
6382
  PATH_PLACEHOLDER = /^\$\{([^}]+)\}$/;
6250
6383
  MISSING = /* @__PURE__ */ Symbol("predicate.missing");
6251
6384
  __name(resolvePath, "resolvePath");
6252
- __name3(resolvePath, "resolvePath");
6385
+ __name4(resolvePath, "resolvePath");
6253
6386
  __name(walk, "walk");
6254
- __name3(walk, "walk");
6387
+ __name4(walk, "walk");
6255
6388
  __name(resolveValue, "resolveValue");
6256
- __name3(resolveValue, "resolveValue");
6389
+ __name4(resolveValue, "resolveValue");
6257
6390
  __name(evaluatePredicate, "evaluatePredicate");
6258
- __name3(evaluatePredicate, "evaluatePredicate");
6391
+ __name4(evaluatePredicate, "evaluatePredicate");
6259
6392
  __name(compare, "compare");
6260
- __name3(compare, "compare");
6393
+ __name4(compare, "compare");
6261
6394
  __name(derivePredicateLabel, "derivePredicateLabel");
6262
- __name3(derivePredicateLabel, "derivePredicateLabel");
6395
+ __name4(derivePredicateLabel, "derivePredicateLabel");
6263
6396
  __name(renderPredicate, "renderPredicate");
6264
- __name3(renderPredicate, "renderPredicate");
6397
+ __name4(renderPredicate, "renderPredicate");
6265
6398
  __name(wrapLabel, "wrapLabel");
6266
- __name3(wrapLabel, "wrapLabel");
6399
+ __name4(wrapLabel, "wrapLabel");
6267
6400
  __name(renderRef, "renderRef");
6268
- __name3(renderRef, "renderRef");
6269
- 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");
6270
6403
  __name(step, "step");
6271
- __name3(step, "step");
6404
+ __name4(step, "step");
6272
6405
  __name(stepOf, "stepOf");
6273
- __name3(stepOf, "stepOf");
6406
+ __name4(stepOf, "stepOf");
6274
6407
  __name(init, "init");
6275
- __name3(init, "init");
6408
+ __name4(init, "init");
6276
6409
  __name(state, "state");
6277
- __name3(state, "state");
6410
+ __name4(state, "state");
6278
6411
  __name(lit, "lit");
6279
- __name3(lit, "lit");
6412
+ __name4(lit, "lit");
6280
6413
  __name(toPathOrLiteral, "toPathOrLiteral");
6281
- __name3(toPathOrLiteral, "toPathOrLiteral");
6282
- cmp = /* @__PURE__ */ __name3((op) => (l, r) => ({
6414
+ __name4(toPathOrLiteral, "toPathOrLiteral");
6415
+ cmp = /* @__PURE__ */ __name4((op) => (l, r) => ({
6283
6416
  op,
6284
6417
  left: toPathOrLiteral(l),
6285
6418
  right: toPathOrLiteral(r)
@@ -6290,49 +6423,49 @@ var init_dist2 = __esm({
6290
6423
  gte = cmp("gte");
6291
6424
  lt = cmp("lt");
6292
6425
  lte = cmp("lte");
6293
- inSet = /* @__PURE__ */ __name3((v, set) => ({
6426
+ inSet = /* @__PURE__ */ __name4((v, set) => ({
6294
6427
  op: "in",
6295
6428
  value: {
6296
6429
  path: v.path
6297
6430
  },
6298
6431
  set
6299
6432
  }), "inSet");
6300
- notIn = /* @__PURE__ */ __name3((v, set) => ({
6433
+ notIn = /* @__PURE__ */ __name4((v, set) => ({
6301
6434
  op: "notIn",
6302
6435
  value: {
6303
6436
  path: v.path
6304
6437
  },
6305
6438
  set
6306
6439
  }), "notIn");
6307
- exists = /* @__PURE__ */ __name3((ref) => ({
6440
+ exists = /* @__PURE__ */ __name4((ref) => ({
6308
6441
  op: "exists",
6309
6442
  path: ref.path
6310
6443
  }), "exists");
6311
- notExists = /* @__PURE__ */ __name3((ref) => ({
6444
+ notExists = /* @__PURE__ */ __name4((ref) => ({
6312
6445
  op: "notExists",
6313
6446
  path: ref.path
6314
6447
  }), "notExists");
6315
- truthy = /* @__PURE__ */ __name3((ref) => ({
6448
+ truthy = /* @__PURE__ */ __name4((ref) => ({
6316
6449
  op: "truthy",
6317
6450
  value: {
6318
6451
  path: ref.path
6319
6452
  }
6320
6453
  }), "truthy");
6321
- falsy = /* @__PURE__ */ __name3((ref) => ({
6454
+ falsy = /* @__PURE__ */ __name4((ref) => ({
6322
6455
  op: "falsy",
6323
6456
  value: {
6324
6457
  path: ref.path
6325
6458
  }
6326
6459
  }), "falsy");
6327
- and = /* @__PURE__ */ __name3((...args) => ({
6460
+ and = /* @__PURE__ */ __name4((...args) => ({
6328
6461
  op: "and",
6329
6462
  args
6330
6463
  }), "and");
6331
- or = /* @__PURE__ */ __name3((...args) => ({
6464
+ or = /* @__PURE__ */ __name4((...args) => ({
6332
6465
  op: "or",
6333
6466
  args
6334
6467
  }), "or");
6335
- not = /* @__PURE__ */ __name3((arg) => ({
6468
+ not = /* @__PURE__ */ __name4((arg) => ({
6336
6469
  op: "not",
6337
6470
  arg
6338
6471
  }), "not");
@@ -6384,17 +6517,17 @@ var init_dist2 = __esm({
6384
6517
  "text"
6385
6518
  ]);
6386
6519
  __name(continuedFailureValue, "continuedFailureValue");
6387
- __name3(continuedFailureValue, "continuedFailureValue");
6520
+ __name4(continuedFailureValue, "continuedFailureValue");
6388
6521
  __name(isContinuedFailureValue, "isContinuedFailureValue");
6389
- __name3(isContinuedFailureValue, "isContinuedFailureValue");
6390
- isHitlNode2 = /* @__PURE__ */ __name3((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6522
+ __name4(isContinuedFailureValue, "isContinuedFailureValue");
6523
+ isHitlNode2 = /* @__PURE__ */ __name4((n2) => isWorkflowHitlEntryType(n2.type), "isHitlNode");
6391
6524
  __name(inlineContainerArm, "inlineContainerArm");
6392
- __name3(inlineContainerArm, "inlineContainerArm");
6393
- 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");
6394
6527
  __name(entryIds, "entryIds");
6395
- __name3(entryIds, "entryIds");
6528
+ __name4(entryIds, "entryIds");
6396
6529
  __name(resolvePlacements, "resolvePlacements");
6397
- __name3(resolvePlacements, "resolvePlacements");
6530
+ __name4(resolvePlacements, "resolvePlacements");
6398
6531
  GOAL_JUDGE_STEP_ID = "__goal_judge";
6399
6532
  NON_LEAF_KINDS = /* @__PURE__ */ new Set([
6400
6533
  "foreach",
@@ -6402,26 +6535,26 @@ var init_dist2 = __esm({
6402
6535
  ]);
6403
6536
  CONDITIONAL_JOIN_ID = /^conditional@\d+\.join$/;
6404
6537
  __name(isConditionalJoinId, "isConditionalJoinId");
6405
- __name3(isConditionalJoinId, "isConditionalJoinId");
6538
+ __name4(isConditionalJoinId, "isConditionalJoinId");
6406
6539
  __name(isPlainObject, "isPlainObject");
6407
- __name3(isPlainObject, "isPlainObject");
6540
+ __name4(isPlainObject, "isPlainObject");
6408
6541
  __name(leafValue, "leafValue");
6409
- __name3(leafValue, "leafValue");
6542
+ __name4(leafValue, "leafValue");
6410
6543
  __name(runOutputLeaves, "runOutputLeaves");
6411
- __name3(runOutputLeaves, "runOutputLeaves");
6544
+ __name4(runOutputLeaves, "runOutputLeaves");
6412
6545
  __name(deriveRunOutput, "deriveRunOutput");
6413
- __name3(deriveRunOutput, "deriveRunOutput");
6546
+ __name4(deriveRunOutput, "deriveRunOutput");
6414
6547
  __name(subrunSettledOutput, "subrunSettledOutput");
6415
- __name3(subrunSettledOutput, "subrunSettledOutput");
6548
+ __name4(subrunSettledOutput, "subrunSettledOutput");
6416
6549
  __name(seedLedgerFromRun, "seedLedgerFromRun");
6417
- __name3(seedLedgerFromRun, "seedLedgerFromRun");
6418
- 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");
6419
6552
  __name(branchSpecFromConditional, "branchSpecFromConditional");
6420
- __name3(branchSpecFromConditional, "branchSpecFromConditional");
6553
+ __name4(branchSpecFromConditional, "branchSpecFromConditional");
6421
6554
  __name(selectBranchArms, "selectBranchArms");
6422
- __name3(selectBranchArms, "selectBranchArms");
6423
- canonical = /* @__PURE__ */ __name3((v) => JSON.stringify(sortKeys(v)), "canonical");
6424
- sortKeys = /* @__PURE__ */ __name3((v) => {
6555
+ __name4(selectBranchArms, "selectBranchArms");
6556
+ canonical = /* @__PURE__ */ __name4((v) => JSON.stringify(sortKeys(v)), "canonical");
6557
+ sortKeys = /* @__PURE__ */ __name4((v) => {
6425
6558
  if (Array.isArray(v)) return v.map(sortKeys);
6426
6559
  if (v && typeof v === "object") {
6427
6560
  return Object.fromEntries(Object.keys(v).sort().map((k) => [
@@ -6432,65 +6565,65 @@ var init_dist2 = __esm({
6432
6565
  return v;
6433
6566
  }, "sortKeys");
6434
6567
  __name(replayLedger, "replayLedger");
6435
- __name3(replayLedger, "replayLedger");
6568
+ __name4(replayLedger, "replayLedger");
6436
6569
  JOIN = ".join";
6437
- 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");
6438
6571
  __name(replayResultOf, "replayResultOf");
6439
- __name3(replayResultOf, "replayResultOf");
6572
+ __name4(replayResultOf, "replayResultOf");
6440
6573
  __name(ancestorResults, "ancestorResults");
6441
- __name3(ancestorResults, "ancestorResults");
6574
+ __name4(ancestorResults, "ancestorResults");
6442
6575
  __name(inferTaken, "inferTaken");
6443
- __name3(inferTaken, "inferTaken");
6576
+ __name4(inferTaken, "inferTaken");
6444
6577
  __name(countChildren, "countChildren");
6445
- __name3(countChildren, "countChildren");
6578
+ __name4(countChildren, "countChildren");
6446
6579
  FORCE_CANCEL_STALE_MS = 10 * 60 * 1e3;
6447
6580
  TERMINAL = new Set(WORKFLOW_RUN_TERMINAL);
6448
6581
  __name(isTerminalRunStatus, "isTerminalRunStatus");
6449
- __name3(isTerminalRunStatus, "isTerminalRunStatus");
6582
+ __name4(isTerminalRunStatus, "isTerminalRunStatus");
6450
6583
  __name(pruneUndefined, "pruneUndefined");
6451
- __name3(pruneUndefined, "pruneUndefined");
6584
+ __name4(pruneUndefined, "pruneUndefined");
6452
6585
  WORKFLOW_INLINE_RUN_TAG = "inline";
6453
6586
  __name(runOrigin, "runOrigin");
6454
- __name3(runOrigin, "runOrigin");
6587
+ __name4(runOrigin, "runOrigin");
6455
6588
  RUN_ERROR_ISSUES_MAX = 20;
6456
6589
  __name(runErrorIssues, "runErrorIssues");
6457
- __name3(runErrorIssues, "runErrorIssues");
6590
+ __name4(runErrorIssues, "runErrorIssues");
6458
6591
  __name(runNextAction, "runNextAction");
6459
- __name3(runNextAction, "runNextAction");
6592
+ __name4(runNextAction, "runNextAction");
6460
6593
  IN_FLIGHT = new Set(WORKFLOW_STEP_IN_FLIGHT);
6461
6594
  __name(emptyRunCounts, "emptyRunCounts");
6462
- __name3(emptyRunCounts, "emptyRunCounts");
6595
+ __name4(emptyRunCounts, "emptyRunCounts");
6463
6596
  __name(runCountsFromStatusTally, "runCountsFromStatusTally");
6464
- __name3(runCountsFromStatusTally, "runCountsFromStatusTally");
6597
+ __name4(runCountsFromStatusTally, "runCountsFromStatusTally");
6465
6598
  __name(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6466
- __name3(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6599
+ __name4(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6467
6600
  __name(isBillingHeldStep, "isBillingHeldStep");
6468
- __name3(isBillingHeldStep, "isBillingHeldStep");
6601
+ __name4(isBillingHeldStep, "isBillingHeldStep");
6469
6602
  __name(stepEffectiveStatus, "stepEffectiveStatus");
6470
- __name3(stepEffectiveStatus, "stepEffectiveStatus");
6471
- 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");
6472
6605
  __name(runCounts, "runCounts");
6473
- __name3(runCounts, "runCounts");
6606
+ __name4(runCounts, "runCounts");
6474
6607
  __name(isPricedStepReceipt, "isPricedStepReceipt");
6475
- __name3(isPricedStepReceipt, "isPricedStepReceipt");
6608
+ __name4(isPricedStepReceipt, "isPricedStepReceipt");
6476
6609
  __name(receiptEngine, "receiptEngine");
6477
- __name3(receiptEngine, "receiptEngine");
6610
+ __name4(receiptEngine, "receiptEngine");
6478
6611
  __name(receiptTier, "receiptTier");
6479
- __name3(receiptTier, "receiptTier");
6612
+ __name4(receiptTier, "receiptTier");
6480
6613
  __name(stepBillingView, "stepBillingView");
6481
- __name3(stepBillingView, "stepBillingView");
6614
+ __name4(stepBillingView, "stepBillingView");
6482
6615
  __name(runUsage, "runUsage");
6483
- __name3(runUsage, "runUsage");
6616
+ __name4(runUsage, "runUsage");
6484
6617
  __name(runBudgetCap, "runBudgetCap");
6485
- __name3(runBudgetCap, "runBudgetCap");
6618
+ __name4(runBudgetCap, "runBudgetCap");
6486
6619
  __name(runBudgetRemaining, "runBudgetRemaining");
6487
- __name3(runBudgetRemaining, "runBudgetRemaining");
6620
+ __name4(runBudgetRemaining, "runBudgetRemaining");
6488
6621
  __name(runCancelView, "runCancelView");
6489
- __name3(runCancelView, "runCancelView");
6622
+ __name4(runCancelView, "runCancelView");
6490
6623
  __name(runWorkspaceView, "runWorkspaceView");
6491
- __name3(runWorkspaceView, "runWorkspaceView");
6624
+ __name4(runWorkspaceView, "runWorkspaceView");
6492
6625
  __name(toWorkflowRunSummary, "toWorkflowRunSummary");
6493
- __name3(toWorkflowRunSummary, "toWorkflowRunSummary");
6626
+ __name4(toWorkflowRunSummary, "toWorkflowRunSummary");
6494
6627
  STEP_ERROR_DETAIL_KEYS = [
6495
6628
  "reason",
6496
6629
  "key",
@@ -6519,15 +6652,25 @@ var init_dist2 = __esm({
6519
6652
  "workflowId",
6520
6653
  // LUA-696 (review 2): the `ctx.once` key of an `effect_in_doubt` park — the step site stamps it here (scrubbed)
6521
6654
  // beside `park.effectKey`; a key is user text and leaves scrubbed like every other string leaf.
6522
- "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"
6523
6666
  ];
6524
6667
  STEP_ERROR_DETAIL_MAX_BYTES = 8 * 1024;
6525
6668
  DETAIL_MAX_DEPTH = 4;
6526
6669
  DETAIL_MAX_ITEMS = 100;
6527
6670
  __name(scrubDetailValue, "scrubDetailValue");
6528
- __name3(scrubDetailValue, "scrubDetailValue");
6671
+ __name4(scrubDetailValue, "scrubDetailValue");
6529
6672
  __name(stepErrorDetail, "stepErrorDetail");
6530
- __name3(stepErrorDetail, "stepErrorDetail");
6673
+ __name4(stepErrorDetail, "stepErrorDetail");
6531
6674
  MAX_HOLIDAYS = 366;
6532
6675
  MAX_WALK_DAYS = 400;
6533
6676
  HHMM = /^([01]\d|2[0-3]):([0-5]\d)$/;
@@ -6547,18 +6690,18 @@ var init_dist2 = __esm({
6547
6690
  };
6548
6691
  supportedTz = null;
6549
6692
  __name(timeZoneSupported, "timeZoneSupported");
6550
- __name3(timeZoneSupported, "timeZoneSupported");
6693
+ __name4(timeZoneSupported, "timeZoneSupported");
6551
6694
  __name(validateBusinessHours, "validateBusinessHours");
6552
- __name3(validateBusinessHours, "validateBusinessHours");
6695
+ __name4(validateBusinessHours, "validateBusinessHours");
6553
6696
  __name(toMinutes, "toMinutes");
6554
- __name3(toMinutes, "toMinutes");
6697
+ __name4(toMinutes, "toMinutes");
6555
6698
  __name(resolveCalendar, "resolveCalendar");
6556
- __name3(resolveCalendar, "resolveCalendar");
6699
+ __name4(resolveCalendar, "resolveCalendar");
6557
6700
  __name(assertValid, "assertValid");
6558
- __name3(assertValid, "assertValid");
6701
+ __name4(assertValid, "assertValid");
6559
6702
  fmtCache = /* @__PURE__ */ new Map();
6560
6703
  __name(formatter, "formatter");
6561
- __name3(formatter, "formatter");
6704
+ __name4(formatter, "formatter");
6562
6705
  WEEKDAYS = {
6563
6706
  Sun: 0,
6564
6707
  Mon: 1,
@@ -6569,25 +6712,25 @@ var init_dist2 = __esm({
6569
6712
  Sat: 6
6570
6713
  };
6571
6714
  __name(localParts, "localParts");
6572
- __name3(localParts, "localParts");
6715
+ __name4(localParts, "localParts");
6573
6716
  __name(offsetAt, "offsetAt");
6574
- __name3(offsetAt, "offsetAt");
6717
+ __name4(offsetAt, "offsetAt");
6575
6718
  __name(localToUtc, "localToUtc");
6576
- __name3(localToUtc, "localToUtc");
6719
+ __name4(localToUtc, "localToUtc");
6577
6720
  __name(sameWall, "sameWall");
6578
- __name3(sameWall, "sameWall");
6721
+ __name4(sameWall, "sameWall");
6579
6722
  __name(ymd, "ymd");
6580
- __name3(ymd, "ymd");
6723
+ __name4(ymd, "ymd");
6581
6724
  __name(windowOf, "windowOf");
6582
- __name3(windowOf, "windowOf");
6725
+ __name4(windowOf, "windowOf");
6583
6726
  __name(nextDayAnchor, "nextDayAnchor");
6584
- __name3(nextDayAnchor, "nextDayAnchor");
6727
+ __name4(nextDayAnchor, "nextDayAnchor");
6585
6728
  __name(addBusinessTime, "addBusinessTime");
6586
- __name3(addBusinessTime, "addBusinessTime");
6729
+ __name4(addBusinessTime, "addBusinessTime");
6587
6730
  __name(roundToBusinessTime, "roundToBusinessTime");
6588
- __name3(roundToBusinessTime, "roundToBusinessTime");
6731
+ __name4(roundToBusinessTime, "roundToBusinessTime");
6589
6732
  __name(isBusinessTime, "isBusinessTime");
6590
- __name3(isBusinessTime, "isBusinessTime");
6733
+ __name4(isBusinessTime, "isBusinessTime");
6591
6734
  JSON_PATCH_OPS = [
6592
6735
  "replace",
6593
6736
  "add",
@@ -6598,27 +6741,27 @@ var init_dist2 = __esm({
6598
6741
  JSON_PATCH_MAX_TOTAL_BYTES = 1024 * 1024;
6599
6742
  SEGMENT_RE = /^([A-Za-z_$][\w$-]*)((?:\[(?:\*|\d+)\])*)$/;
6600
6743
  __name(parseEditablePath, "parseEditablePath");
6601
- __name3(parseEditablePath, "parseEditablePath");
6744
+ __name4(parseEditablePath, "parseEditablePath");
6602
6745
  __name(isEditablePathEntry, "isEditablePathEntry");
6603
- __name3(isEditablePathEntry, "isEditablePathEntry");
6746
+ __name4(isEditablePathEntry, "isEditablePathEntry");
6604
6747
  __name(pointerToSegments, "pointerToSegments");
6605
- __name3(pointerToSegments, "pointerToSegments");
6748
+ __name4(pointerToSegments, "pointerToSegments");
6606
6749
  __name(pointerToDotPath, "pointerToDotPath");
6607
- __name3(pointerToDotPath, "pointerToDotPath");
6750
+ __name4(pointerToDotPath, "pointerToDotPath");
6608
6751
  __name(coveredBy, "coveredBy");
6609
- __name3(coveredBy, "coveredBy");
6752
+ __name4(coveredBy, "coveredBy");
6610
6753
  __name(matchesEditablePath, "matchesEditablePath");
6611
- __name3(matchesEditablePath, "matchesEditablePath");
6754
+ __name4(matchesEditablePath, "matchesEditablePath");
6612
6755
  __name(changedPointers, "changedPointers");
6613
- __name3(changedPointers, "changedPointers");
6756
+ __name4(changedPointers, "changedPointers");
6614
6757
  __name(escapePointer, "escapePointer");
6615
- __name3(escapePointer, "escapePointer");
6758
+ __name4(escapePointer, "escapePointer");
6616
6759
  __name(validateJsonPatch, "validateJsonPatch");
6617
- __name3(validateJsonPatch, "validateJsonPatch");
6760
+ __name4(validateJsonPatch, "validateJsonPatch");
6618
6761
  __name(applyJsonPatch, "applyJsonPatch");
6619
- __name3(applyJsonPatch, "applyJsonPatch");
6762
+ __name4(applyJsonPatch, "applyJsonPatch");
6620
6763
  __name(rebaseItemPointer, "rebaseItemPointer");
6621
- __name3(rebaseItemPointer, "rebaseItemPointer");
6764
+ __name4(rebaseItemPointer, "rebaseItemPointer");
6622
6765
  WORKFLOW_SCHEDULE_TYPES = [
6623
6766
  "cron",
6624
6767
  "interval",
@@ -6626,22 +6769,26 @@ var init_dist2 = __esm({
6626
6769
  ];
6627
6770
  WORKFLOW_SCHEDULE_SHAPE_ISSUE = "schedule-shape-invalid";
6628
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>' }";
6629
- isObject = /* @__PURE__ */ __name3((v) => typeof v === "object" && v !== null && !Array.isArray(v), "isObject");
6772
+ WORKFLOW_SCHEDULE_RUN_AS = [
6773
+ "installer",
6774
+ "system"
6775
+ ];
6776
+ isObject = /* @__PURE__ */ __name4((v) => typeof v === "object" && v !== null && !Array.isArray(v), "isObject");
6630
6777
  __name(validateWorkflowSchedule, "validateWorkflowSchedule");
6631
- __name3(validateWorkflowSchedule, "validateWorkflowSchedule");
6778
+ __name4(validateWorkflowSchedule, "validateWorkflowSchedule");
6632
6779
  WORKFLOW_ENV_OVERLAY_MAX_KEYS = 64;
6633
6780
  WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES = 4096;
6634
6781
  WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
6635
- isEnvRef = /* @__PURE__ */ __name3((v) => typeof v === "object" && v !== null && !Array.isArray(v) && typeof v.__envRef === "string" && Object.keys(v).length === 1, "isEnvRef");
6636
- 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");
6637
6784
  __name(collectEnvTemplateKeys, "collectEnvTemplateKeys");
6638
- __name3(collectEnvTemplateKeys, "collectEnvTemplateKeys");
6785
+ __name4(collectEnvTemplateKeys, "collectEnvTemplateKeys");
6639
6786
  __name(substituteEnvRefs, "substituteEnvRefs");
6640
- __name3(substituteEnvRefs, "substituteEnvRefs");
6787
+ __name4(substituteEnvRefs, "substituteEnvRefs");
6641
6788
  __name(hashEnvOverlay, "hashEnvOverlay");
6642
- __name3(hashEnvOverlay, "hashEnvOverlay");
6789
+ __name4(hashEnvOverlay, "hashEnvOverlay");
6643
6790
  __name(validateEnvOverlay, "validateEnvOverlay");
6644
- __name3(validateEnvOverlay, "validateEnvOverlay");
6791
+ __name4(validateEnvOverlay, "validateEnvOverlay");
6645
6792
  ZERO = {
6646
6793
  steps: {
6647
6794
  min: 0,
@@ -6654,24 +6801,24 @@ var init_dist2 = __esm({
6654
6801
  agentCalls: 0
6655
6802
  };
6656
6803
  __name(add, "add");
6657
- __name3(add, "add");
6804
+ __name4(add, "add");
6658
6805
  __name(scale, "scale");
6659
- __name3(scale, "scale");
6806
+ __name4(scale, "scale");
6660
6807
  __name(armEntry, "armEntry");
6661
- __name3(armEntry, "armEntry");
6808
+ __name4(armEntry, "armEntry");
6662
6809
  __name(ofEntry, "ofEntry");
6663
- __name3(ofEntry, "ofEntry");
6810
+ __name4(ofEntry, "ofEntry");
6664
6811
  __name(estimateGraph, "estimateGraph");
6665
- __name3(estimateGraph, "estimateGraph");
6666
- 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");
6667
6814
  __name(singleStepsOf, "singleStepsOf");
6668
- __name3(singleStepsOf, "singleStepsOf");
6815
+ __name4(singleStepsOf, "singleStepsOf");
6669
6816
  __name(entriesOf, "entriesOf");
6670
- __name3(entriesOf, "entriesOf");
6817
+ __name4(entriesOf, "entriesOf");
6671
6818
  __name(inheritTargets, "inheritTargets");
6672
- __name3(inheritTargets, "inheritTargets");
6819
+ __name4(inheritTargets, "inheritTargets");
6673
6820
  __name(needsInheritedWorkspace, "needsInheritedWorkspace");
6674
- __name3(needsInheritedWorkspace, "needsInheritedWorkspace");
6821
+ __name4(needsInheritedWorkspace, "needsInheritedWorkspace");
6675
6822
  }
6676
6823
  });
6677
6824
 
@@ -6808,7 +6955,7 @@ function defineWorkflow(cfg, build) {
6808
6955
  if (!(wf instanceof LuaWorkflow)) throw new LuaWorkflowBuildError("invalid-envelope", "defineWorkflow: the build callback must return `wf\u2026.commit()`");
6809
6956
  return wf;
6810
6957
  }
6811
- 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;
6812
6959
  var init_workflow = __esm({
6813
6960
  "src/types/workflow.ts"() {
6814
6961
  "use strict";
@@ -6927,6 +7074,7 @@ var init_workflow = __esm({
6927
7074
  }
6928
7075
  for (const inner of Object.values(v)) envRefKeys(inner, into);
6929
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");
6930
7078
  refToDescriptor = /* @__PURE__ */ __name((items) => {
6931
7079
  if (!items) throw new LuaWorkflowBuildError("invalid-envelope", "foreach.items needs a ref");
6932
7080
  if ("initData" in items && items.initData === true) {
@@ -6936,11 +7084,14 @@ var init_workflow = __esm({
6936
7084
  };
6937
7085
  }
6938
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)");
6939
7088
  return {
6940
7089
  step: items.step,
6941
7090
  path: items.path
6942
7091
  };
6943
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)");
6944
7095
  const path3 = items.path;
6945
7096
  if (path3.startsWith("initData")) return {
6946
7097
  initData: true,
@@ -7671,360 +7822,130 @@ var init_auth_error = __esm({
7671
7822
  }
7672
7823
  });
7673
7824
 
7674
- // src/errors/cli.error.ts
7675
- function apiErrorDetail(error) {
7676
- return {
7677
- serverCode: error?.code,
7678
- issues: error?.issues,
7679
- upstream: error?.upstream,
7680
- requestId: error?.requestId,
7681
- vendor: error?.vendor,
7682
- retryAfterSeconds: error?.retryAfterSeconds
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
7683
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));
7684
7856
  }
7685
- function isAccessDeniedError(error) {
7686
- if (CliError.isCliError(error)) return error.statusCode === 403;
7687
- return error instanceof Error && error.message.startsWith("Access denied (403)");
7857
+ function getCliVersion() {
7858
+ try {
7859
+ return locate().pkg.version;
7860
+ } catch {
7861
+ return "0.0.0";
7862
+ }
7688
7863
  }
7689
- function upstreamUnavailableHint(upstream, requestId) {
7690
- const service = typeof upstream === "string" && upstream ? `its ${upstream} service` : "a service behind it";
7691
- const ref = typeof requestId === "string" && requestId ? ` If it persists, quote request ${requestId}.` : "";
7692
- return `The Lua API is up, but ${service} is temporarily unavailable (503 UPSTREAM_UNAVAILABLE) \u2014 retry in a moment.${ref}`;
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());
7693
7878
  }
7694
- function vendorUnavailableHint(vendor, requestId, retryAfterSeconds) {
7695
- const name = typeof vendor === "string" && vendor ? VENDOR_LABELS[vendor] ?? vendor : "a vendor it depends on";
7696
- const ref = typeof requestId === "string" && requestId ? ` If it persists, quote request ${requestId}.` : "";
7697
- const retry = typeof retryAfterSeconds === "number" ? "retry in a moment" : "the request may have applied at the vendor \u2014 check before retrying";
7698
- return `The Lua API is up, but ${name} is temporarily unavailable (503 VENDOR_UNAVAILABLE) \u2014 ${retry}.${ref}`;
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;
7886
+ }
7887
+ return record;
7699
7888
  }
7700
- function authHint(error) {
7701
- if (error.suppressDefaultRemediation) return void 0;
7702
- if (error.reason === "no_agent_access") {
7703
- return [
7704
- "Your API key is valid, but it does not have access to the agentId in lua.skill.yaml \u2014 the agent belongs",
7705
- "to another account or organization, was deleted or transferred, or the yaml was copied from another project.",
7706
- "Check the configured agent and switch if needed:",
7707
- " lua agents (list agents you have access to)",
7708
- " lua init (re-select the agent for this project)"
7709
- ].join("\n");
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];
7710
7893
  }
7711
- return "Re-authenticate or check your API key: lua auth configure \xB7 https://admin.heylua.ai";
7894
+ headers[LUA_CLIENT_HEADER] = luaClientHeaderValue();
7895
+ return fetch(input, {
7896
+ ...init3,
7897
+ headers
7898
+ });
7712
7899
  }
7713
- function numericStatus(error) {
7714
- const candidate = error.statusCode ?? error.status;
7715
- return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : void 0;
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));
7716
7916
  }
7717
- function classifyCliError(error) {
7718
- if (CliError.isCliError(error)) {
7719
- return {
7720
- code: error.code,
7721
- exitCode: error.exitCode,
7722
- message: error.message,
7723
- hint: error.hint,
7724
- statusCode: error.statusCode,
7725
- serverCode: error.serverCode,
7726
- issues: error.issues
7727
- };
7917
+ function requireFirebaseWebApiKey() {
7918
+ if (!FIREBASE_WEB_API_KEY) {
7919
+ throw new Error("Firebase sign-in is not configured for this CLI build.");
7728
7920
  }
7729
- if (AuthenticationError.isAuthenticationError(error)) {
7730
- return {
7731
- code: "auth",
7732
- exitCode: CLI_EXIT.AUTH,
7733
- message: error.message,
7734
- hint: authHint(error)
7735
- };
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);
7736
7932
  }
7737
- const e = typeof error === "object" && error !== null ? error : {};
7738
- const message = typeof e.message === "string" && e.message.length > 0 ? e.message : error instanceof Error ? error.name : String(error ?? "Unknown error");
7739
- if (e.name === "WorkflowLocalUsageError" || typeof e.code === "string" && e.code.startsWith("commander.")) {
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;
7740
7944
  return {
7741
- code: "usage",
7742
- exitCode: CLI_EXIT.USAGE,
7743
- message
7744
- };
7745
- }
7746
- const status = numericStatus(e);
7747
- if (status !== void 0) {
7748
- const statusCode = status;
7749
- if (status === 401) return {
7750
- code: "auth",
7751
- exitCode: CLI_EXIT.AUTH,
7752
- message,
7753
- statusCode
7754
- };
7755
- if (status === 403) return {
7756
- code: "forbidden",
7757
- exitCode: CLI_EXIT.FORBIDDEN,
7758
- message,
7759
- statusCode
7760
- };
7761
- if (status === 404) return {
7762
- code: "not_found",
7763
- exitCode: CLI_EXIT.NOT_FOUND,
7764
- message,
7765
- statusCode
7766
- };
7767
- if (status >= 400 && status < 500) return {
7768
- code: `http_${status}`,
7769
- exitCode: CLI_EXIT.FORBIDDEN,
7770
- message,
7771
- statusCode
7772
- };
7773
- if (status >= 500 || status === 0) return {
7774
- code: "unavailable",
7775
- exitCode: CLI_EXIT.UNAVAILABLE,
7776
- message,
7777
- statusCode
7778
- };
7779
- }
7780
- const causeCode = e.cause?.code;
7781
- 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)) {
7782
- return {
7783
- code: "unavailable",
7784
- exitCode: CLI_EXIT.UNAVAILABLE,
7785
- message,
7786
- hint: UNAVAILABLE_HINT
7787
- };
7788
- }
7789
- return {
7790
- code: "error",
7791
- exitCode: CLI_EXIT.ERROR,
7792
- message
7793
- };
7794
- }
7795
- var CLI_EXIT, CliError, NETWORK_ERRNO, NETWORK_MESSAGE, UNAVAILABLE_HINT, VENDOR_LABELS;
7796
- var init_cli_error = __esm({
7797
- "src/errors/cli.error.ts"() {
7798
- "use strict";
7799
- init_auth_error();
7800
- CLI_EXIT = {
7801
- OK: 0,
7802
- ERROR: 1,
7803
- USAGE: 2,
7804
- NOT_FOUND: 3,
7805
- AUTH: 9,
7806
- FORBIDDEN: 10,
7807
- UNAVAILABLE: 11
7808
- };
7809
- __name(apiErrorDetail, "apiErrorDetail");
7810
- CliError = class _CliError extends Error {
7811
- static {
7812
- __name(this, "CliError");
7813
- }
7814
- isCliError = true;
7815
- code;
7816
- exitCode;
7817
- hint;
7818
- statusCode;
7819
- serverCode;
7820
- issues;
7821
- constructor(code, message, options = {}) {
7822
- super(message);
7823
- this.name = "CliError";
7824
- this.code = code;
7825
- this.exitCode = options.exitCode ?? CLI_EXIT.ERROR;
7826
- this.hint = options.hint;
7827
- this.statusCode = options.statusCode;
7828
- this.serverCode = options.serverCode;
7829
- this.issues = options.issues?.length ? options.issues : void 0;
7830
- if (Error.captureStackTrace) Error.captureStackTrace(this, _CliError);
7831
- }
7832
- /** Bad arguments, an unknown action, no project — exit 2. */
7833
- static usage(message, hint) {
7834
- return new _CliError("usage", message, {
7835
- exitCode: CLI_EXIT.USAGE,
7836
- hint
7837
- });
7838
- }
7839
- /** The named thing does not exist — exit 3. */
7840
- static notFound(message, hint) {
7841
- return new _CliError("not_found", message, {
7842
- exitCode: CLI_EXIT.NOT_FOUND,
7843
- hint,
7844
- statusCode: 404
7845
- });
7846
- }
7847
- /** The credential may not do this — exit 10. */
7848
- static forbidden(message, hint) {
7849
- return new _CliError("forbidden", message, {
7850
- exitCode: CLI_EXIT.FORBIDDEN,
7851
- hint,
7852
- statusCode: 403
7853
- });
7854
- }
7855
- /**
7856
- * An API refusal the site already holds the status of (LUA-766) — classified by the same table the top-level
7857
- * classifier applies to an untyped error: 401 auth · 403 forbidden · 404 not_found · other 4xx `http_<status>`
7858
- * (10) · 5xx / 0 unavailable (11, with the network hint unless the site gives its own — or the body's code
7859
- * picks one: a 503 UPSTREAM_UNAVAILABLE names the Lua service behind the API, LUA-810) · no status `error` (1).
7860
- * A command that reads `response.error.statusCode` throws through here, so `lua logs` on a 503 exits 11 like
7861
- * every other verb instead of printing the message itself and then throwing an exit-1 `Error`.
7862
- */
7863
- static fromStatus(statusCode, message, hint, detail = {}) {
7864
- const reported = classifyCliError(Object.assign(new Error(message), {
7865
- statusCode
7866
- }));
7867
- const codeHint = detail.serverCode === "UPSTREAM_UNAVAILABLE" ? upstreamUnavailableHint(detail.upstream, detail.requestId) : detail.serverCode === "VENDOR_UNAVAILABLE" ? vendorUnavailableHint(detail.vendor, detail.requestId, detail.retryAfterSeconds) : void 0;
7868
- const classHint = reported.exitCode === CLI_EXIT.UNAVAILABLE ? UNAVAILABLE_HINT : reported.hint;
7869
- return new _CliError(reported.code, message, {
7870
- exitCode: reported.exitCode,
7871
- hint: hint ?? codeHint ?? classHint,
7872
- statusCode,
7873
- serverCode: detail.serverCode,
7874
- issues: detail.issues
7875
- });
7876
- }
7877
- static isCliError(error) {
7878
- return error instanceof _CliError || typeof error === "object" && error !== null && error.isCliError === true;
7879
- }
7880
- };
7881
- __name(isAccessDeniedError, "isAccessDeniedError");
7882
- NETWORK_ERRNO = /* @__PURE__ */ new Set([
7883
- "ECONNREFUSED",
7884
- "ECONNRESET",
7885
- "ENOTFOUND",
7886
- "ETIMEDOUT",
7887
- "EAI_AGAIN",
7888
- "EPIPE",
7889
- "EHOSTUNREACH",
7890
- "ENETUNREACH",
7891
- "UND_ERR_CONNECT_TIMEOUT",
7892
- "UND_ERR_HEADERS_TIMEOUT",
7893
- "UND_ERR_BODY_TIMEOUT",
7894
- "UND_ERR_SOCKET"
7895
- ]);
7896
- NETWORK_MESSAGE = /fetch failed|socket hang up|network request failed|request timeout|ECONNREFUSED|ENOTFOUND/i;
7897
- UNAVAILABLE_HINT = "The Lua API could not be reached \u2014 check your network and https://status.heylua.ai, then retry.";
7898
- __name(upstreamUnavailableHint, "upstreamUnavailableHint");
7899
- VENDOR_LABELS = {
7900
- unified: "Unified.to",
7901
- github: "GitHub",
7902
- pusher: "Pusher",
7903
- google: "Google"
7904
- };
7905
- __name(vendorUnavailableHint, "vendorUnavailableHint");
7906
- __name(authHint, "authHint");
7907
- __name(numericStatus, "numericStatus");
7908
- __name(classifyCliError, "classifyCliError");
7909
- }
7910
- });
7911
-
7912
- // src/utils/package-root.ts
7913
- import { readFileSync, existsSync } from "fs";
7914
- import { fileURLToPath, pathToFileURL } from "url";
7915
- import { dirname, join as join2 } from "path";
7916
- function locate() {
7917
- if (cachedRoot && cachedPkg) return {
7918
- root: cachedRoot,
7919
- pkg: cachedPkg
7920
- };
7921
- let dir = dirname(fileURLToPath(import.meta.url));
7922
- while (true) {
7923
- const candidate = join2(dir, "package.json");
7924
- if (existsSync(candidate)) {
7925
- try {
7926
- const parsed = JSON.parse(readFileSync(candidate, "utf8"));
7927
- if (parsed?.name === "lua-cli") {
7928
- cachedRoot = dir;
7929
- cachedPkg = parsed;
7930
- return {
7931
- root: dir,
7932
- pkg: parsed
7933
- };
7934
- }
7935
- } catch {
7936
- }
7937
- }
7938
- const parent = dirname(dir);
7939
- if (parent === dir) break;
7940
- dir = parent;
7941
- }
7942
- throw new Error("Could not locate lua-cli package root from " + fileURLToPath(import.meta.url));
7943
- }
7944
- function getCliVersion() {
7945
- try {
7946
- return locate().pkg.version;
7947
- } catch {
7948
- return "0.0.0";
7949
- }
7950
- }
7951
- var cachedRoot, cachedPkg;
7952
- var init_package_root = __esm({
7953
- "src/utils/package-root.ts"() {
7954
- "use strict";
7955
- cachedRoot = null;
7956
- cachedPkg = null;
7957
- __name(locate, "locate");
7958
- __name(getCliVersion, "getCliVersion");
7959
- }
7960
- });
7961
-
7962
- // src/utils/lua-fetch.ts
7963
- function luaClientHeaderValue() {
7964
- return formatLuaClientHeader("cli", getCliVersion());
7965
- }
7966
- function headerRecord(headers) {
7967
- if (!headers) return {};
7968
- if (headers instanceof Headers) return Object.fromEntries(headers.entries());
7969
- if (Array.isArray(headers)) return Object.fromEntries(headers);
7970
- const record = {};
7971
- for (const [name, value3] of Object.entries(headers)) {
7972
- if (typeof value3 === "string") record[name] = value3;
7973
- }
7974
- return record;
7975
- }
7976
- function luaFetch(input, init3 = {}) {
7977
- const headers = headerRecord(init3.headers);
7978
- for (const name of Object.keys(headers)) {
7979
- if (name.toLowerCase() === LUA_CLIENT_HEADER.toLowerCase()) delete headers[name];
7980
- }
7981
- headers[LUA_CLIENT_HEADER] = luaClientHeaderValue();
7982
- return fetch(input, {
7983
- ...init3,
7984
- headers
7985
- });
7986
- }
7987
- var init_lua_fetch = __esm({
7988
- "src/utils/lua-fetch.ts"() {
7989
- "use strict";
7990
- init_dist();
7991
- init_package_root();
7992
- __name(luaClientHeaderValue, "luaClientHeaderValue");
7993
- __name(headerRecord, "headerRecord");
7994
- __name(luaFetch, "luaFetch");
7995
- }
7996
- });
7997
-
7998
- // src/services/firebase-session.ts
7999
- import { z as z5 } from "zod";
8000
- function requireFirebaseWebApiKey() {
8001
- if (!FIREBASE_WEB_API_KEY) {
8002
- throw new Error("Firebase sign-in is not configured for this CLI build.");
8003
- }
8004
- return FIREBASE_WEB_API_KEY;
8005
- }
8006
- function uidFromFirebaseIdToken(idToken) {
8007
- const segments = idToken.split(".");
8008
- if (segments.length !== 3 || !segments[1]) throw new Error(INVALID_FIREBASE_SESSION);
8009
- let payload;
8010
- try {
8011
- payload = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf8"));
8012
- } catch {
8013
- throw new Error(INVALID_FIREBASE_SESSION);
8014
- }
8015
- const parsed = firebaseIdTokenPayloadSchema.safeParse(payload);
8016
- if (parsed.success) return parsed.data.sub;
8017
- throw new Error(INVALID_FIREBASE_SESSION);
8018
- }
8019
- function parseFirebaseSession(json, now = Date.now()) {
8020
- const customTokenResponse = customTokenResponseSchema.safeParse(json);
8021
- if (customTokenResponse.success) {
8022
- const { idToken: idToken2, refreshToken: refreshToken2, expiresIn: expiresIn2, localId } = customTokenResponse.data;
8023
- return {
8024
- idToken: idToken2,
8025
- refreshToken: refreshToken2,
8026
- expiresAt: now + expiresIn2 * 1e3,
8027
- uid: localId ?? uidFromFirebaseIdToken(idToken2)
7945
+ idToken: idToken2,
7946
+ refreshToken: refreshToken2,
7947
+ expiresAt: now + expiresIn2 * 1e3,
7948
+ uid: localId ?? uidFromFirebaseIdToken(idToken2)
8028
7949
  };
8029
7950
  }
8030
7951
  const refreshResponse = refreshResponseSchema.safeParse(json);
@@ -8067,6 +7988,23 @@ async function fetchFirebase(url, init3, timeoutMessage) {
8067
7988
  if (timeoutId !== void 0) clearTimeout(timeoutId);
8068
7989
  }
8069
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
+ }
8070
8008
  async function refreshFirebaseSession(session) {
8071
8009
  const key = requireFirebaseWebApiKey();
8072
8010
  const response = await fetchFirebase(`${FIREBASE_REFRESH_URL}?key=${encodeURIComponent(key)}`, {
@@ -8080,20 +8018,43 @@ async function refreshFirebaseSession(session) {
8080
8018
  }).toString()
8081
8019
  }, "Firebase session refresh timed out after 15 seconds.");
8082
8020
  if (!response.ok) {
8083
- 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}`);
8084
8025
  }
8085
8026
  const refreshed = parseFirebaseSession(await response.json());
8086
8027
  if (refreshed.uid !== session.uid) throw new Error("Firebase session refresh returned a different identity.");
8087
8028
  return refreshed;
8088
8029
  }
8089
- 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;
8090
8031
  var init_firebase_session = __esm({
8091
8032
  "src/services/firebase-session.ts"() {
8092
8033
  "use strict";
8093
8034
  init_constants();
8035
+ FIREBASE_CUSTOM_TOKEN_URL = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken";
8094
8036
  FIREBASE_REFRESH_URL = "https://securetoken.googleapis.com/v1/token";
8095
8037
  FIREBASE_REQUEST_TIMEOUT_MS = 15e3;
8096
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
+ };
8097
8058
  customTokenResponseSchema = z5.object({
8098
8059
  idToken: z5.string().min(1),
8099
8060
  refreshToken: z5.string().min(1),
@@ -8110,17 +8071,19 @@ var init_firebase_session = __esm({
8110
8071
  sub: z5.string().min(1)
8111
8072
  });
8112
8073
  __name(requireFirebaseWebApiKey, "requireFirebaseWebApiKey");
8074
+ __name(claimsOfFirebaseIdToken, "claimsOfFirebaseIdToken");
8113
8075
  __name(uidFromFirebaseIdToken, "uidFromFirebaseIdToken");
8114
8076
  __name(parseFirebaseSession, "parseFirebaseSession");
8115
8077
  __name(parseFirebaseError, "parseFirebaseError");
8116
8078
  __name(fetchFirebase, "fetchFirebase");
8079
+ __name(exchangeFirebaseCustomToken, "exchangeFirebaseCustomToken");
8117
8080
  __name(refreshFirebaseSession, "refreshFirebaseSession");
8118
8081
  }
8119
8082
  });
8120
8083
 
8121
8084
  // src/services/firebase-session-store.ts
8122
8085
  import { createHash as createHash3, randomUUID } from "crypto";
8123
- import { mkdir, open, readFile, rename, unlink } from "fs/promises";
8086
+ import { mkdir, open, readFile, rename, rm, stat, unlink, writeFile } from "fs/promises";
8124
8087
  import { join as join3 } from "path";
8125
8088
  import { z as z6 } from "zod";
8126
8089
  function environmentKey(environment) {
@@ -8131,7 +8094,10 @@ ${environment.firebaseWebApiKey}`).digest("hex").slice(0, 16);
8131
8094
  function isMissing(error) {
8132
8095
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
8133
8096
  }
8134
- 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;
8135
8101
  var init_firebase_session_store = __esm({
8136
8102
  "src/services/firebase-session-store.ts"() {
8137
8103
  "use strict";
@@ -8154,6 +8120,9 @@ var init_firebase_session_store = __esm({
8154
8120
  __name(environmentKey, "environmentKey");
8155
8121
  __name(isMissing, "isMissing");
8156
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");
8157
8126
  FirebaseSessionStore = class {
8158
8127
  static {
8159
8128
  __name(this, "FirebaseSessionStore");
@@ -8235,27 +8204,39 @@ var init_firebase_session_store = __esm({
8235
8204
  if (!isMissing(error)) throw error;
8236
8205
  }
8237
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
+ */
8238
8212
  async withLock(operation) {
8239
8213
  await mkdir(this.directory, {
8240
8214
  recursive: true,
8241
8215
  mode: 448
8242
8216
  });
8243
8217
  const lockPath = `${this.path()}.lock`;
8218
+ const ownerPath = join3(lockPath, "owner");
8244
8219
  const lockOwner = randomUUID();
8245
- const deadline = Date.now() + 2e4;
8220
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
8246
8221
  while (true) {
8247
8222
  try {
8248
- const handle = await open(lockPath, "wx", 384);
8249
- try {
8250
- await handle.writeFile(lockOwner, "utf8");
8251
- await handle.sync();
8252
- } finally {
8253
- await handle.close();
8254
- }
8255
- 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;
8256
8231
  } catch (error) {
8257
- const code = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
8258
- 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
+ }
8259
8240
  if (Date.now() >= deadline) {
8260
8241
  throw new Error("Timed out waiting for another Lua CLI process to finish updating the session.");
8261
8242
  }
@@ -8266,115 +8247,480 @@ var init_firebase_session_store = __esm({
8266
8247
  return await operation();
8267
8248
  } finally {
8268
8249
  try {
8269
- 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
+ });
8270
8254
  } catch (error) {
8271
8255
  if (!isMissing(error)) throw error;
8272
8256
  }
8273
8257
  }
8274
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
+ }
8266
+ };
8267
+ }
8268
+ });
8269
+
8270
+ // src/services/request-credential.ts
8271
+ import "dotenv/config";
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
+ }
8276
+ function loadStoredApiKey() {
8277
+ try {
8278
+ return readFileSync2(CREDENTIALS_FILE, "utf8").trim() || null;
8279
+ } catch {
8280
+ return null;
8281
+ }
8282
+ }
8283
+ function isRequestCredential(value3) {
8284
+ return typeof value3 !== "string";
8285
+ }
8286
+ async function bearerFor(credential) {
8287
+ return isRequestCredential(credential) ? credential.bearer() : credential;
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
+ }
8307
+ async function resolveRequestCredential() {
8308
+ if (process.env.LUA_API_KEY) return new StaticRequestCredential(process.env.LUA_API_KEY, "environment");
8309
+ const store = new FirebaseSessionStore();
8310
+ const session = await store.read();
8311
+ if (session) return new FirebaseRequestCredential(store, session);
8312
+ const storedApiKey = loadStoredApiKey();
8313
+ if (storedApiKey) return new StaticRequestCredential(storedApiKey, "stored");
8314
+ throw new AuthenticationError("No Lua CLI authentication found. Run `lua auth configure` or set LUA_API_KEY.", "invalid_credentials", void 0, true);
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
+ }
8321
+ var StaticRequestCredential, FirebaseRequestCredential;
8322
+ var init_request_credential = __esm({
8323
+ "src/services/request-credential.ts"() {
8324
+ "use strict";
8325
+ init_dist();
8326
+ init_constants();
8327
+ init_auth_error();
8328
+ init_lua_fetch();
8329
+ init_firebase_session();
8330
+ init_firebase_session_store();
8331
+ __name(sessionSignedOutError, "sessionSignedOutError");
8332
+ __name(loadStoredApiKey, "loadStoredApiKey");
8333
+ __name(isRequestCredential, "isRequestCredential");
8334
+ __name(bearerFor, "bearerFor");
8335
+ StaticRequestCredential = class StaticRequestCredential2 {
8336
+ static {
8337
+ __name(this, "StaticRequestCredential");
8338
+ }
8339
+ apiKey;
8340
+ descriptor;
8341
+ constructor(apiKey, source) {
8342
+ this.apiKey = apiKey;
8343
+ this.descriptor = {
8344
+ kind: "api-key",
8345
+ source
8346
+ };
8347
+ }
8348
+ async bearer() {
8349
+ return this.apiKey;
8350
+ }
8351
+ };
8352
+ FirebaseRequestCredential = class FirebaseRequestCredential2 {
8353
+ static {
8354
+ __name(this, "FirebaseRequestCredential");
8355
+ }
8356
+ store;
8357
+ descriptor;
8358
+ liveSession;
8359
+ refresh;
8360
+ constructor(store, stored) {
8361
+ this.store = store;
8362
+ this.descriptor = {
8363
+ kind: "first-party-session",
8364
+ source: "stored",
8365
+ uid: stored.firebaseUid
8366
+ };
8367
+ }
8368
+ async bearer() {
8369
+ if (this.liveSession && this.liveSession.expiresAt - Date.now() > 6e4) return this.liveSession.idToken;
8370
+ if (!this.refresh) this.refresh = this.refreshBearer().finally(() => this.refresh = void 0);
8371
+ return this.refresh;
8372
+ }
8373
+ async refreshBearer() {
8374
+ let live;
8375
+ let rejected = false;
8376
+ await this.store.update(async (stored) => {
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;
8389
+ }
8390
+ live = await registerSessionIfNeeded(live, stored.authUrl) ?? live;
8391
+ return {
8392
+ ...stored,
8393
+ refreshToken: live.refreshToken,
8394
+ firebaseUid: live.uid
8395
+ };
8396
+ });
8397
+ if (rejected) throw sessionSignedOutError();
8398
+ if (!live) throw new Error("Firebase session refresh did not return a session.");
8399
+ this.liveSession = live;
8400
+ return live.idToken;
8401
+ }
8402
+ };
8403
+ __name(registerSessionIfNeeded, "registerSessionIfNeeded");
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)
8275
8507
  };
8276
8508
  }
8277
- });
8278
-
8279
- // src/services/request-credential.ts
8280
- import "dotenv/config";
8281
- import { readFileSync as readFileSync2, unlinkSync } from "fs";
8282
- function loadStoredApiKey() {
8283
- try {
8284
- return readFileSync2(CREDENTIALS_FILE, "utf8").trim() || null;
8285
- } catch {
8286
- return null;
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
+ };
8287
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
+ };
8288
8566
  }
8289
- function isRequestCredential(value3) {
8290
- return typeof value3 !== "string";
8291
- }
8292
- async function bearerFor(credential) {
8293
- return isRequestCredential(credential) ? credential.bearer() : credential;
8294
- }
8295
- async function resolveRequestCredential() {
8296
- if (process.env.LUA_API_KEY) return new StaticRequestCredential(process.env.LUA_API_KEY, "environment");
8297
- const store = new FirebaseSessionStore();
8298
- const session = await store.read();
8299
- if (session) return new FirebaseRequestCredential(store, session);
8300
- const storedApiKey = loadStoredApiKey();
8301
- if (storedApiKey) return new StaticRequestCredential(storedApiKey, "stored");
8302
- throw new AuthenticationError("No Lua CLI authentication found. Run `lua auth configure` or set LUA_API_KEY.", "invalid_credentials", void 0, true);
8303
- }
8304
- var StaticRequestCredential, FirebaseRequestCredential;
8305
- var init_request_credential = __esm({
8306
- "src/services/request-credential.ts"() {
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"() {
8307
8570
  "use strict";
8308
- init_constants();
8309
8571
  init_auth_error();
8310
- init_lua_fetch();
8311
- init_firebase_session();
8312
- init_firebase_session_store();
8313
- __name(loadStoredApiKey, "loadStoredApiKey");
8314
- __name(isRequestCredential, "isRequestCredential");
8315
- __name(bearerFor, "bearerFor");
8316
- StaticRequestCredential = class StaticRequestCredential2 {
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 {
8317
8584
  static {
8318
- __name(this, "StaticRequestCredential");
8585
+ __name(this, "CliError");
8319
8586
  }
8320
- apiKey;
8321
- descriptor;
8322
- constructor(apiKey, source) {
8323
- this.apiKey = apiKey;
8324
- this.descriptor = {
8325
- kind: "api-key",
8326
- source
8327
- };
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);
8328
8604
  }
8329
- async bearer() {
8330
- return this.apiKey;
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
+ });
8331
8611
  }
8332
- };
8333
- FirebaseRequestCredential = class FirebaseRequestCredential2 {
8334
- static {
8335
- __name(this, "FirebaseRequestCredential");
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
+ });
8336
8619
  }
8337
- store;
8338
- descriptor;
8339
- liveSession;
8340
- refresh;
8341
- constructor(store, stored) {
8342
- this.store = store;
8343
- this.descriptor = {
8344
- kind: "first-party-session",
8345
- source: "stored",
8346
- uid: stored.firebaseUid
8347
- };
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
+ });
8348
8627
  }
8349
- async bearer() {
8350
- if (this.liveSession && this.liveSession.expiresAt - Date.now() > 6e4) return this.liveSession.idToken;
8351
- if (!this.refresh) this.refresh = this.refreshBearer().finally(() => this.refresh = void 0);
8352
- return this.refresh;
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
+ });
8353
8643
  }
8354
- async refreshBearer() {
8355
- let live;
8356
- await this.store.update(async (stored) => {
8357
- if (!stored) {
8358
- throw new AuthenticationError("Your Lua CLI session has expired. Run `lua auth configure`.", "invalid_credentials");
8359
- }
8360
- live = await refreshFirebaseSession({
8361
- idToken: "",
8362
- refreshToken: stored.refreshToken,
8363
- expiresAt: 0,
8364
- uid: stored.firebaseUid
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
8365
8659
  });
8366
- return {
8367
- ...stored,
8368
- refreshToken: live.refreshToken,
8369
- firebaseUid: live.uid
8370
- };
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
8371
8672
  });
8372
- if (!live) throw new Error("Firebase session refresh did not return a session.");
8373
- this.liveSession = live;
8374
- return live.idToken;
8673
+ }
8674
+ static isCliError(error) {
8675
+ return error instanceof _CliError || typeof error === "object" && error !== null && error.isCliError === true;
8375
8676
  }
8376
8677
  };
8377
- __name(resolveRequestCredential, "resolveRequestCredential");
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");
8378
8724
  }
8379
8725
  });
8380
8726
 
@@ -8388,6 +8734,10 @@ async function classifyErrorResponse(response) {
8388
8734
  errorData = {};
8389
8735
  }
8390
8736
  if (response.status === 401) {
8737
+ if (serverCodeOf(errorData.code, errorData.error) === SESSION_REVOKED_CODE) {
8738
+ await clearStoredFirebaseSession().catch(() => false);
8739
+ throw sessionSignedOutError();
8740
+ }
8391
8741
  const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
8392
8742
  if (serverMessage && /not an admin/i.test(serverMessage)) {
8393
8743
  throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
@@ -8513,6 +8863,7 @@ var init_http_client = __esm({
8513
8863
  "src/api/http.client.ts"() {
8514
8864
  "use strict";
8515
8865
  init_dist();
8866
+ init_dist();
8516
8867
  init_auth_error();
8517
8868
  init_cli_error();
8518
8869
  init_lua_fetch();
@@ -8837,23 +9188,25 @@ var init_http_client = __esm({
8837
9188
  }
8838
9189
  });
8839
9190
 
8840
- // src/api/auth.api.service.ts
8841
- var init_auth_api_service = __esm({
8842
- "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"() {
8843
9194
  "use strict";
8844
9195
  init_http_client();
9196
+ init_dist();
8845
9197
  }
8846
9198
  });
8847
9199
 
8848
- // src/services/auth.ts
8849
- import "dotenv/config";
8850
- var init_auth = __esm({
8851
- "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"() {
8852
9203
  "use strict";
8853
- init_auth_api_service();
9204
+ init_dist();
9205
+ init_cli_credentials_api_service();
8854
9206
  init_constants();
8855
9207
  init_auth_error();
8856
9208
  init_cli_error();
9209
+ init_request_credential();
8857
9210
  }
8858
9211
  });
8859
9212
 
@@ -9152,7 +9505,7 @@ function walkWorkspace(rootDir, opts = {}) {
9152
9505
  const refs = [];
9153
9506
  const contentByHash = /* @__PURE__ */ new Map();
9154
9507
  let totalSize = 0;
9155
- const visit = /* @__PURE__ */ __name4((relPrefix) => {
9508
+ const visit = /* @__PURE__ */ __name5((relPrefix) => {
9156
9509
  const absDir = relPrefix ? join4(rootDir, relPrefix) : rootDir;
9157
9510
  let entries;
9158
9511
  try {
@@ -9446,21 +9799,21 @@ function walk2(root, prefix, out) {
9446
9799
  }
9447
9800
  }
9448
9801
  }
9449
- 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;
9450
9803
  var init_dist3 = __esm({
9451
9804
  "../shared-source-sync/dist/index.mjs"() {
9452
9805
  "use strict";
9453
- __defProp4 = Object.defineProperty;
9454
- __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");
9455
9808
  FILE_HASH_LENGTH = 16;
9456
9809
  __name(hashContentTruncated, "hashContentTruncated");
9457
- __name4(hashContentTruncated, "hashContentTruncated");
9810
+ __name5(hashContentTruncated, "hashContentTruncated");
9458
9811
  __name(sha256Hex, "sha256Hex");
9459
- __name4(sha256Hex, "sha256Hex");
9812
+ __name5(sha256Hex, "sha256Hex");
9460
9813
  __name(matchesFileHash, "matchesFileHash");
9461
- __name4(matchesFileHash, "matchesFileHash");
9814
+ __name5(matchesFileHash, "matchesFileHash");
9462
9815
  __name(combineFileHashes, "combineFileHashes");
9463
- __name4(combineFileHashes, "combineFileHashes");
9816
+ __name5(combineFileHashes, "combineFileHashes");
9464
9817
  SKIP_DIRECTORIES = /* @__PURE__ */ new Set([
9465
9818
  "node_modules",
9466
9819
  "dist",
@@ -9477,9 +9830,9 @@ var init_dist3 = __esm({
9477
9830
  ]);
9478
9831
  DEFAULT_MAX_FILE_BYTES = 256 * 1024;
9479
9832
  __name(shouldSkipDirectory, "shouldSkipDirectory");
9480
- __name4(shouldSkipDirectory, "shouldSkipDirectory");
9833
+ __name5(shouldSkipDirectory, "shouldSkipDirectory");
9481
9834
  __name(shouldSkipFile, "shouldSkipFile");
9482
- __name4(shouldSkipFile, "shouldSkipFile");
9835
+ __name5(shouldSkipFile, "shouldSkipFile");
9483
9836
  KIND_BY_EXT = {
9484
9837
  ".ts": "source",
9485
9838
  ".tsx": "source",
@@ -9491,16 +9844,16 @@ var init_dist3 = __esm({
9491
9844
  ".toml": "config"
9492
9845
  };
9493
9846
  __name(classifyFile, "classifyFile");
9494
- __name4(classifyFile, "classifyFile");
9847
+ __name5(classifyFile, "classifyFile");
9495
9848
  __name(walkWorkspace, "walkWorkspace");
9496
- __name4(walkWorkspace, "walkWorkspace");
9849
+ __name5(walkWorkspace, "walkWorkspace");
9497
9850
  CHECK_BLOBS_MAX_HASHES = 500;
9498
9851
  BackupHttpError = class extends Error {
9499
9852
  static {
9500
9853
  __name(this, "BackupHttpError");
9501
9854
  }
9502
9855
  static {
9503
- __name4(this, "BackupHttpError");
9856
+ __name5(this, "BackupHttpError");
9504
9857
  }
9505
9858
  status;
9506
9859
  endpoint;
@@ -9515,7 +9868,7 @@ var init_dist3 = __esm({
9515
9868
  __name(this, "BackupHttpClient");
9516
9869
  }
9517
9870
  static {
9518
- __name4(this, "BackupHttpClient");
9871
+ __name5(this, "BackupHttpClient");
9519
9872
  }
9520
9873
  options;
9521
9874
  fetchFn;
@@ -9620,17 +9973,17 @@ var init_dist3 = __esm({
9620
9973
  };
9621
9974
  DEFAULT_CONCURRENCY = 10;
9622
9975
  __name(uploadBlobs, "uploadBlobs");
9623
- __name4(uploadBlobs, "uploadBlobs");
9976
+ __name5(uploadBlobs, "uploadBlobs");
9624
9977
  __name(decodeBlob, "decodeBlob");
9625
- __name4(decodeBlob, "decodeBlob");
9978
+ __name5(decodeBlob, "decodeBlob");
9626
9979
  __name(verifyDownloaded, "verifyDownloaded");
9627
- __name4(verifyDownloaded, "verifyDownloaded");
9980
+ __name5(verifyDownloaded, "verifyDownloaded");
9628
9981
  __name(downloadBlobs, "downloadBlobs");
9629
- __name4(downloadBlobs, "downloadBlobs");
9982
+ __name5(downloadBlobs, "downloadBlobs");
9630
9983
  __name(resolveBackupFileTarget, "resolveBackupFileTarget");
9631
- __name4(resolveBackupFileTarget, "resolveBackupFileTarget");
9984
+ __name5(resolveBackupFileTarget, "resolveBackupFileTarget");
9632
9985
  __name(restoreFromBlobs, "restoreFromBlobs");
9633
- __name4(restoreFromBlobs, "restoreFromBlobs");
9986
+ __name5(restoreFromBlobs, "restoreFromBlobs");
9634
9987
  CREDENTIAL_PATHS = /* @__PURE__ */ new Set([
9635
9988
  ".env",
9636
9989
  ".lua/config.json",
@@ -9638,22 +9991,22 @@ var init_dist3 = __esm({
9638
9991
  ]);
9639
9992
  WINDOWS_ABSOLUTE_PATH = /^[a-z]:\//i;
9640
9993
  __name(normalizeWorkspaceRelativePath, "normalizeWorkspaceRelativePath");
9641
- __name4(normalizeWorkspaceRelativePath, "normalizeWorkspaceRelativePath");
9994
+ __name5(normalizeWorkspaceRelativePath, "normalizeWorkspaceRelativePath");
9642
9995
  __name(isCredentialPersistencePath, "isCredentialPersistencePath");
9643
- __name4(isCredentialPersistencePath, "isCredentialPersistencePath");
9996
+ __name5(isCredentialPersistencePath, "isCredentialPersistencePath");
9644
9997
  __name(pushAgentBackup, "pushAgentBackup");
9645
- __name4(pushAgentBackup, "pushAgentBackup");
9998
+ __name5(pushAgentBackup, "pushAgentBackup");
9646
9999
  __name(pullAgentBackup, "pullAgentBackup");
9647
- __name4(pullAgentBackup, "pullAgentBackup");
10000
+ __name5(pullAgentBackup, "pullAgentBackup");
9648
10001
  ARCHIVE_SCHEMA_VERSION = 1;
9649
10002
  __name(encodeWorkspaceArchive, "encodeWorkspaceArchive");
9650
- __name4(encodeWorkspaceArchive, "encodeWorkspaceArchive");
10003
+ __name5(encodeWorkspaceArchive, "encodeWorkspaceArchive");
9651
10004
  __name(decodeWorkspaceArchive, "decodeWorkspaceArchive");
9652
- __name4(decodeWorkspaceArchive, "decodeWorkspaceArchive");
10005
+ __name5(decodeWorkspaceArchive, "decodeWorkspaceArchive");
9653
10006
  __name(writeArchiveToWorkspace, "writeArchiveToWorkspace");
9654
- __name4(writeArchiveToWorkspace, "writeArchiveToWorkspace");
10007
+ __name5(writeArchiveToWorkspace, "writeArchiveToWorkspace");
9655
10008
  __name(walk2, "walk");
9656
- __name4(walk2, "walk");
10009
+ __name5(walk2, "walk");
9657
10010
  }
9658
10011
  });
9659
10012
 
@@ -10538,8 +10891,8 @@ async function requireAuth() {
10538
10891
  var init_command_utils = __esm({
10539
10892
  "src/utils/command-utils.ts"() {
10540
10893
  "use strict";
10541
- init_auth();
10542
10894
  init_request_credential();
10895
+ init_credential_operational_context();
10543
10896
  init_files();
10544
10897
  init_cli();
10545
10898
  init_cli_error();
@@ -13137,11 +13490,48 @@ var init_ai_api_service = __esm({
13137
13490
  });
13138
13491
 
13139
13492
  // src/api/integrations.api.service.ts
13140
- 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;
13141
13520
  var init_integrations_api_service = __esm({
13142
13521
  "src/api/integrations.api.service.ts"() {
13143
13522
  "use strict";
13144
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");
13145
13535
  IntegrationsApiService = class extends HttpClient {
13146
13536
  static {
13147
13537
  __name(this, "IntegrationsApiService");
@@ -13157,12 +13547,14 @@ var init_integrations_api_service = __esm({
13157
13547
  * Sandbox-facing wrapper: returns the raw provider envelope
13158
13548
  * `{ status, headers, data }` (provider error statuses relayed faithfully in
13159
13549
  * `status`), and throws only on route-level failures (no connection,
13160
- * 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.
13161
13553
  */
13162
13554
  async passthroughForSandbox(integrationType, request) {
13163
13555
  const result = await this.passthrough(integrationType, request);
13164
13556
  if (!result.success || !result.data) {
13165
- 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));
13166
13558
  }
13167
13559
  return result.data;
13168
13560
  }