lua-cli 3.32.4 → 3.32.5

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.
@@ -7314,11 +7314,21 @@ declare interface WorkflowRun {
7314
7314
  parentRunId?: string;
7315
7315
  correlationKey?: string;
7316
7316
  tags?: string[];
7317
+ /** R4 `gate` (02 §2.4). LUA-788: a `kind:'billing'` gate names the wallet's refusal (`code`), the held step and its expiry. */
7317
7318
  gate?: {
7318
7319
  kind: string;
7319
7320
  reason?: string;
7320
- since?: string;
7321
+ since?: string | number;
7322
+ code?: string;
7323
+ stepId?: string;
7324
+ expiresAt?: number;
7321
7325
  };
7326
+ /**
7327
+ * Server-decided (09 §9.6): `raise_budget` on a budget gate (LUA-665), `top_up` on a billing gate (LUA-788 — the
7328
+ * wallet clears it; the engine re-checks and resumes on its own), `cancel_again` / `force` under a pending cancel,
7329
+ * else `none`. Absent on an older server.
7330
+ */
7331
+ nextAction?: 'cancel_again' | 'force' | 'none' | 'raise_budget' | 'top_up';
7322
7332
  /**
7323
7333
  * The pending / audited cancel request (`runCancelView`): who asked and when; `wall` when it was the run wall's
7324
7334
  * own (LUA-686); LUA-704: `forcedBy` / `forcedAt` / `forceReason` on a forced terminal (`abandoned`, or
@@ -544,6 +544,11 @@ function isDeviceCredentialPrincipal(context) {
544
544
  function hasDeviceCredentialType(value3) {
545
545
  return DeviceCredentialClaimSchema.safeParse(value3).success;
546
546
  }
547
+ function sessionAuthTime(context) {
548
+ if (!context || context.credential.type !== "firstPartySession") return void 0;
549
+ const authTime = context.authTime;
550
+ return typeof authTime === "number" && Number.isInteger(authTime) && authTime >= 0 && authTime <= SESSION_AUTH_TIME_MAX_S ? authTime : void 0;
551
+ }
547
552
  function isTypedApiKeyPrincipal(context) {
548
553
  return context?.subject.subjectType === "apiKey" && context.credential.type === "apiKey" && !context.compatibility;
549
554
  }
@@ -716,6 +721,39 @@ function scheduledWorkflowRunId(jobId, scheduledTime) {
716
721
  const key = typeof scheduledTime === "number" ? String(scheduledTime) : scheduledTimeKey(scheduledTime);
717
722
  return `${WORKFLOW_SCHEDULED_RUN_ID_PREFIX}${jobId}_${key}`;
718
723
  }
724
+ function renderWorkflowScheduleKeyTemplate(template3, ctx) {
725
+ if (!template3) return void 0;
726
+ const read = /* @__PURE__ */ __name2((path3) => path3.split(".").reduce((o, k) => o && typeof o === "object" ? o[k] : void 0, ctx.input), "read");
727
+ let unresolved = false;
728
+ const out = template3.replace(/\$\{\s*([a-zA-Z0-9_.]+)\s*\}/g, (_m, expr) => {
729
+ let v = "";
730
+ if (expr === "scheduledTime") v = ctx.scheduledTime ?? "";
731
+ else if (expr.startsWith("input.")) v = read(expr.slice("input.".length));
732
+ const s = v === void 0 || v === null ? "" : String(v);
733
+ if (s === "") unresolved = true;
734
+ return s;
735
+ });
736
+ if (unresolved) return void 0;
737
+ const key = out.slice(0, WORKFLOW_SCHEDULE_KEY_MAX);
738
+ return key && /^[A-Za-z0-9:_\-.\/]+$/.test(key) ? key : void 0;
739
+ }
740
+ function scheduledWorkflowIdempotencyKey(jobId, rendered) {
741
+ const head = `${WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX}${jobId}:`;
742
+ if (head.length + rendered.length <= WORKFLOW_SCHEDULE_KEY_MAX) return `${head}${rendered}`;
743
+ const digest = stableKeyDigest(rendered);
744
+ const room = WORKFLOW_SCHEDULE_KEY_MAX - head.length - digest.length - 1;
745
+ return `${head}${rendered.slice(0, Math.max(0, room))}~${digest}`;
746
+ }
747
+ function stableKeyDigest(s) {
748
+ let a = 2166136261;
749
+ let b = 84696351;
750
+ for (let i = 0; i < s.length; i++) {
751
+ const c = s.charCodeAt(i);
752
+ a = Math.imul(a ^ c, 16777619);
753
+ b = Math.imul(b ^ c, 16777619) ^ b >>> 13;
754
+ }
755
+ return (a >>> 0).toString(16).padStart(8, "0") + (b >>> 0).toString(16).padStart(8, "0");
756
+ }
719
757
  function workflowOperationId(runId, stepId, billingEpoch) {
720
758
  return `${WORKFLOW_OPERATION_ID_PREFIX}${runId}:${stepId}:${billingEpoch}`;
721
759
  }
@@ -1019,7 +1057,59 @@ function extractSingleJsonValue(text) {
1019
1057
  };
1020
1058
  }
1021
1059
  }
1022
- var __defProp2, __name2, CHANNEL_SEND_CHANNELS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, MODEL_ID_BYOK_PROVIDERS, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, CORE_DRAINING_CODE, CORE_DRAINING_DEFAULT_RETRY_MS, CORE_DRAINING_MAX_RETRY_MS, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS, TEMPLATE_TRIGGER_URL_ENV_PREFIX, SUBJECT_TYPES, SubjectTypeSchema, CREDENTIAL_TYPES, CredentialTypeSchema, DEVICE_OPERATIONS, DeviceOperationSchema, DEVICE_SCOPE_BY_OPERATION, DeviceBindingSchema, IdSchema, PrincipalDescriptorSchema, ActorDescriptorSchema, PrincipalOwnerSchema, CredentialLifecycleSchema, GeneralCredentialDescriptorSchema, DeviceCredentialDescriptorSchema, GeneralPrincipalContextSchema, DeviceCredentialPrincipalContextSchema, RawPrincipalContextSchema, PrincipalContextSchema, DeviceCredentialClaimSchema, LUA_CLIENT_HEADER, LUA_CLIENT_APPS, SEMVER_PATTERN, WEB_RELEASE_PATTERN, CLIENT_HEADER_PATTERN, AUTHZ_PROJECTION_VERSION, ProjectedScopeSchema, DisplayRoleSchema, AuthorizationPrincipalSchema, CredentialContextSchema, ProjectionAnomalySchema, ProjectedOrgSchema, ProjectedResourceSchema, CapabilityProfilesSchema, RoleCatalogSchema, EffectiveAuthorizationSchema, ResourcePageSchema, SYSTEM_USER_PREFIX, WORKFLOW_RUN_IN_FLIGHT, WORKFLOW_RUN_IDLE, WORKFLOW_RUN_TERMINAL, WORKFLOW_RUN_STATUSES, WORKFLOW_STEP_STATUSES, WORKFLOW_STEP_IN_FLIGHT, ARCHIVE_WINDOW_MARGIN_DAYS, WORKFLOW_ORG_PURGING_TTL_S, WORKFLOW_ORG_PURGE_FORCE_AFTER_MS, IDEMPOTENCY_HOLDING_STATUSES, WORKFLOW_SCHEDULED_RUN_ID_PREFIX, CLOUD_TASK_RUN_ID_PREFIX, WORKFLOW_OPERATION_ID_PREFIX, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, WORKFLOW_RETRY_BACKOFFS, WORKFLOW_RETRY_MIN_ATTEMPTS, WORKFLOW_RETRY_POLICY_KEYS, WORKFLOW_RETRY_MAX_ATTEMPTS, WORKFLOW_RETRY_ENGINE_KEYS, WORKFLOW_JOB_RESOURCES, WORKFLOW_SIDE_EFFECTS, WORKFLOW_JOB_RANGES, WORKFLOW_JOB_RANGE_MEMBERS, WORKFLOW_SINGLE_STEP_TYPES, WORKFLOW_HITL_ENTRY_TYPES, WORKFLOW_ARM_ENTRY_TYPES, WORKFLOW_HITL_ARM_CONTAINERS, WORKFLOW_GRAPH_ENTRY_STEP_KINDS, WORKFLOW_ARM_ENTRY_STEP_KINDS, WORKFLOW_BUDGET_MAX_DURATION_SECONDS, REDACTED_PLACEHOLDER, PROVIDER_MESSAGE_MAX_CHARS, ERROR_MESSAGE_MAX_CHARS, SECRET_LITERAL_PATTERNS, SECRET_NAME, SECRET_PAIR_PATTERNS, GROUP_COUNT, WORKFLOW_SECRET_KEY_RE, WORKFLOW_RESERVED_SECRET_KEYS, SCRUB_INPUT_MAX_CHARS, SCRUB_CUT_BACKOFF_CHARS, WORKFLOW_AUDIT_EVENTS, WORKFLOW_AUDIT_METADATA_MAX_BYTES, INDENT, WRAP_WIDTH, NOUNS, GET_TOOL_NAMES, PREAMBLE, WORKFLOW_APPROVAL_OUTPUT_DECISIONS, WORKFLOW_APPROVAL_OUTPUT_SCHEMA, JSON_FENCE_RE;
1060
+ function agentFeatureCatalogDefault(featureName) {
1061
+ return DEFAULT_ON_AGENT_FEATURES.includes(featureName);
1062
+ }
1063
+ function hasExplicitFeatureActive(row) {
1064
+ return typeof row?.active === "boolean";
1065
+ }
1066
+ function effectiveFeatureActive(row, catalogDefault) {
1067
+ return hasExplicitFeatureActive(row) ? row.active : catalogDefault;
1068
+ }
1069
+ function resolveEffectiveFeature(row, catalogDefault) {
1070
+ return hasExplicitFeatureActive(row) ? {
1071
+ active: row.active,
1072
+ source: "agent",
1073
+ default: catalogDefault
1074
+ } : {
1075
+ active: catalogDefault,
1076
+ source: "default",
1077
+ default: catalogDefault
1078
+ };
1079
+ }
1080
+ function isFeatureRow(value3) {
1081
+ return typeof value3 === "object" && value3 !== null;
1082
+ }
1083
+ function effectiveAgentFeatureRows(base, override) {
1084
+ const merged = /* @__PURE__ */ new Map();
1085
+ for (const [name, row] of Object.entries(base ?? {})) {
1086
+ if (isFeatureRow(row)) merged.set(name, {
1087
+ row,
1088
+ origin: "baseAgent"
1089
+ });
1090
+ }
1091
+ for (const [name, row] of Object.entries(override ?? {})) {
1092
+ if (isFeatureRow(row)) merged.set(name, {
1093
+ row,
1094
+ origin: "subAgent"
1095
+ });
1096
+ }
1097
+ return {
1098
+ rows: Object.fromEntries([
1099
+ ...merged
1100
+ ].map(([name, e]) => [
1101
+ name,
1102
+ e.row
1103
+ ])),
1104
+ origins: Object.fromEntries([
1105
+ ...merged
1106
+ ].map(([name, e]) => [
1107
+ name,
1108
+ e.origin
1109
+ ]))
1110
+ };
1111
+ }
1112
+ var __defProp2, __name2, CHANNEL_SEND_CHANNELS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, MODEL_ID_BYOK_PROVIDERS, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, CORE_DRAINING_CODE, CORE_DRAINING_DEFAULT_RETRY_MS, CORE_DRAINING_MAX_RETRY_MS, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS, TEMPLATE_TRIGGER_URL_ENV_PREFIX, SUBJECT_TYPES, SubjectTypeSchema, CREDENTIAL_TYPES, CredentialTypeSchema, DEVICE_OPERATIONS, DeviceOperationSchema, DEVICE_SCOPE_BY_OPERATION, DeviceBindingSchema, IdSchema, SESSION_AUTH_TIME_MAX_S, PrincipalDescriptorSchema, ActorDescriptorSchema, PrincipalOwnerSchema, CredentialLifecycleSchema, GeneralCredentialDescriptorSchema, DeviceCredentialDescriptorSchema, GeneralPrincipalContextSchema, DeviceCredentialPrincipalContextSchema, RawPrincipalContextSchema, PrincipalContextSchema, DeviceCredentialClaimSchema, LUA_CLIENT_HEADER, LUA_CLIENT_APPS, SEMVER_PATTERN, WEB_RELEASE_PATTERN, CLIENT_HEADER_PATTERN, AUTHZ_PROJECTION_VERSION, ProjectedScopeSchema, DisplayRoleSchema, AuthorizationPrincipalSchema, CredentialContextSchema, ProjectionAnomalySchema, ProjectedOrgSchema, ProjectedResourceSchema, CapabilityProfilesSchema, RoleCatalogSchema, EffectiveAuthorizationSchema, ResourcePageSchema, SYSTEM_USER_PREFIX, WORKFLOW_RUN_IN_FLIGHT, WORKFLOW_RUN_IDLE, WORKFLOW_RUN_TERMINAL, WORKFLOW_RUN_STATUSES, WORKFLOW_STEP_STATUSES, WORKFLOW_STEP_IN_FLIGHT, ARCHIVE_WINDOW_MARGIN_DAYS, WORKFLOW_ORG_PURGING_TTL_S, WORKFLOW_ORG_PURGE_FORCE_AFTER_MS, IDEMPOTENCY_HOLDING_STATUSES, WORKFLOW_SCHEDULED_RUN_ID_PREFIX, CLOUD_TASK_RUN_ID_PREFIX, WORKFLOW_SCHEDULE_KEY_MAX, WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX, WORKFLOW_OPERATION_ID_PREFIX, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, WORKFLOW_RETRY_BACKOFFS, WORKFLOW_RETRY_MIN_ATTEMPTS, WORKFLOW_RETRY_POLICY_KEYS, WORKFLOW_RETRY_MAX_ATTEMPTS, WORKFLOW_RETRY_ENGINE_KEYS, WORKFLOW_JOB_RESOURCES, WORKFLOW_SIDE_EFFECTS, WORKFLOW_JOB_RANGES, WORKFLOW_JOB_RANGE_MEMBERS, WORKFLOW_SINGLE_STEP_TYPES, WORKFLOW_HITL_ENTRY_TYPES, WORKFLOW_ARM_ENTRY_TYPES, WORKFLOW_HITL_ARM_CONTAINERS, WORKFLOW_GRAPH_ENTRY_STEP_KINDS, WORKFLOW_ARM_ENTRY_STEP_KINDS, WORKFLOW_BUDGET_MAX_DURATION_SECONDS, REDACTED_PLACEHOLDER, PROVIDER_MESSAGE_MAX_CHARS, ERROR_MESSAGE_MAX_CHARS, SECRET_LITERAL_PATTERNS, SECRET_NAME, SECRET_PAIR_PATTERNS, GROUP_COUNT, WORKFLOW_SECRET_KEY_RE, WORKFLOW_RESERVED_SECRET_KEYS, SCRUB_INPUT_MAX_CHARS, SCRUB_CUT_BACKOFF_CHARS, WORKFLOW_AUDIT_EVENTS, WORKFLOW_AUDIT_METADATA_MAX_BYTES, INDENT, WRAP_WIDTH, NOUNS, GET_TOOL_NAMES, PREAMBLE, WORKFLOW_APPROVAL_OUTPUT_DECISIONS, WORKFLOW_APPROVAL_OUTPUT_SCHEMA, JSON_FENCE_RE, DEFAULT_ON_AGENT_FEATURES;
1023
1113
  var init_dist = __esm({
1024
1114
  "../shared-types/dist/index.mjs"() {
1025
1115
  "use strict";
@@ -1764,6 +1854,7 @@ This text is who you are for this person. As you learn them, their name, their w
1764
1854
  }
1765
1855
  });
1766
1856
  IdSchema = z2.string().min(1).max(256);
1857
+ SESSION_AUTH_TIME_MAX_S = 4102444800;
1767
1858
  PrincipalDescriptorSchema = z2.object({
1768
1859
  subjectType: SubjectTypeSchema,
1769
1860
  subjectId: IdSchema
@@ -1812,7 +1903,8 @@ This text is who you are for this person. As you learn them, their name, their w
1812
1903
  owner: PrincipalOwnerSchema.optional(),
1813
1904
  compatibility: z2.object({
1814
1905
  mode: z2.literal("legacy-owner-delegation")
1815
- }).strict().optional()
1906
+ }).strict().optional(),
1907
+ authTime: z2.number().int().nonnegative().max(SESSION_AUTH_TIME_MAX_S).optional()
1816
1908
  }).strict();
1817
1909
  DeviceCredentialPrincipalContextSchema = z2.object({
1818
1910
  version: z2.literal(1),
@@ -1868,6 +1960,8 @@ This text is who you are for this person. As you learn them, their name, their w
1868
1960
  }).passthrough();
1869
1961
  __name(hasDeviceCredentialType, "hasDeviceCredentialType");
1870
1962
  __name2(hasDeviceCredentialType, "hasDeviceCredentialType");
1963
+ __name(sessionAuthTime, "sessionAuthTime");
1964
+ __name2(sessionAuthTime, "sessionAuthTime");
1871
1965
  __name(isTypedApiKeyPrincipal, "isTypedApiKeyPrincipal");
1872
1966
  __name2(isTypedApiKeyPrincipal, "isTypedApiKeyPrincipal");
1873
1967
  __name(typedApiKeyPrincipalId, "typedApiKeyPrincipalId");
@@ -2099,6 +2193,14 @@ This text is who you are for this person. As you learn them, their name, their w
2099
2193
  __name2(isScheduledWorkflowRunId, "isScheduledWorkflowRunId");
2100
2194
  __name(scheduledWorkflowRunId, "scheduledWorkflowRunId");
2101
2195
  __name2(scheduledWorkflowRunId, "scheduledWorkflowRunId");
2196
+ WORKFLOW_SCHEDULE_KEY_MAX = 128;
2197
+ __name(renderWorkflowScheduleKeyTemplate, "renderWorkflowScheduleKeyTemplate");
2198
+ __name2(renderWorkflowScheduleKeyTemplate, "renderWorkflowScheduleKeyTemplate");
2199
+ WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX = "sched:";
2200
+ __name(scheduledWorkflowIdempotencyKey, "scheduledWorkflowIdempotencyKey");
2201
+ __name2(scheduledWorkflowIdempotencyKey, "scheduledWorkflowIdempotencyKey");
2202
+ __name(stableKeyDigest, "stableKeyDigest");
2203
+ __name2(stableKeyDigest, "stableKeyDigest");
2102
2204
  WORKFLOW_OPERATION_ID_PREFIX = "wf:";
2103
2205
  __name(workflowOperationId, "workflowOperationId");
2104
2206
  __name2(workflowOperationId, "workflowOperationId");
@@ -2544,6 +2646,23 @@ listed here; never invent a target.`;
2544
2646
  JSON_FENCE_RE = /```(?:json)?[ \t]*\r?\n([\s\S]*?)\r?\n?```/g;
2545
2647
  __name(extractSingleJsonValue, "extractSingleJsonValue");
2546
2648
  __name2(extractSingleJsonValue, "extractSingleJsonValue");
2649
+ DEFAULT_ON_AGENT_FEATURES = [
2650
+ "workflows",
2651
+ "workflowCompose",
2652
+ "observationalMemory"
2653
+ ];
2654
+ __name(agentFeatureCatalogDefault, "agentFeatureCatalogDefault");
2655
+ __name2(agentFeatureCatalogDefault, "agentFeatureCatalogDefault");
2656
+ __name(hasExplicitFeatureActive, "hasExplicitFeatureActive");
2657
+ __name2(hasExplicitFeatureActive, "hasExplicitFeatureActive");
2658
+ __name(effectiveFeatureActive, "effectiveFeatureActive");
2659
+ __name2(effectiveFeatureActive, "effectiveFeatureActive");
2660
+ __name(resolveEffectiveFeature, "resolveEffectiveFeature");
2661
+ __name2(resolveEffectiveFeature, "resolveEffectiveFeature");
2662
+ __name(isFeatureRow, "isFeatureRow");
2663
+ __name2(isFeatureRow, "isFeatureRow");
2664
+ __name(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2665
+ __name2(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2547
2666
  }
2548
2667
  });
2549
2668
 
@@ -3176,7 +3295,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3176
3295
  const id = singleId(node);
3177
3296
  const unknown = unknownWorkflowRetryMembers(r);
3178
3297
  if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path3}.retry`, id);
3179
- if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
3298
+ if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
3180
3299
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
3181
3300
  err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path3}.retry.maxAttempts`, id);
3182
3301
  }
@@ -4717,6 +4836,7 @@ function runErrorIssues(issues) {
4717
4836
  function runNextAction(run) {
4718
4837
  if (isTerminalRunStatus(run.status)) return "none";
4719
4838
  if (run.status === "suspended" && run.gate?.kind === "budget") return "raise_budget";
4839
+ if (run.status === "suspended" && run.gate?.kind === "billing") return "top_up";
4720
4840
  if (!run.cancel?.requestedAt) return "none";
4721
4841
  const forceAt = run.cancel.forceAfter ?? run.cancel.requestedAt + FORCE_CANCEL_STALE_MS;
4722
4842
  return Date.now() >= forceAt ? "force" : "cancel_again";
@@ -4744,6 +4864,12 @@ function runCountsFromStepStatuses(statuses) {
4744
4864
  for (const s of statuses) tally[s] = (tally[s] ?? 0) + 1;
4745
4865
  return runCountsFromStatusTally(tally);
4746
4866
  }
4867
+ function isBillingHeldStep(row) {
4868
+ return row.status === "ready" && row.billingHold === true;
4869
+ }
4870
+ function stepEffectiveStatus(row) {
4871
+ return isBillingHeldStep(row) ? "suspended" : row.status;
4872
+ }
4747
4873
  function runCounts(counts) {
4748
4874
  const c = counts ?? {};
4749
4875
  const rawInFlight = c.dispatched !== void 0 || c.claimed !== void 0 || c.running !== void 0 || c.cancellation_requested !== void 0;
@@ -6274,6 +6400,10 @@ var init_dist2 = __esm({
6274
6400
  __name3(runCountsFromStatusTally, "runCountsFromStatusTally");
6275
6401
  __name(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6276
6402
  __name3(runCountsFromStepStatuses, "runCountsFromStepStatuses");
6403
+ __name(isBillingHeldStep, "isBillingHeldStep");
6404
+ __name3(isBillingHeldStep, "isBillingHeldStep");
6405
+ __name(stepEffectiveStatus, "stepEffectiveStatus");
6406
+ __name3(stepEffectiveStatus, "stepEffectiveStatus");
6277
6407
  n = /* @__PURE__ */ __name3((v) => typeof v === "number" && Number.isFinite(v) ? v : 0, "n");
6278
6408
  __name(runCounts, "runCounts");
6279
6409
  __name3(runCounts, "runCounts");
@@ -6691,7 +6821,7 @@ var init_workflow = __esm({
6691
6821
  }, "assertPredicate");
6692
6822
  assertRetry = /* @__PURE__ */ __name((r, id) => {
6693
6823
  if (!r) return;
6694
- if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
6824
+ if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
6695
6825
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
6696
6826
  throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
6697
6827
  }
@@ -7492,7 +7622,10 @@ function classifyCliError(error) {
7492
7622
  code: error.code,
7493
7623
  exitCode: error.exitCode,
7494
7624
  message: error.message,
7495
- hint: error.hint
7625
+ hint: error.hint,
7626
+ statusCode: error.statusCode,
7627
+ serverCode: error.serverCode,
7628
+ issues: error.issues
7496
7629
  };
7497
7630
  }
7498
7631
  if (AuthenticationError.isAuthenticationError(error)) {
@@ -7514,30 +7647,36 @@ function classifyCliError(error) {
7514
7647
  }
7515
7648
  const status = numericStatus(e);
7516
7649
  if (status !== void 0) {
7650
+ const statusCode = status;
7517
7651
  if (status === 401) return {
7518
7652
  code: "auth",
7519
7653
  exitCode: CLI_EXIT.AUTH,
7520
- message
7654
+ message,
7655
+ statusCode
7521
7656
  };
7522
7657
  if (status === 403) return {
7523
7658
  code: "forbidden",
7524
7659
  exitCode: CLI_EXIT.FORBIDDEN,
7525
- message
7660
+ message,
7661
+ statusCode
7526
7662
  };
7527
7663
  if (status === 404) return {
7528
7664
  code: "not_found",
7529
7665
  exitCode: CLI_EXIT.NOT_FOUND,
7530
- message
7666
+ message,
7667
+ statusCode
7531
7668
  };
7532
7669
  if (status >= 400 && status < 500) return {
7533
7670
  code: `http_${status}`,
7534
7671
  exitCode: CLI_EXIT.FORBIDDEN,
7535
- message
7672
+ message,
7673
+ statusCode
7536
7674
  };
7537
7675
  if (status >= 500 || status === 0) return {
7538
7676
  code: "unavailable",
7539
7677
  exitCode: CLI_EXIT.UNAVAILABLE,
7540
- message
7678
+ message,
7679
+ statusCode
7541
7680
  };
7542
7681
  }
7543
7682
  const causeCode = e.cause?.code;
@@ -7578,6 +7717,8 @@ var init_cli_error = __esm({
7578
7717
  exitCode;
7579
7718
  hint;
7580
7719
  statusCode;
7720
+ serverCode;
7721
+ issues;
7581
7722
  constructor(code, message, options = {}) {
7582
7723
  super(message);
7583
7724
  this.name = "CliError";
@@ -7585,6 +7726,8 @@ var init_cli_error = __esm({
7585
7726
  this.exitCode = options.exitCode ?? CLI_EXIT.ERROR;
7586
7727
  this.hint = options.hint;
7587
7728
  this.statusCode = options.statusCode;
7729
+ this.serverCode = options.serverCode;
7730
+ this.issues = options.issues?.length ? options.issues : void 0;
7588
7731
  if (Error.captureStackTrace) Error.captureStackTrace(this, _CliError);
7589
7732
  }
7590
7733
  /** Bad arguments, an unknown action, no project — exit 2. */
@@ -7617,7 +7760,7 @@ var init_cli_error = __esm({
7617
7760
  * A command that reads `response.error.statusCode` throws through here, so `lua logs` on a 503 exits 11 like
7618
7761
  * every other verb instead of printing the message itself and then throwing an exit-1 `Error`.
7619
7762
  */
7620
- static fromStatus(statusCode, message, hint) {
7763
+ static fromStatus(statusCode, message, hint, detail = {}) {
7621
7764
  const reported = classifyCliError(Object.assign(new Error(message), {
7622
7765
  statusCode
7623
7766
  }));
@@ -7625,7 +7768,9 @@ var init_cli_error = __esm({
7625
7768
  return new _CliError(reported.code, message, {
7626
7769
  exitCode: reported.exitCode,
7627
7770
  hint: hint ?? classHint,
7628
- statusCode
7771
+ statusCode,
7772
+ serverCode: detail.serverCode,
7773
+ issues: detail.issues
7629
7774
  });
7630
7775
  }
7631
7776
  static isCliError(error) {
@@ -8126,6 +8271,52 @@ var init_request_credential = __esm({
8126
8271
 
8127
8272
  // src/api/http.client.ts
8128
8273
  import { randomUUID as randomUUID2 } from "crypto";
8274
+ async function classifyErrorResponse(response) {
8275
+ let errorData;
8276
+ try {
8277
+ errorData = await response.json();
8278
+ } catch (jsonError) {
8279
+ errorData = {};
8280
+ }
8281
+ if (response.status === 401) {
8282
+ const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
8283
+ if (serverMessage && /not an admin/i.test(serverMessage)) {
8284
+ throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
8285
+ }
8286
+ const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
8287
+ const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
8288
+ if (isExplicitCredential || isBareAuthRejection) {
8289
+ throw new AuthenticationError("Authentication failed. Your Lua credential may be invalid or expired.", "invalid_credentials", serverMessage);
8290
+ }
8291
+ throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
8292
+ }
8293
+ if (response.status === 403) {
8294
+ const detail = errorData.message || "You do not have permission to access this resource.";
8295
+ const serverCode = serverCodeOf(errorData.code, errorData.error);
8296
+ throw new CliError("forbidden", `Access denied (403): ${detail}${serverCode ? ` (${serverCode})` : ""}`, {
8297
+ exitCode: CLI_EXIT.FORBIDDEN,
8298
+ statusCode: 403,
8299
+ serverCode,
8300
+ issues: Array.isArray(errorData.issues) ? errorData.issues : void 0,
8301
+ hint: "Check that your Lua login has access to this agent or organization."
8302
+ });
8303
+ }
8304
+ return {
8305
+ success: false,
8306
+ error: {
8307
+ message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
8308
+ statusCode: response.status,
8309
+ error: errorData.error,
8310
+ retryAfterSeconds: parseRetryAfter(response.headers.get("retry-after")),
8311
+ ...errorData
8312
+ }
8313
+ };
8314
+ }
8315
+ function serverCodeOf(code, error) {
8316
+ if (typeof code === "string" && code.length > 0) return code;
8317
+ if (typeof error === "string" && /^[A-Z0-9][A-Z0-9_]*$/.test(error)) return error;
8318
+ return void 0;
8319
+ }
8129
8320
  async function* parseSseStream(body, signal) {
8130
8321
  const reader = body.getReader();
8131
8322
  const decoder = new TextDecoder();
@@ -8306,42 +8497,7 @@ var init_http_client = __esm({
8306
8497
  * @private
8307
8498
  */
8308
8499
  async classifyErrorResponse(response) {
8309
- let errorData;
8310
- try {
8311
- errorData = await response.json();
8312
- } catch (jsonError) {
8313
- errorData = {};
8314
- }
8315
- if (response.status === 401) {
8316
- const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
8317
- if (serverMessage && /not an admin/i.test(serverMessage)) {
8318
- throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
8319
- }
8320
- const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
8321
- const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
8322
- if (isExplicitCredential || isBareAuthRejection) {
8323
- throw new AuthenticationError("Authentication failed. Your Lua credential may be invalid or expired.", "invalid_credentials", serverMessage);
8324
- }
8325
- throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
8326
- }
8327
- if (response.status === 403) {
8328
- const detail = errorData.message || "You do not have permission to access this resource.";
8329
- throw new CliError("forbidden", `Access denied (403): ${detail}`, {
8330
- exitCode: CLI_EXIT.FORBIDDEN,
8331
- statusCode: 403,
8332
- hint: "Check that your Lua login has access to this agent or organization."
8333
- });
8334
- }
8335
- return {
8336
- success: false,
8337
- error: {
8338
- message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
8339
- statusCode: response.status,
8340
- error: errorData.error,
8341
- retryAfterSeconds: parseRetryAfter(response.headers.get("retry-after")),
8342
- ...errorData
8343
- }
8344
- };
8500
+ return classifyErrorResponse(response);
8345
8501
  }
8346
8502
  /**
8347
8503
  * Checks if an HTTP status code is retryable
@@ -8549,6 +8705,8 @@ var init_http_client = __esm({
8549
8705
  };
8550
8706
  }
8551
8707
  };
8708
+ __name(classifyErrorResponse, "classifyErrorResponse");
8709
+ __name(serverCodeOf, "serverCodeOf");
8552
8710
  __name(parseSseStream, "parseSseStream");
8553
8711
  __name(parseRetryAfter, "parseRetryAfter");
8554
8712
  __name(isCoreDrainApiError, "isCoreDrainApiError");
@@ -12607,6 +12765,7 @@ var init_job_api_service = __esm({
12607
12765
  "src/api/job.api.service.ts"() {
12608
12766
  "use strict";
12609
12767
  init_http_client();
12768
+ init_cli_error();
12610
12769
  init_job_instance();
12611
12770
  JobApi = class extends HttpClient {
12612
12771
  static {
@@ -12663,7 +12822,7 @@ var init_job_api_service = __esm({
12663
12822
  if (response.success && response.data) {
12664
12823
  return new JobInstance(this, response.data);
12665
12824
  }
12666
- throw new Error(response.error?.message || "Failed to get job");
12825
+ throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Failed to get job");
12667
12826
  }
12668
12827
  /**
12669
12828
  * Creates a new job for the agent.