lua-cli 3.40.0 → 3.41.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.
package/dist/index.js CHANGED
@@ -1752,24 +1752,24 @@ function composePresetEndpoint(type, endpoint) {
1752
1752
  reason: "invalid_url"
1753
1753
  };
1754
1754
  const origin = url.origin;
1755
- const path26 = url.pathname.replace(/\/+$/, "");
1755
+ const path27 = url.pathname.replace(/\/+$/, "");
1756
1756
  if (!rule.segment) {
1757
- const base2 = path26.endsWith(rule.path) ? path26.slice(0, path26.length - rule.path.length) : path26;
1757
+ const base2 = path27.endsWith(rule.path) ? path27.slice(0, path27.length - rule.path.length) : path27;
1758
1758
  return {
1759
1759
  ok: true,
1760
1760
  endpoint: `${origin}${base2}${rule.path}`
1761
1761
  };
1762
1762
  }
1763
1763
  const marker = `${rule.path}/`;
1764
- const at = path26.indexOf(marker);
1764
+ const at = path27.indexOf(marker);
1765
1765
  if (at < 0) {
1766
1766
  return {
1767
1767
  ok: false,
1768
1768
  reason: rule.segment === "dataset" ? "missing_dataset" : "missing_token"
1769
1769
  };
1770
1770
  }
1771
- const base = path26.slice(0, at);
1772
- const afterMarker = path26.slice(at + marker.length);
1771
+ const base = path27.slice(0, at);
1772
+ const afterMarker = path27.slice(at + marker.length);
1773
1773
  const rest = rule.suffix && afterMarker.endsWith(rule.suffix) ? afterMarker.slice(0, afterMarker.length - rule.suffix.length) : afterMarker;
1774
1774
  if (!rest || rest.includes("/")) {
1775
1775
  return {
@@ -2467,7 +2467,7 @@ function scheduledWorkflowRunId(jobId, scheduledTime) {
2467
2467
  }
2468
2468
  function renderWorkflowScheduleKeyTemplate(template3, ctx) {
2469
2469
  if (!template3) return void 0;
2470
- const read = /* @__PURE__ */ __name2((path26) => path26.split(".").reduce((o, k) => o && typeof o === "object" ? o[k] : void 0, ctx.input), "read");
2470
+ const read = /* @__PURE__ */ __name2((path27) => path27.split(".").reduce((o, k) => o && typeof o === "object" ? o[k] : void 0, ctx.input), "read");
2471
2471
  let unresolved = false;
2472
2472
  const out = template3.replace(/\$\{\s*([a-zA-Z0-9_.]+)\s*\}/g, (_m, expr) => {
2473
2473
  let v = "";
@@ -3337,7 +3337,15 @@ function sortVerdictReasons(reasons) {
3337
3337
  ...reasons
3338
3338
  ].sort((a, b) => REVIEW_VERDICT_REASON_ORDER.indexOf(a.kind) - REVIEW_VERDICT_REASON_ORDER.indexOf(b.kind));
3339
3339
  }
3340
- var __defProp2, __name2, PLUMBING_THREAD_CHANNELS, CHANNEL_CONVERSATION_CHANNELS, HIDDEN_THREAD_CHANNELS, PLATFORM_INVOCATION_CALLERS, SUPERVISION_OPS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_STANDING_START_TOOLS, 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, LOG_FIELDS_MAX_KEYS, LOG_FIELD_MAX_VALUE_BYTES, LOG_FIELDS_MAX_BYTES, LOG_FIELD_KEY_PATTERN, LOG_FIELD_SECRET_SHAPED_KEY_PATTERNS, LOG_FIELDS_CLAMPED_KEY, LOG_FIELD_ARRAY_COUNT_SUFFIX, LuaLogFieldsError, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, 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_AGENT_EFFORTS, WORKFLOW_MODEL_CLASSES, WORKFLOW_TASK_CLASSES, WORKFLOW_MODEL_TRAITS, WORKFLOW_MODEL_REASON_MAX_LENGTH, WORKFLOW_MODELS_COMPOSE_MODES, WORKFLOW_MODELS_PIN_MODES, WORKFLOW_MODELS_FALLBACK_MODES, WORKFLOW_MODELS_CONSENT_ACTIONS_MIN, WORKFLOW_DEFAULT_TASK_CLASS_MAP, WORKFLOW_MODELS_MAX_CLASS_DEFAULT, WORKFLOW_AUTONOMY_FORMS, WORKFLOW_AUTONOMY_NUMERIC_KEYS, WORKFLOW_AUTONOMY_ENVELOPE_KEYS, WORKFLOW_AUTONOMY_ENABLED_DEFAULT, WORKFLOW_AUTONOMY_DEFAULTS, WORKFLOW_AUTONOMY_CEILINGS, WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_ENV, WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_CEILING, WORKFLOW_AUTONOMY_FORMS_DEFAULT, WORKFLOW_AUTONOMY_MIN_VALUE, 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, MODEL_ID_BYOK_PROVIDERS, MODEL_CLASS_REF_PREFIX, MODEL_SNAPSHOT_SUFFIX, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, AGENT_LOG_SOURCES, AGENT_LOG_ENVIRONMENTS, AGENT_LOG_FIELDS_MAX_WIRE_KEYS, LOG_DRAIN_TYPES_PHASE1, LOG_DRAIN_TYPES_PHASE2, LOG_DRAIN_TYPES_IMPLEMENTED, LOG_DRAIN_FORMATS, LOG_DRAIN_SEVERITIES, LOG_DRAIN_SOURCES, LOG_DRAIN_CONTENT_SOURCES, LOG_DRAIN_DEFAULT_SOURCES, LOG_DRAIN_MAX_PER_ORG, LOG_DRAIN_MAX_PER_ORG_ENTERPRISE, LOG_DRAIN_DATADOG_SITES, LOG_DRAIN_NEWRELIC_SITES, LOG_DRAIN_ENDPOINT_TEMPLATES, LOG_DRAIN_PRESET_SITES, LOG_DRAIN_BUCKET_NAME_PATTERN, LOG_DRAIN_BUCKET_HOST_PATTERNS, LOG_DRAIN_PRESET_HOST_SUFFIXES, DRAIN_CONTENT_ACK_ERROR_CODE, DRAIN_CONTENT_ACK_FIELD, DrainContentAckRequiredError, LOG_DRAIN_PRESET_PATHS, PRESET_SEGMENT_RE, LOG_DRAIN_QUOTAS, LOG_DRAIN_QUOTA_WARN_RATIO, LOG_DRAIN_QUOTA_DROP_DEBUG_RATIO, LOG_DRAIN_QUOTA_DROP_INFO_RATIO, LOG_DRAIN_QUOTA_PAUSE_RATIO, LOG_EXPORT_SOURCES, LOG_EXPORT_MAX_WINDOW_DAYS, LOG_EXPORT_MAX_WINDOW_MS, LOG_EXPORT_URL_TTL_SECONDS, LOG_EXPORT_FILE_RETENTION_DAYS, LOG_EXPORT_FILE_RETENTION_MS, LOG_EXPORT_PART_MAX_BYTES, LOG_DRAIN_NOTICE_RATE_LIMIT_MS, LOG_DRAIN_VERIFICATION_STALE_MS, LOG_DRAIN_DIGEST_INTERVAL_MS, LOG_DRAIN_DIGEST_MAX_ENTRIES, LOG_DRAIN_NOTICE_ERROR_MAX_CHARS, LOG_DRAIN_USAGE_LINE_ITEM, LOG_DRAIN_BYTES_PER_GIB, DEFAULT_LOG_DRAIN_PLAN_CONFIG, TIERS, LOG_CURSOR_MAX_LENGTH, LOG_CURSOR_MAX_ID_LENGTH, LOG_RELATIVE_TIME_PATTERN, LOG_ISO_TIME_PATTERN, RELATIVE_UNIT_MS, 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, EventType, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS, KEYS, MAX_BODY_BYTES, MAX_ID_LENGTH, UTC_ISO, 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, TYPED_API_KEY, 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_JOURNAL_PROTOCOL_VERSION, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_JOB_MODEL_SOURCE_LABELS, WORKFLOW_SUSPEND_KINDS, WORKFLOW_RUN_NOTIFICATION_SUSPENDED_KINDS, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, SCHEDULE_HEALTH_NOTIFY_CHANNELS, SCHEDULE_HEALTH_DEFAULT_NOTIFY, SCHEDULE_HEALTH_LIMITS, KNOWN_KEYS, 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, ONBOARDING_FLOW_KEY, ONBOARDING_SCHEMA_VERSION, id, copy, onboardingHeadingSchema, onboardingRichTextInlineSchema, onboardingRichTextSchema, onboardingDestinationSchema, onboardingArtworkSchema, onboardingAnswerSchema, onboardingQuestionSchema, onboardingTemplateSectionSchema, onboardingTemplateContentSchema, onboardingUnavailableOutcomeSchema, onboardingFlowSchema, onboardingActorSchema, onboardingEditorSchema, onboardingPublicationSummarySchema, onboardingValidationIssueSchema, onboardingValidationResponseSchema, onboardingAssetSchema, onboardingPublicAssetSchema, getOnboardingConfigResponseSchema, saveOnboardingDraftRequestSchema, validateOnboardingRequestSchema, publishOnboardingRequestSchema, rollbackOnboardingRequestSchema, onboardingTemplateCatalogItemSchema, getPublishedOnboardingResponseSchema, WEB_ROUTE_PROTOCOL_VERSION, WEB_ROUTE_METHODS, WEB_ROUTE_REQUEST_HEADER_ALLOWLIST, WEB_ROUTE_RESPONSE_HEADER_ALLOWLIST, WEB_ROUTE_MAX_REQUEST_BODY_BYTES, WEB_ROUTE_MAX_RESPONSE_BYTES, EVIDENCE_SESSION_IDLE_MS, EVIDENCE_MIN_CONVERSATIONS, EVIDENCE_LOW_CONFIDENCE_N, EVIDENCE_SNIPPET_MAX_CHARS, EVIDENCE_EXAMPLES_PER_ITEM, EVIDENCE_SHOWN_ITEMS, EVIDENCE_LATENCY_BOUNDS_MS, EVIDENCE_WORD_BOUNDS, BAD_CONVERSATION_REASONS, ATTACHMENT_LINES, REVIEW_VERDICT_REASON_ORDER;
3340
+ function envTemplatePlaceholder(key) {
3341
+ if (ENV_TEMPLATE_SECRET_KEY_RE.test(key)) {
3342
+ throw new Error(`env-template-secret-key: \`${key}\` looks like a secret \u2014 read it with env('${key}') inside execute instead`);
3343
+ }
3344
+ return {
3345
+ __envRef: key
3346
+ };
3347
+ }
3348
+ var __defProp2, __name2, PLUMBING_THREAD_CHANNELS, CHANNEL_CONVERSATION_CHANNELS, HIDDEN_THREAD_CHANNELS, PLATFORM_INVOCATION_CALLERS, SUPERVISION_OPS, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_STANDING_START_TOOLS, 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, LOG_FIELDS_MAX_KEYS, LOG_FIELD_MAX_VALUE_BYTES, LOG_FIELDS_MAX_BYTES, LOG_FIELD_KEY_PATTERN, LOG_FIELD_SECRET_SHAPED_KEY_PATTERNS, LOG_FIELDS_CLAMPED_KEY, LOG_FIELD_ARRAY_COUNT_SUFFIX, LuaLogFieldsError, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, 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_AGENT_EFFORTS, WORKFLOW_MODEL_CLASSES, WORKFLOW_TASK_CLASSES, WORKFLOW_MODEL_TRAITS, WORKFLOW_MODEL_REASON_MAX_LENGTH, WORKFLOW_MODELS_COMPOSE_MODES, WORKFLOW_MODELS_PIN_MODES, WORKFLOW_MODELS_FALLBACK_MODES, WORKFLOW_MODELS_CONSENT_ACTIONS_MIN, WORKFLOW_DEFAULT_TASK_CLASS_MAP, WORKFLOW_MODELS_MAX_CLASS_DEFAULT, WORKFLOW_AUTONOMY_FORMS, WORKFLOW_AUTONOMY_NUMERIC_KEYS, WORKFLOW_AUTONOMY_ENVELOPE_KEYS, WORKFLOW_AUTONOMY_ENABLED_DEFAULT, WORKFLOW_AUTONOMY_DEFAULTS, WORKFLOW_AUTONOMY_CEILINGS, WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_ENV, WORKFLOW_AUTONOMY_MAX_RUNS_PER_HOUR_CEILING, WORKFLOW_AUTONOMY_FORMS_DEFAULT, WORKFLOW_AUTONOMY_MIN_VALUE, 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, MODEL_ID_BYOK_PROVIDERS, MODEL_CLASS_REF_PREFIX, MODEL_SNAPSHOT_SUFFIX, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, AGENT_LOG_SOURCES, AGENT_LOG_ENVIRONMENTS, AGENT_LOG_FIELDS_MAX_WIRE_KEYS, LOG_DRAIN_TYPES_PHASE1, LOG_DRAIN_TYPES_PHASE2, LOG_DRAIN_TYPES_IMPLEMENTED, LOG_DRAIN_FORMATS, LOG_DRAIN_SEVERITIES, LOG_DRAIN_SOURCES, LOG_DRAIN_CONTENT_SOURCES, LOG_DRAIN_DEFAULT_SOURCES, LOG_DRAIN_MAX_PER_ORG, LOG_DRAIN_MAX_PER_ORG_ENTERPRISE, LOG_DRAIN_DATADOG_SITES, LOG_DRAIN_NEWRELIC_SITES, LOG_DRAIN_ENDPOINT_TEMPLATES, LOG_DRAIN_PRESET_SITES, LOG_DRAIN_BUCKET_NAME_PATTERN, LOG_DRAIN_BUCKET_HOST_PATTERNS, LOG_DRAIN_PRESET_HOST_SUFFIXES, DRAIN_CONTENT_ACK_ERROR_CODE, DRAIN_CONTENT_ACK_FIELD, DrainContentAckRequiredError, LOG_DRAIN_PRESET_PATHS, PRESET_SEGMENT_RE, LOG_DRAIN_QUOTAS, LOG_DRAIN_QUOTA_WARN_RATIO, LOG_DRAIN_QUOTA_DROP_DEBUG_RATIO, LOG_DRAIN_QUOTA_DROP_INFO_RATIO, LOG_DRAIN_QUOTA_PAUSE_RATIO, LOG_EXPORT_SOURCES, LOG_EXPORT_MAX_WINDOW_DAYS, LOG_EXPORT_MAX_WINDOW_MS, LOG_EXPORT_URL_TTL_SECONDS, LOG_EXPORT_FILE_RETENTION_DAYS, LOG_EXPORT_FILE_RETENTION_MS, LOG_EXPORT_PART_MAX_BYTES, LOG_DRAIN_NOTICE_RATE_LIMIT_MS, LOG_DRAIN_VERIFICATION_STALE_MS, LOG_DRAIN_DIGEST_INTERVAL_MS, LOG_DRAIN_DIGEST_MAX_ENTRIES, LOG_DRAIN_NOTICE_ERROR_MAX_CHARS, LOG_DRAIN_USAGE_LINE_ITEM, LOG_DRAIN_BYTES_PER_GIB, DEFAULT_LOG_DRAIN_PLAN_CONFIG, TIERS, LOG_CURSOR_MAX_LENGTH, LOG_CURSOR_MAX_ID_LENGTH, LOG_RELATIVE_TIME_PATTERN, LOG_ISO_TIME_PATTERN, RELATIVE_UNIT_MS, 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, EventType, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS, KEYS, MAX_BODY_BYTES, MAX_ID_LENGTH, UTC_ISO, 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, TYPED_API_KEY, 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_JOURNAL_PROTOCOL_VERSION, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_JOB_MODEL_SOURCE_LABELS, WORKFLOW_SUSPEND_KINDS, WORKFLOW_RUN_NOTIFICATION_SUSPENDED_KINDS, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, SCHEDULE_HEALTH_NOTIFY_CHANNELS, SCHEDULE_HEALTH_DEFAULT_NOTIFY, SCHEDULE_HEALTH_LIMITS, KNOWN_KEYS, 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, ONBOARDING_FLOW_KEY, ONBOARDING_SCHEMA_VERSION, id, copy, onboardingHeadingSchema, onboardingRichTextInlineSchema, onboardingRichTextSchema, onboardingDestinationSchema, onboardingArtworkSchema, onboardingAnswerSchema, onboardingQuestionSchema, onboardingTemplateSectionSchema, onboardingTemplateContentSchema, onboardingUnavailableOutcomeSchema, onboardingFlowSchema, onboardingActorSchema, onboardingEditorSchema, onboardingPublicationSummarySchema, onboardingValidationIssueSchema, onboardingValidationResponseSchema, onboardingAssetSchema, onboardingPublicAssetSchema, getOnboardingConfigResponseSchema, saveOnboardingDraftRequestSchema, validateOnboardingRequestSchema, publishOnboardingRequestSchema, rollbackOnboardingRequestSchema, onboardingTemplateCatalogItemSchema, getPublishedOnboardingResponseSchema, WEB_ROUTE_PROTOCOL_VERSION, WEB_ROUTE_METHODS, WEB_ROUTE_REQUEST_HEADER_ALLOWLIST, WEB_ROUTE_RESPONSE_HEADER_ALLOWLIST, WEB_ROUTE_MAX_REQUEST_BODY_BYTES, WEB_ROUTE_MAX_RESPONSE_BYTES, EVIDENCE_SESSION_IDLE_MS, EVIDENCE_MIN_CONVERSATIONS, EVIDENCE_LOW_CONFIDENCE_N, EVIDENCE_SNIPPET_MAX_CHARS, EVIDENCE_EXAMPLES_PER_ITEM, EVIDENCE_SHOWN_ITEMS, EVIDENCE_LATENCY_BOUNDS_MS, EVIDENCE_WORD_BOUNDS, BAD_CONVERSATION_REASONS, ATTACHMENT_LINES, REVIEW_VERDICT_REASON_ORDER, ENV_TEMPLATE_SECRET_KEY_RE;
3341
3349
  var init_dist = __esm({
3342
3350
  "../shared-types/dist/index.mjs"() {
3343
3351
  "use strict";
@@ -6046,6 +6054,9 @@ listed here; never invent a target.`;
6046
6054
  ];
6047
6055
  __name(sortVerdictReasons, "sortVerdictReasons");
6048
6056
  __name2(sortVerdictReasons, "sortVerdictReasons");
6057
+ ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
6058
+ __name(envTemplatePlaceholder, "envTemplatePlaceholder");
6059
+ __name2(envTemplatePlaceholder, "envTemplatePlaceholder");
6049
6060
  }
6050
6061
  });
6051
6062
 
@@ -6675,16 +6686,110 @@ function workflowJobPluginsProblem(plugins) {
6675
6686
  if (new Set(plugins).size !== plugins.length) return "plugins must not repeat";
6676
6687
  return null;
6677
6688
  }
6678
- function workflowJobTargetProblem(target, plugins) {
6689
+ function workflowJobTargetTemplatePath(binding) {
6690
+ if (!binding || typeof binding !== "object" || Array.isArray(binding)) return null;
6691
+ const keys = Object.keys(binding);
6692
+ const tpl = binding.template;
6693
+ if (keys.length !== 1 || typeof tpl !== "string" || tpl.length > 512) return null;
6694
+ const m = WORKFLOW_JOB_TARGET_TEMPLATE_RE.exec(tpl.trim());
6695
+ if (!m) return null;
6696
+ const names = m[1].split(".").map((seg) => seg.replace(/\[(?:0|[1-9]\d*)\]/g, ""));
6697
+ if (names.some((n2) => n2 === "__proto__" || n2 === "prototype" || n2 === "constructor")) return null;
6698
+ return m[1].split(".").every((seg) => TARGET_PATH_SEGMENT_RE.test(seg)) ? m[1] : null;
6699
+ }
6700
+ function isWorkflowJobTargetTemplate(target) {
6701
+ const agentId = target?.agentId;
6702
+ return !!agentId && typeof agentId === "object";
6703
+ }
6704
+ function workflowJobLuaApiProblem(luaApi, nodeType, tier) {
6705
+ if (luaApi === void 0) return null;
6706
+ if (luaApi !== true) return "`luaApi` must be exactly true";
6707
+ if (nodeType !== "code") return "`luaApi` is legal on code steps only (an agent step uses `plugins`)";
6708
+ if (tier !== "job") return "`luaApi` requires tier:'job'";
6709
+ return null;
6710
+ }
6711
+ function workflowJobUsesLuaApi(step3) {
6712
+ return Array.isArray(step3.plugins) && step3.plugins.length > 0 || step3.kind === "code" && step3.luaApi === true;
6713
+ }
6714
+ function workflowJobTargetProblem(target, plugins, luaApi) {
6679
6715
  if (target === void 0) return null;
6680
6716
  if (!target || typeof target !== "object" || Array.isArray(target)) return "target must be { agentId }";
6681
6717
  const keys = Object.keys(target);
6682
6718
  const agentId = target.agentId;
6683
- if (keys.length !== 1 || typeof agentId !== "string" || !agentId.trim() || agentId.length > 256) return "target must be exactly { agentId: <non-empty string> }";
6684
- if (!Array.isArray(plugins) || plugins.length === 0) return "`target` is legal only beside `plugins`";
6719
+ if (keys.length !== 1 || !("agentId" in target)) return "target must be exactly { agentId }";
6720
+ if (typeof agentId === "string") {
6721
+ if (!agentId.trim() || agentId.length > 256) return "target must be exactly { agentId: <non-empty string> }";
6722
+ if (agentId.includes("${")) return "a run-input target is written template('${initData.<path>}'), never a string with ${\u2026}";
6723
+ } else if (workflowJobTargetTemplatePath(agentId) === null) {
6724
+ return "target.agentId must be a static id or template('${initData.<path>}') \u2014 exactly one initData placeholder, no default";
6725
+ }
6726
+ const hasPlugins = Array.isArray(plugins) && plugins.length > 0;
6727
+ if (!hasPlugins && luaApi !== true) return "`target` is legal only beside `plugins` or `luaApi: true`";
6685
6728
  return null;
6686
6729
  }
6687
- var __defProp3, __name3, WORKFLOW_JOB_TOOLS, WORKFLOW_JOB_READ_ONLY_DROPPED, WORKFLOW_JOB_DEFAULT_TOOLS, WORKFLOW_JOB_PLUGINS, WORKFLOW_JOB_PLUGIN_ROOT, WORKFLOW_JOB_PLUGINS_MAX;
6730
+ function readInitDataPath(root, path27) {
6731
+ let cur = root;
6732
+ for (const seg of path27.split(".")) {
6733
+ const name = seg.replace(/\[(?:0|[1-9]\d*)\]/g, "");
6734
+ const indexes = [
6735
+ ...seg.matchAll(/\[(0|[1-9]\d*)\]/g)
6736
+ ].map((x) => Number(x[1]));
6737
+ if (cur === null || typeof cur !== "object" || !Object.prototype.hasOwnProperty.call(cur, name)) return void 0;
6738
+ cur = cur[name];
6739
+ for (const i of indexes) {
6740
+ if (!Array.isArray(cur) || i >= cur.length) return void 0;
6741
+ cur = cur[i];
6742
+ }
6743
+ }
6744
+ return cur;
6745
+ }
6746
+ function renderWorkflowJobTarget(target, initData) {
6747
+ const agentId = target?.agentId;
6748
+ if (target === void 0 || target === null || agentId === void 0) return {
6749
+ ok: true,
6750
+ agentId: void 0,
6751
+ templated: false
6752
+ };
6753
+ if (typeof agentId === "string") {
6754
+ if (!agentId.trim() || agentId.includes("${")) return {
6755
+ ok: false,
6756
+ reason: "invalid",
6757
+ message: "target.agentId is invalid"
6758
+ };
6759
+ return {
6760
+ ok: true,
6761
+ agentId,
6762
+ templated: false
6763
+ };
6764
+ }
6765
+ const path27 = workflowJobTargetTemplatePath(agentId);
6766
+ if (path27 === null) return {
6767
+ ok: false,
6768
+ reason: "invalid",
6769
+ message: "target.agentId is not a valid initData template"
6770
+ };
6771
+ const value3 = readInitDataPath(initData, path27);
6772
+ if (value3 === void 0 || value3 === null) {
6773
+ return {
6774
+ ok: false,
6775
+ reason: "unbound",
6776
+ message: `target_unresolved: the run input has no initData.${path27}`
6777
+ };
6778
+ }
6779
+ if (typeof value3 !== "string" || !value3.trim() || value3.length > 256 || /\s/.test(value3.trim())) {
6780
+ return {
6781
+ ok: false,
6782
+ reason: "empty",
6783
+ message: `target_unresolved: initData.${path27} is not a non-empty agent id`
6784
+ };
6785
+ }
6786
+ return {
6787
+ ok: true,
6788
+ agentId: value3.trim(),
6789
+ templated: true
6790
+ };
6791
+ }
6792
+ var __defProp3, __name3, WORKFLOW_JOB_TOOLS, WORKFLOW_JOB_READ_ONLY_DROPPED, WORKFLOW_JOB_DEFAULT_TOOLS, WORKFLOW_JOB_PLUGINS, WORKFLOW_JOB_PLUGIN_ROOT, WORKFLOW_JOB_PLUGINS_MAX, WORKFLOW_JOB_TARGET_TEMPLATE_RE, TARGET_PATH_SEGMENT_RE;
6688
6793
  var init_workflow_job_tools = __esm({
6689
6794
  "../shared-types/dist/workflow-job-tools.mjs"() {
6690
6795
  "use strict";
@@ -6730,8 +6835,22 @@ var init_workflow_job_tools = __esm({
6730
6835
  __name3(workflowJobPluginDir, "workflowJobPluginDir");
6731
6836
  __name(workflowJobPluginsProblem, "workflowJobPluginsProblem");
6732
6837
  __name3(workflowJobPluginsProblem, "workflowJobPluginsProblem");
6838
+ WORKFLOW_JOB_TARGET_TEMPLATE_RE = /^\$\{\s*initData\.([A-Za-z0-9_.\-[\]]+)\s*\}$/;
6839
+ TARGET_PATH_SEGMENT_RE = /^[A-Za-z0-9_-]+(?:\[(?:0|[1-9]\d*)\])*$/;
6840
+ __name(workflowJobTargetTemplatePath, "workflowJobTargetTemplatePath");
6841
+ __name3(workflowJobTargetTemplatePath, "workflowJobTargetTemplatePath");
6842
+ __name(isWorkflowJobTargetTemplate, "isWorkflowJobTargetTemplate");
6843
+ __name3(isWorkflowJobTargetTemplate, "isWorkflowJobTargetTemplate");
6844
+ __name(workflowJobLuaApiProblem, "workflowJobLuaApiProblem");
6845
+ __name3(workflowJobLuaApiProblem, "workflowJobLuaApiProblem");
6846
+ __name(workflowJobUsesLuaApi, "workflowJobUsesLuaApi");
6847
+ __name3(workflowJobUsesLuaApi, "workflowJobUsesLuaApi");
6733
6848
  __name(workflowJobTargetProblem, "workflowJobTargetProblem");
6734
6849
  __name3(workflowJobTargetProblem, "workflowJobTargetProblem");
6850
+ __name(readInitDataPath, "readInitDataPath");
6851
+ __name3(readInitDataPath, "readInitDataPath");
6852
+ __name(renderWorkflowJobTarget, "renderWorkflowJobTarget");
6853
+ __name3(renderWorkflowJobTarget, "renderWorkflowJobTarget");
6735
6854
  }
6736
6855
  });
6737
6856
 
@@ -6769,13 +6888,13 @@ function parseTemplatePlaceholder(rawExpr) {
6769
6888
  rest: dot === -1 ? "" : rawExpr.slice(dot + 1)
6770
6889
  };
6771
6890
  }
6772
- function traverseMappingPath(root, path26, errorLabel2) {
6773
- if (path26 === "" || path26 === ".") return root;
6774
- const parts = path26.split(".");
6891
+ function traverseMappingPath(root, path27, errorLabel2) {
6892
+ if (path27 === "" || path27 === ".") return root;
6893
+ const parts = path27.split(".");
6775
6894
  let value22 = root;
6776
6895
  for (const part of parts) {
6777
6896
  if (typeof value22 === "object" && value22 !== null) value22 = value22[part];
6778
- else throw new WorkflowTemplateError(`Invalid path ${path26} in ${errorLabel2}`, path26);
6897
+ else throw new WorkflowTemplateError(`Invalid path ${path27} in ${errorLabel2}`, path27);
6779
6898
  }
6780
6899
  return value22;
6781
6900
  }
@@ -6960,11 +7079,11 @@ function parseModelTemplate(model) {
6960
7079
  message: modelTemplateInvalidMessage(model, why)
6961
7080
  };
6962
7081
  }
6963
- const path26 = m[1];
6964
- if (!path26.split(".").every((seg) => PATH_SEGMENT_RE.test(seg))) {
7082
+ const path27 = m[1];
7083
+ if (!path27.split(".").every((seg) => PATH_SEGMENT_RE.test(seg))) {
6965
7084
  return {
6966
7085
  kind: "invalid",
6967
- message: modelTemplateInvalidMessage(model, `the path \`${path26}\` is not a dotted path of names and canonical [n] indexes`)
7086
+ message: modelTemplateInvalidMessage(model, `the path \`${path27}\` is not a dotted path of names and canonical [n] indexes`)
6968
7087
  };
6969
7088
  }
6970
7089
  if (m[2] !== void 0) {
@@ -6983,7 +7102,7 @@ function parseModelTemplate(model) {
6983
7102
  kind: "template",
6984
7103
  template: {
6985
7104
  placeholder: trimmed2,
6986
- path: path26,
7105
+ path: path27,
6987
7106
  default: dflt
6988
7107
  }
6989
7108
  };
@@ -6992,7 +7111,7 @@ function parseModelTemplate(model) {
6992
7111
  kind: "template",
6993
7112
  template: {
6994
7113
  placeholder: trimmed2,
6995
- path: path26
7114
+ path: path27
6996
7115
  }
6997
7116
  };
6998
7117
  }
@@ -7009,9 +7128,9 @@ function staticModelPin(model) {
7009
7128
  if (parsed.kind === "template") return parsed.template.default;
7010
7129
  return void 0;
7011
7130
  }
7012
- function readPath(root, path26) {
7131
+ function readPath(root, path27) {
7013
7132
  let cur = root;
7014
- for (const seg of path26.split(".")) {
7133
+ for (const seg of path27.split(".")) {
7015
7134
  const name = seg.replace(/\[(?:0|[1-9]\d*)\]/g, "");
7016
7135
  const indexes = [
7017
7136
  ...seg.matchAll(/\[(0|[1-9]\d*)\]/g)
@@ -7046,17 +7165,17 @@ function renderModelTemplate(model, initData) {
7046
7165
  model,
7047
7166
  source: "static"
7048
7167
  };
7049
- const { placeholder, path: path26 } = parsed.template;
7168
+ const { placeholder, path: path27 } = parsed.template;
7050
7169
  if (initData !== void 0 && initData !== null && (typeof initData !== "object" || Array.isArray(initData))) {
7051
7170
  return {
7052
7171
  ok: false,
7053
7172
  placeholder,
7054
- path: path26,
7173
+ path: path27,
7055
7174
  reason: "input-not-object",
7056
7175
  message: modelTemplateInputNotObjectMessage(placeholder, initData)
7057
7176
  };
7058
7177
  }
7059
- const value22 = readPath(initData, path26);
7178
+ const value22 = readPath(initData, path27);
7060
7179
  const reason = value22 === void 0 || value22 === null ? "unbound" : typeof value22 !== "string" ? "not-a-string" : value22.trim() ? null : "empty";
7061
7180
  if (reason === null) return {
7062
7181
  ok: true,
@@ -7071,14 +7190,14 @@ function renderModelTemplate(model, initData) {
7071
7190
  return {
7072
7191
  ok: false,
7073
7192
  placeholder,
7074
- path: path26,
7193
+ path: path27,
7075
7194
  reason,
7076
- message: modelTemplateUnboundMessage(placeholder, path26, reason)
7195
+ message: modelTemplateUnboundMessage(placeholder, path27, reason)
7077
7196
  };
7078
7197
  }
7079
- function modelTemplateUnboundMessage(placeholder, path26, reason) {
7080
- const what = reason === "unbound" ? `the run input has no ${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path26}` : reason === "empty" ? `${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path26} is empty on the run input` : `${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path26} on the run input is not a string`;
7081
- return `model placeholder "${placeholder}" is unbound \u2014 ${what} and the placeholder declares no default; pass one in the run input or write \${${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path26}|<provider/model>}`;
7198
+ function modelTemplateUnboundMessage(placeholder, path27, reason) {
7199
+ const what = reason === "unbound" ? `the run input has no ${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path27}` : reason === "empty" ? `${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path27} is empty on the run input` : `${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path27} on the run input is not a string`;
7200
+ return `model placeholder "${placeholder}" is unbound \u2014 ${what} and the placeholder declares no default; pass one in the run input or write \${${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path27}|<provider/model>}`;
7082
7201
  }
7083
7202
  function modelTemplateInputNotObjectMessage(placeholder, initData) {
7084
7203
  const type = Array.isArray(initData) ? "an array" : `a ${typeof initData}`;
@@ -7118,22 +7237,22 @@ function validateApproverBlock(node, opts = {
7118
7237
  path: "approval"
7119
7238
  }) {
7120
7239
  const issues = [];
7121
- const push = /* @__PURE__ */ __name4((code, path26, message, severity = "error") => issues.push({
7240
+ const push = /* @__PURE__ */ __name4((code, path27, message, severity = "error") => issues.push({
7122
7241
  code,
7123
- path: path26,
7242
+ path: path27,
7124
7243
  severity,
7125
7244
  message
7126
7245
  }), "push");
7127
- const checkSpec = /* @__PURE__ */ __name4((spec, path26) => {
7246
+ const checkSpec = /* @__PURE__ */ __name4((spec, path27) => {
7128
7247
  const r = ApproverSpecSchema.safeParse(spec);
7129
7248
  if (!r.success) {
7130
7249
  const users = spec?.users;
7131
- if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path26, `at most ${APPROVER_SPEC_MAX_USERS} users`);
7250
+ if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path27, `at most ${APPROVER_SPEC_MAX_USERS} users`);
7132
7251
  else {
7133
7252
  const refusal2 = describeApproverSpecRefusal(spec);
7134
7253
  issues.push({
7135
7254
  code: "approver-invalid",
7136
- path: path26,
7255
+ path: path27,
7137
7256
  severity: "error",
7138
7257
  message: refusal2.message,
7139
7258
  repair: {
@@ -7146,12 +7265,12 @@ function validateApproverBlock(node, opts = {
7146
7265
  }
7147
7266
  const s = r.data;
7148
7267
  if (typeof s === "object") {
7149
- if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path26, "governance reviewer routing is not enabled for this deployment");
7150
- if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path26, "IdP-group approvers are not enabled for this deployment");
7268
+ if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path27, "governance reviewer routing is not enabled for this deployment");
7269
+ if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path27, "IdP-group approvers are not enabled for this deployment");
7151
7270
  const binding = "users" in s ? s.users : "role" in s ? s.role : "group" in s ? s.group : void 0;
7152
7271
  if (isTemplateBinding(binding)) {
7153
- if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path26}.template`, "binding root must be initData / stepResults / requestContext / state");
7154
- if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path26}.users`, "a customer-reachable workflow may not bind its approver list");
7272
+ if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path27}.template`, "binding root must be initData / stepResults / requestContext / state");
7273
+ if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path27}.users`, "a customer-reachable workflow may not bind its approver list");
7155
7274
  }
7156
7275
  }
7157
7276
  }, "checkSpec");
@@ -7207,6 +7326,15 @@ function liftRenderedApprover(row2, rendered) {
7207
7326
  group: text
7208
7327
  };
7209
7328
  }
7329
+ function approverUsersOf(users) {
7330
+ if (Array.isArray(users)) {
7331
+ if (users.length === 0 || users.length > APPROVER_SPEC_MAX_USERS) return null;
7332
+ return users.every((m) => typeof m === "string" && m.length > 0 && m.length <= 128) ? users : null;
7333
+ }
7334
+ if (typeof users !== "string") return null;
7335
+ const lifted = liftRenderedApprover("users", users);
7336
+ return lifted && "users" in lifted ? lifted.users : null;
7337
+ }
7210
7338
  function workspaceTemplatePath(template22) {
7211
7339
  const key = template22.trim();
7212
7340
  const expr = WORKSPACE_TEMPLATE_EXPR_RE.exec(key);
@@ -7327,8 +7455,8 @@ function withDefaultsFilled(g) {
7327
7455
  function isConnectionKeyShaped(value22) {
7328
7456
  return WORKFLOW_CONNECTION_KEY_RE.test(value22) && !CONNECTION_ID_HEX_RE.test(value22);
7329
7457
  }
7330
- function connectionKeyUndeclaredMessage(path26, key) {
7331
- return `${path26} '${key}' is neither a connection id nor a declared connections[].key \u2014 declare it: connections: [{ key: '${key}', integrationType: '<catalog slug, e.g. github>' }] and it resolves on any agent`;
7458
+ function connectionKeyUndeclaredMessage(path27, key) {
7459
+ return `${path27} '${key}' is neither a connection id nor a declared connections[].key \u2014 declare it: connections: [{ key: '${key}', integrationType: '<catalog slug, e.g. github>' }] and it resolves on any agent`;
7332
7460
  }
7333
7461
  function classifyModelProvider(model) {
7334
7462
  const m = (model ?? "").trim().toLowerCase();
@@ -7338,10 +7466,10 @@ function classifyModelProvider(model) {
7338
7466
  if (/^(google\/|gemini)/.test(m)) return "google";
7339
7467
  return null;
7340
7468
  }
7341
- function schemaAtPath(schema, path26) {
7469
+ function schemaAtPath(schema, path27) {
7342
7470
  let cur = schema;
7343
7471
  if (!cur || typeof cur !== "object") return void 0;
7344
- for (const seg of path26.split(".").filter(Boolean)) {
7472
+ for (const seg of path27.split(".").filter(Boolean)) {
7345
7473
  const props = cur.properties;
7346
7474
  const next = props?.[seg];
7347
7475
  if (!next || typeof next !== "object") return void 0;
@@ -7408,21 +7536,21 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7408
7536
  static: true
7409
7537
  }) {
7410
7538
  const issues = [];
7411
- const err = /* @__PURE__ */ __name4((code, message, path26, stepId) => {
7539
+ const err = /* @__PURE__ */ __name4((code, message, path27, stepId) => {
7412
7540
  issues.push({
7413
7541
  code,
7414
7542
  message,
7415
7543
  severity: "error",
7416
- path: path26,
7544
+ path: path27,
7417
7545
  stepId
7418
7546
  });
7419
7547
  }, "err");
7420
- const warn = /* @__PURE__ */ __name4((code, message, path26, stepId) => {
7548
+ const warn = /* @__PURE__ */ __name4((code, message, path27, stepId) => {
7421
7549
  issues.push({
7422
7550
  code,
7423
7551
  message,
7424
7552
  severity: "warning",
7425
- path: path26,
7553
+ path: path27,
7426
7554
  stepId
7427
7555
  });
7428
7556
  }, "warn");
@@ -7458,19 +7586,19 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7458
7586
  err("connection-declaration-invalid", "`connections` must be an array of { key, integrationType }", "connections");
7459
7587
  }
7460
7588
  (Array.isArray(g.connections) ? g.connections : []).forEach((c, i) => {
7461
- const path26 = `connections.${i}`;
7589
+ const path27 = `connections.${i}`;
7462
7590
  const key = c?.key;
7463
7591
  const integrationType = c?.integrationType;
7464
7592
  if (typeof key !== "string" || !WORKFLOW_CONNECTION_KEY_RE.test(key)) {
7465
- err("connection-declaration-invalid", `connections[${i}].key must match ${WORKFLOW_CONNECTION_KEY_RE}`, `${path26}.key`);
7593
+ err("connection-declaration-invalid", `connections[${i}].key must match ${WORKFLOW_CONNECTION_KEY_RE}`, `${path27}.key`);
7466
7594
  return;
7467
7595
  }
7468
7596
  if (ownKeys.has(key)) {
7469
- err("connection-declaration-invalid", `connections[${i}].key "${key}" is declared twice`, `${path26}.key`);
7597
+ err("connection-declaration-invalid", `connections[${i}].key "${key}" is declared twice`, `${path27}.key`);
7470
7598
  return;
7471
7599
  }
7472
7600
  if (typeof integrationType !== "string" || !integrationType.trim()) {
7473
- err("connection-declaration-invalid", `connections[${i}] ("${key}") needs an integrationType (the catalog slug, e.g. 'github')`, `${path26}.integrationType`);
7601
+ err("connection-declaration-invalid", `connections[${i}] ("${key}") needs an integrationType (the catalog slug, e.g. 'github')`, `${path27}.integrationType`);
7474
7602
  return;
7475
7603
  }
7476
7604
  ownKeys.add(key);
@@ -7484,112 +7612,112 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7484
7612
  const seen = /* @__PURE__ */ new Map();
7485
7613
  let nodeCount = 0;
7486
7614
  const upstream = /* @__PURE__ */ new Set();
7487
- const checkId = /* @__PURE__ */ __name4((id2, path26) => {
7615
+ const checkId = /* @__PURE__ */ __name4((id2, path27) => {
7488
7616
  nodeCount += 1;
7489
7617
  if (seen.has(id2)) {
7490
- err("duplicate-step-id", `step id "${id2}" is declared twice (first at ${seen.get(id2)})`, path26, id2);
7618
+ err("duplicate-step-id", `step id "${id2}" is declared twice (first at ${seen.get(id2)})`, path27, id2);
7491
7619
  } else {
7492
- seen.set(id2, path26);
7620
+ seen.set(id2, path27);
7493
7621
  }
7494
7622
  }, "checkId");
7495
- const checkPolicyEnums = /* @__PURE__ */ __name4((node, path26) => {
7623
+ const checkPolicyEnums = /* @__PURE__ */ __name4((node, path27) => {
7496
7624
  const id2 = singleId(node);
7497
7625
  const check = /* @__PURE__ */ __name4((member, allowed) => {
7498
7626
  const value22 = node[member];
7499
7627
  if (value22 === void 0 || typeof value22 === "string" && allowed.includes(value22)) return;
7500
- err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path26}.${member}`, id2);
7628
+ err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path27}.${member}`, id2);
7501
7629
  }, "check");
7502
7630
  check("sideEffects", WORKFLOW_SIDE_EFFECTS);
7503
7631
  check("jobResources", WORKFLOW_JOB_RESOURCES);
7504
7632
  }, "checkPolicyEnums");
7505
- const checkRetry = /* @__PURE__ */ __name4((node, path26) => {
7633
+ const checkRetry = /* @__PURE__ */ __name4((node, path27) => {
7506
7634
  const r = node.retry;
7507
7635
  if (!r) return;
7508
7636
  const id2 = singleId(node);
7509
7637
  const unknown = unknownWorkflowRetryMembers(r);
7510
- if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path26}.retry`, id2);
7638
+ if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path27}.retry`, id2);
7511
7639
  if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
7512
7640
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
7513
- err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path26}.retry.maxAttempts`, id2);
7641
+ err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path27}.retry.maxAttempts`, id2);
7514
7642
  }
7515
7643
  const backoffs = retryBackoffs();
7516
7644
  if (r.backoff !== void 0 && !backoffs.includes(r.backoff)) {
7517
7645
  const list = backoffs.map((b) => `'${b}'`).join(" | ");
7518
- err("backoff-invalid", `retry.backoff must be ${list}`, `${path26}.retry.backoff`, id2);
7646
+ err("backoff-invalid", `retry.backoff must be ${list}`, `${path27}.retry.backoff`, id2);
7519
7647
  }
7520
7648
  if (r.backoffSeconds !== void 0 && r.backoffSeconds < 0) {
7521
- err("backoff-invalid", "retry.backoffSeconds must be \u2265 0", `${path26}.retry.backoffSeconds`, id2);
7649
+ err("backoff-invalid", "retry.backoffSeconds must be \u2265 0", `${path27}.retry.backoffSeconds`, id2);
7522
7650
  }
7523
7651
  if (r.maxBackoffSeconds !== void 0) {
7524
7652
  if (r.backoff !== "exponential") {
7525
- err("backoff-invalid", "retry.maxBackoffSeconds is only meaningful with backoff:'exponential'", `${path26}.retry`, id2);
7653
+ err("backoff-invalid", "retry.maxBackoffSeconds is only meaningful with backoff:'exponential'", `${path27}.retry`, id2);
7526
7654
  } else if (r.maxBackoffSeconds <= 0 || r.backoffSeconds !== void 0 && r.maxBackoffSeconds < r.backoffSeconds) {
7527
- err("backoff-invalid", "retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds", `${path26}.retry.maxBackoffSeconds`, id2);
7655
+ err("backoff-invalid", "retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds", `${path27}.retry.maxBackoffSeconds`, id2);
7528
7656
  }
7529
7657
  }
7530
7658
  }, "checkRetry");
7531
- const checkTimeout = /* @__PURE__ */ __name4((node, path26) => {
7659
+ const checkTimeout = /* @__PURE__ */ __name4((node, path27) => {
7532
7660
  const t = node.timeoutSeconds;
7533
7661
  if (t === void 0) return;
7534
7662
  const id2 = singleId(node);
7535
7663
  if (!Number.isInteger(t) || t < 1) {
7536
- err("timeout-out-of-range", `timeoutSeconds must be an integer \u2265 1 (got ${t})`, `${path26}.timeoutSeconds`, id2);
7664
+ err("timeout-out-of-range", `timeoutSeconds must be an integer \u2265 1 (got ${t})`, `${path27}.timeoutSeconds`, id2);
7537
7665
  return;
7538
7666
  }
7539
7667
  if (node.tier === "job") {
7540
7668
  const cap = node.type === "agent" ? caps.maxJobTimeoutSeconds : caps.maxJobSegmentSeconds;
7541
7669
  if (t > cap) {
7542
- err("job-timeout-exceeds-cap", `timeoutSeconds ${t} exceeds the Job-tier cap of ${cap} s`, `${path26}.timeoutSeconds`, id2);
7670
+ err("job-timeout-exceeds-cap", `timeoutSeconds ${t} exceeds the Job-tier cap of ${cap} s`, `${path27}.timeoutSeconds`, id2);
7543
7671
  } else if (node.type === "agent" && t > caps.maxJobSegmentSeconds && !node.workspace) {
7544
- err("long-job-requires-workspace", `steps longer than 4 h checkpoint to the run workspace \u2014 add workspace:{mount:'rw'} (and workspace on createWorkflow) or split the step`, `${path26}.timeoutSeconds`, id2);
7672
+ err("long-job-requires-workspace", `steps longer than 4 h checkpoint to the run workspace \u2014 add workspace:{mount:'rw'} (and workspace on createWorkflow) or split the step`, `${path27}.timeoutSeconds`, id2);
7545
7673
  }
7546
7674
  } else if (t > caps.maxWorkerTimeoutSeconds) {
7547
- 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)`, `${path26}.timeoutSeconds`, id2);
7675
+ 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)`, `${path27}.timeoutSeconds`, id2);
7548
7676
  }
7549
7677
  }, "checkTimeout");
7550
- const checkSpecialistRole = /* @__PURE__ */ __name4((node, path26) => {
7678
+ const checkSpecialistRole = /* @__PURE__ */ __name4((node, path27) => {
7551
7679
  const role = node.role;
7552
7680
  const hasRef = typeof role.ref === "string";
7553
7681
  const hasInline = role.name !== void 0 || role.instructions !== void 0 || Array.isArray(role.tools) && role.tools.length > 0;
7554
7682
  if (hasRef && hasInline) {
7555
- err("role-ref-and-inline", "a role is either `{ref}` or inline `{name, instructions, tools}`, never both", `${path26}.role`, node.id);
7683
+ err("role-ref-and-inline", "a role is either `{ref}` or inline `{name, instructions, tools}`, never both", `${path27}.role`, node.id);
7556
7684
  }
7557
7685
  if (node.agentId !== "$self") {
7558
- err("ephemeral-base-not-self", "a role runs on the owner only: use '$self'", `${path26}.agentId`, node.id);
7686
+ err("ephemeral-base-not-self", "a role runs on the owner only: use '$self'", `${path27}.agentId`, node.id);
7559
7687
  }
7560
7688
  if (opts.policy && opts.policy.ephemeralSpecialists !== true) {
7561
- err("ephemeral-specialists-disabled", "ephemeral specialists are off for this org/agent (workflowPolicy.ephemeralSpecialists)", `${path26}.role`, node.id);
7689
+ err("ephemeral-specialists-disabled", "ephemeral specialists are off for this org/agent (workflowPolicy.ephemeralSpecialists)", `${path27}.role`, node.id);
7562
7690
  }
7563
7691
  let tools = Array.isArray(role.tools) ? role.tools.filter((t) => typeof t === "string") : [];
7564
7692
  if (hasRef && opts.roleLibrary) {
7565
7693
  const saved = opts.roleLibrary.get(role.ref);
7566
7694
  if (!saved) {
7567
- err("role-ref-unknown", `no saved role \`${role.ref}\` in the owner's library`, `${path26}.role.ref`, node.id);
7695
+ err("role-ref-unknown", `no saved role \`${role.ref}\` in the owner's library`, `${path27}.role.ref`, node.id);
7568
7696
  } else {
7569
7697
  tools = saved.tools ?? [];
7570
7698
  if (typeof role.roleHash === "string" && saved.roleHash && role.roleHash !== saved.roleHash) {
7571
- warn("role-ref-stale", `saved role \`${role.ref}\` changed since this version was frozen`, `${path26}.role.ref`, node.id);
7699
+ warn("role-ref-stale", `saved role \`${role.ref}\` changed since this version was frozen`, `${path27}.role.ref`, node.id);
7572
7700
  }
7573
7701
  }
7574
7702
  }
7575
7703
  if (tools.length && opts.toolCatalog) {
7576
7704
  const missing = tools.filter((t) => !opts.toolCatalog.has(t));
7577
7705
  if (missing.length) {
7578
- err("ephemeral-tools-not-subset", `role tools not in the owner's catalog: ${missing.join(", ")}`, `${path26}.role.tools`, node.id);
7706
+ err("ephemeral-tools-not-subset", `role tools not in the owner's catalog: ${missing.join(", ")}`, `${path27}.role.tools`, node.id);
7579
7707
  }
7580
7708
  }
7581
7709
  }, "checkSpecialistRole");
7582
- const checkRequiredConnections = /* @__PURE__ */ __name4((node, path26) => {
7710
+ const checkRequiredConnections = /* @__PURE__ */ __name4((node, path27) => {
7583
7711
  const required = node.requiredConnections;
7584
7712
  if (!Array.isArray(required)) return;
7585
7713
  const undeclared = required.filter(undeclaredKey);
7586
7714
  if (undeclared.length) {
7587
- err("connection-key-undeclared", connectionKeyUndeclaredMessage(`${path26}.requiredConnections`, undeclared[0]) + (undeclared.length > 1 ? ` (also undeclared: ${JSON.stringify(undeclared.slice(1))})` : ""), `${path26}.requiredConnections`, singleId(node));
7715
+ err("connection-key-undeclared", connectionKeyUndeclaredMessage(`${path27}.requiredConnections`, undeclared[0]) + (undeclared.length > 1 ? ` (also undeclared: ${JSON.stringify(undeclared.slice(1))})` : ""), `${path27}.requiredConnections`, singleId(node));
7588
7716
  }
7589
7717
  if (!opts.connectionIds) return;
7590
7718
  const unknown = required.filter((c) => typeof c !== "string" || !declaredKeys.has(c) && !opts.connectionIds.has(c));
7591
7719
  if (unknown.length) {
7592
- err("required-connection-unknown", `requiredConnections ${JSON.stringify(unknown)} are neither declared connections[].key values nor connections the owner can mount`, `${path26}.requiredConnections`, singleId(node));
7720
+ err("required-connection-unknown", `requiredConnections ${JSON.stringify(unknown)} are neither declared connections[].key values nor connections the owner can mount`, `${path27}.requiredConnections`, singleId(node));
7593
7721
  }
7594
7722
  }, "checkRequiredConnections");
7595
7723
  const jobClassifiablePin = /* @__PURE__ */ __name4((model) => {
@@ -7607,33 +7735,33 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7607
7735
  }
7608
7736
  return void 0;
7609
7737
  }, "jobClassifiablePin");
7610
- const checkTier = /* @__PURE__ */ __name4((node, path26) => {
7738
+ const checkTier = /* @__PURE__ */ __name4((node, path27) => {
7611
7739
  const id2 = singleId(node);
7612
7740
  if (node.workspace && node.workspace !== "inherit" && node.tier !== void 0 && node.tier !== "job") {
7613
- err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path26}.workspace`, id2);
7741
+ err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path27}.workspace`, id2);
7614
7742
  }
7615
7743
  if (node.harness !== void 0 && node.tier !== "job") {
7616
- err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${path26}.harness`, id2);
7744
+ err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${path27}.harness`, id2);
7617
7745
  }
7618
7746
  const provider = node.type === "agent" ? classifyModelProvider(jobClassifiablePin(node.model)) : null;
7619
7747
  if (node.harness === "claude-code" && provider !== null && provider !== "anthropic") {
7620
- err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${path26}.harness`, id2);
7748
+ err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${path27}.harness`, id2);
7621
7749
  }
7622
7750
  if (isJobTier(node) && provider !== null && opts.policy?.jobProviders && !opts.policy.jobProviders.includes(provider)) {
7623
- err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path26}.model`, id2);
7751
+ err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path27}.model`, id2);
7624
7752
  }
7625
7753
  }, "checkTier");
7626
- const checkModel = /* @__PURE__ */ __name4((node, path26) => {
7754
+ const checkModel = /* @__PURE__ */ __name4((node, path27) => {
7627
7755
  if (node.type !== "agent" || typeof node.model !== "string") return;
7628
7756
  const id2 = singleId(node);
7629
7757
  const parsed = parseModelTemplate(node.model);
7630
7758
  if (parsed.kind === "invalid") {
7631
- err("model-template-invalid", parsed.message, `${path26}.model`, id2);
7759
+ err("model-template-invalid", parsed.message, `${path27}.model`, id2);
7632
7760
  return;
7633
7761
  }
7634
7762
  if (parsed.kind === "template" && parsed.template.default === void 0) {
7635
7763
  if (isJobTier(node)) {
7636
- err("model-template-default-required", modelTemplateDefaultRequiredMessage(node.model), `${path26}.model`, id2);
7764
+ err("model-template-default-required", modelTemplateDefaultRequiredMessage(node.model), `${path27}.model`, id2);
7637
7765
  }
7638
7766
  return;
7639
7767
  }
@@ -7646,80 +7774,85 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7646
7774
  if (registry === "unavailable") {
7647
7775
  const trimmed2 = pin.trim();
7648
7776
  if (trimmed2 && !normalizeModelId(trimmed2, []).ok) {
7649
- warn("model-unresolved", inContext(`model "${trimmed2}" could not be checked against the approved-model registry (unavailable at push) \u2014 it dispatches only if it resolves there (a provider/model registry code, or a bare id exactly one approved model carries)`), `${path26}.model`, id2);
7777
+ warn("model-unresolved", inContext(`model "${trimmed2}" could not be checked against the approved-model registry (unavailable at push) \u2014 it dispatches only if it resolves there (a provider/model registry code, or a bare id exactly one approved model carries)`), `${path27}.model`, id2);
7650
7778
  }
7651
7779
  return;
7652
7780
  }
7653
7781
  const resolved = normalizeModelId(pin, registry);
7654
- if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path26}.model`, id2);
7782
+ if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path27}.model`, id2);
7655
7783
  }, "checkModel");
7656
- const checkTaskClass = /* @__PURE__ */ __name4((node, path26) => {
7784
+ const checkTaskClass = /* @__PURE__ */ __name4((node, path27) => {
7657
7785
  if (node.type !== "agent" || node.taskClass === void 0) return;
7658
7786
  if (!opts.static) return;
7659
7787
  if (typeof node.model === "string" && node.model.trim()) return;
7660
- err("task-class-without-model", `taskClass '${String(node.taskClass)}' needs a \`model\` on a pushed definition \u2014 write a class (model: 'class/fast' | 'class/balanced' | 'class/strong') or an approved provider/model code; nothing maps a task class to a model at dispatch, so a step with neither would run on the agent\u2019s own model`, `${path26}.taskClass`, singleId(node));
7788
+ err("task-class-without-model", `taskClass '${String(node.taskClass)}' needs a \`model\` on a pushed definition \u2014 write a class (model: 'class/fast' | 'class/balanced' | 'class/strong') or an approved provider/model code; nothing maps a task class to a model at dispatch, so a step with neither would run on the agent\u2019s own model`, `${path27}.taskClass`, singleId(node));
7661
7789
  }, "checkTaskClass");
7662
- const checkWorkspace = /* @__PURE__ */ __name4((node, path26) => {
7790
+ const checkWorkspace = /* @__PURE__ */ __name4((node, path27) => {
7663
7791
  const id2 = singleId(node);
7664
7792
  const ws = workspaceOf(node);
7665
7793
  if (isJobTier(node) && opts.policy && opts.policy.jobTier !== true) {
7666
- err("job-tier-disabled", `"${id2}" runs on the Job tier but the org's workflowPolicy.jobTier is off \u2014 an org admin enables it (lua features workflows.caps.jobTier true)`, `${path26}.tier`, id2);
7794
+ err("job-tier-disabled", `"${id2}" runs on the Job tier but the org's workflowPolicy.jobTier is off \u2014 an org admin enables it (lua features workflows.caps.jobTier true)`, `${path27}.tier`, id2);
7667
7795
  }
7668
7796
  const tools = jobToolsOf(node);
7669
7797
  if (tools !== void 0) {
7670
7798
  if (!isJobTier(node)) {
7671
- err("job-tools-require-job-tier", "`jobTools` needs tier:'job'", `${path26}.jobTools`, id2);
7799
+ err("job-tools-require-job-tier", "`jobTools` needs tier:'job'", `${path27}.jobTools`, id2);
7672
7800
  }
7673
7801
  const unknown = (Array.isArray(tools) ? tools : [
7674
7802
  tools
7675
7803
  ]).filter((t) => !WORKFLOW_JOB_TOOLS.includes(t));
7676
7804
  if (unknown.length > 0) {
7677
- err("job-tools-unknown", `jobTools ${JSON.stringify(unknown)} outside WORKFLOW_JOB_TOOLS [${WORKFLOW_JOB_TOOLS.join(", ")}]`, `${path26}.jobTools`, id2);
7805
+ err("job-tools-unknown", `jobTools ${JSON.stringify(unknown)} outside WORKFLOW_JOB_TOOLS [${WORKFLOW_JOB_TOOLS.join(", ")}]`, `${path27}.jobTools`, id2);
7678
7806
  }
7679
7807
  if (node.type === "agent" && (Array.isArray(tools) ? tools : [
7680
7808
  tools
7681
7809
  ]).includes("gh")) {
7682
- warn("gh-on-coding-turn", `"${id2}" 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)`, `${path26}.jobTools`, id2);
7810
+ warn("gh-on-coding-turn", `"${id2}" 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)`, `${path27}.jobTools`, id2);
7683
7811
  }
7684
7812
  }
7685
7813
  const plugins = node.plugins;
7686
7814
  const target = node.target;
7815
+ const luaApi = node.luaApi;
7816
+ if (luaApi !== void 0) {
7817
+ const problem = workflowJobLuaApiProblem(luaApi, node.type === "step" ? "code" : node.type, isJobTier(node) ? "job" : node.tier);
7818
+ if (problem) err("lua-api-invalid", problem, `${path27}.luaApi`, id2);
7819
+ }
7687
7820
  if (target !== void 0) {
7688
- const problem = workflowJobTargetProblem(target, plugins);
7689
- if (problem) err("target-invalid", problem, `${path26}.target`, id2);
7821
+ const problem = workflowJobTargetProblem(target, plugins, luaApi);
7822
+ if (problem) err("target-invalid", problem, `${path27}.target`, id2);
7690
7823
  }
7691
7824
  if (plugins !== void 0) {
7692
7825
  const problem = workflowJobPluginsProblem(plugins);
7693
- if (problem) err("plugins-invalid", problem, `${path26}.plugins`, id2);
7694
- if (node.type !== "agent") err("plugins-invalid", "`plugins` is legal on agent steps only", `${path26}.plugins`, id2);
7826
+ if (problem) err("plugins-invalid", problem, `${path27}.plugins`, id2);
7827
+ if (node.type !== "agent") err("plugins-invalid", "`plugins` is legal on agent steps only", `${path27}.plugins`, id2);
7695
7828
  else {
7696
- if (!isJobTier(node)) err("plugins-invalid", "`plugins` needs tier:'job'", `${path26}.plugins`, id2);
7829
+ if (!isJobTier(node)) err("plugins-invalid", "`plugins` needs tier:'job'", `${path27}.plugins`, id2);
7697
7830
  const provider = classifyModelProvider(jobClassifiablePin(node.model));
7698
- if (node.harness === "generic" || provider !== null && provider !== "anthropic") err("plugins-invalid", "`plugins` run on the claude-code harness only (an Anthropic model, no `harness:'generic'`)", `${path26}.plugins`, id2);
7831
+ if (node.harness === "generic" || provider !== null && provider !== "anthropic") err("plugins-invalid", "`plugins` run on the claude-code harness only (an Anthropic model, no `harness:'generic'`)", `${path27}.plugins`, id2);
7699
7832
  const w = workspaceOf(node);
7700
7833
  const ro = w !== void 0 && w !== "inherit" && w.mount === "ro";
7701
7834
  const declared = Array.isArray(tools) ? tools : void 0;
7702
- if (!effectiveJobTools(declared, ro).includes("shell")) err("plugins-invalid", "`plugins` need the `shell` job tool (the plugin drives lua-cli) \u2014 keep it in jobTools and mount rw", `${path26}.plugins`, id2);
7835
+ if (!effectiveJobTools(declared, ro).includes("shell")) err("plugins-invalid", "`plugins` need the `shell` job tool (the plugin drives lua-cli) \u2014 keep it in jobTools and mount rw", `${path27}.plugins`, id2);
7703
7836
  }
7704
7837
  }
7705
7838
  if (node.type === "agent" && ws && ws !== "inherit" && ws.mount === "ro" && Array.isArray(tools) && effectiveJobTools(tools, true).length === 0) {
7706
- warn("ro-step-has-no-tools", `"${id2}" 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`, `${path26}.jobTools`, id2);
7839
+ warn("ro-step-has-no-tools", `"${id2}" 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`, `${path27}.jobTools`, id2);
7707
7840
  }
7708
7841
  if (ws && ws !== "inherit") {
7709
7842
  if (!envelopeWorkspace && !opts.mayInherit) {
7710
- err("workspace-not-declared", `"${id2}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path26}.workspace`, id2);
7843
+ err("workspace-not-declared", `"${id2}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path27}.workspace`, id2);
7711
7844
  }
7712
7845
  if (ws.isolation === "worktree" && envelopeWorkspace?.kind === "empty") {
7713
- err("worktree-requires-git-workspace", `"${id2}": isolation:'worktree' needs a kind:'git' workspace (the envelope declares kind:'empty')`, `${path26}.workspace.isolation`, id2);
7846
+ err("worktree-requires-git-workspace", `"${id2}": isolation:'worktree' needs a kind:'git' workspace (the envelope declares kind:'empty')`, `${path27}.workspace.isolation`, id2);
7714
7847
  }
7715
7848
  }
7716
7849
  if (node.type === "workflow" && ws === "inherit") {
7717
7850
  if (!envelopeWorkspace) {
7718
- err("workspace-inherit-without-parent-workspace", `"${id2}": workspace:'inherit' but the parent workflow declares no workspace \u2014 there is nothing to inherit`, `${path26}.workspace`, id2);
7851
+ err("workspace-inherit-without-parent-workspace", `"${id2}": workspace:'inherit' but the parent workflow declares no workspace \u2014 there is nothing to inherit`, `${path27}.workspace`, id2);
7719
7852
  }
7720
7853
  const child = opts.resolveWorkflow?.(node.workflowId);
7721
7854
  if (child?.workspace) {
7722
- err("workspace-inherit-conflict", `"${id2}": workspace:'inherit' on "${node.workflowId}", which declares its own workspace`, `${path26}.workspace`, id2);
7855
+ err("workspace-inherit-conflict", `"${id2}": workspace:'inherit' on "${node.workflowId}", which declares its own workspace`, `${path27}.workspace`, id2);
7723
7856
  }
7724
7857
  }
7725
7858
  }, "checkWorkspace");
@@ -7733,165 +7866,165 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7733
7866
  warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id2, m), `${basePath}.${m.member}`, id2);
7734
7867
  }
7735
7868
  }, "checkMapMembers");
7736
- const checkInputShape = /* @__PURE__ */ __name4((node, path26) => {
7869
+ const checkInputShape = /* @__PURE__ */ __name4((node, path27) => {
7737
7870
  const input = node.input;
7738
7871
  if (input === void 0) return;
7739
7872
  const id2 = singleId(node);
7740
7873
  if (input !== null && typeof input === "object" && !Array.isArray(input)) {
7741
- checkMapMembers(input, `${path26}.input`, id2);
7874
+ checkMapMembers(input, `${path27}.input`, id2);
7742
7875
  return;
7743
7876
  }
7744
- 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)})`, `${path26}.input`, id2);
7877
+ 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)})`, `${path27}.input`, id2);
7745
7878
  }, "checkInputShape");
7746
- const checkBodyInput = /* @__PURE__ */ __name4((body, path26, container) => {
7879
+ const checkBodyInput = /* @__PURE__ */ __name4((body, path27, container) => {
7747
7880
  if (body.type === "workflow" || body.input === void 0) return;
7748
- 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`, `${path26}.input`, singleId(body));
7881
+ 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`, `${path27}.input`, singleId(body));
7749
7882
  }, "checkBodyInput");
7750
- const checkSingle = /* @__PURE__ */ __name4((node, path26, depth) => {
7883
+ const checkSingle = /* @__PURE__ */ __name4((node, path27, depth) => {
7751
7884
  recordOutputSchema(node);
7752
7885
  if (node.type === "workflow" && (typeof node.workflowId !== "string" || node.workflowId.length === 0)) {
7753
- checkId(node.id, path26);
7754
- err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${path26}.workflowId`, node.id);
7886
+ checkId(node.id, path27);
7887
+ err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${path27}.workflowId`, node.id);
7755
7888
  return;
7756
7889
  }
7757
7890
  if (node.type === "workflow" && (node.workflowId.startsWith("$") || Array.isArray(node.graph))) {
7758
- checkId(node.id, path26);
7759
- err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId), path26, node.id);
7891
+ checkId(node.id, path27);
7892
+ err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId), path27, node.id);
7760
7893
  return;
7761
7894
  }
7762
- checkId(singleId(node), path26);
7763
- checkPolicyEnums(node, path26);
7764
- checkInputShape(node, path26);
7765
- checkTimeout(node, path26);
7766
- checkTier(node, path26);
7767
- checkModel(node, path26);
7768
- checkTaskClass(node, path26);
7769
- checkRetry(node, path26);
7770
- checkWorkspace(node, path26);
7895
+ checkId(singleId(node), path27);
7896
+ checkPolicyEnums(node, path27);
7897
+ checkInputShape(node, path27);
7898
+ checkTimeout(node, path27);
7899
+ checkTier(node, path27);
7900
+ checkModel(node, path27);
7901
+ checkTaskClass(node, path27);
7902
+ checkRetry(node, path27);
7903
+ checkWorkspace(node, path27);
7771
7904
  if (!opts.static) {
7772
- if (node.type === "step") err("code-step-not-allowed", "code steps are static-only (03 \xA73.4.2)", path26, node.step.id);
7905
+ if (node.type === "step") err("code-step-not-allowed", "code steps are static-only (03 \xA73.4.2)", path27, node.step.id);
7773
7906
  if (node.type === "agent" && node.systemPrompt !== void 0) {
7774
- err("persona-override-not-allowed", "`systemPrompt` is static-only (03 \xA73.4.2)", `${path26}.systemPrompt`, node.id);
7907
+ err("persona-override-not-allowed", "`systemPrompt` is static-only (03 \xA73.4.2)", `${path27}.systemPrompt`, node.id);
7775
7908
  }
7776
7909
  }
7777
7910
  if (node.type === "agent" && node.role && node.systemPrompt !== void 0) {
7778
- err("ephemeral-persona-not-overridable", "a specialist role and systemPrompt cannot coexist", `${path26}.systemPrompt`, node.id);
7911
+ err("ephemeral-persona-not-overridable", "a specialist role and systemPrompt cannot coexist", `${path27}.systemPrompt`, node.id);
7779
7912
  }
7780
7913
  if (node.type === "agent" && node.role && typeof node.role.instructions === "string" && node.role.instructions.length > 4e3) {
7781
- err("ephemeral-role-too-long", "role.instructions exceeds 4000 chars", `${path26}.role.instructions`, node.id);
7914
+ err("ephemeral-role-too-long", "role.instructions exceeds 4000 chars", `${path27}.role.instructions`, node.id);
7782
7915
  }
7783
7916
  if (node.type === "agent" && node.role && (node.role.tools?.length ?? 0) > 64) {
7784
- err("cap-exceeded", "role.tools exceeds 64 entries", `${path26}.role.tools`, node.id);
7917
+ err("cap-exceeded", "role.tools exceeds 64 entries", `${path27}.role.tools`, node.id);
7785
7918
  }
7786
- if (node.type === "agent" && node.role) checkSpecialistRole(node, path26);
7787
- checkRequiredConnections(node, path26);
7919
+ if (node.type === "agent" && node.role) checkSpecialistRole(node, path27);
7920
+ checkRequiredConnections(node, path27);
7788
7921
  if (node.type === "workflow" && node.kind === "subrun" && depth > caps.maxNestingDepth) {
7789
- err("cap-exceeded", `nesting depth ${depth} exceeds ${caps.maxNestingDepth}`, path26, node.id);
7922
+ err("cap-exceeded", `nesting depth ${depth} exceeds ${caps.maxNestingDepth}`, path27, node.id);
7790
7923
  }
7791
7924
  if (node.type === "workflow" && typeof g.definition?.id === "string" && node.workflowId === g.definition.id) {
7792
- err("subrun-cycle", `"${node.id}" starts "${node.workflowId}", which is this workflow itself`, path26, node.id);
7925
+ err("subrun-cycle", `"${node.id}" starts "${node.workflowId}", which is this workflow itself`, path27, node.id);
7793
7926
  }
7794
7927
  for (const ref of nodeStepRefs(node)) {
7795
7928
  if (!upstream.has(ref)) {
7796
- err("template-reference-unresolved", `"${singleId(node)}" references stepResults.${ref}, which is not upstream`, path26, singleId(node));
7929
+ err("template-reference-unresolved", `"${singleId(node)}" references stepResults.${ref}, which is not upstream`, path27, singleId(node));
7797
7930
  }
7798
7931
  }
7799
7932
  }, "checkSingle");
7800
- const checkHitl = /* @__PURE__ */ __name4((node, path26) => {
7933
+ const checkHitl = /* @__PURE__ */ __name4((node, path27) => {
7801
7934
  if (node.type === "waitForSignal") {
7802
7935
  const w = node;
7803
- checkId(w.id, path26);
7804
- if (typeof w.signal !== "string" || w.signal.length === 0) err("invalid-envelope", "waitForSignal.signal is required", `${path26}.signal`, w.id);
7936
+ checkId(w.id, path27);
7937
+ if (typeof w.signal !== "string" || w.signal.length === 0) err("invalid-envelope", "waitForSignal.signal is required", `${path27}.signal`, w.id);
7805
7938
  return;
7806
7939
  }
7807
7940
  const a = node;
7808
- checkId(a.id, path26);
7941
+ checkId(a.id, path27);
7809
7942
  if ((a.approver ?? "creator") === "creator" && a.excludeInitiator === true) {
7810
- err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path26, a.id);
7943
+ err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path27, a.id);
7811
7944
  }
7812
7945
  const editable = approvalEditable(a);
7813
7946
  if (a.fourEyes !== void 0 && !editable) {
7814
- err("four-eyes-requires-editable", "`fourEyes` requires editable:true", `${path26}.fourEyes`, a.id);
7947
+ err("four-eyes-requires-editable", "`fourEyes` requires editable:true", `${path27}.fourEyes`, a.id);
7815
7948
  }
7816
7949
  if (a.editable === false && Array.isArray(a.editablePaths) && a.editablePaths.length > 0) {
7817
- err("editable-path-invalid", "`editablePaths` beside editable:false is contradictory \u2014 drop the paths or set editable:true", `${path26}.editablePaths`, a.id);
7950
+ err("editable-path-invalid", "`editablePaths` beside editable:false is contradictory \u2014 drop the paths or set editable:true", `${path27}.editablePaths`, a.id);
7818
7951
  } else if ((a.editablePaths !== void 0 || a.editedPayloadSchema !== void 0) && !editable) {
7819
- err("editable-path-invalid", "`editablePaths` / `editedPayloadSchema` require editable:true (a non-empty editablePaths implies it)", `${path26}.editablePaths`, a.id);
7952
+ err("editable-path-invalid", "`editablePaths` / `editedPayloadSchema` require editable:true (a non-empty editablePaths implies it)", `${path27}.editablePaths`, a.id);
7820
7953
  }
7821
7954
  for (const p of a.editablePaths ?? []) {
7822
- if (!EDITABLE_PATH_RE.test(p)) err("editable-path-invalid", `editablePaths entry "${p}" is outside the seg(.seg)*[*]/[n] grammar`, `${path26}.editablePaths`, a.id);
7955
+ if (!EDITABLE_PATH_RE.test(p)) err("editable-path-invalid", `editablePaths entry "${p}" is outside the seg(.seg)*[*]/[n] grammar`, `${path27}.editablePaths`, a.id);
7823
7956
  }
7824
7957
  if (Array.isArray(a.onTimeout)) {
7825
7958
  const chain = a.onTimeout;
7826
7959
  const hops = chain.filter((h) => typeof h === "object" && h !== null && "escalateTo" in h);
7827
- if (hops.length > 3) err("escalation-chain-too-long", "an onTimeout chain carries at most 3 escalation hops", `${path26}.onTimeout`, a.id);
7960
+ if (hops.length > 3) err("escalation-chain-too-long", "an onTimeout chain carries at most 3 escalation hops", `${path27}.onTimeout`, a.id);
7828
7961
  const last = chain[chain.length - 1];
7829
7962
  if (last === void 0 || typeof last === "object" && last !== null && "escalateTo" in last) {
7830
- err("escalation-chain-not-terminal", "an onTimeout chain must end in a terminal member", `${path26}.onTimeout`, a.id);
7963
+ err("escalation-chain-not-terminal", "an onTimeout chain must end in a terminal member", `${path27}.onTimeout`, a.id);
7831
7964
  }
7832
7965
  }
7833
7966
  if (typeof a.details === "string") {
7834
7967
  for (const ref of templateStepRefs(a.details)) {
7835
- if (!upstream.has(ref)) err("template-reference-unresolved", `"${a.id}" references stepResults.${ref}, which is not upstream`, path26, a.id);
7968
+ if (!upstream.has(ref)) err("template-reference-unresolved", `"${a.id}" references stepResults.${ref}, which is not upstream`, path27, a.id);
7836
7969
  }
7837
7970
  }
7838
7971
  }, "checkHitl");
7839
- const checkHitlArm = /* @__PURE__ */ __name4((node, path26, container) => {
7972
+ const checkHitlArm = /* @__PURE__ */ __name4((node, path27, container) => {
7840
7973
  if (!workflowContainerRunsHitlArm(container)) {
7841
- checkId(node.id, path26);
7842
- err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container), path26, node.id);
7974
+ checkId(node.id, path27);
7975
+ err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container), path27, node.id);
7843
7976
  return;
7844
7977
  }
7845
- checkHitl(node, path26);
7978
+ checkHitl(node, path27);
7846
7979
  }, "checkHitlArm");
7847
- const checkArm = /* @__PURE__ */ __name4((arm, path26, depth, container) => {
7980
+ const checkArm = /* @__PURE__ */ __name4((arm, path27, depth, container) => {
7848
7981
  if (arm.type === "mapping") {
7849
- checkId(arm.id, path26);
7850
- checkMapMembers(readMapConfig(arm.mapConfig), `${path26}.mapConfig`, arm.id);
7982
+ checkId(arm.id, path27);
7983
+ checkMapMembers(readMapConfig(arm.mapConfig), `${path27}.mapConfig`, arm.id);
7851
7984
  for (const ref of nodeStepRefs(arm)) {
7852
- if (!upstream.has(ref)) err("template-reference-unresolved", `"${arm.id}" references stepResults.${ref}, which is not upstream`, path26, arm.id);
7985
+ if (!upstream.has(ref)) err("template-reference-unresolved", `"${arm.id}" references stepResults.${ref}, which is not upstream`, path27, arm.id);
7853
7986
  }
7854
7987
  return;
7855
7988
  }
7856
7989
  if (isHitlNode(arm)) {
7857
- checkHitlArm(arm, path26, container);
7990
+ checkHitlArm(arm, path27, container);
7858
7991
  return;
7859
7992
  }
7860
- checkSingle(arm, path26, depth);
7993
+ checkSingle(arm, path27, depth);
7861
7994
  }, "checkArm");
7862
7995
  graph.forEach((entry, i) => {
7863
- const path26 = `graph.${i}`;
7996
+ const path27 = `graph.${i}`;
7864
7997
  const declared = [];
7865
7998
  switch (entry.type) {
7866
7999
  case "step":
7867
8000
  case "agent":
7868
8001
  case "tool":
7869
8002
  case "workflow":
7870
- checkSingle(entry, path26, 1);
8003
+ checkSingle(entry, path27, 1);
7871
8004
  declared.push(singleId(entry));
7872
8005
  break;
7873
8006
  case "mapping":
7874
- checkId(entry.id, path26);
7875
- checkMapMembers(readMapConfig(entry.mapConfig), `${path26}.mapConfig`, entry.id);
8007
+ checkId(entry.id, path27);
8008
+ checkMapMembers(readMapConfig(entry.mapConfig), `${path27}.mapConfig`, entry.id);
7876
8009
  for (const ref of nodeStepRefs(entry)) {
7877
- if (!upstream.has(ref)) err("template-reference-unresolved", `"${entry.id}" references stepResults.${ref}, which is not upstream`, path26, entry.id);
8010
+ if (!upstream.has(ref)) err("template-reference-unresolved", `"${entry.id}" references stepResults.${ref}, which is not upstream`, path27, entry.id);
7878
8011
  }
7879
8012
  declared.push(entry.id);
7880
8013
  break;
7881
8014
  case "sleep":
7882
- checkId(entry.id, path26);
7883
- if (!Number.isFinite(entry.duration) || entry.duration < 0) err("invalid-envelope", "sleep.duration must be a non-negative number", `${path26}.duration`, entry.id);
8015
+ checkId(entry.id, path27);
8016
+ if (!Number.isFinite(entry.duration) || entry.duration < 0) err("invalid-envelope", "sleep.duration must be a non-negative number", `${path27}.duration`, entry.id);
7884
8017
  declared.push(entry.id);
7885
8018
  break;
7886
8019
  case "sleepUntil": {
7887
8020
  const s = entry;
7888
- checkId(s.id, path26);
7889
- err("node-type-unsupported-by-engine", sleepUntilUnsupportedMessage(s.id), path26, s.id);
8021
+ checkId(s.id, path27);
8022
+ err("node-type-unsupported-by-engine", sleepUntilUnsupportedMessage(s.id), path27, s.id);
7890
8023
  if (s.date === void 0 === (s.dateFrom === void 0)) {
7891
- err("invalid-envelope", "sleepUntil needs exactly one of `date` | `dateFrom`", path26, s.id);
8024
+ err("invalid-envelope", "sleepUntil needs exactly one of `date` | `dateFrom`", path27, s.id);
7892
8025
  }
7893
8026
  if (s.dateFrom && !upstream.has(s.dateFrom.step)) {
7894
- err("sleep-until-source-missing", `sleepUntil "${s.id}" reads dateFrom.step "${s.dateFrom.step}", which is not upstream`, `${path26}.dateFrom`, s.id);
8027
+ err("sleep-until-source-missing", `sleepUntil "${s.id}" reads dateFrom.step "${s.dateFrom.step}", which is not upstream`, `${path27}.dateFrom`, s.id);
7895
8028
  }
7896
8029
  declared.push(s.id);
7897
8030
  break;
@@ -7899,10 +8032,10 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7899
8032
  case "parallel": {
7900
8033
  const p = entry;
7901
8034
  if (p.steps.length < 2 || p.steps.length > caps.maxParallelArms) {
7902
- err("cap-exceeded", `parallel needs 2..${caps.maxParallelArms} arms (got ${p.steps.length})`, path26);
8035
+ err("cap-exceeded", `parallel needs 2..${caps.maxParallelArms} arms (got ${p.steps.length})`, path27);
7903
8036
  }
7904
8037
  p.steps.forEach((arm, j) => {
7905
- const armPath = `${path26}.steps.${j}`;
8038
+ const armPath = `${path27}.steps.${j}`;
7906
8039
  if (arm.type === "mapping") {
7907
8040
  err("mapping-placement", "a bare mapping cannot be a parallel arm \u2014 chain it as [map, step]", armPath);
7908
8041
  return;
@@ -7912,31 +8045,31 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7912
8045
  });
7913
8046
  const executableArms = p.steps.filter(isSingleStep);
7914
8047
  const worktreeArms = executableArms.filter((a) => a.workspace?.isolation === "worktree");
7915
- if (worktreeArms.length > 0 && !p.merge) err("worktree-arms-require-merge", "worktree arms need a `merge` policy", path26);
7916
- if (worktreeArms.length === 0 && p.merge) err("merge-requires-worktree-arms", "`merge` needs at least one worktree arm", path26);
7917
- if (worktreeArms.length > WORKFLOW_JOB_MAX_WORKTREE_ARMS) err("worktree-arms-exceed-cap", `at most ${WORKFLOW_JOB_MAX_WORKTREE_ARMS} worktree arms per parallel`, path26);
8048
+ if (worktreeArms.length > 0 && !p.merge) err("worktree-arms-require-merge", "worktree arms need a `merge` policy", path27);
8049
+ if (worktreeArms.length === 0 && p.merge) err("merge-requires-worktree-arms", "`merge` needs at least one worktree arm", path27);
8050
+ if (worktreeArms.length > WORKFLOW_JOB_MAX_WORKTREE_ARMS) err("worktree-arms-exceed-cap", `at most ${WORKFLOW_JOB_MAX_WORKTREE_ARMS} worktree arms per parallel`, path27);
7918
8051
  const sharedArms = executableArms.filter((a) => {
7919
8052
  const w = workspaceOf(a);
7920
8053
  if (!w || w === "inherit" || w.isolation === "worktree") return false;
7921
8054
  return !(envelopeWorkspace?.backend === "efs" && w.mount === "ro");
7922
8055
  });
7923
- if (sharedArms.length > 1) err("workspace-parallel-requires-worktree", `${sharedArms.length} arms mount the shared workspace inside one parallel \u2014 give each arm isolation:'worktree' (+ merge) or run them sequentially`, `${path26}.steps`);
8056
+ if (sharedArms.length > 1) err("workspace-parallel-requires-worktree", `${sharedArms.length} arms mount the shared workspace inside one parallel \u2014 give each arm isolation:'worktree' (+ merge) or run them sequentially`, `${path27}.steps`);
7924
8057
  break;
7925
8058
  }
7926
8059
  case "conditional": {
7927
8060
  const c = entry;
7928
8061
  if (!Array.isArray(c.predicates) || c.predicates.length !== c.steps.length) {
7929
- err("invalid-envelope", "conditional.predicates must match conditional.steps one-to-one", path26);
8062
+ err("invalid-envelope", "conditional.predicates must match conditional.steps one-to-one", path27);
7930
8063
  }
7931
8064
  (c.predicates ?? []).forEach((p, j) => {
7932
- if (!isWellFormedPredicate(p)) err("closure-predicate", "a conditional predicate must be a well-formed LuaPredicate object ({op, left/right | value | path | args | arg}), not a function or an expression string", `${path26}.predicates.${j}`);
8065
+ if (!isWellFormedPredicate(p)) err("closure-predicate", "a conditional predicate must be a well-formed LuaPredicate object ({op, left/right | value | path | args | arg}), not a function or an expression string", `${path27}.predicates.${j}`);
7933
8066
  });
7934
8067
  c.steps.forEach((arm, j) => {
7935
- checkArm(arm, `${path26}.steps.${j}`, 1, "conditional");
8068
+ checkArm(arm, `${path27}.steps.${j}`, 1, "conditional");
7936
8069
  declared.push(armId(arm));
7937
8070
  });
7938
8071
  if (c.otherwise) {
7939
- checkArm(c.otherwise, `${path26}.otherwise`, 1, "conditional");
8072
+ checkArm(c.otherwise, `${path27}.otherwise`, 1, "conditional");
7940
8073
  declared.push(armId(c.otherwise));
7941
8074
  }
7942
8075
  break;
@@ -7945,34 +8078,34 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7945
8078
  const f = entry;
7946
8079
  const o = f.opts ?? {};
7947
8080
  if (o.concurrency !== void 0 && (o.concurrency < 1 || o.concurrency > caps.maxForeachConcurrency)) {
7948
- err("cap-exceeded", `foreach.concurrency must be 1..${caps.maxForeachConcurrency}`, `${path26}.opts.concurrency`);
8081
+ err("cap-exceeded", `foreach.concurrency must be 1..${caps.maxForeachConcurrency}`, `${path27}.opts.concurrency`);
7949
8082
  }
7950
8083
  if (o.maxItems !== void 0 && (o.maxItems < 1 || o.maxItems > caps.maxForeachItems)) {
7951
- err("cap-exceeded", `foreach.maxItems must be 1..${caps.maxForeachItems} (the platform ceiling of maxForeachItems)`, `${path26}.opts.maxItems`);
8084
+ err("cap-exceeded", `foreach.maxItems must be 1..${caps.maxForeachItems} (the platform ceiling of maxForeachItems)`, `${path27}.opts.maxItems`);
7952
8085
  }
7953
8086
  {
7954
8087
  const itemsCap = o.maxItems ?? WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS;
7955
8088
  const literal = o.items;
7956
8089
  if (Array.isArray(literal) && literal.length > itemsCap) {
7957
- err("foreach-items-exceed-cap", `foreach({items}) carries ${literal.length} items \u2014 above maxItems ${itemsCap}`, `${path26}.opts.items`);
8090
+ err("foreach-items-exceed-cap", `foreach({items}) carries ${literal.length} items \u2014 above maxItems ${itemsCap}`, `${path27}.opts.items`);
7958
8091
  }
7959
8092
  }
7960
8093
  if (o.chunk !== void 0) {
7961
8094
  const max = o.maxItems ?? WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS;
7962
8095
  const size = typeof o.chunk === "number" ? o.chunk : o.chunk.size;
7963
8096
  if (!Number.isInteger(size) || size < 1 || size > max) {
7964
- err("chunk-size-invalid", `foreach.chunk.size must be an integer in [1, ${max}]`, typeof o.chunk === "number" ? `${path26}.opts.chunk` : `${path26}.opts.chunk.size`);
8097
+ err("chunk-size-invalid", `foreach.chunk.size must be an integer in [1, ${max}]`, typeof o.chunk === "number" ? `${path27}.opts.chunk` : `${path27}.opts.chunk.size`);
7965
8098
  }
7966
8099
  }
7967
8100
  if (o.rateLimit !== void 0) {
7968
8101
  const hasS = o.rateLimit.perSecond !== void 0;
7969
8102
  const hasM = o.rateLimit.perMinute !== void 0;
7970
8103
  if (hasS === hasM) {
7971
- err("rate-limit-invalid", "foreach.rateLimit needs exactly one of perSecond | perMinute", `${path26}.opts.rateLimit`);
8104
+ err("rate-limit-invalid", "foreach.rateLimit needs exactly one of perSecond | perMinute", `${path27}.opts.rateLimit`);
7972
8105
  } else if (hasS && (o.rateLimit.perSecond <= 0 || o.rateLimit.perSecond > caps.maxForeachRatePerSecond)) {
7973
- err("rate-limit-invalid", `rateLimit.perSecond must be in (0, ${caps.maxForeachRatePerSecond}]`, `${path26}.opts.rateLimit.perSecond`);
8106
+ err("rate-limit-invalid", `rateLimit.perSecond must be in (0, ${caps.maxForeachRatePerSecond}]`, `${path27}.opts.rateLimit.perSecond`);
7974
8107
  } else if (hasM && (o.rateLimit.perMinute <= 0 || o.rateLimit.perMinute > caps.maxForeachRatePerSecond * 60)) {
7975
- err("rate-limit-invalid", `rateLimit.perMinute must be in (0, ${caps.maxForeachRatePerSecond * 60}]`, `${path26}.opts.rateLimit.perMinute`);
8108
+ err("rate-limit-invalid", `rateLimit.perMinute must be in (0, ${caps.maxForeachRatePerSecond * 60}]`, `${path27}.opts.rateLimit.perMinute`);
7976
8109
  }
7977
8110
  }
7978
8111
  const bodyType = f.step.type;
@@ -7987,18 +8120,18 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
7987
8120
  const src = outputSchemas.get(d.step);
7988
8121
  arrayLike = src === void 0 ? void 0 : schemaIsArray(schemaAtPath(src, d.path ?? ""));
7989
8122
  }
7990
- if (arrayLike === false) err("foreach-items-not-array", `foreach({items}) for "${singleId(f.step)}" binds a value that is not an array`, `${path26}.step`, singleId(f.step));
8123
+ if (arrayLike === false) err("foreach-items-not-array", `foreach({items}) for "${singleId(f.step)}" binds a value that is not an array`, `${path27}.step`, singleId(f.step));
7991
8124
  }
7992
- if (bodyType === "mapping") err("container-arm-empty", "a foreach body needs a step, not a bare mapping", `${path26}.step`);
8125
+ if (bodyType === "mapping") err("container-arm-empty", "a foreach body needs a step, not a bare mapping", `${path27}.step`);
7993
8126
  else if (isHitlNode(f.step)) {
7994
8127
  if (o.chunk !== void 0) {
7995
- checkId(f.step.id, `${path26}.step`);
7996
- err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(f.step.type, f.step.id, "chunked-foreach"), `${path26}.step`, f.step.id);
7997
- } else checkHitlArm(f.step, `${path26}.step`, "foreach");
8128
+ checkId(f.step.id, `${path27}.step`);
8129
+ err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(f.step.type, f.step.id, "chunked-foreach"), `${path27}.step`, f.step.id);
8130
+ } else checkHitlArm(f.step, `${path27}.step`, "foreach");
7998
8131
  declared.push(f.step.id);
7999
8132
  } else {
8000
- checkBodyInput(f.step, `${path26}.step`, "foreach");
8001
- checkSingle(f.step, `${path26}.step`, o.chunk ? 2 : 1);
8133
+ checkBodyInput(f.step, `${path27}.step`, "foreach");
8134
+ checkSingle(f.step, `${path27}.step`, o.chunk ? 2 : 1);
8002
8135
  declared.push(singleId(f.step));
8003
8136
  }
8004
8137
  break;
@@ -8006,31 +8139,31 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
8006
8139
  case "loop": {
8007
8140
  const l = entry;
8008
8141
  if (l.maxIterations !== void 0 && (!Number.isInteger(l.maxIterations) || l.maxIterations < 1)) {
8009
- err("invalid-envelope", "loop.maxIterations must be a positive integer", `${path26}.maxIterations`);
8142
+ err("invalid-envelope", "loop.maxIterations must be a positive integer", `${path27}.maxIterations`);
8010
8143
  }
8011
8144
  if (l.intervalSeconds !== void 0 && (!Number.isInteger(l.intervalSeconds) || l.intervalSeconds < 1 || l.intervalSeconds > caps.maxLoopIntervalSeconds)) {
8012
- err("loop-interval-out-of-range", `loop.intervalSeconds must be an integer in 1..${caps.maxLoopIntervalSeconds}`, `${path26}.intervalSeconds`);
8145
+ err("loop-interval-out-of-range", `loop.intervalSeconds must be an integer in 1..${caps.maxLoopIntervalSeconds}`, `${path27}.intervalSeconds`);
8013
8146
  }
8014
- if (!isWellFormedPredicate(l.predicate)) err("closure-predicate", "a loop predicate must be a well-formed LuaPredicate object ({op, left/right | value | path | args | arg}), not a function or an expression string", `${path26}.predicate`);
8147
+ if (!isWellFormedPredicate(l.predicate)) err("closure-predicate", "a loop predicate must be a well-formed LuaPredicate object ({op, left/right | value | path | args | arg}), not a function or an expression string", `${path27}.predicate`);
8015
8148
  const bodyType = l.step.type;
8016
- if (bodyType === "mapping") err("container-arm-empty", "a loop body needs a step, not a bare mapping", `${path26}.step`);
8149
+ if (bodyType === "mapping") err("container-arm-empty", "a loop body needs a step, not a bare mapping", `${path27}.step`);
8017
8150
  else if (isHitlNode(l.step)) {
8018
- checkHitlArm(l.step, `${path26}.step`, "loop");
8151
+ checkHitlArm(l.step, `${path27}.step`, "loop");
8019
8152
  declared.push(l.step.id);
8020
8153
  } else {
8021
- checkBodyInput(l.step, `${path26}.step`, "loop");
8022
- checkSingle(l.step, `${path26}.step`, 1);
8154
+ checkBodyInput(l.step, `${path27}.step`, "loop");
8155
+ checkSingle(l.step, `${path27}.step`, 1);
8023
8156
  declared.push(singleId(l.step));
8024
8157
  }
8025
8158
  break;
8026
8159
  }
8027
8160
  case "approval":
8028
8161
  case "waitForSignal":
8029
- checkHitl(entry, path26);
8162
+ checkHitl(entry, path27);
8030
8163
  declared.push(entry.id);
8031
8164
  break;
8032
8165
  default:
8033
- err("invalid-envelope", `unknown entry type "${entry.type}"`, path26);
8166
+ err("invalid-envelope", `unknown entry type "${entry.type}"`, path27);
8034
8167
  }
8035
8168
  for (const id2 of declared) upstream.add(id2);
8036
8169
  });
@@ -8279,11 +8412,11 @@ function compilePlan(g) {
8279
8412
  }
8280
8413
  function resolvePath(rawPath, ctx) {
8281
8414
  const templateMatch = PATH_PLACEHOLDER.exec(rawPath.trim());
8282
- const path26 = templateMatch ? templateMatch[1].trim() : rawPath.trim();
8283
- if (path26 === "") return MISSING;
8284
- const dot = path26.indexOf(".");
8285
- const scope = dot === -1 ? path26 : path26.slice(0, dot);
8286
- const rest = dot === -1 ? "" : path26.slice(dot + 1);
8415
+ const path27 = templateMatch ? templateMatch[1].trim() : rawPath.trim();
8416
+ if (path27 === "") return MISSING;
8417
+ const dot = path27.indexOf(".");
8418
+ const scope = dot === -1 ? path27 : path27.slice(0, dot);
8419
+ const rest = dot === -1 ? "" : path27.slice(dot + 1);
8287
8420
  let root;
8288
8421
  switch (scope) {
8289
8422
  case "initData":
@@ -8317,9 +8450,9 @@ function resolvePath(rawPath, ctx) {
8317
8450
  }
8318
8451
  return walk(root, rest);
8319
8452
  }
8320
- function walk(root, path26) {
8321
- if (path26 === "") return root;
8322
- const parts = path26.split(".");
8453
+ function walk(root, path27) {
8454
+ if (path27 === "") return root;
8455
+ const parts = path27.split(".");
8323
8456
  let value22 = root;
8324
8457
  for (const part of parts) {
8325
8458
  if (value22 === null || value22 === void 0) return MISSING;
@@ -8445,14 +8578,14 @@ function step(s) {
8445
8578
  function stepOf(id2) {
8446
8579
  return step(id2);
8447
8580
  }
8448
- function init(path26) {
8581
+ function init(path27) {
8449
8582
  return {
8450
- path: path26 === "" ? "initData" : `initData.${path26}`
8583
+ path: path27 === "" ? "initData" : `initData.${path27}`
8451
8584
  };
8452
8585
  }
8453
- function state(path26) {
8586
+ function state(path27) {
8454
8587
  return {
8455
- path: path26 === "" ? "state" : `state.${path26}`
8588
+ path: path27 === "" ? "state" : `state.${path27}`
8456
8589
  };
8457
8590
  }
8458
8591
  function lit(v) {
@@ -9382,7 +9515,7 @@ function timeZoneSupported(tz) {
9382
9515
  return false;
9383
9516
  }
9384
9517
  }
9385
- function validateBusinessHours(cal, path26 = "businessHours") {
9518
+ function validateBusinessHours(cal, path27 = "businessHours") {
9386
9519
  const issues = [];
9387
9520
  const issue = /* @__PURE__ */ __name4((p, message) => issues.push({
9388
9521
  code: "business-hours-invalid",
@@ -9392,32 +9525,32 @@ function validateBusinessHours(cal, path26 = "businessHours") {
9392
9525
  if (typeof cal !== "object" || cal === null) return [
9393
9526
  {
9394
9527
  code: "business-hours-invalid",
9395
- path: path26,
9528
+ path: path27,
9396
9529
  message: "not an object"
9397
9530
  }
9398
9531
  ];
9399
9532
  const c = cal;
9400
- if (!timeZoneSupported(c.tz)) issue(`${path26}.tz`, "unknown IANA time zone");
9533
+ if (!timeZoneSupported(c.tz)) issue(`${path27}.tz`, "unknown IANA time zone");
9401
9534
  if (c.calendar === void 0 || c.calendar === "mon-fri") return issues;
9402
9535
  if (typeof c.calendar !== "object" || c.calendar === null) {
9403
- issue(`${path26}.calendar`, "expected 'mon-fri' or { days, start, end, holidays? }");
9536
+ issue(`${path27}.calendar`, "expected 'mon-fri' or { days, start, end, holidays? }");
9404
9537
  return issues;
9405
9538
  }
9406
9539
  const k = c.calendar;
9407
9540
  if (!Array.isArray(k.days) || k.days.length === 0 || k.days.some((d) => !Number.isInteger(d) || d < 0 || d > 6)) {
9408
- issue(`${path26}.calendar.days`, "days must be a non-empty array of 0\u20136");
9541
+ issue(`${path27}.calendar.days`, "days must be a non-empty array of 0\u20136");
9409
9542
  }
9410
9543
  const startOk = typeof k.start === "string" && HHMM.test(k.start);
9411
9544
  const endOk = typeof k.end === "string" && HHMM.test(k.end);
9412
- if (!startOk) issue(`${path26}.calendar.start`, "expected 'HH:MM'");
9413
- if (!endOk) issue(`${path26}.calendar.end`, "expected 'HH:MM'");
9414
- if (startOk && endOk && toMinutes(k.start) >= toMinutes(k.end)) issue(`${path26}.calendar`, "start must be before end");
9545
+ if (!startOk) issue(`${path27}.calendar.start`, "expected 'HH:MM'");
9546
+ if (!endOk) issue(`${path27}.calendar.end`, "expected 'HH:MM'");
9547
+ if (startOk && endOk && toMinutes(k.start) >= toMinutes(k.end)) issue(`${path27}.calendar`, "start must be before end");
9415
9548
  if (k.holidays !== void 0) {
9416
- if (!Array.isArray(k.holidays)) issue(`${path26}.calendar.holidays`, "expected an array of YYYY-MM-DD");
9549
+ if (!Array.isArray(k.holidays)) issue(`${path27}.calendar.holidays`, "expected an array of YYYY-MM-DD");
9417
9550
  else {
9418
- if (k.holidays.length > MAX_HOLIDAYS) issue(`${path26}.calendar.holidays`, `at most ${MAX_HOLIDAYS} holidays`);
9551
+ if (k.holidays.length > MAX_HOLIDAYS) issue(`${path27}.calendar.holidays`, `at most ${MAX_HOLIDAYS} holidays`);
9419
9552
  k.holidays.forEach((h, i) => {
9420
- if (typeof h !== "string" || !YMD.test(h)) issue(`${path26}.calendar.holidays[${i}]`, "expected 'YYYY-MM-DD'");
9553
+ if (typeof h !== "string" || !YMD.test(h)) issue(`${path27}.calendar.holidays[${i}]`, "expected 'YYYY-MM-DD'");
9421
9554
  });
9422
9555
  }
9423
9556
  }
@@ -9829,7 +9962,7 @@ function rebaseItemPointer(pointer, itemsPath, index) {
9829
9962
  const base = `/${itemsPath.split(".").map(escapePointer).join("/")}/${index}`;
9830
9963
  return pointer === "/" || pointer === "" ? base : `${base}${pointer}`;
9831
9964
  }
9832
- function validateWorkflowSchedule(schedule, path26 = "/schedule") {
9965
+ function validateWorkflowSchedule(schedule, path27 = "/schedule") {
9833
9966
  if (schedule === void 0 || schedule === null) return [];
9834
9967
  const issue = /* @__PURE__ */ __name4((at, detail) => [
9835
9968
  {
@@ -9840,40 +9973,40 @@ function validateWorkflowSchedule(schedule, path26 = "/schedule") {
9840
9973
  }
9841
9974
  ], "issue");
9842
9975
  if (!isObject(schedule)) {
9843
- return issue(path26, `\`schedule\` is ${Array.isArray(schedule) ? "an array" : `a ${typeof schedule}`}, not a typed schedule object`);
9976
+ return issue(path27, `\`schedule\` is ${Array.isArray(schedule) ? "an array" : `a ${typeof schedule}`}, not a typed schedule object`);
9844
9977
  }
9845
9978
  const type = schedule.type;
9846
9979
  if (type === void 0) {
9847
9980
  const keys = Object.keys(schedule);
9848
9981
  const seen = keys.length ? ` (got { ${keys.join(", ")} })` : " (got {})";
9849
- return issue(path26, `\`schedule\` carries no \`type\` discriminator${seen}`);
9982
+ return issue(path27, `\`schedule\` carries no \`type\` discriminator${seen}`);
9850
9983
  }
9851
9984
  if (typeof type !== "string" || !WORKFLOW_SCHEDULE_TYPES.includes(type)) {
9852
- return issue(path26, `\`schedule.type\` ${JSON.stringify(type)} is not one of ${WORKFLOW_SCHEDULE_TYPES.map((t) => `'${t}'`).join(" | ")}`);
9985
+ return issue(path27, `\`schedule.type\` ${JSON.stringify(type)} is not one of ${WORKFLOW_SCHEDULE_TYPES.map((t) => `'${t}'`).join(" | ")}`);
9853
9986
  }
9854
9987
  if (schedule.runAs !== void 0 && !WORKFLOW_SCHEDULE_RUN_AS.includes(schedule.runAs)) {
9855
- return issue(`${path26}/runAs`, `\`schedule.runAs\` ${JSON.stringify(schedule.runAs)} is not one of ${WORKFLOW_SCHEDULE_RUN_AS.map((v) => `'${v}'`).join(" | ")}`);
9988
+ return issue(`${path27}/runAs`, `\`schedule.runAs\` ${JSON.stringify(schedule.runAs)} is not one of ${WORKFLOW_SCHEDULE_RUN_AS.map((v) => `'${v}'`).join(" | ")}`);
9856
9989
  }
9857
9990
  switch (type) {
9858
9991
  case "cron": {
9859
9992
  if (typeof schedule.expression !== "string" || schedule.expression.trim().length === 0) {
9860
- return issue(`${path26}/expression`, "a { type: 'cron' } schedule needs a non-empty string `expression`");
9993
+ return issue(`${path27}/expression`, "a { type: 'cron' } schedule needs a non-empty string `expression`");
9861
9994
  }
9862
9995
  if (schedule.timezone !== void 0 && (typeof schedule.timezone !== "string" || schedule.timezone.length === 0)) {
9863
- return issue(`${path26}/timezone`, "a { type: 'cron' } schedule's `timezone`, when given, is a non-empty IANA string");
9996
+ return issue(`${path27}/timezone`, "a { type: 'cron' } schedule's `timezone`, when given, is a non-empty IANA string");
9864
9997
  }
9865
9998
  return [];
9866
9999
  }
9867
10000
  case "interval": {
9868
10001
  const s = schedule.seconds;
9869
10002
  if (typeof s !== "number" || !Number.isFinite(s) || s <= 0) {
9870
- return issue(`${path26}/seconds`, "a { type: 'interval' } schedule needs a positive number `seconds`");
10003
+ return issue(`${path27}/seconds`, "a { type: 'interval' } schedule needs a positive number `seconds`");
9871
10004
  }
9872
10005
  return [];
9873
10006
  }
9874
10007
  case "once": {
9875
10008
  if (typeof schedule.executeAt !== "string" || Number.isNaN(Date.parse(schedule.executeAt))) {
9876
- return issue(`${path26}/executeAt`, "a { type: 'once' } schedule needs an ISO-8601 string `executeAt`");
10009
+ return issue(`${path27}/executeAt`, "a { type: 'once' } schedule needs an ISO-8601 string `executeAt`");
9877
10010
  }
9878
10011
  return [];
9879
10012
  }
@@ -10316,15 +10449,15 @@ var init_dist2 = __esm({
10316
10449
  __name4(resolveDescriptor, "resolveDescriptor");
10317
10450
  __name(resolveMapping, "resolveMapping");
10318
10451
  __name4(resolveMapping, "resolveMapping");
10319
- fromInit = /* @__PURE__ */ __name4((path26) => ({
10452
+ fromInit = /* @__PURE__ */ __name4((path27) => ({
10320
10453
  initData: true,
10321
- path: path26
10454
+ path: path27
10322
10455
  }), "fromInit");
10323
- fromStep = /* @__PURE__ */ __name4((s, path26 = "") => {
10456
+ fromStep = /* @__PURE__ */ __name4((s, path27 = "") => {
10324
10457
  const idOf = /* @__PURE__ */ __name4((x) => typeof x === "string" ? x : x.id, "idOf");
10325
10458
  return {
10326
10459
  step: Array.isArray(s) ? s.map(idOf) : idOf(s),
10327
- path: path26
10460
+ path: path27
10328
10461
  };
10329
10462
  }, "fromStep");
10330
10463
  value = /* @__PURE__ */ __name4((v) => ({
@@ -10333,12 +10466,12 @@ var init_dist2 = __esm({
10333
10466
  template = /* @__PURE__ */ __name4((s) => ({
10334
10467
  template: s
10335
10468
  }), "template");
10336
- fromRequest = /* @__PURE__ */ __name4((path26) => ({
10337
- requestContextPath: path26
10469
+ fromRequest = /* @__PURE__ */ __name4((path27) => ({
10470
+ requestContextPath: path27
10338
10471
  }), "fromRequest");
10339
- rows = /* @__PURE__ */ __name4((s, path26, page) => ({
10472
+ rows = /* @__PURE__ */ __name4((s, path27, page) => ({
10340
10473
  step: typeof s === "string" ? s : s.id,
10341
- path: path26,
10474
+ path: path27,
10342
10475
  rows: page
10343
10476
  }), "rows");
10344
10477
  fromKnowledge = /* @__PURE__ */ __name4((k) => ({
@@ -10449,6 +10582,8 @@ var init_dist2 = __esm({
10449
10582
  __name4(validateApproverBlock, "validateApproverBlock");
10450
10583
  __name(liftRenderedApprover, "liftRenderedApprover");
10451
10584
  __name4(liftRenderedApprover, "liftRenderedApprover");
10585
+ __name(approverUsersOf, "approverUsersOf");
10586
+ __name4(approverUsersOf, "approverUsersOf");
10452
10587
  WORKSPACE_TEMPLATE_EXPR_RE = /^\$\{\s*(?:initData|input)\.([^}]+?)\s*\}$/;
10453
10588
  __name(workspaceTemplatePath, "workspaceTemplatePath");
10454
10589
  __name4(workspaceTemplatePath, "workspaceTemplatePath");
@@ -11105,7 +11240,9 @@ function stepNodeOf(s) {
11105
11240
  tier,
11106
11241
  workspace: s.workspace,
11107
11242
  jobResources: s.jobResources,
11108
- jobTools: s.jobTools
11243
+ jobTools: s.jobTools,
11244
+ luaApi: s.luaApi,
11245
+ target: s.target
11109
11246
  });
11110
11247
  }
11111
11248
  function materializeEntry(entry, steps) {
@@ -11337,13 +11474,13 @@ var init_workflow = __esm({
11337
11474
  }
11338
11475
  if ("step" in items && Array.isArray(items.step)) throw foreachItemsNotLowered("a fan-in fromStep([\u2026])");
11339
11476
  if (typeof items.path !== "string") throw foreachItemsNotLowered("value(\u2026) / template(\u2026) / fromRequest(\u2026) / fromKnowledge(\u2026)");
11340
- const path26 = items.path;
11341
- if (path26.startsWith("initData")) return {
11477
+ const path27 = items.path;
11478
+ if (path27.startsWith("initData")) return {
11342
11479
  initData: true,
11343
- path: path26 === "initData" ? "" : path26.slice("initData.".length)
11480
+ path: path27 === "initData" ? "" : path27.slice("initData.".length)
11344
11481
  };
11345
- if (path26.startsWith("stepResults.")) {
11346
- const rest = path26.slice("stepResults.".length);
11482
+ if (path27.startsWith("stepResults.")) {
11483
+ const rest = path27.slice("stepResults.".length);
11347
11484
  const dot = rest.indexOf(".");
11348
11485
  return dot === -1 ? {
11349
11486
  step: rest,
@@ -11353,7 +11490,7 @@ var init_workflow = __esm({
11353
11490
  path: rest.slice(dot + 1)
11354
11491
  };
11355
11492
  }
11356
- throw new LuaWorkflowBuildError("invalid-envelope", `foreach.items ref "${path26}" must point at initData.* or stepResults.*`);
11493
+ throw new LuaWorkflowBuildError("invalid-envelope", `foreach.items ref "${path27}" must point at initData.* or stepResults.*`);
11357
11494
  }, "refToDescriptor");
11358
11495
  __workflowCommitHook = {};
11359
11496
  LuaWorkflow = class {
@@ -11453,6 +11590,14 @@ var init_workflow = __esm({
11453
11590
  const tier = s.tier ?? (s.workspace ? "job" : void 0);
11454
11591
  if (s.workspace && s.tier !== void 0 && s.tier !== "job") throw new LuaWorkflowBuildError("workspace-requires-job-tier", `"${s.id}": a step mounting a workspace must be tier:'job'`);
11455
11592
  if (s.jobTools && tier !== "job") throw new LuaWorkflowBuildError("cap-exceeded", `"${s.id}": jobTools require tier:'job' (job-tools-require-job-tier)`);
11593
+ if (s.luaApi !== void 0) {
11594
+ const problem = workflowJobLuaApiProblem(s.luaApi, "code", tier);
11595
+ if (problem) throw new LuaWorkflowBuildError("lua-api-invalid", `"${s.id}": ${problem}`);
11596
+ }
11597
+ if (s.target !== void 0) {
11598
+ const problem = workflowJobTargetProblem(s.target, void 0, s.luaApi);
11599
+ if (problem) throw new LuaWorkflowBuildError("target-invalid", `"${s.id}": ${problem}`);
11600
+ }
11456
11601
  assertTimeout({
11457
11602
  id: s.id,
11458
11603
  timeoutSeconds: s.timeoutSeconds,
@@ -11709,7 +11854,7 @@ var init_workflow = __esm({
11709
11854
  }
11710
11855
  if (opts.target !== void 0) {
11711
11856
  const problem = workflowJobTargetProblem(opts.target, opts.plugins);
11712
- if (problem) throw new LuaWorkflowBuildError("plugins-invalid", `"${id2}": ${problem}`);
11857
+ if (problem) throw new LuaWorkflowBuildError("target-invalid", `"${id2}": ${problem}`);
11713
11858
  }
11714
11859
  assertTimeout({
11715
11860
  id: id2,
@@ -12165,6 +12310,7 @@ var init_types = __esm({
12165
12310
  PrimitiveKind2["DEVICE_TRIGGER"] = "device-trigger";
12166
12311
  PrimitiveKind2["VOICE"] = "voice";
12167
12312
  PrimitiveKind2["WORKFLOW"] = "workflow";
12313
+ PrimitiveKind2["WEB_APP"] = "web-app";
12168
12314
  return PrimitiveKind2;
12169
12315
  })({});
12170
12316
  }
@@ -13304,12 +13450,12 @@ var init_dist3 = __esm({
13304
13450
  this.options = options;
13305
13451
  this.fetchFn = options.fetch ?? fetch;
13306
13452
  }
13307
- url(path26) {
13453
+ url(path27) {
13308
13454
  const base = this.options.baseUrl.replace(/\/$/, "");
13309
- return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${path26}`;
13455
+ return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${path27}`;
13310
13456
  }
13311
- async json(method, path26, body) {
13312
- const endpoint = this.url(path26);
13457
+ async json(method, path27, body) {
13458
+ const endpoint = this.url(path27);
13313
13459
  const res = await this.fetchFn(endpoint, {
13314
13460
  method,
13315
13461
  headers: {
@@ -13328,7 +13474,7 @@ var init_dist3 = __esm({
13328
13474
  } catch {
13329
13475
  text2 = void 0;
13330
13476
  }
13331
- throw new BackupHttpError(`Backup request failed: ${method} ${path26} \u2192 ${res.status} ${res.statusText}`, res.status, endpoint, text2);
13477
+ throw new BackupHttpError(`Backup request failed: ${method} ${path27} \u2192 ${res.status} ${res.statusText}`, res.status, endpoint, text2);
13332
13478
  }
13333
13479
  const text = await res.text();
13334
13480
  if (!text) return void 0;
@@ -13475,12 +13621,12 @@ var init_backup_api_service = __esm({
13475
13621
  * @returns Promise resolving to missing/existing hash lists
13476
13622
  */
13477
13623
  async checkBlobsExist(hashes) {
13478
- const path26 = `/developer/agents/${this.agentId}/backup/check-blobs`;
13624
+ const path27 = `/developer/agents/${this.agentId}/backup/check-blobs`;
13479
13625
  if (hashes.length <= CHECK_BLOBS_MAX_HASHES) {
13480
13626
  const data = {
13481
13627
  hashes
13482
13628
  };
13483
- return this.httpPost(path26, data, {});
13629
+ return this.httpPost(path27, data, {});
13484
13630
  }
13485
13631
  const merged = {
13486
13632
  missing: [],
@@ -13492,7 +13638,7 @@ var init_backup_api_service = __esm({
13492
13638
  const data = {
13493
13639
  hashes: hashes.slice(i, i + CHECK_BLOBS_MAX_HASHES)
13494
13640
  };
13495
- const part = await this.httpPost(path26, data, {});
13641
+ const part = await this.httpPost(path27, data, {});
13496
13642
  if (!part.success || !part.data) return part;
13497
13643
  merged.missing.push(...part.data.missing);
13498
13644
  merged.existing.push(...part.data.existing);
@@ -20563,8 +20709,8 @@ var init_voice_plugin = __esm({
20563
20709
  }, "isMissingTopLevelRequired");
20564
20710
  for (const issue of parsed.error.issues) {
20565
20711
  if (isMissingTopLevelRequired(issue)) continue;
20566
- const path26 = issue.path.length > 0 ? issue.path.join(".") : "<root>";
20567
- errors.push(validationError(`Voice config invalid at \`${path26}\`: ${issue.message}`, {
20712
+ const path27 = issue.path.length > 0 ? issue.path.join(".") : "<root>";
20713
+ errors.push(validationError(`Voice config invalid at \`${path27}\`: ${issue.message}`, {
20568
20714
  line
20569
20715
  }));
20570
20716
  }
@@ -23045,8 +23191,9 @@ function metaOf(node, sources) {
23045
23191
  const jobTools = n2.toolScope?.jobTools;
23046
23192
  pick("jobTools", jobTools);
23047
23193
  pick("plugins", n2.plugins);
23048
- pick("target", n2.target);
23049
23194
  }
23195
+ if (n2.type === "agent" || n2.type === "step") pick("target", n2.target);
23196
+ if (n2.type === "step") pick("luaApi", n2.luaApi);
23050
23197
  if (n2.type === "approval") {
23051
23198
  pick("editedPayloadSchema", n2.editedPayloadSchema);
23052
23199
  pick("itemsPath", n2.itemsPath);
@@ -23948,6 +24095,402 @@ ${firstBundleFrame(vmResult.error.stack)}` : ""}`,
23948
24095
  }
23949
24096
  });
23950
24097
 
24098
+ // src/compiler/plugins/web-app.plugin.ts
24099
+ import path9 from "path";
24100
+ import { Node as Node19 } from "ts-morph";
24101
+ function resolveValue2(node) {
24102
+ let cur = unwrapExpression(node);
24103
+ if (cur && Node19.isIdentifier(cur)) cur = unwrapExpression(resolveIdentifier(cur));
24104
+ return cur;
24105
+ }
24106
+ function propertyValue(obj, name) {
24107
+ const prop = obj.getProperty(name);
24108
+ if (!prop) return void 0;
24109
+ if (Node19.isShorthandPropertyAssignment(prop)) return resolveValue2(prop.getNameNode());
24110
+ if (Node19.isPropertyAssignment(prop)) return resolveValue2(prop.getInitializer());
24111
+ return void 0;
24112
+ }
24113
+ function literalKey(prop) {
24114
+ if (!Node19.isPropertyAssignment(prop) && !Node19.isShorthandPropertyAssignment(prop)) return void 0;
24115
+ const nameNode = prop.getNameNode();
24116
+ if (Node19.isStringLiteral(nameNode) || Node19.isNoSubstitutionTemplateLiteral(nameNode)) {
24117
+ return nameNode.getLiteralValue();
24118
+ }
24119
+ if (Node19.isIdentifier(nameNode) || Node19.isNumericLiteral(nameNode)) return nameNode.getText();
24120
+ return void 0;
24121
+ }
24122
+ function isLuaCliRouteCall(call) {
24123
+ if (!Node19.isCallExpression(call)) return false;
24124
+ const callee = call.getExpression();
24125
+ if (!Node19.isIdentifier(callee) || callee.getText() !== "route") return false;
24126
+ return call.getSourceFile().getImportDeclarations().some((decl) => LUA_CLI_SPECIFIERS.has(decl.getModuleSpecifierValue()) && decl.getNamedImports().some((n2) => n2.getName() === "route" && !n2.getAliasNode()));
24127
+ }
24128
+ function aliasedHelpers(files) {
24129
+ const out = [];
24130
+ for (const sf of files) {
24131
+ for (const decl of sf.getImportDeclarations()) {
24132
+ if (!LUA_CLI_SPECIFIERS.has(decl.getModuleSpecifierValue())) continue;
24133
+ for (const n2 of decl.getNamedImports()) {
24134
+ const alias = n2.getAliasNode()?.getText();
24135
+ if (alias && INJECTED_HELPERS.has(n2.getName())) {
24136
+ out.push(`${n2.getName()} as ${alias} (${path9.basename(sf.getFilePath())})`);
24137
+ }
24138
+ }
24139
+ }
24140
+ }
24141
+ return out;
24142
+ }
24143
+ function readRoutes(config) {
24144
+ const routes = [];
24145
+ const unreadable = [];
24146
+ const duplicates = [];
24147
+ const files = /* @__PURE__ */ new Set([
24148
+ config.getSourceFile()
24149
+ ]);
24150
+ const seen = /* @__PURE__ */ new Set();
24151
+ const routesNode = propertyValue(config, "routes");
24152
+ if (!routesNode) return {
24153
+ routes,
24154
+ unreadable,
24155
+ duplicates,
24156
+ files
24157
+ };
24158
+ if (!Node19.isObjectLiteralExpression(routesNode)) {
24159
+ return {
24160
+ routes,
24161
+ unreadable: [
24162
+ routesNode.getText().slice(0, 60)
24163
+ ],
24164
+ duplicates,
24165
+ files
24166
+ };
24167
+ }
24168
+ files.add(routesNode.getSourceFile());
24169
+ for (const prop of routesNode.getProperties()) {
24170
+ const key = literalKey(prop);
24171
+ if (key === void 0) {
24172
+ unreadable.push(prop.getText().slice(0, 60));
24173
+ continue;
24174
+ }
24175
+ if (seen.has(key)) {
24176
+ duplicates.push(key);
24177
+ continue;
24178
+ }
24179
+ seen.add(key);
24180
+ const value3 = Node19.isShorthandPropertyAssignment(prop) ? resolveValue2(prop.getNameNode()) : Node19.isPropertyAssignment(prop) ? resolveValue2(prop.getInitializer()) : void 0;
24181
+ if (value3) files.add(value3.getSourceFile());
24182
+ if (value3 && isLuaCliRouteCall(value3) && Node19.isCallExpression(value3)) {
24183
+ const arg = resolveValue2(value3.getArguments()[0]);
24184
+ if (arg && Node19.isObjectLiteralExpression(arg)) {
24185
+ routes.push({
24186
+ key,
24187
+ description: extractStringProperty(arg, "description"),
24188
+ definition: arg
24189
+ });
24190
+ continue;
24191
+ }
24192
+ }
24193
+ if (value3 && (Node19.isArrowFunction(value3) || Node19.isFunctionExpression(value3) || Node19.isFunctionDeclaration(value3))) {
24194
+ routes.push({
24195
+ key
24196
+ });
24197
+ continue;
24198
+ }
24199
+ unreadable.push(key);
24200
+ }
24201
+ return {
24202
+ routes,
24203
+ unreadable,
24204
+ duplicates,
24205
+ files
24206
+ };
24207
+ }
24208
+ function responseStatuses(definition) {
24209
+ const responses = definition ? propertyValue(definition, "responses") : void 0;
24210
+ if (!responses || !Node19.isObjectLiteralExpression(responses)) return [];
24211
+ const out = [];
24212
+ for (const prop of responses.getProperties()) {
24213
+ const status = Number(literalKey(prop));
24214
+ const node = Node19.isPropertyAssignment(prop) ? prop.getInitializer() : void 0;
24215
+ if (Number.isInteger(status) && node) out.push({
24216
+ status,
24217
+ node
24218
+ });
24219
+ }
24220
+ return out;
24221
+ }
24222
+ function pageImportsOf(definitionFile, files, pagesRoot) {
24223
+ if (!pagesRoot) return [];
24224
+ const pagesDir = path9.resolve(path9.dirname(definitionFile.getFilePath()), pagesRoot) + path9.sep;
24225
+ const out = [];
24226
+ for (const sourceFile of files) {
24227
+ out.push(...valueImportsInto(sourceFile, pagesDir));
24228
+ }
24229
+ return out;
24230
+ }
24231
+ function valueImportsInto(sourceFile, pagesDir) {
24232
+ const out = [];
24233
+ for (const decl of sourceFile.getImportDeclarations()) {
24234
+ if (decl.isTypeOnly()) continue;
24235
+ const named = decl.getNamedImports();
24236
+ const valueBinding = !!decl.getDefaultImport() || !!decl.getNamespaceImport() || named.some((n2) => !n2.isTypeOnly()) || !decl.getImportClause();
24237
+ if (!valueBinding) continue;
24238
+ const specifier = decl.getModuleSpecifierValue();
24239
+ const target = decl.getModuleSpecifierSourceFile()?.getFilePath() ?? (specifier.startsWith(".") ? path9.resolve(path9.dirname(sourceFile.getFilePath()), specifier) : void 0);
24240
+ if (target && (target + path9.sep).startsWith(pagesDir)) out.push(specifier);
24241
+ }
24242
+ return out;
24243
+ }
24244
+ function isOutsideProject(sourceFile, pagesRoot) {
24245
+ if (path9.isAbsolute(pagesRoot)) return true;
24246
+ const configFile = sourceFile.getProject().getCompilerOptions().configFilePath;
24247
+ const projectRoot = typeof configFile === "string" ? path9.dirname(configFile) : void 0;
24248
+ if (!projectRoot) return false;
24249
+ const rel = path9.relative(projectRoot, path9.resolve(path9.dirname(sourceFile.getFilePath()), pagesRoot));
24250
+ return rel === ".." || rel.startsWith(`..${path9.sep}`) || path9.isAbsolute(rel);
24251
+ }
24252
+ function findConfig(sourceFile, exportName) {
24253
+ const argOf = /* @__PURE__ */ __name((expr) => {
24254
+ const e = unwrapExpression(expr);
24255
+ if (!e || !(Node19.isCallExpression(e) || Node19.isNewExpression(e))) return void 0;
24256
+ const arg = e.getArguments()[0];
24257
+ return arg && Node19.isObjectLiteralExpression(arg) ? arg : void 0;
24258
+ }, "argOf");
24259
+ if (exportName === "default") {
24260
+ for (const assignment of sourceFile.getExportAssignments()) {
24261
+ const arg = argOf(assignment.getExpression());
24262
+ if (arg) return arg;
24263
+ }
24264
+ return void 0;
24265
+ }
24266
+ return argOf(sourceFile.getVariableDeclaration(exportName)?.getInitializer());
24267
+ }
24268
+ var WEB_APP_NAME_PATTERN, ROUTE_KEY_PATTERN, MAX_ROUTES, SCHEMA_PARTS, LUA_CLI_SPECIFIERS, INJECTED_HELPERS, schemaKey, WebAppPlugin;
24269
+ var init_web_app_plugin = __esm({
24270
+ "src/compiler/plugins/web-app.plugin.ts"() {
24271
+ "use strict";
24272
+ init_dist();
24273
+ init_base();
24274
+ init_ast_helpers();
24275
+ init_schema_converter();
24276
+ WEB_APP_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
24277
+ ROUTE_KEY_PATTERN = new RegExp(`^(${WEB_ROUTE_METHODS.join("|")}) (/\\S*)$`);
24278
+ MAX_ROUTES = 200;
24279
+ SCHEMA_PARTS = [
24280
+ "params",
24281
+ "query",
24282
+ "body"
24283
+ ];
24284
+ LUA_CLI_SPECIFIERS = /* @__PURE__ */ new Set([
24285
+ "lua-cli",
24286
+ "lua-cli/skill",
24287
+ "lua-cli/voice"
24288
+ ]);
24289
+ INJECTED_HELPERS = /* @__PURE__ */ new Set([
24290
+ "route",
24291
+ "json"
24292
+ ]);
24293
+ __name(resolveValue2, "resolveValue");
24294
+ __name(propertyValue, "propertyValue");
24295
+ __name(literalKey, "literalKey");
24296
+ __name(isLuaCliRouteCall, "isLuaCliRouteCall");
24297
+ __name(aliasedHelpers, "aliasedHelpers");
24298
+ __name(readRoutes, "readRoutes");
24299
+ __name(responseStatuses, "responseStatuses");
24300
+ __name(pageImportsOf, "pageImportsOf");
24301
+ __name(valueImportsInto, "valueImportsInto");
24302
+ __name(isOutsideProject, "isOutsideProject");
24303
+ __name(findConfig, "findConfig");
24304
+ schemaKey = /* @__PURE__ */ __name((routeKey, part) => `route:${routeKey}:${part}`, "schemaKey");
24305
+ WebAppPlugin = class extends BasePlugin {
24306
+ static {
24307
+ __name(this, "WebAppPlugin");
24308
+ }
24309
+ kind = "web-app";
24310
+ displayName = "Web app";
24311
+ defineFunction = "defineWebApp";
24312
+ legacyClassNames = [
24313
+ "LuaWebApp"
24314
+ ];
24315
+ crossFileRewrite = {
24316
+ copyAllFields: true
24317
+ };
24318
+ extractFromConfig(config, exportName, sourcePath, position, pattern) {
24319
+ const common = this.extractCommonFields(config, exportName, sourcePath, position);
24320
+ if (!common) return null;
24321
+ const pages = extractObjectProperty(config, "pages");
24322
+ const pagesNode = propertyValue(config, "pages");
24323
+ const pagesRoot = typeof pages?.root === "string" ? pages.root : pagesNode && Node19.isObjectLiteralExpression(pagesNode) ? extractStringProperty(pagesNode, "root") : void 0;
24324
+ const { routes, unreadable, duplicates, files } = readRoutes(config);
24325
+ const sourceFile = config.getSourceFile();
24326
+ return {
24327
+ kind: this.kind,
24328
+ ...common,
24329
+ metadata: {
24330
+ pattern,
24331
+ pagesRoot,
24332
+ spa: typeof pages?.spa === "boolean" ? pages.spa : void 0,
24333
+ nav: Array.isArray(pages?.nav) ? pages.nav : void 0,
24334
+ csp: pages?.csp && typeof pages.csp === "object" ? pages.csp : void 0,
24335
+ branding: extractObjectProperty(config, "branding"),
24336
+ routes: routes.map((r) => {
24337
+ const match = ROUTE_KEY_PATTERN.exec(r.key);
24338
+ return {
24339
+ key: r.key,
24340
+ method: match ? match[1] : "",
24341
+ path: match ? match[2] : "",
24342
+ ...r.description ? {
24343
+ description: r.description
24344
+ } : {},
24345
+ has: {
24346
+ params: !!r.definition && hasProperty(r.definition, "params"),
24347
+ query: !!r.definition && hasProperty(r.definition, "query"),
24348
+ body: !!r.definition && hasProperty(r.definition, "body"),
24349
+ responses: responseStatuses(r.definition).map((x) => x.status)
24350
+ }
24351
+ };
24352
+ }),
24353
+ hasFetch: hasProperty(config, "fetch"),
24354
+ unreadableRoutes: unreadable,
24355
+ duplicateRoutes: duplicates,
24356
+ aliasedHelpers: aliasedHelpers(files),
24357
+ pagesRootOutsideProject: !!pagesRoot && isOutsideProject(sourceFile, pagesRoot),
24358
+ pageImports: pageImportsOf(sourceFile, files, pagesRoot)
24359
+ }
24360
+ };
24361
+ }
24362
+ validate(metadata) {
24363
+ const { errors, warnings } = this.baseValidation(metadata);
24364
+ const meta = metadata.metadata;
24365
+ const at = {
24366
+ line: metadata.line
24367
+ };
24368
+ if (metadata.name && !WEB_APP_NAME_PATTERN.test(metadata.name)) {
24369
+ errors.push(validationError(`Web app name must match ${WEB_APP_NAME_PATTERN} (lower-case letters, digits, dashes)`, at));
24370
+ }
24371
+ if (!meta.pagesRoot) {
24372
+ errors.push(validationError("Web app `pages.root` must be a string literal naming the Vite project directory", at));
24373
+ }
24374
+ for (const entry of meta.unreadableRoutes) {
24375
+ errors.push(validationError(`Web app route ${JSON.stringify(entry)} cannot be read at compile time: use a literal key with \`route({...})\` or a handler function`, at));
24376
+ }
24377
+ for (const key of meta.duplicateRoutes) {
24378
+ errors.push(validationError(`Web app route ${JSON.stringify(key)} is declared more than once; only the last would run`, at));
24379
+ }
24380
+ for (const entry of meta.aliasedHelpers) {
24381
+ errors.push(validationError(`Web app imports \`${entry}\` from lua-cli: import \`route\` and \`json\` under their own names (the bundle provides them only as such)`, at));
24382
+ }
24383
+ if (meta.pagesRootOutsideProject) {
24384
+ errors.push(validationError(`Web app \`pages.root\` ${JSON.stringify(meta.pagesRoot)} must be a relative path to a directory inside the project`, at));
24385
+ }
24386
+ for (const r of meta.routes) {
24387
+ if (!r.method) {
24388
+ errors.push(validationError(`Web app route key ${JSON.stringify(r.key)} must look like 'GET /path' (${WEB_ROUTE_METHODS.join(", ")})`, at));
24389
+ }
24390
+ }
24391
+ if (meta.routes.length > MAX_ROUTES) {
24392
+ errors.push(validationError(`Web app declares ${meta.routes.length} routes; the limit is ${MAX_ROUTES}`, at));
24393
+ }
24394
+ if (meta.routes.length === 0 && !meta.hasFetch && meta.unreadableRoutes.length === 0) {
24395
+ errors.push(validationError("Web app must declare at least one route or a `fetch` handler", at));
24396
+ }
24397
+ for (const specifier of meta.pageImports) {
24398
+ errors.push(validationError(`Web app definition imports ${JSON.stringify(specifier)} from its pages directory: route code runs in the sandbox, pages in the browser. Use \`import type\` for shared types.`, at));
24399
+ }
24400
+ return {
24401
+ valid: errors.length === 0,
24402
+ errors,
24403
+ warnings
24404
+ };
24405
+ }
24406
+ getRuntimeValidation() {
24407
+ return `
24408
+ const app = primitive.primitive;
24409
+ if (!app || (typeof app.fetch !== 'function' && (!app.routes || typeof app.routes !== 'object'))) {
24410
+ throw new Error('[Lua] Invalid web-app artifact: missing routes or fetch');
24411
+ }`;
24412
+ }
24413
+ /** JSON Schema per route part, keyed by `schemaKey`. A schema that cannot be converted is left out, not fatal. */
24414
+ async extractSchemas(metadata, project) {
24415
+ const sourceFile = project.getSourceFile(metadata.sourcePath);
24416
+ const config = sourceFile && findConfig(sourceFile, metadata.exportName);
24417
+ if (!config) return void 0;
24418
+ const schemas = {};
24419
+ const convert = /* @__PURE__ */ __name(async (key, node, label2) => {
24420
+ if (!node) return;
24421
+ try {
24422
+ schemas[key] = await zodToJsonSchema2(node);
24423
+ } catch (error) {
24424
+ console.warn(`Warning: Could not convert ${label2} for web app ${metadata.name}:`, error);
24425
+ }
24426
+ }, "convert");
24427
+ for (const r of readRoutes(config).routes) {
24428
+ if (!r.definition) continue;
24429
+ for (const part of SCHEMA_PARTS) {
24430
+ await convert(schemaKey(r.key, part), propertyValue(r.definition, part), `${r.key} ${part}`);
24431
+ }
24432
+ for (const { status, node } of responseStatuses(r.definition)) {
24433
+ await convert(schemaKey(r.key, `responses:${status}`), node, `${r.key} response ${status}`);
24434
+ }
24435
+ }
24436
+ return Object.keys(schemas).length > 0 ? schemas : void 0;
24437
+ }
24438
+ toManifestEntry(compiled) {
24439
+ const meta = compiled.metadata;
24440
+ const schemas = compiled.schemas ?? {};
24441
+ const routes = meta.routes.map((r) => {
24442
+ const part = /* @__PURE__ */ __name((p) => schemas[schemaKey(r.key, p)], "part");
24443
+ const responses = {};
24444
+ for (const status of r.has.responses) {
24445
+ const s = part(`responses:${status}`);
24446
+ if (s) responses[String(status)] = s;
24447
+ }
24448
+ const routeSchemas = {
24449
+ ...part("params") ? {
24450
+ params: part("params")
24451
+ } : {},
24452
+ ...part("query") ? {
24453
+ query: part("query")
24454
+ } : {},
24455
+ ...part("body") ? {
24456
+ body: part("body")
24457
+ } : {},
24458
+ ...Object.keys(responses).length ? {
24459
+ responses
24460
+ } : {}
24461
+ };
24462
+ return {
24463
+ key: r.key,
24464
+ method: r.method,
24465
+ path: r.path,
24466
+ ...r.description ? {
24467
+ description: r.description
24468
+ } : {},
24469
+ ...Object.keys(routeSchemas).length ? {
24470
+ schemas: routeSchemas
24471
+ } : {}
24472
+ };
24473
+ });
24474
+ return {
24475
+ ...this.baseManifestFields(compiled),
24476
+ kind: "web-app",
24477
+ pagesRoot: meta.pagesRoot ?? ".",
24478
+ spa: meta.spa !== false,
24479
+ nav: meta.nav ?? [],
24480
+ ...meta.csp ? {
24481
+ csp: meta.csp
24482
+ } : {},
24483
+ ...meta.branding ? {
24484
+ branding: meta.branding
24485
+ } : {},
24486
+ routes,
24487
+ hasFetch: meta.hasFetch
24488
+ };
24489
+ }
24490
+ };
24491
+ }
24492
+ });
24493
+
23951
24494
  // src/compiler/plugins/registry.ts
23952
24495
  function getAllDefineFunctions() {
23953
24496
  return pluginRegistry.getAll().map((p) => p.defineFunction);
@@ -23972,6 +24515,7 @@ var init_registry = __esm({
23972
24515
  init_device_trigger_plugin();
23973
24516
  init_voice_plugin();
23974
24517
  init_workflow_plugin();
24518
+ init_web_app_plugin();
23975
24519
  PluginRegistry = class {
23976
24520
  static {
23977
24521
  __name(this, "PluginRegistry");
@@ -23991,6 +24535,7 @@ var init_registry = __esm({
23991
24535
  this.register(new DeviceTriggerPlugin());
23992
24536
  this.register(new VoicePlugin());
23993
24537
  this.register(new WorkflowPlugin());
24538
+ this.register(new WebAppPlugin());
23994
24539
  }
23995
24540
  /**
23996
24541
  * Register a plugin.
@@ -24041,13 +24586,13 @@ var init_registry = __esm({
24041
24586
 
24042
24587
  // src/compiler/bundler.ts
24043
24588
  import fs7 from "fs/promises";
24044
- import path9 from "path";
24589
+ import path10 from "path";
24045
24590
  import crypto4 from "crypto";
24046
24591
  import { build } from "esbuild";
24047
24592
  function nodeCapabilityUnavailableMessage(specifier) {
24048
24593
  return `${NODE_CAPABILITY_UNAVAILABLE}: \`${specifier}\` is not available to a workflow code step \u2014 on the Job tier run a command through \`ctx.exec(['git', 'status'])\` or \`ctx.$\`git status\`\` (allow-listed binaries, argv only, no shell; see docs/workflows/workspaces-and-long-steps.md); a worker-tier step has no process access at all`;
24049
24594
  }
24050
- var WORKFLOW_BUILDER_SUBPATH, WORKFLOW_BUILDER_INJECT_FILE, NODE_CAPABILITY_UNAVAILABLE, NODE_CAPABILITY_GUARDED, Bundler;
24595
+ var WORKFLOW_BUILDER_SUBPATH, WORKFLOW_BUILDER_INJECT_FILE, WEB_APP_RUNTIME_INJECT_FILE, WEB_APP_RUNTIME_INJECT_SOURCE, NODE_CAPABILITY_UNAVAILABLE, NODE_CAPABILITY_GUARDED, Bundler;
24051
24596
  var init_bundler = __esm({
24052
24597
  "src/compiler/bundler.ts"() {
24053
24598
  "use strict";
@@ -24058,6 +24603,23 @@ var init_bundler = __esm({
24058
24603
  init_package_root();
24059
24604
  WORKFLOW_BUILDER_SUBPATH = "lua-cli/workflow-builder";
24060
24605
  WORKFLOW_BUILDER_INJECT_FILE = "workflow-builder.inject.mjs";
24606
+ WEB_APP_RUNTIME_INJECT_FILE = "web-app-runtime.inject.mjs";
24607
+ WEB_APP_RUNTIME_INJECT_SOURCE = `// AUTO-GENERATED by lua-cli (compiler/bundler.ts) \u2014 esbuild inject shim for web-app bundles.
24608
+ export function route(def) {
24609
+ if (!def || typeof def.handler !== 'function') throw new Error('route() requires a \`handler\` function.');
24610
+ return def;
24611
+ }
24612
+ export function json(data, status = 200, headers = {}) {
24613
+ const hasBody = data !== undefined && status !== 204 && status !== 304;
24614
+ return new Response(hasBody ? JSON.stringify(data) : null, {
24615
+ status,
24616
+ headers: hasBody ? { 'content-type': 'application/json', ...headers } : headers,
24617
+ });
24618
+ }
24619
+ export function defineWebApp(config) {
24620
+ return config;
24621
+ }
24622
+ `;
24061
24623
  NODE_CAPABILITY_UNAVAILABLE = "node-capability-unavailable";
24062
24624
  NODE_CAPABILITY_GUARDED = /^(node:)?(child_process|worker_threads|cluster)$/;
24063
24625
  __name(nodeCapabilityUnavailableMessage, "nodeCapabilityUnavailableMessage");
@@ -24126,9 +24688,9 @@ var init_bundler = __esm({
24126
24688
  * Bundle a primitive's entry point using esbuild.
24127
24689
  */
24128
24690
  async bundle(metadata, entryPointCode) {
24129
- const tempDir = path9.join(this.options.outDir, ".temp");
24130
- const outfile = path9.join(tempDir, `${metadata.kind}-${metadata.name}.bundle.js`);
24131
- const sourceDir = path9.dirname(metadata.sourcePath);
24691
+ const tempDir = path10.join(this.options.outDir, ".temp");
24692
+ const outfile = path10.join(tempDir, `${metadata.kind}-${metadata.name}.bundle.js`);
24693
+ const sourceDir = path10.dirname(metadata.sourcePath);
24132
24694
  if (this.options.debug) {
24133
24695
  this.verbose(` Source: ${metadata.sourcePath}`);
24134
24696
  this.verbose(` Output: ${outfile}`);
@@ -24138,6 +24700,8 @@ var init_bundler = __esm({
24138
24700
  const selfContainedWorkflow = metadata.kind === "workflow";
24139
24701
  const inject = selfContainedWorkflow ? [
24140
24702
  await this.writeWorkflowBuilderInject(tempDir)
24703
+ ] : metadata.kind === "web-app" ? [
24704
+ await this.writeWebAppRuntimeInject(tempDir)
24141
24705
  ] : [];
24142
24706
  const plugins = selfContainedWorkflow ? [
24143
24707
  this.createNodeCapabilityGuardPlugin(),
@@ -24205,7 +24769,7 @@ var init_bundler = __esm({
24205
24769
  * untouched — the same scoping rules as the stripped import would have had.
24206
24770
  */
24207
24771
  async writeWorkflowBuilderInject(tempDir) {
24208
- const injectPath = path9.join(tempDir, WORKFLOW_BUILDER_INJECT_FILE);
24772
+ const injectPath = path10.join(tempDir, WORKFLOW_BUILDER_INJECT_FILE);
24209
24773
  const contents = `// AUTO-GENERATED by lua-cli (compiler/bundler.ts) \u2014 esbuild inject shim for graph-form workflow bundles (F5).
24210
24774
  export { ${WORKFLOW_SHIM_NAMES.join(", ")} } from ${JSON.stringify(this.workflowBuilderModule)};
24211
24775
  `;
@@ -24215,6 +24779,15 @@ export { ${WORKFLOW_SHIM_NAMES.join(", ")} } from ${JSON.stringify(this.workflow
24215
24779
  await fs7.writeFile(injectPath, contents, "utf-8");
24216
24780
  return injectPath;
24217
24781
  }
24782
+ /** Write the esbuild `inject` module for a web-app bundle (see `WEB_APP_RUNTIME_INJECT_SOURCE`). */
24783
+ async writeWebAppRuntimeInject(tempDir) {
24784
+ const injectPath = path10.join(tempDir, WEB_APP_RUNTIME_INJECT_FILE);
24785
+ await fs7.mkdir(tempDir, {
24786
+ recursive: true
24787
+ });
24788
+ await fs7.writeFile(injectPath, WEB_APP_RUNTIME_INJECT_SOURCE, "utf-8");
24789
+ return injectPath;
24790
+ }
24218
24791
  /**
24219
24792
  * F5 companion plugin for workflow bundles. The bundled builder pulls in
24220
24793
  * `zod-to-json-schema`, whose own `import … from 'zod/v3'` would otherwise
@@ -24248,8 +24821,8 @@ export { ${WORKFLOW_SHIM_NAMES.join(", ")} } from ${JSON.stringify(this.workflow
24248
24821
  */
24249
24822
  isWorkflowBuilderSource(filePath) {
24250
24823
  if (filePath === this.workflowBuilderModule) return true;
24251
- if (filePath.endsWith(path9.join("dist", "workflow-builder.js"))) return true;
24252
- const srcDir = path9.join(getPackageRoot(), "src") + path9.sep;
24824
+ if (filePath.endsWith(path10.join("dist", "workflow-builder.js"))) return true;
24825
+ const srcDir = path10.join(getPackageRoot(), "src") + path10.sep;
24253
24826
  return this.workflowBuilderModule.startsWith(srcDir) && filePath.startsWith(srcDir);
24254
24827
  }
24255
24828
  /**
@@ -24290,14 +24863,14 @@ export { ${WORKFLOW_SHIM_NAMES.join(", ")} } from ${JSON.stringify(this.workflow
24290
24863
  const bundler = this;
24291
24864
  const sourcePath = metadata.sourcePath;
24292
24865
  const exportName = metadata.exportName;
24293
- const sourceDir = path9.dirname(sourcePath);
24866
+ const sourceDir = path10.dirname(sourcePath);
24294
24867
  return {
24295
24868
  name: "lua-virtual-source",
24296
24869
  setup(build2) {
24297
24870
  build2.onResolve({
24298
24871
  filter: /.*/
24299
24872
  }, (args2) => {
24300
- const resolved = args2.path.startsWith(".") ? path9.resolve(args2.resolveDir, args2.path) : args2.path;
24873
+ const resolved = args2.path.startsWith(".") ? path10.resolve(args2.resolveDir, args2.path) : args2.path;
24301
24874
  const normalizedResolved = resolved.replace(/\.(ts|tsx|js|jsx)$/, "");
24302
24875
  const normalizedSource = sourcePath.replace(/\.(ts|tsx|js|jsx)$/, "");
24303
24876
  if (normalizedResolved === normalizedSource) {
@@ -24314,7 +24887,7 @@ export { ${WORKFLOW_SHIM_NAMES.join(", ")} } from ${JSON.stringify(this.workflow
24314
24887
  }, async () => {
24315
24888
  const sourceFile = bundler.project.getSourceFile(sourcePath);
24316
24889
  let content = sourceFile?.getText() ?? await fs7.readFile(sourcePath, "utf-8");
24317
- content = bundler.stripLuaCliImportsAST(content, path9.basename(sourcePath));
24890
+ content = bundler.stripLuaCliImportsAST(content, path10.basename(sourcePath));
24318
24891
  const virtualContent = metadata.isDefaultExport ? content : `${content}
24319
24892
  export { ${exportName} as __lua_target__ };
24320
24893
  `;
@@ -24349,12 +24922,12 @@ export { ${exportName} as __lua_target__ };
24349
24922
  return null;
24350
24923
  }
24351
24924
  try {
24352
- const modifiedContents = stripImports(contents, path9.basename(args2.path));
24925
+ const modifiedContents = stripImports(contents, path10.basename(args2.path));
24353
24926
  if (modifiedContents !== contents) {
24354
24927
  return {
24355
24928
  contents: modifiedContents,
24356
24929
  loader: args2.path.endsWith(".ts") || args2.path.endsWith(".tsx") ? "ts" : "js",
24357
- resolveDir: path9.dirname(args2.path)
24930
+ resolveDir: path10.dirname(args2.path)
24358
24931
  };
24359
24932
  }
24360
24933
  return null;
@@ -24410,8 +24983,8 @@ var init_bundle_hazards = __esm({
24410
24983
  });
24411
24984
 
24412
24985
  // src/compiler/agent-traverser.ts
24413
- import { Project as Project2, Node as Node19 } from "ts-morph";
24414
- import path10 from "path";
24986
+ import { Project as Project2, Node as Node20 } from "ts-morph";
24987
+ import path11 from "path";
24415
24988
  import fs8 from "fs";
24416
24989
  var PRIMITIVE_TYPES, AgentTraverser;
24417
24990
  var init_agent_traverser = __esm({
@@ -24474,6 +25047,11 @@ var init_agent_traverser = __esm({
24474
25047
  kind: "workflow",
24475
25048
  configProperty: "workflows",
24476
25049
  resolveNested: true
25050
+ },
25051
+ // Lua Apps (PRD 7.1): `webApps: [opsDashboard]`. Inert for any agent without a `webApps` config.
25052
+ {
25053
+ kind: "web-app",
25054
+ configProperty: "webApps"
24477
25055
  }
24478
25056
  ];
24479
25057
  AgentTraverser = class {
@@ -24496,7 +25074,7 @@ var init_agent_traverser = __esm({
24496
25074
  this.rootDir = rootDir;
24497
25075
  this.debug = debug;
24498
25076
  this.project = new Project2({
24499
- tsConfigFilePath: path10.join(rootDir, "tsconfig.json"),
25077
+ tsConfigFilePath: path11.join(rootDir, "tsconfig.json"),
24500
25078
  skipAddingFilesFromTsConfig: true
24501
25079
  });
24502
25080
  registerProjectRootDir(this.project, this.rootDir);
@@ -24587,12 +25165,12 @@ var init_agent_traverser = __esm({
24587
25165
  */
24588
25166
  detectAgent() {
24589
25167
  const priorityFiles = [
24590
- path10.join(this.rootDir, "index.ts"),
24591
- path10.join(this.rootDir, "src", "index.ts"),
24592
- path10.join(this.rootDir, "agent.ts"),
24593
- path10.join(this.rootDir, "src", "agent.ts"),
24594
- path10.join(this.rootDir, "main.ts"),
24595
- path10.join(this.rootDir, "src", "main.ts")
25168
+ path11.join(this.rootDir, "index.ts"),
25169
+ path11.join(this.rootDir, "src", "index.ts"),
25170
+ path11.join(this.rootDir, "agent.ts"),
25171
+ path11.join(this.rootDir, "src", "agent.ts"),
25172
+ path11.join(this.rootDir, "main.ts"),
25173
+ path11.join(this.rootDir, "src", "main.ts")
24596
25174
  ];
24597
25175
  for (const filePath of priorityFiles) {
24598
25176
  if (fs8.existsSync(filePath)) {
@@ -24651,7 +25229,7 @@ var init_agent_traverser = __esm({
24651
25229
  */
24652
25230
  extractArrayRefs(config, propName) {
24653
25231
  const prop = config.getProperty(propName);
24654
- if (!prop || !Node19.isPropertyAssignment(prop)) return [];
25232
+ if (!prop || !Node20.isPropertyAssignment(prop)) return [];
24655
25233
  const value3 = prop.getInitializer();
24656
25234
  if (!value3) return [];
24657
25235
  const ctx = {
@@ -24736,7 +25314,7 @@ var init_agent_traverser = __esm({
24736
25314
  for (const assign of file.getExportAssignments()) {
24737
25315
  if (assign.isExportEquals()) continue;
24738
25316
  const expr = assign.getExpression();
24739
- if (!Node19.isIdentifier(expr)) continue;
25317
+ if (!Node20.isIdentifier(expr)) continue;
24740
25318
  const targetName = expr.getText();
24741
25319
  defaultMatch = detected.find((d) => d.exportName === targetName);
24742
25320
  if (defaultMatch) break;
@@ -24747,7 +25325,7 @@ var init_agent_traverser = __esm({
24747
25325
  console.warn(formatSarifWarning({
24748
25326
  ruleId: "lua/missing-primitive-declaration",
24749
25327
  filePath: sourcePath,
24750
- message: `agent references ${kind} "${refName}" but ${path10.basename(sourcePath)} does not define a matching primitive`,
25328
+ message: `agent references ${kind} "${refName}" but ${path11.basename(sourcePath)} does not define a matching primitive`,
24751
25329
  hint: `export a named ${plugin.displayName.toLowerCase()} declaration as "${refName}", or adjust the import so it points to the file that does`
24752
25330
  }));
24753
25331
  return null;
@@ -24768,19 +25346,19 @@ var init_agent_traverser = __esm({
24768
25346
 
24769
25347
  // src/compiler/utils/workspace.ts
24770
25348
  import fs9 from "fs";
24771
- import path11 from "path";
25349
+ import path12 from "path";
24772
25350
  function findWorkspaceRoot(rootDir) {
24773
- const resolvedInput = path11.resolve(rootDir);
25351
+ const resolvedInput = path12.resolve(rootDir);
24774
25352
  const cached = workspaceRootCache.get(resolvedInput);
24775
25353
  if (cached !== void 0) return cached;
24776
25354
  let current = resolvedInput;
24777
- const { root } = path11.parse(current);
25355
+ const { root } = path12.parse(current);
24778
25356
  while (true) {
24779
25357
  if (isWorkspaceRoot(current)) {
24780
25358
  workspaceRootCache.set(resolvedInput, current);
24781
25359
  return current;
24782
25360
  }
24783
- const parent = path11.dirname(current);
25361
+ const parent = path12.dirname(current);
24784
25362
  if (parent === current || current === root) break;
24785
25363
  current = parent;
24786
25364
  }
@@ -24788,10 +25366,10 @@ function findWorkspaceRoot(rootDir) {
24788
25366
  return resolvedInput;
24789
25367
  }
24790
25368
  function isWorkspaceRoot(dir) {
24791
- if (fileExists(path11.join(dir, "pnpm-workspace.yaml"))) return true;
24792
- if (fileExists(path11.join(dir, "lerna.json"))) return true;
24793
- if (packageJsonHasWorkspaces(path11.join(dir, "package.json"))) return true;
24794
- if (dirExists(path11.join(dir, ".git"))) return true;
25369
+ if (fileExists(path12.join(dir, "pnpm-workspace.yaml"))) return true;
25370
+ if (fileExists(path12.join(dir, "lerna.json"))) return true;
25371
+ if (packageJsonHasWorkspaces(path12.join(dir, "package.json"))) return true;
25372
+ if (dirExists(path12.join(dir, ".git"))) return true;
24795
25373
  return false;
24796
25374
  }
24797
25375
  function fileExists(p) {
@@ -24834,7 +25412,7 @@ var init_workspace = __esm({
24834
25412
 
24835
25413
  // src/compiler/compiler.ts
24836
25414
  import fs10 from "fs/promises";
24837
- import path12 from "path";
25415
+ import path13 from "path";
24838
25416
  import { Project as Project3 } from "ts-morph";
24839
25417
  async function compile2(options) {
24840
25418
  const compiler = new Compiler(options);
@@ -24891,7 +25469,7 @@ var init_compiler = __esm({
24891
25469
  ...options
24892
25470
  };
24893
25471
  this.project = new Project3({
24894
- tsConfigFilePath: path12.join(options.rootDir, "tsconfig.json")
25472
+ tsConfigFilePath: path13.join(options.rootDir, "tsconfig.json")
24895
25473
  });
24896
25474
  registerProjectRootDir(this.project, this.options.rootDir);
24897
25475
  this.bundler = new Bundler({
@@ -24972,7 +25550,7 @@ var init_compiler = __esm({
24972
25550
  await fs10.mkdir(this.options.outDir, {
24973
25551
  recursive: true
24974
25552
  });
24975
- await fs10.mkdir(path12.join(this.options.outDir, ".temp"), {
25553
+ await fs10.mkdir(path13.join(this.options.outDir, ".temp"), {
24976
25554
  recursive: true
24977
25555
  });
24978
25556
  const CONCURRENCY = 4;
@@ -25024,7 +25602,7 @@ var init_compiler = __esm({
25024
25602
  this.verbose("\u{1F4BE} Writing artifacts...");
25025
25603
  await this.writeArtifacts(compiledPrimitives);
25026
25604
  if (!this.options.debug) {
25027
- await fs10.rm(path12.join(this.options.outDir, ".temp"), {
25605
+ await fs10.rm(path13.join(this.options.outDir, ".temp"), {
25028
25606
  recursive: true,
25029
25607
  force: true
25030
25608
  });
@@ -25076,7 +25654,7 @@ var init_compiler = __esm({
25076
25654
  */
25077
25655
  getWorkspaceRoot() {
25078
25656
  if (this._workspaceRoot === void 0) {
25079
- this._workspaceRoot = findWorkspaceRoot(path12.resolve(this.options.rootDir));
25657
+ this._workspaceRoot = findWorkspaceRoot(path13.resolve(this.options.rootDir));
25080
25658
  }
25081
25659
  return this._workspaceRoot;
25082
25660
  }
@@ -25090,18 +25668,18 @@ var init_compiler = __esm({
25090
25668
  * - Files outside the detected workspace root (not our code)
25091
25669
  */
25092
25670
  collectExternalWorkspaceFiles(traverser) {
25093
- const rootDir = path12.resolve(this.options.rootDir);
25671
+ const rootDir = path13.resolve(this.options.rootDir);
25094
25672
  const workspaceRoot = this.getWorkspaceRoot();
25095
25673
  if (workspaceRoot === rootDir) return [];
25096
25674
  const loaded = traverser.getAllLoadedSourceFilePaths();
25097
25675
  const result = [];
25098
25676
  const seen = /* @__PURE__ */ new Set();
25099
25677
  for (const raw of loaded) {
25100
- const abs = path12.resolve(raw);
25678
+ const abs = path13.resolve(raw);
25101
25679
  if (seen.has(abs)) continue;
25102
25680
  seen.add(abs);
25103
25681
  if (isInside(abs, rootDir)) continue;
25104
- if (abs.includes(`${path12.sep}node_modules${path12.sep}`)) continue;
25682
+ if (abs.includes(`${path13.sep}node_modules${path13.sep}`)) continue;
25105
25683
  if (!isInside(abs, workspaceRoot)) continue;
25106
25684
  result.push(abs);
25107
25685
  }
@@ -25244,8 +25822,8 @@ var init_compiler = __esm({
25244
25822
  * @param primitives - All compiled primitives to write
25245
25823
  */
25246
25824
  async writeArtifacts(primitives) {
25247
- const artifactsDir = path12.join(this.options.outDir, "artifacts");
25248
- const sourcesDir = path12.join(this.options.outDir, "sources");
25825
+ const artifactsDir = path13.join(this.options.outDir, "artifacts");
25826
+ const sourcesDir = path13.join(this.options.outDir, "sources");
25249
25827
  await fs10.mkdir(sourcesDir, {
25250
25828
  recursive: true
25251
25829
  });
@@ -25254,7 +25832,7 @@ var init_compiler = __esm({
25254
25832
  this.verbose(" \u{1F4C2} Collecting project files...");
25255
25833
  const projectFiles = await this.storeProjectFiles(sourcesDir, writtenSources);
25256
25834
  const manifest = await this.createManifest(primitives, projectFiles);
25257
- await fs10.writeFile(path12.join(this.options.outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
25835
+ await fs10.writeFile(path13.join(this.options.outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
25258
25836
  this.verbose(` \u{1F4E6} Total files stored: ${writtenSources.size} (deduplicated)`);
25259
25837
  this.verbose(` \u{1F4C1} Project files: ${projectFiles.length}`);
25260
25838
  if (this.options.verbose || this.options.debug) {
@@ -25266,25 +25844,25 @@ var init_compiler = __esm({
25266
25844
  */
25267
25845
  async writePrimitiveArtifacts(primitives, artifactsDir, sourcesDir, writtenSources) {
25268
25846
  for (const primitive of primitives) {
25269
- const primitiveDir = path12.join(artifactsDir, primitive.kind);
25847
+ const primitiveDir = path13.join(artifactsDir, primitive.kind);
25270
25848
  await fs10.mkdir(primitiveDir, {
25271
25849
  recursive: true
25272
25850
  });
25273
25851
  const baseName = primitive.name;
25274
- await fs10.writeFile(path12.join(primitiveDir, `${baseName}.js`), primitive.artifact.code);
25852
+ await fs10.writeFile(path13.join(primitiveDir, `${baseName}.js`), primitive.artifact.code);
25275
25853
  if (primitive.artifact.sourceMap) {
25276
- await fs10.writeFile(path12.join(primitiveDir, `${baseName}.js.map`), primitive.artifact.sourceMap);
25854
+ await fs10.writeFile(path13.join(primitiveDir, `${baseName}.js.map`), primitive.artifact.sourceMap);
25277
25855
  }
25278
25856
  const sourceHash = hashContent(primitive.artifact.originalSource);
25279
25857
  if (!writtenSources.has(sourceHash)) {
25280
25858
  const ext = primitive.sourcePath.endsWith(".tsx") ? ".tsx" : primitive.sourcePath.endsWith(".js") ? ".js" : ".ts";
25281
- await fs10.writeFile(path12.join(sourcesDir, `${sourceHash}${ext}`), primitive.artifact.originalSource);
25282
- const relativePath = path12.relative(this.options.rootDir, primitive.sourcePath);
25859
+ await fs10.writeFile(path13.join(sourcesDir, `${sourceHash}${ext}`), primitive.artifact.originalSource);
25860
+ const relativePath = path13.relative(this.options.rootDir, primitive.sourcePath);
25283
25861
  writtenSources.set(sourceHash, relativePath);
25284
25862
  }
25285
25863
  const sidecarPlugin = pluginRegistry.get(primitive.kind);
25286
25864
  const sidecarMetadata = sidecarPlugin?.sanitizeForPersistence ? sidecarPlugin.sanitizeForPersistence(primitive.metadata) : primitive.metadata;
25287
- await fs10.writeFile(path12.join(primitiveDir, `${baseName}.json`), JSON.stringify({
25865
+ await fs10.writeFile(path13.join(primitiveDir, `${baseName}.json`), JSON.stringify({
25288
25866
  kind: primitive.kind,
25289
25867
  name: primitive.name,
25290
25868
  description: primitive.description,
@@ -25306,12 +25884,12 @@ var init_compiler = __esm({
25306
25884
  const allFiles = await this.collectProjectFiles();
25307
25885
  const workspaceRoot = this.getWorkspaceRoot();
25308
25886
  for (const file of allFiles) {
25309
- const absPath = file.external ? path12.join(workspaceRoot, file.relativePath) : path12.join(this.options.rootDir, file.relativePath);
25887
+ const absPath = file.external ? path13.join(workspaceRoot, file.relativePath) : path13.join(this.options.rootDir, file.relativePath);
25310
25888
  const content = await fs10.readFile(absPath, "utf-8");
25311
25889
  const hash = hashContent(content);
25312
25890
  if (!writtenSources.has(hash)) {
25313
- const ext = path12.extname(file.relativePath) || ".txt";
25314
- await fs10.writeFile(path12.join(sourcesDir, `${hash}${ext}`), content);
25891
+ const ext = path13.extname(file.relativePath) || ".txt";
25892
+ await fs10.writeFile(path13.join(sourcesDir, `${hash}${ext}`), content);
25315
25893
  writtenSources.set(hash, file.relativePath);
25316
25894
  }
25317
25895
  projectFiles.push({
@@ -25392,7 +25970,7 @@ var init_compiler = __esm({
25392
25970
  });
25393
25971
  for (const entry of entries) {
25394
25972
  const relativePath = relativeBase ? `${relativeBase}/${entry.name}` : entry.name;
25395
- const fullPath = path12.join(dir, entry.name);
25973
+ const fullPath = path13.join(dir, entry.name);
25396
25974
  if (entry.isDirectory()) {
25397
25975
  if (shouldSkipDirectory(entry.name)) continue;
25398
25976
  await scanDir(fullPath, relativePath);
@@ -25409,10 +25987,10 @@ var init_compiler = __esm({
25409
25987
  const workspaceRoot = this.getWorkspaceRoot();
25410
25988
  const externalSeen = /* @__PURE__ */ new Set();
25411
25989
  for (const abs of this.externalWorkspaceFiles) {
25412
- const rel = path12.relative(workspaceRoot, abs).split(path12.sep).join("/");
25990
+ const rel = path13.relative(workspaceRoot, abs).split(path13.sep).join("/");
25413
25991
  if (!rel || rel.startsWith("..")) continue;
25414
25992
  if (externalSeen.has(rel)) continue;
25415
- const name = path12.basename(abs);
25993
+ const name = path13.basename(abs);
25416
25994
  if (shouldSkipFile(rel) || shouldSkipFile(name)) continue;
25417
25995
  externalSeen.add(rel);
25418
25996
  files.push({
@@ -25513,12 +26091,12 @@ var init_compiler = __esm({
25513
26091
  });
25514
26092
 
25515
26093
  // src/compiler/utils/file-discovery.ts
25516
- import path13 from "path";
26094
+ import path14 from "path";
25517
26095
  import fs11 from "fs";
25518
26096
  function findEntryPoint(projectDir) {
25519
26097
  const baseDir = projectDir || process.cwd();
25520
26098
  for (const relativePath of ENTRY_POINT_PRIORITY) {
25521
- const fullPath = path13.join(baseDir, relativePath);
26099
+ const fullPath = path14.join(baseDir, relativePath);
25522
26100
  if (fs11.existsSync(fullPath)) {
25523
26101
  return fullPath;
25524
26102
  }
@@ -25555,9 +26133,9 @@ var init_file_discovery = __esm({
25555
26133
  });
25556
26134
 
25557
26135
  // src/compiler/source-writer.ts
25558
- import { Project as Project4, Node as Node20 } from "ts-morph";
26136
+ import { Project as Project4, Node as Node21 } from "ts-morph";
25559
26137
  import fs12 from "fs";
25560
- import path14 from "path";
26138
+ import path15 from "path";
25561
26139
  function resolveEntryPath(options) {
25562
26140
  let indexPath;
25563
26141
  try {
@@ -25569,12 +26147,12 @@ function resolveEntryPath(options) {
25569
26147
  indexPath = entryPoint;
25570
26148
  } else {
25571
26149
  const baseDir = options?.projectDir || process.cwd();
25572
- indexPath = path14.join(baseDir, "src", "index.ts");
26150
+ indexPath = path15.join(baseDir, "src", "index.ts");
25573
26151
  }
25574
26152
  }
25575
26153
  } catch {
25576
26154
  const baseDir = options?.projectDir || process.cwd();
25577
- indexPath = path14.join(baseDir, "src", "index.ts");
26155
+ indexPath = path15.join(baseDir, "src", "index.ts");
25578
26156
  }
25579
26157
  if (!fs12.existsSync(indexPath)) {
25580
26158
  console.warn(`Warning: Entry file not found at ${indexPath}`);
@@ -25604,14 +26182,14 @@ function updateAgentConfig(updates, options) {
25604
26182
  const sourceFile = project.addSourceFileAtPath(indexPath);
25605
26183
  let updated = false;
25606
26184
  sourceFile.forEachDescendant((node) => {
25607
- if (Node20.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
26185
+ if (Node21.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
25608
26186
  const args2 = node.getArguments();
25609
- if (args2.length > 0 && Node20.isObjectLiteralExpression(args2[0])) {
26187
+ if (args2.length > 0 && Node21.isObjectLiteralExpression(args2[0])) {
25610
26188
  const configObj = args2[0];
25611
26189
  const replacedKeys = /* @__PURE__ */ new Set();
25612
26190
  let lastReplacedIndex = -1;
25613
26191
  configObj.getProperties().forEach((prop, index) => {
25614
- if (Node20.isPropertyAssignment(prop)) {
26192
+ if (Node21.isPropertyAssignment(prop)) {
25615
26193
  const propName = prop.getName();
25616
26194
  if (Object.prototype.hasOwnProperty.call(filteredUpdates, propName)) {
25617
26195
  const newValue = filteredUpdates[propName];
@@ -25674,14 +26252,14 @@ function removeAgentConfigProperty(propertyName, options) {
25674
26252
  let foundConstructor = false;
25675
26253
  let removed = false;
25676
26254
  sourceFile.forEachDescendant((node) => {
25677
- if (Node20.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
26255
+ if (Node21.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
25678
26256
  const args2 = node.getArguments();
25679
- if (args2.length > 0 && Node20.isObjectLiteralExpression(args2[0])) {
26257
+ if (args2.length > 0 && Node21.isObjectLiteralExpression(args2[0])) {
25680
26258
  foundConstructor = true;
25681
26259
  const configObj = args2[0];
25682
26260
  const props = configObj.getProperties();
25683
26261
  for (const prop of props) {
25684
- if (Node20.isPropertyAssignment(prop) && prop.getName() === propertyName) {
26262
+ if (Node21.isPropertyAssignment(prop) && prop.getName() === propertyName) {
25685
26263
  prop.remove();
25686
26264
  removed = true;
25687
26265
  break;
@@ -28445,8 +29023,8 @@ var init_developer_api_service = __esm({
28445
29023
  * @returns Promise resolving to an ApiResponse containing the profile, or null if not found
28446
29024
  */
28447
29025
  async getUserProfileByEmail(email, agentId) {
28448
- const path26 = `/developer/user/profile/email/${encodeURIComponent(email)}`;
28449
- const scopedPath = agentId ? `${path26}?agentId=${encodeURIComponent(agentId)}` : path26;
29026
+ const path27 = `/developer/user/profile/email/${encodeURIComponent(email)}`;
29027
+ const scopedPath = agentId ? `${path27}?agentId=${encodeURIComponent(agentId)}` : path27;
28450
29028
  return this.httpGet(scopedPath, {});
28451
29029
  }
28452
29030
  /**
@@ -28456,8 +29034,8 @@ var init_developer_api_service = __esm({
28456
29034
  */
28457
29035
  async getUserProfileByPhone(phone, agentId) {
28458
29036
  const normalizedPhone = phone.replace(/^\+/, "");
28459
- const path26 = `/developer/user/profile/phone/${normalizedPhone}`;
28460
- const scopedPath = agentId ? `${path26}?agentId=${encodeURIComponent(agentId)}` : path26;
29037
+ const path27 = `/developer/user/profile/phone/${normalizedPhone}`;
29038
+ const scopedPath = agentId ? `${path27}?agentId=${encodeURIComponent(agentId)}` : path27;
28461
29039
  return this.httpGet(scopedPath, {});
28462
29040
  }
28463
29041
  };
@@ -31477,7 +32055,7 @@ init_artifact_loader();
31477
32055
  init_backup_api_service();
31478
32056
  init_constants();
31479
32057
  import fs13 from "fs";
31480
- import path15 from "path";
32058
+ import path16 from "path";
31481
32059
  var BACKUP_CACHE_FILENAME = "backup-manifest.json";
31482
32060
  function calculateProjectHash(projectFiles) {
31483
32061
  return combineFileHashes(projectFiles);
@@ -31490,9 +32068,9 @@ function getCurrentProjectHash(projectPath = process.cwd()) {
31490
32068
  }
31491
32069
  __name(getCurrentProjectHash, "getCurrentProjectHash");
31492
32070
  function loadSourceByHash(hash, relativePath, projectPath = process.cwd()) {
31493
- const sourcesDir = path15.join(projectPath, COMPILE_DIRS.DIST_V2, "sources");
31494
- const ext = path15.extname(relativePath) || ".txt";
31495
- const sourcePath = path15.join(sourcesDir, `${hash}${ext}`);
32071
+ const sourcesDir = path16.join(projectPath, COMPILE_DIRS.DIST_V2, "sources");
32072
+ const ext = path16.extname(relativePath) || ".txt";
32073
+ const sourcePath = path16.join(sourcesDir, `${hash}${ext}`);
31496
32074
  if (fs13.existsSync(sourcePath)) {
31497
32075
  return fs13.readFileSync(sourcePath, "utf-8");
31498
32076
  }
@@ -31513,17 +32091,17 @@ function prepareFileRefs(projectPath = process.cwd()) {
31513
32091
  }
31514
32092
  __name(prepareFileRefs, "prepareFileRefs");
31515
32093
  function reconcileManifestWithDisk(projectPath = process.cwd()) {
31516
- const manifestPath = path15.join(projectPath, COMPILE_DIRS.DIST_V2, "manifest.json");
32094
+ const manifestPath = path16.join(projectPath, COMPILE_DIRS.DIST_V2, "manifest.json");
31517
32095
  if (!fs13.existsSync(manifestPath)) return;
31518
32096
  const manifest = loadManifest(projectPath);
31519
- const sourcesDir = path15.join(projectPath, COMPILE_DIRS.DIST_V2, "sources");
32097
+ const sourcesDir = path16.join(projectPath, COMPILE_DIRS.DIST_V2, "sources");
31520
32098
  fs13.mkdirSync(sourcesDir, {
31521
32099
  recursive: true
31522
32100
  });
31523
32101
  let changed = false;
31524
32102
  for (const file of manifest.projectFiles) {
31525
32103
  if (file.external) continue;
31526
- const absPath = path15.join(projectPath, file.relativePath);
32104
+ const absPath = path16.join(projectPath, file.relativePath);
31527
32105
  if (!fs13.existsSync(absPath)) continue;
31528
32106
  let content;
31529
32107
  try {
@@ -31533,8 +32111,8 @@ function reconcileManifestWithDisk(projectPath = process.cwd()) {
31533
32111
  }
31534
32112
  const freshHash = hashContent(content);
31535
32113
  if (freshHash === file.hash) continue;
31536
- const ext = path15.extname(file.relativePath) || ".txt";
31537
- const sourceTargetPath = path15.join(sourcesDir, `${freshHash}${ext}`);
32114
+ const ext = path16.extname(file.relativePath) || ".txt";
32115
+ const sourceTargetPath = path16.join(sourcesDir, `${freshHash}${ext}`);
31538
32116
  try {
31539
32117
  fs13.writeFileSync(sourceTargetPath, content, "utf-8");
31540
32118
  } catch {
@@ -31681,13 +32259,13 @@ function createBackupTracking(projectHash) {
31681
32259
  }
31682
32260
  __name(createBackupTracking, "createBackupTracking");
31683
32261
  function getBackupCachePath(projectPath = process.cwd()) {
31684
- return path15.join(projectPath, ".lua", BACKUP_CACHE_FILENAME);
32262
+ return path16.join(projectPath, ".lua", BACKUP_CACHE_FILENAME);
31685
32263
  }
31686
32264
  __name(getBackupCachePath, "getBackupCachePath");
31687
32265
  function writeBackupManifestCache(cache, projectPath = process.cwd()) {
31688
32266
  const cachePath = getBackupCachePath(projectPath);
31689
32267
  try {
31690
- fs13.mkdirSync(path15.dirname(cachePath), {
32268
+ fs13.mkdirSync(path16.dirname(cachePath), {
31691
32269
  recursive: true
31692
32270
  });
31693
32271
  fs13.writeFileSync(cachePath, JSON.stringify(cache, null, 2), "utf-8");
@@ -31728,12 +32306,12 @@ function detectLocalConflictsForPull(incomingFiles, projectPath = process.cwd())
31728
32306
  f.hash
31729
32307
  ]));
31730
32308
  const conflicts = /* @__PURE__ */ new Set();
31731
- const projectRoot = path15.resolve(projectPath);
32309
+ const projectRoot = path16.resolve(projectPath);
31732
32310
  for (const incoming of incomingFiles) {
31733
32311
  if (COMPILE_MANAGED_FILES.has(incoming.relativePath)) continue;
31734
32312
  if (incoming.external) continue;
31735
- const absPath = path15.resolve(projectRoot, incoming.relativePath);
31736
- if (absPath !== projectRoot && !absPath.startsWith(projectRoot + path15.sep)) {
32313
+ const absPath = path16.resolve(projectRoot, incoming.relativePath);
32314
+ if (absPath !== projectRoot && !absPath.startsWith(projectRoot + path16.sep)) {
31737
32315
  continue;
31738
32316
  }
31739
32317
  if (!fs13.existsSync(absPath)) continue;
@@ -31925,7 +32503,7 @@ function writeBackupFilesWithByteCompare(manifest, blobs, targetDir) {
31925
32503
  continue;
31926
32504
  }
31927
32505
  }
31928
- fs13.mkdirSync(path15.dirname(filePath), {
32506
+ fs13.mkdirSync(path16.dirname(filePath), {
31929
32507
  recursive: true
31930
32508
  });
31931
32509
  fs13.writeFileSync(filePath, content);
@@ -34088,13 +34666,13 @@ __name(apiKeyCommand, "apiKeyCommand");
34088
34666
  init_cli();
34089
34667
  init_files();
34090
34668
  init_request_credential();
34091
- import path22 from "path";
34669
+ import path23 from "path";
34092
34670
 
34093
34671
  // src/commands/sync.ts
34094
34672
  init_dist();
34095
34673
  init_cli();
34096
34674
  import fs14 from "fs";
34097
- import path16 from "path";
34675
+ import path17 from "path";
34098
34676
  init_command_utils();
34099
34677
 
34100
34678
  // src/commands/log-tip.ts
@@ -34297,7 +34875,7 @@ init_mcp_server_handler();
34297
34875
  async function syncCommand(options) {
34298
34876
  return withErrorHandling(async () => {
34299
34877
  const preCompileYaml = readYamlConfig();
34300
- const yamlPath = path16.resolve(process.cwd(), "lua.skill.yaml");
34878
+ const yamlPath = path17.resolve(process.cwd(), "lua.skill.yaml");
34301
34879
  const preCompileYamlBytes = fs14.existsSync(yamlPath) ? fs14.readFileSync(yamlPath, "utf-8") : null;
34302
34880
  let syncCompletedSuccessfully = false;
34303
34881
  try {
@@ -36171,8 +36749,8 @@ function buildSupervisionAgentsApi(call) {
36171
36749
  }), "persona"),
36172
36750
  source: /* @__PURE__ */ __name7((agentId) => ({
36173
36751
  list: /* @__PURE__ */ __name7(() => call("source.list", agentId), "list"),
36174
- get: /* @__PURE__ */ __name7((path26) => call("source.get", agentId, {
36175
- path: path26
36752
+ get: /* @__PURE__ */ __name7((path27) => call("source.get", agentId, {
36753
+ path: path27
36176
36754
  }), "get")
36177
36755
  }), "source"),
36178
36756
  /** Environment variable NAMES only — values are never returned. */
@@ -36187,10 +36765,10 @@ __name7(buildSupervisionAgentsApi, "buildSupervisionAgentsApi");
36187
36765
  // src/utils/sandbox.ts
36188
36766
  init_dist4();
36189
36767
  import vm4 from "vm";
36190
- import path21 from "path";
36768
+ import path22 from "path";
36191
36769
 
36192
36770
  // src/utils/env-loader.utils.ts
36193
- import path17 from "path";
36771
+ import path18 from "path";
36194
36772
  import fs15 from "fs";
36195
36773
  function parseEnvFile(filePath) {
36196
36774
  if (!fs15.existsSync(filePath)) {
@@ -36223,7 +36801,7 @@ async function loadEnvironmentVariables(context) {
36223
36801
  }
36224
36802
  __name(loadEnvironmentVariables, "loadEnvironmentVariables");
36225
36803
  function loadSandboxEnvVariables() {
36226
- const envFilePath = path17.join(process.cwd(), ".env");
36804
+ const envFilePath = path18.join(process.cwd(), ".env");
36227
36805
  const envMap = parseEnvFile(envFilePath);
36228
36806
  return Object.entries(envMap).map(([key, value3]) => ({
36229
36807
  key,
@@ -36295,15 +36873,15 @@ init_compile_constants();
36295
36873
  init_dist2();
36296
36874
  init_dist();
36297
36875
  import fs16 from "fs";
36298
- import path20 from "path";
36876
+ import path21 from "path";
36299
36877
 
36300
36878
  // src/utils/workflow-exec.ts
36301
- import path19 from "path";
36879
+ import path20 from "path";
36302
36880
 
36303
36881
  // ../shared-types/dist/workflow-exec.mjs
36304
36882
  import { spawn as nodeSpawn } from "child_process";
36305
36883
  import { accessSync, constants as fsConstants, realpathSync, statSync as statSync5 } from "fs";
36306
- import path18 from "path";
36884
+ import path19 from "path";
36307
36885
  var __defProp8 = Object.defineProperty;
36308
36886
  var __name8 = /* @__PURE__ */ __name((target, value3) => __defProp8(target, "name", { value: value3, configurable: true }), "__name");
36309
36887
  var WORKFLOW_EXEC_BINARIES = Object.freeze([
@@ -36316,7 +36894,10 @@ var WORKFLOW_EXEC_BINARIES = Object.freeze([
36316
36894
  "yarn",
36317
36895
  "python3",
36318
36896
  "pytest",
36319
- "make"
36897
+ "make",
36898
+ // EM-WS3 × EM-WS2: lua-cli. On the Job tier the host refuses it unless the claim declared `luaApi: true`, and then it
36899
+ // runs against the sidecar's `:8092` staging-only proxy with a placeholder key (the real key is the sidecar's).
36900
+ "lua"
36320
36901
  ]);
36321
36902
  var WORKFLOW_EXEC_DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
36322
36903
  var WORKFLOW_EXEC_OUTPUT_MAX_BYTES = 1024 * 1024;
@@ -36489,7 +37070,7 @@ function resolveWorkflowExecBinary(name, pathDirs) {
36489
37070
  }
36490
37071
  for (const dir of pathDirs) {
36491
37072
  if (!dir) continue;
36492
- const file = path18.join(dir, name);
37073
+ const file = path19.join(dir, name);
36493
37074
  try {
36494
37075
  if (!statSync5(file).isFile()) continue;
36495
37076
  accessSync(file, fsConstants.X_OK);
@@ -36504,7 +37085,7 @@ function resolveWorkflowExecBinary(name, pathDirs) {
36504
37085
  __name(resolveWorkflowExecBinary, "resolveWorkflowExecBinary");
36505
37086
  __name8(resolveWorkflowExecBinary, "resolveWorkflowExecBinary");
36506
37087
  function within(root, p) {
36507
- return p === root || p.startsWith(root.endsWith(path18.sep) ? root : root + path18.sep);
37088
+ return p === root || p.startsWith(root.endsWith(path19.sep) ? root : root + path19.sep);
36508
37089
  }
36509
37090
  __name(within, "within");
36510
37091
  __name8(within, "within");
@@ -36519,7 +37100,7 @@ function confineWorkflowExecCwd(root, cwd) {
36519
37100
  if (cwd !== void 0 && typeof cwd !== "string") throw refused("cwd_outside_workspace", "cwd must be a string");
36520
37101
  const given = typeof cwd === "string" ? cwd : ".";
36521
37102
  if (given.includes("\0")) throw refused("cwd_outside_workspace", "cwd contains NUL");
36522
- const abs = path18.resolve(root, given);
37103
+ const abs = path19.resolve(root, given);
36523
37104
  if (!within(root, abs) && !within(rootReal, abs)) {
36524
37105
  throw refused("cwd_outside_workspace", `cwd ${given} is outside the workspace (${root})`);
36525
37106
  }
@@ -36912,7 +37493,7 @@ var processSigint = {
36912
37493
  };
36913
37494
  function createLocalWorkflowExec(o) {
36914
37495
  const env = localWorkflowExecEnv(o.env);
36915
- const pathDirs = o.pathDirs ?? env.PATH.split(path19.delimiter).filter(Boolean);
37496
+ const pathDirs = o.pathDirs ?? env.PATH.split(path20.delimiter).filter(Boolean);
36916
37497
  const queue = createWorkflowExecQueue();
36917
37498
  const sigint = o.sigint ?? processSigint;
36918
37499
  return buildWorkflowExecApi((req) => queue(async () => {
@@ -36937,7 +37518,13 @@ function createLocalWorkflowExec(o) {
36937
37518
  deadlineAt: o.deadlineAt?.(),
36938
37519
  mount: o.mount,
36939
37520
  signal: abort.signal,
36940
- spawnImpl: o.spawnImpl
37521
+ spawnImpl: o.spawnImpl,
37522
+ // EM-WS3 × EM-WS2: `lua` is on the shared allowlist for the Job pod, where it only ever reaches the
37523
+ // platform's staging-only :8092 proxy. Offline there is no such proxy: it would run with YOUR credentials
37524
+ // against the real API, so a local run refuses it.
37525
+ beforeSpawn: /* @__PURE__ */ __name(async (argv) => {
37526
+ if (argv[0] === "lua") throw workflowExecRefusal("lua_api_not_declared", "lua: runs only on the platform's Job tier (a luaApi: true step, through the staging-only proxy); refused offline", argv);
37527
+ }, "beforeSpawn")
36941
37528
  });
36942
37529
  o.log?.(`exec \xB7 ${formatWorkflowExecArgv(out.argv)} \xB7 ${out.timedOut ? "timed out" : `exit ${out.code ?? out.signal}`} \xB7 ${out.durationMs} ms${out.truncated ? " \xB7 output truncated" : ""}`);
36943
37530
  return out;
@@ -37368,7 +37955,7 @@ async function runWorkflowLocallyInner(rawOpts) {
37368
37955
  skipReason: reason
37369
37956
  });
37370
37957
  }, "skipRow");
37371
- const fixturePath = /* @__PURE__ */ __name((stepId, attempt, dir) => path20.join(dir, `${stepId.replace(/[\\/]/g, "_")}.${attempt}.json`), "fixturePath");
37958
+ const fixturePath = /* @__PURE__ */ __name((stepId, attempt, dir) => path21.join(dir, `${stepId.replace(/[\\/]/g, "_")}.${attempt}.json`), "fixturePath");
37372
37959
  const readFixture = /* @__PURE__ */ __name((stepId, attempt) => {
37373
37960
  if (!opts.fixturesDir) return void 0;
37374
37961
  const file = fixturePath(stepId, attempt, opts.fixturesDir);
@@ -37430,7 +38017,7 @@ async function runWorkflowLocallyInner(rawOpts) {
37430
38017
  artefactSeq += 1;
37431
38018
  const artefactId = `local-${artefactSeq}`;
37432
38019
  const bytes = typeof data === "string" || Buffer.isBuffer(data) ? data : JSON.stringify(data);
37433
- fs16.writeFileSync(path20.join(dir, artefactId), bytes);
38020
+ fs16.writeFileSync(path21.join(dir, artefactId), bytes);
37434
38021
  const metaDoc = {
37435
38022
  artefactId,
37436
38023
  name,
@@ -37438,7 +38025,7 @@ async function runWorkflowLocallyInner(rawOpts) {
37438
38025
  size: Buffer.byteLength(bytes),
37439
38026
  ...meta
37440
38027
  };
37441
- fs16.writeFileSync(path20.join(dir, `${artefactId}.meta.json`), `${JSON.stringify(metaDoc, null, 2)}
38028
+ fs16.writeFileSync(path21.join(dir, `${artefactId}.meta.json`), `${JSON.stringify(metaDoc, null, 2)}
37442
38029
  `);
37443
38030
  say(`[artefact:${stepId}] ${name} \u2192 ${artefactId}`);
37444
38031
  return {
@@ -37446,11 +38033,11 @@ async function runWorkflowLocallyInner(rawOpts) {
37446
38033
  };
37447
38034
  }, "put"),
37448
38035
  get: /* @__PURE__ */ __name(async (artefactId) => {
37449
- const file = path20.join(dir, artefactId);
38036
+ const file = path21.join(dir, artefactId);
37450
38037
  if (!fs16.existsSync(file)) {
37451
38038
  throw new StepFailure("ARTEFACT_NOT_FOUND", `no artefact "${artefactId}" under --artefacts-dir`);
37452
38039
  }
37453
- const metaFile = path20.join(dir, `${artefactId}.meta.json`);
38040
+ const metaFile = path21.join(dir, `${artefactId}.meta.json`);
37454
38041
  const meta = fs16.existsSync(metaFile) ? JSON.parse(fs16.readFileSync(metaFile, "utf8")) : {
37455
38042
  artefactId
37456
38043
  };
@@ -37461,10 +38048,10 @@ async function runWorkflowLocallyInner(rawOpts) {
37461
38048
  text: /* @__PURE__ */ __name(async () => text, "text")
37462
38049
  };
37463
38050
  }, "get"),
37464
- list: /* @__PURE__ */ __name(async () => fs16.readdirSync(dir).filter((f) => f.endsWith(".meta.json")).map((f) => JSON.parse(fs16.readFileSync(path20.join(dir, f), "utf8"))), "list")
38051
+ list: /* @__PURE__ */ __name(async () => fs16.readdirSync(dir).filter((f) => f.endsWith(".meta.json")).map((f) => JSON.parse(fs16.readFileSync(path21.join(dir, f), "utf8"))), "list")
37465
38052
  };
37466
38053
  }, "artefactsApi");
37467
- const workspaceRoot = opts.workspaceDir ? path20.resolve(opts.workspaceDir) : void 0;
38054
+ const workspaceRoot = opts.workspaceDir ? path21.resolve(opts.workspaceDir) : void 0;
37468
38055
  const jobTierCtx = /* @__PURE__ */ __name((single, stepId, signal) => {
37469
38056
  if (single.type !== "step" || single.tier !== "job" && single.workspace === void 0) return {};
37470
38057
  const declared = single.workspace && typeof single.workspace === "object" ? single.workspace : {};
@@ -38440,7 +39027,7 @@ function kindOfSingle(s) {
38440
39027
  }
38441
39028
  __name(kindOfSingle, "kindOfSingle");
38442
39029
  function writeLedger(file, ledger) {
38443
- fs16.mkdirSync(path20.dirname(path20.resolve(file)), {
39030
+ fs16.mkdirSync(path21.dirname(path21.resolve(file)), {
38444
39031
  recursive: true
38445
39032
  });
38446
39033
  fs16.writeFileSync(file, `${JSON.stringify(ledger, null, 2)}
@@ -38534,7 +39121,7 @@ function loadEnvironmentVariables2() {
38534
39121
  envVars[key] = value3;
38535
39122
  }
38536
39123
  }
38537
- const envFilePath = path21.join(process.cwd(), ".env");
39124
+ const envFilePath = path22.join(process.cwd(), ".env");
38538
39125
  const fileEnvVars = parseEnvFile(envFilePath);
38539
39126
  Object.assign(envVars, fileEnvVars);
38540
39127
  return envVars;
@@ -39131,12 +39718,12 @@ function isWrittenAsModelClassRef(model) {
39131
39718
  }
39132
39719
  __name(isWrittenAsModelClassRef, "isWrittenAsModelClassRef");
39133
39720
  var oneOf = /* @__PURE__ */ __name((tuple) => tuple.map((v) => `\`${v}\``).join(", "), "oneOf");
39134
- function validateAgentNodeModelMembers(node, path26) {
39721
+ function validateAgentNodeModelMembers(node, path27) {
39135
39722
  const issues = [];
39136
39723
  if (typeof node.model === "string" && isWrittenAsModelClassRef(node.model)) {
39137
39724
  if (!modelClassOf(node.model)) {
39138
39725
  issues.push({
39139
- path: `${path26}.model`,
39726
+ path: `${path27}.model`,
39140
39727
  code: "model-class-unknown",
39141
39728
  message: `"${node.model}" is not a model class \u2014 use one of ${oneOf(WORKFLOW_MODEL_CLASSES.map((c) => modelClassRef(c)))}, or pin an approved model code`
39142
39729
  });
@@ -39145,7 +39732,7 @@ function validateAgentNodeModelMembers(node, path26) {
39145
39732
  if (node.taskClass !== void 0) {
39146
39733
  if (typeof node.taskClass !== "string" || !isWorkflowTaskClass(node.taskClass)) {
39147
39734
  issues.push({
39148
- path: `${path26}.taskClass`,
39735
+ path: `${path27}.taskClass`,
39149
39736
  code: "task-class-unknown",
39150
39737
  message: `"${String(node.taskClass)}" is not a task class \u2014 use one of ${oneOf(WORKFLOW_TASK_CLASSES)}`
39151
39738
  });
@@ -39154,7 +39741,7 @@ function validateAgentNodeModelMembers(node, path26) {
39154
39741
  if (node.requires !== void 0) {
39155
39742
  if (!Array.isArray(node.requires)) {
39156
39743
  issues.push({
39157
- path: `${path26}.requires`,
39744
+ path: `${path27}.requires`,
39158
39745
  code: "requires-invalid",
39159
39746
  message: `\`requires\` must be an array of ${oneOf(WORKFLOW_MODEL_TRAITS)}`
39160
39747
  });
@@ -39162,7 +39749,7 @@ function validateAgentNodeModelMembers(node, path26) {
39162
39749
  node.requires.forEach((trait, i) => {
39163
39750
  if (typeof trait !== "string" || !isWorkflowModelTrait(trait)) {
39164
39751
  issues.push({
39165
- path: `${path26}.requires.${i}`,
39752
+ path: `${path27}.requires.${i}`,
39166
39753
  code: "model-trait-unknown",
39167
39754
  message: `"${String(trait)}" is not a model trait \u2014 use one of ${oneOf(WORKFLOW_MODEL_TRAITS)}`
39168
39755
  });
@@ -39173,7 +39760,7 @@ function validateAgentNodeModelMembers(node, path26) {
39173
39760
  if (node.effort !== void 0) {
39174
39761
  if (typeof node.effort !== "string" || !isWorkflowEffort(node.effort)) {
39175
39762
  issues.push({
39176
- path: `${path26}.effort`,
39763
+ path: `${path27}.effort`,
39177
39764
  code: "effort-unknown",
39178
39765
  message: `"${String(node.effort)}" is not a workflow effort \u2014 use one of ${oneOf(WORKFLOW_AGENT_EFFORTS)}. (\`off\`, \`minimal\` and \`max\` are the agent-level \`modelSettings.reasoning.effort\` scale, not this one.)`
39179
39766
  });
@@ -39182,13 +39769,13 @@ function validateAgentNodeModelMembers(node, path26) {
39182
39769
  if (node.modelReason !== void 0) {
39183
39770
  if (typeof node.modelReason !== "string") {
39184
39771
  issues.push({
39185
- path: `${path26}.modelReason`,
39772
+ path: `${path27}.modelReason`,
39186
39773
  code: "model-reason-invalid",
39187
39774
  message: "`modelReason` must be a string"
39188
39775
  });
39189
39776
  } else if (node.modelReason.length > WORKFLOW_MODEL_REASON_MAX_LENGTH) {
39190
39777
  issues.push({
39191
- path: `${path26}.modelReason`,
39778
+ path: `${path27}.modelReason`,
39192
39779
  code: "model-reason-too-long",
39193
39780
  message: `\`modelReason\` is ${node.modelReason.length} characters \u2014 the cap is ${WORKFLOW_MODEL_REASON_MAX_LENGTH}`
39194
39781
  });
@@ -39208,20 +39795,20 @@ var MEMBERS = [
39208
39795
  function validateGraphModelMembers(graph) {
39209
39796
  const issues = [];
39210
39797
  const seen = /* @__PURE__ */ new Set();
39211
- const walk3 = /* @__PURE__ */ __name((value3, path26, depth) => {
39798
+ const walk3 = /* @__PURE__ */ __name((value3, path27, depth) => {
39212
39799
  if (depth > WORKFLOW_MODEL_WALK_MAX_DEPTH || value3 === null || typeof value3 !== "object") return;
39213
39800
  if (seen.has(value3)) return;
39214
39801
  seen.add(value3);
39215
39802
  if (Array.isArray(value3)) {
39216
- value3.forEach((v, i) => walk3(v, `${path26}.${i}`, depth + 1));
39803
+ value3.forEach((v, i) => walk3(v, `${path27}.${i}`, depth + 1));
39217
39804
  return;
39218
39805
  }
39219
39806
  const node = value3;
39220
39807
  if (MEMBERS.some((m) => node[m] !== void 0)) {
39221
- const label2 = typeof node.id === "string" && node.id ? node.id : path26;
39808
+ const label2 = typeof node.id === "string" && node.id ? node.id : path27;
39222
39809
  issues.push(...validateAgentNodeModelMembers(node, label2));
39223
39810
  }
39224
- for (const [k, v] of Object.entries(node)) walk3(v, path26 ? `${path26}.${k}` : k, depth + 1);
39811
+ for (const [k, v] of Object.entries(node)) walk3(v, path27 ? `${path27}.${k}` : k, depth + 1);
39225
39812
  }, "walk");
39226
39813
  walk3(graph, "", 0);
39227
39814
  return issues;
@@ -39535,7 +40122,7 @@ async function compileCommand(options) {
39535
40122
  }
39536
40123
  writeProgress("\u{1F528} Compiling...");
39537
40124
  const rootDir = process.cwd();
39538
- const outDir = path22.join(rootDir, "dist-v2");
40125
+ const outDir = path23.join(rootDir, "dist-v2");
39539
40126
  const result = await compile2({
39540
40127
  rootDir,
39541
40128
  outDir,
@@ -40650,7 +41237,7 @@ __name(validateOrSuggest, "validateOrSuggest");
40650
41237
 
40651
41238
  // src/commands/workflow-local-run.ts
40652
41239
  import fs17 from "fs";
40653
- import path23 from "path";
41240
+ import path24 from "path";
40654
41241
  init_cli();
40655
41242
 
40656
41243
  // src/utils/stdout-redirect.ts
@@ -41733,7 +42320,7 @@ async function runWorkflowLocalFromProject(name, flags) {
41733
42320
  fastRetries: !!flags.fastRetries,
41734
42321
  realTime: !!flags.realTime,
41735
42322
  artefactsDir: flags.artefactsDir,
41736
- workspaceDir: flags.workspace ? path23.resolve(flags.workspace) : void 0,
42323
+ workspaceDir: flags.workspace ? path24.resolve(flags.workspace) : void 0,
41737
42324
  env: parseEnvFlags(flags.env),
41738
42325
  prompt: process.stdin.isTTY && !asJson && !isCiModeEnabled() ? promptForLocalDecision : void 0,
41739
42326
  log: asJson ? void 0 : (line) => console.log(line)
@@ -41884,7 +42471,7 @@ async function runScriptFormLocally(wf, flags, say) {
41884
42471
  }
41885
42472
  __name(runScriptFormLocally, "runScriptFormLocally");
41886
42473
  function writeLedgerFile(file, value3) {
41887
- fs17.mkdirSync(path23.dirname(path23.resolve(file)), {
42474
+ fs17.mkdirSync(path24.dirname(path24.resolve(file)), {
41888
42475
  recursive: true
41889
42476
  });
41890
42477
  fs17.writeFileSync(file, `${JSON.stringify(value3, null, 2)}
@@ -47095,7 +47682,7 @@ init_constants();
47095
47682
  init_command_utils();
47096
47683
  init_developer_api_service();
47097
47684
  import fs18 from "fs";
47098
- import path24 from "path";
47685
+ import path25 from "path";
47099
47686
  import inquirer10 from "inquirer";
47100
47687
  init_analytics();
47101
47688
  init_cli_error();
@@ -47444,7 +48031,7 @@ function variablesToEnvContent(variables) {
47444
48031
  }
47445
48032
  __name(variablesToEnvContent, "variablesToEnvContent");
47446
48033
  function saveSandboxEnvVariables(variables) {
47447
- const envFilePath = path24.join(process.cwd(), ".env");
48034
+ const envFilePath = path25.join(process.cwd(), ".env");
47448
48035
  try {
47449
48036
  const content = variablesToEnvContent(variables);
47450
48037
  fs18.writeFileSync(envFilePath, content, "utf8");
@@ -51335,8 +51922,8 @@ var DrainsApi = class extends HttpClient {
51335
51922
  * answer is a plain `LogDrainRead` and is safe to retry; minting is not.
51336
51923
  */
51337
51924
  async rotateSecret(drainId, finalize) {
51338
- const path26 = this.drainPath(drainId, `/rotate-secret${finalize ? "?finalize=true" : ""}`);
51339
- return finalize ? this.httpPost(path26, {}) : this.httpPostOnce(path26, {});
51925
+ const path27 = this.drainPath(drainId, `/rotate-secret${finalize ? "?finalize=true" : ""}`);
51926
+ return finalize ? this.httpPost(path27, {}) : this.httpPostOnce(path27, {});
51340
51927
  }
51341
51928
  /**
51342
51929
  * Re-enqueue one batch's records (PRO-2126).
@@ -57386,7 +57973,7 @@ init_types();
57386
57973
  init_cli_error();
57387
57974
  import fs19 from "fs";
57388
57975
  import os2 from "os";
57389
- import path25 from "path";
57976
+ import path26 from "path";
57390
57977
  var EXPORT_NOT_COMPILABLE = "export-not-compilable";
57391
57978
  var EXPORT_CHECK_TSCONFIG = {
57392
57979
  compilerOptions: {
@@ -57407,13 +57994,13 @@ var EXPORT_CHECK_TSCONFIG = {
57407
57994
  ]
57408
57995
  };
57409
57996
  async function dryCompileWorkflowExport(files) {
57410
- const root = fs19.mkdtempSync(path25.join(os2.tmpdir(), "lua-workflows-export-"));
57997
+ const root = fs19.mkdtempSync(path26.join(os2.tmpdir(), "lua-workflows-export-"));
57411
57998
  const issues = [];
57412
57999
  const workflows = [];
57413
58000
  try {
57414
- fs19.writeFileSync(path25.join(root, "tsconfig.json"), `${JSON.stringify(EXPORT_CHECK_TSCONFIG, null, 2)}
58001
+ fs19.writeFileSync(path26.join(root, "tsconfig.json"), `${JSON.stringify(EXPORT_CHECK_TSCONFIG, null, 2)}
57415
58002
  `);
57416
- fs19.writeFileSync(path25.join(root, "package.json"), `${JSON.stringify({
58003
+ fs19.writeFileSync(path26.join(root, "package.json"), `${JSON.stringify({
57417
58004
  name: "lua-workflows-export-check",
57418
58005
  version: "0.0.0",
57419
58006
  private: true,
@@ -57421,23 +58008,23 @@ async function dryCompileWorkflowExport(files) {
57421
58008
  }, null, 2)}
57422
58009
  `);
57423
58010
  for (const f of files) {
57424
- const target = path25.resolve(root, f.path);
57425
- if (!target.startsWith(root + path25.sep)) continue;
57426
- fs19.mkdirSync(path25.dirname(target), {
58011
+ const target = path26.resolve(root, f.path);
58012
+ if (!target.startsWith(root + path26.sep)) continue;
58013
+ fs19.mkdirSync(path26.dirname(target), {
57427
58014
  recursive: true
57428
58015
  });
57429
58016
  fs19.writeFileSync(target, f.contents);
57430
58017
  }
57431
58018
  const result = await new Compiler({
57432
58019
  rootDir: root,
57433
- outDir: path25.join(root, "dist-v2"),
58020
+ outDir: path26.join(root, "dist-v2"),
57434
58021
  minify: false,
57435
58022
  sourceMaps: false,
57436
58023
  quietWarnings: true,
57437
58024
  runtimeValidation: false
57438
58025
  }).compile();
57439
58026
  for (const e of result.errors) {
57440
- const file = e.file ? path25.relative(root, e.file) : void 0;
58027
+ const file = e.file ? path26.relative(root, e.file) : void 0;
57441
58028
  const where = file ? `${file}${e.line ? `:${e.line}` : ""}` : void 0;
57442
58029
  issues.push({
57443
58030
  code: EXPORT_NOT_COMPILABLE,
@@ -59327,15 +59914,15 @@ function actorLabel(by, now = Date.now()) {
59327
59914
  return Number.isFinite(at) ? `${who} (${agoFrom(at, now)})` : who;
59328
59915
  }
59329
59916
  __name(actorLabel, "actorLabel");
59330
- function reservedSecretKeyPaths(value3, path26 = "", depth = 0, out = []) {
59917
+ function reservedSecretKeyPaths(value3, path27 = "", depth = 0, out = []) {
59331
59918
  if (depth > 64 || out.length >= 20 || value3 === null || typeof value3 !== "object") return out;
59332
59919
  if (Array.isArray(value3)) {
59333
- value3.forEach((v, i) => reservedSecretKeyPaths(v, `${path26}[${i}]`, depth + 1, out));
59920
+ value3.forEach((v, i) => reservedSecretKeyPaths(v, `${path27}[${i}]`, depth + 1, out));
59334
59921
  return out;
59335
59922
  }
59336
59923
  for (const [k, v] of Object.entries(value3)) {
59337
59924
  if (out.length >= 20) break;
59338
- const child = path26 ? `${path26}.${k}` : k;
59925
+ const child = path27 ? `${path27}.${k}` : k;
59339
59926
  if (isWorkflowSecretKey(k) && v !== null && v !== void 0 && typeof v !== "object") out.push(child);
59340
59927
  else reservedSecretKeyPaths(v, child, depth + 1, out);
59341
59928
  }
@@ -59796,10 +60383,10 @@ async function exportCore(ctx, name, o) {
59796
60383
  return apiFailure(ctx, res, "export");
59797
60384
  }
59798
60385
  const fs20 = await import("fs");
59799
- const path26 = await import("path");
59800
- const outDir = path26.resolve(o.out ?? ".");
60386
+ const path27 = await import("path");
60387
+ const outDir = path27.resolve(o.out ?? ".");
59801
60388
  const d = res.data;
59802
- const escaping = d.files.filter((f) => !path26.resolve(outDir, f.path).startsWith(outDir + path26.sep));
60389
+ const escaping = d.files.filter((f) => !path27.resolve(outDir, f.path).startsWith(outDir + path27.sep));
59803
60390
  if (escaping.length > 0) {
59804
60391
  if (ctx.json) {
59805
60392
  emitJson(ctx, {
@@ -59858,14 +60445,14 @@ async function exportCore(ctx, name, o) {
59858
60445
  }, null, 2));
59859
60446
  return WORKFLOW_EXIT.OK;
59860
60447
  }
59861
- const clash = d.files.filter((f) => fs20.existsSync(path26.join(outDir, f.path)));
60448
+ const clash = d.files.filter((f) => fs20.existsSync(path27.join(outDir, f.path)));
59862
60449
  if (clash.length > 0 && !o.force) {
59863
60450
  console.error(`\u274C export: ${clash.map((f) => f.path).join(", ")} already exist${clash.length === 1 ? "s" : ""} under ${outDir} \u2014 pass --force to overwrite, or --out <dir>`);
59864
60451
  return WORKFLOW_EXIT.API;
59865
60452
  }
59866
60453
  for (const f of d.files) {
59867
- const target = path26.join(outDir, f.path);
59868
- fs20.mkdirSync(path26.dirname(target), {
60454
+ const target = path27.join(outDir, f.path);
60455
+ fs20.mkdirSync(path27.dirname(target), {
59869
60456
  recursive: true
59870
60457
  });
59871
60458
  fs20.writeFileSync(target, f.contents);
@@ -59909,7 +60496,7 @@ var archiveDownload = {
59909
60496
  };
59910
60497
  async function archiveRunsCore(ctx, o) {
59911
60498
  const fs20 = await import("fs");
59912
- const path26 = await import("path");
60499
+ const path27 = await import("path");
59913
60500
  const crypto5 = await import("crypto");
59914
60501
  const now = Date.now();
59915
60502
  const since = parseSinceFlag(o.since, now);
@@ -59943,7 +60530,7 @@ async function archiveRunsCore(ctx, o) {
59943
60530
  fs20.mkdirSync(o.out, {
59944
60531
  recursive: true
59945
60532
  });
59946
- const indexFile = path26.join(o.out, "archive-index.ndjson");
60533
+ const indexFile = path27.join(o.out, "archive-index.ndjson");
59947
60534
  const indexed = /* @__PURE__ */ new Map();
59948
60535
  if (fs20.existsSync(indexFile)) {
59949
60536
  for (const line of fs20.readFileSync(indexFile, "utf8").split("\n")) {
@@ -59998,7 +60585,7 @@ async function archiveRunsCore(ctx, o) {
59998
60585
  ...apiRow,
59999
60586
  id: runIdOf(apiRow)
60000
60587
  };
60001
- const zipFile = path26.join(o.out, `${run.id}.zip`);
60588
+ const zipFile = path27.join(o.out, `${run.id}.zip`);
60002
60589
  const prior = indexed.get(run.id);
60003
60590
  const completedAt = run.completedAt ? Date.parse(run.completedAt) : NaN;
60004
60591
  if (prior && run.exportedAt && Number.isFinite(completedAt) && Date.parse(run.exportedAt) >= completedAt && fs20.existsSync(zipFile) && sha256(fs20.readFileSync(zipFile)) === prior.sha256) {
@@ -60866,10 +61453,10 @@ function parseJudgePredicateFlag(raw) {
60866
61453
  } : {}
60867
61454
  };
60868
61455
  }
60869
- const [path26, op, ...rest] = raw.trim().split(/\s+/);
60870
- if (!path26 || !op || !GOAL_PREDICATE_OPS.includes(op)) throw new WorkflowLocalUsageError("usage", `--judge-predicate: expected "<path> <op> [value]" with op ${opList} (got "${raw}")`);
61456
+ const [path27, op, ...rest] = raw.trim().split(/\s+/);
61457
+ if (!path27 || !op || !GOAL_PREDICATE_OPS.includes(op)) throw new WorkflowLocalUsageError("usage", `--judge-predicate: expected "<path> <op> [value]" with op ${opList} (got "${raw}")`);
60871
61458
  if (rest.length === 0) return {
60872
- path: path26,
61459
+ path: path27,
60873
61460
  op
60874
61461
  };
60875
61462
  const text = rest.join(" ");
@@ -60879,7 +61466,7 @@ function parseJudgePredicateFlag(raw) {
60879
61466
  } catch {
60880
61467
  }
60881
61468
  return {
60882
- path: path26,
61469
+ path: path27,
60883
61470
  op,
60884
61471
  value: value3
60885
61472
  };