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/api-exports.d.ts +41 -21
- package/dist/api-exports.js +161 -16
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +1006 -419
- package/dist/index.js.map +1 -1
- package/dist/voice/test/index.d.ts +18 -18
- package/dist/workflow-builder.d.ts +19 -3
- package/dist/workflow-builder.js +151 -6
- package/dist/workflow-builder.js.map +1 -1
- package/docs/workflows/workspaces-and-long-steps.md +1 -1
- package/package.json +3 -3
- package/template/package.json +1 -1
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
|
|
1755
|
+
const path27 = url.pathname.replace(/\/+$/, "");
|
|
1756
1756
|
if (!rule.segment) {
|
|
1757
|
-
const base2 =
|
|
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 =
|
|
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 =
|
|
1772
|
-
const afterMarker =
|
|
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((
|
|
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
|
-
|
|
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
|
|
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 ||
|
|
6684
|
-
if (
|
|
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
|
-
|
|
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,
|
|
6773
|
-
if (
|
|
6774
|
-
const parts =
|
|
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 ${
|
|
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
|
|
6964
|
-
if (!
|
|
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 \`${
|
|
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:
|
|
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:
|
|
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,
|
|
7131
|
+
function readPath(root, path27) {
|
|
7013
7132
|
let cur = root;
|
|
7014
|
-
for (const seg of
|
|
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:
|
|
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:
|
|
7173
|
+
path: path27,
|
|
7055
7174
|
reason: "input-not-object",
|
|
7056
7175
|
message: modelTemplateInputNotObjectMessage(placeholder, initData)
|
|
7057
7176
|
};
|
|
7058
7177
|
}
|
|
7059
|
-
const value22 = readPath(initData,
|
|
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:
|
|
7193
|
+
path: path27,
|
|
7075
7194
|
reason,
|
|
7076
|
-
message: modelTemplateUnboundMessage(placeholder,
|
|
7195
|
+
message: modelTemplateUnboundMessage(placeholder, path27, reason)
|
|
7077
7196
|
};
|
|
7078
7197
|
}
|
|
7079
|
-
function modelTemplateUnboundMessage(placeholder,
|
|
7080
|
-
const what = reason === "unbound" ? `the run input has no ${WORKFLOW_MODEL_TEMPLATE_ROOT}.${
|
|
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}.${
|
|
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,
|
|
7240
|
+
const push = /* @__PURE__ */ __name4((code, path27, message, severity = "error") => issues.push({
|
|
7122
7241
|
code,
|
|
7123
|
-
path:
|
|
7242
|
+
path: path27,
|
|
7124
7243
|
severity,
|
|
7125
7244
|
message
|
|
7126
7245
|
}), "push");
|
|
7127
|
-
const checkSpec = /* @__PURE__ */ __name4((spec,
|
|
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",
|
|
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:
|
|
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",
|
|
7150
|
-
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable",
|
|
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", `${
|
|
7154
|
-
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${
|
|
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(
|
|
7331
|
-
return `${
|
|
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,
|
|
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
|
|
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,
|
|
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:
|
|
7544
|
+
path: path27,
|
|
7417
7545
|
stepId
|
|
7418
7546
|
});
|
|
7419
7547
|
}, "err");
|
|
7420
|
-
const warn = /* @__PURE__ */ __name4((code, message,
|
|
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:
|
|
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
|
|
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}`, `${
|
|
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`, `${
|
|
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')`, `${
|
|
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,
|
|
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)})`,
|
|
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,
|
|
7620
|
+
seen.set(id2, path27);
|
|
7493
7621
|
}
|
|
7494
7622
|
}, "checkId");
|
|
7495
|
-
const checkPolicyEnums = /* @__PURE__ */ __name4((node,
|
|
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)})`, `${
|
|
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,
|
|
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), `${
|
|
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), `${
|
|
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}`, `${
|
|
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", `${
|
|
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'", `${
|
|
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", `${
|
|
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,
|
|
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})`, `${
|
|
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`, `${
|
|
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`, `${
|
|
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)`, `${
|
|
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,
|
|
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", `${
|
|
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'", `${
|
|
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)", `${
|
|
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`, `${
|
|
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`, `${
|
|
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(", ")}`, `${
|
|
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,
|
|
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(`${
|
|
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`, `${
|
|
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,
|
|
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'", `${
|
|
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", `${
|
|
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})`, `${
|
|
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(", ")}]`, `${
|
|
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,
|
|
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, `${
|
|
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), `${
|
|
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)`), `${
|
|
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)), `${
|
|
7782
|
+
if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path27}.model`, id2);
|
|
7655
7783
|
}, "checkModel");
|
|
7656
|
-
const checkTaskClass = /* @__PURE__ */ __name4((node,
|
|
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`, `${
|
|
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,
|
|
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)`, `${
|
|
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'", `${
|
|
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(", ")}]`, `${
|
|
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)`, `${
|
|
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, `${
|
|
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, `${
|
|
7694
|
-
if (node.type !== "agent") err("plugins-invalid", "`plugins` is legal on agent steps only", `${
|
|
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'", `${
|
|
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'`)", `${
|
|
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", `${
|
|
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`, `${
|
|
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`, `${
|
|
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')`, `${
|
|
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`, `${
|
|
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`, `${
|
|
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,
|
|
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, `${
|
|
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)})`, `${
|
|
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,
|
|
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`, `${
|
|
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,
|
|
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,
|
|
7754
|
-
err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${
|
|
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,
|
|
7759
|
-
err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId),
|
|
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),
|
|
7763
|
-
checkPolicyEnums(node,
|
|
7764
|
-
checkInputShape(node,
|
|
7765
|
-
checkTimeout(node,
|
|
7766
|
-
checkTier(node,
|
|
7767
|
-
checkModel(node,
|
|
7768
|
-
checkTaskClass(node,
|
|
7769
|
-
checkRetry(node,
|
|
7770
|
-
checkWorkspace(node,
|
|
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)",
|
|
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)", `${
|
|
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", `${
|
|
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", `${
|
|
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", `${
|
|
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,
|
|
7787
|
-
checkRequiredConnections(node,
|
|
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}`,
|
|
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`,
|
|
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`,
|
|
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,
|
|
7933
|
+
const checkHitl = /* @__PURE__ */ __name4((node, path27) => {
|
|
7801
7934
|
if (node.type === "waitForSignal") {
|
|
7802
7935
|
const w = node;
|
|
7803
|
-
checkId(w.id,
|
|
7804
|
-
if (typeof w.signal !== "string" || w.signal.length === 0) err("invalid-envelope", "waitForSignal.signal is required", `${
|
|
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,
|
|
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",
|
|
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", `${
|
|
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", `${
|
|
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)", `${
|
|
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`, `${
|
|
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", `${
|
|
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", `${
|
|
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`,
|
|
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,
|
|
7972
|
+
const checkHitlArm = /* @__PURE__ */ __name4((node, path27, container) => {
|
|
7840
7973
|
if (!workflowContainerRunsHitlArm(container)) {
|
|
7841
|
-
checkId(node.id,
|
|
7842
|
-
err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container),
|
|
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,
|
|
7978
|
+
checkHitl(node, path27);
|
|
7846
7979
|
}, "checkHitlArm");
|
|
7847
|
-
const checkArm = /* @__PURE__ */ __name4((arm,
|
|
7980
|
+
const checkArm = /* @__PURE__ */ __name4((arm, path27, depth, container) => {
|
|
7848
7981
|
if (arm.type === "mapping") {
|
|
7849
|
-
checkId(arm.id,
|
|
7850
|
-
checkMapMembers(readMapConfig(arm.mapConfig), `${
|
|
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`,
|
|
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,
|
|
7990
|
+
checkHitlArm(arm, path27, container);
|
|
7858
7991
|
return;
|
|
7859
7992
|
}
|
|
7860
|
-
checkSingle(arm,
|
|
7993
|
+
checkSingle(arm, path27, depth);
|
|
7861
7994
|
}, "checkArm");
|
|
7862
7995
|
graph.forEach((entry, i) => {
|
|
7863
|
-
const
|
|
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,
|
|
8003
|
+
checkSingle(entry, path27, 1);
|
|
7871
8004
|
declared.push(singleId(entry));
|
|
7872
8005
|
break;
|
|
7873
8006
|
case "mapping":
|
|
7874
|
-
checkId(entry.id,
|
|
7875
|
-
checkMapMembers(readMapConfig(entry.mapConfig), `${
|
|
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`,
|
|
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,
|
|
7883
|
-
if (!Number.isFinite(entry.duration) || entry.duration < 0) err("invalid-envelope", "sleep.duration must be a non-negative number", `${
|
|
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,
|
|
7889
|
-
err("node-type-unsupported-by-engine", sleepUntilUnsupportedMessage(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`",
|
|
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`, `${
|
|
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})`,
|
|
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 = `${
|
|
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",
|
|
7916
|
-
if (worktreeArms.length === 0 && p.merge) err("merge-requires-worktree-arms", "`merge` needs at least one worktree arm",
|
|
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`,
|
|
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`, `${
|
|
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",
|
|
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", `${
|
|
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, `${
|
|
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, `${
|
|
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}`, `${
|
|
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)`, `${
|
|
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}`, `${
|
|
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" ? `${
|
|
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", `${
|
|
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}]`, `${
|
|
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}]`, `${
|
|
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`, `${
|
|
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", `${
|
|
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, `${
|
|
7996
|
-
err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(f.step.type, f.step.id, "chunked-foreach"), `${
|
|
7997
|
-
} else checkHitlArm(f.step, `${
|
|
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, `${
|
|
8001
|
-
checkSingle(f.step, `${
|
|
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", `${
|
|
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}`, `${
|
|
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", `${
|
|
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", `${
|
|
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, `${
|
|
8151
|
+
checkHitlArm(l.step, `${path27}.step`, "loop");
|
|
8019
8152
|
declared.push(l.step.id);
|
|
8020
8153
|
} else {
|
|
8021
|
-
checkBodyInput(l.step, `${
|
|
8022
|
-
checkSingle(l.step, `${
|
|
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,
|
|
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}"`,
|
|
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
|
|
8283
|
-
if (
|
|
8284
|
-
const dot =
|
|
8285
|
-
const scope = dot === -1 ?
|
|
8286
|
-
const rest = 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,
|
|
8321
|
-
if (
|
|
8322
|
-
const parts =
|
|
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(
|
|
8581
|
+
function init(path27) {
|
|
8449
8582
|
return {
|
|
8450
|
-
path:
|
|
8583
|
+
path: path27 === "" ? "initData" : `initData.${path27}`
|
|
8451
8584
|
};
|
|
8452
8585
|
}
|
|
8453
|
-
function state(
|
|
8586
|
+
function state(path27) {
|
|
8454
8587
|
return {
|
|
8455
|
-
path:
|
|
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,
|
|
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:
|
|
9528
|
+
path: path27,
|
|
9396
9529
|
message: "not an object"
|
|
9397
9530
|
}
|
|
9398
9531
|
];
|
|
9399
9532
|
const c = cal;
|
|
9400
|
-
if (!timeZoneSupported(c.tz)) issue(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
9413
|
-
if (!endOk) issue(`${
|
|
9414
|
-
if (startOk && endOk && toMinutes(k.start) >= toMinutes(k.end)) issue(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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(`${
|
|
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((
|
|
10452
|
+
fromInit = /* @__PURE__ */ __name4((path27) => ({
|
|
10320
10453
|
initData: true,
|
|
10321
|
-
path:
|
|
10454
|
+
path: path27
|
|
10322
10455
|
}), "fromInit");
|
|
10323
|
-
fromStep = /* @__PURE__ */ __name4((s,
|
|
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:
|
|
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((
|
|
10337
|
-
requestContextPath:
|
|
10469
|
+
fromRequest = /* @__PURE__ */ __name4((path27) => ({
|
|
10470
|
+
requestContextPath: path27
|
|
10338
10471
|
}), "fromRequest");
|
|
10339
|
-
rows = /* @__PURE__ */ __name4((s,
|
|
10472
|
+
rows = /* @__PURE__ */ __name4((s, path27, page) => ({
|
|
10340
10473
|
step: typeof s === "string" ? s : s.id,
|
|
10341
|
-
path:
|
|
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
|
|
11341
|
-
if (
|
|
11477
|
+
const path27 = items.path;
|
|
11478
|
+
if (path27.startsWith("initData")) return {
|
|
11342
11479
|
initData: true,
|
|
11343
|
-
path:
|
|
11480
|
+
path: path27 === "initData" ? "" : path27.slice("initData.".length)
|
|
11344
11481
|
};
|
|
11345
|
-
if (
|
|
11346
|
-
const rest =
|
|
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 "${
|
|
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("
|
|
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(
|
|
13453
|
+
url(path27) {
|
|
13308
13454
|
const base = this.options.baseUrl.replace(/\/$/, "");
|
|
13309
|
-
return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${
|
|
13455
|
+
return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${path27}`;
|
|
13310
13456
|
}
|
|
13311
|
-
async json(method,
|
|
13312
|
-
const endpoint = this.url(
|
|
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} ${
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
20567
|
-
errors.push(validationError(`Voice config invalid at \`${
|
|
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
|
|
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 =
|
|
24130
|
-
const outfile =
|
|
24131
|
-
const sourceDir =
|
|
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 =
|
|
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(
|
|
24252
|
-
const srcDir =
|
|
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 =
|
|
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(".") ?
|
|
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,
|
|
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,
|
|
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:
|
|
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
|
|
24414
|
-
import
|
|
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:
|
|
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
|
-
|
|
24591
|
-
|
|
24592
|
-
|
|
24593
|
-
|
|
24594
|
-
|
|
24595
|
-
|
|
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 || !
|
|
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 (!
|
|
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 ${
|
|
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
|
|
25349
|
+
import path12 from "path";
|
|
24772
25350
|
function findWorkspaceRoot(rootDir) {
|
|
24773
|
-
const resolvedInput =
|
|
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 } =
|
|
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 =
|
|
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(
|
|
24792
|
-
if (fileExists(
|
|
24793
|
-
if (packageJsonHasWorkspaces(
|
|
24794
|
-
if (dirExists(
|
|
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
|
|
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:
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(`${
|
|
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 =
|
|
25248
|
-
const sourcesDir =
|
|
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(
|
|
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 =
|
|
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(
|
|
25852
|
+
await fs10.writeFile(path13.join(primitiveDir, `${baseName}.js`), primitive.artifact.code);
|
|
25275
25853
|
if (primitive.artifact.sourceMap) {
|
|
25276
|
-
await fs10.writeFile(
|
|
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(
|
|
25282
|
-
const relativePath =
|
|
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(
|
|
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 ?
|
|
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 =
|
|
25314
|
-
await fs10.writeFile(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
26136
|
+
import { Project as Project4, Node as Node21 } from "ts-morph";
|
|
25559
26137
|
import fs12 from "fs";
|
|
25560
|
-
import
|
|
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 =
|
|
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 =
|
|
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 (
|
|
26185
|
+
if (Node21.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
|
|
25608
26186
|
const args2 = node.getArguments();
|
|
25609
|
-
if (args2.length > 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 (
|
|
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 (
|
|
26255
|
+
if (Node21.isNewExpression(node) && node.getExpression().getText() === "LuaAgent") {
|
|
25678
26256
|
const args2 = node.getArguments();
|
|
25679
|
-
if (args2.length > 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 (
|
|
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
|
|
28449
|
-
const scopedPath = agentId ? `${
|
|
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
|
|
28460
|
-
const scopedPath = agentId ? `${
|
|
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
|
|
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 =
|
|
31494
|
-
const ext =
|
|
31495
|
-
const sourcePath =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
31537
|
-
const sourceTargetPath =
|
|
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
|
|
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(
|
|
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 =
|
|
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 =
|
|
31736
|
-
if (absPath !== projectRoot && !absPath.startsWith(projectRoot +
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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((
|
|
36175
|
-
path:
|
|
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
|
|
36768
|
+
import path22 from "path";
|
|
36191
36769
|
|
|
36192
36770
|
// src/utils/env-loader.utils.ts
|
|
36193
|
-
import
|
|
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 =
|
|
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
|
|
36876
|
+
import path21 from "path";
|
|
36299
36877
|
|
|
36300
36878
|
// src/utils/workflow-exec.ts
|
|
36301
|
-
import
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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) =>
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 ?
|
|
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(
|
|
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 =
|
|
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,
|
|
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: `${
|
|
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: `${
|
|
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: `${
|
|
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: `${
|
|
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: `${
|
|
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: `${
|
|
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: `${
|
|
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,
|
|
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, `${
|
|
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 :
|
|
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,
|
|
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 =
|
|
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
|
|
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 ?
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
51339
|
-
return finalize ? this.httpPost(
|
|
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
|
|
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(
|
|
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(
|
|
58001
|
+
fs19.writeFileSync(path26.join(root, "tsconfig.json"), `${JSON.stringify(EXPORT_CHECK_TSCONFIG, null, 2)}
|
|
57415
58002
|
`);
|
|
57416
|
-
fs19.writeFileSync(
|
|
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 =
|
|
57425
|
-
if (!target.startsWith(root +
|
|
57426
|
-
fs19.mkdirSync(
|
|
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:
|
|
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 ?
|
|
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,
|
|
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, `${
|
|
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 =
|
|
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
|
|
59800
|
-
const outDir =
|
|
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) => !
|
|
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(
|
|
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 =
|
|
59868
|
-
fs20.mkdirSync(
|
|
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
|
|
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 =
|
|
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 =
|
|
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 [
|
|
60870
|
-
if (!
|
|
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:
|
|
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:
|
|
61469
|
+
path: path27,
|
|
60883
61470
|
op,
|
|
60884
61471
|
value: value3
|
|
60885
61472
|
};
|