lua-cli 3.41.0 → 3.42.0-beta.1
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 +57 -33
- package/dist/api-exports.js +32 -6
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +2124 -501
- package/dist/index.js.map +1 -1
- package/dist/voice/test/index.d.ts +18 -18
- package/dist/workflow-builder.js +26 -2
- package/dist/workflow-builder.js.map +1 -1
- package/docs/workflows/reply-channels.md +2 -2
- package/package.json +4 -3
- package/template/package.json +1 -1
- package/template/tsconfig.json +1 -1
- package/template-web-app/app.ts +29 -0
- package/template-web-app/web/index.html +12 -0
- package/template-web-app/web/package.json +27 -0
- package/template-web-app/web/src/App.tsx +28 -0
- package/template-web-app/web/src/index.css +3 -0
- package/template-web-app/web/src/lua/client.ts +254 -0
- package/template-web-app/web/src/main.tsx +16 -0
- package/template-web-app/web/tsconfig.json +14 -0
- package/template-web-app/web/vite.config.ts +9 -0
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 path30 = url.pathname.replace(/\/+$/, "");
|
|
1756
1756
|
if (!rule.segment) {
|
|
1757
|
-
const base2 =
|
|
1757
|
+
const base2 = path30.endsWith(rule.path) ? path30.slice(0, path30.length - rule.path.length) : path30;
|
|
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 = path30.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 = path30.slice(0, at);
|
|
1772
|
+
const afterMarker = path30.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((path30) => path30.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 = "";
|
|
@@ -3345,7 +3345,7 @@ function envTemplatePlaceholder(key) {
|
|
|
3345
3345
|
__envRef: key
|
|
3346
3346
|
};
|
|
3347
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;
|
|
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, onboardingInstallScreenSchema, onboardingResultScreenSchema, onboardingConnectScreenSchema, 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_WALL_MS, WEB_ROUTE_MAX_REQUEST_BODY_BYTES, WEB_ROUTE_MAX_RESPONSE_BYTES, WEB_APP_NAME_PATTERN, WEB_APP_ENTRY_HTML_MAX_CHARS, WEB_APP_MAX_ASSETS, WEB_APP_ASSET_PATH_PATTERN, WEB_APP_ASSET_PATH_MAX_CHARS, WEB_APP_MAX_ROUTES, WEB_APP_MAX_ASSET_BYTES, WEB_APP_CSP_NONCE_PLACEHOLDER, 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;
|
|
3349
3349
|
var init_dist = __esm({
|
|
3350
3350
|
"../shared-types/dist/index.mjs"() {
|
|
3351
3351
|
"use strict";
|
|
@@ -3428,7 +3428,8 @@ var init_dist = __esm({
|
|
|
3428
3428
|
"sendWebchatMessage",
|
|
3429
3429
|
"sendTeamsMessage",
|
|
3430
3430
|
"sendInstagramMessage",
|
|
3431
|
-
"sendMessengerMessage"
|
|
3431
|
+
"sendMessengerMessage",
|
|
3432
|
+
"sendSlackMessage"
|
|
3432
3433
|
];
|
|
3433
3434
|
__name(isAllowedReviewableExecuteTool, "isAllowedReviewableExecuteTool");
|
|
3434
3435
|
__name2(isAllowedReviewableExecuteTool, "isAllowedReviewableExecuteTool");
|
|
@@ -5765,6 +5766,24 @@ listed here; never invent a target.`;
|
|
|
5765
5766
|
label: copy(100),
|
|
5766
5767
|
body: onboardingRichTextSchema
|
|
5767
5768
|
}).strict();
|
|
5769
|
+
onboardingInstallScreenSchema = z4.object({
|
|
5770
|
+
title: onboardingHeadingSchema,
|
|
5771
|
+
subtitle: copy(240),
|
|
5772
|
+
ctaLabel: copy(80),
|
|
5773
|
+
ctaHelperText: onboardingRichTextSchema
|
|
5774
|
+
}).strict();
|
|
5775
|
+
onboardingResultScreenSchema = z4.object({
|
|
5776
|
+
title: onboardingHeadingSchema,
|
|
5777
|
+
subheader: copy(240),
|
|
5778
|
+
inputPlaceholder: copy(120)
|
|
5779
|
+
}).strict();
|
|
5780
|
+
onboardingConnectScreenSchema = z4.object({
|
|
5781
|
+
title: onboardingHeadingSchema,
|
|
5782
|
+
description: onboardingRichTextSchema,
|
|
5783
|
+
ctaLabel: copy(80),
|
|
5784
|
+
neverLine: copy(120),
|
|
5785
|
+
footnote: copy(240)
|
|
5786
|
+
}).strict();
|
|
5768
5787
|
onboardingTemplateContentSchema = z4.object({
|
|
5769
5788
|
id,
|
|
5770
5789
|
templateId: copy(160),
|
|
@@ -5777,7 +5796,10 @@ listed here; never invent a target.`;
|
|
|
5777
5796
|
artwork: onboardingArtworkSchema,
|
|
5778
5797
|
hireButtonLabel: copy(80),
|
|
5779
5798
|
changeRoleButtonLabel: copy(80),
|
|
5780
|
-
nextStepText: onboardingRichTextSchema
|
|
5799
|
+
nextStepText: onboardingRichTextSchema,
|
|
5800
|
+
install: onboardingInstallScreenSchema.optional(),
|
|
5801
|
+
result: onboardingResultScreenSchema.optional(),
|
|
5802
|
+
connect: onboardingConnectScreenSchema.optional()
|
|
5781
5803
|
}).strict();
|
|
5782
5804
|
onboardingUnavailableOutcomeSchema = z4.object({
|
|
5783
5805
|
id,
|
|
@@ -5937,6 +5959,7 @@ listed here; never invent a target.`;
|
|
|
5937
5959
|
__name2(isForwardableWebRouteRequestHeader, "isForwardableWebRouteRequestHeader");
|
|
5938
5960
|
__name(isForwardableWebRouteResponseHeader, "isForwardableWebRouteResponseHeader");
|
|
5939
5961
|
__name2(isForwardableWebRouteResponseHeader, "isForwardableWebRouteResponseHeader");
|
|
5962
|
+
WEB_ROUTE_MAX_WALL_MS = 6e4;
|
|
5940
5963
|
WEB_ROUTE_MAX_REQUEST_BODY_BYTES = 1 * 1024 * 1024;
|
|
5941
5964
|
WEB_ROUTE_MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
5942
5965
|
__name(isWebRouteBody, "isWebRouteBody");
|
|
@@ -5947,6 +5970,14 @@ listed here; never invent a target.`;
|
|
|
5947
5970
|
__name2(isQueryRecord, "isQueryRecord");
|
|
5948
5971
|
__name(isWebRouteInput, "isWebRouteInput");
|
|
5949
5972
|
__name2(isWebRouteInput, "isWebRouteInput");
|
|
5973
|
+
WEB_APP_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
5974
|
+
WEB_APP_ENTRY_HTML_MAX_CHARS = 256 * 1024;
|
|
5975
|
+
WEB_APP_MAX_ASSETS = 1e3;
|
|
5976
|
+
WEB_APP_ASSET_PATH_PATTERN = /^assets\/(?!.*\.\.)[A-Za-z0-9._\-/]+$/;
|
|
5977
|
+
WEB_APP_ASSET_PATH_MAX_CHARS = 512;
|
|
5978
|
+
WEB_APP_MAX_ROUTES = 200;
|
|
5979
|
+
WEB_APP_MAX_ASSET_BYTES = 8 * 1024 * 1024;
|
|
5980
|
+
WEB_APP_CSP_NONCE_PLACEHOLDER = "__LUA_CSP_NONCE__";
|
|
5950
5981
|
EVIDENCE_SESSION_IDLE_MS = 30 * 6e4;
|
|
5951
5982
|
EVIDENCE_MIN_CONVERSATIONS = 20;
|
|
5952
5983
|
EVIDENCE_LOW_CONFIDENCE_N = 5;
|
|
@@ -6125,8 +6156,8 @@ function uidFromFirebaseIdToken(idToken) {
|
|
|
6125
6156
|
if (parsed.success) return parsed.data.sub;
|
|
6126
6157
|
throw new Error(INVALID_FIREBASE_SESSION);
|
|
6127
6158
|
}
|
|
6128
|
-
function parseFirebaseSession(
|
|
6129
|
-
const customTokenResponse = customTokenResponseSchema.safeParse(
|
|
6159
|
+
function parseFirebaseSession(json2, now = Date.now()) {
|
|
6160
|
+
const customTokenResponse = customTokenResponseSchema.safeParse(json2);
|
|
6130
6161
|
if (customTokenResponse.success) {
|
|
6131
6162
|
const { idToken: idToken2, refreshToken: refreshToken2, expiresIn: expiresIn2, localId } = customTokenResponse.data;
|
|
6132
6163
|
return {
|
|
@@ -6136,7 +6167,7 @@ function parseFirebaseSession(json, now = Date.now()) {
|
|
|
6136
6167
|
uid: localId ?? uidFromFirebaseIdToken(idToken2)
|
|
6137
6168
|
};
|
|
6138
6169
|
}
|
|
6139
|
-
const refreshResponse = refreshResponseSchema.safeParse(
|
|
6170
|
+
const refreshResponse = refreshResponseSchema.safeParse(json2);
|
|
6140
6171
|
if (!refreshResponse.success) throw new Error(INVALID_FIREBASE_SESSION);
|
|
6141
6172
|
const { id_token: idToken, refresh_token: refreshToken, expires_in: expiresIn, user_id: uid } = refreshResponse.data;
|
|
6142
6173
|
return {
|
|
@@ -6727,9 +6758,9 @@ function workflowJobTargetProblem(target, plugins, luaApi) {
|
|
|
6727
6758
|
if (!hasPlugins && luaApi !== true) return "`target` is legal only beside `plugins` or `luaApi: true`";
|
|
6728
6759
|
return null;
|
|
6729
6760
|
}
|
|
6730
|
-
function readInitDataPath(root,
|
|
6761
|
+
function readInitDataPath(root, path30) {
|
|
6731
6762
|
let cur = root;
|
|
6732
|
-
for (const seg of
|
|
6763
|
+
for (const seg of path30.split(".")) {
|
|
6733
6764
|
const name = seg.replace(/\[(?:0|[1-9]\d*)\]/g, "");
|
|
6734
6765
|
const indexes = [
|
|
6735
6766
|
...seg.matchAll(/\[(0|[1-9]\d*)\]/g)
|
|
@@ -6762,25 +6793,25 @@ function renderWorkflowJobTarget(target, initData) {
|
|
|
6762
6793
|
templated: false
|
|
6763
6794
|
};
|
|
6764
6795
|
}
|
|
6765
|
-
const
|
|
6766
|
-
if (
|
|
6796
|
+
const path30 = workflowJobTargetTemplatePath(agentId);
|
|
6797
|
+
if (path30 === null) return {
|
|
6767
6798
|
ok: false,
|
|
6768
6799
|
reason: "invalid",
|
|
6769
6800
|
message: "target.agentId is not a valid initData template"
|
|
6770
6801
|
};
|
|
6771
|
-
const value3 = readInitDataPath(initData,
|
|
6802
|
+
const value3 = readInitDataPath(initData, path30);
|
|
6772
6803
|
if (value3 === void 0 || value3 === null) {
|
|
6773
6804
|
return {
|
|
6774
6805
|
ok: false,
|
|
6775
6806
|
reason: "unbound",
|
|
6776
|
-
message: `target_unresolved: the run input has no initData.${
|
|
6807
|
+
message: `target_unresolved: the run input has no initData.${path30}`
|
|
6777
6808
|
};
|
|
6778
6809
|
}
|
|
6779
6810
|
if (typeof value3 !== "string" || !value3.trim() || value3.length > 256 || /\s/.test(value3.trim())) {
|
|
6780
6811
|
return {
|
|
6781
6812
|
ok: false,
|
|
6782
6813
|
reason: "empty",
|
|
6783
|
-
message: `target_unresolved: initData.${
|
|
6814
|
+
message: `target_unresolved: initData.${path30} is not a non-empty agent id`
|
|
6784
6815
|
};
|
|
6785
6816
|
}
|
|
6786
6817
|
return {
|
|
@@ -6888,13 +6919,13 @@ function parseTemplatePlaceholder(rawExpr) {
|
|
|
6888
6919
|
rest: dot === -1 ? "" : rawExpr.slice(dot + 1)
|
|
6889
6920
|
};
|
|
6890
6921
|
}
|
|
6891
|
-
function traverseMappingPath(root,
|
|
6892
|
-
if (
|
|
6893
|
-
const parts =
|
|
6922
|
+
function traverseMappingPath(root, path30, errorLabel2) {
|
|
6923
|
+
if (path30 === "" || path30 === ".") return root;
|
|
6924
|
+
const parts = path30.split(".");
|
|
6894
6925
|
let value22 = root;
|
|
6895
6926
|
for (const part of parts) {
|
|
6896
6927
|
if (typeof value22 === "object" && value22 !== null) value22 = value22[part];
|
|
6897
|
-
else throw new WorkflowTemplateError(`Invalid path ${
|
|
6928
|
+
else throw new WorkflowTemplateError(`Invalid path ${path30} in ${errorLabel2}`, path30);
|
|
6898
6929
|
}
|
|
6899
6930
|
return value22;
|
|
6900
6931
|
}
|
|
@@ -7079,11 +7110,11 @@ function parseModelTemplate(model) {
|
|
|
7079
7110
|
message: modelTemplateInvalidMessage(model, why)
|
|
7080
7111
|
};
|
|
7081
7112
|
}
|
|
7082
|
-
const
|
|
7083
|
-
if (!
|
|
7113
|
+
const path30 = m[1];
|
|
7114
|
+
if (!path30.split(".").every((seg) => PATH_SEGMENT_RE.test(seg))) {
|
|
7084
7115
|
return {
|
|
7085
7116
|
kind: "invalid",
|
|
7086
|
-
message: modelTemplateInvalidMessage(model, `the path \`${
|
|
7117
|
+
message: modelTemplateInvalidMessage(model, `the path \`${path30}\` is not a dotted path of names and canonical [n] indexes`)
|
|
7087
7118
|
};
|
|
7088
7119
|
}
|
|
7089
7120
|
if (m[2] !== void 0) {
|
|
@@ -7102,7 +7133,7 @@ function parseModelTemplate(model) {
|
|
|
7102
7133
|
kind: "template",
|
|
7103
7134
|
template: {
|
|
7104
7135
|
placeholder: trimmed2,
|
|
7105
|
-
path:
|
|
7136
|
+
path: path30,
|
|
7106
7137
|
default: dflt
|
|
7107
7138
|
}
|
|
7108
7139
|
};
|
|
@@ -7111,7 +7142,7 @@ function parseModelTemplate(model) {
|
|
|
7111
7142
|
kind: "template",
|
|
7112
7143
|
template: {
|
|
7113
7144
|
placeholder: trimmed2,
|
|
7114
|
-
path:
|
|
7145
|
+
path: path30
|
|
7115
7146
|
}
|
|
7116
7147
|
};
|
|
7117
7148
|
}
|
|
@@ -7128,9 +7159,9 @@ function staticModelPin(model) {
|
|
|
7128
7159
|
if (parsed.kind === "template") return parsed.template.default;
|
|
7129
7160
|
return void 0;
|
|
7130
7161
|
}
|
|
7131
|
-
function readPath(root,
|
|
7162
|
+
function readPath(root, path30) {
|
|
7132
7163
|
let cur = root;
|
|
7133
|
-
for (const seg of
|
|
7164
|
+
for (const seg of path30.split(".")) {
|
|
7134
7165
|
const name = seg.replace(/\[(?:0|[1-9]\d*)\]/g, "");
|
|
7135
7166
|
const indexes = [
|
|
7136
7167
|
...seg.matchAll(/\[(0|[1-9]\d*)\]/g)
|
|
@@ -7165,17 +7196,17 @@ function renderModelTemplate(model, initData) {
|
|
|
7165
7196
|
model,
|
|
7166
7197
|
source: "static"
|
|
7167
7198
|
};
|
|
7168
|
-
const { placeholder, path:
|
|
7199
|
+
const { placeholder, path: path30 } = parsed.template;
|
|
7169
7200
|
if (initData !== void 0 && initData !== null && (typeof initData !== "object" || Array.isArray(initData))) {
|
|
7170
7201
|
return {
|
|
7171
7202
|
ok: false,
|
|
7172
7203
|
placeholder,
|
|
7173
|
-
path:
|
|
7204
|
+
path: path30,
|
|
7174
7205
|
reason: "input-not-object",
|
|
7175
7206
|
message: modelTemplateInputNotObjectMessage(placeholder, initData)
|
|
7176
7207
|
};
|
|
7177
7208
|
}
|
|
7178
|
-
const value22 = readPath(initData,
|
|
7209
|
+
const value22 = readPath(initData, path30);
|
|
7179
7210
|
const reason = value22 === void 0 || value22 === null ? "unbound" : typeof value22 !== "string" ? "not-a-string" : value22.trim() ? null : "empty";
|
|
7180
7211
|
if (reason === null) return {
|
|
7181
7212
|
ok: true,
|
|
@@ -7190,14 +7221,14 @@ function renderModelTemplate(model, initData) {
|
|
|
7190
7221
|
return {
|
|
7191
7222
|
ok: false,
|
|
7192
7223
|
placeholder,
|
|
7193
|
-
path:
|
|
7224
|
+
path: path30,
|
|
7194
7225
|
reason,
|
|
7195
|
-
message: modelTemplateUnboundMessage(placeholder,
|
|
7226
|
+
message: modelTemplateUnboundMessage(placeholder, path30, reason)
|
|
7196
7227
|
};
|
|
7197
7228
|
}
|
|
7198
|
-
function modelTemplateUnboundMessage(placeholder,
|
|
7199
|
-
const what = reason === "unbound" ? `the run input has no ${WORKFLOW_MODEL_TEMPLATE_ROOT}.${
|
|
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}.${
|
|
7229
|
+
function modelTemplateUnboundMessage(placeholder, path30, reason) {
|
|
7230
|
+
const what = reason === "unbound" ? `the run input has no ${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path30}` : reason === "empty" ? `${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path30} is empty on the run input` : `${WORKFLOW_MODEL_TEMPLATE_ROOT}.${path30} on the run input is not a string`;
|
|
7231
|
+
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}.${path30}|<provider/model>}`;
|
|
7201
7232
|
}
|
|
7202
7233
|
function modelTemplateInputNotObjectMessage(placeholder, initData) {
|
|
7203
7234
|
const type = Array.isArray(initData) ? "an array" : `a ${typeof initData}`;
|
|
@@ -7237,22 +7268,22 @@ function validateApproverBlock(node, opts = {
|
|
|
7237
7268
|
path: "approval"
|
|
7238
7269
|
}) {
|
|
7239
7270
|
const issues = [];
|
|
7240
|
-
const push = /* @__PURE__ */ __name4((code,
|
|
7271
|
+
const push = /* @__PURE__ */ __name4((code, path30, message, severity = "error") => issues.push({
|
|
7241
7272
|
code,
|
|
7242
|
-
path:
|
|
7273
|
+
path: path30,
|
|
7243
7274
|
severity,
|
|
7244
7275
|
message
|
|
7245
7276
|
}), "push");
|
|
7246
|
-
const checkSpec = /* @__PURE__ */ __name4((spec,
|
|
7277
|
+
const checkSpec = /* @__PURE__ */ __name4((spec, path30) => {
|
|
7247
7278
|
const r = ApproverSpecSchema.safeParse(spec);
|
|
7248
7279
|
if (!r.success) {
|
|
7249
7280
|
const users = spec?.users;
|
|
7250
|
-
if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded",
|
|
7281
|
+
if (Array.isArray(users) && users.length > APPROVER_SPEC_MAX_USERS) push("cap-exceeded", path30, `at most ${APPROVER_SPEC_MAX_USERS} users`);
|
|
7251
7282
|
else {
|
|
7252
7283
|
const refusal2 = describeApproverSpecRefusal(spec);
|
|
7253
7284
|
issues.push({
|
|
7254
7285
|
code: "approver-invalid",
|
|
7255
|
-
path:
|
|
7286
|
+
path: path30,
|
|
7256
7287
|
severity: "error",
|
|
7257
7288
|
message: refusal2.message,
|
|
7258
7289
|
repair: {
|
|
@@ -7265,12 +7296,12 @@ function validateApproverBlock(node, opts = {
|
|
|
7265
7296
|
}
|
|
7266
7297
|
const s = r.data;
|
|
7267
7298
|
if (typeof s === "object") {
|
|
7268
|
-
if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable",
|
|
7269
|
-
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable",
|
|
7299
|
+
if ("governance" in s && !opts.governanceEnabled) push("approver-governance-unavailable", path30, "governance reviewer routing is not enabled for this deployment");
|
|
7300
|
+
if ("group" in s && typeof s.group === "string" && !opts.scimEnabled && opts.idpGroups?.includes(s.group)) push("approver-idp-group-unavailable", path30, "IdP-group approvers are not enabled for this deployment");
|
|
7270
7301
|
const binding = "users" in s ? s.users : "role" in s ? s.role : "group" in s ? s.group : void 0;
|
|
7271
7302
|
if (isTemplateBinding(binding)) {
|
|
7272
|
-
if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${
|
|
7273
|
-
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${
|
|
7303
|
+
if (!bindingRootsOk(binding.template)) push("approver-binding-invalid", `${path30}.template`, "binding root must be initData / stepResults / requestContext / state");
|
|
7304
|
+
if ("users" in s && opts.customerReachable) push("approver-binding-customer-reachable", `${path30}.users`, "a customer-reachable workflow may not bind its approver list");
|
|
7274
7305
|
}
|
|
7275
7306
|
}
|
|
7276
7307
|
}, "checkSpec");
|
|
@@ -7455,8 +7486,8 @@ function withDefaultsFilled(g) {
|
|
|
7455
7486
|
function isConnectionKeyShaped(value22) {
|
|
7456
7487
|
return WORKFLOW_CONNECTION_KEY_RE.test(value22) && !CONNECTION_ID_HEX_RE.test(value22);
|
|
7457
7488
|
}
|
|
7458
|
-
function connectionKeyUndeclaredMessage(
|
|
7459
|
-
return `${
|
|
7489
|
+
function connectionKeyUndeclaredMessage(path30, key) {
|
|
7490
|
+
return `${path30} '${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`;
|
|
7460
7491
|
}
|
|
7461
7492
|
function classifyModelProvider(model) {
|
|
7462
7493
|
const m = (model ?? "").trim().toLowerCase();
|
|
@@ -7466,10 +7497,10 @@ function classifyModelProvider(model) {
|
|
|
7466
7497
|
if (/^(google\/|gemini)/.test(m)) return "google";
|
|
7467
7498
|
return null;
|
|
7468
7499
|
}
|
|
7469
|
-
function schemaAtPath(schema,
|
|
7500
|
+
function schemaAtPath(schema, path30) {
|
|
7470
7501
|
let cur = schema;
|
|
7471
7502
|
if (!cur || typeof cur !== "object") return void 0;
|
|
7472
|
-
for (const seg of
|
|
7503
|
+
for (const seg of path30.split(".").filter(Boolean)) {
|
|
7473
7504
|
const props = cur.properties;
|
|
7474
7505
|
const next = props?.[seg];
|
|
7475
7506
|
if (!next || typeof next !== "object") return void 0;
|
|
@@ -7536,21 +7567,21 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7536
7567
|
static: true
|
|
7537
7568
|
}) {
|
|
7538
7569
|
const issues = [];
|
|
7539
|
-
const err = /* @__PURE__ */ __name4((code, message,
|
|
7570
|
+
const err = /* @__PURE__ */ __name4((code, message, path30, stepId) => {
|
|
7540
7571
|
issues.push({
|
|
7541
7572
|
code,
|
|
7542
7573
|
message,
|
|
7543
7574
|
severity: "error",
|
|
7544
|
-
path:
|
|
7575
|
+
path: path30,
|
|
7545
7576
|
stepId
|
|
7546
7577
|
});
|
|
7547
7578
|
}, "err");
|
|
7548
|
-
const warn = /* @__PURE__ */ __name4((code, message,
|
|
7579
|
+
const warn = /* @__PURE__ */ __name4((code, message, path30, stepId) => {
|
|
7549
7580
|
issues.push({
|
|
7550
7581
|
code,
|
|
7551
7582
|
message,
|
|
7552
7583
|
severity: "warning",
|
|
7553
|
-
path:
|
|
7584
|
+
path: path30,
|
|
7554
7585
|
stepId
|
|
7555
7586
|
});
|
|
7556
7587
|
}, "warn");
|
|
@@ -7586,19 +7617,19 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7586
7617
|
err("connection-declaration-invalid", "`connections` must be an array of { key, integrationType }", "connections");
|
|
7587
7618
|
}
|
|
7588
7619
|
(Array.isArray(g.connections) ? g.connections : []).forEach((c, i) => {
|
|
7589
|
-
const
|
|
7620
|
+
const path30 = `connections.${i}`;
|
|
7590
7621
|
const key = c?.key;
|
|
7591
7622
|
const integrationType = c?.integrationType;
|
|
7592
7623
|
if (typeof key !== "string" || !WORKFLOW_CONNECTION_KEY_RE.test(key)) {
|
|
7593
|
-
err("connection-declaration-invalid", `connections[${i}].key must match ${WORKFLOW_CONNECTION_KEY_RE}`, `${
|
|
7624
|
+
err("connection-declaration-invalid", `connections[${i}].key must match ${WORKFLOW_CONNECTION_KEY_RE}`, `${path30}.key`);
|
|
7594
7625
|
return;
|
|
7595
7626
|
}
|
|
7596
7627
|
if (ownKeys.has(key)) {
|
|
7597
|
-
err("connection-declaration-invalid", `connections[${i}].key "${key}" is declared twice`, `${
|
|
7628
|
+
err("connection-declaration-invalid", `connections[${i}].key "${key}" is declared twice`, `${path30}.key`);
|
|
7598
7629
|
return;
|
|
7599
7630
|
}
|
|
7600
7631
|
if (typeof integrationType !== "string" || !integrationType.trim()) {
|
|
7601
|
-
err("connection-declaration-invalid", `connections[${i}] ("${key}") needs an integrationType (the catalog slug, e.g. 'github')`, `${
|
|
7632
|
+
err("connection-declaration-invalid", `connections[${i}] ("${key}") needs an integrationType (the catalog slug, e.g. 'github')`, `${path30}.integrationType`);
|
|
7602
7633
|
return;
|
|
7603
7634
|
}
|
|
7604
7635
|
ownKeys.add(key);
|
|
@@ -7612,112 +7643,112 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7612
7643
|
const seen = /* @__PURE__ */ new Map();
|
|
7613
7644
|
let nodeCount = 0;
|
|
7614
7645
|
const upstream = /* @__PURE__ */ new Set();
|
|
7615
|
-
const checkId = /* @__PURE__ */ __name4((id2,
|
|
7646
|
+
const checkId = /* @__PURE__ */ __name4((id2, path30) => {
|
|
7616
7647
|
nodeCount += 1;
|
|
7617
7648
|
if (seen.has(id2)) {
|
|
7618
|
-
err("duplicate-step-id", `step id "${id2}" is declared twice (first at ${seen.get(id2)})`,
|
|
7649
|
+
err("duplicate-step-id", `step id "${id2}" is declared twice (first at ${seen.get(id2)})`, path30, id2);
|
|
7619
7650
|
} else {
|
|
7620
|
-
seen.set(id2,
|
|
7651
|
+
seen.set(id2, path30);
|
|
7621
7652
|
}
|
|
7622
7653
|
}, "checkId");
|
|
7623
|
-
const checkPolicyEnums = /* @__PURE__ */ __name4((node,
|
|
7654
|
+
const checkPolicyEnums = /* @__PURE__ */ __name4((node, path30) => {
|
|
7624
7655
|
const id2 = singleId(node);
|
|
7625
7656
|
const check = /* @__PURE__ */ __name4((member, allowed) => {
|
|
7626
7657
|
const value22 = node[member];
|
|
7627
7658
|
if (value22 === void 0 || typeof value22 === "string" && allowed.includes(value22)) return;
|
|
7628
|
-
err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${
|
|
7659
|
+
err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path30}.${member}`, id2);
|
|
7629
7660
|
}, "check");
|
|
7630
7661
|
check("sideEffects", WORKFLOW_SIDE_EFFECTS);
|
|
7631
7662
|
check("jobResources", WORKFLOW_JOB_RESOURCES);
|
|
7632
7663
|
}, "checkPolicyEnums");
|
|
7633
|
-
const checkRetry = /* @__PURE__ */ __name4((node,
|
|
7664
|
+
const checkRetry = /* @__PURE__ */ __name4((node, path30) => {
|
|
7634
7665
|
const r = node.retry;
|
|
7635
7666
|
if (!r) return;
|
|
7636
7667
|
const id2 = singleId(node);
|
|
7637
7668
|
const unknown = unknownWorkflowRetryMembers(r);
|
|
7638
|
-
if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${
|
|
7669
|
+
if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path30}.retry`, id2);
|
|
7639
7670
|
if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
7640
7671
|
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
7641
|
-
err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${
|
|
7672
|
+
err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path30}.retry.maxAttempts`, id2);
|
|
7642
7673
|
}
|
|
7643
7674
|
const backoffs = retryBackoffs();
|
|
7644
7675
|
if (r.backoff !== void 0 && !backoffs.includes(r.backoff)) {
|
|
7645
7676
|
const list = backoffs.map((b) => `'${b}'`).join(" | ");
|
|
7646
|
-
err("backoff-invalid", `retry.backoff must be ${list}`, `${
|
|
7677
|
+
err("backoff-invalid", `retry.backoff must be ${list}`, `${path30}.retry.backoff`, id2);
|
|
7647
7678
|
}
|
|
7648
7679
|
if (r.backoffSeconds !== void 0 && r.backoffSeconds < 0) {
|
|
7649
|
-
err("backoff-invalid", "retry.backoffSeconds must be \u2265 0", `${
|
|
7680
|
+
err("backoff-invalid", "retry.backoffSeconds must be \u2265 0", `${path30}.retry.backoffSeconds`, id2);
|
|
7650
7681
|
}
|
|
7651
7682
|
if (r.maxBackoffSeconds !== void 0) {
|
|
7652
7683
|
if (r.backoff !== "exponential") {
|
|
7653
|
-
err("backoff-invalid", "retry.maxBackoffSeconds is only meaningful with backoff:'exponential'", `${
|
|
7684
|
+
err("backoff-invalid", "retry.maxBackoffSeconds is only meaningful with backoff:'exponential'", `${path30}.retry`, id2);
|
|
7654
7685
|
} else if (r.maxBackoffSeconds <= 0 || r.backoffSeconds !== void 0 && r.maxBackoffSeconds < r.backoffSeconds) {
|
|
7655
|
-
err("backoff-invalid", "retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds", `${
|
|
7686
|
+
err("backoff-invalid", "retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds", `${path30}.retry.maxBackoffSeconds`, id2);
|
|
7656
7687
|
}
|
|
7657
7688
|
}
|
|
7658
7689
|
}, "checkRetry");
|
|
7659
|
-
const checkTimeout = /* @__PURE__ */ __name4((node,
|
|
7690
|
+
const checkTimeout = /* @__PURE__ */ __name4((node, path30) => {
|
|
7660
7691
|
const t = node.timeoutSeconds;
|
|
7661
7692
|
if (t === void 0) return;
|
|
7662
7693
|
const id2 = singleId(node);
|
|
7663
7694
|
if (!Number.isInteger(t) || t < 1) {
|
|
7664
|
-
err("timeout-out-of-range", `timeoutSeconds must be an integer \u2265 1 (got ${t})`, `${
|
|
7695
|
+
err("timeout-out-of-range", `timeoutSeconds must be an integer \u2265 1 (got ${t})`, `${path30}.timeoutSeconds`, id2);
|
|
7665
7696
|
return;
|
|
7666
7697
|
}
|
|
7667
7698
|
if (node.tier === "job") {
|
|
7668
7699
|
const cap = node.type === "agent" ? caps.maxJobTimeoutSeconds : caps.maxJobSegmentSeconds;
|
|
7669
7700
|
if (t > cap) {
|
|
7670
|
-
err("job-timeout-exceeds-cap", `timeoutSeconds ${t} exceeds the Job-tier cap of ${cap} s`, `${
|
|
7701
|
+
err("job-timeout-exceeds-cap", `timeoutSeconds ${t} exceeds the Job-tier cap of ${cap} s`, `${path30}.timeoutSeconds`, id2);
|
|
7671
7702
|
} else if (node.type === "agent" && t > caps.maxJobSegmentSeconds && !node.workspace) {
|
|
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`, `${
|
|
7703
|
+
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`, `${path30}.timeoutSeconds`, id2);
|
|
7673
7704
|
}
|
|
7674
7705
|
} else if (t > caps.maxWorkerTimeoutSeconds) {
|
|
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)`, `${
|
|
7706
|
+
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)`, `${path30}.timeoutSeconds`, id2);
|
|
7676
7707
|
}
|
|
7677
7708
|
}, "checkTimeout");
|
|
7678
|
-
const checkSpecialistRole = /* @__PURE__ */ __name4((node,
|
|
7709
|
+
const checkSpecialistRole = /* @__PURE__ */ __name4((node, path30) => {
|
|
7679
7710
|
const role = node.role;
|
|
7680
7711
|
const hasRef = typeof role.ref === "string";
|
|
7681
7712
|
const hasInline = role.name !== void 0 || role.instructions !== void 0 || Array.isArray(role.tools) && role.tools.length > 0;
|
|
7682
7713
|
if (hasRef && hasInline) {
|
|
7683
|
-
err("role-ref-and-inline", "a role is either `{ref}` or inline `{name, instructions, tools}`, never both", `${
|
|
7714
|
+
err("role-ref-and-inline", "a role is either `{ref}` or inline `{name, instructions, tools}`, never both", `${path30}.role`, node.id);
|
|
7684
7715
|
}
|
|
7685
7716
|
if (node.agentId !== "$self") {
|
|
7686
|
-
err("ephemeral-base-not-self", "a role runs on the owner only: use '$self'", `${
|
|
7717
|
+
err("ephemeral-base-not-self", "a role runs on the owner only: use '$self'", `${path30}.agentId`, node.id);
|
|
7687
7718
|
}
|
|
7688
7719
|
if (opts.policy && opts.policy.ephemeralSpecialists !== true) {
|
|
7689
|
-
err("ephemeral-specialists-disabled", "ephemeral specialists are off for this org/agent (workflowPolicy.ephemeralSpecialists)", `${
|
|
7720
|
+
err("ephemeral-specialists-disabled", "ephemeral specialists are off for this org/agent (workflowPolicy.ephemeralSpecialists)", `${path30}.role`, node.id);
|
|
7690
7721
|
}
|
|
7691
7722
|
let tools = Array.isArray(role.tools) ? role.tools.filter((t) => typeof t === "string") : [];
|
|
7692
7723
|
if (hasRef && opts.roleLibrary) {
|
|
7693
7724
|
const saved = opts.roleLibrary.get(role.ref);
|
|
7694
7725
|
if (!saved) {
|
|
7695
|
-
err("role-ref-unknown", `no saved role \`${role.ref}\` in the owner's library`, `${
|
|
7726
|
+
err("role-ref-unknown", `no saved role \`${role.ref}\` in the owner's library`, `${path30}.role.ref`, node.id);
|
|
7696
7727
|
} else {
|
|
7697
7728
|
tools = saved.tools ?? [];
|
|
7698
7729
|
if (typeof role.roleHash === "string" && saved.roleHash && role.roleHash !== saved.roleHash) {
|
|
7699
|
-
warn("role-ref-stale", `saved role \`${role.ref}\` changed since this version was frozen`, `${
|
|
7730
|
+
warn("role-ref-stale", `saved role \`${role.ref}\` changed since this version was frozen`, `${path30}.role.ref`, node.id);
|
|
7700
7731
|
}
|
|
7701
7732
|
}
|
|
7702
7733
|
}
|
|
7703
7734
|
if (tools.length && opts.toolCatalog) {
|
|
7704
7735
|
const missing = tools.filter((t) => !opts.toolCatalog.has(t));
|
|
7705
7736
|
if (missing.length) {
|
|
7706
|
-
err("ephemeral-tools-not-subset", `role tools not in the owner's catalog: ${missing.join(", ")}`, `${
|
|
7737
|
+
err("ephemeral-tools-not-subset", `role tools not in the owner's catalog: ${missing.join(", ")}`, `${path30}.role.tools`, node.id);
|
|
7707
7738
|
}
|
|
7708
7739
|
}
|
|
7709
7740
|
}, "checkSpecialistRole");
|
|
7710
|
-
const checkRequiredConnections = /* @__PURE__ */ __name4((node,
|
|
7741
|
+
const checkRequiredConnections = /* @__PURE__ */ __name4((node, path30) => {
|
|
7711
7742
|
const required = node.requiredConnections;
|
|
7712
7743
|
if (!Array.isArray(required)) return;
|
|
7713
7744
|
const undeclared = required.filter(undeclaredKey);
|
|
7714
7745
|
if (undeclared.length) {
|
|
7715
|
-
err("connection-key-undeclared", connectionKeyUndeclaredMessage(`${
|
|
7746
|
+
err("connection-key-undeclared", connectionKeyUndeclaredMessage(`${path30}.requiredConnections`, undeclared[0]) + (undeclared.length > 1 ? ` (also undeclared: ${JSON.stringify(undeclared.slice(1))})` : ""), `${path30}.requiredConnections`, singleId(node));
|
|
7716
7747
|
}
|
|
7717
7748
|
if (!opts.connectionIds) return;
|
|
7718
7749
|
const unknown = required.filter((c) => typeof c !== "string" || !declaredKeys.has(c) && !opts.connectionIds.has(c));
|
|
7719
7750
|
if (unknown.length) {
|
|
7720
|
-
err("required-connection-unknown", `requiredConnections ${JSON.stringify(unknown)} are neither declared connections[].key values nor connections the owner can mount`, `${
|
|
7751
|
+
err("required-connection-unknown", `requiredConnections ${JSON.stringify(unknown)} are neither declared connections[].key values nor connections the owner can mount`, `${path30}.requiredConnections`, singleId(node));
|
|
7721
7752
|
}
|
|
7722
7753
|
}, "checkRequiredConnections");
|
|
7723
7754
|
const jobClassifiablePin = /* @__PURE__ */ __name4((model) => {
|
|
@@ -7735,33 +7766,33 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7735
7766
|
}
|
|
7736
7767
|
return void 0;
|
|
7737
7768
|
}, "jobClassifiablePin");
|
|
7738
|
-
const checkTier = /* @__PURE__ */ __name4((node,
|
|
7769
|
+
const checkTier = /* @__PURE__ */ __name4((node, path30) => {
|
|
7739
7770
|
const id2 = singleId(node);
|
|
7740
7771
|
if (node.workspace && node.workspace !== "inherit" && node.tier !== void 0 && node.tier !== "job") {
|
|
7741
|
-
err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${
|
|
7772
|
+
err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path30}.workspace`, id2);
|
|
7742
7773
|
}
|
|
7743
7774
|
if (node.harness !== void 0 && node.tier !== "job") {
|
|
7744
|
-
err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${
|
|
7775
|
+
err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${path30}.harness`, id2);
|
|
7745
7776
|
}
|
|
7746
7777
|
const provider = node.type === "agent" ? classifyModelProvider(jobClassifiablePin(node.model)) : null;
|
|
7747
7778
|
if (node.harness === "claude-code" && provider !== null && provider !== "anthropic") {
|
|
7748
|
-
err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${
|
|
7779
|
+
err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${path30}.harness`, id2);
|
|
7749
7780
|
}
|
|
7750
7781
|
if (isJobTier(node) && provider !== null && opts.policy?.jobProviders && !opts.policy.jobProviders.includes(provider)) {
|
|
7751
|
-
err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${
|
|
7782
|
+
err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path30}.model`, id2);
|
|
7752
7783
|
}
|
|
7753
7784
|
}, "checkTier");
|
|
7754
|
-
const checkModel = /* @__PURE__ */ __name4((node,
|
|
7785
|
+
const checkModel = /* @__PURE__ */ __name4((node, path30) => {
|
|
7755
7786
|
if (node.type !== "agent" || typeof node.model !== "string") return;
|
|
7756
7787
|
const id2 = singleId(node);
|
|
7757
7788
|
const parsed = parseModelTemplate(node.model);
|
|
7758
7789
|
if (parsed.kind === "invalid") {
|
|
7759
|
-
err("model-template-invalid", parsed.message, `${
|
|
7790
|
+
err("model-template-invalid", parsed.message, `${path30}.model`, id2);
|
|
7760
7791
|
return;
|
|
7761
7792
|
}
|
|
7762
7793
|
if (parsed.kind === "template" && parsed.template.default === void 0) {
|
|
7763
7794
|
if (isJobTier(node)) {
|
|
7764
|
-
err("model-template-default-required", modelTemplateDefaultRequiredMessage(node.model), `${
|
|
7795
|
+
err("model-template-default-required", modelTemplateDefaultRequiredMessage(node.model), `${path30}.model`, id2);
|
|
7765
7796
|
}
|
|
7766
7797
|
return;
|
|
7767
7798
|
}
|
|
@@ -7774,40 +7805,40 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7774
7805
|
if (registry === "unavailable") {
|
|
7775
7806
|
const trimmed2 = pin.trim();
|
|
7776
7807
|
if (trimmed2 && !normalizeModelId(trimmed2, []).ok) {
|
|
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)`), `${
|
|
7808
|
+
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)`), `${path30}.model`, id2);
|
|
7778
7809
|
}
|
|
7779
7810
|
return;
|
|
7780
7811
|
}
|
|
7781
7812
|
const resolved = normalizeModelId(pin, registry);
|
|
7782
|
-
if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${
|
|
7813
|
+
if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path30}.model`, id2);
|
|
7783
7814
|
}, "checkModel");
|
|
7784
|
-
const checkTaskClass = /* @__PURE__ */ __name4((node,
|
|
7815
|
+
const checkTaskClass = /* @__PURE__ */ __name4((node, path30) => {
|
|
7785
7816
|
if (node.type !== "agent" || node.taskClass === void 0) return;
|
|
7786
7817
|
if (!opts.static) return;
|
|
7787
7818
|
if (typeof node.model === "string" && node.model.trim()) return;
|
|
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`, `${
|
|
7819
|
+
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`, `${path30}.taskClass`, singleId(node));
|
|
7789
7820
|
}, "checkTaskClass");
|
|
7790
|
-
const checkWorkspace = /* @__PURE__ */ __name4((node,
|
|
7821
|
+
const checkWorkspace = /* @__PURE__ */ __name4((node, path30) => {
|
|
7791
7822
|
const id2 = singleId(node);
|
|
7792
7823
|
const ws = workspaceOf(node);
|
|
7793
7824
|
if (isJobTier(node) && opts.policy && opts.policy.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)`, `${
|
|
7825
|
+
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)`, `${path30}.tier`, id2);
|
|
7795
7826
|
}
|
|
7796
7827
|
const tools = jobToolsOf(node);
|
|
7797
7828
|
if (tools !== void 0) {
|
|
7798
7829
|
if (!isJobTier(node)) {
|
|
7799
|
-
err("job-tools-require-job-tier", "`jobTools` needs tier:'job'", `${
|
|
7830
|
+
err("job-tools-require-job-tier", "`jobTools` needs tier:'job'", `${path30}.jobTools`, id2);
|
|
7800
7831
|
}
|
|
7801
7832
|
const unknown = (Array.isArray(tools) ? tools : [
|
|
7802
7833
|
tools
|
|
7803
7834
|
]).filter((t) => !WORKFLOW_JOB_TOOLS.includes(t));
|
|
7804
7835
|
if (unknown.length > 0) {
|
|
7805
|
-
err("job-tools-unknown", `jobTools ${JSON.stringify(unknown)} outside WORKFLOW_JOB_TOOLS [${WORKFLOW_JOB_TOOLS.join(", ")}]`, `${
|
|
7836
|
+
err("job-tools-unknown", `jobTools ${JSON.stringify(unknown)} outside WORKFLOW_JOB_TOOLS [${WORKFLOW_JOB_TOOLS.join(", ")}]`, `${path30}.jobTools`, id2);
|
|
7806
7837
|
}
|
|
7807
7838
|
if (node.type === "agent" && (Array.isArray(tools) ? tools : [
|
|
7808
7839
|
tools
|
|
7809
7840
|
]).includes("gh")) {
|
|
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)`, `${
|
|
7841
|
+
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)`, `${path30}.jobTools`, id2);
|
|
7811
7842
|
}
|
|
7812
7843
|
}
|
|
7813
7844
|
const plugins = node.plugins;
|
|
@@ -7815,44 +7846,44 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7815
7846
|
const luaApi = node.luaApi;
|
|
7816
7847
|
if (luaApi !== void 0) {
|
|
7817
7848
|
const problem = workflowJobLuaApiProblem(luaApi, node.type === "step" ? "code" : node.type, isJobTier(node) ? "job" : node.tier);
|
|
7818
|
-
if (problem) err("lua-api-invalid", problem, `${
|
|
7849
|
+
if (problem) err("lua-api-invalid", problem, `${path30}.luaApi`, id2);
|
|
7819
7850
|
}
|
|
7820
7851
|
if (target !== void 0) {
|
|
7821
7852
|
const problem = workflowJobTargetProblem(target, plugins, luaApi);
|
|
7822
|
-
if (problem) err("target-invalid", problem, `${
|
|
7853
|
+
if (problem) err("target-invalid", problem, `${path30}.target`, id2);
|
|
7823
7854
|
}
|
|
7824
7855
|
if (plugins !== void 0) {
|
|
7825
7856
|
const problem = workflowJobPluginsProblem(plugins);
|
|
7826
|
-
if (problem) err("plugins-invalid", problem, `${
|
|
7827
|
-
if (node.type !== "agent") err("plugins-invalid", "`plugins` is legal on agent steps only", `${
|
|
7857
|
+
if (problem) err("plugins-invalid", problem, `${path30}.plugins`, id2);
|
|
7858
|
+
if (node.type !== "agent") err("plugins-invalid", "`plugins` is legal on agent steps only", `${path30}.plugins`, id2);
|
|
7828
7859
|
else {
|
|
7829
|
-
if (!isJobTier(node)) err("plugins-invalid", "`plugins` needs tier:'job'", `${
|
|
7860
|
+
if (!isJobTier(node)) err("plugins-invalid", "`plugins` needs tier:'job'", `${path30}.plugins`, id2);
|
|
7830
7861
|
const provider = classifyModelProvider(jobClassifiablePin(node.model));
|
|
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'`)", `${
|
|
7862
|
+
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'`)", `${path30}.plugins`, id2);
|
|
7832
7863
|
const w = workspaceOf(node);
|
|
7833
7864
|
const ro = w !== void 0 && w !== "inherit" && w.mount === "ro";
|
|
7834
7865
|
const declared = Array.isArray(tools) ? tools : void 0;
|
|
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", `${
|
|
7866
|
+
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", `${path30}.plugins`, id2);
|
|
7836
7867
|
}
|
|
7837
7868
|
}
|
|
7838
7869
|
if (node.type === "agent" && ws && ws !== "inherit" && ws.mount === "ro" && Array.isArray(tools) && effectiveJobTools(tools, true).length === 0) {
|
|
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`, `${
|
|
7870
|
+
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`, `${path30}.jobTools`, id2);
|
|
7840
7871
|
}
|
|
7841
7872
|
if (ws && ws !== "inherit") {
|
|
7842
7873
|
if (!envelopeWorkspace && !opts.mayInherit) {
|
|
7843
|
-
err("workspace-not-declared", `"${id2}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${
|
|
7874
|
+
err("workspace-not-declared", `"${id2}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path30}.workspace`, id2);
|
|
7844
7875
|
}
|
|
7845
7876
|
if (ws.isolation === "worktree" && envelopeWorkspace?.kind === "empty") {
|
|
7846
|
-
err("worktree-requires-git-workspace", `"${id2}": isolation:'worktree' needs a kind:'git' workspace (the envelope declares kind:'empty')`, `${
|
|
7877
|
+
err("worktree-requires-git-workspace", `"${id2}": isolation:'worktree' needs a kind:'git' workspace (the envelope declares kind:'empty')`, `${path30}.workspace.isolation`, id2);
|
|
7847
7878
|
}
|
|
7848
7879
|
}
|
|
7849
7880
|
if (node.type === "workflow" && ws === "inherit") {
|
|
7850
7881
|
if (!envelopeWorkspace) {
|
|
7851
|
-
err("workspace-inherit-without-parent-workspace", `"${id2}": workspace:'inherit' but the parent workflow declares no workspace \u2014 there is nothing to inherit`, `${
|
|
7882
|
+
err("workspace-inherit-without-parent-workspace", `"${id2}": workspace:'inherit' but the parent workflow declares no workspace \u2014 there is nothing to inherit`, `${path30}.workspace`, id2);
|
|
7852
7883
|
}
|
|
7853
7884
|
const child = opts.resolveWorkflow?.(node.workflowId);
|
|
7854
7885
|
if (child?.workspace) {
|
|
7855
|
-
err("workspace-inherit-conflict", `"${id2}": workspace:'inherit' on "${node.workflowId}", which declares its own workspace`, `${
|
|
7886
|
+
err("workspace-inherit-conflict", `"${id2}": workspace:'inherit' on "${node.workflowId}", which declares its own workspace`, `${path30}.workspace`, id2);
|
|
7856
7887
|
}
|
|
7857
7888
|
}
|
|
7858
7889
|
}, "checkWorkspace");
|
|
@@ -7866,165 +7897,165 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
7866
7897
|
warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id2, m), `${basePath}.${m.member}`, id2);
|
|
7867
7898
|
}
|
|
7868
7899
|
}, "checkMapMembers");
|
|
7869
|
-
const checkInputShape = /* @__PURE__ */ __name4((node,
|
|
7900
|
+
const checkInputShape = /* @__PURE__ */ __name4((node, path30) => {
|
|
7870
7901
|
const input = node.input;
|
|
7871
7902
|
if (input === void 0) return;
|
|
7872
7903
|
const id2 = singleId(node);
|
|
7873
7904
|
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
7874
|
-
checkMapMembers(input, `${
|
|
7905
|
+
checkMapMembers(input, `${path30}.input`, id2);
|
|
7875
7906
|
return;
|
|
7876
7907
|
}
|
|
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)})`, `${
|
|
7908
|
+
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)})`, `${path30}.input`, id2);
|
|
7878
7909
|
}, "checkInputShape");
|
|
7879
|
-
const checkBodyInput = /* @__PURE__ */ __name4((body,
|
|
7910
|
+
const checkBodyInput = /* @__PURE__ */ __name4((body, path30, container) => {
|
|
7880
7911
|
if (body.type === "workflow" || body.input === void 0) return;
|
|
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`, `${
|
|
7912
|
+
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`, `${path30}.input`, singleId(body));
|
|
7882
7913
|
}, "checkBodyInput");
|
|
7883
|
-
const checkSingle = /* @__PURE__ */ __name4((node,
|
|
7914
|
+
const checkSingle = /* @__PURE__ */ __name4((node, path30, depth) => {
|
|
7884
7915
|
recordOutputSchema(node);
|
|
7885
7916
|
if (node.type === "workflow" && (typeof node.workflowId !== "string" || node.workflowId.length === 0)) {
|
|
7886
|
-
checkId(node.id,
|
|
7887
|
-
err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${
|
|
7917
|
+
checkId(node.id, path30);
|
|
7918
|
+
err("invalid-envelope", `\`workflowId\` must be a non-empty string naming the workflow to start (got ${JSON.stringify(node.workflowId)})`, `${path30}.workflowId`, node.id);
|
|
7888
7919
|
return;
|
|
7889
7920
|
}
|
|
7890
7921
|
if (node.type === "workflow" && (node.workflowId.startsWith("$") || Array.isArray(node.graph))) {
|
|
7891
|
-
checkId(node.id,
|
|
7892
|
-
err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId),
|
|
7922
|
+
checkId(node.id, path30);
|
|
7923
|
+
err("node-type-unsupported-by-engine", armSubrunUnsupportedMessage(node.id, node.workflowId), path30, node.id);
|
|
7893
7924
|
return;
|
|
7894
7925
|
}
|
|
7895
|
-
checkId(singleId(node),
|
|
7896
|
-
checkPolicyEnums(node,
|
|
7897
|
-
checkInputShape(node,
|
|
7898
|
-
checkTimeout(node,
|
|
7899
|
-
checkTier(node,
|
|
7900
|
-
checkModel(node,
|
|
7901
|
-
checkTaskClass(node,
|
|
7902
|
-
checkRetry(node,
|
|
7903
|
-
checkWorkspace(node,
|
|
7926
|
+
checkId(singleId(node), path30);
|
|
7927
|
+
checkPolicyEnums(node, path30);
|
|
7928
|
+
checkInputShape(node, path30);
|
|
7929
|
+
checkTimeout(node, path30);
|
|
7930
|
+
checkTier(node, path30);
|
|
7931
|
+
checkModel(node, path30);
|
|
7932
|
+
checkTaskClass(node, path30);
|
|
7933
|
+
checkRetry(node, path30);
|
|
7934
|
+
checkWorkspace(node, path30);
|
|
7904
7935
|
if (!opts.static) {
|
|
7905
|
-
if (node.type === "step") err("code-step-not-allowed", "code steps are static-only (03 \xA73.4.2)",
|
|
7936
|
+
if (node.type === "step") err("code-step-not-allowed", "code steps are static-only (03 \xA73.4.2)", path30, node.step.id);
|
|
7906
7937
|
if (node.type === "agent" && node.systemPrompt !== void 0) {
|
|
7907
|
-
err("persona-override-not-allowed", "`systemPrompt` is static-only (03 \xA73.4.2)", `${
|
|
7938
|
+
err("persona-override-not-allowed", "`systemPrompt` is static-only (03 \xA73.4.2)", `${path30}.systemPrompt`, node.id);
|
|
7908
7939
|
}
|
|
7909
7940
|
}
|
|
7910
7941
|
if (node.type === "agent" && node.role && node.systemPrompt !== void 0) {
|
|
7911
|
-
err("ephemeral-persona-not-overridable", "a specialist role and systemPrompt cannot coexist", `${
|
|
7942
|
+
err("ephemeral-persona-not-overridable", "a specialist role and systemPrompt cannot coexist", `${path30}.systemPrompt`, node.id);
|
|
7912
7943
|
}
|
|
7913
7944
|
if (node.type === "agent" && node.role && typeof node.role.instructions === "string" && node.role.instructions.length > 4e3) {
|
|
7914
|
-
err("ephemeral-role-too-long", "role.instructions exceeds 4000 chars", `${
|
|
7945
|
+
err("ephemeral-role-too-long", "role.instructions exceeds 4000 chars", `${path30}.role.instructions`, node.id);
|
|
7915
7946
|
}
|
|
7916
7947
|
if (node.type === "agent" && node.role && (node.role.tools?.length ?? 0) > 64) {
|
|
7917
|
-
err("cap-exceeded", "role.tools exceeds 64 entries", `${
|
|
7948
|
+
err("cap-exceeded", "role.tools exceeds 64 entries", `${path30}.role.tools`, node.id);
|
|
7918
7949
|
}
|
|
7919
|
-
if (node.type === "agent" && node.role) checkSpecialistRole(node,
|
|
7920
|
-
checkRequiredConnections(node,
|
|
7950
|
+
if (node.type === "agent" && node.role) checkSpecialistRole(node, path30);
|
|
7951
|
+
checkRequiredConnections(node, path30);
|
|
7921
7952
|
if (node.type === "workflow" && node.kind === "subrun" && depth > caps.maxNestingDepth) {
|
|
7922
|
-
err("cap-exceeded", `nesting depth ${depth} exceeds ${caps.maxNestingDepth}`,
|
|
7953
|
+
err("cap-exceeded", `nesting depth ${depth} exceeds ${caps.maxNestingDepth}`, path30, node.id);
|
|
7923
7954
|
}
|
|
7924
7955
|
if (node.type === "workflow" && typeof g.definition?.id === "string" && node.workflowId === g.definition.id) {
|
|
7925
|
-
err("subrun-cycle", `"${node.id}" starts "${node.workflowId}", which is this workflow itself`,
|
|
7956
|
+
err("subrun-cycle", `"${node.id}" starts "${node.workflowId}", which is this workflow itself`, path30, node.id);
|
|
7926
7957
|
}
|
|
7927
7958
|
for (const ref of nodeStepRefs(node)) {
|
|
7928
7959
|
if (!upstream.has(ref)) {
|
|
7929
|
-
err("template-reference-unresolved", `"${singleId(node)}" references stepResults.${ref}, which is not upstream`,
|
|
7960
|
+
err("template-reference-unresolved", `"${singleId(node)}" references stepResults.${ref}, which is not upstream`, path30, singleId(node));
|
|
7930
7961
|
}
|
|
7931
7962
|
}
|
|
7932
7963
|
}, "checkSingle");
|
|
7933
|
-
const checkHitl = /* @__PURE__ */ __name4((node,
|
|
7964
|
+
const checkHitl = /* @__PURE__ */ __name4((node, path30) => {
|
|
7934
7965
|
if (node.type === "waitForSignal") {
|
|
7935
7966
|
const w = node;
|
|
7936
|
-
checkId(w.id,
|
|
7937
|
-
if (typeof w.signal !== "string" || w.signal.length === 0) err("invalid-envelope", "waitForSignal.signal is required", `${
|
|
7967
|
+
checkId(w.id, path30);
|
|
7968
|
+
if (typeof w.signal !== "string" || w.signal.length === 0) err("invalid-envelope", "waitForSignal.signal is required", `${path30}.signal`, w.id);
|
|
7938
7969
|
return;
|
|
7939
7970
|
}
|
|
7940
7971
|
const a = node;
|
|
7941
|
-
checkId(a.id,
|
|
7972
|
+
checkId(a.id, path30);
|
|
7942
7973
|
if ((a.approver ?? "creator") === "creator" && a.excludeInitiator === true) {
|
|
7943
|
-
err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate",
|
|
7974
|
+
err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path30, a.id);
|
|
7944
7975
|
}
|
|
7945
7976
|
const editable = approvalEditable(a);
|
|
7946
7977
|
if (a.fourEyes !== void 0 && !editable) {
|
|
7947
|
-
err("four-eyes-requires-editable", "`fourEyes` requires editable:true", `${
|
|
7978
|
+
err("four-eyes-requires-editable", "`fourEyes` requires editable:true", `${path30}.fourEyes`, a.id);
|
|
7948
7979
|
}
|
|
7949
7980
|
if (a.editable === false && Array.isArray(a.editablePaths) && a.editablePaths.length > 0) {
|
|
7950
|
-
err("editable-path-invalid", "`editablePaths` beside editable:false is contradictory \u2014 drop the paths or set editable:true", `${
|
|
7981
|
+
err("editable-path-invalid", "`editablePaths` beside editable:false is contradictory \u2014 drop the paths or set editable:true", `${path30}.editablePaths`, a.id);
|
|
7951
7982
|
} else if ((a.editablePaths !== void 0 || a.editedPayloadSchema !== void 0) && !editable) {
|
|
7952
|
-
err("editable-path-invalid", "`editablePaths` / `editedPayloadSchema` require editable:true (a non-empty editablePaths implies it)", `${
|
|
7983
|
+
err("editable-path-invalid", "`editablePaths` / `editedPayloadSchema` require editable:true (a non-empty editablePaths implies it)", `${path30}.editablePaths`, a.id);
|
|
7953
7984
|
}
|
|
7954
7985
|
for (const p of a.editablePaths ?? []) {
|
|
7955
|
-
if (!EDITABLE_PATH_RE.test(p)) err("editable-path-invalid", `editablePaths entry "${p}" is outside the seg(.seg)*[*]/[n] grammar`, `${
|
|
7986
|
+
if (!EDITABLE_PATH_RE.test(p)) err("editable-path-invalid", `editablePaths entry "${p}" is outside the seg(.seg)*[*]/[n] grammar`, `${path30}.editablePaths`, a.id);
|
|
7956
7987
|
}
|
|
7957
7988
|
if (Array.isArray(a.onTimeout)) {
|
|
7958
7989
|
const chain = a.onTimeout;
|
|
7959
7990
|
const hops = chain.filter((h) => typeof h === "object" && h !== null && "escalateTo" in h);
|
|
7960
|
-
if (hops.length > 3) err("escalation-chain-too-long", "an onTimeout chain carries at most 3 escalation hops", `${
|
|
7991
|
+
if (hops.length > 3) err("escalation-chain-too-long", "an onTimeout chain carries at most 3 escalation hops", `${path30}.onTimeout`, a.id);
|
|
7961
7992
|
const last = chain[chain.length - 1];
|
|
7962
7993
|
if (last === void 0 || typeof last === "object" && last !== null && "escalateTo" in last) {
|
|
7963
|
-
err("escalation-chain-not-terminal", "an onTimeout chain must end in a terminal member", `${
|
|
7994
|
+
err("escalation-chain-not-terminal", "an onTimeout chain must end in a terminal member", `${path30}.onTimeout`, a.id);
|
|
7964
7995
|
}
|
|
7965
7996
|
}
|
|
7966
7997
|
if (typeof a.details === "string") {
|
|
7967
7998
|
for (const ref of templateStepRefs(a.details)) {
|
|
7968
|
-
if (!upstream.has(ref)) err("template-reference-unresolved", `"${a.id}" references stepResults.${ref}, which is not upstream`,
|
|
7999
|
+
if (!upstream.has(ref)) err("template-reference-unresolved", `"${a.id}" references stepResults.${ref}, which is not upstream`, path30, a.id);
|
|
7969
8000
|
}
|
|
7970
8001
|
}
|
|
7971
8002
|
}, "checkHitl");
|
|
7972
|
-
const checkHitlArm = /* @__PURE__ */ __name4((node,
|
|
8003
|
+
const checkHitlArm = /* @__PURE__ */ __name4((node, path30, container) => {
|
|
7973
8004
|
if (!workflowContainerRunsHitlArm(container)) {
|
|
7974
|
-
checkId(node.id,
|
|
7975
|
-
err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container),
|
|
8005
|
+
checkId(node.id, path30);
|
|
8006
|
+
err("node-type-unsupported-in-container", workflowHitlArmUnsupportedMessage(node.type, node.id, container), path30, node.id);
|
|
7976
8007
|
return;
|
|
7977
8008
|
}
|
|
7978
|
-
checkHitl(node,
|
|
8009
|
+
checkHitl(node, path30);
|
|
7979
8010
|
}, "checkHitlArm");
|
|
7980
|
-
const checkArm = /* @__PURE__ */ __name4((arm,
|
|
8011
|
+
const checkArm = /* @__PURE__ */ __name4((arm, path30, depth, container) => {
|
|
7981
8012
|
if (arm.type === "mapping") {
|
|
7982
|
-
checkId(arm.id,
|
|
7983
|
-
checkMapMembers(readMapConfig(arm.mapConfig), `${
|
|
8013
|
+
checkId(arm.id, path30);
|
|
8014
|
+
checkMapMembers(readMapConfig(arm.mapConfig), `${path30}.mapConfig`, arm.id);
|
|
7984
8015
|
for (const ref of nodeStepRefs(arm)) {
|
|
7985
|
-
if (!upstream.has(ref)) err("template-reference-unresolved", `"${arm.id}" references stepResults.${ref}, which is not upstream`,
|
|
8016
|
+
if (!upstream.has(ref)) err("template-reference-unresolved", `"${arm.id}" references stepResults.${ref}, which is not upstream`, path30, arm.id);
|
|
7986
8017
|
}
|
|
7987
8018
|
return;
|
|
7988
8019
|
}
|
|
7989
8020
|
if (isHitlNode(arm)) {
|
|
7990
|
-
checkHitlArm(arm,
|
|
8021
|
+
checkHitlArm(arm, path30, container);
|
|
7991
8022
|
return;
|
|
7992
8023
|
}
|
|
7993
|
-
checkSingle(arm,
|
|
8024
|
+
checkSingle(arm, path30, depth);
|
|
7994
8025
|
}, "checkArm");
|
|
7995
8026
|
graph.forEach((entry, i) => {
|
|
7996
|
-
const
|
|
8027
|
+
const path30 = `graph.${i}`;
|
|
7997
8028
|
const declared = [];
|
|
7998
8029
|
switch (entry.type) {
|
|
7999
8030
|
case "step":
|
|
8000
8031
|
case "agent":
|
|
8001
8032
|
case "tool":
|
|
8002
8033
|
case "workflow":
|
|
8003
|
-
checkSingle(entry,
|
|
8034
|
+
checkSingle(entry, path30, 1);
|
|
8004
8035
|
declared.push(singleId(entry));
|
|
8005
8036
|
break;
|
|
8006
8037
|
case "mapping":
|
|
8007
|
-
checkId(entry.id,
|
|
8008
|
-
checkMapMembers(readMapConfig(entry.mapConfig), `${
|
|
8038
|
+
checkId(entry.id, path30);
|
|
8039
|
+
checkMapMembers(readMapConfig(entry.mapConfig), `${path30}.mapConfig`, entry.id);
|
|
8009
8040
|
for (const ref of nodeStepRefs(entry)) {
|
|
8010
|
-
if (!upstream.has(ref)) err("template-reference-unresolved", `"${entry.id}" references stepResults.${ref}, which is not upstream`,
|
|
8041
|
+
if (!upstream.has(ref)) err("template-reference-unresolved", `"${entry.id}" references stepResults.${ref}, which is not upstream`, path30, entry.id);
|
|
8011
8042
|
}
|
|
8012
8043
|
declared.push(entry.id);
|
|
8013
8044
|
break;
|
|
8014
8045
|
case "sleep":
|
|
8015
|
-
checkId(entry.id,
|
|
8016
|
-
if (!Number.isFinite(entry.duration) || entry.duration < 0) err("invalid-envelope", "sleep.duration must be a non-negative number", `${
|
|
8046
|
+
checkId(entry.id, path30);
|
|
8047
|
+
if (!Number.isFinite(entry.duration) || entry.duration < 0) err("invalid-envelope", "sleep.duration must be a non-negative number", `${path30}.duration`, entry.id);
|
|
8017
8048
|
declared.push(entry.id);
|
|
8018
8049
|
break;
|
|
8019
8050
|
case "sleepUntil": {
|
|
8020
8051
|
const s = entry;
|
|
8021
|
-
checkId(s.id,
|
|
8022
|
-
err("node-type-unsupported-by-engine", sleepUntilUnsupportedMessage(s.id),
|
|
8052
|
+
checkId(s.id, path30);
|
|
8053
|
+
err("node-type-unsupported-by-engine", sleepUntilUnsupportedMessage(s.id), path30, s.id);
|
|
8023
8054
|
if (s.date === void 0 === (s.dateFrom === void 0)) {
|
|
8024
|
-
err("invalid-envelope", "sleepUntil needs exactly one of `date` | `dateFrom`",
|
|
8055
|
+
err("invalid-envelope", "sleepUntil needs exactly one of `date` | `dateFrom`", path30, s.id);
|
|
8025
8056
|
}
|
|
8026
8057
|
if (s.dateFrom && !upstream.has(s.dateFrom.step)) {
|
|
8027
|
-
err("sleep-until-source-missing", `sleepUntil "${s.id}" reads dateFrom.step "${s.dateFrom.step}", which is not upstream`, `${
|
|
8058
|
+
err("sleep-until-source-missing", `sleepUntil "${s.id}" reads dateFrom.step "${s.dateFrom.step}", which is not upstream`, `${path30}.dateFrom`, s.id);
|
|
8028
8059
|
}
|
|
8029
8060
|
declared.push(s.id);
|
|
8030
8061
|
break;
|
|
@@ -8032,10 +8063,10 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
8032
8063
|
case "parallel": {
|
|
8033
8064
|
const p = entry;
|
|
8034
8065
|
if (p.steps.length < 2 || p.steps.length > caps.maxParallelArms) {
|
|
8035
|
-
err("cap-exceeded", `parallel needs 2..${caps.maxParallelArms} arms (got ${p.steps.length})`,
|
|
8066
|
+
err("cap-exceeded", `parallel needs 2..${caps.maxParallelArms} arms (got ${p.steps.length})`, path30);
|
|
8036
8067
|
}
|
|
8037
8068
|
p.steps.forEach((arm, j) => {
|
|
8038
|
-
const armPath = `${
|
|
8069
|
+
const armPath = `${path30}.steps.${j}`;
|
|
8039
8070
|
if (arm.type === "mapping") {
|
|
8040
8071
|
err("mapping-placement", "a bare mapping cannot be a parallel arm \u2014 chain it as [map, step]", armPath);
|
|
8041
8072
|
return;
|
|
@@ -8045,31 +8076,31 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
8045
8076
|
});
|
|
8046
8077
|
const executableArms = p.steps.filter(isSingleStep);
|
|
8047
8078
|
const worktreeArms = executableArms.filter((a) => a.workspace?.isolation === "worktree");
|
|
8048
|
-
if (worktreeArms.length > 0 && !p.merge) err("worktree-arms-require-merge", "worktree arms need a `merge` policy",
|
|
8049
|
-
if (worktreeArms.length === 0 && p.merge) err("merge-requires-worktree-arms", "`merge` needs at least one worktree arm",
|
|
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`,
|
|
8079
|
+
if (worktreeArms.length > 0 && !p.merge) err("worktree-arms-require-merge", "worktree arms need a `merge` policy", path30);
|
|
8080
|
+
if (worktreeArms.length === 0 && p.merge) err("merge-requires-worktree-arms", "`merge` needs at least one worktree arm", path30);
|
|
8081
|
+
if (worktreeArms.length > WORKFLOW_JOB_MAX_WORKTREE_ARMS) err("worktree-arms-exceed-cap", `at most ${WORKFLOW_JOB_MAX_WORKTREE_ARMS} worktree arms per parallel`, path30);
|
|
8051
8082
|
const sharedArms = executableArms.filter((a) => {
|
|
8052
8083
|
const w = workspaceOf(a);
|
|
8053
8084
|
if (!w || w === "inherit" || w.isolation === "worktree") return false;
|
|
8054
8085
|
return !(envelopeWorkspace?.backend === "efs" && w.mount === "ro");
|
|
8055
8086
|
});
|
|
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`, `${
|
|
8087
|
+
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`, `${path30}.steps`);
|
|
8057
8088
|
break;
|
|
8058
8089
|
}
|
|
8059
8090
|
case "conditional": {
|
|
8060
8091
|
const c = entry;
|
|
8061
8092
|
if (!Array.isArray(c.predicates) || c.predicates.length !== c.steps.length) {
|
|
8062
|
-
err("invalid-envelope", "conditional.predicates must match conditional.steps one-to-one",
|
|
8093
|
+
err("invalid-envelope", "conditional.predicates must match conditional.steps one-to-one", path30);
|
|
8063
8094
|
}
|
|
8064
8095
|
(c.predicates ?? []).forEach((p, j) => {
|
|
8065
|
-
if (!isWellFormedPredicate(p)) err("closure-predicate", "a conditional predicate must be a well-formed LuaPredicate object ({op, left/right | value | path | args | arg}), not a function or an expression string", `${
|
|
8096
|
+
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", `${path30}.predicates.${j}`);
|
|
8066
8097
|
});
|
|
8067
8098
|
c.steps.forEach((arm, j) => {
|
|
8068
|
-
checkArm(arm, `${
|
|
8099
|
+
checkArm(arm, `${path30}.steps.${j}`, 1, "conditional");
|
|
8069
8100
|
declared.push(armId(arm));
|
|
8070
8101
|
});
|
|
8071
8102
|
if (c.otherwise) {
|
|
8072
|
-
checkArm(c.otherwise, `${
|
|
8103
|
+
checkArm(c.otherwise, `${path30}.otherwise`, 1, "conditional");
|
|
8073
8104
|
declared.push(armId(c.otherwise));
|
|
8074
8105
|
}
|
|
8075
8106
|
break;
|
|
@@ -8078,34 +8109,34 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
8078
8109
|
const f = entry;
|
|
8079
8110
|
const o = f.opts ?? {};
|
|
8080
8111
|
if (o.concurrency !== void 0 && (o.concurrency < 1 || o.concurrency > caps.maxForeachConcurrency)) {
|
|
8081
|
-
err("cap-exceeded", `foreach.concurrency must be 1..${caps.maxForeachConcurrency}`, `${
|
|
8112
|
+
err("cap-exceeded", `foreach.concurrency must be 1..${caps.maxForeachConcurrency}`, `${path30}.opts.concurrency`);
|
|
8082
8113
|
}
|
|
8083
8114
|
if (o.maxItems !== void 0 && (o.maxItems < 1 || o.maxItems > caps.maxForeachItems)) {
|
|
8084
|
-
err("cap-exceeded", `foreach.maxItems must be 1..${caps.maxForeachItems} (the platform ceiling of maxForeachItems)`, `${
|
|
8115
|
+
err("cap-exceeded", `foreach.maxItems must be 1..${caps.maxForeachItems} (the platform ceiling of maxForeachItems)`, `${path30}.opts.maxItems`);
|
|
8085
8116
|
}
|
|
8086
8117
|
{
|
|
8087
8118
|
const itemsCap = o.maxItems ?? WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS;
|
|
8088
8119
|
const literal = o.items;
|
|
8089
8120
|
if (Array.isArray(literal) && literal.length > itemsCap) {
|
|
8090
|
-
err("foreach-items-exceed-cap", `foreach({items}) carries ${literal.length} items \u2014 above maxItems ${itemsCap}`, `${
|
|
8121
|
+
err("foreach-items-exceed-cap", `foreach({items}) carries ${literal.length} items \u2014 above maxItems ${itemsCap}`, `${path30}.opts.items`);
|
|
8091
8122
|
}
|
|
8092
8123
|
}
|
|
8093
8124
|
if (o.chunk !== void 0) {
|
|
8094
8125
|
const max = o.maxItems ?? WORKFLOW_FOREACH_DEFAULT_MAX_ITEMS;
|
|
8095
8126
|
const size = typeof o.chunk === "number" ? o.chunk : o.chunk.size;
|
|
8096
8127
|
if (!Number.isInteger(size) || size < 1 || size > max) {
|
|
8097
|
-
err("chunk-size-invalid", `foreach.chunk.size must be an integer in [1, ${max}]`, typeof o.chunk === "number" ? `${
|
|
8128
|
+
err("chunk-size-invalid", `foreach.chunk.size must be an integer in [1, ${max}]`, typeof o.chunk === "number" ? `${path30}.opts.chunk` : `${path30}.opts.chunk.size`);
|
|
8098
8129
|
}
|
|
8099
8130
|
}
|
|
8100
8131
|
if (o.rateLimit !== void 0) {
|
|
8101
8132
|
const hasS = o.rateLimit.perSecond !== void 0;
|
|
8102
8133
|
const hasM = o.rateLimit.perMinute !== void 0;
|
|
8103
8134
|
if (hasS === hasM) {
|
|
8104
|
-
err("rate-limit-invalid", "foreach.rateLimit needs exactly one of perSecond | perMinute", `${
|
|
8135
|
+
err("rate-limit-invalid", "foreach.rateLimit needs exactly one of perSecond | perMinute", `${path30}.opts.rateLimit`);
|
|
8105
8136
|
} else if (hasS && (o.rateLimit.perSecond <= 0 || o.rateLimit.perSecond > caps.maxForeachRatePerSecond)) {
|
|
8106
|
-
err("rate-limit-invalid", `rateLimit.perSecond must be in (0, ${caps.maxForeachRatePerSecond}]`, `${
|
|
8137
|
+
err("rate-limit-invalid", `rateLimit.perSecond must be in (0, ${caps.maxForeachRatePerSecond}]`, `${path30}.opts.rateLimit.perSecond`);
|
|
8107
8138
|
} else if (hasM && (o.rateLimit.perMinute <= 0 || o.rateLimit.perMinute > caps.maxForeachRatePerSecond * 60)) {
|
|
8108
|
-
err("rate-limit-invalid", `rateLimit.perMinute must be in (0, ${caps.maxForeachRatePerSecond * 60}]`, `${
|
|
8139
|
+
err("rate-limit-invalid", `rateLimit.perMinute must be in (0, ${caps.maxForeachRatePerSecond * 60}]`, `${path30}.opts.rateLimit.perMinute`);
|
|
8109
8140
|
}
|
|
8110
8141
|
}
|
|
8111
8142
|
const bodyType = f.step.type;
|
|
@@ -8120,18 +8151,18 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
8120
8151
|
const src = outputSchemas.get(d.step);
|
|
8121
8152
|
arrayLike = src === void 0 ? void 0 : schemaIsArray(schemaAtPath(src, d.path ?? ""));
|
|
8122
8153
|
}
|
|
8123
|
-
if (arrayLike === false) err("foreach-items-not-array", `foreach({items}) for "${singleId(f.step)}" binds a value that is not an array`, `${
|
|
8154
|
+
if (arrayLike === false) err("foreach-items-not-array", `foreach({items}) for "${singleId(f.step)}" binds a value that is not an array`, `${path30}.step`, singleId(f.step));
|
|
8124
8155
|
}
|
|
8125
|
-
if (bodyType === "mapping") err("container-arm-empty", "a foreach body needs a step, not a bare mapping", `${
|
|
8156
|
+
if (bodyType === "mapping") err("container-arm-empty", "a foreach body needs a step, not a bare mapping", `${path30}.step`);
|
|
8126
8157
|
else if (isHitlNode(f.step)) {
|
|
8127
8158
|
if (o.chunk !== void 0) {
|
|
8128
|
-
checkId(f.step.id, `${
|
|
8129
|
-
err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(f.step.type, f.step.id, "chunked-foreach"), `${
|
|
8130
|
-
} else checkHitlArm(f.step, `${
|
|
8159
|
+
checkId(f.step.id, `${path30}.step`);
|
|
8160
|
+
err("node-type-unsupported-in-container", workflowHitlArmShapeMessage(f.step.type, f.step.id, "chunked-foreach"), `${path30}.step`, f.step.id);
|
|
8161
|
+
} else checkHitlArm(f.step, `${path30}.step`, "foreach");
|
|
8131
8162
|
declared.push(f.step.id);
|
|
8132
8163
|
} else {
|
|
8133
|
-
checkBodyInput(f.step, `${
|
|
8134
|
-
checkSingle(f.step, `${
|
|
8164
|
+
checkBodyInput(f.step, `${path30}.step`, "foreach");
|
|
8165
|
+
checkSingle(f.step, `${path30}.step`, o.chunk ? 2 : 1);
|
|
8135
8166
|
declared.push(singleId(f.step));
|
|
8136
8167
|
}
|
|
8137
8168
|
break;
|
|
@@ -8139,31 +8170,31 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
8139
8170
|
case "loop": {
|
|
8140
8171
|
const l = entry;
|
|
8141
8172
|
if (l.maxIterations !== void 0 && (!Number.isInteger(l.maxIterations) || l.maxIterations < 1)) {
|
|
8142
|
-
err("invalid-envelope", "loop.maxIterations must be a positive integer", `${
|
|
8173
|
+
err("invalid-envelope", "loop.maxIterations must be a positive integer", `${path30}.maxIterations`);
|
|
8143
8174
|
}
|
|
8144
8175
|
if (l.intervalSeconds !== void 0 && (!Number.isInteger(l.intervalSeconds) || l.intervalSeconds < 1 || l.intervalSeconds > caps.maxLoopIntervalSeconds)) {
|
|
8145
|
-
err("loop-interval-out-of-range", `loop.intervalSeconds must be an integer in 1..${caps.maxLoopIntervalSeconds}`, `${
|
|
8176
|
+
err("loop-interval-out-of-range", `loop.intervalSeconds must be an integer in 1..${caps.maxLoopIntervalSeconds}`, `${path30}.intervalSeconds`);
|
|
8146
8177
|
}
|
|
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", `${
|
|
8178
|
+
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", `${path30}.predicate`);
|
|
8148
8179
|
const bodyType = l.step.type;
|
|
8149
|
-
if (bodyType === "mapping") err("container-arm-empty", "a loop body needs a step, not a bare mapping", `${
|
|
8180
|
+
if (bodyType === "mapping") err("container-arm-empty", "a loop body needs a step, not a bare mapping", `${path30}.step`);
|
|
8150
8181
|
else if (isHitlNode(l.step)) {
|
|
8151
|
-
checkHitlArm(l.step, `${
|
|
8182
|
+
checkHitlArm(l.step, `${path30}.step`, "loop");
|
|
8152
8183
|
declared.push(l.step.id);
|
|
8153
8184
|
} else {
|
|
8154
|
-
checkBodyInput(l.step, `${
|
|
8155
|
-
checkSingle(l.step, `${
|
|
8185
|
+
checkBodyInput(l.step, `${path30}.step`, "loop");
|
|
8186
|
+
checkSingle(l.step, `${path30}.step`, 1);
|
|
8156
8187
|
declared.push(singleId(l.step));
|
|
8157
8188
|
}
|
|
8158
8189
|
break;
|
|
8159
8190
|
}
|
|
8160
8191
|
case "approval":
|
|
8161
8192
|
case "waitForSignal":
|
|
8162
|
-
checkHitl(entry,
|
|
8193
|
+
checkHitl(entry, path30);
|
|
8163
8194
|
declared.push(entry.id);
|
|
8164
8195
|
break;
|
|
8165
8196
|
default:
|
|
8166
|
-
err("invalid-envelope", `unknown entry type "${entry.type}"`,
|
|
8197
|
+
err("invalid-envelope", `unknown entry type "${entry.type}"`, path30);
|
|
8167
8198
|
}
|
|
8168
8199
|
for (const id2 of declared) upstream.add(id2);
|
|
8169
8200
|
});
|
|
@@ -8412,11 +8443,11 @@ function compilePlan(g) {
|
|
|
8412
8443
|
}
|
|
8413
8444
|
function resolvePath(rawPath, ctx) {
|
|
8414
8445
|
const templateMatch = PATH_PLACEHOLDER.exec(rawPath.trim());
|
|
8415
|
-
const
|
|
8416
|
-
if (
|
|
8417
|
-
const dot =
|
|
8418
|
-
const scope = dot === -1 ?
|
|
8419
|
-
const rest = dot === -1 ? "" :
|
|
8446
|
+
const path30 = templateMatch ? templateMatch[1].trim() : rawPath.trim();
|
|
8447
|
+
if (path30 === "") return MISSING;
|
|
8448
|
+
const dot = path30.indexOf(".");
|
|
8449
|
+
const scope = dot === -1 ? path30 : path30.slice(0, dot);
|
|
8450
|
+
const rest = dot === -1 ? "" : path30.slice(dot + 1);
|
|
8420
8451
|
let root;
|
|
8421
8452
|
switch (scope) {
|
|
8422
8453
|
case "initData":
|
|
@@ -8450,9 +8481,9 @@ function resolvePath(rawPath, ctx) {
|
|
|
8450
8481
|
}
|
|
8451
8482
|
return walk(root, rest);
|
|
8452
8483
|
}
|
|
8453
|
-
function walk(root,
|
|
8454
|
-
if (
|
|
8455
|
-
const parts =
|
|
8484
|
+
function walk(root, path30) {
|
|
8485
|
+
if (path30 === "") return root;
|
|
8486
|
+
const parts = path30.split(".");
|
|
8456
8487
|
let value22 = root;
|
|
8457
8488
|
for (const part of parts) {
|
|
8458
8489
|
if (value22 === null || value22 === void 0) return MISSING;
|
|
@@ -8578,14 +8609,14 @@ function step(s) {
|
|
|
8578
8609
|
function stepOf(id2) {
|
|
8579
8610
|
return step(id2);
|
|
8580
8611
|
}
|
|
8581
|
-
function init(
|
|
8612
|
+
function init(path30) {
|
|
8582
8613
|
return {
|
|
8583
|
-
path:
|
|
8614
|
+
path: path30 === "" ? "initData" : `initData.${path30}`
|
|
8584
8615
|
};
|
|
8585
8616
|
}
|
|
8586
|
-
function state(
|
|
8617
|
+
function state(path30) {
|
|
8587
8618
|
return {
|
|
8588
|
-
path:
|
|
8619
|
+
path: path30 === "" ? "state" : `state.${path30}`
|
|
8589
8620
|
};
|
|
8590
8621
|
}
|
|
8591
8622
|
function lit(v) {
|
|
@@ -9515,7 +9546,7 @@ function timeZoneSupported(tz) {
|
|
|
9515
9546
|
return false;
|
|
9516
9547
|
}
|
|
9517
9548
|
}
|
|
9518
|
-
function validateBusinessHours(cal,
|
|
9549
|
+
function validateBusinessHours(cal, path30 = "businessHours") {
|
|
9519
9550
|
const issues = [];
|
|
9520
9551
|
const issue = /* @__PURE__ */ __name4((p, message) => issues.push({
|
|
9521
9552
|
code: "business-hours-invalid",
|
|
@@ -9525,32 +9556,32 @@ function validateBusinessHours(cal, path27 = "businessHours") {
|
|
|
9525
9556
|
if (typeof cal !== "object" || cal === null) return [
|
|
9526
9557
|
{
|
|
9527
9558
|
code: "business-hours-invalid",
|
|
9528
|
-
path:
|
|
9559
|
+
path: path30,
|
|
9529
9560
|
message: "not an object"
|
|
9530
9561
|
}
|
|
9531
9562
|
];
|
|
9532
9563
|
const c = cal;
|
|
9533
|
-
if (!timeZoneSupported(c.tz)) issue(`${
|
|
9564
|
+
if (!timeZoneSupported(c.tz)) issue(`${path30}.tz`, "unknown IANA time zone");
|
|
9534
9565
|
if (c.calendar === void 0 || c.calendar === "mon-fri") return issues;
|
|
9535
9566
|
if (typeof c.calendar !== "object" || c.calendar === null) {
|
|
9536
|
-
issue(`${
|
|
9567
|
+
issue(`${path30}.calendar`, "expected 'mon-fri' or { days, start, end, holidays? }");
|
|
9537
9568
|
return issues;
|
|
9538
9569
|
}
|
|
9539
9570
|
const k = c.calendar;
|
|
9540
9571
|
if (!Array.isArray(k.days) || k.days.length === 0 || k.days.some((d) => !Number.isInteger(d) || d < 0 || d > 6)) {
|
|
9541
|
-
issue(`${
|
|
9572
|
+
issue(`${path30}.calendar.days`, "days must be a non-empty array of 0\u20136");
|
|
9542
9573
|
}
|
|
9543
9574
|
const startOk = typeof k.start === "string" && HHMM.test(k.start);
|
|
9544
9575
|
const endOk = typeof k.end === "string" && HHMM.test(k.end);
|
|
9545
|
-
if (!startOk) issue(`${
|
|
9546
|
-
if (!endOk) issue(`${
|
|
9547
|
-
if (startOk && endOk && toMinutes(k.start) >= toMinutes(k.end)) issue(`${
|
|
9576
|
+
if (!startOk) issue(`${path30}.calendar.start`, "expected 'HH:MM'");
|
|
9577
|
+
if (!endOk) issue(`${path30}.calendar.end`, "expected 'HH:MM'");
|
|
9578
|
+
if (startOk && endOk && toMinutes(k.start) >= toMinutes(k.end)) issue(`${path30}.calendar`, "start must be before end");
|
|
9548
9579
|
if (k.holidays !== void 0) {
|
|
9549
|
-
if (!Array.isArray(k.holidays)) issue(`${
|
|
9580
|
+
if (!Array.isArray(k.holidays)) issue(`${path30}.calendar.holidays`, "expected an array of YYYY-MM-DD");
|
|
9550
9581
|
else {
|
|
9551
|
-
if (k.holidays.length > MAX_HOLIDAYS) issue(`${
|
|
9582
|
+
if (k.holidays.length > MAX_HOLIDAYS) issue(`${path30}.calendar.holidays`, `at most ${MAX_HOLIDAYS} holidays`);
|
|
9552
9583
|
k.holidays.forEach((h, i) => {
|
|
9553
|
-
if (typeof h !== "string" || !YMD.test(h)) issue(`${
|
|
9584
|
+
if (typeof h !== "string" || !YMD.test(h)) issue(`${path30}.calendar.holidays[${i}]`, "expected 'YYYY-MM-DD'");
|
|
9554
9585
|
});
|
|
9555
9586
|
}
|
|
9556
9587
|
}
|
|
@@ -9962,7 +9993,7 @@ function rebaseItemPointer(pointer, itemsPath, index) {
|
|
|
9962
9993
|
const base = `/${itemsPath.split(".").map(escapePointer).join("/")}/${index}`;
|
|
9963
9994
|
return pointer === "/" || pointer === "" ? base : `${base}${pointer}`;
|
|
9964
9995
|
}
|
|
9965
|
-
function validateWorkflowSchedule(schedule,
|
|
9996
|
+
function validateWorkflowSchedule(schedule, path30 = "/schedule") {
|
|
9966
9997
|
if (schedule === void 0 || schedule === null) return [];
|
|
9967
9998
|
const issue = /* @__PURE__ */ __name4((at, detail) => [
|
|
9968
9999
|
{
|
|
@@ -9973,40 +10004,40 @@ function validateWorkflowSchedule(schedule, path27 = "/schedule") {
|
|
|
9973
10004
|
}
|
|
9974
10005
|
], "issue");
|
|
9975
10006
|
if (!isObject(schedule)) {
|
|
9976
|
-
return issue(
|
|
10007
|
+
return issue(path30, `\`schedule\` is ${Array.isArray(schedule) ? "an array" : `a ${typeof schedule}`}, not a typed schedule object`);
|
|
9977
10008
|
}
|
|
9978
10009
|
const type = schedule.type;
|
|
9979
10010
|
if (type === void 0) {
|
|
9980
10011
|
const keys = Object.keys(schedule);
|
|
9981
10012
|
const seen = keys.length ? ` (got { ${keys.join(", ")} })` : " (got {})";
|
|
9982
|
-
return issue(
|
|
10013
|
+
return issue(path30, `\`schedule\` carries no \`type\` discriminator${seen}`);
|
|
9983
10014
|
}
|
|
9984
10015
|
if (typeof type !== "string" || !WORKFLOW_SCHEDULE_TYPES.includes(type)) {
|
|
9985
|
-
return issue(
|
|
10016
|
+
return issue(path30, `\`schedule.type\` ${JSON.stringify(type)} is not one of ${WORKFLOW_SCHEDULE_TYPES.map((t) => `'${t}'`).join(" | ")}`);
|
|
9986
10017
|
}
|
|
9987
10018
|
if (schedule.runAs !== void 0 && !WORKFLOW_SCHEDULE_RUN_AS.includes(schedule.runAs)) {
|
|
9988
|
-
return issue(`${
|
|
10019
|
+
return issue(`${path30}/runAs`, `\`schedule.runAs\` ${JSON.stringify(schedule.runAs)} is not one of ${WORKFLOW_SCHEDULE_RUN_AS.map((v) => `'${v}'`).join(" | ")}`);
|
|
9989
10020
|
}
|
|
9990
10021
|
switch (type) {
|
|
9991
10022
|
case "cron": {
|
|
9992
10023
|
if (typeof schedule.expression !== "string" || schedule.expression.trim().length === 0) {
|
|
9993
|
-
return issue(`${
|
|
10024
|
+
return issue(`${path30}/expression`, "a { type: 'cron' } schedule needs a non-empty string `expression`");
|
|
9994
10025
|
}
|
|
9995
10026
|
if (schedule.timezone !== void 0 && (typeof schedule.timezone !== "string" || schedule.timezone.length === 0)) {
|
|
9996
|
-
return issue(`${
|
|
10027
|
+
return issue(`${path30}/timezone`, "a { type: 'cron' } schedule's `timezone`, when given, is a non-empty IANA string");
|
|
9997
10028
|
}
|
|
9998
10029
|
return [];
|
|
9999
10030
|
}
|
|
10000
10031
|
case "interval": {
|
|
10001
10032
|
const s = schedule.seconds;
|
|
10002
10033
|
if (typeof s !== "number" || !Number.isFinite(s) || s <= 0) {
|
|
10003
|
-
return issue(`${
|
|
10034
|
+
return issue(`${path30}/seconds`, "a { type: 'interval' } schedule needs a positive number `seconds`");
|
|
10004
10035
|
}
|
|
10005
10036
|
return [];
|
|
10006
10037
|
}
|
|
10007
10038
|
case "once": {
|
|
10008
10039
|
if (typeof schedule.executeAt !== "string" || Number.isNaN(Date.parse(schedule.executeAt))) {
|
|
10009
|
-
return issue(`${
|
|
10040
|
+
return issue(`${path30}/executeAt`, "a { type: 'once' } schedule needs an ISO-8601 string `executeAt`");
|
|
10010
10041
|
}
|
|
10011
10042
|
return [];
|
|
10012
10043
|
}
|
|
@@ -10449,15 +10480,15 @@ var init_dist2 = __esm({
|
|
|
10449
10480
|
__name4(resolveDescriptor, "resolveDescriptor");
|
|
10450
10481
|
__name(resolveMapping, "resolveMapping");
|
|
10451
10482
|
__name4(resolveMapping, "resolveMapping");
|
|
10452
|
-
fromInit = /* @__PURE__ */ __name4((
|
|
10483
|
+
fromInit = /* @__PURE__ */ __name4((path30) => ({
|
|
10453
10484
|
initData: true,
|
|
10454
|
-
path:
|
|
10485
|
+
path: path30
|
|
10455
10486
|
}), "fromInit");
|
|
10456
|
-
fromStep = /* @__PURE__ */ __name4((s,
|
|
10487
|
+
fromStep = /* @__PURE__ */ __name4((s, path30 = "") => {
|
|
10457
10488
|
const idOf = /* @__PURE__ */ __name4((x) => typeof x === "string" ? x : x.id, "idOf");
|
|
10458
10489
|
return {
|
|
10459
10490
|
step: Array.isArray(s) ? s.map(idOf) : idOf(s),
|
|
10460
|
-
path:
|
|
10491
|
+
path: path30
|
|
10461
10492
|
};
|
|
10462
10493
|
}, "fromStep");
|
|
10463
10494
|
value = /* @__PURE__ */ __name4((v) => ({
|
|
@@ -10466,12 +10497,12 @@ var init_dist2 = __esm({
|
|
|
10466
10497
|
template = /* @__PURE__ */ __name4((s) => ({
|
|
10467
10498
|
template: s
|
|
10468
10499
|
}), "template");
|
|
10469
|
-
fromRequest = /* @__PURE__ */ __name4((
|
|
10470
|
-
requestContextPath:
|
|
10500
|
+
fromRequest = /* @__PURE__ */ __name4((path30) => ({
|
|
10501
|
+
requestContextPath: path30
|
|
10471
10502
|
}), "fromRequest");
|
|
10472
|
-
rows = /* @__PURE__ */ __name4((s,
|
|
10503
|
+
rows = /* @__PURE__ */ __name4((s, path30, page) => ({
|
|
10473
10504
|
step: typeof s === "string" ? s : s.id,
|
|
10474
|
-
path:
|
|
10505
|
+
path: path30,
|
|
10475
10506
|
rows: page
|
|
10476
10507
|
}), "rows");
|
|
10477
10508
|
fromKnowledge = /* @__PURE__ */ __name4((k) => ({
|
|
@@ -11474,13 +11505,13 @@ var init_workflow = __esm({
|
|
|
11474
11505
|
}
|
|
11475
11506
|
if ("step" in items && Array.isArray(items.step)) throw foreachItemsNotLowered("a fan-in fromStep([\u2026])");
|
|
11476
11507
|
if (typeof items.path !== "string") throw foreachItemsNotLowered("value(\u2026) / template(\u2026) / fromRequest(\u2026) / fromKnowledge(\u2026)");
|
|
11477
|
-
const
|
|
11478
|
-
if (
|
|
11508
|
+
const path30 = items.path;
|
|
11509
|
+
if (path30.startsWith("initData")) return {
|
|
11479
11510
|
initData: true,
|
|
11480
|
-
path:
|
|
11511
|
+
path: path30 === "initData" ? "" : path30.slice("initData.".length)
|
|
11481
11512
|
};
|
|
11482
|
-
if (
|
|
11483
|
-
const rest =
|
|
11513
|
+
if (path30.startsWith("stepResults.")) {
|
|
11514
|
+
const rest = path30.slice("stepResults.".length);
|
|
11484
11515
|
const dot = rest.indexOf(".");
|
|
11485
11516
|
return dot === -1 ? {
|
|
11486
11517
|
step: rest,
|
|
@@ -11490,7 +11521,7 @@ var init_workflow = __esm({
|
|
|
11490
11521
|
path: rest.slice(dot + 1)
|
|
11491
11522
|
};
|
|
11492
11523
|
}
|
|
11493
|
-
throw new LuaWorkflowBuildError("invalid-envelope", `foreach.items ref "${
|
|
11524
|
+
throw new LuaWorkflowBuildError("invalid-envelope", `foreach.items ref "${path30}" must point at initData.* or stepResults.*`);
|
|
11494
11525
|
}, "refToDescriptor");
|
|
11495
11526
|
__workflowCommitHook = {};
|
|
11496
11527
|
LuaWorkflow = class {
|
|
@@ -12980,8 +13011,8 @@ function buildSourceArchive(files) {
|
|
|
12980
13011
|
map[entryFile] = source;
|
|
12981
13012
|
}
|
|
12982
13013
|
if (Object.keys(map).length === 0) return null;
|
|
12983
|
-
const
|
|
12984
|
-
const gz = zlib.gzipSync(Buffer.from(
|
|
13014
|
+
const json2 = JSON.stringify(map);
|
|
13015
|
+
const gz = zlib.gzipSync(Buffer.from(json2, "utf-8"));
|
|
12985
13016
|
return gz.toString("base64");
|
|
12986
13017
|
}
|
|
12987
13018
|
function getPrimitivesByKind(manifest, kind) {
|
|
@@ -13450,12 +13481,12 @@ var init_dist3 = __esm({
|
|
|
13450
13481
|
this.options = options;
|
|
13451
13482
|
this.fetchFn = options.fetch ?? fetch;
|
|
13452
13483
|
}
|
|
13453
|
-
url(
|
|
13484
|
+
url(path30) {
|
|
13454
13485
|
const base = this.options.baseUrl.replace(/\/$/, "");
|
|
13455
|
-
return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${
|
|
13486
|
+
return `${base}/developer/agents/${encodeURIComponent(this.options.agentId)}${path30}`;
|
|
13456
13487
|
}
|
|
13457
|
-
async json(method,
|
|
13458
|
-
const endpoint = this.url(
|
|
13488
|
+
async json(method, path30, body) {
|
|
13489
|
+
const endpoint = this.url(path30);
|
|
13459
13490
|
const res = await this.fetchFn(endpoint, {
|
|
13460
13491
|
method,
|
|
13461
13492
|
headers: {
|
|
@@ -13474,7 +13505,7 @@ var init_dist3 = __esm({
|
|
|
13474
13505
|
} catch {
|
|
13475
13506
|
text2 = void 0;
|
|
13476
13507
|
}
|
|
13477
|
-
throw new BackupHttpError(`Backup request failed: ${method} ${
|
|
13508
|
+
throw new BackupHttpError(`Backup request failed: ${method} ${path30} \u2192 ${res.status} ${res.statusText}`, res.status, endpoint, text2);
|
|
13478
13509
|
}
|
|
13479
13510
|
const text = await res.text();
|
|
13480
13511
|
if (!text) return void 0;
|
|
@@ -13621,12 +13652,12 @@ var init_backup_api_service = __esm({
|
|
|
13621
13652
|
* @returns Promise resolving to missing/existing hash lists
|
|
13622
13653
|
*/
|
|
13623
13654
|
async checkBlobsExist(hashes) {
|
|
13624
|
-
const
|
|
13655
|
+
const path30 = `/developer/agents/${this.agentId}/backup/check-blobs`;
|
|
13625
13656
|
if (hashes.length <= CHECK_BLOBS_MAX_HASHES) {
|
|
13626
13657
|
const data = {
|
|
13627
13658
|
hashes
|
|
13628
13659
|
};
|
|
13629
|
-
return this.httpPost(
|
|
13660
|
+
return this.httpPost(path30, data, {});
|
|
13630
13661
|
}
|
|
13631
13662
|
const merged = {
|
|
13632
13663
|
missing: [],
|
|
@@ -13638,7 +13669,7 @@ var init_backup_api_service = __esm({
|
|
|
13638
13669
|
const data = {
|
|
13639
13670
|
hashes: hashes.slice(i, i + CHECK_BLOBS_MAX_HASHES)
|
|
13640
13671
|
};
|
|
13641
|
-
const part = await this.httpPost(
|
|
13672
|
+
const part = await this.httpPost(path30, data, {});
|
|
13642
13673
|
if (!part.success || !part.data) return part;
|
|
13643
13674
|
merged.missing.push(...part.data.missing);
|
|
13644
13675
|
merged.existing.push(...part.data.existing);
|
|
@@ -14704,7 +14735,8 @@ var init_skill_handler = __esm({
|
|
|
14704
14735
|
}
|
|
14705
14736
|
return {
|
|
14706
14737
|
name: skill.name,
|
|
14707
|
-
description
|
|
14738
|
+
// Same fallback as createOnServer — the server's version row requires a description.
|
|
14739
|
+
description: skill.description || `A Lua skill for ${skill.name}`,
|
|
14708
14740
|
// Same gate as createOnServer — server validator rejects empty content.
|
|
14709
14741
|
...hasPersonaTextContent(skill.context) ? {
|
|
14710
14742
|
context: skill.context
|
|
@@ -15236,14 +15268,14 @@ async function withErrorHandling(commandFn, commandName, opts) {
|
|
|
15236
15268
|
} catch {
|
|
15237
15269
|
}
|
|
15238
15270
|
}
|
|
15239
|
-
let
|
|
15271
|
+
let json2 = false;
|
|
15240
15272
|
try {
|
|
15241
|
-
|
|
15273
|
+
json2 = typeof opts?.json === "function" ? !!opts.json() : !!opts?.json;
|
|
15242
15274
|
} catch {
|
|
15243
15275
|
}
|
|
15244
15276
|
const reported = reportCliError(error, {
|
|
15245
15277
|
extraHint,
|
|
15246
|
-
json
|
|
15278
|
+
json: json2
|
|
15247
15279
|
});
|
|
15248
15280
|
process.exitCode = reported.exitCode;
|
|
15249
15281
|
await showUpdateWarningIfNeeded(versionCheckPromise);
|
|
@@ -20709,8 +20741,8 @@ var init_voice_plugin = __esm({
|
|
|
20709
20741
|
}, "isMissingTopLevelRequired");
|
|
20710
20742
|
for (const issue of parsed.error.issues) {
|
|
20711
20743
|
if (isMissingTopLevelRequired(issue)) continue;
|
|
20712
|
-
const
|
|
20713
|
-
errors.push(validationError(`Voice config invalid at \`${
|
|
20744
|
+
const path30 = issue.path.length > 0 ? issue.path.join(".") : "<root>";
|
|
20745
|
+
errors.push(validationError(`Voice config invalid at \`${path30}\`: ${issue.message}`, {
|
|
20714
20746
|
line
|
|
20715
20747
|
}));
|
|
20716
20748
|
}
|
|
@@ -22527,7 +22559,7 @@ function parseWorkflowScript(script, fileName) {
|
|
|
22527
22559
|
status: "deferred"
|
|
22528
22560
|
});
|
|
22529
22561
|
}, "collectRole");
|
|
22530
|
-
const
|
|
22562
|
+
const walk4 = /* @__PURE__ */ __name((node) => {
|
|
22531
22563
|
if (node === metaStatement) return;
|
|
22532
22564
|
if (ts4.isIdentifier(node)) {
|
|
22533
22565
|
const parent = node.parent;
|
|
@@ -22593,15 +22625,15 @@ function parseWorkflowScript(script, fileName) {
|
|
|
22593
22625
|
issues.push(errorAt(sf, file, t, "SCRIPT_META_INVALID", `step() timeoutSeconds must be a literal 1..${WORKFLOW_SCRIPT_STEP_MAX_TIMEOUT_SECONDS}`, "step-timeout-invalid"));
|
|
22594
22626
|
}
|
|
22595
22627
|
}
|
|
22596
|
-
if (label2)
|
|
22597
|
-
if (stepOpts)
|
|
22628
|
+
if (label2) walk4(label2);
|
|
22629
|
+
if (stepOpts) walk4(stepOpts);
|
|
22598
22630
|
return;
|
|
22599
22631
|
}
|
|
22600
22632
|
}
|
|
22601
22633
|
}
|
|
22602
|
-
ts4.forEachChild(node,
|
|
22634
|
+
ts4.forEachChild(node, walk4);
|
|
22603
22635
|
}, "walk");
|
|
22604
|
-
for (const st of sf.statements)
|
|
22636
|
+
for (const st of sf.statements) walk4(st);
|
|
22605
22637
|
return {
|
|
22606
22638
|
meta,
|
|
22607
22639
|
issues,
|
|
@@ -24265,7 +24297,7 @@ function findConfig(sourceFile, exportName) {
|
|
|
24265
24297
|
}
|
|
24266
24298
|
return argOf(sourceFile.getVariableDeclaration(exportName)?.getInitializer());
|
|
24267
24299
|
}
|
|
24268
|
-
var
|
|
24300
|
+
var ROUTE_KEY_PATTERN, SCHEMA_PARTS, LUA_CLI_SPECIFIERS, INJECTED_HELPERS, schemaKey, WebAppPlugin;
|
|
24269
24301
|
var init_web_app_plugin = __esm({
|
|
24270
24302
|
"src/compiler/plugins/web-app.plugin.ts"() {
|
|
24271
24303
|
"use strict";
|
|
@@ -24273,9 +24305,7 @@ var init_web_app_plugin = __esm({
|
|
|
24273
24305
|
init_base();
|
|
24274
24306
|
init_ast_helpers();
|
|
24275
24307
|
init_schema_converter();
|
|
24276
|
-
WEB_APP_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
24277
24308
|
ROUTE_KEY_PATTERN = new RegExp(`^(${WEB_ROUTE_METHODS.join("|")}) (/\\S*)$`);
|
|
24278
|
-
MAX_ROUTES = 200;
|
|
24279
24309
|
SCHEMA_PARTS = [
|
|
24280
24310
|
"params",
|
|
24281
24311
|
"query",
|
|
@@ -24388,8 +24418,8 @@ var init_web_app_plugin = __esm({
|
|
|
24388
24418
|
errors.push(validationError(`Web app route key ${JSON.stringify(r.key)} must look like 'GET /path' (${WEB_ROUTE_METHODS.join(", ")})`, at));
|
|
24389
24419
|
}
|
|
24390
24420
|
}
|
|
24391
|
-
if (meta.routes.length >
|
|
24392
|
-
errors.push(validationError(`Web app declares ${meta.routes.length} routes; the limit is ${
|
|
24421
|
+
if (meta.routes.length > WEB_APP_MAX_ROUTES) {
|
|
24422
|
+
errors.push(validationError(`Web app declares ${meta.routes.length} routes; the limit is ${WEB_APP_MAX_ROUTES}`, at));
|
|
24393
24423
|
}
|
|
24394
24424
|
if (meta.routes.length === 0 && !meta.hasFetch && meta.unreadableRoutes.length === 0) {
|
|
24395
24425
|
errors.push(validationError("Web app must declare at least one route or a `fetch` handler", at));
|
|
@@ -25390,9 +25420,9 @@ function packageJsonHasWorkspaces(pkgPath) {
|
|
|
25390
25420
|
if (!fileExists(pkgPath)) return false;
|
|
25391
25421
|
try {
|
|
25392
25422
|
const raw = fs9.readFileSync(pkgPath, "utf-8");
|
|
25393
|
-
const
|
|
25394
|
-
if (!
|
|
25395
|
-
return Array.isArray(
|
|
25423
|
+
const json2 = JSON.parse(raw);
|
|
25424
|
+
if (!json2.workspaces) return false;
|
|
25425
|
+
return Array.isArray(json2.workspaces) || typeof json2.workspaces === "object";
|
|
25396
25426
|
} catch {
|
|
25397
25427
|
return false;
|
|
25398
25428
|
}
|
|
@@ -29023,8 +29053,8 @@ var init_developer_api_service = __esm({
|
|
|
29023
29053
|
* @returns Promise resolving to an ApiResponse containing the profile, or null if not found
|
|
29024
29054
|
*/
|
|
29025
29055
|
async getUserProfileByEmail(email, agentId) {
|
|
29026
|
-
const
|
|
29027
|
-
const scopedPath = agentId ? `${
|
|
29056
|
+
const path30 = `/developer/user/profile/email/${encodeURIComponent(email)}`;
|
|
29057
|
+
const scopedPath = agentId ? `${path30}?agentId=${encodeURIComponent(agentId)}` : path30;
|
|
29028
29058
|
return this.httpGet(scopedPath, {});
|
|
29029
29059
|
}
|
|
29030
29060
|
/**
|
|
@@ -29034,8 +29064,8 @@ var init_developer_api_service = __esm({
|
|
|
29034
29064
|
*/
|
|
29035
29065
|
async getUserProfileByPhone(phone, agentId) {
|
|
29036
29066
|
const normalizedPhone = phone.replace(/^\+/, "");
|
|
29037
|
-
const
|
|
29038
|
-
const scopedPath = agentId ? `${
|
|
29067
|
+
const path30 = `/developer/user/profile/phone/${normalizedPhone}`;
|
|
29068
|
+
const scopedPath = agentId ? `${path30}?agentId=${encodeURIComponent(agentId)}` : path30;
|
|
29039
29069
|
return this.httpGet(scopedPath, {});
|
|
29040
29070
|
}
|
|
29041
29071
|
};
|
|
@@ -31753,6 +31783,29 @@ var AgentApi = class extends HttpClient {
|
|
|
31753
31783
|
async createSlackChannel(agentId, channelData) {
|
|
31754
31784
|
return this.httpPost(`/admin/agents/${agentId}/channels`, channelData, {});
|
|
31755
31785
|
}
|
|
31786
|
+
/** The Slack manifest for this agent: a new app's create link, or with `channelId` the update for that app. */
|
|
31787
|
+
async getSlackManifest(agentId, channelId) {
|
|
31788
|
+
const query = channelId ? `?channelId=${encodeURIComponent(channelId)}` : "";
|
|
31789
|
+
return this.httpGet(`/admin/agents/${agentId}/channels/slack/manifest${query}`, {});
|
|
31790
|
+
}
|
|
31791
|
+
/** A signed install link for a public Slack connection; the installer lands on Lua's result page. */
|
|
31792
|
+
async getSlackInstallUrl(agentId, channelId) {
|
|
31793
|
+
return this.httpPost(`/admin/agents/${agentId}/channels/${channelId}/slack/install-url`, {
|
|
31794
|
+
origin: "cli"
|
|
31795
|
+
}, {});
|
|
31796
|
+
}
|
|
31797
|
+
/** Asks Slack what the connection's token may do now; a dead token marks it uninstalled. */
|
|
31798
|
+
async checkSlackConnection(agentId, channelId) {
|
|
31799
|
+
return this.httpPost(`/admin/agents/${agentId}/channels/${channelId}/slack/check`, {}, {});
|
|
31800
|
+
}
|
|
31801
|
+
/** Saves the app's signing secret on every connection of this agent to the app. */
|
|
31802
|
+
async saveSlackSigningSecret(agentId, channelIdentifier, signingSecret) {
|
|
31803
|
+
return this.httpPut(`/admin/agents/${agentId}/channels/${encodeURIComponent(channelIdentifier)}`, {
|
|
31804
|
+
slack: {
|
|
31805
|
+
signingSecret
|
|
31806
|
+
}
|
|
31807
|
+
}, {});
|
|
31808
|
+
}
|
|
31756
31809
|
/**
|
|
31757
31810
|
* Creates a new Email channel for a specific agent
|
|
31758
31811
|
* @param agentId - The unique identifier of the agent
|
|
@@ -34666,7 +34719,7 @@ __name(apiKeyCommand, "apiKeyCommand");
|
|
|
34666
34719
|
init_cli();
|
|
34667
34720
|
init_files();
|
|
34668
34721
|
init_request_credential();
|
|
34669
|
-
import
|
|
34722
|
+
import path25 from "path";
|
|
34670
34723
|
|
|
34671
34724
|
// src/commands/sync.ts
|
|
34672
34725
|
init_dist();
|
|
@@ -36749,8 +36802,8 @@ function buildSupervisionAgentsApi(call) {
|
|
|
36749
36802
|
}), "persona"),
|
|
36750
36803
|
source: /* @__PURE__ */ __name7((agentId) => ({
|
|
36751
36804
|
list: /* @__PURE__ */ __name7(() => call("source.list", agentId), "list"),
|
|
36752
|
-
get: /* @__PURE__ */ __name7((
|
|
36753
|
-
path:
|
|
36805
|
+
get: /* @__PURE__ */ __name7((path30) => call("source.get", agentId, {
|
|
36806
|
+
path: path30
|
|
36754
36807
|
}), "get")
|
|
36755
36808
|
}), "source"),
|
|
36756
36809
|
/** Environment variable NAMES only — values are never returned. */
|
|
@@ -36762,6 +36815,211 @@ function buildSupervisionAgentsApi(call) {
|
|
|
36762
36815
|
__name(buildSupervisionAgentsApi, "buildSupervisionAgentsApi");
|
|
36763
36816
|
__name7(buildSupervisionAgentsApi, "buildSupervisionAgentsApi");
|
|
36764
36817
|
|
|
36818
|
+
// ../sandbox-runtime/dist/web-route-wrapper.mjs
|
|
36819
|
+
init_dist();
|
|
36820
|
+
var __defProp8 = Object.defineProperty;
|
|
36821
|
+
var __name8 = /* @__PURE__ */ __name((target, value3) => __defProp8(target, "name", { value: value3, configurable: true }), "__name");
|
|
36822
|
+
var WEB_ROUTE_WRAPPER_FUNCTION_SOURCE = `async function (input, primitive, logTiming, console) {
|
|
36823
|
+
const RESPONSE_HEADER_ALLOWLIST = ${JSON.stringify(WEB_ROUTE_RESPONSE_HEADER_ALLOWLIST)};
|
|
36824
|
+
const MAX_RESPONSE_BYTES = ${WEB_ROUTE_MAX_RESPONSE_BYTES};
|
|
36825
|
+
const startTime = Date.now();
|
|
36826
|
+
const timing = typeof logTiming === 'function' ? logTiming : async () => {};
|
|
36827
|
+
const req = input.request;
|
|
36828
|
+
|
|
36829
|
+
// Buffer and URLSearchParams are sandbox contract globals (shared-sandbox contract.ts).
|
|
36830
|
+
const encodeBase64 = (bytes) => Buffer.from(bytes).toString('base64');
|
|
36831
|
+
const decodeBase64 = (text) => new Uint8Array(Buffer.from(text, 'base64'));
|
|
36832
|
+
const jsonResult = (status, value) => ({ status, headers: { 'content-type': 'application/json' }, body: { kind: 'json', value } });
|
|
36833
|
+
|
|
36834
|
+
const bodyValue = req.body ? req.body.value : undefined;
|
|
36835
|
+
const rawBodyForRequest = () => {
|
|
36836
|
+
if (!req.body || req.method === 'GET') return undefined;
|
|
36837
|
+
if (req.body.kind === 'json') return JSON.stringify(req.body.value);
|
|
36838
|
+
if (req.body.kind === 'text') return req.body.value;
|
|
36839
|
+
return decodeBase64(req.body.value);
|
|
36840
|
+
};
|
|
36841
|
+
|
|
36842
|
+
// Built on first use: typed handlers get the parsed body and rarely read ctx.request,
|
|
36843
|
+
// so the body is not re-serialized (or base64-decoded) for them.
|
|
36844
|
+
let webRequest;
|
|
36845
|
+
const getRequest = () => {
|
|
36846
|
+
if (webRequest === undefined && typeof Request === 'function' && typeof URL === 'function') {
|
|
36847
|
+
const url = new URL(req.path, input.app.origin);
|
|
36848
|
+
for (const key of Object.keys(req.query || {})) {
|
|
36849
|
+
const v = req.query[key];
|
|
36850
|
+
for (const one of Array.isArray(v) ? v : [v]) url.searchParams.append(key, String(one));
|
|
36851
|
+
}
|
|
36852
|
+
webRequest = new Request(url, { method: req.method, headers: req.headers || {}, body: rawBodyForRequest() });
|
|
36853
|
+
}
|
|
36854
|
+
return webRequest;
|
|
36855
|
+
};
|
|
36856
|
+
|
|
36857
|
+
// The contract's response cap, enforced here so an oversized body is refused before it
|
|
36858
|
+
// is materialized (and base64-inflated) in the sandbox; the gateway re-checks the bytes.
|
|
36859
|
+
const tooLarge = () => jsonResult(500, { code: 'RESPONSE_TOO_LARGE', message: 'Response exceeds ' + MAX_RESPONSE_BYTES + ' bytes' });
|
|
36860
|
+
|
|
36861
|
+
// Reads a Response body up to the cap: a stream is cancelled as soon as it passes it.
|
|
36862
|
+
const readCapped = async (response) => {
|
|
36863
|
+
if (response.body && typeof response.body.getReader === 'function') {
|
|
36864
|
+
const reader = response.body.getReader();
|
|
36865
|
+
const chunks = [];
|
|
36866
|
+
let total = 0;
|
|
36867
|
+
for (;;) {
|
|
36868
|
+
const { done, value } = await reader.read();
|
|
36869
|
+
if (done) break;
|
|
36870
|
+
total += value.byteLength;
|
|
36871
|
+
if (total > MAX_RESPONSE_BYTES) {
|
|
36872
|
+
try { await reader.cancel(); } catch (e) {}
|
|
36873
|
+
return null;
|
|
36874
|
+
}
|
|
36875
|
+
chunks.push(value);
|
|
36876
|
+
}
|
|
36877
|
+
const out = new Uint8Array(total);
|
|
36878
|
+
let offset = 0;
|
|
36879
|
+
for (const c of chunks) { out.set(c, offset); offset += c.byteLength; }
|
|
36880
|
+
return out;
|
|
36881
|
+
}
|
|
36882
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
36883
|
+
return bytes.length > MAX_RESPONSE_BYTES ? null : bytes;
|
|
36884
|
+
};
|
|
36885
|
+
|
|
36886
|
+
// type/subtype without parameters, lower-cased.
|
|
36887
|
+
const mediaTypeOf = (contentType) => String(contentType || '').split(';')[0].trim().toLowerCase();
|
|
36888
|
+
const isJsonType = (t) => t === 'application/json' || t.endsWith('+json');
|
|
36889
|
+
const isTextType = (t) =>
|
|
36890
|
+
t.startsWith('text/') || t.endsWith('+xml') || t === 'application/xml' || t === 'application/javascript' || t === 'application/ecmascript';
|
|
36891
|
+
|
|
36892
|
+
const normalize = async (result) => {
|
|
36893
|
+
if (result === undefined || result === null) return { status: 204, headers: {} };
|
|
36894
|
+
const looksLikeResponse =
|
|
36895
|
+
typeof result === 'object' && typeof result.status === 'number' && result.headers && typeof result.headers.get === 'function' && typeof result.arrayBuffer === 'function';
|
|
36896
|
+
if (!looksLikeResponse) {
|
|
36897
|
+
// UTF-16 length never exceeds the UTF-8 byte length, so this under-counts at worst;
|
|
36898
|
+
// the gateway applies the exact byte cap.
|
|
36899
|
+
const serialized = JSON.stringify(result);
|
|
36900
|
+
if (serialized !== undefined && serialized.length > MAX_RESPONSE_BYTES) return tooLarge();
|
|
36901
|
+
return jsonResult(200, result);
|
|
36902
|
+
}
|
|
36903
|
+
const headers = {};
|
|
36904
|
+
result.headers.forEach((value, name) => {
|
|
36905
|
+
const n = String(name).toLowerCase();
|
|
36906
|
+
if (n === 'set-cookie') return;
|
|
36907
|
+
if (RESPONSE_HEADER_ALLOWLIST.includes(n) || n.startsWith('x-lua-')) headers[n] = value;
|
|
36908
|
+
});
|
|
36909
|
+
const out = { status: result.status, headers };
|
|
36910
|
+
if (result.status === 204 || result.status === 304) return out;
|
|
36911
|
+
const mediaType = mediaTypeOf(headers['content-type']);
|
|
36912
|
+
const bytes = await readCapped(result);
|
|
36913
|
+
if (bytes === null) return tooLarge();
|
|
36914
|
+
if (bytes.length === 0) return out;
|
|
36915
|
+
if (isJsonType(mediaType)) {
|
|
36916
|
+
const text = new TextDecoder().decode(bytes);
|
|
36917
|
+
try { out.body = { kind: 'json', value: JSON.parse(text) }; } catch (e) { out.body = { kind: 'text', value: text }; }
|
|
36918
|
+
return out;
|
|
36919
|
+
}
|
|
36920
|
+
if (isTextType(mediaType)) {
|
|
36921
|
+
out.body = { kind: 'text', value: new TextDecoder().decode(bytes) };
|
|
36922
|
+
return out;
|
|
36923
|
+
}
|
|
36924
|
+
out.body = { kind: 'base64', value: encodeBase64(bytes) };
|
|
36925
|
+
return out;
|
|
36926
|
+
};
|
|
36927
|
+
|
|
36928
|
+
const validationFailure = (part, issues) => jsonResult(400, { code: 'VALIDATION', message: 'Invalid ' + part, issues });
|
|
36929
|
+
|
|
36930
|
+
await timing('start', 'Web route started');
|
|
36931
|
+
try {
|
|
36932
|
+
const def = req.route && primitive.routes && typeof primitive.routes === 'object' ? primitive.routes[req.route] : undefined;
|
|
36933
|
+
const handler = typeof def === 'function' ? def : def && typeof def.handler === 'function' ? def.handler : undefined;
|
|
36934
|
+
let result;
|
|
36935
|
+
if (!handler) {
|
|
36936
|
+
const request = typeof primitive.fetch === 'function' ? getRequest() : undefined;
|
|
36937
|
+
if (request) {
|
|
36938
|
+
result = await normalize(await primitive.fetch(request));
|
|
36939
|
+
} else {
|
|
36940
|
+
result = jsonResult(404, { code: 'NOT_FOUND', message: 'No route handler for ' + (req.route || req.method + ' ' + req.path) });
|
|
36941
|
+
}
|
|
36942
|
+
} else {
|
|
36943
|
+
const parsed = { params: req.params || {}, query: req.query || {}, body: bodyValue };
|
|
36944
|
+
const schemas = typeof def === 'object' && def ? def : {};
|
|
36945
|
+
for (const part of ['params', 'query', 'body']) {
|
|
36946
|
+
const schema = schemas[part];
|
|
36947
|
+
if (schema && typeof schema.safeParse === 'function') {
|
|
36948
|
+
const r = schema.safeParse(parsed[part]);
|
|
36949
|
+
if (!r.success) {
|
|
36950
|
+
const issues = r.error && Array.isArray(r.error.issues) ? r.error.issues : r.error;
|
|
36951
|
+
result = validationFailure(part, issues);
|
|
36952
|
+
break;
|
|
36953
|
+
}
|
|
36954
|
+
parsed[part] = r.data;
|
|
36955
|
+
}
|
|
36956
|
+
}
|
|
36957
|
+
if (!result) {
|
|
36958
|
+
const ctx = {
|
|
36959
|
+
params: parsed.params,
|
|
36960
|
+
query: parsed.query,
|
|
36961
|
+
body: parsed.body,
|
|
36962
|
+
headers: req.headers || {},
|
|
36963
|
+
method: req.method,
|
|
36964
|
+
path: req.path,
|
|
36965
|
+
route: req.route,
|
|
36966
|
+
auth: input.auth,
|
|
36967
|
+
app: input.app,
|
|
36968
|
+
get request() {
|
|
36969
|
+
return getRequest();
|
|
36970
|
+
},
|
|
36971
|
+
};
|
|
36972
|
+
result = await normalize(await handler(ctx));
|
|
36973
|
+
}
|
|
36974
|
+
}
|
|
36975
|
+
const duration = Date.now() - startTime;
|
|
36976
|
+
timing('complete', 'Web route completed', duration).catch((err) => console.error('Error logging timing', err));
|
|
36977
|
+
console.log('Web route', req.route || req.method + ' ' + req.path, 'answered', result.status, 'in', duration, 'ms');
|
|
36978
|
+
return result;
|
|
36979
|
+
} catch (error) {
|
|
36980
|
+
const duration = Date.now() - startTime;
|
|
36981
|
+
timing('error', 'Web route failed', duration, error).catch((err) => console.error('Error logging timing', err));
|
|
36982
|
+
console.error('Web route failed after', duration, 'ms:', error);
|
|
36983
|
+
throw error;
|
|
36984
|
+
}
|
|
36985
|
+
}`;
|
|
36986
|
+
function buildWebRouteWrapper(decompressedCode, input) {
|
|
36987
|
+
const code = `
|
|
36988
|
+
// Run the bundled module
|
|
36989
|
+
${decompressedCode}
|
|
36990
|
+
|
|
36991
|
+
// Extract primitive from module exports
|
|
36992
|
+
const __exports = module.exports.default || module.exports;
|
|
36993
|
+
const __primitive = __exports?.primitive;
|
|
36994
|
+
|
|
36995
|
+
if (
|
|
36996
|
+
!__primitive ||
|
|
36997
|
+
(typeof __primitive.fetch !== 'function' && (!__primitive.routes || typeof __primitive.routes !== 'object'))
|
|
36998
|
+
) {
|
|
36999
|
+
const __platformErr = new Error('[Lua] Invalid web-app artifact: missing primitive.routes or primitive.fetch');
|
|
37000
|
+
__platformErr.code = 'PLATFORM_VM_ERROR';
|
|
37001
|
+
throw __platformErr;
|
|
37002
|
+
}
|
|
37003
|
+
|
|
37004
|
+
// Wrapper function
|
|
37005
|
+
const wrapperFunction = ${WEB_ROUTE_WRAPPER_FUNCTION_SOURCE};
|
|
37006
|
+
|
|
37007
|
+
// Execute immediately and return result
|
|
37008
|
+
(async () => {
|
|
37009
|
+
return await wrapperFunction(${JSON.stringify(input)}, __primitive, typeof logTiming === 'function' ? logTiming : undefined, console);
|
|
37010
|
+
})();
|
|
37011
|
+
`;
|
|
37012
|
+
return {
|
|
37013
|
+
code,
|
|
37014
|
+
contextName: "WebRouteExecutionContext",
|
|
37015
|
+
contextOrigin: "web-route-execution",
|
|
37016
|
+
source: "web-route",
|
|
37017
|
+
timeoutMs: WEB_ROUTE_MAX_WALL_MS
|
|
37018
|
+
};
|
|
37019
|
+
}
|
|
37020
|
+
__name(buildWebRouteWrapper, "buildWebRouteWrapper");
|
|
37021
|
+
__name8(buildWebRouteWrapper, "buildWebRouteWrapper");
|
|
37022
|
+
|
|
36765
37023
|
// src/utils/sandbox.ts
|
|
36766
37024
|
init_dist4();
|
|
36767
37025
|
import vm4 from "vm";
|
|
@@ -36882,8 +37140,8 @@ import path20 from "path";
|
|
|
36882
37140
|
import { spawn as nodeSpawn } from "child_process";
|
|
36883
37141
|
import { accessSync, constants as fsConstants, realpathSync, statSync as statSync5 } from "fs";
|
|
36884
37142
|
import path19 from "path";
|
|
36885
|
-
var
|
|
36886
|
-
var
|
|
37143
|
+
var __defProp9 = Object.defineProperty;
|
|
37144
|
+
var __name9 = /* @__PURE__ */ __name((target, value3) => __defProp9(target, "name", { value: value3, configurable: true }), "__name");
|
|
36887
37145
|
var WORKFLOW_EXEC_BINARIES = Object.freeze([
|
|
36888
37146
|
"git",
|
|
36889
37147
|
"gh",
|
|
@@ -36910,7 +37168,7 @@ var WorkflowExecError = class extends Error {
|
|
|
36910
37168
|
__name(this, "WorkflowExecError");
|
|
36911
37169
|
}
|
|
36912
37170
|
static {
|
|
36913
|
-
|
|
37171
|
+
__name9(this, "WorkflowExecError");
|
|
36914
37172
|
}
|
|
36915
37173
|
code;
|
|
36916
37174
|
reason;
|
|
@@ -36944,7 +37202,7 @@ function isWorkflowExecError(err) {
|
|
|
36944
37202
|
return !!e && typeof e === "object" && e.name === "ExecError" && typeof e.code === "string";
|
|
36945
37203
|
}
|
|
36946
37204
|
__name(isWorkflowExecError, "isWorkflowExecError");
|
|
36947
|
-
|
|
37205
|
+
__name9(isWorkflowExecError, "isWorkflowExecError");
|
|
36948
37206
|
function workflowExecRefusal(reason, detail, argv) {
|
|
36949
37207
|
return new WorkflowExecError("EXEC_REFUSED", `[Lua] exec refused: ${detail} (EXEC_REFUSED/${reason})`, {
|
|
36950
37208
|
reason,
|
|
@@ -36954,7 +37212,7 @@ function workflowExecRefusal(reason, detail, argv) {
|
|
|
36954
37212
|
});
|
|
36955
37213
|
}
|
|
36956
37214
|
__name(workflowExecRefusal, "workflowExecRefusal");
|
|
36957
|
-
|
|
37215
|
+
__name9(workflowExecRefusal, "workflowExecRefusal");
|
|
36958
37216
|
var refused = workflowExecRefusal;
|
|
36959
37217
|
var ALLOWLIST_TEXT = WORKFLOW_EXEC_BINARIES.join(", ");
|
|
36960
37218
|
function parseCommandTemplate(template3, values) {
|
|
@@ -36965,13 +37223,13 @@ function parseCommandTemplate(template3, values) {
|
|
|
36965
37223
|
const argv = [];
|
|
36966
37224
|
let current = null;
|
|
36967
37225
|
let quote = null;
|
|
36968
|
-
const flush = /* @__PURE__ */
|
|
37226
|
+
const flush = /* @__PURE__ */ __name9(() => {
|
|
36969
37227
|
if (current !== null) {
|
|
36970
37228
|
argv.push(current);
|
|
36971
37229
|
current = null;
|
|
36972
37230
|
}
|
|
36973
37231
|
}, "flush");
|
|
36974
|
-
const scalar = /* @__PURE__ */
|
|
37232
|
+
const scalar = /* @__PURE__ */ __name9((v, at) => {
|
|
36975
37233
|
if (typeof v === "string") return v;
|
|
36976
37234
|
if (typeof v === "number" && Number.isFinite(v)) return String(v);
|
|
36977
37235
|
if (typeof v === "boolean") return String(v);
|
|
@@ -37032,7 +37290,7 @@ function parseCommandTemplate(template3, values) {
|
|
|
37032
37290
|
return argv;
|
|
37033
37291
|
}
|
|
37034
37292
|
__name(parseCommandTemplate, "parseCommandTemplate");
|
|
37035
|
-
|
|
37293
|
+
__name9(parseCommandTemplate, "parseCommandTemplate");
|
|
37036
37294
|
function validateWorkflowExecArgv(argv) {
|
|
37037
37295
|
if (!Array.isArray(argv)) throw refused("argv_invalid", 'argv must be an array of strings \u2014 exec(["git", "status"])');
|
|
37038
37296
|
if (argv.length === 0) throw refused("argv_empty", "the command is empty");
|
|
@@ -37054,7 +37312,7 @@ function validateWorkflowExecArgv(argv) {
|
|
|
37054
37312
|
];
|
|
37055
37313
|
}
|
|
37056
37314
|
__name(validateWorkflowExecArgv, "validateWorkflowExecArgv");
|
|
37057
|
-
|
|
37315
|
+
__name9(validateWorkflowExecArgv, "validateWorkflowExecArgv");
|
|
37058
37316
|
function resolveWorkflowExecBinary(name, pathDirs) {
|
|
37059
37317
|
if (typeof name !== "string" || name.length === 0) throw refused("argv_invalid", "argv[0] must name a binary");
|
|
37060
37318
|
if (name.includes("/") || name.includes("\\") || name.startsWith(".")) {
|
|
@@ -37083,12 +37341,12 @@ function resolveWorkflowExecBinary(name, pathDirs) {
|
|
|
37083
37341
|
]);
|
|
37084
37342
|
}
|
|
37085
37343
|
__name(resolveWorkflowExecBinary, "resolveWorkflowExecBinary");
|
|
37086
|
-
|
|
37344
|
+
__name9(resolveWorkflowExecBinary, "resolveWorkflowExecBinary");
|
|
37087
37345
|
function within(root, p) {
|
|
37088
37346
|
return p === root || p.startsWith(root.endsWith(path19.sep) ? root : root + path19.sep);
|
|
37089
37347
|
}
|
|
37090
37348
|
__name(within, "within");
|
|
37091
|
-
|
|
37349
|
+
__name9(within, "within");
|
|
37092
37350
|
function confineWorkflowExecCwd(root, cwd) {
|
|
37093
37351
|
if (typeof root !== "string" || root.length === 0) throw refused("workspace_unavailable", "the step has no workspace");
|
|
37094
37352
|
let rootReal;
|
|
@@ -37122,7 +37380,7 @@ function confineWorkflowExecCwd(root, cwd) {
|
|
|
37122
37380
|
return abs;
|
|
37123
37381
|
}
|
|
37124
37382
|
__name(confineWorkflowExecCwd, "confineWorkflowExecCwd");
|
|
37125
|
-
|
|
37383
|
+
__name9(confineWorkflowExecCwd, "confineWorkflowExecCwd");
|
|
37126
37384
|
var RESERVED_ENV_KEY = /^(LUA_|LD_|DYLD_|GIT_|GH_|GITHUB_)|^(PATH|HOME|NODE_OPTIONS|BASH_ENV|ENV|TZ)$|_PROXY$/i;
|
|
37127
37385
|
function checkWorkflowExecEnv(env) {
|
|
37128
37386
|
if (env === void 0) return {};
|
|
@@ -37140,7 +37398,7 @@ function checkWorkflowExecEnv(env) {
|
|
|
37140
37398
|
return out;
|
|
37141
37399
|
}
|
|
37142
37400
|
__name(checkWorkflowExecEnv, "checkWorkflowExecEnv");
|
|
37143
|
-
|
|
37401
|
+
__name9(checkWorkflowExecEnv, "checkWorkflowExecEnv");
|
|
37144
37402
|
var WORKFLOW_EXEC_GIT_DENIED_SUBCOMMANDS = Object.freeze([
|
|
37145
37403
|
"push-mirror",
|
|
37146
37404
|
"daemon",
|
|
@@ -37170,7 +37428,7 @@ function gitOptionMatches(arg, opt) {
|
|
|
37170
37428
|
return opt.length === 2 && arg.length > 2 && arg.startsWith(opt);
|
|
37171
37429
|
}
|
|
37172
37430
|
__name(gitOptionMatches, "gitOptionMatches");
|
|
37173
|
-
|
|
37431
|
+
__name9(gitOptionMatches, "gitOptionMatches");
|
|
37174
37432
|
var GIT_PUSH_FORBIDDEN_FLAG = /^(--mirror|--delete|-d|-f|--force|--force-with-lease(=.*)?|--force-if-includes|--prune|--all|--tags)$/;
|
|
37175
37433
|
function checkWorkflowExecGitArgv(argv, opts = {}) {
|
|
37176
37434
|
if (argv[0] !== "git") return {};
|
|
@@ -37213,9 +37471,9 @@ function checkWorkflowExecGitArgv(argv, opts = {}) {
|
|
|
37213
37471
|
};
|
|
37214
37472
|
}
|
|
37215
37473
|
__name(checkWorkflowExecGitArgv, "checkWorkflowExecGitArgv");
|
|
37216
|
-
|
|
37474
|
+
__name9(checkWorkflowExecGitArgv, "checkWorkflowExecGitArgv");
|
|
37217
37475
|
function formatWorkflowExecArgv(argv, max = WORKFLOW_EXEC_LOG_ARGV_MAX) {
|
|
37218
|
-
const q = /* @__PURE__ */
|
|
37476
|
+
const q = /* @__PURE__ */ __name9((a) => {
|
|
37219
37477
|
const s = String(a);
|
|
37220
37478
|
return s.length > 0 && /^[A-Za-z0-9_@%+=:,./-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
37221
37479
|
}, "q");
|
|
@@ -37223,7 +37481,7 @@ function formatWorkflowExecArgv(argv, max = WORKFLOW_EXEC_LOG_ARGV_MAX) {
|
|
|
37223
37481
|
return line.length > max ? `${line.slice(0, max)}\u2026` : line;
|
|
37224
37482
|
}
|
|
37225
37483
|
__name(formatWorkflowExecArgv, "formatWorkflowExecArgv");
|
|
37226
|
-
|
|
37484
|
+
__name9(formatWorkflowExecArgv, "formatWorkflowExecArgv");
|
|
37227
37485
|
function spawnWorkflowExec(o) {
|
|
37228
37486
|
const spawnFn = o.spawnImpl ?? nodeSpawn;
|
|
37229
37487
|
const max = o.outputMaxBytes ?? WORKFLOW_EXEC_OUTPUT_MAX_BYTES;
|
|
@@ -37258,7 +37516,7 @@ function spawnWorkflowExec(o) {
|
|
|
37258
37516
|
let settled = false;
|
|
37259
37517
|
let killTimer;
|
|
37260
37518
|
let wallTimer;
|
|
37261
|
-
const collect2 = /* @__PURE__ */
|
|
37519
|
+
const collect2 = /* @__PURE__ */ __name9((stream) => {
|
|
37262
37520
|
const chunks = [];
|
|
37263
37521
|
let bytes = 0;
|
|
37264
37522
|
stream?.on("data", (c) => {
|
|
@@ -37281,7 +37539,7 @@ function spawnWorkflowExec(o) {
|
|
|
37281
37539
|
}, "collect");
|
|
37282
37540
|
const stdout = collect2(child.stdout);
|
|
37283
37541
|
const stderr = collect2(child.stderr);
|
|
37284
|
-
const killTree = /* @__PURE__ */
|
|
37542
|
+
const killTree = /* @__PURE__ */ __name9((sig) => {
|
|
37285
37543
|
const pid = child.pid;
|
|
37286
37544
|
if (!pid) return;
|
|
37287
37545
|
try {
|
|
@@ -37290,7 +37548,7 @@ function spawnWorkflowExec(o) {
|
|
|
37290
37548
|
} catch {
|
|
37291
37549
|
}
|
|
37292
37550
|
}, "killTree");
|
|
37293
|
-
const end = /* @__PURE__ */
|
|
37551
|
+
const end = /* @__PURE__ */ __name9(() => {
|
|
37294
37552
|
if (settled || timedOut) return;
|
|
37295
37553
|
timedOut = true;
|
|
37296
37554
|
killTree("SIGTERM");
|
|
@@ -37301,7 +37559,7 @@ function spawnWorkflowExec(o) {
|
|
|
37301
37559
|
}, grace);
|
|
37302
37560
|
killTimer.unref?.();
|
|
37303
37561
|
}, "end");
|
|
37304
|
-
const cleanup = /* @__PURE__ */
|
|
37562
|
+
const cleanup = /* @__PURE__ */ __name9(() => {
|
|
37305
37563
|
if (wallTimer) clearTimeout(wallTimer);
|
|
37306
37564
|
if (killTimer) clearTimeout(killTimer);
|
|
37307
37565
|
o.signal?.removeEventListener("abort", end);
|
|
@@ -37335,7 +37593,7 @@ function spawnWorkflowExec(o) {
|
|
|
37335
37593
|
});
|
|
37336
37594
|
}
|
|
37337
37595
|
__name(spawnWorkflowExec, "spawnWorkflowExec");
|
|
37338
|
-
|
|
37596
|
+
__name9(spawnWorkflowExec, "spawnWorkflowExec");
|
|
37339
37597
|
async function runWorkflowExec(o) {
|
|
37340
37598
|
const argv = validateWorkflowExecArgv(o.request.argv);
|
|
37341
37599
|
const file = resolveWorkflowExecBinary(argv[0], o.pathDirs);
|
|
@@ -37381,7 +37639,7 @@ async function runWorkflowExec(o) {
|
|
|
37381
37639
|
});
|
|
37382
37640
|
}
|
|
37383
37641
|
__name(runWorkflowExec, "runWorkflowExec");
|
|
37384
|
-
|
|
37642
|
+
__name9(runWorkflowExec, "runWorkflowExec");
|
|
37385
37643
|
function createWorkflowExecQueue() {
|
|
37386
37644
|
let tail = Promise.resolve();
|
|
37387
37645
|
return (task) => {
|
|
@@ -37391,7 +37649,7 @@ function createWorkflowExecQueue() {
|
|
|
37391
37649
|
};
|
|
37392
37650
|
}
|
|
37393
37651
|
__name(createWorkflowExecQueue, "createWorkflowExecQueue");
|
|
37394
|
-
|
|
37652
|
+
__name9(createWorkflowExecQueue, "createWorkflowExecQueue");
|
|
37395
37653
|
function stderrTail(s) {
|
|
37396
37654
|
const t = s.trim();
|
|
37397
37655
|
if (!t) return "";
|
|
@@ -37399,9 +37657,9 @@ function stderrTail(s) {
|
|
|
37399
37657
|
return `: ${tail.replace(/\s+/g, " ")}`;
|
|
37400
37658
|
}
|
|
37401
37659
|
__name(stderrTail, "stderrTail");
|
|
37402
|
-
|
|
37660
|
+
__name9(stderrTail, "stderrTail");
|
|
37403
37661
|
function buildWorkflowExecApi(run) {
|
|
37404
|
-
const call = /* @__PURE__ */
|
|
37662
|
+
const call = /* @__PURE__ */ __name9(async (req, strict) => {
|
|
37405
37663
|
const out = await run(req);
|
|
37406
37664
|
if (out.timedOut) {
|
|
37407
37665
|
throw new WorkflowExecError("EXEC_TIMEOUT", `[Lua] ${formatWorkflowExecArgv(out.argv)} did not finish within its wall (${out.durationMs} ms) and was killed (EXEC_TIMEOUT)`, out);
|
|
@@ -37411,7 +37669,7 @@ function buildWorkflowExecApi(run) {
|
|
|
37411
37669
|
}
|
|
37412
37670
|
return out;
|
|
37413
37671
|
}, "call");
|
|
37414
|
-
const request2 = /* @__PURE__ */
|
|
37672
|
+
const request2 = /* @__PURE__ */ __name9((argv, opts) => {
|
|
37415
37673
|
const o = opts && typeof opts === "object" ? opts : {};
|
|
37416
37674
|
return {
|
|
37417
37675
|
argv,
|
|
@@ -37420,9 +37678,9 @@ function buildWorkflowExecApi(run) {
|
|
|
37420
37678
|
env: o.env
|
|
37421
37679
|
};
|
|
37422
37680
|
}, "request");
|
|
37423
|
-
const exec = /* @__PURE__ */
|
|
37681
|
+
const exec = /* @__PURE__ */ __name9((argv, opts) => call(request2(argv, opts), false), "exec");
|
|
37424
37682
|
exec.strict = (argv, opts) => call(request2(argv, opts), true);
|
|
37425
|
-
const $ = /* @__PURE__ */
|
|
37683
|
+
const $ = /* @__PURE__ */ __name9(async (strings, ...values) => call({
|
|
37426
37684
|
argv: parseCommandTemplate(strings, values)
|
|
37427
37685
|
}, false), "$");
|
|
37428
37686
|
$.strict = async (strings, ...values) => call({
|
|
@@ -37434,16 +37692,16 @@ function buildWorkflowExecApi(run) {
|
|
|
37434
37692
|
};
|
|
37435
37693
|
}
|
|
37436
37694
|
__name(buildWorkflowExecApi, "buildWorkflowExecApi");
|
|
37437
|
-
|
|
37695
|
+
__name9(buildWorkflowExecApi, "buildWorkflowExecApi");
|
|
37438
37696
|
function unavailableWorkflowExecApi(why) {
|
|
37439
|
-
const reject = /* @__PURE__ */
|
|
37697
|
+
const reject = /* @__PURE__ */ __name9(async () => {
|
|
37440
37698
|
throw new WorkflowExecError("EXEC_UNAVAILABLE", `[Lua] ctx.exec is not available here: ${why} (EXEC_UNAVAILABLE)`);
|
|
37441
37699
|
}, "reject");
|
|
37442
37700
|
const exec = Object.assign(() => reject(), {
|
|
37443
|
-
strict: /* @__PURE__ */
|
|
37701
|
+
strict: /* @__PURE__ */ __name9(() => reject(), "strict")
|
|
37444
37702
|
});
|
|
37445
37703
|
const $ = Object.assign(() => reject(), {
|
|
37446
|
-
strict: /* @__PURE__ */
|
|
37704
|
+
strict: /* @__PURE__ */ __name9(() => reject(), "strict")
|
|
37447
37705
|
});
|
|
37448
37706
|
return {
|
|
37449
37707
|
exec,
|
|
@@ -37451,7 +37709,7 @@ function unavailableWorkflowExecApi(why) {
|
|
|
37451
37709
|
};
|
|
37452
37710
|
}
|
|
37453
37711
|
__name(unavailableWorkflowExecApi, "unavailableWorkflowExecApi");
|
|
37454
|
-
|
|
37712
|
+
__name9(unavailableWorkflowExecApi, "unavailableWorkflowExecApi");
|
|
37455
37713
|
|
|
37456
37714
|
// src/utils/workflow-exec.ts
|
|
37457
37715
|
var WORKFLOW_LOCAL_EXEC_ENV_KEYS = [
|
|
@@ -39441,6 +39699,28 @@ module.exports = async (event) => {
|
|
|
39441
39699
|
}
|
|
39442
39700
|
}
|
|
39443
39701
|
__name(executeWebhook, "executeWebhook");
|
|
39702
|
+
async function executeWebRoute(options) {
|
|
39703
|
+
const context = vm4.createContext(createSandbox(options));
|
|
39704
|
+
applyGlobalSelfReference(context);
|
|
39705
|
+
const wrapper = buildWebRouteWrapper(options.appCode, options.input);
|
|
39706
|
+
const pending = vm4.runInContext(wrapper.code, context, {
|
|
39707
|
+
filename: "web-app.bundle.js",
|
|
39708
|
+
timeout: wrapper.timeoutMs
|
|
39709
|
+
});
|
|
39710
|
+
let timer;
|
|
39711
|
+
const wall = new Promise((_, reject) => {
|
|
39712
|
+
timer = setTimeout(() => reject(new Error(`The route did not answer within ${wrapper.timeoutMs} ms (the wall-clock cap)`)), wrapper.timeoutMs);
|
|
39713
|
+
});
|
|
39714
|
+
try {
|
|
39715
|
+
return await Promise.race([
|
|
39716
|
+
pending,
|
|
39717
|
+
wall
|
|
39718
|
+
]);
|
|
39719
|
+
} finally {
|
|
39720
|
+
clearTimeout(timer);
|
|
39721
|
+
}
|
|
39722
|
+
}
|
|
39723
|
+
__name(executeWebRoute, "executeWebRoute");
|
|
39444
39724
|
async function executeJob(options) {
|
|
39445
39725
|
const { jobCode, jobData, apiKey, agentId } = options;
|
|
39446
39726
|
const sandbox = createSandbox(options);
|
|
@@ -39718,12 +39998,12 @@ function isWrittenAsModelClassRef(model) {
|
|
|
39718
39998
|
}
|
|
39719
39999
|
__name(isWrittenAsModelClassRef, "isWrittenAsModelClassRef");
|
|
39720
40000
|
var oneOf = /* @__PURE__ */ __name((tuple) => tuple.map((v) => `\`${v}\``).join(", "), "oneOf");
|
|
39721
|
-
function validateAgentNodeModelMembers(node,
|
|
40001
|
+
function validateAgentNodeModelMembers(node, path30) {
|
|
39722
40002
|
const issues = [];
|
|
39723
40003
|
if (typeof node.model === "string" && isWrittenAsModelClassRef(node.model)) {
|
|
39724
40004
|
if (!modelClassOf(node.model)) {
|
|
39725
40005
|
issues.push({
|
|
39726
|
-
path: `${
|
|
40006
|
+
path: `${path30}.model`,
|
|
39727
40007
|
code: "model-class-unknown",
|
|
39728
40008
|
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`
|
|
39729
40009
|
});
|
|
@@ -39732,7 +40012,7 @@ function validateAgentNodeModelMembers(node, path27) {
|
|
|
39732
40012
|
if (node.taskClass !== void 0) {
|
|
39733
40013
|
if (typeof node.taskClass !== "string" || !isWorkflowTaskClass(node.taskClass)) {
|
|
39734
40014
|
issues.push({
|
|
39735
|
-
path: `${
|
|
40015
|
+
path: `${path30}.taskClass`,
|
|
39736
40016
|
code: "task-class-unknown",
|
|
39737
40017
|
message: `"${String(node.taskClass)}" is not a task class \u2014 use one of ${oneOf(WORKFLOW_TASK_CLASSES)}`
|
|
39738
40018
|
});
|
|
@@ -39741,7 +40021,7 @@ function validateAgentNodeModelMembers(node, path27) {
|
|
|
39741
40021
|
if (node.requires !== void 0) {
|
|
39742
40022
|
if (!Array.isArray(node.requires)) {
|
|
39743
40023
|
issues.push({
|
|
39744
|
-
path: `${
|
|
40024
|
+
path: `${path30}.requires`,
|
|
39745
40025
|
code: "requires-invalid",
|
|
39746
40026
|
message: `\`requires\` must be an array of ${oneOf(WORKFLOW_MODEL_TRAITS)}`
|
|
39747
40027
|
});
|
|
@@ -39749,7 +40029,7 @@ function validateAgentNodeModelMembers(node, path27) {
|
|
|
39749
40029
|
node.requires.forEach((trait, i) => {
|
|
39750
40030
|
if (typeof trait !== "string" || !isWorkflowModelTrait(trait)) {
|
|
39751
40031
|
issues.push({
|
|
39752
|
-
path: `${
|
|
40032
|
+
path: `${path30}.requires.${i}`,
|
|
39753
40033
|
code: "model-trait-unknown",
|
|
39754
40034
|
message: `"${String(trait)}" is not a model trait \u2014 use one of ${oneOf(WORKFLOW_MODEL_TRAITS)}`
|
|
39755
40035
|
});
|
|
@@ -39760,7 +40040,7 @@ function validateAgentNodeModelMembers(node, path27) {
|
|
|
39760
40040
|
if (node.effort !== void 0) {
|
|
39761
40041
|
if (typeof node.effort !== "string" || !isWorkflowEffort(node.effort)) {
|
|
39762
40042
|
issues.push({
|
|
39763
|
-
path: `${
|
|
40043
|
+
path: `${path30}.effort`,
|
|
39764
40044
|
code: "effort-unknown",
|
|
39765
40045
|
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.)`
|
|
39766
40046
|
});
|
|
@@ -39769,13 +40049,13 @@ function validateAgentNodeModelMembers(node, path27) {
|
|
|
39769
40049
|
if (node.modelReason !== void 0) {
|
|
39770
40050
|
if (typeof node.modelReason !== "string") {
|
|
39771
40051
|
issues.push({
|
|
39772
|
-
path: `${
|
|
40052
|
+
path: `${path30}.modelReason`,
|
|
39773
40053
|
code: "model-reason-invalid",
|
|
39774
40054
|
message: "`modelReason` must be a string"
|
|
39775
40055
|
});
|
|
39776
40056
|
} else if (node.modelReason.length > WORKFLOW_MODEL_REASON_MAX_LENGTH) {
|
|
39777
40057
|
issues.push({
|
|
39778
|
-
path: `${
|
|
40058
|
+
path: `${path30}.modelReason`,
|
|
39779
40059
|
code: "model-reason-too-long",
|
|
39780
40060
|
message: `\`modelReason\` is ${node.modelReason.length} characters \u2014 the cap is ${WORKFLOW_MODEL_REASON_MAX_LENGTH}`
|
|
39781
40061
|
});
|
|
@@ -39795,22 +40075,22 @@ var MEMBERS = [
|
|
|
39795
40075
|
function validateGraphModelMembers(graph) {
|
|
39796
40076
|
const issues = [];
|
|
39797
40077
|
const seen = /* @__PURE__ */ new Set();
|
|
39798
|
-
const
|
|
40078
|
+
const walk4 = /* @__PURE__ */ __name((value3, path30, depth) => {
|
|
39799
40079
|
if (depth > WORKFLOW_MODEL_WALK_MAX_DEPTH || value3 === null || typeof value3 !== "object") return;
|
|
39800
40080
|
if (seen.has(value3)) return;
|
|
39801
40081
|
seen.add(value3);
|
|
39802
40082
|
if (Array.isArray(value3)) {
|
|
39803
|
-
value3.forEach((v, i) =>
|
|
40083
|
+
value3.forEach((v, i) => walk4(v, `${path30}.${i}`, depth + 1));
|
|
39804
40084
|
return;
|
|
39805
40085
|
}
|
|
39806
40086
|
const node = value3;
|
|
39807
40087
|
if (MEMBERS.some((m) => node[m] !== void 0)) {
|
|
39808
|
-
const label2 = typeof node.id === "string" && node.id ? node.id :
|
|
40088
|
+
const label2 = typeof node.id === "string" && node.id ? node.id : path30;
|
|
39809
40089
|
issues.push(...validateAgentNodeModelMembers(node, label2));
|
|
39810
40090
|
}
|
|
39811
|
-
for (const [k, v] of Object.entries(node))
|
|
40091
|
+
for (const [k, v] of Object.entries(node)) walk4(v, path30 ? `${path30}.${k}` : k, depth + 1);
|
|
39812
40092
|
}, "walk");
|
|
39813
|
-
|
|
40093
|
+
walk4(graph, "", 0);
|
|
39814
40094
|
return issues;
|
|
39815
40095
|
}
|
|
39816
40096
|
__name(validateGraphModelMembers, "validateGraphModelMembers");
|
|
@@ -40064,6 +40344,325 @@ function workflowModelMemberError(workflowName, issues) {
|
|
|
40064
40344
|
}
|
|
40065
40345
|
__name(workflowModelMemberError, "workflowModelMemberError");
|
|
40066
40346
|
|
|
40347
|
+
// src/primitives/web-app.handler.ts
|
|
40348
|
+
init_types();
|
|
40349
|
+
init_constants();
|
|
40350
|
+
import path24 from "path";
|
|
40351
|
+
|
|
40352
|
+
// src/api/web-app.api.service.ts
|
|
40353
|
+
init_http_client();
|
|
40354
|
+
var WebAppApi = class extends HttpClient {
|
|
40355
|
+
static {
|
|
40356
|
+
__name(this, "WebAppApi");
|
|
40357
|
+
}
|
|
40358
|
+
agentId;
|
|
40359
|
+
constructor(baseUrl, credential, agentId) {
|
|
40360
|
+
super(baseUrl, credential);
|
|
40361
|
+
this.agentId = agentId;
|
|
40362
|
+
}
|
|
40363
|
+
/** Every web app of the agent, each with its versions (newest first). */
|
|
40364
|
+
async getWebApps() {
|
|
40365
|
+
return this.httpGet(`/developer/web-apps/${this.agentId}`, {});
|
|
40366
|
+
}
|
|
40367
|
+
/** Register the app; the server assigns its slug (the app origin's host label). */
|
|
40368
|
+
async createWebApp(data) {
|
|
40369
|
+
return this.httpPost(`/developer/web-apps/${this.agentId}`, data, {});
|
|
40370
|
+
}
|
|
40371
|
+
/** A new, inactive version; it goes live with the agent version that pins it. */
|
|
40372
|
+
async pushWebAppVersion(webAppId, data) {
|
|
40373
|
+
return this.httpPost(`/developer/web-apps/${this.agentId}/${webAppId}/version`, data, {});
|
|
40374
|
+
}
|
|
40375
|
+
};
|
|
40376
|
+
|
|
40377
|
+
// src/primitives/web-app.handler.ts
|
|
40378
|
+
init_artifact_loader();
|
|
40379
|
+
|
|
40380
|
+
// src/utils/web-app-build.ts
|
|
40381
|
+
init_dist();
|
|
40382
|
+
import crypto5 from "crypto";
|
|
40383
|
+
import fs17 from "fs";
|
|
40384
|
+
import os from "os";
|
|
40385
|
+
import path23 from "path";
|
|
40386
|
+
import { createRequire as createRequire2 } from "module";
|
|
40387
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
40388
|
+
var WebAppBuildError = class extends Error {
|
|
40389
|
+
static {
|
|
40390
|
+
__name(this, "WebAppBuildError");
|
|
40391
|
+
}
|
|
40392
|
+
constructor(message) {
|
|
40393
|
+
super(message);
|
|
40394
|
+
this.name = "WebAppBuildError";
|
|
40395
|
+
}
|
|
40396
|
+
};
|
|
40397
|
+
var CONTENT_TYPES = {
|
|
40398
|
+
".js": "text/javascript",
|
|
40399
|
+
".mjs": "text/javascript",
|
|
40400
|
+
".css": "text/css",
|
|
40401
|
+
".html": "text/html; charset=utf-8",
|
|
40402
|
+
".json": "application/json",
|
|
40403
|
+
".map": "application/json",
|
|
40404
|
+
".svg": "image/svg+xml",
|
|
40405
|
+
".png": "image/png",
|
|
40406
|
+
".jpg": "image/jpeg",
|
|
40407
|
+
".jpeg": "image/jpeg",
|
|
40408
|
+
".gif": "image/gif",
|
|
40409
|
+
".webp": "image/webp",
|
|
40410
|
+
".avif": "image/avif",
|
|
40411
|
+
".ico": "image/x-icon",
|
|
40412
|
+
".woff": "font/woff",
|
|
40413
|
+
".woff2": "font/woff2",
|
|
40414
|
+
".ttf": "font/ttf",
|
|
40415
|
+
".otf": "font/otf",
|
|
40416
|
+
".wasm": "application/wasm",
|
|
40417
|
+
".txt": "text/plain; charset=utf-8",
|
|
40418
|
+
".mp4": "video/mp4",
|
|
40419
|
+
".webm": "video/webm",
|
|
40420
|
+
".mp3": "audio/mpeg"
|
|
40421
|
+
};
|
|
40422
|
+
function contentTypeFor(file) {
|
|
40423
|
+
return CONTENT_TYPES[path23.extname(file).toLowerCase()] ?? "application/octet-stream";
|
|
40424
|
+
}
|
|
40425
|
+
__name(contentTypeFor, "contentTypeFor");
|
|
40426
|
+
async function loadAppVite(pagesDir) {
|
|
40427
|
+
const requireFromApp = createRequire2(path23.join(pagesDir, "package.json"));
|
|
40428
|
+
let entry;
|
|
40429
|
+
let version;
|
|
40430
|
+
try {
|
|
40431
|
+
entry = requireFromApp.resolve("vite");
|
|
40432
|
+
version = requireFromApp("vite/package.json").version;
|
|
40433
|
+
} catch {
|
|
40434
|
+
throw new WebAppBuildError(`No Vite installation found for ${pagesDir}. Install the page dependencies first (npm install in that directory).`);
|
|
40435
|
+
}
|
|
40436
|
+
const mod = await import(pathToFileURL2(entry).href);
|
|
40437
|
+
const build2 = mod.build ?? mod.default?.build;
|
|
40438
|
+
if (typeof build2 !== "function") throw new WebAppBuildError(`The Vite at ${entry} exposes no build() function.`);
|
|
40439
|
+
const createServer = mod.createServer ?? mod.default?.createServer;
|
|
40440
|
+
return {
|
|
40441
|
+
build: build2,
|
|
40442
|
+
createServer: typeof createServer === "function" ? createServer : void 0,
|
|
40443
|
+
version
|
|
40444
|
+
};
|
|
40445
|
+
}
|
|
40446
|
+
__name(loadAppVite, "loadAppVite");
|
|
40447
|
+
function walk3(dir, base = dir) {
|
|
40448
|
+
const out = [];
|
|
40449
|
+
for (const entry of fs17.readdirSync(dir, {
|
|
40450
|
+
withFileTypes: true
|
|
40451
|
+
})) {
|
|
40452
|
+
const full = path23.join(dir, entry.name);
|
|
40453
|
+
if (entry.isDirectory()) out.push(...walk3(full, base));
|
|
40454
|
+
else if (entry.isFile()) out.push(path23.relative(base, full).split(path23.sep).join("/"));
|
|
40455
|
+
}
|
|
40456
|
+
return out.sort();
|
|
40457
|
+
}
|
|
40458
|
+
__name(walk3, "walk");
|
|
40459
|
+
function collectBuildOutput(outDir) {
|
|
40460
|
+
const files = walk3(outDir);
|
|
40461
|
+
if (!files.includes("index.html")) {
|
|
40462
|
+
throw new WebAppBuildError(`The page build produced no index.html in ${outDir}.`);
|
|
40463
|
+
}
|
|
40464
|
+
const entryHtml = fs17.readFileSync(path23.join(outDir, "index.html"), "utf8");
|
|
40465
|
+
if (entryHtml.length > WEB_APP_ENTRY_HTML_MAX_CHARS) {
|
|
40466
|
+
throw new WebAppBuildError(`index.html is ${entryHtml.length} characters; the limit is ${WEB_APP_ENTRY_HTML_MAX_CHARS}. Move inline content into assets.`);
|
|
40467
|
+
}
|
|
40468
|
+
const assets = [];
|
|
40469
|
+
const skipped = [];
|
|
40470
|
+
for (const rel of files) {
|
|
40471
|
+
if (rel === "index.html") continue;
|
|
40472
|
+
if (!rel.startsWith("assets/")) {
|
|
40473
|
+
skipped.push(rel);
|
|
40474
|
+
continue;
|
|
40475
|
+
}
|
|
40476
|
+
if (rel.length > WEB_APP_ASSET_PATH_MAX_CHARS || !WEB_APP_ASSET_PATH_PATTERN.test(rel)) {
|
|
40477
|
+
throw new WebAppBuildError(`${rel} is not a servable asset path (letters, digits, . _ - / only, at most ${WEB_APP_ASSET_PATH_MAX_CHARS} characters). Rename the source file.`);
|
|
40478
|
+
}
|
|
40479
|
+
const bytes = fs17.readFileSync(path23.join(outDir, rel));
|
|
40480
|
+
if (bytes.length > WEB_APP_MAX_ASSET_BYTES) {
|
|
40481
|
+
throw new WebAppBuildError(`${rel} is ${bytes.length} bytes; a page asset may be at most ${WEB_APP_MAX_ASSET_BYTES} bytes.`);
|
|
40482
|
+
}
|
|
40483
|
+
assets.push({
|
|
40484
|
+
path: rel,
|
|
40485
|
+
hash: crypto5.createHash("sha256").update(bytes).digest("hex"),
|
|
40486
|
+
size: bytes.length,
|
|
40487
|
+
contentType: contentTypeFor(rel),
|
|
40488
|
+
bytes
|
|
40489
|
+
});
|
|
40490
|
+
}
|
|
40491
|
+
if (assets.length > WEB_APP_MAX_ASSETS) {
|
|
40492
|
+
throw new WebAppBuildError(`The page build produced ${assets.length} assets; the limit is ${WEB_APP_MAX_ASSETS}.`);
|
|
40493
|
+
}
|
|
40494
|
+
return {
|
|
40495
|
+
entryHtml,
|
|
40496
|
+
assets,
|
|
40497
|
+
skipped
|
|
40498
|
+
};
|
|
40499
|
+
}
|
|
40500
|
+
__name(collectBuildOutput, "collectBuildOutput");
|
|
40501
|
+
async function buildWebAppPages(pagesDir, loadVite = loadAppVite) {
|
|
40502
|
+
if (!fs17.existsSync(path23.join(pagesDir, "index.html"))) {
|
|
40503
|
+
throw new WebAppBuildError(`${pagesDir} has no index.html: \`pages.root\` must name the Vite project directory.`);
|
|
40504
|
+
}
|
|
40505
|
+
const { build: build2, version } = await loadVite(pagesDir);
|
|
40506
|
+
const outDir = fs17.mkdtempSync(path23.join(os.tmpdir(), "lua-web-app-"));
|
|
40507
|
+
try {
|
|
40508
|
+
await build2({
|
|
40509
|
+
root: pagesDir,
|
|
40510
|
+
base: "/",
|
|
40511
|
+
logLevel: "warn",
|
|
40512
|
+
html: {
|
|
40513
|
+
cspNonce: WEB_APP_CSP_NONCE_PLACEHOLDER
|
|
40514
|
+
},
|
|
40515
|
+
build: {
|
|
40516
|
+
outDir,
|
|
40517
|
+
emptyOutDir: true,
|
|
40518
|
+
assetsDir: "assets",
|
|
40519
|
+
manifest: false
|
|
40520
|
+
}
|
|
40521
|
+
});
|
|
40522
|
+
return {
|
|
40523
|
+
...collectBuildOutput(outDir),
|
|
40524
|
+
viteVersion: version
|
|
40525
|
+
};
|
|
40526
|
+
} finally {
|
|
40527
|
+
fs17.rmSync(outDir, {
|
|
40528
|
+
recursive: true,
|
|
40529
|
+
force: true
|
|
40530
|
+
});
|
|
40531
|
+
}
|
|
40532
|
+
}
|
|
40533
|
+
__name(buildWebAppPages, "buildWebAppPages");
|
|
40534
|
+
|
|
40535
|
+
// src/primitives/web-app.handler.ts
|
|
40536
|
+
init_package_root();
|
|
40537
|
+
init_cli();
|
|
40538
|
+
init_write_info();
|
|
40539
|
+
init_base_handler();
|
|
40540
|
+
var WEB_APP_GOES_LIVE_WITH_AGENT_VERSION = "A web app version goes live with the agent version that pins it: create an agent version and promote it.";
|
|
40541
|
+
var WebAppHandler = class extends BaseVersionedHandler {
|
|
40542
|
+
static {
|
|
40543
|
+
__name(this, "WebAppHandler");
|
|
40544
|
+
}
|
|
40545
|
+
kind = PrimitiveKind.WEB_APP;
|
|
40546
|
+
displayName = "webapp";
|
|
40547
|
+
displayNamePlural = "web apps";
|
|
40548
|
+
/** No CLI delete in the MVP; unused because server-only apps are never stubbed (see shouldConsiderForOrphan). */
|
|
40549
|
+
deleteCommand = "";
|
|
40550
|
+
yamlConfig = {
|
|
40551
|
+
yamlKey: "webApps",
|
|
40552
|
+
idField: "webAppId"
|
|
40553
|
+
};
|
|
40554
|
+
getApi(apiKey, agentId) {
|
|
40555
|
+
return new WebAppApi(BASE_URLS.API, apiKey, agentId);
|
|
40556
|
+
}
|
|
40557
|
+
async fetchFromServer(api) {
|
|
40558
|
+
const response = await api.getWebApps();
|
|
40559
|
+
if (!response.success || !response.data?.webApps) return null;
|
|
40560
|
+
return response.data.webApps;
|
|
40561
|
+
}
|
|
40562
|
+
async createOnServer(api, primitive) {
|
|
40563
|
+
const response = await api.createWebApp({
|
|
40564
|
+
name: primitive.name,
|
|
40565
|
+
description: primitive.description || void 0
|
|
40566
|
+
});
|
|
40567
|
+
if (!response.success || !response.data?.id) return null;
|
|
40568
|
+
return response.data.id;
|
|
40569
|
+
}
|
|
40570
|
+
getActiveVersion(serverItem) {
|
|
40571
|
+
if (serverItem.activeVersionId) {
|
|
40572
|
+
return serverItem.versions?.find((v) => v.id === serverItem.activeVersionId)?.version ?? null;
|
|
40573
|
+
}
|
|
40574
|
+
return serverItem.versions?.find((v) => v.active === true)?.version ?? null;
|
|
40575
|
+
}
|
|
40576
|
+
/** The CLI cannot delete a web app (MVP), so an app only on the server is left alone, not stubbed. */
|
|
40577
|
+
shouldConsiderForOrphan(_item) {
|
|
40578
|
+
return false;
|
|
40579
|
+
}
|
|
40580
|
+
/**
|
|
40581
|
+
* Silent for an agent that has no web apps on either side, so every other
|
|
40582
|
+
* push and compile prints exactly what it printed before this kind existed.
|
|
40583
|
+
*/
|
|
40584
|
+
async applySyncToYaml(serverData, config, manifest, apiCredentials) {
|
|
40585
|
+
const local = this.getFromYaml(config).length > 0;
|
|
40586
|
+
const compiled = !!manifest?.primitives.some((p) => p.kind === this.kind);
|
|
40587
|
+
const remote = (serverData.serverItems?.length ?? 0) > 0;
|
|
40588
|
+
if (!local && !compiled && !remote) return {
|
|
40589
|
+
messages: [],
|
|
40590
|
+
yamlUpdated: false,
|
|
40591
|
+
orphanedCount: 0
|
|
40592
|
+
};
|
|
40593
|
+
return super.applySyncToYaml(serverData, config, manifest, apiCredentials);
|
|
40594
|
+
}
|
|
40595
|
+
buildPushData(primitive, compressedCode, codeS3Hash) {
|
|
40596
|
+
const app = primitive;
|
|
40597
|
+
return {
|
|
40598
|
+
name: app.name,
|
|
40599
|
+
...app.description ? {
|
|
40600
|
+
description: app.description
|
|
40601
|
+
} : {},
|
|
40602
|
+
...codeS3Hash ? {
|
|
40603
|
+
codeS3Hash
|
|
40604
|
+
} : {
|
|
40605
|
+
code: compressedCode
|
|
40606
|
+
},
|
|
40607
|
+
routes: app.routes,
|
|
40608
|
+
hasFetch: app.hasFetch,
|
|
40609
|
+
nav: app.nav,
|
|
40610
|
+
...app.csp ? {
|
|
40611
|
+
csp: app.csp
|
|
40612
|
+
} : {},
|
|
40613
|
+
...app.branding ? {
|
|
40614
|
+
branding: app.branding
|
|
40615
|
+
} : {},
|
|
40616
|
+
compiler: {
|
|
40617
|
+
luaCli: getCliVersion()
|
|
40618
|
+
}
|
|
40619
|
+
};
|
|
40620
|
+
}
|
|
40621
|
+
/**
|
|
40622
|
+
* The page build: runs the app's Vite, adds every asset to the blob upload
|
|
40623
|
+
* (`bundleAccumulator`, keyed by the sha256 of the raw bytes) and the entry
|
|
40624
|
+
* HTML plus the asset manifest to the version.
|
|
40625
|
+
*/
|
|
40626
|
+
async completePushData(pushData, manifest, name, bundleAccumulator) {
|
|
40627
|
+
const app = findPrimitive(manifest, name, this.kind);
|
|
40628
|
+
if (!app) throw new Error(`Web app "${name}" not found in compiled output.`);
|
|
40629
|
+
const pagesDir = path24.resolve(path24.dirname(app.sourcePath), app.pagesRoot);
|
|
40630
|
+
writeProgress(`\u{1F9F1} Building the pages of ${name} (${path24.relative(process.cwd(), pagesDir) || "."})...`);
|
|
40631
|
+
const pages = await buildWebAppPages(pagesDir);
|
|
40632
|
+
for (const asset of pages.assets) bundleAccumulator.set(asset.hash, asset.bytes);
|
|
40633
|
+
const bytes = pages.assets.reduce((n2, a) => n2 + a.size, 0);
|
|
40634
|
+
writeSuccess(`\u2705 Pages built: ${pages.assets.length} asset(s), ${Math.round(bytes / 1024)} KiB (Vite ${pages.viteVersion})`);
|
|
40635
|
+
if (pages.skipped.length > 0) {
|
|
40636
|
+
writeInfo(`\u26A0\uFE0F Not served (outside assets/): ${pages.skipped.slice(0, 10).join(", ")}${pages.skipped.length > 10 ? ", \u2026" : ""}. Import files from your source so Vite emits them under assets/.`);
|
|
40637
|
+
}
|
|
40638
|
+
const compiler = pushData.compiler ?? {};
|
|
40639
|
+
return {
|
|
40640
|
+
...pushData,
|
|
40641
|
+
entryHtml: pages.entryHtml,
|
|
40642
|
+
assets: pages.assets.map(({ bytes: _bytes, ...entry }) => entry),
|
|
40643
|
+
compiler: {
|
|
40644
|
+
...compiler,
|
|
40645
|
+
vite: pages.viteVersion
|
|
40646
|
+
}
|
|
40647
|
+
};
|
|
40648
|
+
}
|
|
40649
|
+
async pushToServer(apiKey, agentId, entityId, pushData) {
|
|
40650
|
+
const api = this.getApi(apiKey, agentId);
|
|
40651
|
+
const response = await api.pushWebAppVersion(entityId, pushData);
|
|
40652
|
+
return {
|
|
40653
|
+
success: response.success,
|
|
40654
|
+
error: response.error?.message
|
|
40655
|
+
};
|
|
40656
|
+
}
|
|
40657
|
+
async publishVersion(_apiKey, _agentId, _entityId, _version) {
|
|
40658
|
+
return {
|
|
40659
|
+
success: false,
|
|
40660
|
+
error: WEB_APP_GOES_LIVE_WITH_AGENT_VERSION
|
|
40661
|
+
};
|
|
40662
|
+
}
|
|
40663
|
+
};
|
|
40664
|
+
var webAppHandler = new WebAppHandler();
|
|
40665
|
+
|
|
40067
40666
|
// src/primitives/index.ts
|
|
40068
40667
|
init_skill_handler();
|
|
40069
40668
|
init_mcp_server_handler();
|
|
@@ -40081,7 +40680,9 @@ var primitiveHandlers = {
|
|
|
40081
40680
|
[PrimitiveKind.DEVICE_TRIGGER]: deviceTriggerHandler,
|
|
40082
40681
|
[PrimitiveKind.VOICE]: voiceHandler,
|
|
40083
40682
|
// WB-09 (WF-543): dark — no `workflows:` rows in lua.skill.yaml ⇒ never selected.
|
|
40084
|
-
[PrimitiveKind.WORKFLOW]: workflowHandler
|
|
40683
|
+
[PrimitiveKind.WORKFLOW]: workflowHandler,
|
|
40684
|
+
// Lua Apps: inert (and silent, see WebAppHandler.applySyncToYaml) for an agent without `webApps`.
|
|
40685
|
+
[PrimitiveKind.WEB_APP]: webAppHandler
|
|
40085
40686
|
};
|
|
40086
40687
|
var versionedHandlers = Object.values(primitiveHandlers).filter((h) => isVersionedHandler(h));
|
|
40087
40688
|
var syncableHandlers = Object.values(primitiveHandlers);
|
|
@@ -40122,7 +40723,7 @@ async function compileCommand(options) {
|
|
|
40122
40723
|
}
|
|
40123
40724
|
writeProgress("\u{1F528} Compiling...");
|
|
40124
40725
|
const rootDir = process.cwd();
|
|
40125
|
-
const outDir =
|
|
40726
|
+
const outDir = path25.join(rootDir, "dist-v2");
|
|
40126
40727
|
const result = await compile2({
|
|
40127
40728
|
rootDir,
|
|
40128
40729
|
outDir,
|
|
@@ -40293,6 +40894,415 @@ __name(printToolOutput, "printToolOutput");
|
|
|
40293
40894
|
// src/commands/test.ts
|
|
40294
40895
|
init_cli();
|
|
40295
40896
|
init_command_utils();
|
|
40897
|
+
|
|
40898
|
+
// src/utils/web-app-route.ts
|
|
40899
|
+
init_dist();
|
|
40900
|
+
var WebRouteSpecError = class extends Error {
|
|
40901
|
+
static {
|
|
40902
|
+
__name(this, "WebRouteSpecError");
|
|
40903
|
+
}
|
|
40904
|
+
constructor(message) {
|
|
40905
|
+
super(message);
|
|
40906
|
+
this.name = "WebRouteSpecError";
|
|
40907
|
+
}
|
|
40908
|
+
};
|
|
40909
|
+
function parseRouteSpec(spec) {
|
|
40910
|
+
const match = /^\s*([A-Za-z]+)\s+(\/\S*)\s*$/.exec(spec);
|
|
40911
|
+
const method = match?.[1].toUpperCase();
|
|
40912
|
+
if (!match || !WEB_ROUTE_METHODS.includes(method)) {
|
|
40913
|
+
throw new WebRouteSpecError(`--route must look like 'GET /path?query' (${WEB_ROUTE_METHODS.join(", ")}); got ${JSON.stringify(spec)}`);
|
|
40914
|
+
}
|
|
40915
|
+
const url = new URL(match[2], "http://local");
|
|
40916
|
+
const query = {};
|
|
40917
|
+
for (const [key, value3] of url.searchParams) {
|
|
40918
|
+
const existing = query[key];
|
|
40919
|
+
if (existing === void 0) query[key] = value3;
|
|
40920
|
+
else if (Array.isArray(existing)) existing.push(value3);
|
|
40921
|
+
else query[key] = [
|
|
40922
|
+
existing,
|
|
40923
|
+
value3
|
|
40924
|
+
];
|
|
40925
|
+
}
|
|
40926
|
+
return {
|
|
40927
|
+
method,
|
|
40928
|
+
path: url.pathname,
|
|
40929
|
+
query
|
|
40930
|
+
};
|
|
40931
|
+
}
|
|
40932
|
+
__name(parseRouteSpec, "parseRouteSpec");
|
|
40933
|
+
var segmentsOf = /* @__PURE__ */ __name((p) => p.split("/").filter(Boolean), "segmentsOf");
|
|
40934
|
+
function matchManifestRoute(routes, method, path30) {
|
|
40935
|
+
const parts = segmentsOf(path30);
|
|
40936
|
+
const candidates = routes.map((r, order) => ({
|
|
40937
|
+
r,
|
|
40938
|
+
order,
|
|
40939
|
+
segs: segmentsOf(r.path)
|
|
40940
|
+
})).filter(({ r, segs }) => r.method === method && segs.length === parts.length).sort((a, b) => b.segs.filter((s) => !s.startsWith(":")).length - a.segs.filter((s) => !s.startsWith(":")).length || a.order - b.order);
|
|
40941
|
+
for (const { r, segs } of candidates) {
|
|
40942
|
+
const params = {};
|
|
40943
|
+
let ok = true;
|
|
40944
|
+
for (let i = 0; i < segs.length && ok; i++) {
|
|
40945
|
+
if (segs[i].startsWith(":")) {
|
|
40946
|
+
try {
|
|
40947
|
+
params[segs[i].slice(1)] = decodeURIComponent(parts[i]);
|
|
40948
|
+
} catch {
|
|
40949
|
+
ok = false;
|
|
40950
|
+
}
|
|
40951
|
+
} else if (segs[i] !== parts[i]) {
|
|
40952
|
+
ok = false;
|
|
40953
|
+
}
|
|
40954
|
+
}
|
|
40955
|
+
if (ok) return {
|
|
40956
|
+
key: r.key,
|
|
40957
|
+
params
|
|
40958
|
+
};
|
|
40959
|
+
}
|
|
40960
|
+
return null;
|
|
40961
|
+
}
|
|
40962
|
+
__name(matchManifestRoute, "matchManifestRoute");
|
|
40963
|
+
function buildWebRouteInput(opts) {
|
|
40964
|
+
const headers = {};
|
|
40965
|
+
for (const [name, value3] of Object.entries(opts.headers ?? {})) {
|
|
40966
|
+
if (typeof value3 === "string" && isForwardableWebRouteRequestHeader(name)) headers[name.toLowerCase()] = value3;
|
|
40967
|
+
}
|
|
40968
|
+
let body;
|
|
40969
|
+
if (opts.body !== void 0 && opts.spec.method !== "GET") {
|
|
40970
|
+
body = typeof opts.body === "string" ? {
|
|
40971
|
+
kind: "text",
|
|
40972
|
+
value: opts.body
|
|
40973
|
+
} : {
|
|
40974
|
+
kind: "json",
|
|
40975
|
+
value: opts.body
|
|
40976
|
+
};
|
|
40977
|
+
headers["content-type"] ??= body.kind === "json" ? "application/json" : "text/plain";
|
|
40978
|
+
}
|
|
40979
|
+
return {
|
|
40980
|
+
v: WEB_ROUTE_PROTOCOL_VERSION,
|
|
40981
|
+
request: {
|
|
40982
|
+
method: opts.spec.method,
|
|
40983
|
+
path: opts.spec.path,
|
|
40984
|
+
...opts.route ? {
|
|
40985
|
+
route: opts.route.key,
|
|
40986
|
+
params: opts.route.params
|
|
40987
|
+
} : {
|
|
40988
|
+
params: {}
|
|
40989
|
+
},
|
|
40990
|
+
query: opts.spec.query,
|
|
40991
|
+
headers,
|
|
40992
|
+
...body ? {
|
|
40993
|
+
body
|
|
40994
|
+
} : {}
|
|
40995
|
+
},
|
|
40996
|
+
auth: opts.auth,
|
|
40997
|
+
app: {
|
|
40998
|
+
id: opts.app.id,
|
|
40999
|
+
name: opts.app.name,
|
|
41000
|
+
version: opts.app.version,
|
|
41001
|
+
deployment: 0,
|
|
41002
|
+
origin: "http://localhost",
|
|
41003
|
+
preview: false
|
|
41004
|
+
}
|
|
41005
|
+
};
|
|
41006
|
+
}
|
|
41007
|
+
__name(buildWebRouteInput, "buildWebRouteInput");
|
|
41008
|
+
|
|
41009
|
+
// src/utils/web-app-dev.ts
|
|
41010
|
+
init_dist();
|
|
41011
|
+
init_credential_operational_context();
|
|
41012
|
+
init_cli_error();
|
|
41013
|
+
async function developerAuth(apiKey, agentId, config) {
|
|
41014
|
+
const credential = await resolveCredentialOperationalContext(apiKey);
|
|
41015
|
+
if (!credential.userId) {
|
|
41016
|
+
throw CliError.usage("A web app route runs as a signed-in person; this credential has no user. Run `lua auth configure` and sign in.");
|
|
41017
|
+
}
|
|
41018
|
+
const orgId = config?.agent?.orgId || credential.authorization.orgs[0]?.orgId;
|
|
41019
|
+
if (!orgId) {
|
|
41020
|
+
throw CliError.usage("No organization for this project: lua.skill.yaml has no agent.orgId and the credential belongs to no organization. Run `lua init` in the project.");
|
|
41021
|
+
}
|
|
41022
|
+
return {
|
|
41023
|
+
userId: credential.userId,
|
|
41024
|
+
orgId,
|
|
41025
|
+
agentId,
|
|
41026
|
+
subjectType: "user",
|
|
41027
|
+
credentialType: "firstPartySession",
|
|
41028
|
+
roles: [],
|
|
41029
|
+
scopes: [],
|
|
41030
|
+
...credential.identity?.fullName ? {
|
|
41031
|
+
name: credential.identity.fullName
|
|
41032
|
+
} : {},
|
|
41033
|
+
...credential.identity?.email ? {
|
|
41034
|
+
email: credential.identity.email
|
|
41035
|
+
} : {}
|
|
41036
|
+
};
|
|
41037
|
+
}
|
|
41038
|
+
__name(developerAuth, "developerAuth");
|
|
41039
|
+
function devBootstrap(app, origin) {
|
|
41040
|
+
return {
|
|
41041
|
+
v: 1,
|
|
41042
|
+
app: {
|
|
41043
|
+
id: "local",
|
|
41044
|
+
name: app.name,
|
|
41045
|
+
version: "0.0.0-dev",
|
|
41046
|
+
deployment: 0,
|
|
41047
|
+
origin
|
|
41048
|
+
},
|
|
41049
|
+
apiBase: "/_lua/api",
|
|
41050
|
+
manifest: "/_lua/manifest",
|
|
41051
|
+
auth: {
|
|
41052
|
+
origin: "",
|
|
41053
|
+
exchangePath: "",
|
|
41054
|
+
audience: "web-app"
|
|
41055
|
+
},
|
|
41056
|
+
embedded: false,
|
|
41057
|
+
hostOrigins: [],
|
|
41058
|
+
theme: "dark",
|
|
41059
|
+
density: "compact",
|
|
41060
|
+
preview: false,
|
|
41061
|
+
dev: true
|
|
41062
|
+
};
|
|
41063
|
+
}
|
|
41064
|
+
__name(devBootstrap, "devBootstrap");
|
|
41065
|
+
function devBootstrapScript(app, origin) {
|
|
41066
|
+
const json2 = JSON.stringify(devBootstrap(app, origin)).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
41067
|
+
return `<script>window.__LUA__=${json2};</script>`;
|
|
41068
|
+
}
|
|
41069
|
+
__name(devBootstrapScript, "devBootstrapScript");
|
|
41070
|
+
var json = /* @__PURE__ */ __name((status, value3) => ({
|
|
41071
|
+
status,
|
|
41072
|
+
headers: {
|
|
41073
|
+
"content-type": "application/json",
|
|
41074
|
+
"cache-control": "no-store"
|
|
41075
|
+
},
|
|
41076
|
+
body: Buffer.from(JSON.stringify(value3), "utf8")
|
|
41077
|
+
}), "json");
|
|
41078
|
+
function shapeBody(raw, contentType) {
|
|
41079
|
+
if (!raw || raw.length === 0) return void 0;
|
|
41080
|
+
const ct = (contentType || "").toLowerCase();
|
|
41081
|
+
if (ct.includes("json")) return {
|
|
41082
|
+
kind: "json",
|
|
41083
|
+
value: JSON.parse(raw.toString("utf8"))
|
|
41084
|
+
};
|
|
41085
|
+
if (ct.startsWith("text/") || ct.includes("xml") || ct.includes("x-www-form-urlencoded")) {
|
|
41086
|
+
return {
|
|
41087
|
+
kind: "text",
|
|
41088
|
+
value: raw.toString("utf8")
|
|
41089
|
+
};
|
|
41090
|
+
}
|
|
41091
|
+
return {
|
|
41092
|
+
kind: "base64",
|
|
41093
|
+
value: raw.toString("base64")
|
|
41094
|
+
};
|
|
41095
|
+
}
|
|
41096
|
+
__name(shapeBody, "shapeBody");
|
|
41097
|
+
function materialize(result) {
|
|
41098
|
+
const headers = {
|
|
41099
|
+
"cache-control": "no-store",
|
|
41100
|
+
...result.headers
|
|
41101
|
+
};
|
|
41102
|
+
const body = result.body;
|
|
41103
|
+
if (!body) return {
|
|
41104
|
+
status: result.status,
|
|
41105
|
+
headers
|
|
41106
|
+
};
|
|
41107
|
+
if (body.kind === "json") {
|
|
41108
|
+
headers["content-type"] ??= "application/json";
|
|
41109
|
+
return {
|
|
41110
|
+
status: result.status,
|
|
41111
|
+
headers,
|
|
41112
|
+
body: Buffer.from(JSON.stringify(body.value ?? null), "utf8")
|
|
41113
|
+
};
|
|
41114
|
+
}
|
|
41115
|
+
if (body.kind === "text") {
|
|
41116
|
+
headers["content-type"] ??= "text/plain; charset=utf-8";
|
|
41117
|
+
return {
|
|
41118
|
+
status: result.status,
|
|
41119
|
+
headers,
|
|
41120
|
+
body: Buffer.from(body.value ?? "", "utf8")
|
|
41121
|
+
};
|
|
41122
|
+
}
|
|
41123
|
+
return {
|
|
41124
|
+
status: result.status,
|
|
41125
|
+
headers,
|
|
41126
|
+
body: Buffer.from(body.value ?? "", "base64")
|
|
41127
|
+
};
|
|
41128
|
+
}
|
|
41129
|
+
__name(materialize, "materialize");
|
|
41130
|
+
async function handleDevRequest(req, ctx) {
|
|
41131
|
+
const url = new URL(req.url, "http://local");
|
|
41132
|
+
if (url.pathname === "/_lua/manifest") {
|
|
41133
|
+
return json(200, {
|
|
41134
|
+
v: 1,
|
|
41135
|
+
app: {
|
|
41136
|
+
id: "local",
|
|
41137
|
+
name: ctx.app.name,
|
|
41138
|
+
description: ctx.app.description,
|
|
41139
|
+
version: "0.0.0-dev",
|
|
41140
|
+
deployment: 0
|
|
41141
|
+
},
|
|
41142
|
+
nav: ctx.app.nav,
|
|
41143
|
+
user: {
|
|
41144
|
+
id: ctx.auth.userId,
|
|
41145
|
+
name: ctx.auth.name,
|
|
41146
|
+
email: ctx.auth.email
|
|
41147
|
+
},
|
|
41148
|
+
org: {
|
|
41149
|
+
id: ctx.auth.orgId
|
|
41150
|
+
},
|
|
41151
|
+
agent: {
|
|
41152
|
+
id: ctx.auth.agentId
|
|
41153
|
+
},
|
|
41154
|
+
auth: {
|
|
41155
|
+
roles: ctx.auth.roles,
|
|
41156
|
+
scopes: ctx.auth.scopes
|
|
41157
|
+
}
|
|
41158
|
+
});
|
|
41159
|
+
}
|
|
41160
|
+
if (url.pathname !== "/_lua/api" && !url.pathname.startsWith("/_lua/api/")) return null;
|
|
41161
|
+
const method = req.method.toUpperCase();
|
|
41162
|
+
if (!WEB_ROUTE_METHODS.includes(method)) {
|
|
41163
|
+
return json(405, {
|
|
41164
|
+
code: "METHOD_NOT_ALLOWED",
|
|
41165
|
+
message: `Method ${method} is not supported`
|
|
41166
|
+
});
|
|
41167
|
+
}
|
|
41168
|
+
if (req.bodyTooLarge || req.body && req.body.length > WEB_ROUTE_MAX_REQUEST_BODY_BYTES) {
|
|
41169
|
+
return json(413, {
|
|
41170
|
+
code: "VALIDATION",
|
|
41171
|
+
message: `Request body exceeds ${WEB_ROUTE_MAX_REQUEST_BODY_BYTES} bytes`
|
|
41172
|
+
});
|
|
41173
|
+
}
|
|
41174
|
+
const routePath = url.pathname.slice("/_lua/api".length) || "/";
|
|
41175
|
+
const spec = parseRouteSpec(`${method} ${routePath}${url.search}`);
|
|
41176
|
+
const route = matchManifestRoute(ctx.app.routes, spec.method, spec.path);
|
|
41177
|
+
if (!route && !ctx.app.hasFetch) {
|
|
41178
|
+
return json(404, {
|
|
41179
|
+
code: "NOT_FOUND",
|
|
41180
|
+
message: `No route for ${spec.method} ${spec.path}`
|
|
41181
|
+
});
|
|
41182
|
+
}
|
|
41183
|
+
let body;
|
|
41184
|
+
try {
|
|
41185
|
+
const ct = req.headers["content-type"];
|
|
41186
|
+
body = shapeBody(req.body, Array.isArray(ct) ? ct[0] : ct);
|
|
41187
|
+
} catch {
|
|
41188
|
+
return json(400, {
|
|
41189
|
+
code: "VALIDATION",
|
|
41190
|
+
message: "Request body is not valid JSON"
|
|
41191
|
+
});
|
|
41192
|
+
}
|
|
41193
|
+
const headers = {};
|
|
41194
|
+
for (const [name, value3] of Object.entries(req.headers)) if (typeof value3 === "string") headers[name] = value3;
|
|
41195
|
+
const input = buildWebRouteInput({
|
|
41196
|
+
spec,
|
|
41197
|
+
route,
|
|
41198
|
+
headers,
|
|
41199
|
+
auth: ctx.auth,
|
|
41200
|
+
app: {
|
|
41201
|
+
id: "local",
|
|
41202
|
+
name: ctx.app.name,
|
|
41203
|
+
version: "0.0.0-dev"
|
|
41204
|
+
}
|
|
41205
|
+
});
|
|
41206
|
+
if (body && spec.method !== "GET") input.request.body = body;
|
|
41207
|
+
try {
|
|
41208
|
+
const execute = ctx.execute ?? executeWebRoute;
|
|
41209
|
+
return materialize(await execute({
|
|
41210
|
+
appCode: ctx.appCode(),
|
|
41211
|
+
input,
|
|
41212
|
+
apiKey: ctx.apiKey,
|
|
41213
|
+
agentId: ctx.agentId
|
|
41214
|
+
}));
|
|
41215
|
+
} catch (error) {
|
|
41216
|
+
console.error(error);
|
|
41217
|
+
return json(500, {
|
|
41218
|
+
code: "HANDLER_ERROR",
|
|
41219
|
+
message: error?.message || "The route handler failed"
|
|
41220
|
+
});
|
|
41221
|
+
}
|
|
41222
|
+
}
|
|
41223
|
+
__name(handleDevRequest, "handleDevRequest");
|
|
41224
|
+
function readBody(req) {
|
|
41225
|
+
return new Promise((resolve7, reject) => {
|
|
41226
|
+
const chunks = [];
|
|
41227
|
+
let total = 0;
|
|
41228
|
+
let settled = false;
|
|
41229
|
+
const onData = /* @__PURE__ */ __name((chunk) => {
|
|
41230
|
+
total += chunk.length;
|
|
41231
|
+
if (total > WEB_ROUTE_MAX_REQUEST_BODY_BYTES) {
|
|
41232
|
+
settled = true;
|
|
41233
|
+
req.off("data", onData);
|
|
41234
|
+
req.pause();
|
|
41235
|
+
resolve7({
|
|
41236
|
+
body: Buffer.alloc(0),
|
|
41237
|
+
tooLarge: true
|
|
41238
|
+
});
|
|
41239
|
+
return;
|
|
41240
|
+
}
|
|
41241
|
+
chunks.push(chunk);
|
|
41242
|
+
}, "onData");
|
|
41243
|
+
req.on("data", onData);
|
|
41244
|
+
req.on("end", () => settled || resolve7({
|
|
41245
|
+
body: Buffer.concat(chunks),
|
|
41246
|
+
tooLarge: false
|
|
41247
|
+
}));
|
|
41248
|
+
req.on("error", (error) => settled || reject(error));
|
|
41249
|
+
});
|
|
41250
|
+
}
|
|
41251
|
+
__name(readBody, "readBody");
|
|
41252
|
+
function isRouteSource(file, appDir, pagesDir) {
|
|
41253
|
+
const inApp = file.startsWith(appDir + "/") || file.startsWith(appDir + "\\");
|
|
41254
|
+
const inPages = file === pagesDir || file.startsWith(pagesDir + "/") || file.startsWith(pagesDir + "\\");
|
|
41255
|
+
return inApp && !inPages && /\.[cm]?[jt]sx?$/.test(file);
|
|
41256
|
+
}
|
|
41257
|
+
__name(isRouteSource, "isRouteSource");
|
|
41258
|
+
function luaAppsDevPlugin(opts) {
|
|
41259
|
+
return {
|
|
41260
|
+
name: "lua-apps-dev",
|
|
41261
|
+
configureServer(dev) {
|
|
41262
|
+
dev.middlewares.use(async (req, res, next) => {
|
|
41263
|
+
if (!String(req.url ?? "").startsWith("/_lua/")) return next();
|
|
41264
|
+
try {
|
|
41265
|
+
const read = await readBody(req);
|
|
41266
|
+
const answer = await handleDevRequest({
|
|
41267
|
+
method: req.method ?? "GET",
|
|
41268
|
+
url: req.url ?? "/",
|
|
41269
|
+
headers: req.headers,
|
|
41270
|
+
body: read.body,
|
|
41271
|
+
bodyTooLarge: read.tooLarge
|
|
41272
|
+
}, opts.context());
|
|
41273
|
+
if (!answer) return next();
|
|
41274
|
+
res.statusCode = answer.status;
|
|
41275
|
+
for (const [k, v] of Object.entries(answer.headers)) res.setHeader(k, v);
|
|
41276
|
+
res.end(answer.body);
|
|
41277
|
+
if (read.tooLarge) req.resume();
|
|
41278
|
+
opts.log?.(`${req.method} ${req.url} \u2192 ${answer.status}`, answer.status);
|
|
41279
|
+
} catch (error) {
|
|
41280
|
+
res.statusCode = 500;
|
|
41281
|
+
res.setHeader("content-type", "application/json");
|
|
41282
|
+
res.end(JSON.stringify({
|
|
41283
|
+
code: "PLATFORM_ERROR",
|
|
41284
|
+
message: String(error?.message ?? error)
|
|
41285
|
+
}));
|
|
41286
|
+
}
|
|
41287
|
+
});
|
|
41288
|
+
if (opts.onRouteChange) {
|
|
41289
|
+
dev.watcher.add(opts.appDir);
|
|
41290
|
+
dev.watcher.on("change", (file) => {
|
|
41291
|
+
if (isRouteSource(file, opts.appDir, opts.pagesDir)) void opts.onRouteChange(file);
|
|
41292
|
+
});
|
|
41293
|
+
}
|
|
41294
|
+
},
|
|
41295
|
+
transformIndexHtml(html) {
|
|
41296
|
+
const script = devBootstrapScript(opts.context().app, opts.origin() || "http://localhost");
|
|
41297
|
+
return html.includes("</head>") ? html.replace("</head>", `${script}
|
|
41298
|
+
</head>`) : `${script}
|
|
41299
|
+
${html}`;
|
|
41300
|
+
}
|
|
41301
|
+
};
|
|
41302
|
+
}
|
|
41303
|
+
__name(luaAppsDevPlugin, "luaAppsDevPlugin");
|
|
41304
|
+
|
|
41305
|
+
// src/commands/test.ts
|
|
40296
41306
|
init_files();
|
|
40297
41307
|
init_artifact_loader();
|
|
40298
41308
|
init_types();
|
|
@@ -40397,9 +41407,13 @@ var ALIAS_MAP = {
|
|
|
40397
41407
|
"device-trigger",
|
|
40398
41408
|
"voice",
|
|
40399
41409
|
"workflow",
|
|
41410
|
+
"webapp",
|
|
40400
41411
|
"backup"
|
|
40401
41412
|
],
|
|
40402
41413
|
aliases: lowerKeys({
|
|
41414
|
+
webapps: "webapp",
|
|
41415
|
+
"web-app": "webapp",
|
|
41416
|
+
"web-apps": "webapp",
|
|
40403
41417
|
skills: "skill",
|
|
40404
41418
|
sk: "skill",
|
|
40405
41419
|
voices: "voice",
|
|
@@ -40526,9 +41540,13 @@ var ALIAS_MAP = {
|
|
|
40526
41540
|
"job",
|
|
40527
41541
|
"preprocessor",
|
|
40528
41542
|
"postprocessor",
|
|
40529
|
-
"workflow"
|
|
41543
|
+
"workflow",
|
|
41544
|
+
"webapp"
|
|
40530
41545
|
],
|
|
40531
41546
|
aliases: lowerKeys({
|
|
41547
|
+
webapps: "webapp",
|
|
41548
|
+
"web-app": "webapp",
|
|
41549
|
+
"web-apps": "webapp",
|
|
40532
41550
|
workflows: "workflow",
|
|
40533
41551
|
wf: "workflow",
|
|
40534
41552
|
skills: "skill",
|
|
@@ -41236,8 +42254,8 @@ function validateOrSuggest(group, input, opts) {
|
|
|
41236
42254
|
__name(validateOrSuggest, "validateOrSuggest");
|
|
41237
42255
|
|
|
41238
42256
|
// src/commands/workflow-local-run.ts
|
|
41239
|
-
import
|
|
41240
|
-
import
|
|
42257
|
+
import fs18 from "fs";
|
|
42258
|
+
import path26 from "path";
|
|
41241
42259
|
init_cli();
|
|
41242
42260
|
|
|
41243
42261
|
// src/utils/stdout-redirect.ts
|
|
@@ -41455,13 +42473,13 @@ __name(runScriptWorkflowLocally, "runScriptWorkflowLocally");
|
|
|
41455
42473
|
|
|
41456
42474
|
// src/utils/workflow-script-replay.ts
|
|
41457
42475
|
init_dist4();
|
|
41458
|
-
import { createRequire as
|
|
42476
|
+
import { createRequire as createRequire3 } from "module";
|
|
41459
42477
|
import vm5 from "vm";
|
|
41460
42478
|
import { createHash as createHash7, randomUUID as randomUUID4 } from "crypto";
|
|
41461
42479
|
|
|
41462
42480
|
// ../sandbox-runtime/dist/workflow-script-wrapper.mjs
|
|
41463
|
-
var
|
|
41464
|
-
var
|
|
42481
|
+
var __defProp10 = Object.defineProperty;
|
|
42482
|
+
var __name10 = /* @__PURE__ */ __name((target, value3) => __defProp10(target, "name", { value: value3, configurable: true }), "__name");
|
|
41465
42483
|
var WORKFLOW_SCRIPT_RUNTIME_KEY = "__luaWorkflowScriptRuntime";
|
|
41466
42484
|
var WORKFLOW_SCRIPT_PROTOCOL_VERSION = 1;
|
|
41467
42485
|
var WORKFLOW_SCRIPT_DEFAULT_CAPS = {
|
|
@@ -41796,18 +42814,18 @@ function computeWorkflowProtocolShipWindow(input) {
|
|
|
41796
42814
|
};
|
|
41797
42815
|
}
|
|
41798
42816
|
__name(computeWorkflowProtocolShipWindow, "computeWorkflowProtocolShipWindow");
|
|
41799
|
-
|
|
42817
|
+
__name10(computeWorkflowProtocolShipWindow, "computeWorkflowProtocolShipWindow");
|
|
41800
42818
|
var WORKFLOW_SCRIPT_EFFORT_PROTOCOL_VERSION = 2;
|
|
41801
42819
|
function scriptEffortForwardable(journalProtocolVersion) {
|
|
41802
42820
|
return typeof journalProtocolVersion === "number" && journalProtocolVersion >= WORKFLOW_SCRIPT_EFFORT_PROTOCOL_VERSION;
|
|
41803
42821
|
}
|
|
41804
42822
|
__name(scriptEffortForwardable, "scriptEffortForwardable");
|
|
41805
|
-
|
|
42823
|
+
__name10(scriptEffortForwardable, "scriptEffortForwardable");
|
|
41806
42824
|
function workflowScriptReplaySource(journalProtocolVersion) {
|
|
41807
42825
|
return WORKFLOW_SCRIPT_PROTOCOL_VERSIONS.includes(journalProtocolVersion) ? WORKFLOW_SCRIPT_REPLAY_SOURCES[journalProtocolVersion] : void 0;
|
|
41808
42826
|
}
|
|
41809
42827
|
__name(workflowScriptReplaySource, "workflowScriptReplaySource");
|
|
41810
|
-
|
|
42828
|
+
__name10(workflowScriptReplaySource, "workflowScriptReplaySource");
|
|
41811
42829
|
var HOST_BINDINGS = [
|
|
41812
42830
|
"args",
|
|
41813
42831
|
"agent",
|
|
@@ -41836,7 +42854,7 @@ function transformWorkflowScriptModule(script) {
|
|
|
41836
42854
|
return script.replace(/^\s*export\s+const\s+meta\s*=/m, "const meta =");
|
|
41837
42855
|
}
|
|
41838
42856
|
__name(transformWorkflowScriptModule, "transformWorkflowScriptModule");
|
|
41839
|
-
|
|
42857
|
+
__name10(transformWorkflowScriptModule, "transformWorkflowScriptModule");
|
|
41840
42858
|
function buildWorkflowScriptWrapper(script, input) {
|
|
41841
42859
|
const tick = input ?? {};
|
|
41842
42860
|
const version = tick.journalProtocolVersion ?? WORKFLOW_SCRIPT_PROTOCOL_VERSION;
|
|
@@ -41886,7 +42904,7 @@ ${transformWorkflowScriptModule(script)}
|
|
|
41886
42904
|
};
|
|
41887
42905
|
}
|
|
41888
42906
|
__name(buildWorkflowScriptWrapper, "buildWorkflowScriptWrapper");
|
|
41889
|
-
|
|
42907
|
+
__name10(buildWorkflowScriptWrapper, "buildWorkflowScriptWrapper");
|
|
41890
42908
|
|
|
41891
42909
|
// src/utils/workflow-script-replay.ts
|
|
41892
42910
|
var ReplayRuntimeUnavailableError = class extends Error {
|
|
@@ -42010,7 +43028,7 @@ __name(bundledScriptRunner, "bundledScriptRunner");
|
|
|
42010
43028
|
function projectScriptRunner(projectDir) {
|
|
42011
43029
|
let runtime;
|
|
42012
43030
|
try {
|
|
42013
|
-
const req =
|
|
43031
|
+
const req = createRequire3(`${projectDir.replace(/\/$/, "")}/package.json`);
|
|
42014
43032
|
runtime = req("@lua/sandbox-runtime");
|
|
42015
43033
|
} catch (e) {
|
|
42016
43034
|
throw new ReplayRuntimeUnavailableError(e.message);
|
|
@@ -42320,7 +43338,7 @@ async function runWorkflowLocalFromProject(name, flags) {
|
|
|
42320
43338
|
fastRetries: !!flags.fastRetries,
|
|
42321
43339
|
realTime: !!flags.realTime,
|
|
42322
43340
|
artefactsDir: flags.artefactsDir,
|
|
42323
|
-
workspaceDir: flags.workspace ?
|
|
43341
|
+
workspaceDir: flags.workspace ? path26.resolve(flags.workspace) : void 0,
|
|
42324
43342
|
env: parseEnvFlags(flags.env),
|
|
42325
43343
|
prompt: process.stdin.isTTY && !asJson && !isCiModeEnabled() ? promptForLocalDecision : void 0,
|
|
42326
43344
|
log: asJson ? void 0 : (line) => console.log(line)
|
|
@@ -42471,10 +43489,10 @@ async function runScriptFormLocally(wf, flags, say) {
|
|
|
42471
43489
|
}
|
|
42472
43490
|
__name(runScriptFormLocally, "runScriptFormLocally");
|
|
42473
43491
|
function writeLedgerFile(file, value3) {
|
|
42474
|
-
|
|
43492
|
+
fs18.mkdirSync(path26.dirname(path26.resolve(file)), {
|
|
42475
43493
|
recursive: true
|
|
42476
43494
|
});
|
|
42477
|
-
|
|
43495
|
+
fs18.writeFileSync(file, `${JSON.stringify(value3, null, 2)}
|
|
42478
43496
|
`);
|
|
42479
43497
|
}
|
|
42480
43498
|
__name(writeLedgerFile, "writeLedgerFile");
|
|
@@ -42668,6 +43686,10 @@ async function testCommand(type, cmdObj) {
|
|
|
42668
43686
|
{
|
|
42669
43687
|
name: "\u{1F4E4} PostProcessor",
|
|
42670
43688
|
value: "postprocessor"
|
|
43689
|
+
},
|
|
43690
|
+
{
|
|
43691
|
+
name: "\u{1F5A5}\uFE0F Web app route",
|
|
43692
|
+
value: "webapp"
|
|
42671
43693
|
}
|
|
42672
43694
|
]
|
|
42673
43695
|
}
|
|
@@ -42685,6 +43707,9 @@ async function testCommand(type, cmdObj) {
|
|
|
42685
43707
|
case "webhook":
|
|
42686
43708
|
await testWebhook(entityName, inputJson, asJson);
|
|
42687
43709
|
break;
|
|
43710
|
+
case "webapp":
|
|
43711
|
+
await testWebApp(entityName, cmdObj?.route ?? null, inputJson, asJson);
|
|
43712
|
+
break;
|
|
42688
43713
|
case "job":
|
|
42689
43714
|
await testJob(entityName, asJson);
|
|
42690
43715
|
break;
|
|
@@ -42924,6 +43949,108 @@ async function testWebhook(entityName, inputJson, asJson = false) {
|
|
|
42924
43949
|
});
|
|
42925
43950
|
}
|
|
42926
43951
|
__name(testWebhook, "testWebhook");
|
|
43952
|
+
async function testWebApp(entityName, routeSpec, inputJson, asJson = false) {
|
|
43953
|
+
progress(asJson, "\u{1F5A5}\uFE0F Testing web app route...");
|
|
43954
|
+
progress(asJson, "\u{1F4E6} Compiling code first...");
|
|
43955
|
+
await compileQuietly(asJson);
|
|
43956
|
+
const { apiKey, agentId, config } = await loadAuthOrFail();
|
|
43957
|
+
const manifest = loadManifest();
|
|
43958
|
+
const apps = getPrimitivesByKind(manifest, PrimitiveKind.WEB_APP);
|
|
43959
|
+
if (apps.length === 0) {
|
|
43960
|
+
console.error("\u274C No web apps found in compiled output.");
|
|
43961
|
+
console.log("\u{1F4A1} Define one with defineWebApp and list it under `webApps` on your LuaAgent.");
|
|
43962
|
+
return;
|
|
43963
|
+
}
|
|
43964
|
+
const app = await selectEntityOrPrompt({
|
|
43965
|
+
items: apps,
|
|
43966
|
+
entityName,
|
|
43967
|
+
entityType: "Web app",
|
|
43968
|
+
idProperty: "name",
|
|
43969
|
+
nameProperty: "name",
|
|
43970
|
+
promptMessage: "Select a web app:",
|
|
43971
|
+
formatChoice: /* @__PURE__ */ __name((a) => `${a.name} (${a.routes.length} route(s))`, "formatChoice"),
|
|
43972
|
+
asJson
|
|
43973
|
+
});
|
|
43974
|
+
if (!app) {
|
|
43975
|
+
console.log("Test cancelled.");
|
|
43976
|
+
return;
|
|
43977
|
+
}
|
|
43978
|
+
let spec = routeSpec;
|
|
43979
|
+
if (!spec) {
|
|
43980
|
+
if (asJson) {
|
|
43981
|
+
throw CliError.usage("--route is required with --json, e.g. --route 'GET /tickets?status=open'");
|
|
43982
|
+
}
|
|
43983
|
+
const answer = await safePrompt([
|
|
43984
|
+
{
|
|
43985
|
+
type: "input",
|
|
43986
|
+
name: "route",
|
|
43987
|
+
message: "Route to call (METHOD /path?query):",
|
|
43988
|
+
default: app.routes[0] ? `${app.routes[0].method} ${app.routes[0].path}` : "GET /"
|
|
43989
|
+
}
|
|
43990
|
+
]);
|
|
43991
|
+
if (!answer) {
|
|
43992
|
+
console.log("Test cancelled.");
|
|
43993
|
+
return;
|
|
43994
|
+
}
|
|
43995
|
+
spec = answer.route;
|
|
43996
|
+
}
|
|
43997
|
+
let parsed;
|
|
43998
|
+
try {
|
|
43999
|
+
parsed = parseRouteSpec(spec);
|
|
44000
|
+
} catch (error) {
|
|
44001
|
+
throw CliError.usage(error.message);
|
|
44002
|
+
}
|
|
44003
|
+
const matched = matchManifestRoute(app.routes, parsed.method, parsed.path);
|
|
44004
|
+
if (!matched && !app.hasFetch) {
|
|
44005
|
+
throw CliError.usage(`No route of ${app.name} matches ${parsed.method} ${parsed.path}.`, [
|
|
44006
|
+
"Routes:",
|
|
44007
|
+
...app.routes.map((r) => ` ${r.key}`)
|
|
44008
|
+
].join("\n"));
|
|
44009
|
+
}
|
|
44010
|
+
const input = inputJson ? parseJsonInputOrFail(inputJson, '{"body": {...}, "headers": {"x-custom": "..."}}') : {};
|
|
44011
|
+
const auth = await developerAuth(apiKey, agentId, config);
|
|
44012
|
+
const yamlApp = config?.webApps?.find((a) => a.name === app.name);
|
|
44013
|
+
const webRouteInput = buildWebRouteInput({
|
|
44014
|
+
spec: parsed,
|
|
44015
|
+
route: matched,
|
|
44016
|
+
body: input.body,
|
|
44017
|
+
headers: input.headers,
|
|
44018
|
+
auth,
|
|
44019
|
+
app: {
|
|
44020
|
+
id: yamlApp?.webAppId || "local",
|
|
44021
|
+
name: app.name,
|
|
44022
|
+
version: yamlApp?.version || "0.0.0"
|
|
44023
|
+
}
|
|
44024
|
+
});
|
|
44025
|
+
progress(asJson, `
|
|
44026
|
+
\u{1F680} ${parsed.method} ${parsed.path}${matched ? ` \u2192 ${matched.key}` : " \u2192 fetch"}`);
|
|
44027
|
+
const appCode = loadArtifact(app, process.cwd());
|
|
44028
|
+
await withSandboxEnv(async () => {
|
|
44029
|
+
try {
|
|
44030
|
+
const result = await executeWebRoute({
|
|
44031
|
+
appCode,
|
|
44032
|
+
input: webRouteInput,
|
|
44033
|
+
apiKey,
|
|
44034
|
+
agentId
|
|
44035
|
+
});
|
|
44036
|
+
if (asJson) {
|
|
44037
|
+
console.log(JSON.stringify(result, null, 2));
|
|
44038
|
+
} else {
|
|
44039
|
+
const ok = result.status < 400;
|
|
44040
|
+
(ok ? success : (_, m) => console.error(m))(asJson, `
|
|
44041
|
+
${ok ? "\u2705" : "\u26A0\uFE0F "} ${result.status}`);
|
|
44042
|
+
for (const [name, value3] of Object.entries(result.headers ?? {})) console.log(`${name}: ${value3}`);
|
|
44043
|
+
if (result.body) {
|
|
44044
|
+
console.log(result.body.kind === "json" ? JSON.stringify(result.body.value, null, 2) : result.body.kind === "text" ? result.body.value : `<${Buffer.from(result.body.value, "base64").length} bytes, base64>`);
|
|
44045
|
+
}
|
|
44046
|
+
}
|
|
44047
|
+
if (result.status >= 500) process.exitCode = 1;
|
|
44048
|
+
} catch (error) {
|
|
44049
|
+
handleExecutionError(error, "Web app route", asJson);
|
|
44050
|
+
}
|
|
44051
|
+
});
|
|
44052
|
+
}
|
|
44053
|
+
__name(testWebApp, "testWebApp");
|
|
42927
44054
|
async function testJob(entityName, asJson = false) {
|
|
42928
44055
|
progress(asJson, "\u23F0 Testing job...");
|
|
42929
44056
|
progress(asJson, "\u{1F4E6} Compiling code first...");
|
|
@@ -44487,10 +45614,11 @@ async function pushVersionedPrimitive(handler, options = {}) {
|
|
|
44487
45614
|
}
|
|
44488
45615
|
const manifest = loadManifest();
|
|
44489
45616
|
const bundleAccumulator = /* @__PURE__ */ new Map();
|
|
44490
|
-
const
|
|
44491
|
-
if (!
|
|
45617
|
+
const prepared = handler.prepareForPush(manifest, selected.name, void 0, bundleAccumulator);
|
|
45618
|
+
if (!prepared) {
|
|
44492
45619
|
throw new Error(`${handler.displayName} "${selected.name}" not found in compiled output.`);
|
|
44493
45620
|
}
|
|
45621
|
+
const pushData = handler.completePushData ? await handler.completePushData(prepared, manifest, selected.name, bundleAccumulator) : prepared;
|
|
44494
45622
|
let bundleStats = {
|
|
44495
45623
|
total: 0,
|
|
44496
45624
|
alreadyExisted: 0,
|
|
@@ -44520,6 +45648,12 @@ async function pushVersionedPrimitive(handler, options = {}) {
|
|
|
44520
45648
|
writeSuccess(`
|
|
44521
45649
|
\u2705 Successfully pushed ${selected.name} v${confirmedVersion}
|
|
44522
45650
|
`);
|
|
45651
|
+
if (handler.kind === PrimitiveKind.WEB_APP) {
|
|
45652
|
+
return {
|
|
45653
|
+
productionDeploySucceeded: false,
|
|
45654
|
+
bundleStats
|
|
45655
|
+
};
|
|
45656
|
+
}
|
|
44523
45657
|
if (await shouldDeployAfterPush(options)) {
|
|
44524
45658
|
const deployedOk = await genericDeployAfterPush(handler, apiKey, agentId, entityId, selected.name, confirmedVersion, options.autoDeploy || false);
|
|
44525
45659
|
return {
|
|
@@ -44666,6 +45800,8 @@ async function pushCommand(type, cmdObj) {
|
|
|
44666
45800
|
versionedPushDeployResult = await pushVersionedPrimitive(voiceHandler, options);
|
|
44667
45801
|
} else if (selectedType === "workflow") {
|
|
44668
45802
|
versionedPushDeployResult = await pushVersionedPrimitive(workflowHandler, options);
|
|
45803
|
+
} else if (selectedType === "webapp") {
|
|
45804
|
+
versionedPushDeployResult = await pushVersionedPrimitive(webAppHandler, options);
|
|
44669
45805
|
} else if (selectedType === "mcp") {
|
|
44670
45806
|
const mcpActivated = await pushMCPServer(options);
|
|
44671
45807
|
versionedPushDeployResult = {
|
|
@@ -44785,6 +45921,21 @@ Until the backup catches up, \`lua init\` for this agent will restore an older s
|
|
|
44785
45921
|
});
|
|
44786
45922
|
} else if (selectedType === "backup") {
|
|
44787
45923
|
} else if (selectedType === "agent") {
|
|
45924
|
+
} else if (selectedType === "webapp") {
|
|
45925
|
+
writeHintBlock({
|
|
45926
|
+
headline: `Staged but NOT live yet. ${WEB_APP_GOES_LIVE_WITH_AGENT_VERSION}`,
|
|
45927
|
+
lines: [
|
|
45928
|
+
{
|
|
45929
|
+
label: "Snapshot:",
|
|
45930
|
+
command: "lua version create"
|
|
45931
|
+
},
|
|
45932
|
+
{
|
|
45933
|
+
label: "Go live:",
|
|
45934
|
+
command: "lua version promote"
|
|
45935
|
+
}
|
|
45936
|
+
],
|
|
45937
|
+
when: "success"
|
|
45938
|
+
});
|
|
44788
45939
|
} else if (deployHint) {
|
|
44789
45940
|
writeHintBlock({
|
|
44790
45941
|
headline: "Staged but NOT live yet. To make it active:",
|
|
@@ -45067,7 +46218,8 @@ async function pushAllCommand(options) {
|
|
|
45067
46218
|
preprocessor: "\u{1F4E5}",
|
|
45068
46219
|
postprocessor: "\u{1F4E4}",
|
|
45069
46220
|
device: "\u{1F4E1}",
|
|
45070
|
-
voice: "\u{1F399}\uFE0F"
|
|
46221
|
+
voice: "\u{1F399}\uFE0F",
|
|
46222
|
+
"web-app": "\u{1F5A5}\uFE0F"
|
|
45071
46223
|
};
|
|
45072
46224
|
const handlers = [
|
|
45073
46225
|
skillHandler,
|
|
@@ -45083,7 +46235,10 @@ async function pushAllCommand(options) {
|
|
|
45083
46235
|
postprocessorHandler,
|
|
45084
46236
|
deviceHandler,
|
|
45085
46237
|
deviceTriggerHandler,
|
|
45086
|
-
voiceHandler
|
|
46238
|
+
voiceHandler,
|
|
46239
|
+
// Lua Apps: pushed (route bundle + page build) like any versioned kind, never deployed here —
|
|
46240
|
+
// a web app version goes live with the agent version that pins it.
|
|
46241
|
+
webAppHandler
|
|
45087
46242
|
];
|
|
45088
46243
|
const handlerItems = handlers.map((handler) => ({
|
|
45089
46244
|
handler,
|
|
@@ -45117,11 +46272,12 @@ ${icon} Pushing ${items.length} ${handler.displayName}(s)...`);
|
|
|
45117
46272
|
for (const item of items) {
|
|
45118
46273
|
try {
|
|
45119
46274
|
const bundleAccumulator = /* @__PURE__ */ new Map();
|
|
45120
|
-
const
|
|
45121
|
-
if (!
|
|
46275
|
+
const prepared = handler.prepareForPush(manifest, item.name, void 0, bundleAccumulator);
|
|
46276
|
+
if (!prepared) {
|
|
45122
46277
|
console.warn(`\u26A0\uFE0F ${handler.displayName} "${item.name}" not found in compiled output, skipping`);
|
|
45123
46278
|
continue;
|
|
45124
46279
|
}
|
|
46280
|
+
const pushData = handler.completePushData ? await handler.completePushData(prepared, manifest, item.name, bundleAccumulator) : prepared;
|
|
45125
46281
|
if (bundleAccumulator.size > 0) {
|
|
45126
46282
|
const stats = await ensureBundlesUploaded(apiKey, agentId, bundleAccumulator);
|
|
45127
46283
|
bundleStatsAggregate.total += stats.total;
|
|
@@ -45179,7 +46335,8 @@ ${icon} Pushing ${items.length} ${handler.displayName}(s)...`);
|
|
|
45179
46335
|
entityId
|
|
45180
46336
|
});
|
|
45181
46337
|
writeSuccess(` \u2705 ${item.name} v${newVersion} pushed`);
|
|
45182
|
-
if (
|
|
46338
|
+
if (handler.kind === PrimitiveKind.WEB_APP) {
|
|
46339
|
+
} else if (options.autoDeploy) {
|
|
45183
46340
|
toDeploy.push({
|
|
45184
46341
|
handler,
|
|
45185
46342
|
name: item.name,
|
|
@@ -45318,7 +46475,8 @@ Until the backup catches up, \`lua init\` for this agent will restore an older s
|
|
|
45318
46475
|
jobs: "\u23F0",
|
|
45319
46476
|
preprocessors: "\u{1F4E5}",
|
|
45320
46477
|
postprocessors: "\u{1F4E4}",
|
|
45321
|
-
voices: "\u{1F399}\uFE0F"
|
|
46478
|
+
voices: "\u{1F399}\uFE0F",
|
|
46479
|
+
"web apps": "\u{1F5A5}\uFE0F"
|
|
45322
46480
|
};
|
|
45323
46481
|
for (const [kind, items] of byKind) {
|
|
45324
46482
|
const icon = summaryIcons[kind] || "\u{1F4E6}";
|
|
@@ -47681,8 +48839,8 @@ init_cli();
|
|
|
47681
48839
|
init_constants();
|
|
47682
48840
|
init_command_utils();
|
|
47683
48841
|
init_developer_api_service();
|
|
47684
|
-
import
|
|
47685
|
-
import
|
|
48842
|
+
import fs19 from "fs";
|
|
48843
|
+
import path27 from "path";
|
|
47686
48844
|
import inquirer10 from "inquirer";
|
|
47687
48845
|
init_analytics();
|
|
47688
48846
|
init_cli_error();
|
|
@@ -48031,10 +49189,10 @@ function variablesToEnvContent(variables) {
|
|
|
48031
49189
|
}
|
|
48032
49190
|
__name(variablesToEnvContent, "variablesToEnvContent");
|
|
48033
49191
|
function saveSandboxEnvVariables(variables) {
|
|
48034
|
-
const envFilePath =
|
|
49192
|
+
const envFilePath = path27.join(process.cwd(), ".env");
|
|
48035
49193
|
try {
|
|
48036
49194
|
const content = variablesToEnvContent(variables);
|
|
48037
|
-
|
|
49195
|
+
fs19.writeFileSync(envFilePath, content, "utf8");
|
|
48038
49196
|
return true;
|
|
48039
49197
|
} catch (error) {
|
|
48040
49198
|
console.error("\u274C Error saving .env file:", error);
|
|
@@ -50490,6 +51648,7 @@ async function listChannelsInteractive(agentApi, agentId, config) {
|
|
|
50490
51648
|
clearPromptLines(2);
|
|
50491
51649
|
const selectedChannel = channels[selectedIndex];
|
|
50492
51650
|
displayChannelDetails(selectedChannel);
|
|
51651
|
+
if (selectedChannel.type === "slack") await slackConnectionActions(agentApi, agentId, selectedChannel);
|
|
50493
51652
|
}
|
|
50494
51653
|
__name(listChannelsInteractive, "listChannelsInteractive");
|
|
50495
51654
|
function displayChannelDetails(channel) {
|
|
@@ -50617,6 +51776,20 @@ function displaySlackDetails(channel) {
|
|
|
50617
51776
|
if (channel.data.botId) {
|
|
50618
51777
|
writeInfo(`Bot ID: ${channel.data.botId}`);
|
|
50619
51778
|
}
|
|
51779
|
+
const status = channel.data.status;
|
|
51780
|
+
if (status === "uninstalled") {
|
|
51781
|
+
writeInfo("Status: uninstalled in Slack \u2014 reinstall the app to reconnect");
|
|
51782
|
+
} else if (status === "pending_setup" || status === "pending_oauth") {
|
|
51783
|
+
writeInfo("Status: not installed yet \u2014 get an install link below");
|
|
51784
|
+
}
|
|
51785
|
+
const setup = channel.data.setup;
|
|
51786
|
+
if (setup) {
|
|
51787
|
+
writeInfo(`Signing secret: ${SLACK_SIGNING_LABELS[setup.signing]}`);
|
|
51788
|
+
if (setup.updateAvailable) {
|
|
51789
|
+
const missing = setup.missingRequired.length ? ` (missing: ${setup.missingRequired.join(", ")})` : "";
|
|
51790
|
+
writeInfo(`Update: available${missing} \u2014 choose "Show the update steps" below`);
|
|
51791
|
+
}
|
|
51792
|
+
}
|
|
50620
51793
|
}
|
|
50621
51794
|
}
|
|
50622
51795
|
__name(displaySlackDetails, "displaySlackDetails");
|
|
@@ -50888,8 +52061,97 @@ To complete the email channel setup, configure email forwarding:`);
|
|
|
50888
52061
|
}
|
|
50889
52062
|
}
|
|
50890
52063
|
__name(createEmailChannel, "createEmailChannel");
|
|
52064
|
+
var SLACK_SIGNING_SECRET = /^[0-9A-Za-z]{32}$/;
|
|
52065
|
+
var SLACK_SIGNING_LABELS = {
|
|
52066
|
+
none: "not saved \u2014 Slack events are not verified",
|
|
52067
|
+
verifying: "saved, waiting for the first event to confirm it",
|
|
52068
|
+
mismatch: "saved, but Slack's events don't match it \u2014 paste it again",
|
|
52069
|
+
failing: "an event didn't match it and was rejected \u2014 if you regenerated it in Slack, paste the new one; otherwise this clears with the next real message",
|
|
52070
|
+
verified: "verified \u2014 events that fail the check are rejected"
|
|
52071
|
+
};
|
|
52072
|
+
function slackSigningSecretPrompt() {
|
|
52073
|
+
return {
|
|
52074
|
+
type: "password",
|
|
52075
|
+
name: "signingSecret",
|
|
52076
|
+
message: "Enter the Slack app Signing Secret (Basic Information \u2192 App Credentials):",
|
|
52077
|
+
mask: "*",
|
|
52078
|
+
validate: /* @__PURE__ */ __name((input, answers) => {
|
|
52079
|
+
const value3 = input.trim();
|
|
52080
|
+
if (!SLACK_SIGNING_SECRET.test(value3)) return "The signing secret is 32 letters and digits";
|
|
52081
|
+
if (answers?.clientSecret && value3 === answers.clientSecret.trim()) {
|
|
52082
|
+
return "That's the Client Secret. Paste the Signing Secret, just below it";
|
|
52083
|
+
}
|
|
52084
|
+
return true;
|
|
52085
|
+
}, "validate")
|
|
52086
|
+
};
|
|
52087
|
+
}
|
|
52088
|
+
__name(slackSigningSecretPrompt, "slackSigningSecretPrompt");
|
|
52089
|
+
async function offerToOpen(url, question) {
|
|
52090
|
+
const { openIt } = await inquirer12.prompt([
|
|
52091
|
+
{
|
|
52092
|
+
type: "confirm",
|
|
52093
|
+
name: "openIt",
|
|
52094
|
+
message: question,
|
|
52095
|
+
default: true
|
|
52096
|
+
}
|
|
52097
|
+
]);
|
|
52098
|
+
if (openIt) await open5(url);
|
|
52099
|
+
}
|
|
52100
|
+
__name(offerToOpen, "offerToOpen");
|
|
52101
|
+
async function startSlackApp(agentApi, agentId, kind) {
|
|
52102
|
+
const { source } = await inquirer12.prompt([
|
|
52103
|
+
{
|
|
52104
|
+
type: "list",
|
|
52105
|
+
name: "source",
|
|
52106
|
+
message: "Which Slack app?",
|
|
52107
|
+
choices: [
|
|
52108
|
+
{
|
|
52109
|
+
name: "Create a new app from Lua\u2019s manifest (recommended)",
|
|
52110
|
+
value: "new"
|
|
52111
|
+
},
|
|
52112
|
+
{
|
|
52113
|
+
name: "I already have a Slack app",
|
|
52114
|
+
value: "existing"
|
|
52115
|
+
}
|
|
52116
|
+
]
|
|
52117
|
+
}
|
|
52118
|
+
]);
|
|
52119
|
+
if (source === "existing") return true;
|
|
52120
|
+
const response = await agentApi.getSlackManifest(agentId);
|
|
52121
|
+
const createAppUrl = response.success ? response.data?.createAppUrl : void 0;
|
|
52122
|
+
if (!createAppUrl) {
|
|
52123
|
+
throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Could not prepare the Slack app", response.error?.error);
|
|
52124
|
+
}
|
|
52125
|
+
writeInfo("\n1. Create the app. Slack opens with it named after your agent, with its permissions and events.");
|
|
52126
|
+
writeInfo(" Pick the workspace, then click Next and Create and Install:");
|
|
52127
|
+
console.log(`
|
|
52128
|
+
${createAppUrl}
|
|
52129
|
+
`);
|
|
52130
|
+
await offerToOpen(createAppUrl, "Open it in your browser?");
|
|
52131
|
+
writeInfo(" If Slack says the Request URL didn't respond, click Retry under Event Subscriptions.");
|
|
52132
|
+
if (kind === "private") {
|
|
52133
|
+
writeInfo("2. In the new app: Install App \u2192 Install to Workspace \u2192 Allow, then copy the Bot User OAuth Token.");
|
|
52134
|
+
writeInfo("3. Basic Information \u2192 App Credentials: copy the Signing Secret.\n");
|
|
52135
|
+
} else {
|
|
52136
|
+
writeInfo("2. Basic Information \u2192 App Credentials: copy the App ID, Client ID, Client Secret and Signing Secret.\n");
|
|
52137
|
+
}
|
|
52138
|
+
return false;
|
|
52139
|
+
}
|
|
52140
|
+
__name(startSlackApp, "startSlackApp");
|
|
52141
|
+
var slackManifestEditorUrl = /* @__PURE__ */ __name((appId, teamId) => teamId ? `https://app.slack.com/app-settings/${teamId}/${appId}/app-manifest` : `https://api.slack.com/apps/${appId}`, "slackManifestEditorUrl");
|
|
52142
|
+
function printManifestUpdate(manifestUrl, manifest) {
|
|
52143
|
+
writeInfo("\nUpdate the app with Lua\u2019s manifest:");
|
|
52144
|
+
writeInfo(` 1. Open ${manifestUrl}`);
|
|
52145
|
+
writeInfo(" 2. Paste this on the JSON tab and click Save Changes");
|
|
52146
|
+
writeInfo(" 3. Reinstall the app when Slack asks");
|
|
52147
|
+
writeInfo(" Saving replaces the app's settings in Slack: add anything you set up there yourself (slash commands, extra permissions) to the manifest first.\n");
|
|
52148
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
52149
|
+
console.log();
|
|
52150
|
+
}
|
|
52151
|
+
__name(printManifestUpdate, "printManifestUpdate");
|
|
50891
52152
|
async function createSlackPrivateChannel(agentApi, agentId) {
|
|
50892
52153
|
writeInfo("\u{1F512} Creating Private Slack Channel\n");
|
|
52154
|
+
const existingApp = await startSlackApp(agentApi, agentId, "private");
|
|
50893
52155
|
const answers = await inquirer12.prompt([
|
|
50894
52156
|
{
|
|
50895
52157
|
type: "password",
|
|
@@ -50905,13 +52167,15 @@ async function createSlackPrivateChannel(agentApi, agentId) {
|
|
|
50905
52167
|
}
|
|
50906
52168
|
return true;
|
|
50907
52169
|
}, "validate")
|
|
50908
|
-
}
|
|
52170
|
+
},
|
|
52171
|
+
slackSigningSecretPrompt()
|
|
50909
52172
|
]);
|
|
50910
52173
|
const channelData = {
|
|
50911
52174
|
type: "slack",
|
|
50912
52175
|
slack: {
|
|
50913
52176
|
type: "private",
|
|
50914
|
-
accessToken: answers.accessToken.trim()
|
|
52177
|
+
accessToken: answers.accessToken.trim(),
|
|
52178
|
+
signingSecret: answers.signingSecret.trim()
|
|
50915
52179
|
}
|
|
50916
52180
|
};
|
|
50917
52181
|
writeInfo("\n\u{1F4E1} Creating Slack private channel...");
|
|
@@ -50920,19 +52184,16 @@ async function createSlackPrivateChannel(agentApi, agentId) {
|
|
|
50920
52184
|
throw channelCreateError(response.error, "This Slack workspace is already connected to this agent.");
|
|
50921
52185
|
}
|
|
50922
52186
|
const data = response.data;
|
|
50923
|
-
|
|
50924
|
-
|
|
50925
|
-
|
|
50926
|
-
|
|
50927
|
-
|
|
50928
|
-
writeInfo(`Ensure your app Manifest is configured correctly. Below is an example:
|
|
50929
|
-
`);
|
|
50930
|
-
writeInfo(JSON.stringify(data.slack.manifest, null, 2));
|
|
50931
|
-
}
|
|
52187
|
+
writeSuccess("\n\u2705 Slack private channel created successfully!\n");
|
|
52188
|
+
writeInfo(`\u{1F916} Bot Name: ${data.botName}`);
|
|
52189
|
+
writeInfo(`\u{1F3E2} Workspace: ${data.teamName || data.url}`);
|
|
52190
|
+
if (existingApp) printManifestUpdate(slackManifestEditorUrl(data.appId, data.teamId), data.manifest);
|
|
52191
|
+
writeInfo("\u{1F4AC} Send the bot a message in Slack: the first event confirms the signing secret.");
|
|
50932
52192
|
}
|
|
50933
52193
|
__name(createSlackPrivateChannel, "createSlackPrivateChannel");
|
|
50934
52194
|
async function createSlackPublicChannel(agentApi, agentId) {
|
|
50935
52195
|
writeInfo("\u{1F310} Creating Public Slack Channel\n");
|
|
52196
|
+
const existingApp = await startSlackApp(agentApi, agentId, "public");
|
|
50936
52197
|
const answers = await inquirer12.prompt([
|
|
50937
52198
|
{
|
|
50938
52199
|
type: "input",
|
|
@@ -50955,10 +52216,9 @@ async function createSlackPublicChannel(agentApi, agentId) {
|
|
|
50955
52216
|
name: "clientSecret",
|
|
50956
52217
|
message: "Enter Slack client secret:",
|
|
50957
52218
|
mask: "*",
|
|
50958
|
-
validate: /* @__PURE__ */ __name((input) =>
|
|
50959
|
-
|
|
50960
|
-
|
|
50961
|
-
}
|
|
52219
|
+
validate: /* @__PURE__ */ __name((input) => input.trim().length > 0 || "Client secret is required", "validate")
|
|
52220
|
+
},
|
|
52221
|
+
slackSigningSecretPrompt()
|
|
50962
52222
|
]);
|
|
50963
52223
|
const channelData = {
|
|
50964
52224
|
type: "slack",
|
|
@@ -50966,7 +52226,8 @@ async function createSlackPublicChannel(agentApi, agentId) {
|
|
|
50966
52226
|
type: "public",
|
|
50967
52227
|
appId: answers.appId.trim(),
|
|
50968
52228
|
clientId: answers.clientId.trim(),
|
|
50969
|
-
clientSecret: answers.clientSecret.trim()
|
|
52229
|
+
clientSecret: answers.clientSecret.trim(),
|
|
52230
|
+
signingSecret: answers.signingSecret.trim()
|
|
50970
52231
|
}
|
|
50971
52232
|
};
|
|
50972
52233
|
writeInfo("\n\u{1F4E1} Creating Slack public channel...");
|
|
@@ -50975,19 +52236,84 @@ async function createSlackPublicChannel(agentApi, agentId) {
|
|
|
50975
52236
|
throw channelCreateError(response.error, "This Slack app is already connected to this agent.");
|
|
50976
52237
|
}
|
|
50977
52238
|
const data = response.data;
|
|
50978
|
-
|
|
50979
|
-
|
|
50980
|
-
|
|
50981
|
-
|
|
50982
|
-
|
|
52239
|
+
writeSuccess("\n\u2705 Slack public channel created successfully!\n");
|
|
52240
|
+
writeInfo(`\u{1F194} App ID: ${data.appId}`);
|
|
52241
|
+
if (existingApp) printManifestUpdate(slackManifestEditorUrl(data.appId), data.manifest);
|
|
52242
|
+
writeInfo("Last step: install the app in your workspace (the link works for 30 minutes):");
|
|
52243
|
+
console.log(`
|
|
52244
|
+
${data.installUrl}
|
|
50983
52245
|
`);
|
|
50984
|
-
|
|
50985
|
-
|
|
52246
|
+
await offerToOpen(data.installUrl, "Open it in your browser?");
|
|
52247
|
+
writeInfo("After you allow it, Slack shows Lua's result page. For a new link later: lua channels \u2192 List \u2192 this connection.");
|
|
52248
|
+
}
|
|
52249
|
+
__name(createSlackPublicChannel, "createSlackPublicChannel");
|
|
52250
|
+
async function slackConnectionActions(agentApi, agentId, channel) {
|
|
52251
|
+
if (!channel.id) return;
|
|
52252
|
+
const choices = [
|
|
52253
|
+
{
|
|
52254
|
+
name: "Show the update steps and manifest",
|
|
52255
|
+
value: "manifest"
|
|
52256
|
+
},
|
|
52257
|
+
{
|
|
52258
|
+
name: "Add or replace the signing secret",
|
|
52259
|
+
value: "secret"
|
|
52260
|
+
},
|
|
52261
|
+
{
|
|
52262
|
+
name: "Re-check permissions with Slack",
|
|
52263
|
+
value: "check"
|
|
52264
|
+
}
|
|
52265
|
+
];
|
|
52266
|
+
if (channel.data?.type === "public") choices.push({
|
|
52267
|
+
name: "Get an install link",
|
|
52268
|
+
value: "install"
|
|
52269
|
+
});
|
|
52270
|
+
choices.push({
|
|
52271
|
+
name: "\u2190 Back",
|
|
52272
|
+
value: "back"
|
|
52273
|
+
});
|
|
52274
|
+
const { action } = await inquirer12.prompt([
|
|
52275
|
+
{
|
|
52276
|
+
type: "list",
|
|
52277
|
+
name: "action",
|
|
52278
|
+
message: "What would you like to do?",
|
|
52279
|
+
choices
|
|
52280
|
+
}
|
|
52281
|
+
]);
|
|
52282
|
+
if (action === "manifest") {
|
|
52283
|
+
const response = await agentApi.getSlackManifest(agentId, channel.id);
|
|
52284
|
+
if (!response.success || !response.data) throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Could not load the manifest");
|
|
52285
|
+
printManifestUpdate(response.data.manifestUrl ?? slackManifestEditorUrl(channel.data.appId, channel.data.teamId), response.data.manifest);
|
|
52286
|
+
writeInfo("Then save the signing secret here and check again.");
|
|
52287
|
+
} else if (action === "secret") {
|
|
52288
|
+
const { signingSecret } = await inquirer12.prompt([
|
|
52289
|
+
slackSigningSecretPrompt()
|
|
52290
|
+
]);
|
|
52291
|
+
const response = await agentApi.saveSlackSigningSecret(agentId, channel.identifier, signingSecret.trim());
|
|
52292
|
+
if (!response.success) throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Could not save the signing secret");
|
|
52293
|
+
writeSuccess("\u2705 Signing secret saved. The next message the bot receives confirms it.");
|
|
52294
|
+
} else if (action === "check") {
|
|
52295
|
+
const response = await agentApi.checkSlackConnection(agentId, channel.id);
|
|
52296
|
+
if (!response.success || !response.data) throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Could not reach Slack");
|
|
52297
|
+
const { status, setup } = response.data;
|
|
52298
|
+
if (status === "uninstalled") {
|
|
52299
|
+
writeInfo("\u26A0\uFE0F Slack says this app is no longer installed. Reinstall it, then reconnect.");
|
|
52300
|
+
} else if (setup.missingRequired.length) {
|
|
52301
|
+
writeInfo(`\u26A0\uFE0F Missing required permissions: ${setup.missingRequired.join(", ")}. Update the manifest and reinstall.`);
|
|
52302
|
+
} else {
|
|
52303
|
+
writeSuccess(`\u2705 Slack answered. Signing secret: ${SLACK_SIGNING_LABELS[setup.signing]}.`);
|
|
52304
|
+
}
|
|
52305
|
+
if (setup.missingOptional.length) writeInfo(`Optional permissions not granted: ${setup.missingOptional.join(", ")}.`);
|
|
52306
|
+
} else if (action === "install") {
|
|
52307
|
+
const response = await agentApi.getSlackInstallUrl(agentId, channel.id);
|
|
52308
|
+
if (!response.success || !response.data) throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Could not get an install link");
|
|
52309
|
+
writeInfo("Install link (works for 30 minutes):");
|
|
52310
|
+
console.log(`
|
|
52311
|
+
${response.data.installUrl}
|
|
50986
52312
|
`);
|
|
50987
|
-
|
|
52313
|
+
await offerToOpen(response.data.installUrl, "Open it in your browser?");
|
|
50988
52314
|
}
|
|
50989
52315
|
}
|
|
50990
|
-
__name(
|
|
52316
|
+
__name(slackConnectionActions, "slackConnectionActions");
|
|
50991
52317
|
|
|
50992
52318
|
// src/commands/logs.ts
|
|
50993
52319
|
init_cli();
|
|
@@ -51922,8 +53248,8 @@ var DrainsApi = class extends HttpClient {
|
|
|
51922
53248
|
* answer is a plain `LogDrainRead` and is safe to retry; minting is not.
|
|
51923
53249
|
*/
|
|
51924
53250
|
async rotateSecret(drainId, finalize) {
|
|
51925
|
-
const
|
|
51926
|
-
return finalize ? this.httpPost(
|
|
53251
|
+
const path30 = this.drainPath(drainId, `/rotate-secret${finalize ? "?finalize=true" : ""}`);
|
|
53252
|
+
return finalize ? this.httpPost(path30, {}) : this.httpPostOnce(path30, {});
|
|
51927
53253
|
}
|
|
51928
53254
|
/**
|
|
51929
53255
|
* Re-enqueue one batch's records (PRO-2126).
|
|
@@ -52003,8 +53329,8 @@ function printJson(payload) {
|
|
|
52003
53329
|
console.log(JSON.stringify(payload, null, 2));
|
|
52004
53330
|
}
|
|
52005
53331
|
__name(printJson, "printJson");
|
|
52006
|
-
function emitAside(line,
|
|
52007
|
-
if (
|
|
53332
|
+
function emitAside(line, json2) {
|
|
53333
|
+
if (json2) process.stderr.write(`${line}
|
|
52008
53334
|
`);
|
|
52009
53335
|
else writeInfo(line);
|
|
52010
53336
|
}
|
|
@@ -52429,48 +53755,48 @@ function verificationCurl(type, endpoint, headers) {
|
|
|
52429
53755
|
];
|
|
52430
53756
|
}
|
|
52431
53757
|
__name(verificationCurl, "verificationCurl");
|
|
52432
|
-
function bucketVerificationInstructions(drain,
|
|
53758
|
+
function bucketVerificationInstructions(drain, json2) {
|
|
52433
53759
|
const prefix = drain.bucket?.prefix;
|
|
52434
53760
|
const where = prefix ? `${prefix}/_lua-verify-*` : "_lua-verify-*";
|
|
52435
53761
|
const bucket = drain.bucket?.bucket ?? "<your bucket>";
|
|
52436
53762
|
const endpointArg = drain.bucket?.endpoint ? ` --endpoint-url '${drain.bucket.endpoint}'` : "";
|
|
52437
|
-
emitAside("Lua writes a challenge object into the bucket itself \u2014 nothing is POSTed to a URL.",
|
|
52438
|
-
emitAside("Check the credentials can write under the prefix first:",
|
|
52439
|
-
emitAside("",
|
|
52440
|
-
emitAside(` aws s3 cp - 's3://${bucket}/${prefix ? `${prefix}/` : ""}_lua-write-check'${endpointArg} </dev/null`,
|
|
52441
|
-
emitAside("",
|
|
52442
|
-
emitAside(" (a zero-byte object, yours to delete \u2014 a write-only role cannot remove it itself)",
|
|
52443
|
-
emitAside("",
|
|
52444
|
-
emitAside(`Then: lua drains verify ${drain.id}`,
|
|
52445
|
-
emitAside("",
|
|
52446
|
-
emitAside("That is what mints the challenge, and how it settles depends on the role:",
|
|
52447
|
-
emitAside(" \xB7 with s3:GetObject, Lua reads the object back and 'verify' finishes on its own;",
|
|
52448
|
-
emitAside(" \xB7 write-only \u2014 the grant we recommend \u2014 leaves the claim open. List the prefix",
|
|
52449
|
-
emitAside(` for ${where}, take the <token> off the object name, and run:`,
|
|
52450
|
-
emitAside("",
|
|
52451
|
-
emitAside(` lua drains confirm ${drain.id} --token <token>`,
|
|
53763
|
+
emitAside("Lua writes a challenge object into the bucket itself \u2014 nothing is POSTed to a URL.", json2);
|
|
53764
|
+
emitAside("Check the credentials can write under the prefix first:", json2);
|
|
53765
|
+
emitAside("", json2);
|
|
53766
|
+
emitAside(` aws s3 cp - 's3://${bucket}/${prefix ? `${prefix}/` : ""}_lua-write-check'${endpointArg} </dev/null`, json2);
|
|
53767
|
+
emitAside("", json2);
|
|
53768
|
+
emitAside(" (a zero-byte object, yours to delete \u2014 a write-only role cannot remove it itself)", json2);
|
|
53769
|
+
emitAside("", json2);
|
|
53770
|
+
emitAside(`Then: lua drains verify ${drain.id}`, json2);
|
|
53771
|
+
emitAside("", json2);
|
|
53772
|
+
emitAside("That is what mints the challenge, and how it settles depends on the role:", json2);
|
|
53773
|
+
emitAside(" \xB7 with s3:GetObject, Lua reads the object back and 'verify' finishes on its own;", json2);
|
|
53774
|
+
emitAside(" \xB7 write-only \u2014 the grant we recommend \u2014 leaves the claim open. List the prefix", json2);
|
|
53775
|
+
emitAside(` for ${where}, take the <token> off the object name, and run:`, json2);
|
|
53776
|
+
emitAside("", json2);
|
|
53777
|
+
emitAside(` lua drains confirm ${drain.id} --token <token>`, json2);
|
|
52452
53778
|
}
|
|
52453
53779
|
__name(bucketVerificationInstructions, "bucketVerificationInstructions");
|
|
52454
53780
|
function verificationInstructions(drain, headers, options) {
|
|
52455
53781
|
const type = drain.type;
|
|
52456
|
-
const
|
|
52457
|
-
emitAside("",
|
|
52458
|
-
emitAside("Before anything is delivered, Lua has to confirm you own this destination.",
|
|
53782
|
+
const json2 = options.json;
|
|
53783
|
+
emitAside("", json2);
|
|
53784
|
+
emitAside("Before anything is delivered, Lua has to confirm you own this destination.", json2);
|
|
52459
53785
|
if (type === "s3") {
|
|
52460
|
-
bucketVerificationInstructions(drain,
|
|
53786
|
+
bucketVerificationInstructions(drain, json2);
|
|
52461
53787
|
return;
|
|
52462
53788
|
}
|
|
52463
53789
|
if (TOKEN_ECHO_TYPES.includes(type)) {
|
|
52464
|
-
emitAside("Lua POSTs one record carrying an X-Lua-Verify header; your receiver must answer 2xx AND",
|
|
52465
|
-
emitAside("repeat that header back on the response. Check yours first:",
|
|
53790
|
+
emitAside("Lua POSTs one record carrying an X-Lua-Verify header; your receiver must answer 2xx AND", json2);
|
|
53791
|
+
emitAside("repeat that header back on the response. Check yours first:", json2);
|
|
52466
53792
|
} else {
|
|
52467
|
-
emitAside("Lua POSTs one record to the intake; any 2xx from the vendor verifies the drain.",
|
|
52468
|
-
emitAside("Check the credentials reach the intake first:",
|
|
53793
|
+
emitAside("Lua POSTs one record to the intake; any 2xx from the vendor verifies the drain.", json2);
|
|
53794
|
+
emitAside("Check the credentials reach the intake first:", json2);
|
|
52469
53795
|
}
|
|
52470
|
-
emitAside("",
|
|
52471
|
-
for (const line of verificationCurl(type, drain.endpoint, headers)) emitAside(` ${line}`,
|
|
52472
|
-
emitAside("",
|
|
52473
|
-
emitAside(`Then: lua drains verify ${drain.id}`,
|
|
53796
|
+
emitAside("", json2);
|
|
53797
|
+
for (const line of verificationCurl(type, drain.endpoint, headers)) emitAside(` ${line}`, json2);
|
|
53798
|
+
emitAside("", json2);
|
|
53799
|
+
emitAside(`Then: lua drains verify ${drain.id}`, json2);
|
|
52474
53800
|
}
|
|
52475
53801
|
__name(verificationInstructions, "verificationInstructions");
|
|
52476
53802
|
async function createDrainCore(context, options) {
|
|
@@ -54662,7 +55988,7 @@ import chalk3 from "chalk";
|
|
|
54662
55988
|
import { existsSync as existsSync10, readFileSync as readFileSync13 } from "fs";
|
|
54663
55989
|
import { join as join10 } from "path";
|
|
54664
55990
|
import { performance } from "perf_hooks";
|
|
54665
|
-
import * as
|
|
55991
|
+
import * as os2 from "os";
|
|
54666
55992
|
init_semver();
|
|
54667
55993
|
init_version_check();
|
|
54668
55994
|
init_constants();
|
|
@@ -54702,9 +56028,9 @@ function gatherEnvironment(currentVersion) {
|
|
|
54702
56028
|
cliVersion: currentVersion,
|
|
54703
56029
|
channel: detectChannel(currentVersion),
|
|
54704
56030
|
nodeVersion: process.version,
|
|
54705
|
-
platform:
|
|
54706
|
-
arch:
|
|
54707
|
-
osRelease:
|
|
56031
|
+
platform: os2.platform(),
|
|
56032
|
+
arch: os2.arch(),
|
|
56033
|
+
osRelease: os2.release(),
|
|
54708
56034
|
installMethod: detectInstallMethod(process.execPath),
|
|
54709
56035
|
execPath: process.execPath,
|
|
54710
56036
|
configDir: CLI_CONFIG_DIR,
|
|
@@ -56220,12 +57546,12 @@ function resolveTrigger(triggers, ref) {
|
|
|
56220
57546
|
return trigger;
|
|
56221
57547
|
}
|
|
56222
57548
|
__name(resolveTrigger, "resolveTrigger");
|
|
56223
|
-
function displayTriggersCore(triggers,
|
|
57549
|
+
function displayTriggersCore(triggers, json2) {
|
|
56224
57550
|
trackEvent("cli_triggers_list", {
|
|
56225
57551
|
triggers_count: triggers.length,
|
|
56226
|
-
json_output:
|
|
57552
|
+
json_output: json2
|
|
56227
57553
|
});
|
|
56228
|
-
if (
|
|
57554
|
+
if (json2) {
|
|
56229
57555
|
console.log(JSON.stringify(triggers.map((t) => ({
|
|
56230
57556
|
id: t.id,
|
|
56231
57557
|
name: t.name,
|
|
@@ -56373,7 +57699,7 @@ function snippet(value3, maxLength = 100) {
|
|
|
56373
57699
|
return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
|
|
56374
57700
|
}
|
|
56375
57701
|
__name(snippet, "snippet");
|
|
56376
|
-
async function fetchAndDisplayLogsCore(context, trigger, limit,
|
|
57702
|
+
async function fetchAndDisplayLogsCore(context, trigger, limit, json2) {
|
|
56377
57703
|
const triggerApi = triggerApiFor(context);
|
|
56378
57704
|
const response = await triggerApi.getTriggerExecutions(trigger.id, {
|
|
56379
57705
|
limit
|
|
@@ -56381,7 +57707,7 @@ async function fetchAndDisplayLogsCore(context, trigger, limit, json) {
|
|
|
56381
57707
|
trackEvent("cli_triggers_logs", {
|
|
56382
57708
|
trigger_name: trigger.name,
|
|
56383
57709
|
limit,
|
|
56384
|
-
json_output:
|
|
57710
|
+
json_output: json2,
|
|
56385
57711
|
success: !!response.success
|
|
56386
57712
|
});
|
|
56387
57713
|
if (!response.success || !response.data) {
|
|
@@ -56389,7 +57715,7 @@ async function fetchAndDisplayLogsCore(context, trigger, limit, json) {
|
|
|
56389
57715
|
return false;
|
|
56390
57716
|
}
|
|
56391
57717
|
const { executions = [], total } = response.data;
|
|
56392
|
-
if (
|
|
57718
|
+
if (json2) {
|
|
56393
57719
|
console.log(JSON.stringify(response.data, null, 2));
|
|
56394
57720
|
return true;
|
|
56395
57721
|
}
|
|
@@ -57971,9 +59297,9 @@ init_lua_fetch();
|
|
|
57971
59297
|
init_compiler();
|
|
57972
59298
|
init_types();
|
|
57973
59299
|
init_cli_error();
|
|
57974
|
-
import
|
|
57975
|
-
import
|
|
57976
|
-
import
|
|
59300
|
+
import fs20 from "fs";
|
|
59301
|
+
import os3 from "os";
|
|
59302
|
+
import path28 from "path";
|
|
57977
59303
|
var EXPORT_NOT_COMPILABLE = "export-not-compilable";
|
|
57978
59304
|
var EXPORT_CHECK_TSCONFIG = {
|
|
57979
59305
|
compilerOptions: {
|
|
@@ -57994,13 +59320,13 @@ var EXPORT_CHECK_TSCONFIG = {
|
|
|
57994
59320
|
]
|
|
57995
59321
|
};
|
|
57996
59322
|
async function dryCompileWorkflowExport(files) {
|
|
57997
|
-
const root =
|
|
59323
|
+
const root = fs20.mkdtempSync(path28.join(os3.tmpdir(), "lua-workflows-export-"));
|
|
57998
59324
|
const issues = [];
|
|
57999
59325
|
const workflows = [];
|
|
58000
59326
|
try {
|
|
58001
|
-
|
|
59327
|
+
fs20.writeFileSync(path28.join(root, "tsconfig.json"), `${JSON.stringify(EXPORT_CHECK_TSCONFIG, null, 2)}
|
|
58002
59328
|
`);
|
|
58003
|
-
|
|
59329
|
+
fs20.writeFileSync(path28.join(root, "package.json"), `${JSON.stringify({
|
|
58004
59330
|
name: "lua-workflows-export-check",
|
|
58005
59331
|
version: "0.0.0",
|
|
58006
59332
|
private: true,
|
|
@@ -58008,23 +59334,23 @@ async function dryCompileWorkflowExport(files) {
|
|
|
58008
59334
|
}, null, 2)}
|
|
58009
59335
|
`);
|
|
58010
59336
|
for (const f of files) {
|
|
58011
|
-
const target =
|
|
58012
|
-
if (!target.startsWith(root +
|
|
58013
|
-
|
|
59337
|
+
const target = path28.resolve(root, f.path);
|
|
59338
|
+
if (!target.startsWith(root + path28.sep)) continue;
|
|
59339
|
+
fs20.mkdirSync(path28.dirname(target), {
|
|
58014
59340
|
recursive: true
|
|
58015
59341
|
});
|
|
58016
|
-
|
|
59342
|
+
fs20.writeFileSync(target, f.contents);
|
|
58017
59343
|
}
|
|
58018
59344
|
const result = await new Compiler({
|
|
58019
59345
|
rootDir: root,
|
|
58020
|
-
outDir:
|
|
59346
|
+
outDir: path28.join(root, "dist-v2"),
|
|
58021
59347
|
minify: false,
|
|
58022
59348
|
sourceMaps: false,
|
|
58023
59349
|
quietWarnings: true,
|
|
58024
59350
|
runtimeValidation: false
|
|
58025
59351
|
}).compile();
|
|
58026
59352
|
for (const e of result.errors) {
|
|
58027
|
-
const file = e.file ?
|
|
59353
|
+
const file = e.file ? path28.relative(root, e.file) : void 0;
|
|
58028
59354
|
const where = file ? `${file}${e.line ? `:${e.line}` : ""}` : void 0;
|
|
58029
59355
|
issues.push({
|
|
58030
59356
|
code: EXPORT_NOT_COMPILABLE,
|
|
@@ -58059,7 +59385,7 @@ async function dryCompileWorkflowExport(files) {
|
|
|
58059
59385
|
});
|
|
58060
59386
|
} finally {
|
|
58061
59387
|
if (debugEnabled()) console.error(`\u{1F41B} export check project kept at ${root}`);
|
|
58062
|
-
else
|
|
59388
|
+
else fs20.rmSync(root, {
|
|
58063
59389
|
recursive: true,
|
|
58064
59390
|
force: true
|
|
58065
59391
|
});
|
|
@@ -58114,7 +59440,7 @@ async function workflowsCommand(action, target, extra, cmdObj) {
|
|
|
58114
59440
|
const options = {
|
|
58115
59441
|
...cmdObj ?? {}
|
|
58116
59442
|
};
|
|
58117
|
-
const
|
|
59443
|
+
const json2 = !!options.json;
|
|
58118
59444
|
let resolved;
|
|
58119
59445
|
if (action) {
|
|
58120
59446
|
resolved = validateOrSuggest("workflows.action", action);
|
|
@@ -58157,14 +59483,14 @@ async function workflowsCommand(action, target, extra, cmdObj) {
|
|
|
58157
59483
|
return;
|
|
58158
59484
|
}
|
|
58159
59485
|
const { agentId, orgId, apiKey } = await initializeCommand({
|
|
58160
|
-
showProgress: !
|
|
59486
|
+
showProgress: !json2
|
|
58161
59487
|
});
|
|
58162
59488
|
const ctx = {
|
|
58163
59489
|
agentId,
|
|
58164
59490
|
orgId,
|
|
58165
59491
|
apiKey,
|
|
58166
59492
|
api: new WorkflowApi(BASE_URLS.API, apiKey, agentId),
|
|
58167
|
-
json
|
|
59493
|
+
json: json2
|
|
58168
59494
|
};
|
|
58169
59495
|
const code = await executeAction(ctx, resolved, target, extra, options);
|
|
58170
59496
|
if (code !== void 0 && code !== 0) process.exitCode = code;
|
|
@@ -59914,15 +61240,15 @@ function actorLabel(by, now = Date.now()) {
|
|
|
59914
61240
|
return Number.isFinite(at) ? `${who} (${agoFrom(at, now)})` : who;
|
|
59915
61241
|
}
|
|
59916
61242
|
__name(actorLabel, "actorLabel");
|
|
59917
|
-
function reservedSecretKeyPaths(value3,
|
|
61243
|
+
function reservedSecretKeyPaths(value3, path30 = "", depth = 0, out = []) {
|
|
59918
61244
|
if (depth > 64 || out.length >= 20 || value3 === null || typeof value3 !== "object") return out;
|
|
59919
61245
|
if (Array.isArray(value3)) {
|
|
59920
|
-
value3.forEach((v, i) => reservedSecretKeyPaths(v, `${
|
|
61246
|
+
value3.forEach((v, i) => reservedSecretKeyPaths(v, `${path30}[${i}]`, depth + 1, out));
|
|
59921
61247
|
return out;
|
|
59922
61248
|
}
|
|
59923
61249
|
for (const [k, v] of Object.entries(value3)) {
|
|
59924
61250
|
if (out.length >= 20) break;
|
|
59925
|
-
const child =
|
|
61251
|
+
const child = path30 ? `${path30}.${k}` : k;
|
|
59926
61252
|
if (isWorkflowSecretKey(k) && v !== null && v !== void 0 && typeof v !== "object") out.push(child);
|
|
59927
61253
|
else reservedSecretKeyPaths(v, child, depth + 1, out);
|
|
59928
61254
|
}
|
|
@@ -60382,11 +61708,11 @@ async function exportCore(ctx, name, o) {
|
|
|
60382
61708
|
if (!ctx.json && res.error?.statusCode === 404 && code === "VERSION_NOT_FOUND") console.error(`\u274C "${wf.name}" has no active version to export \u2014 pass -v <version|latest>`);
|
|
60383
61709
|
return apiFailure(ctx, res, "export");
|
|
60384
61710
|
}
|
|
60385
|
-
const
|
|
60386
|
-
const
|
|
60387
|
-
const outDir =
|
|
61711
|
+
const fs22 = await import("fs");
|
|
61712
|
+
const path30 = await import("path");
|
|
61713
|
+
const outDir = path30.resolve(o.out ?? ".");
|
|
60388
61714
|
const d = res.data;
|
|
60389
|
-
const escaping = d.files.filter((f) => !
|
|
61715
|
+
const escaping = d.files.filter((f) => !path30.resolve(outDir, f.path).startsWith(outDir + path30.sep));
|
|
60390
61716
|
if (escaping.length > 0) {
|
|
60391
61717
|
if (ctx.json) {
|
|
60392
61718
|
emitJson(ctx, {
|
|
@@ -60445,17 +61771,17 @@ async function exportCore(ctx, name, o) {
|
|
|
60445
61771
|
}, null, 2));
|
|
60446
61772
|
return WORKFLOW_EXIT.OK;
|
|
60447
61773
|
}
|
|
60448
|
-
const clash = d.files.filter((f) =>
|
|
61774
|
+
const clash = d.files.filter((f) => fs22.existsSync(path30.join(outDir, f.path)));
|
|
60449
61775
|
if (clash.length > 0 && !o.force) {
|
|
60450
61776
|
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>`);
|
|
60451
61777
|
return WORKFLOW_EXIT.API;
|
|
60452
61778
|
}
|
|
60453
61779
|
for (const f of d.files) {
|
|
60454
|
-
const target =
|
|
60455
|
-
|
|
61780
|
+
const target = path30.join(outDir, f.path);
|
|
61781
|
+
fs22.mkdirSync(path30.dirname(target), {
|
|
60456
61782
|
recursive: true
|
|
60457
61783
|
});
|
|
60458
|
-
|
|
61784
|
+
fs22.writeFileSync(target, f.contents);
|
|
60459
61785
|
console.log(` ${f.path}`);
|
|
60460
61786
|
}
|
|
60461
61787
|
const written = `exported "${wf.name}" v${d.version} (${d.form} form) \u2014 ${d.files.length} file(s) under ${outDir}`;
|
|
@@ -60495,9 +61821,9 @@ var archiveDownload = {
|
|
|
60495
61821
|
}, "fetchBytes")
|
|
60496
61822
|
};
|
|
60497
61823
|
async function archiveRunsCore(ctx, o) {
|
|
60498
|
-
const
|
|
60499
|
-
const
|
|
60500
|
-
const
|
|
61824
|
+
const fs22 = await import("fs");
|
|
61825
|
+
const path30 = await import("path");
|
|
61826
|
+
const crypto6 = await import("crypto");
|
|
60501
61827
|
const now = Date.now();
|
|
60502
61828
|
const since = parseSinceFlag(o.since, now);
|
|
60503
61829
|
if (!Number.isFinite(since)) {
|
|
@@ -60527,13 +61853,13 @@ async function archiveRunsCore(ctx, o) {
|
|
|
60527
61853
|
if (!wf) return WORKFLOW_EXIT.NOT_FOUND;
|
|
60528
61854
|
workflowId = wf.id;
|
|
60529
61855
|
}
|
|
60530
|
-
|
|
61856
|
+
fs22.mkdirSync(o.out, {
|
|
60531
61857
|
recursive: true
|
|
60532
61858
|
});
|
|
60533
|
-
const indexFile =
|
|
61859
|
+
const indexFile = path30.join(o.out, "archive-index.ndjson");
|
|
60534
61860
|
const indexed = /* @__PURE__ */ new Map();
|
|
60535
|
-
if (
|
|
60536
|
-
for (const line of
|
|
61861
|
+
if (fs22.existsSync(indexFile)) {
|
|
61862
|
+
for (const line of fs22.readFileSync(indexFile, "utf8").split("\n")) {
|
|
60537
61863
|
if (!line.trim()) continue;
|
|
60538
61864
|
try {
|
|
60539
61865
|
const row2 = JSON.parse(line);
|
|
@@ -60578,17 +61904,17 @@ async function archiveRunsCore(ctx, o) {
|
|
|
60578
61904
|
const say = /* @__PURE__ */ __name((line) => {
|
|
60579
61905
|
if (!ctx.json) console.log(line);
|
|
60580
61906
|
}, "say");
|
|
60581
|
-
const sha256 = /* @__PURE__ */ __name((buf) =>
|
|
61907
|
+
const sha256 = /* @__PURE__ */ __name((buf) => crypto6.createHash("sha256").update(buf).digest("hex"), "sha256");
|
|
60582
61908
|
const sleep4 = /* @__PURE__ */ __name((ms) => new Promise((r) => setTimeout(r, ms)), "sleep");
|
|
60583
61909
|
const archiveOne = /* @__PURE__ */ __name(async (apiRow) => {
|
|
60584
61910
|
const run = {
|
|
60585
61911
|
...apiRow,
|
|
60586
61912
|
id: runIdOf(apiRow)
|
|
60587
61913
|
};
|
|
60588
|
-
const zipFile =
|
|
61914
|
+
const zipFile = path30.join(o.out, `${run.id}.zip`);
|
|
60589
61915
|
const prior = indexed.get(run.id);
|
|
60590
61916
|
const completedAt = run.completedAt ? Date.parse(run.completedAt) : NaN;
|
|
60591
|
-
if (prior && run.exportedAt && Number.isFinite(completedAt) && Date.parse(run.exportedAt) >= completedAt &&
|
|
61917
|
+
if (prior && run.exportedAt && Number.isFinite(completedAt) && Date.parse(run.exportedAt) >= completedAt && fs22.existsSync(zipFile) && sha256(fs22.readFileSync(zipFile)) === prior.sha256) {
|
|
60592
61918
|
report2.skipped.push(run.id);
|
|
60593
61919
|
say(` ${run.id} \xB7 skipped (archived ${prior.exportId}, sha256 matches)`);
|
|
60594
61920
|
return;
|
|
@@ -60683,7 +62009,7 @@ async function archiveRunsCore(ctx, o) {
|
|
|
60683
62009
|
say(` ${run.id} \xB7 failed (sha256 mismatch)`);
|
|
60684
62010
|
return;
|
|
60685
62011
|
}
|
|
60686
|
-
|
|
62012
|
+
fs22.writeFileSync(zipFile, bytes);
|
|
60687
62013
|
const row2 = {
|
|
60688
62014
|
runId: run.id,
|
|
60689
62015
|
workflowId: run.workflowId,
|
|
@@ -60692,7 +62018,7 @@ async function archiveRunsCore(ctx, o) {
|
|
|
60692
62018
|
sha256: digest,
|
|
60693
62019
|
bytes: bytes.length
|
|
60694
62020
|
};
|
|
60695
|
-
|
|
62021
|
+
fs22.appendFileSync(indexFile, `${JSON.stringify(row2)}
|
|
60696
62022
|
`);
|
|
60697
62023
|
indexed.set(run.id, row2);
|
|
60698
62024
|
report2.archived.push(run.id);
|
|
@@ -61453,10 +62779,10 @@ function parseJudgePredicateFlag(raw) {
|
|
|
61453
62779
|
} : {}
|
|
61454
62780
|
};
|
|
61455
62781
|
}
|
|
61456
|
-
const [
|
|
61457
|
-
if (!
|
|
62782
|
+
const [path30, op, ...rest] = raw.trim().split(/\s+/);
|
|
62783
|
+
if (!path30 || !op || !GOAL_PREDICATE_OPS.includes(op)) throw new WorkflowLocalUsageError("usage", `--judge-predicate: expected "<path> <op> [value]" with op ${opList} (got "${raw}")`);
|
|
61458
62784
|
if (rest.length === 0) return {
|
|
61459
|
-
path:
|
|
62785
|
+
path: path30,
|
|
61460
62786
|
op
|
|
61461
62787
|
};
|
|
61462
62788
|
const text = rest.join(" ");
|
|
@@ -61466,7 +62792,7 @@ function parseJudgePredicateFlag(raw) {
|
|
|
61466
62792
|
} catch {
|
|
61467
62793
|
}
|
|
61468
62794
|
return {
|
|
61469
|
-
path:
|
|
62795
|
+
path: path30,
|
|
61470
62796
|
op,
|
|
61471
62797
|
value: value3
|
|
61472
62798
|
};
|
|
@@ -64049,8 +65375,12 @@ var TemplateApiService = class {
|
|
|
64049
65375
|
body: JSON.stringify(data)
|
|
64050
65376
|
});
|
|
64051
65377
|
}
|
|
64052
|
-
|
|
64053
|
-
|
|
65378
|
+
/**
|
|
65379
|
+
* PRO-2201 — the catalog hides never-published templates; `includeUnpublished`
|
|
65380
|
+
* (the template picker only) also lists the caller's own-org unpublished ones.
|
|
65381
|
+
*/
|
|
65382
|
+
async listTemplates(opts = {}) {
|
|
65383
|
+
return this._fetch(`/marketplace/templates${opts.includeUnpublished ? "?includeUnpublished=true" : ""}`);
|
|
64054
65384
|
}
|
|
64055
65385
|
async getTemplate(templateId) {
|
|
64056
65386
|
return this._fetch(`/marketplace/templates/${templateId}`);
|
|
@@ -64251,10 +65581,12 @@ function missingVersionOrRethrow(error) {
|
|
|
64251
65581
|
throw error;
|
|
64252
65582
|
}
|
|
64253
65583
|
__name(missingVersionOrRethrow, "missingVersionOrRethrow");
|
|
64254
|
-
async function resolveTemplateId(templateApi, options, message) {
|
|
65584
|
+
async function resolveTemplateId(templateApi, options, message, includeUnpublished) {
|
|
64255
65585
|
if (options.templateId) return options.templateId;
|
|
64256
65586
|
writeProgress("\u{1F504} Loading your templates...");
|
|
64257
|
-
const { templates } = await templateApi.listTemplates(
|
|
65587
|
+
const { templates } = await templateApi.listTemplates({
|
|
65588
|
+
includeUnpublished
|
|
65589
|
+
});
|
|
64258
65590
|
if (!templates.length) {
|
|
64259
65591
|
throw new Error("You haven't created any templates yet. Run `lua marketplace template create` first.");
|
|
64260
65592
|
}
|
|
@@ -64476,7 +65808,7 @@ __name(templateCreateAction, "templateCreateAction");
|
|
|
64476
65808
|
async function templateDraftAction(templateApi, options) {
|
|
64477
65809
|
const config = readYamlConfig();
|
|
64478
65810
|
if (!config) throw new Error("No lua.skill.yaml found in this directory.");
|
|
64479
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to draft for?");
|
|
65811
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to draft for?", true);
|
|
64480
65812
|
const sourceAgentVersion = options.sourceVersion ? Number.parseInt(options.sourceVersion, 10) : void 0;
|
|
64481
65813
|
if (options.sourceVersion && (!Number.isFinite(sourceAgentVersion) || sourceAgentVersion <= 0)) {
|
|
64482
65814
|
throw new Error(`Invalid --source-version "${options.sourceVersion}": must be a positive integer.`);
|
|
@@ -64595,7 +65927,7 @@ async function confirmTemplateSectionConsequences(templateApi, templateId, local
|
|
|
64595
65927
|
}
|
|
64596
65928
|
__name(confirmTemplateSectionConsequences, "confirmTemplateSectionConsequences");
|
|
64597
65929
|
async function templatePublishAction(templateApi, config, options) {
|
|
64598
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to publish a version for?");
|
|
65930
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to publish a version for?", true);
|
|
64599
65931
|
const sourceAgentVersion = options.sourceVersion ? Number.parseInt(options.sourceVersion, 10) : void 0;
|
|
64600
65932
|
if (options.sourceVersion && (!Number.isFinite(sourceAgentVersion) || sourceAgentVersion <= 0)) {
|
|
64601
65933
|
throw new Error(`Invalid --source-version "${options.sourceVersion}": must be a positive integer.`);
|
|
@@ -64637,19 +65969,27 @@ async function templatePublishAction(templateApi, config, options) {
|
|
|
64637
65969
|
selfAudit: templateSection.selfAudit
|
|
64638
65970
|
} : {}
|
|
64639
65971
|
});
|
|
65972
|
+
const personaWarning = personaWarningLine(version, templateId);
|
|
64640
65973
|
if (options.json) {
|
|
64641
65974
|
console.log(JSON.stringify(version, null, 2));
|
|
65975
|
+
if (personaWarning) console.warn(personaWarning);
|
|
64642
65976
|
return;
|
|
64643
65977
|
}
|
|
64644
65978
|
writeSuccess(`\u2705 Published v${version.version}`);
|
|
64645
65979
|
writeInfo(`Frozen from agent version v${version.sourceAgentVersion}`);
|
|
64646
65980
|
writeInfo(autoApplyLine(version, options.skipAutoApply === true));
|
|
65981
|
+
if (personaWarning) writeInfo(personaWarning);
|
|
64647
65982
|
console.log("\nManifest:");
|
|
64648
65983
|
printManifestSummary(version.content);
|
|
64649
65984
|
const envCount = version.envContract ? Object.keys(version.envContract).length : 0;
|
|
64650
65985
|
console.log(` Env contract: ${envCount} var(s)`);
|
|
64651
65986
|
}
|
|
64652
65987
|
__name(templatePublishAction, "templatePublishAction");
|
|
65988
|
+
function personaWarningLine(version, templateId) {
|
|
65989
|
+
if (version.personaTemplate) return void 0;
|
|
65990
|
+
return `\u26A0\uFE0F No persona template on v${version.version}: installs will run on the stock placeholder persona, not the source agent's. Compose one with \`lua marketplace template draft --template-id ${templateId}\`, then publish again.`;
|
|
65991
|
+
}
|
|
65992
|
+
__name(personaWarningLine, "personaWarningLine");
|
|
64653
65993
|
function autoApplyLine(version, skipped) {
|
|
64654
65994
|
if (skipped) return "Auto-update: skipped (--skip-auto-apply)";
|
|
64655
65995
|
if (version.autoApplyRunId) {
|
|
@@ -64661,7 +66001,7 @@ function autoApplyLine(version, skipped) {
|
|
|
64661
66001
|
}
|
|
64662
66002
|
__name(autoApplyLine, "autoApplyLine");
|
|
64663
66003
|
async function templateViewAction(templateApi, options) {
|
|
64664
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to view?");
|
|
66004
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to view?", true);
|
|
64665
66005
|
if (options.version) {
|
|
64666
66006
|
const versionNum = Number.parseInt(options.version, 10);
|
|
64667
66007
|
if (!Number.isFinite(versionNum) || versionNum <= 0) {
|
|
@@ -64706,7 +66046,7 @@ ${"=".repeat(60)}
|
|
|
64706
66046
|
}
|
|
64707
66047
|
__name(templateViewAction, "templateViewAction");
|
|
64708
66048
|
async function templateVersionsAction(templateApi, options) {
|
|
64709
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template\u2019s versions would you like to see?");
|
|
66049
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template\u2019s versions would you like to see?", true);
|
|
64710
66050
|
const versions = await templateApi.getVersions(templateId);
|
|
64711
66051
|
if (options.json) {
|
|
64712
66052
|
console.log(JSON.stringify(versions, null, 2));
|
|
@@ -64728,7 +66068,7 @@ __name(templateVersionsAction, "templateVersionsAction");
|
|
|
64728
66068
|
async function templateInstallAction(templateApi, config, options) {
|
|
64729
66069
|
const agentId = config.agent?.agentId;
|
|
64730
66070
|
if (!agentId) throw new Error("Agent ID not found in configuration.");
|
|
64731
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to install?");
|
|
66071
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to install?", false);
|
|
64732
66072
|
const version = options.version ? Number.parseInt(options.version, 10) : void 0;
|
|
64733
66073
|
const envValues = options.envVars ? parseKeyValuePairs(options.envVars) : void 0;
|
|
64734
66074
|
if (!options.force) {
|
|
@@ -64812,7 +66152,7 @@ function resolveApplyTargets(options) {
|
|
|
64812
66152
|
}
|
|
64813
66153
|
__name(resolveApplyTargets, "resolveApplyTargets");
|
|
64814
66154
|
async function templateApplyAction(templateApi, options) {
|
|
64815
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to apply?");
|
|
66155
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to apply?", false);
|
|
64816
66156
|
let targets = resolveApplyTargets(options);
|
|
64817
66157
|
if (!targets && options.allInstalled) {
|
|
64818
66158
|
writeProgress("\u{1F504} Loading install ledger...");
|
|
@@ -64899,7 +66239,7 @@ Apply run ${run.status} (${run.id})`);
|
|
|
64899
66239
|
}
|
|
64900
66240
|
__name(templateApplyAction, "templateApplyAction");
|
|
64901
66241
|
async function templateHealthAction(templateApi, options) {
|
|
64902
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template\u2019s fleet health would you like?");
|
|
66242
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template\u2019s fleet health would you like?", true);
|
|
64903
66243
|
const windowDays = options.windowDays !== void 0 ? parseInt(options.windowDays, 10) : void 0;
|
|
64904
66244
|
if (windowDays !== void 0 && (!Number.isFinite(windowDays) || windowDays < 1)) {
|
|
64905
66245
|
throw new Error("--window-days must be a positive integer");
|
|
@@ -64970,7 +66310,7 @@ async function templateHealthAction(templateApi, options) {
|
|
|
64970
66310
|
}
|
|
64971
66311
|
__name(templateHealthAction, "templateHealthAction");
|
|
64972
66312
|
async function templateStatusAction(templateApi, options) {
|
|
64973
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template\u2019s fleet status would you like to see?");
|
|
66313
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template\u2019s fleet status would you like to see?", true);
|
|
64974
66314
|
const installs = await templateApi.getAllInstalls(templateId);
|
|
64975
66315
|
if (options.json) {
|
|
64976
66316
|
console.log(JSON.stringify(installs, null, 2));
|
|
@@ -65038,7 +66378,7 @@ __name(templateInstalledAction, "templateInstalledAction");
|
|
|
65038
66378
|
async function templateUninstallAction(templateApi, config, options) {
|
|
65039
66379
|
const agentId = config.agent?.agentId;
|
|
65040
66380
|
if (!agentId) throw new Error("Agent ID not found in configuration.");
|
|
65041
|
-
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to uninstall?");
|
|
66381
|
+
const templateId = await resolveTemplateId(templateApi, options, "Which template would you like to uninstall?", false);
|
|
65042
66382
|
if (!options.force) {
|
|
65043
66383
|
throw CliError.usage("This action requires --force to confirm", `Use --force to confirm uninstalling template ${templateId} from this agent`);
|
|
65044
66384
|
}
|
|
@@ -71384,13 +72724,13 @@ function hasSox() {
|
|
|
71384
72724
|
}
|
|
71385
72725
|
__name(hasSox, "hasSox");
|
|
71386
72726
|
function detectSoxInstaller() {
|
|
71387
|
-
const
|
|
72727
|
+
const os4 = platform3();
|
|
71388
72728
|
const has3 = /* @__PURE__ */ __name((bin) => spawnSync(bin, [
|
|
71389
72729
|
"--version"
|
|
71390
72730
|
], {
|
|
71391
72731
|
stdio: "ignore"
|
|
71392
72732
|
}).status === 0, "has");
|
|
71393
|
-
if (
|
|
72733
|
+
if (os4 === "darwin") {
|
|
71394
72734
|
if (has3("brew")) return {
|
|
71395
72735
|
manager: "Homebrew",
|
|
71396
72736
|
argv: [
|
|
@@ -71401,7 +72741,7 @@ function detectSoxInstaller() {
|
|
|
71401
72741
|
};
|
|
71402
72742
|
return null;
|
|
71403
72743
|
}
|
|
71404
|
-
if (
|
|
72744
|
+
if (os4 === "linux") {
|
|
71405
72745
|
if (has3("apt-get")) return {
|
|
71406
72746
|
manager: "apt",
|
|
71407
72747
|
argv: [
|
|
@@ -71469,7 +72809,7 @@ function detectSoxInstaller() {
|
|
|
71469
72809
|
};
|
|
71470
72810
|
return null;
|
|
71471
72811
|
}
|
|
71472
|
-
if (
|
|
72812
|
+
if (os4 === "win32") {
|
|
71473
72813
|
if (has3("winget")) return {
|
|
71474
72814
|
manager: "winget",
|
|
71475
72815
|
argv: [
|
|
@@ -72246,7 +73586,7 @@ function findVoiceTestFiles(root) {
|
|
|
72246
73586
|
".lua",
|
|
72247
73587
|
"coverage"
|
|
72248
73588
|
]);
|
|
72249
|
-
const
|
|
73589
|
+
const walk4 = /* @__PURE__ */ __name((dir) => {
|
|
72250
73590
|
let entries;
|
|
72251
73591
|
try {
|
|
72252
73592
|
entries = readdirSync4(dir);
|
|
@@ -72263,13 +73603,13 @@ function findVoiceTestFiles(root) {
|
|
|
72263
73603
|
}
|
|
72264
73604
|
if (s.isDirectory()) {
|
|
72265
73605
|
if (skipDirs.has(entry)) continue;
|
|
72266
|
-
|
|
73606
|
+
walk4(full);
|
|
72267
73607
|
} else if (s.isFile() && /\.voice\.test\.(t|j)sx?$/.test(entry)) {
|
|
72268
73608
|
out.push(resolve6(full));
|
|
72269
73609
|
}
|
|
72270
73610
|
}
|
|
72271
73611
|
}, "walk");
|
|
72272
|
-
|
|
73612
|
+
walk4(root);
|
|
72273
73613
|
return out;
|
|
72274
73614
|
}
|
|
72275
73615
|
__name(findVoiceTestFiles, "findVoiceTestFiles");
|
|
@@ -72531,7 +73871,8 @@ async function versionListCommand(options = {}) {
|
|
|
72531
73871
|
createdByEmail: v.createdByEmail,
|
|
72532
73872
|
createdAt: v.createdAt,
|
|
72533
73873
|
commitHash: v.commitHash,
|
|
72534
|
-
sourceManifestVersion: v.sourceManifestVersion
|
|
73874
|
+
sourceManifestVersion: v.sourceManifestVersion,
|
|
73875
|
+
sourceDigest: v.sourceDigest
|
|
72535
73876
|
}));
|
|
72536
73877
|
console.log(JSON.stringify(summary, null, 2));
|
|
72537
73878
|
} else if (versions.length === 0) {
|
|
@@ -73290,6 +74631,284 @@ async function pullCommand(options = {}) {
|
|
|
73290
74631
|
}
|
|
73291
74632
|
__name(pullCommand, "pullCommand");
|
|
73292
74633
|
|
|
74634
|
+
// src/commands/apps.ts
|
|
74635
|
+
init_dist();
|
|
74636
|
+
init_cli();
|
|
74637
|
+
init_write_info();
|
|
74638
|
+
init_package_root();
|
|
74639
|
+
init_cli_error();
|
|
74640
|
+
init_analytics();
|
|
74641
|
+
import fs21 from "fs";
|
|
74642
|
+
import path29 from "path";
|
|
74643
|
+
import { IndentationText, Node as Node22, Project as Project5, QuoteKind, SyntaxKind } from "ts-morph";
|
|
74644
|
+
init_command_utils();
|
|
74645
|
+
init_artifact_loader();
|
|
74646
|
+
init_types();
|
|
74647
|
+
var WEB_APP_TEMPLATE_DIR = "template-web-app";
|
|
74648
|
+
var PAGES_EXCLUDE_GLOB = "src/apps/*/web";
|
|
74649
|
+
var NAME_PLACEHOLDER = "__APP_NAME__";
|
|
74650
|
+
function appIdentifier(name) {
|
|
74651
|
+
return name.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
74652
|
+
}
|
|
74653
|
+
__name(appIdentifier, "appIdentifier");
|
|
74654
|
+
function copyTemplate(from, to, name, written) {
|
|
74655
|
+
fs21.mkdirSync(to, {
|
|
74656
|
+
recursive: true
|
|
74657
|
+
});
|
|
74658
|
+
for (const entry of fs21.readdirSync(from, {
|
|
74659
|
+
withFileTypes: true
|
|
74660
|
+
})) {
|
|
74661
|
+
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
74662
|
+
const src = path29.join(from, entry.name);
|
|
74663
|
+
const dest = path29.join(to, entry.name);
|
|
74664
|
+
if (entry.isDirectory()) {
|
|
74665
|
+
copyTemplate(src, dest, name, written);
|
|
74666
|
+
} else {
|
|
74667
|
+
fs21.writeFileSync(dest, fs21.readFileSync(src, "utf8").split(NAME_PLACEHOLDER).join(name));
|
|
74668
|
+
written.push(dest);
|
|
74669
|
+
}
|
|
74670
|
+
}
|
|
74671
|
+
}
|
|
74672
|
+
__name(copyTemplate, "copyTemplate");
|
|
74673
|
+
function excludePagesFromTsconfig(projectRoot) {
|
|
74674
|
+
const file = path29.join(projectRoot, "tsconfig.json");
|
|
74675
|
+
if (!fs21.existsSync(file)) return "missing";
|
|
74676
|
+
let config;
|
|
74677
|
+
try {
|
|
74678
|
+
config = JSON.parse(fs21.readFileSync(file, "utf8"));
|
|
74679
|
+
} catch {
|
|
74680
|
+
return "unparsable";
|
|
74681
|
+
}
|
|
74682
|
+
const exclude = Array.isArray(config.exclude) ? config.exclude : [
|
|
74683
|
+
"node_modules"
|
|
74684
|
+
];
|
|
74685
|
+
if (exclude.includes(PAGES_EXCLUDE_GLOB)) return "present";
|
|
74686
|
+
config.exclude = [
|
|
74687
|
+
...exclude,
|
|
74688
|
+
PAGES_EXCLUDE_GLOB
|
|
74689
|
+
];
|
|
74690
|
+
fs21.writeFileSync(file, JSON.stringify(config, null, 2) + "\n");
|
|
74691
|
+
return "added";
|
|
74692
|
+
}
|
|
74693
|
+
__name(excludePagesFromTsconfig, "excludePagesFromTsconfig");
|
|
74694
|
+
function registerWebAppOnAgent(indexFile, name) {
|
|
74695
|
+
if (!fs21.existsSync(indexFile)) return "missing-index";
|
|
74696
|
+
const project = new Project5({
|
|
74697
|
+
skipAddingFilesFromTsConfig: true,
|
|
74698
|
+
// The style of the agent template (and of most agent code): single quotes, two spaces.
|
|
74699
|
+
manipulationSettings: {
|
|
74700
|
+
quoteKind: QuoteKind.Single,
|
|
74701
|
+
indentationText: IndentationText.TwoSpaces
|
|
74702
|
+
}
|
|
74703
|
+
});
|
|
74704
|
+
const sf = project.addSourceFileAtPath(indexFile);
|
|
74705
|
+
const agentNew = sf.getDescendantsOfKind(SyntaxKind.NewExpression).find((n2) => n2.getExpression().getText() === "LuaAgent");
|
|
74706
|
+
const config = agentNew?.getArguments()[0];
|
|
74707
|
+
if (!config || !Node22.isObjectLiteralExpression(config)) return "no-agent";
|
|
74708
|
+
const prop = config.getProperty("webApps");
|
|
74709
|
+
const list = prop && Node22.isPropertyAssignment(prop) ? prop.getInitializer() : void 0;
|
|
74710
|
+
if (prop && !(list && Node22.isArrayLiteralExpression(list))) return "webapps-not-array";
|
|
74711
|
+
const binding = appIdentifier(name);
|
|
74712
|
+
const specifier = `./apps/${name}/app`;
|
|
74713
|
+
if (!sf.getImportDeclaration((d) => d.getModuleSpecifierValue() === specifier)) {
|
|
74714
|
+
const last = sf.getImportDeclarations().at(-1);
|
|
74715
|
+
sf.insertImportDeclaration(last ? last.getChildIndex() + 1 : 0, {
|
|
74716
|
+
defaultImport: binding,
|
|
74717
|
+
moduleSpecifier: specifier
|
|
74718
|
+
});
|
|
74719
|
+
}
|
|
74720
|
+
if (list && Node22.isArrayLiteralExpression(list)) {
|
|
74721
|
+
if (!list.getElements().some((e) => e.getText() === binding)) list.addElement(binding);
|
|
74722
|
+
} else {
|
|
74723
|
+
config.addPropertyAssignment({
|
|
74724
|
+
name: "webApps",
|
|
74725
|
+
initializer: `[${binding}]`
|
|
74726
|
+
});
|
|
74727
|
+
}
|
|
74728
|
+
sf.saveSync();
|
|
74729
|
+
return "registered";
|
|
74730
|
+
}
|
|
74731
|
+
__name(registerWebAppOnAgent, "registerWebAppOnAgent");
|
|
74732
|
+
function scaffoldWebApp(projectRoot, name, templateRoot = getPackageRoot()) {
|
|
74733
|
+
if (!WEB_APP_NAME_PATTERN.test(name)) {
|
|
74734
|
+
throw CliError.usage(`App name must match ${WEB_APP_NAME_PATTERN} (lower-case letters, digits and dashes, starting with a letter); got ${JSON.stringify(name)}.`);
|
|
74735
|
+
}
|
|
74736
|
+
if (!fs21.existsSync(path29.join(projectRoot, "lua.skill.yaml"))) {
|
|
74737
|
+
throw CliError.usage("No lua.skill.yaml here: run `lua apps new` in the root of an agent project (`lua init` makes one).");
|
|
74738
|
+
}
|
|
74739
|
+
const appDir = path29.join(projectRoot, "src", "apps", name);
|
|
74740
|
+
if (fs21.existsSync(appDir)) {
|
|
74741
|
+
throw CliError.usage(`${path29.relative(projectRoot, appDir)} already exists; pick another name or delete it first.`);
|
|
74742
|
+
}
|
|
74743
|
+
const files = [];
|
|
74744
|
+
copyTemplate(path29.join(templateRoot, WEB_APP_TEMPLATE_DIR), appDir, name, files);
|
|
74745
|
+
return {
|
|
74746
|
+
appDir,
|
|
74747
|
+
files,
|
|
74748
|
+
registered: registerWebAppOnAgent(path29.join(projectRoot, "src", "index.ts"), name),
|
|
74749
|
+
tsconfig: excludePagesFromTsconfig(projectRoot)
|
|
74750
|
+
};
|
|
74751
|
+
}
|
|
74752
|
+
__name(scaffoldWebApp, "scaffoldWebApp");
|
|
74753
|
+
async function appsNewCommand(name) {
|
|
74754
|
+
return withErrorHandling(async () => {
|
|
74755
|
+
const projectRoot = process.cwd();
|
|
74756
|
+
const result = scaffoldWebApp(projectRoot, name);
|
|
74757
|
+
const rel = /* @__PURE__ */ __name((p) => path29.relative(projectRoot, p), "rel");
|
|
74758
|
+
for (const file of result.files) writeInfo(` created ${rel(file)}`);
|
|
74759
|
+
const binding = appIdentifier(name);
|
|
74760
|
+
const addLines = ` import ${binding} from './apps/${name}/app';
|
|
74761
|
+
webApps: [${binding}], (on your LuaAgent)`;
|
|
74762
|
+
switch (result.registered) {
|
|
74763
|
+
case "registered":
|
|
74764
|
+
writeInfo(` updated src/index.ts webApps: [${binding}]`);
|
|
74765
|
+
break;
|
|
74766
|
+
case "missing-index":
|
|
74767
|
+
writeInfo(` \u26A0\uFE0F No src/index.ts. Where your LuaAgent is defined, add:
|
|
74768
|
+
${addLines}`);
|
|
74769
|
+
break;
|
|
74770
|
+
case "no-agent":
|
|
74771
|
+
writeInfo(` \u26A0\uFE0F No \`new LuaAgent({...})\` in src/index.ts. Where your LuaAgent is defined, add:
|
|
74772
|
+
${addLines}`);
|
|
74773
|
+
break;
|
|
74774
|
+
case "webapps-not-array":
|
|
74775
|
+
writeInfo(` \u26A0\uFE0F \`webApps\` in src/index.ts is not an array literal, so it was left as is. Add ${binding} to it and:
|
|
74776
|
+
import ${binding} from './apps/${name}/app';`);
|
|
74777
|
+
break;
|
|
74778
|
+
}
|
|
74779
|
+
if (result.tsconfig === "added") writeInfo(` updated tsconfig.json exclude: "${PAGES_EXCLUDE_GLOB}"`);
|
|
74780
|
+
if (result.tsconfig === "unparsable" || result.tsconfig === "missing") {
|
|
74781
|
+
writeInfo(` \u26A0\uFE0F Add "${PAGES_EXCLUDE_GLOB}" to "exclude" in tsconfig.json so the agent compiler never loads the pages.`);
|
|
74782
|
+
}
|
|
74783
|
+
writeSuccess(`
|
|
74784
|
+
\u2705 Web app ${name} created`);
|
|
74785
|
+
writeHintBlock({
|
|
74786
|
+
headline: "Next:",
|
|
74787
|
+
lines: [
|
|
74788
|
+
{
|
|
74789
|
+
label: "Install pages:",
|
|
74790
|
+
command: `cd ${rel(path29.join(result.appDir, "web"))} && npm install`
|
|
74791
|
+
},
|
|
74792
|
+
{
|
|
74793
|
+
label: "Run locally:",
|
|
74794
|
+
command: `lua apps dev ${name}`
|
|
74795
|
+
},
|
|
74796
|
+
{
|
|
74797
|
+
label: "Ship:",
|
|
74798
|
+
command: `lua push webapp --name ${name}`
|
|
74799
|
+
}
|
|
74800
|
+
],
|
|
74801
|
+
when: "success"
|
|
74802
|
+
});
|
|
74803
|
+
trackEvent("cli_apps_new", {
|
|
74804
|
+
registered: result.registered,
|
|
74805
|
+
tsconfig: result.tsconfig
|
|
74806
|
+
});
|
|
74807
|
+
}, "apps new");
|
|
74808
|
+
}
|
|
74809
|
+
__name(appsNewCommand, "appsNewCommand");
|
|
74810
|
+
async function appsDevCommand(name, opts = {}) {
|
|
74811
|
+
return withErrorHandling(async () => {
|
|
74812
|
+
await compileCommand();
|
|
74813
|
+
const { apiKey, agentId, config } = await initializeCommand({
|
|
74814
|
+
showProgress: false
|
|
74815
|
+
});
|
|
74816
|
+
const find = /* @__PURE__ */ __name(() => getPrimitivesByKind(loadManifest(), PrimitiveKind.WEB_APP).find((a) => a.name === name), "find");
|
|
74817
|
+
const app = find();
|
|
74818
|
+
if (!app) {
|
|
74819
|
+
throw CliError.usage(`No web app named ${JSON.stringify(name)} in the compiled agent.`, `Create one with: lua apps new ${name} (and list it under \`webApps\` on your LuaAgent)`);
|
|
74820
|
+
}
|
|
74821
|
+
const appDir = path29.dirname(app.sourcePath);
|
|
74822
|
+
const pagesDir = path29.resolve(appDir, app.pagesRoot);
|
|
74823
|
+
const vite = await loadAppVite(pagesDir);
|
|
74824
|
+
if (!vite.createServer) throw new WebAppBuildError(`The Vite in ${pagesDir} exposes no createServer().`);
|
|
74825
|
+
const auth = await developerAuth(apiKey, agentId, config);
|
|
74826
|
+
const addedEnv = [];
|
|
74827
|
+
for (const [key, value3] of Object.entries(loadEnvironmentVariables2())) {
|
|
74828
|
+
if (process.env[key] === void 0) {
|
|
74829
|
+
process.env[key] = value3;
|
|
74830
|
+
addedEnv.push(key);
|
|
74831
|
+
}
|
|
74832
|
+
}
|
|
74833
|
+
let code = loadArtifact(app, process.cwd());
|
|
74834
|
+
let current = app;
|
|
74835
|
+
const ctx = /* @__PURE__ */ __name(() => ({
|
|
74836
|
+
app: current,
|
|
74837
|
+
appCode: /* @__PURE__ */ __name(() => code, "appCode"),
|
|
74838
|
+
auth,
|
|
74839
|
+
apiKey,
|
|
74840
|
+
agentId
|
|
74841
|
+
}), "ctx");
|
|
74842
|
+
let origin = "";
|
|
74843
|
+
const server = await vite.createServer({
|
|
74844
|
+
root: pagesDir,
|
|
74845
|
+
server: {
|
|
74846
|
+
port: opts.port ? Number(opts.port) : void 0
|
|
74847
|
+
},
|
|
74848
|
+
plugins: [
|
|
74849
|
+
luaAppsDevPlugin({
|
|
74850
|
+
context: ctx,
|
|
74851
|
+
origin: /* @__PURE__ */ __name(() => origin, "origin"),
|
|
74852
|
+
appDir,
|
|
74853
|
+
pagesDir,
|
|
74854
|
+
log: /* @__PURE__ */ __name((line, status) => (status >= 500 ? console.error : console.log)(` ${line}`), "log"),
|
|
74855
|
+
onRouteChange: /* @__PURE__ */ __name(async (file) => {
|
|
74856
|
+
writeInfo(`
|
|
74857
|
+
\u267B\uFE0F ${path29.relative(process.cwd(), file)} changed \u2014 recompiling routes...`);
|
|
74858
|
+
try {
|
|
74859
|
+
await compileCommand();
|
|
74860
|
+
const next = find();
|
|
74861
|
+
if (!next) throw new Error(`web app ${name} is gone from the compiled agent`);
|
|
74862
|
+
current = next;
|
|
74863
|
+
code = loadArtifact(next, process.cwd());
|
|
74864
|
+
writeSuccess("\u2705 Routes reloaded");
|
|
74865
|
+
} catch (error) {
|
|
74866
|
+
console.error(`\u274C Recompile failed; still serving the previous routes: ${error?.message}`);
|
|
74867
|
+
}
|
|
74868
|
+
}, "onRouteChange")
|
|
74869
|
+
})
|
|
74870
|
+
]
|
|
74871
|
+
});
|
|
74872
|
+
await server.listen();
|
|
74873
|
+
origin = server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") ?? "";
|
|
74874
|
+
writeSuccess(`
|
|
74875
|
+
\u2705 ${name} is running`);
|
|
74876
|
+
writeHintBlock({
|
|
74877
|
+
headline: "Lua apps dev:",
|
|
74878
|
+
lines: [
|
|
74879
|
+
{
|
|
74880
|
+
label: "Pages:",
|
|
74881
|
+
command: `${origin || "http://localhost"} (Vite, hot reload)`
|
|
74882
|
+
},
|
|
74883
|
+
{
|
|
74884
|
+
label: "Routes:",
|
|
74885
|
+
command: "/_lua/api/* \u2192 local sandbox, auth = you (Data and env() are live)"
|
|
74886
|
+
},
|
|
74887
|
+
{
|
|
74888
|
+
label: "Stop:",
|
|
74889
|
+
command: "Ctrl+C"
|
|
74890
|
+
}
|
|
74891
|
+
],
|
|
74892
|
+
when: "success"
|
|
74893
|
+
});
|
|
74894
|
+
trackEvent("cli_apps_dev", {
|
|
74895
|
+
routes: app.routes.length,
|
|
74896
|
+
hasFetch: app.hasFetch
|
|
74897
|
+
});
|
|
74898
|
+
await new Promise((resolve7) => {
|
|
74899
|
+
const stop = /* @__PURE__ */ __name(() => {
|
|
74900
|
+
process.off("SIGINT", stop);
|
|
74901
|
+
process.off("SIGTERM", stop);
|
|
74902
|
+
for (const key of addedEnv) delete process.env[key];
|
|
74903
|
+
void server.close().finally(resolve7);
|
|
74904
|
+
}, "stop");
|
|
74905
|
+
process.once("SIGINT", stop);
|
|
74906
|
+
process.once("SIGTERM", stop);
|
|
74907
|
+
});
|
|
74908
|
+
}, "apps dev");
|
|
74909
|
+
}
|
|
74910
|
+
__name(appsDevCommand, "appsDevCommand");
|
|
74911
|
+
|
|
73293
74912
|
// src/cli/command-definitions.ts
|
|
73294
74913
|
init_cli();
|
|
73295
74914
|
function collect(value3, previous) {
|
|
@@ -73465,7 +75084,7 @@ Examples:
|
|
|
73465
75084
|
...opts,
|
|
73466
75085
|
accept: opts.pull || opts.accept
|
|
73467
75086
|
}));
|
|
73468
|
-
program2.command("test [type]").description("\u{1F9EA} Test skills, webhooks, or jobs interactively").option("--name <name>", "Entity name to test").option("--input <json>", "JSON input string for testing").option("--json", "Output result as raw JSON (useful for scripting and piping)").option("--step-output <id=json>", "Workflow: complete a step with this output (repeatable)", collect, []).option("--approve <id[=@payload]>", "Workflow: pre-answer an approval (repeatable)", collect, []).option("--deny <id[=@reason]>", "Workflow: pre-deny an approval (repeatable)", collect, []).option("--signal <name=json>", "Workflow: pre-supply a waitForSignal payload (repeatable)", collect, []).option("--from-run <runId>", "Workflow: seed completed steps from a real run").option("--force", "Workflow: seed from a run whose graph differs").option("--record <dir>", "Workflow: record agent/tool outputs as fixtures").option("--fixtures <dir>", "Workflow: replay recorded fixtures (exit 5 when one is missing)").option("--step-wall <s>", "Workflow: per-step wall in seconds (default 600)").option("--job-wall <s>", "Workflow: virtual wall for tier:'job' steps \u2014 splits at 14400 s segments, > 86400 is exit 2").option("--max-ticks <n>", "Workflow (script form): tick cap before SCRIPT_TICK_LIMIT (default 64)").option("--ledger-out <file>", "Workflow: write the in-memory ledger as JSON").option("--agents <fake|live>", "Workflow: fake agent steps (default) or call the dev API").option("--now <iso>", "Workflow: virtual clock start").option("--park <id>", "Workflow: simulate a platform-fault park of this step (repeatable)", collect, []).option("--fast-retries", "Workflow: collapse retry backoff waits to 0").option("--real-time", "Workflow: actually wait on sleeps/backoffs instead of fast-forwarding").option("--artefacts-dir <dir>", "Workflow: back ctx.artefacts.* on disk").option("--workspace <dir>", "Workflow: the checkout Job-tier code steps run in (ctx.workspace + ctx.exec / ctx.$)").addHelpText("after", `
|
|
75087
|
+
program2.command("test [type]").description("\u{1F9EA} Test skills, webhooks, or jobs interactively").option("--name <name>", "Entity name to test").option("--input <json>", "JSON input string for testing").option("--json", "Output result as raw JSON (useful for scripting and piping)").option("--route <route>", "Web app: the route to call, e.g. 'GET /tickets?status=open'").option("--step-output <id=json>", "Workflow: complete a step with this output (repeatable)", collect, []).option("--approve <id[=@payload]>", "Workflow: pre-answer an approval (repeatable)", collect, []).option("--deny <id[=@reason]>", "Workflow: pre-deny an approval (repeatable)", collect, []).option("--signal <name=json>", "Workflow: pre-supply a waitForSignal payload (repeatable)", collect, []).option("--from-run <runId>", "Workflow: seed completed steps from a real run").option("--force", "Workflow: seed from a run whose graph differs").option("--record <dir>", "Workflow: record agent/tool outputs as fixtures").option("--fixtures <dir>", "Workflow: replay recorded fixtures (exit 5 when one is missing)").option("--step-wall <s>", "Workflow: per-step wall in seconds (default 600)").option("--job-wall <s>", "Workflow: virtual wall for tier:'job' steps \u2014 splits at 14400 s segments, > 86400 is exit 2").option("--max-ticks <n>", "Workflow (script form): tick cap before SCRIPT_TICK_LIMIT (default 64)").option("--ledger-out <file>", "Workflow: write the in-memory ledger as JSON").option("--agents <fake|live>", "Workflow: fake agent steps (default) or call the dev API").option("--now <iso>", "Workflow: virtual clock start").option("--park <id>", "Workflow: simulate a platform-fault park of this step (repeatable)", collect, []).option("--fast-retries", "Workflow: collapse retry backoff waits to 0").option("--real-time", "Workflow: actually wait on sleeps/backoffs instead of fast-forwarding").option("--artefacts-dir <dir>", "Workflow: back ctx.artefacts.* on disk").option("--workspace <dir>", "Workflow: the checkout Job-tier code steps run in (ctx.workspace + ctx.exec / ctx.$)").addHelpText("after", `
|
|
73469
75088
|
Arguments:
|
|
73470
75089
|
type Optional: 'skill', 'webhook', 'job' or 'workflow' (prompts if not provided)
|
|
73471
75090
|
|
|
@@ -73487,7 +75106,7 @@ Examples:
|
|
|
73487
75106
|
`).action(testCommand);
|
|
73488
75107
|
program2.command("push [type]").description("\u2601\uFE0F Push skill, agent, webhook, job, MCP server, or backup to server").option("--force", "Skip all confirmation prompts (auto-confirm)").option("--auto-deploy", "Automatically deploy to production after push").option("--name <name>", "Entity name to push").option("--set-version <version>", "Version to set (e.g., 1.0.5)").option("--fresh", "Build backup manifest from disk instead of compiled manifest.json (push backup only)").option("--apply-effort", "push workflow: send each agent step's effort to the model from this version on (a plain push never does)").option("--no-include-source", "Skip the per-skill source attach after push (default: attach, so admin Builder UI sees CLI edits)").addHelpText("after", `
|
|
73489
75108
|
Arguments:
|
|
73490
|
-
type Optional: 'skill', 'agent', 'persona', 'webhook', 'job', 'preprocessor', 'postprocessor', 'mcp', 'backup', or 'all' (prompts if not provided)
|
|
75109
|
+
type Optional: 'skill', 'agent', 'persona', 'webhook', 'job', 'preprocessor', 'postprocessor', 'mcp', 'webapp', 'backup', or 'all' (prompts if not provided)
|
|
73491
75110
|
|
|
73492
75111
|
Options:
|
|
73493
75112
|
--force Skip all confirmation prompts
|
|
@@ -73505,6 +75124,7 @@ Examples:
|
|
|
73505
75124
|
$ lua push webhook Push a webhook directly
|
|
73506
75125
|
$ lua push job Push a job directly
|
|
73507
75126
|
$ lua push mcp Push an MCP server directly
|
|
75127
|
+
$ lua push webapp --name ops-dashboard Build and push a web app (routes + pages)
|
|
73508
75128
|
$ lua push backup Push project source backup
|
|
73509
75129
|
$ lua push backup --fresh Push backup, building manifest from disk
|
|
73510
75130
|
$ lua push all --force Push all components without prompts
|
|
@@ -74196,6 +75816,9 @@ Examples:
|
|
|
74196
75816
|
$ lua version delete v3 --ci Refused: needs --force (usage error, exit 2)
|
|
74197
75817
|
$ lua version delete v3 --ci --force Delete non-interactively
|
|
74198
75818
|
`).action((version, opts) => versionDeleteCommand(version, opts));
|
|
75819
|
+
const appsGroup = program2.command("apps").description("\u{1F5A5}\uFE0F Create and develop web apps of this agent");
|
|
75820
|
+
appsGroup.command("new <name>").description("Scaffold a web app in src/apps/<name> (routes + a Vite/React page) and list it on the agent").action((name) => appsNewCommand(name));
|
|
75821
|
+
appsGroup.command("dev <name>").description("Run a web app locally: pages on Vite with hot reload, routes in the local sandbox as you").option("--port <port>", "Port for the dev server (default: Vite's)").action((name, opts) => appsDevCommand(name, opts));
|
|
74199
75822
|
const gitGroup = program2.command("git").description("Manage opt-in git auto-commits for this project");
|
|
74200
75823
|
gitGroup.command("connect").description("Enable git auto-commits (runs sanity checks, writes git.enabled: true)").option("--auto-push", "Also enable post-commit auto-push (requires `lua git auth github` + a GitHub HTTPS origin remote)").action((opts) => gitConnectCommand({
|
|
74201
75824
|
autoPush: opts.autoPush
|