lua-cli 3.32.4 → 3.32.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-exports.d.ts +11 -1
- package/dist/api-exports.js +208 -49
- package/dist/api-exports.js.map +1 -1
- package/dist/index.js +869 -481
- package/dist/index.js.map +1 -1
- package/dist/workflow-builder.js +133 -3
- package/dist/workflow-builder.js.map +1 -1
- package/docs/CLI_REFERENCE.md +6 -2
- package/docs/README.md +2 -2
- package/docs/workflows/limits.md +4 -0
- package/docs/workflows/testing-offline.md +1 -1
- package/package.json +3 -3
- package/template/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -116,7 +116,10 @@ function classifyCliError(error) {
|
|
|
116
116
|
code: error.code,
|
|
117
117
|
exitCode: error.exitCode,
|
|
118
118
|
message: error.message,
|
|
119
|
-
hint: error.hint
|
|
119
|
+
hint: error.hint,
|
|
120
|
+
statusCode: error.statusCode,
|
|
121
|
+
serverCode: error.serverCode,
|
|
122
|
+
issues: error.issues
|
|
120
123
|
};
|
|
121
124
|
}
|
|
122
125
|
if (AuthenticationError.isAuthenticationError(error)) {
|
|
@@ -138,30 +141,36 @@ function classifyCliError(error) {
|
|
|
138
141
|
}
|
|
139
142
|
const status = numericStatus(e);
|
|
140
143
|
if (status !== void 0) {
|
|
144
|
+
const statusCode = status;
|
|
141
145
|
if (status === 401) return {
|
|
142
146
|
code: "auth",
|
|
143
147
|
exitCode: CLI_EXIT.AUTH,
|
|
144
|
-
message
|
|
148
|
+
message,
|
|
149
|
+
statusCode
|
|
145
150
|
};
|
|
146
151
|
if (status === 403) return {
|
|
147
152
|
code: "forbidden",
|
|
148
153
|
exitCode: CLI_EXIT.FORBIDDEN,
|
|
149
|
-
message
|
|
154
|
+
message,
|
|
155
|
+
statusCode
|
|
150
156
|
};
|
|
151
157
|
if (status === 404) return {
|
|
152
158
|
code: "not_found",
|
|
153
159
|
exitCode: CLI_EXIT.NOT_FOUND,
|
|
154
|
-
message
|
|
160
|
+
message,
|
|
161
|
+
statusCode
|
|
155
162
|
};
|
|
156
163
|
if (status >= 400 && status < 500) return {
|
|
157
164
|
code: `http_${status}`,
|
|
158
165
|
exitCode: CLI_EXIT.FORBIDDEN,
|
|
159
|
-
message
|
|
166
|
+
message,
|
|
167
|
+
statusCode
|
|
160
168
|
};
|
|
161
169
|
if (status >= 500 || status === 0) return {
|
|
162
170
|
code: "unavailable",
|
|
163
171
|
exitCode: CLI_EXIT.UNAVAILABLE,
|
|
164
|
-
message
|
|
172
|
+
message,
|
|
173
|
+
statusCode
|
|
165
174
|
};
|
|
166
175
|
}
|
|
167
176
|
const causeCode = e.cause?.code;
|
|
@@ -179,9 +188,18 @@ function classifyCliError(error) {
|
|
|
179
188
|
message
|
|
180
189
|
};
|
|
181
190
|
}
|
|
191
|
+
function issueLines(issues) {
|
|
192
|
+
return (issues ?? []).map((issue) => {
|
|
193
|
+
const where = issue.path !== void 0 ? `${issue.path || "/"}: ` : "";
|
|
194
|
+
const what = issue.message ?? issue.code ?? "invalid";
|
|
195
|
+
const tag = issue.message && issue.code ? ` (${issue.code})` : "";
|
|
196
|
+
return ` \u2022 ${where}${what}${tag}`;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
182
199
|
function renderCliError(reported, options = {}) {
|
|
183
200
|
const lines = [
|
|
184
|
-
`\u2716 ${reported.code}: ${reported.message}
|
|
201
|
+
`\u2716 ${reported.code}: ${reported.message}`,
|
|
202
|
+
...issueLines(reported.issues)
|
|
185
203
|
];
|
|
186
204
|
for (const hint of [
|
|
187
205
|
reported.hint,
|
|
@@ -193,9 +211,30 @@ function renderCliError(reported, options = {}) {
|
|
|
193
211
|
if (options.stack) lines.push("", options.stack);
|
|
194
212
|
return lines;
|
|
195
213
|
}
|
|
214
|
+
function cliErrorEnvelope(error) {
|
|
215
|
+
const reported = classifyCliError(error);
|
|
216
|
+
return {
|
|
217
|
+
success: false,
|
|
218
|
+
error: {
|
|
219
|
+
code: reported.serverCode ?? reported.code,
|
|
220
|
+
...reported.statusCode !== void 0 ? {
|
|
221
|
+
statusCode: reported.statusCode
|
|
222
|
+
} : {},
|
|
223
|
+
message: reported.message,
|
|
224
|
+
...reported.issues?.length ? {
|
|
225
|
+
issues: reported.issues
|
|
226
|
+
} : {}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
196
230
|
function reportCliError(error, options = {}) {
|
|
197
231
|
const reported = classifyCliError(error);
|
|
198
232
|
const stack = debugEnabled() && error instanceof Error ? error.stack : void 0;
|
|
233
|
+
if (options.json) {
|
|
234
|
+
console.log(JSON.stringify(cliErrorEnvelope(error), null, 2));
|
|
235
|
+
if (stack) console.error(stack);
|
|
236
|
+
return reported;
|
|
237
|
+
}
|
|
199
238
|
for (const line of renderCliError(reported, {
|
|
200
239
|
extraHint: options.extraHint,
|
|
201
240
|
stack
|
|
@@ -247,6 +286,8 @@ var init_cli_error = __esm({
|
|
|
247
286
|
exitCode;
|
|
248
287
|
hint;
|
|
249
288
|
statusCode;
|
|
289
|
+
serverCode;
|
|
290
|
+
issues;
|
|
250
291
|
constructor(code, message, options = {}) {
|
|
251
292
|
super(message);
|
|
252
293
|
this.name = "CliError";
|
|
@@ -254,6 +295,8 @@ var init_cli_error = __esm({
|
|
|
254
295
|
this.exitCode = options.exitCode ?? CLI_EXIT.ERROR;
|
|
255
296
|
this.hint = options.hint;
|
|
256
297
|
this.statusCode = options.statusCode;
|
|
298
|
+
this.serverCode = options.serverCode;
|
|
299
|
+
this.issues = options.issues?.length ? options.issues : void 0;
|
|
257
300
|
if (Error.captureStackTrace) Error.captureStackTrace(this, _CliError);
|
|
258
301
|
}
|
|
259
302
|
/** Bad arguments, an unknown action, no project — exit 2. */
|
|
@@ -286,7 +329,7 @@ var init_cli_error = __esm({
|
|
|
286
329
|
* A command that reads `response.error.statusCode` throws through here, so `lua logs` on a 503 exits 11 like
|
|
287
330
|
* every other verb instead of printing the message itself and then throwing an exit-1 `Error`.
|
|
288
331
|
*/
|
|
289
|
-
static fromStatus(statusCode, message, hint) {
|
|
332
|
+
static fromStatus(statusCode, message, hint, detail = {}) {
|
|
290
333
|
const reported = classifyCliError(Object.assign(new Error(message), {
|
|
291
334
|
statusCode
|
|
292
335
|
}));
|
|
@@ -294,7 +337,9 @@ var init_cli_error = __esm({
|
|
|
294
337
|
return new _CliError(reported.code, message, {
|
|
295
338
|
exitCode: reported.exitCode,
|
|
296
339
|
hint: hint ?? classHint,
|
|
297
|
-
statusCode
|
|
340
|
+
statusCode,
|
|
341
|
+
serverCode: detail.serverCode,
|
|
342
|
+
issues: detail.issues
|
|
298
343
|
});
|
|
299
344
|
}
|
|
300
345
|
static isCliError(error) {
|
|
@@ -343,7 +388,9 @@ var init_cli_error = __esm({
|
|
|
343
388
|
__name(authHint, "authHint");
|
|
344
389
|
__name(numericStatus, "numericStatus");
|
|
345
390
|
__name(classifyCliError, "classifyCliError");
|
|
391
|
+
__name(issueLines, "issueLines");
|
|
346
392
|
__name(renderCliError, "renderCliError");
|
|
393
|
+
__name(cliErrorEnvelope, "cliErrorEnvelope");
|
|
347
394
|
__name(reportCliError, "reportCliError");
|
|
348
395
|
__name(commanderExitCode, "commanderExitCode");
|
|
349
396
|
__name(reportUnhandledCliError, "reportUnhandledCliError");
|
|
@@ -1179,6 +1226,11 @@ function isDeviceCredentialPrincipal(context) {
|
|
|
1179
1226
|
function hasDeviceCredentialType(value3) {
|
|
1180
1227
|
return DeviceCredentialClaimSchema.safeParse(value3).success;
|
|
1181
1228
|
}
|
|
1229
|
+
function sessionAuthTime(context) {
|
|
1230
|
+
if (!context || context.credential.type !== "firstPartySession") return void 0;
|
|
1231
|
+
const authTime = context.authTime;
|
|
1232
|
+
return typeof authTime === "number" && Number.isInteger(authTime) && authTime >= 0 && authTime <= SESSION_AUTH_TIME_MAX_S ? authTime : void 0;
|
|
1233
|
+
}
|
|
1182
1234
|
function isTypedApiKeyPrincipal(context) {
|
|
1183
1235
|
return context?.subject.subjectType === "apiKey" && context.credential.type === "apiKey" && !context.compatibility;
|
|
1184
1236
|
}
|
|
@@ -1351,6 +1403,39 @@ function scheduledWorkflowRunId(jobId, scheduledTime) {
|
|
|
1351
1403
|
const key = typeof scheduledTime === "number" ? String(scheduledTime) : scheduledTimeKey(scheduledTime);
|
|
1352
1404
|
return `${WORKFLOW_SCHEDULED_RUN_ID_PREFIX}${jobId}_${key}`;
|
|
1353
1405
|
}
|
|
1406
|
+
function renderWorkflowScheduleKeyTemplate(template3, ctx) {
|
|
1407
|
+
if (!template3) return void 0;
|
|
1408
|
+
const read = /* @__PURE__ */ __name2((path25) => path25.split(".").reduce((o, k) => o && typeof o === "object" ? o[k] : void 0, ctx.input), "read");
|
|
1409
|
+
let unresolved = false;
|
|
1410
|
+
const out = template3.replace(/\$\{\s*([a-zA-Z0-9_.]+)\s*\}/g, (_m, expr) => {
|
|
1411
|
+
let v = "";
|
|
1412
|
+
if (expr === "scheduledTime") v = ctx.scheduledTime ?? "";
|
|
1413
|
+
else if (expr.startsWith("input.")) v = read(expr.slice("input.".length));
|
|
1414
|
+
const s = v === void 0 || v === null ? "" : String(v);
|
|
1415
|
+
if (s === "") unresolved = true;
|
|
1416
|
+
return s;
|
|
1417
|
+
});
|
|
1418
|
+
if (unresolved) return void 0;
|
|
1419
|
+
const key = out.slice(0, WORKFLOW_SCHEDULE_KEY_MAX);
|
|
1420
|
+
return key && /^[A-Za-z0-9:_\-.\/]+$/.test(key) ? key : void 0;
|
|
1421
|
+
}
|
|
1422
|
+
function scheduledWorkflowIdempotencyKey(jobId, rendered) {
|
|
1423
|
+
const head = `${WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX}${jobId}:`;
|
|
1424
|
+
if (head.length + rendered.length <= WORKFLOW_SCHEDULE_KEY_MAX) return `${head}${rendered}`;
|
|
1425
|
+
const digest = stableKeyDigest(rendered);
|
|
1426
|
+
const room = WORKFLOW_SCHEDULE_KEY_MAX - head.length - digest.length - 1;
|
|
1427
|
+
return `${head}${rendered.slice(0, Math.max(0, room))}~${digest}`;
|
|
1428
|
+
}
|
|
1429
|
+
function stableKeyDigest(s) {
|
|
1430
|
+
let a = 2166136261;
|
|
1431
|
+
let b = 84696351;
|
|
1432
|
+
for (let i = 0; i < s.length; i++) {
|
|
1433
|
+
const c = s.charCodeAt(i);
|
|
1434
|
+
a = Math.imul(a ^ c, 16777619);
|
|
1435
|
+
b = Math.imul(b ^ c, 16777619) ^ b >>> 13;
|
|
1436
|
+
}
|
|
1437
|
+
return (a >>> 0).toString(16).padStart(8, "0") + (b >>> 0).toString(16).padStart(8, "0");
|
|
1438
|
+
}
|
|
1354
1439
|
function workflowOperationId(runId, stepId, billingEpoch) {
|
|
1355
1440
|
return `${WORKFLOW_OPERATION_ID_PREFIX}${runId}:${stepId}:${billingEpoch}`;
|
|
1356
1441
|
}
|
|
@@ -1654,7 +1739,59 @@ function extractSingleJsonValue(text) {
|
|
|
1654
1739
|
};
|
|
1655
1740
|
}
|
|
1656
1741
|
}
|
|
1657
|
-
|
|
1742
|
+
function agentFeatureCatalogDefault(featureName) {
|
|
1743
|
+
return DEFAULT_ON_AGENT_FEATURES.includes(featureName);
|
|
1744
|
+
}
|
|
1745
|
+
function hasExplicitFeatureActive(row2) {
|
|
1746
|
+
return typeof row2?.active === "boolean";
|
|
1747
|
+
}
|
|
1748
|
+
function effectiveFeatureActive(row2, catalogDefault) {
|
|
1749
|
+
return hasExplicitFeatureActive(row2) ? row2.active : catalogDefault;
|
|
1750
|
+
}
|
|
1751
|
+
function resolveEffectiveFeature(row2, catalogDefault) {
|
|
1752
|
+
return hasExplicitFeatureActive(row2) ? {
|
|
1753
|
+
active: row2.active,
|
|
1754
|
+
source: "agent",
|
|
1755
|
+
default: catalogDefault
|
|
1756
|
+
} : {
|
|
1757
|
+
active: catalogDefault,
|
|
1758
|
+
source: "default",
|
|
1759
|
+
default: catalogDefault
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
function isFeatureRow(value3) {
|
|
1763
|
+
return typeof value3 === "object" && value3 !== null;
|
|
1764
|
+
}
|
|
1765
|
+
function effectiveAgentFeatureRows(base, override) {
|
|
1766
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1767
|
+
for (const [name, row2] of Object.entries(base ?? {})) {
|
|
1768
|
+
if (isFeatureRow(row2)) merged.set(name, {
|
|
1769
|
+
row: row2,
|
|
1770
|
+
origin: "baseAgent"
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
for (const [name, row2] of Object.entries(override ?? {})) {
|
|
1774
|
+
if (isFeatureRow(row2)) merged.set(name, {
|
|
1775
|
+
row: row2,
|
|
1776
|
+
origin: "subAgent"
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
return {
|
|
1780
|
+
rows: Object.fromEntries([
|
|
1781
|
+
...merged
|
|
1782
|
+
].map(([name, e]) => [
|
|
1783
|
+
name,
|
|
1784
|
+
e.row
|
|
1785
|
+
])),
|
|
1786
|
+
origins: Object.fromEntries([
|
|
1787
|
+
...merged
|
|
1788
|
+
].map(([name, e]) => [
|
|
1789
|
+
name,
|
|
1790
|
+
e.origin
|
|
1791
|
+
]))
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
var __defProp2, __name2, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, MODEL_ID_BYOK_PROVIDERS, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, PLATFORM_FALLBACK_MODEL_SOURCE, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, PERSONAL_SPACE_STARTING_PERSONA, AGENT_LOG_SOURCES, 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, TEMPLATE_TRIGGER_URL_ENV_PREFIX, 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, AUTHZ_PROJECTION_VERSION, ProjectedScopeSchema, DisplayRoleSchema, AuthorizationPrincipalSchema, CredentialContextSchema, ProjectionAnomalySchema, ProjectedOrgSchema, ProjectedResourceSchema, CapabilityProfilesSchema, RoleCatalogSchema, EffectiveAuthorizationSchema, ResourcePageSchema, SYSTEM_USER_PREFIX, WORKFLOW_RUN_IN_FLIGHT, WORKFLOW_RUN_IDLE, WORKFLOW_RUN_TERMINAL, WORKFLOW_RUN_STATUSES, WORKFLOW_STEP_STATUSES, WORKFLOW_STEP_IN_FLIGHT, ARCHIVE_WINDOW_MARGIN_DAYS, WORKFLOW_ORG_PURGING_TTL_S, WORKFLOW_ORG_PURGE_FORCE_AFTER_MS, IDEMPOTENCY_HOLDING_STATUSES, WORKFLOW_SCHEDULED_RUN_ID_PREFIX, CLOUD_TASK_RUN_ID_PREFIX, WORKFLOW_SCHEDULE_KEY_MAX, WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX, WORKFLOW_OPERATION_ID_PREFIX, WORKFLOW_JOURNAL_PROTOCOL_VERSION, WORKFLOW_CONNECTION_KEY_RE, WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES, WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES, WORKFLOW_RETRY_BACKOFFS, WORKFLOW_RETRY_MIN_ATTEMPTS, WORKFLOW_RETRY_POLICY_KEYS, WORKFLOW_RETRY_MAX_ATTEMPTS, WORKFLOW_RETRY_ENGINE_KEYS, WORKFLOW_JOB_RESOURCES, WORKFLOW_SIDE_EFFECTS, WORKFLOW_JOB_RANGES, WORKFLOW_JOB_RANGE_MEMBERS, WORKFLOW_SINGLE_STEP_TYPES, WORKFLOW_HITL_ENTRY_TYPES, WORKFLOW_ARM_ENTRY_TYPES, WORKFLOW_HITL_ARM_CONTAINERS, WORKFLOW_GRAPH_ENTRY_STEP_KINDS, WORKFLOW_ARM_ENTRY_STEP_KINDS, WORKFLOW_BUDGET_MAX_DURATION_SECONDS, REDACTED_PLACEHOLDER, PROVIDER_MESSAGE_MAX_CHARS, ERROR_MESSAGE_MAX_CHARS, SECRET_LITERAL_PATTERNS, SECRET_NAME, SECRET_PAIR_PATTERNS, GROUP_COUNT, WORKFLOW_SECRET_KEY_RE, WORKFLOW_RESERVED_SECRET_KEYS, SCRUB_INPUT_MAX_CHARS, SCRUB_CUT_BACKOFF_CHARS, WORKFLOW_AUDIT_EVENTS, WORKFLOW_AUDIT_METADATA_MAX_BYTES, INDENT, WRAP_WIDTH, NOUNS, GET_TOOL_NAMES, PREAMBLE, WORKFLOW_APPROVAL_OUTPUT_DECISIONS, WORKFLOW_APPROVAL_OUTPUT_SCHEMA, JSON_FENCE_RE, DEFAULT_ON_AGENT_FEATURES;
|
|
1658
1795
|
var init_dist = __esm({
|
|
1659
1796
|
"../shared-types/dist/index.mjs"() {
|
|
1660
1797
|
"use strict";
|
|
@@ -2431,6 +2568,7 @@ This text is who you are for this person. As you learn them, their name, their w
|
|
|
2431
2568
|
});
|
|
2432
2569
|
TYPED_API_KEY = /^api_([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\.([A-Za-z0-9_-]{43})$/;
|
|
2433
2570
|
IdSchema = z2.string().min(1).max(256);
|
|
2571
|
+
SESSION_AUTH_TIME_MAX_S = 4102444800;
|
|
2434
2572
|
PrincipalDescriptorSchema = z2.object({
|
|
2435
2573
|
subjectType: SubjectTypeSchema,
|
|
2436
2574
|
subjectId: IdSchema
|
|
@@ -2479,7 +2617,8 @@ This text is who you are for this person. As you learn them, their name, their w
|
|
|
2479
2617
|
owner: PrincipalOwnerSchema.optional(),
|
|
2480
2618
|
compatibility: z2.object({
|
|
2481
2619
|
mode: z2.literal("legacy-owner-delegation")
|
|
2482
|
-
}).strict().optional()
|
|
2620
|
+
}).strict().optional(),
|
|
2621
|
+
authTime: z2.number().int().nonnegative().max(SESSION_AUTH_TIME_MAX_S).optional()
|
|
2483
2622
|
}).strict();
|
|
2484
2623
|
DeviceCredentialPrincipalContextSchema = z2.object({
|
|
2485
2624
|
version: z2.literal(1),
|
|
@@ -2535,6 +2674,8 @@ This text is who you are for this person. As you learn them, their name, their w
|
|
|
2535
2674
|
}).passthrough();
|
|
2536
2675
|
__name(hasDeviceCredentialType, "hasDeviceCredentialType");
|
|
2537
2676
|
__name2(hasDeviceCredentialType, "hasDeviceCredentialType");
|
|
2677
|
+
__name(sessionAuthTime, "sessionAuthTime");
|
|
2678
|
+
__name2(sessionAuthTime, "sessionAuthTime");
|
|
2538
2679
|
__name(isTypedApiKeyPrincipal, "isTypedApiKeyPrincipal");
|
|
2539
2680
|
__name2(isTypedApiKeyPrincipal, "isTypedApiKeyPrincipal");
|
|
2540
2681
|
__name(typedApiKeyPrincipalId, "typedApiKeyPrincipalId");
|
|
@@ -2766,6 +2907,14 @@ This text is who you are for this person. As you learn them, their name, their w
|
|
|
2766
2907
|
__name2(isScheduledWorkflowRunId, "isScheduledWorkflowRunId");
|
|
2767
2908
|
__name(scheduledWorkflowRunId, "scheduledWorkflowRunId");
|
|
2768
2909
|
__name2(scheduledWorkflowRunId, "scheduledWorkflowRunId");
|
|
2910
|
+
WORKFLOW_SCHEDULE_KEY_MAX = 128;
|
|
2911
|
+
__name(renderWorkflowScheduleKeyTemplate, "renderWorkflowScheduleKeyTemplate");
|
|
2912
|
+
__name2(renderWorkflowScheduleKeyTemplate, "renderWorkflowScheduleKeyTemplate");
|
|
2913
|
+
WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX = "sched:";
|
|
2914
|
+
__name(scheduledWorkflowIdempotencyKey, "scheduledWorkflowIdempotencyKey");
|
|
2915
|
+
__name2(scheduledWorkflowIdempotencyKey, "scheduledWorkflowIdempotencyKey");
|
|
2916
|
+
__name(stableKeyDigest, "stableKeyDigest");
|
|
2917
|
+
__name2(stableKeyDigest, "stableKeyDigest");
|
|
2769
2918
|
WORKFLOW_OPERATION_ID_PREFIX = "wf:";
|
|
2770
2919
|
__name(workflowOperationId, "workflowOperationId");
|
|
2771
2920
|
__name2(workflowOperationId, "workflowOperationId");
|
|
@@ -3212,6 +3361,23 @@ listed here; never invent a target.`;
|
|
|
3212
3361
|
JSON_FENCE_RE = /```(?:json)?[ \t]*\r?\n([\s\S]*?)\r?\n?```/g;
|
|
3213
3362
|
__name(extractSingleJsonValue, "extractSingleJsonValue");
|
|
3214
3363
|
__name2(extractSingleJsonValue, "extractSingleJsonValue");
|
|
3364
|
+
DEFAULT_ON_AGENT_FEATURES = [
|
|
3365
|
+
"workflows",
|
|
3366
|
+
"workflowCompose",
|
|
3367
|
+
"observationalMemory"
|
|
3368
|
+
];
|
|
3369
|
+
__name(agentFeatureCatalogDefault, "agentFeatureCatalogDefault");
|
|
3370
|
+
__name2(agentFeatureCatalogDefault, "agentFeatureCatalogDefault");
|
|
3371
|
+
__name(hasExplicitFeatureActive, "hasExplicitFeatureActive");
|
|
3372
|
+
__name2(hasExplicitFeatureActive, "hasExplicitFeatureActive");
|
|
3373
|
+
__name(effectiveFeatureActive, "effectiveFeatureActive");
|
|
3374
|
+
__name2(effectiveFeatureActive, "effectiveFeatureActive");
|
|
3375
|
+
__name(resolveEffectiveFeature, "resolveEffectiveFeature");
|
|
3376
|
+
__name2(resolveEffectiveFeature, "resolveEffectiveFeature");
|
|
3377
|
+
__name(isFeatureRow, "isFeatureRow");
|
|
3378
|
+
__name2(isFeatureRow, "isFeatureRow");
|
|
3379
|
+
__name(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
|
|
3380
|
+
__name2(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
|
|
3215
3381
|
}
|
|
3216
3382
|
});
|
|
3217
3383
|
|
|
@@ -4342,7 +4508,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
|
|
|
4342
4508
|
const id = singleId(node);
|
|
4343
4509
|
const unknown = unknownWorkflowRetryMembers(r);
|
|
4344
4510
|
if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path25}.retry`, id);
|
|
4345
|
-
if (
|
|
4511
|
+
if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
4346
4512
|
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
4347
4513
|
err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path25}.retry.maxAttempts`, id);
|
|
4348
4514
|
}
|
|
@@ -5883,6 +6049,7 @@ function runErrorIssues(issues) {
|
|
|
5883
6049
|
function runNextAction(run) {
|
|
5884
6050
|
if (isTerminalRunStatus(run.status)) return "none";
|
|
5885
6051
|
if (run.status === "suspended" && run.gate?.kind === "budget") return "raise_budget";
|
|
6052
|
+
if (run.status === "suspended" && run.gate?.kind === "billing") return "top_up";
|
|
5886
6053
|
if (!run.cancel?.requestedAt) return "none";
|
|
5887
6054
|
const forceAt = run.cancel.forceAfter ?? run.cancel.requestedAt + FORCE_CANCEL_STALE_MS;
|
|
5888
6055
|
return Date.now() >= forceAt ? "force" : "cancel_again";
|
|
@@ -5910,6 +6077,12 @@ function runCountsFromStepStatuses(statuses) {
|
|
|
5910
6077
|
for (const s of statuses) tally[s] = (tally[s] ?? 0) + 1;
|
|
5911
6078
|
return runCountsFromStatusTally(tally);
|
|
5912
6079
|
}
|
|
6080
|
+
function isBillingHeldStep(row2) {
|
|
6081
|
+
return row2.status === "ready" && row2.billingHold === true;
|
|
6082
|
+
}
|
|
6083
|
+
function stepEffectiveStatus(row2) {
|
|
6084
|
+
return isBillingHeldStep(row2) ? "suspended" : row2.status;
|
|
6085
|
+
}
|
|
5913
6086
|
function runCounts(counts) {
|
|
5914
6087
|
const c = counts ?? {};
|
|
5915
6088
|
const rawInFlight = c.dispatched !== void 0 || c.claimed !== void 0 || c.running !== void 0 || c.cancellation_requested !== void 0;
|
|
@@ -7440,6 +7613,10 @@ var init_dist2 = __esm({
|
|
|
7440
7613
|
__name3(runCountsFromStatusTally, "runCountsFromStatusTally");
|
|
7441
7614
|
__name(runCountsFromStepStatuses, "runCountsFromStepStatuses");
|
|
7442
7615
|
__name3(runCountsFromStepStatuses, "runCountsFromStepStatuses");
|
|
7616
|
+
__name(isBillingHeldStep, "isBillingHeldStep");
|
|
7617
|
+
__name3(isBillingHeldStep, "isBillingHeldStep");
|
|
7618
|
+
__name(stepEffectiveStatus, "stepEffectiveStatus");
|
|
7619
|
+
__name3(stepEffectiveStatus, "stepEffectiveStatus");
|
|
7443
7620
|
n = /* @__PURE__ */ __name3((v) => typeof v === "number" && Number.isFinite(v) ? v : 0, "n");
|
|
7444
7621
|
__name(runCounts, "runCounts");
|
|
7445
7622
|
__name3(runCounts, "runCounts");
|
|
@@ -7860,7 +8037,7 @@ var init_workflow = __esm({
|
|
|
7860
8037
|
}, "assertPredicate");
|
|
7861
8038
|
assertRetry = /* @__PURE__ */ __name((r, id) => {
|
|
7862
8039
|
if (!r) return;
|
|
7863
|
-
if (
|
|
8040
|
+
if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
|
|
7864
8041
|
const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
|
|
7865
8042
|
throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
|
|
7866
8043
|
}
|
|
@@ -8719,6 +8896,59 @@ var init_types = __esm({
|
|
|
8719
8896
|
|
|
8720
8897
|
// src/api/http.client.ts
|
|
8721
8898
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
8899
|
+
async function classifyErrorResponse(response) {
|
|
8900
|
+
let errorData;
|
|
8901
|
+
try {
|
|
8902
|
+
errorData = await response.json();
|
|
8903
|
+
} catch (jsonError) {
|
|
8904
|
+
errorData = {};
|
|
8905
|
+
}
|
|
8906
|
+
if (response.status === 401) {
|
|
8907
|
+
const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
|
|
8908
|
+
if (serverMessage && /not an admin/i.test(serverMessage)) {
|
|
8909
|
+
throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
|
|
8910
|
+
}
|
|
8911
|
+
const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
|
|
8912
|
+
const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
|
|
8913
|
+
if (isExplicitCredential || isBareAuthRejection) {
|
|
8914
|
+
throw new AuthenticationError("Authentication failed. Your Lua credential may be invalid or expired.", "invalid_credentials", serverMessage);
|
|
8915
|
+
}
|
|
8916
|
+
throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
|
|
8917
|
+
}
|
|
8918
|
+
if (response.status === 403) {
|
|
8919
|
+
const detail = errorData.message || "You do not have permission to access this resource.";
|
|
8920
|
+
const serverCode = serverCodeOf(errorData.code, errorData.error);
|
|
8921
|
+
throw new CliError("forbidden", `Access denied (403): ${detail}${serverCode ? ` (${serverCode})` : ""}`, {
|
|
8922
|
+
exitCode: CLI_EXIT.FORBIDDEN,
|
|
8923
|
+
statusCode: 403,
|
|
8924
|
+
serverCode,
|
|
8925
|
+
issues: Array.isArray(errorData.issues) ? errorData.issues : void 0,
|
|
8926
|
+
hint: "Check that your Lua login has access to this agent or organization."
|
|
8927
|
+
});
|
|
8928
|
+
}
|
|
8929
|
+
return {
|
|
8930
|
+
success: false,
|
|
8931
|
+
error: {
|
|
8932
|
+
message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
8933
|
+
statusCode: response.status,
|
|
8934
|
+
error: errorData.error,
|
|
8935
|
+
retryAfterSeconds: parseRetryAfter(response.headers.get("retry-after")),
|
|
8936
|
+
...errorData
|
|
8937
|
+
}
|
|
8938
|
+
};
|
|
8939
|
+
}
|
|
8940
|
+
function serverCodeOf(code, error) {
|
|
8941
|
+
if (typeof code === "string" && code.length > 0) return code;
|
|
8942
|
+
if (typeof error === "string" && /^[A-Z0-9][A-Z0-9_]*$/.test(error)) return error;
|
|
8943
|
+
return void 0;
|
|
8944
|
+
}
|
|
8945
|
+
async function refusalFromResponse(response) {
|
|
8946
|
+
const { error } = await classifyErrorResponse(response);
|
|
8947
|
+
return CliError.fromStatus(error?.statusCode ?? response.status, error?.message ?? `HTTP ${response.status}: ${response.statusText}`, void 0, {
|
|
8948
|
+
serverCode: serverCodeOf(error?.code, error?.error),
|
|
8949
|
+
issues: error?.issues
|
|
8950
|
+
});
|
|
8951
|
+
}
|
|
8722
8952
|
async function* parseSseStream(body, signal) {
|
|
8723
8953
|
const reader = body.getReader();
|
|
8724
8954
|
const decoder = new TextDecoder();
|
|
@@ -8899,42 +9129,7 @@ var init_http_client = __esm({
|
|
|
8899
9129
|
* @private
|
|
8900
9130
|
*/
|
|
8901
9131
|
async classifyErrorResponse(response) {
|
|
8902
|
-
|
|
8903
|
-
try {
|
|
8904
|
-
errorData = await response.json();
|
|
8905
|
-
} catch (jsonError) {
|
|
8906
|
-
errorData = {};
|
|
8907
|
-
}
|
|
8908
|
-
if (response.status === 401) {
|
|
8909
|
-
const serverMessage = typeof errorData.message === "string" ? errorData.message : void 0;
|
|
8910
|
-
if (serverMessage && /not an admin/i.test(serverMessage)) {
|
|
8911
|
-
throw new AuthenticationError(`Access denied for this agent: ${serverMessage}`, "no_agent_access", serverMessage);
|
|
8912
|
-
}
|
|
8913
|
-
const isExplicitCredential = !!serverMessage && /(invalid|expired|missing|no)\s+(api[\s_-]?key|token|credential)/i.test(serverMessage);
|
|
8914
|
-
const isBareAuthRejection = !serverMessage || /^unauthorized$/i.test(serverMessage);
|
|
8915
|
-
if (isExplicitCredential || isBareAuthRejection) {
|
|
8916
|
-
throw new AuthenticationError("Authentication failed. Your Lua credential may be invalid or expired.", "invalid_credentials", serverMessage);
|
|
8917
|
-
}
|
|
8918
|
-
throw new AuthenticationError(`Authentication failed: ${serverMessage}`, "unknown", serverMessage);
|
|
8919
|
-
}
|
|
8920
|
-
if (response.status === 403) {
|
|
8921
|
-
const detail = errorData.message || "You do not have permission to access this resource.";
|
|
8922
|
-
throw new CliError("forbidden", `Access denied (403): ${detail}`, {
|
|
8923
|
-
exitCode: CLI_EXIT.FORBIDDEN,
|
|
8924
|
-
statusCode: 403,
|
|
8925
|
-
hint: "Check that your Lua login has access to this agent or organization."
|
|
8926
|
-
});
|
|
8927
|
-
}
|
|
8928
|
-
return {
|
|
8929
|
-
success: false,
|
|
8930
|
-
error: {
|
|
8931
|
-
message: errorData.message || `HTTP ${response.status}: ${response.statusText}`,
|
|
8932
|
-
statusCode: response.status,
|
|
8933
|
-
error: errorData.error,
|
|
8934
|
-
retryAfterSeconds: parseRetryAfter(response.headers.get("retry-after")),
|
|
8935
|
-
...errorData
|
|
8936
|
-
}
|
|
8937
|
-
};
|
|
9132
|
+
return classifyErrorResponse(response);
|
|
8938
9133
|
}
|
|
8939
9134
|
/**
|
|
8940
9135
|
* Checks if an HTTP status code is retryable
|
|
@@ -9142,6 +9337,9 @@ var init_http_client = __esm({
|
|
|
9142
9337
|
};
|
|
9143
9338
|
}
|
|
9144
9339
|
};
|
|
9340
|
+
__name(classifyErrorResponse, "classifyErrorResponse");
|
|
9341
|
+
__name(serverCodeOf, "serverCodeOf");
|
|
9342
|
+
__name(refusalFromResponse, "refusalFromResponse");
|
|
9145
9343
|
__name(parseSseStream, "parseSseStream");
|
|
9146
9344
|
__name(parseRetryAfter, "parseRetryAfter");
|
|
9147
9345
|
__name(isCoreDrainApiError, "isCoreDrainApiError");
|
|
@@ -11568,8 +11766,14 @@ async function withErrorHandling(commandFn, commandName, opts) {
|
|
|
11568
11766
|
} catch {
|
|
11569
11767
|
}
|
|
11570
11768
|
}
|
|
11769
|
+
let json = false;
|
|
11770
|
+
try {
|
|
11771
|
+
json = typeof opts?.json === "function" ? !!opts.json() : !!opts?.json;
|
|
11772
|
+
} catch {
|
|
11773
|
+
}
|
|
11571
11774
|
const reported = reportCliError(error, {
|
|
11572
|
-
extraHint
|
|
11775
|
+
extraHint,
|
|
11776
|
+
json
|
|
11573
11777
|
});
|
|
11574
11778
|
process.exitCode = reported.exitCode;
|
|
11575
11779
|
await showUpdateWarningIfNeeded(versionCheckPromise);
|
|
@@ -25850,6 +26054,7 @@ var init_job_api_service = __esm({
|
|
|
25850
26054
|
"src/api/job.api.service.ts"() {
|
|
25851
26055
|
"use strict";
|
|
25852
26056
|
init_http_client();
|
|
26057
|
+
init_cli_error();
|
|
25853
26058
|
init_job_instance();
|
|
25854
26059
|
JobApi = class extends HttpClient {
|
|
25855
26060
|
static {
|
|
@@ -25906,7 +26111,7 @@ var init_job_api_service = __esm({
|
|
|
25906
26111
|
if (response.success && response.data) {
|
|
25907
26112
|
return new JobInstance(this, response.data);
|
|
25908
26113
|
}
|
|
25909
|
-
throw
|
|
26114
|
+
throw CliError.fromStatus(response.error?.statusCode, response.error?.message || "Failed to get job");
|
|
25910
26115
|
}
|
|
25911
26116
|
/**
|
|
25912
26117
|
* Creates a new job for the agent.
|
|
@@ -29752,7 +29957,7 @@ async function handleAgentSwitch(credential, organizations, apiKey, existingYaml
|
|
|
29752
29957
|
});
|
|
29753
29958
|
writeSuccess("\u2705 lua.skill.yaml updated successfully!");
|
|
29754
29959
|
writeSuccess("\u2705 LuaAgent configuration updated!");
|
|
29755
|
-
writeInfo("\n\u{1F4A1} Your project now uses the new agent. Run 'lua
|
|
29960
|
+
writeInfo("\n\u{1F4A1} Your project now uses the new agent. Run 'lua sync' (or 'lua push all') to reconcile your skills.\n");
|
|
29756
29961
|
trackEvent("cli_init_agent_switched", {
|
|
29757
29962
|
model_selected: !!selectedModel,
|
|
29758
29963
|
model: selectedModel
|
|
@@ -30137,7 +30342,9 @@ async function syncCommand(options) {
|
|
|
30137
30342
|
let syncCompletedSuccessfully = false;
|
|
30138
30343
|
try {
|
|
30139
30344
|
writeProgress("\u{1F504} Compiling to get latest local state...");
|
|
30140
|
-
await compileCommand(
|
|
30345
|
+
await compileCommand({
|
|
30346
|
+
serverSync: true
|
|
30347
|
+
});
|
|
30141
30348
|
writeProgress("\u{1F504} Checking for drift between server and local code...");
|
|
30142
30349
|
const { agentId, apiKey } = await initializeCommand({
|
|
30143
30350
|
showProgress: false
|
|
@@ -34877,7 +35084,8 @@ var WorkflowHandler = class extends BaseVersionedHandler {
|
|
|
34877
35084
|
success: response.success,
|
|
34878
35085
|
error: response.error?.message,
|
|
34879
35086
|
statusCode: response.error?.statusCode,
|
|
34880
|
-
code: response.error?.code ?? response.error?.error
|
|
35087
|
+
code: response.error?.code ?? response.error?.error,
|
|
35088
|
+
issues: response.error?.issues
|
|
34881
35089
|
};
|
|
34882
35090
|
}
|
|
34883
35091
|
/**
|
|
@@ -35083,7 +35291,7 @@ async function compileCommand(options) {
|
|
|
35083
35291
|
const debugMode = options?.debug || debugEnabled();
|
|
35084
35292
|
const verboseMode = options?.verbose || debugMode;
|
|
35085
35293
|
const doSync = options?.sync === true;
|
|
35086
|
-
const doServerSync = options?.serverSync
|
|
35294
|
+
const doServerSync = options?.serverSync === true;
|
|
35087
35295
|
if (debugMode) {
|
|
35088
35296
|
console.log("\u{1F41B} Debug mode enabled");
|
|
35089
35297
|
}
|
|
@@ -35180,7 +35388,7 @@ async function compileCommand(options) {
|
|
|
35180
35388
|
let syncConfig = readYamlConfig();
|
|
35181
35389
|
const agentId = syncConfig?.agent?.agentId;
|
|
35182
35390
|
if (!doServerSync) {
|
|
35183
|
-
writeInfo("\u2139\uFE0F Server sync skipped
|
|
35391
|
+
writeInfo("\u2139\uFE0F Server sync skipped \u2014 nothing was sent to the server; `lua push` publishes.");
|
|
35184
35392
|
} else if (apiKey && agentId) {
|
|
35185
35393
|
writeProgress("\u{1F504} Syncing with server...");
|
|
35186
35394
|
const fetchResults = await Promise.all(syncableHandlers.map((h) => h.fetchServerState(apiKey, agentId)));
|
|
@@ -38458,7 +38666,8 @@ async function pushBackupCommand(options = {}) {
|
|
|
38458
38666
|
}
|
|
38459
38667
|
writeInfo("No compilation output found. Running compile first...");
|
|
38460
38668
|
await compileCommand({
|
|
38461
|
-
sync: false
|
|
38669
|
+
sync: false,
|
|
38670
|
+
serverSync: true
|
|
38462
38671
|
});
|
|
38463
38672
|
}
|
|
38464
38673
|
writeProgress("Pushing backup...");
|
|
@@ -39156,12 +39365,24 @@ function formatPushFailureSummary(failedItems) {
|
|
|
39156
39365
|
return lines.join("\n");
|
|
39157
39366
|
}
|
|
39158
39367
|
__name(formatPushFailureSummary, "formatPushFailureSummary");
|
|
39368
|
+
function pushRefusalError(handler, name, result) {
|
|
39369
|
+
const reason = result.error || "Unknown error";
|
|
39370
|
+
const isVersionConflict = reason.toLowerCase().includes("already exists");
|
|
39371
|
+
return new CliError("error", `${handler.displayName.toLowerCase()} "${name}" is not pushed: ${reason}`, {
|
|
39372
|
+
exitCode: CLI_EXIT.ERROR,
|
|
39373
|
+
statusCode: result.statusCode,
|
|
39374
|
+
serverCode: result.code,
|
|
39375
|
+
issues: result.issues,
|
|
39376
|
+
hint: isVersionConflict ? `Version conflict \u2014 this version already exists on the server. Auto-bump: lua push ${handler.kind} --force \xB7 or push all: lua push all --force` : void 0
|
|
39377
|
+
});
|
|
39378
|
+
}
|
|
39379
|
+
__name(pushRefusalError, "pushRefusalError");
|
|
39159
39380
|
function stalePushEntryError(handler, name, entityId, serverMessage) {
|
|
39160
39381
|
const field = handler.yamlConfig.idField;
|
|
39161
39382
|
return new CliError("not_found", `${handler.displayName} "${name}" (${entityId}) no longer exists on the server${serverMessage ? ` \u2014 ${serverMessage}` : ""}`, {
|
|
39162
39383
|
exitCode: CLI_EXIT.NOT_FOUND,
|
|
39163
39384
|
statusCode: 404,
|
|
39164
|
-
hint: `lua.skill.yaml still holds ${field}: ${entityId} for "${name}".
|
|
39385
|
+
hint: `lua.skill.yaml still holds ${field}: ${entityId} for "${name}". Remove that ${field}: line from lua.skill.yaml, then run \`lua push ${handler.displayName}\` again \u2014 its compile step registers the definition afresh and writes the new id.`
|
|
39165
39386
|
});
|
|
39166
39387
|
}
|
|
39167
39388
|
__name(stalePushEntryError, "stalePushEntryError");
|
|
@@ -39310,7 +39531,9 @@ __name(shouldDeployAfterPush, "shouldDeployAfterPush");
|
|
|
39310
39531
|
async function pushVersionedPrimitive(handler, options = {}) {
|
|
39311
39532
|
try {
|
|
39312
39533
|
writeProgress("\u{1F4E6} Compiling project...");
|
|
39313
|
-
await compileCommand(
|
|
39534
|
+
await compileCommand({
|
|
39535
|
+
serverSync: true
|
|
39536
|
+
});
|
|
39314
39537
|
writeSuccess("\u2705 Compilation complete");
|
|
39315
39538
|
const apiKey = await authenticateOrFail();
|
|
39316
39539
|
const config = readYamlConfig();
|
|
@@ -39332,7 +39555,7 @@ async function pushVersionedPrimitive(handler, options = {}) {
|
|
|
39332
39555
|
});
|
|
39333
39556
|
const entityId = selected[handler.yamlConfig.idField];
|
|
39334
39557
|
if (!entityId) {
|
|
39335
|
-
throw new Error(`${handler.displayName} "${selected.name}" has no server ID.
|
|
39558
|
+
throw new Error(`${handler.displayName} "${selected.name}" has no server ID \u2014 the create above failed. Fix it and run 'lua push ${handler.displayName}' again.`);
|
|
39336
39559
|
}
|
|
39337
39560
|
const manifest = loadManifest();
|
|
39338
39561
|
const bundleAccumulator = /* @__PURE__ */ new Map();
|
|
@@ -39363,24 +39586,7 @@ async function pushVersionedPrimitive(handler, options = {}) {
|
|
|
39363
39586
|
});
|
|
39364
39587
|
if (!result.success) {
|
|
39365
39588
|
if (result.statusCode === 404) throw stalePushEntryError(handler, selected.name, entityId, result.error);
|
|
39366
|
-
|
|
39367
|
-
if (isVersionConflict) {
|
|
39368
|
-
writeHintBlock({
|
|
39369
|
-
headline: "Version conflict \u2014 this version already exists on the server.",
|
|
39370
|
-
lines: [
|
|
39371
|
-
{
|
|
39372
|
-
label: "Auto-bump:",
|
|
39373
|
-
command: `lua push ${handler.kind} --force`
|
|
39374
|
-
},
|
|
39375
|
-
{
|
|
39376
|
-
label: "Or push all:",
|
|
39377
|
-
command: "lua push all --force"
|
|
39378
|
-
}
|
|
39379
|
-
],
|
|
39380
|
-
when: "error"
|
|
39381
|
-
});
|
|
39382
|
-
}
|
|
39383
|
-
throw new Error(`Push Error: ${result.error || "Unknown error"}`);
|
|
39589
|
+
throw pushRefusalError(handler, selected.name, result);
|
|
39384
39590
|
}
|
|
39385
39591
|
writeSuccess(`
|
|
39386
39592
|
\u2705 Successfully pushed ${selected.name} v${confirmedVersion}
|
|
@@ -39726,7 +39932,9 @@ async function runIncludeSourceHook(apiKey, agentId, selectedType) {
|
|
|
39726
39932
|
__name(runIncludeSourceHook, "runIncludeSourceHook");
|
|
39727
39933
|
async function pushAgentVersion(options = {}) {
|
|
39728
39934
|
writeProgress("\u{1F504} Compiling...");
|
|
39729
|
-
await compileCommand(
|
|
39935
|
+
await compileCommand({
|
|
39936
|
+
serverSync: true
|
|
39937
|
+
});
|
|
39730
39938
|
const config = readYamlConfig();
|
|
39731
39939
|
if (!config || !config.agent?.agentId) {
|
|
39732
39940
|
throw new Error("No agent configuration found. Please run 'lua init' first.");
|
|
@@ -39833,7 +40041,9 @@ __name(deployPersonaVersionAfterPush, "deployPersonaVersionAfterPush");
|
|
|
39833
40041
|
async function pushMCPServer(options = {}) {
|
|
39834
40042
|
try {
|
|
39835
40043
|
writeProgress("\u{1F4E6} Compiling project...");
|
|
39836
|
-
await compileCommand(
|
|
40044
|
+
await compileCommand({
|
|
40045
|
+
serverSync: true
|
|
40046
|
+
});
|
|
39837
40047
|
writeSuccess("\u2705 Compilation complete");
|
|
39838
40048
|
const apiKey = await authenticateOrFail();
|
|
39839
40049
|
writeSuccess("\u2705 Authentication verified");
|
|
@@ -39886,7 +40096,9 @@ async function pushAllCommand(options) {
|
|
|
39886
40096
|
writeInfo("\u{1F680} Auto-deploy to production is ENABLED\n");
|
|
39887
40097
|
}
|
|
39888
40098
|
writeProgress("\u{1F4E6} Compiling project...");
|
|
39889
|
-
await compileCommand(
|
|
40099
|
+
await compileCommand({
|
|
40100
|
+
serverSync: true
|
|
40101
|
+
});
|
|
39890
40102
|
const config = readYamlConfig();
|
|
39891
40103
|
if (!config?.agent?.agentId) {
|
|
39892
40104
|
throw new Error('No agent ID found in lua.skill.yaml. Run "lua init" first.');
|
|
@@ -39974,7 +40186,7 @@ ${icon} Pushing ${items.length} ${handler.displayName}(s)...`);
|
|
|
39974
40186
|
}
|
|
39975
40187
|
const entityId = item[handler.yamlConfig.idField];
|
|
39976
40188
|
if (!entityId) {
|
|
39977
|
-
console.warn(`\u26A0\uFE0F ${handler.displayName} "${item.name}" has no server ID, skipping.
|
|
40189
|
+
console.warn(`\u26A0\uFE0F ${handler.displayName} "${item.name}" has no server ID, skipping \u2014 the create above failed. Fix it and run 'lua push ${handler.displayName}' again.`);
|
|
39978
40190
|
continue;
|
|
39979
40191
|
}
|
|
39980
40192
|
if (!item.version) {
|
|
@@ -41921,7 +42133,9 @@ __name(chatCommand, "chatCommand");
|
|
|
41921
42133
|
async function setupChatEnvironment(chatEnv, config) {
|
|
41922
42134
|
writeProgress("\u{1F504} Setting up sandbox environment...");
|
|
41923
42135
|
writeProgress("\u{1F504} Compiling skill...");
|
|
41924
|
-
await compileCommand(
|
|
42136
|
+
await compileCommand({
|
|
42137
|
+
serverSync: true
|
|
42138
|
+
});
|
|
41925
42139
|
const manifest = loadManifest();
|
|
41926
42140
|
const skills = getPrimitivesByKind(manifest, PrimitiveKind.SKILL);
|
|
41927
42141
|
let sandboxIds = {};
|
|
@@ -49703,7 +49917,7 @@ async function jobsCommand(action, cmdObj) {
|
|
|
49703
49917
|
}, "jobs");
|
|
49704
49918
|
}
|
|
49705
49919
|
__name(jobsCommand, "jobsCommand");
|
|
49706
|
-
async function displayJobsCore(context, jobs) {
|
|
49920
|
+
async function displayJobsCore(context, jobs, opts = {}) {
|
|
49707
49921
|
console.log("\n" + "=".repeat(60));
|
|
49708
49922
|
console.log("\u2699\uFE0F Production Jobs");
|
|
49709
49923
|
console.log("=".repeat(60) + "\n");
|
|
@@ -49726,7 +49940,14 @@ async function displayJobsCore(context, jobs) {
|
|
|
49726
49940
|
}
|
|
49727
49941
|
console.log();
|
|
49728
49942
|
} catch (error) {
|
|
49729
|
-
|
|
49943
|
+
if (CliError.isCliError(error) && error.statusCode === 404) {
|
|
49944
|
+
if (opts.single) {
|
|
49945
|
+
throw CliError.notFound(`Job "${job.name}" (${job.jobId}) no longer exists on the server \u2014 ${error.message}`, "lua.skill.yaml still lists it; `lua sync` reconciles the local config with the server.");
|
|
49946
|
+
}
|
|
49947
|
+
displayJobError(job, "not found on the server");
|
|
49948
|
+
continue;
|
|
49949
|
+
}
|
|
49950
|
+
throw error;
|
|
49730
49951
|
}
|
|
49731
49952
|
}
|
|
49732
49953
|
console.log("=".repeat(60));
|
|
@@ -49994,7 +50215,13 @@ async function executeNonInteractive7(context, config, action, options) {
|
|
|
49994
50215
|
console.log("\u2139\uFE0F No jobs found in configuration.");
|
|
49995
50216
|
return;
|
|
49996
50217
|
}
|
|
49997
|
-
|
|
50218
|
+
const viewed = options.jobName ? jobs.filter((j) => j.jobId === options.jobName || j.name === options.jobName) : jobs;
|
|
50219
|
+
if (viewed.length === 0) {
|
|
50220
|
+
throw CliError.notFound(`Job "${options.jobName}" not found`, listHint("Available jobs in local config:", jobs.map((j) => `${j.name} (${j.jobId})`)));
|
|
50221
|
+
}
|
|
50222
|
+
await displayJobsCore(context, viewed, {
|
|
50223
|
+
single: !!options.jobName
|
|
50224
|
+
});
|
|
49998
50225
|
return;
|
|
49999
50226
|
}
|
|
50000
50227
|
if (!options.jobName) {
|
|
@@ -50500,69 +50727,77 @@ function exitCodeForRunStatus(status) {
|
|
|
50500
50727
|
}
|
|
50501
50728
|
__name(exitCodeForRunStatus, "exitCodeForRunStatus");
|
|
50502
50729
|
async function workflowsCommand(action, target, extra, cmdObj) {
|
|
50503
|
-
return withErrorHandling(
|
|
50504
|
-
|
|
50505
|
-
|
|
50506
|
-
|
|
50507
|
-
|
|
50508
|
-
|
|
50509
|
-
|
|
50510
|
-
|
|
50511
|
-
|
|
50512
|
-
|
|
50513
|
-
|
|
50514
|
-
|
|
50515
|
-
|
|
50516
|
-
|
|
50517
|
-
|
|
50518
|
-
|
|
50519
|
-
|
|
50520
|
-
|
|
50521
|
-
|
|
50522
|
-
|
|
50523
|
-
|
|
50524
|
-
|
|
50525
|
-
|
|
50526
|
-
|
|
50527
|
-
|
|
50528
|
-
|
|
50529
|
-
|
|
50530
|
-
|
|
50531
|
-
|
|
50532
|
-
|
|
50533
|
-
|
|
50534
|
-
|
|
50535
|
-
|
|
50536
|
-
|
|
50537
|
-
|
|
50538
|
-
|
|
50539
|
-
|
|
50540
|
-
|
|
50541
|
-
|
|
50542
|
-
|
|
50730
|
+
return withErrorHandling(
|
|
50731
|
+
async () => {
|
|
50732
|
+
const options = {
|
|
50733
|
+
...cmdObj ?? {}
|
|
50734
|
+
};
|
|
50735
|
+
const json = !!options.json;
|
|
50736
|
+
let resolved;
|
|
50737
|
+
if (action) {
|
|
50738
|
+
resolved = validateOrSuggest("workflows.action", action);
|
|
50739
|
+
} else {
|
|
50740
|
+
const answer = await safePrompt([
|
|
50741
|
+
{
|
|
50742
|
+
type: "list",
|
|
50743
|
+
name: "action",
|
|
50744
|
+
message: "What would you like to do?",
|
|
50745
|
+
choices: [
|
|
50746
|
+
{
|
|
50747
|
+
name: "\u{1F4CB} List workflows",
|
|
50748
|
+
value: "list"
|
|
50749
|
+
},
|
|
50750
|
+
{
|
|
50751
|
+
name: "\u{1F9ED} Run a workflow locally",
|
|
50752
|
+
value: "run"
|
|
50753
|
+
},
|
|
50754
|
+
{
|
|
50755
|
+
name: "\u25B6\uFE0F Start a run",
|
|
50756
|
+
value: "start"
|
|
50757
|
+
},
|
|
50758
|
+
{
|
|
50759
|
+
name: "\u{1F5C2}\uFE0F List runs",
|
|
50760
|
+
value: "runs"
|
|
50761
|
+
}
|
|
50762
|
+
]
|
|
50763
|
+
}
|
|
50764
|
+
]);
|
|
50765
|
+
if (!answer) return;
|
|
50766
|
+
resolved = answer.action;
|
|
50767
|
+
}
|
|
50768
|
+
if (resolved === "run") {
|
|
50769
|
+
const outcome = await runWorkflowLocalFromProject(target ?? options.workflowName ?? null, options);
|
|
50770
|
+
process.exitCode = outcome.exitCode;
|
|
50771
|
+
trackEvent("cli_workflows_action", {
|
|
50772
|
+
action: "run",
|
|
50773
|
+
non_interactive: !!action
|
|
50774
|
+
});
|
|
50775
|
+
return;
|
|
50776
|
+
}
|
|
50777
|
+
const { agentId, apiKey } = await initializeCommand({
|
|
50778
|
+
showProgress: !json
|
|
50779
|
+
});
|
|
50780
|
+
const ctx = {
|
|
50781
|
+
agentId,
|
|
50782
|
+
apiKey,
|
|
50783
|
+
api: new WorkflowApi(BASE_URLS.API, apiKey, agentId),
|
|
50784
|
+
json
|
|
50785
|
+
};
|
|
50786
|
+
const code = await executeAction(ctx, resolved, target, extra, options);
|
|
50787
|
+
if (code !== void 0 && code !== 0) process.exitCode = code;
|
|
50543
50788
|
trackEvent("cli_workflows_action", {
|
|
50544
|
-
action:
|
|
50545
|
-
non_interactive: !!action
|
|
50789
|
+
action: resolved,
|
|
50790
|
+
non_interactive: !!action,
|
|
50791
|
+
exit_code: code ?? 0
|
|
50546
50792
|
});
|
|
50547
|
-
|
|
50793
|
+
},
|
|
50794
|
+
"workflows",
|
|
50795
|
+
// LUA-803: a typed refusal that escapes a verb under `--json` (a 403 the client threw, an unreachable host) is
|
|
50796
|
+
// the envelope on stdout — the same shape `apiFailure` prints for a refused verb — never the `✖` line.
|
|
50797
|
+
{
|
|
50798
|
+
json: /* @__PURE__ */ __name(() => !!cmdObj?.json, "json")
|
|
50548
50799
|
}
|
|
50549
|
-
|
|
50550
|
-
showProgress: !json
|
|
50551
|
-
});
|
|
50552
|
-
const ctx = {
|
|
50553
|
-
agentId,
|
|
50554
|
-
apiKey,
|
|
50555
|
-
api: new WorkflowApi(BASE_URLS.API, apiKey, agentId),
|
|
50556
|
-
json
|
|
50557
|
-
};
|
|
50558
|
-
const code = await executeAction(ctx, resolved, target, extra, options);
|
|
50559
|
-
if (code !== void 0 && code !== 0) process.exitCode = code;
|
|
50560
|
-
trackEvent("cli_workflows_action", {
|
|
50561
|
-
action: resolved,
|
|
50562
|
-
non_interactive: !!action,
|
|
50563
|
-
exit_code: code ?? 0
|
|
50564
|
-
});
|
|
50565
|
-
}, "workflows");
|
|
50800
|
+
);
|
|
50566
50801
|
}
|
|
50567
50802
|
__name(workflowsCommand, "workflowsCommand");
|
|
50568
50803
|
async function executeAction(ctx, action, target, extra, o) {
|
|
@@ -50664,18 +50899,12 @@ async function executeAction(ctx, action, target, extra, o) {
|
|
|
50664
50899
|
}
|
|
50665
50900
|
__name(executeAction, "executeAction");
|
|
50666
50901
|
async function requireName(name, verb, fn) {
|
|
50667
|
-
if (!name) {
|
|
50668
|
-
console.error(`\u274C ${verb}: a workflow name is required \u2014 lua workflows ${verb} <name> (or -i <name>)`);
|
|
50669
|
-
return WORKFLOW_EXIT.USAGE;
|
|
50670
|
-
}
|
|
50902
|
+
if (!name) throw CliError.usage(`${verb}: a workflow name is required`, `lua workflows ${verb} <name> (or -i <name>)`);
|
|
50671
50903
|
return fn();
|
|
50672
50904
|
}
|
|
50673
50905
|
__name(requireName, "requireName");
|
|
50674
50906
|
async function requireRun(runId, verb, fn) {
|
|
50675
|
-
if (!runId) {
|
|
50676
|
-
console.error(`\u274C ${verb}: a run id is required \u2014 lua workflows ${verb} <runId> (or -r <runId>)`);
|
|
50677
|
-
return WORKFLOW_EXIT.USAGE;
|
|
50678
|
-
}
|
|
50907
|
+
if (!runId) throw CliError.usage(`${verb}: a run id is required`, `lua workflows ${verb} <runId> (or -r <runId>)`);
|
|
50679
50908
|
return fn();
|
|
50680
50909
|
}
|
|
50681
50910
|
__name(requireRun, "requireRun");
|
|
@@ -50683,46 +50912,67 @@ function emitJson(ctx, res) {
|
|
|
50683
50912
|
if (ctx.json) console.log(JSON.stringify(res, null, 2));
|
|
50684
50913
|
}
|
|
50685
50914
|
__name(emitJson, "emitJson");
|
|
50686
|
-
function
|
|
50687
|
-
|
|
50915
|
+
function refusalExitCode(status) {
|
|
50916
|
+
if (status === 0 || status !== void 0 && status >= 500) return WORKFLOW_EXIT.UNAVAILABLE;
|
|
50917
|
+
if (status === 404) return WORKFLOW_EXIT.NOT_FOUND;
|
|
50918
|
+
return WORKFLOW_EXIT.API;
|
|
50919
|
+
}
|
|
50920
|
+
__name(refusalExitCode, "refusalExitCode");
|
|
50921
|
+
function apiRefusal(res, verb, detail = {}) {
|
|
50688
50922
|
const err = res.error;
|
|
50689
50923
|
const status = err?.statusCode;
|
|
50690
50924
|
const code = err?.code ?? err?.error;
|
|
50691
|
-
const
|
|
50692
|
-
|
|
50693
|
-
|
|
50925
|
+
const serverMessage = err?.message ?? "Unknown error";
|
|
50926
|
+
const message = detail.message ? code ? `${detail.message} (${code})` : detail.message : code ? serverMessage === code ? `${verb} failed (${code})` : `${verb} failed (${code}): ${serverMessage}` : `${verb} failed: ${serverMessage}`;
|
|
50927
|
+
const issues = detail.issues ?? err?.issues;
|
|
50928
|
+
const exitCode = refusalExitCode(status);
|
|
50929
|
+
if (exitCode === WORKFLOW_EXIT.UNAVAILABLE) {
|
|
50930
|
+
return CliError.fromStatus(status, message, status === 503 && code === "CONTROL_UNAVAILABLE" ? CONTROL_UNAVAILABLE_HINT : detail.hint, {
|
|
50931
|
+
serverCode: code,
|
|
50932
|
+
issues
|
|
50933
|
+
});
|
|
50694
50934
|
}
|
|
50695
|
-
|
|
50696
|
-
|
|
50697
|
-
|
|
50935
|
+
return new CliError(exitCode === WORKFLOW_EXIT.NOT_FOUND ? "not_found" : "error", message, {
|
|
50936
|
+
exitCode,
|
|
50937
|
+
statusCode: status,
|
|
50938
|
+
serverCode: code,
|
|
50939
|
+
issues,
|
|
50940
|
+
hint: detail.hint
|
|
50941
|
+
});
|
|
50942
|
+
}
|
|
50943
|
+
__name(apiRefusal, "apiRefusal");
|
|
50944
|
+
function apiFailure(ctx, res, verb, detail = {}) {
|
|
50945
|
+
if (ctx.json) {
|
|
50946
|
+
emitJson(ctx, res);
|
|
50947
|
+
return refusalExitCode(res.error?.statusCode);
|
|
50948
|
+
}
|
|
50949
|
+
throw apiRefusal(res, verb, detail);
|
|
50698
50950
|
}
|
|
50699
50951
|
__name(apiFailure, "apiFailure");
|
|
50700
50952
|
async function resolveWorkflow(ctx, nameOrId) {
|
|
50701
|
-
|
|
50702
|
-
return list && pickWorkflow(list, nameOrId);
|
|
50953
|
+
return pickWorkflow(await loadWorkflowList(ctx), nameOrId);
|
|
50703
50954
|
}
|
|
50704
50955
|
__name(resolveWorkflow, "resolveWorkflow");
|
|
50705
50956
|
async function loadWorkflowList(ctx) {
|
|
50706
50957
|
const res = await ctx.api.getWorkflows({
|
|
50707
50958
|
includeDynamic: true
|
|
50708
50959
|
});
|
|
50709
|
-
if (!res.success || !res.data)
|
|
50710
|
-
console.error(`\u274C Failed to list workflows: ${res.error?.message ?? "Unknown error"}`);
|
|
50711
|
-
return void 0;
|
|
50712
|
-
}
|
|
50960
|
+
if (!res.success || !res.data) throw apiRefusal(res, "list");
|
|
50713
50961
|
return res.data.workflows;
|
|
50714
50962
|
}
|
|
50715
50963
|
__name(loadWorkflowList, "loadWorkflowList");
|
|
50716
50964
|
function pickWorkflow(list, nameOrId) {
|
|
50717
50965
|
const wf = list.find((w) => w.name === nameOrId) ?? list.find((w) => w.id === nameOrId);
|
|
50718
50966
|
if (!wf) {
|
|
50719
|
-
|
|
50720
|
-
const names = list.map((w) => w.name);
|
|
50721
|
-
if (names.length) console.log(` Available: ${names.join(", ")}`);
|
|
50967
|
+
throw CliError.notFound(`Workflow "${nameOrId}" not found`, listHint("Available:", list.map((w) => w.name)));
|
|
50722
50968
|
}
|
|
50723
50969
|
return wf;
|
|
50724
50970
|
}
|
|
50725
50971
|
__name(pickWorkflow, "pickWorkflow");
|
|
50972
|
+
function isDefinitionId(nameOrId) {
|
|
50973
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(nameOrId);
|
|
50974
|
+
}
|
|
50975
|
+
__name(isDefinitionId, "isDefinitionId");
|
|
50726
50976
|
var shortHash = /* @__PURE__ */ __name((h) => h ? h.replace(/^sha256-cj1:/, "").slice(0, 12) : "\u2014", "shortHash");
|
|
50727
50977
|
var when = /* @__PURE__ */ __name((iso) => iso ? new Date(iso).toLocaleString() : "\u2014", "when");
|
|
50728
50978
|
var clockOf = /* @__PURE__ */ __name((at) => {
|
|
@@ -50735,6 +50985,15 @@ var parseIntFlag = /* @__PURE__ */ __name((v, flag) => {
|
|
|
50735
50985
|
if (!Number.isFinite(n2)) throw new WorkflowLocalUsageError("usage", `${flag}: expected a number (got "${v}")`);
|
|
50736
50986
|
return n2;
|
|
50737
50987
|
}, "parseIntFlag");
|
|
50988
|
+
function parsedOrUsage(parse) {
|
|
50989
|
+
try {
|
|
50990
|
+
return parse();
|
|
50991
|
+
} catch (e) {
|
|
50992
|
+
if (e instanceof WorkflowLocalUsageError) throw CliError.usage(e.message);
|
|
50993
|
+
throw e;
|
|
50994
|
+
}
|
|
50995
|
+
}
|
|
50996
|
+
__name(parsedOrUsage, "parsedOrUsage");
|
|
50738
50997
|
async function listCore(ctx, opts) {
|
|
50739
50998
|
const res = await ctx.api.getWorkflows({
|
|
50740
50999
|
includeDynamic: opts.all
|
|
@@ -50921,35 +51180,22 @@ function startResultLine(d, requestedName) {
|
|
|
50921
51180
|
}
|
|
50922
51181
|
__name(startResultLine, "startResultLine");
|
|
50923
51182
|
async function startCore(ctx, name, o) {
|
|
50924
|
-
const
|
|
50925
|
-
|
|
50926
|
-
|
|
50927
|
-
|
|
50928
|
-
|
|
50929
|
-
try {
|
|
50930
|
-
if (o.input) input = parseJsonOrFile(o.input, "--input");
|
|
50931
|
-
waitSeconds = parseIntFlag(o.wait, "--wait");
|
|
50932
|
-
budgetCredits = parseIntegerFlag(o.budgetCredits, "--budget-credits", {
|
|
50933
|
-
min: 1
|
|
50934
|
-
});
|
|
50935
|
-
} catch (e) {
|
|
50936
|
-
if (e instanceof WorkflowLocalUsageError) {
|
|
50937
|
-
console.error(`\u274C ${e.message}`);
|
|
50938
|
-
return WORKFLOW_EXIT.USAGE;
|
|
50939
|
-
}
|
|
50940
|
-
throw e;
|
|
50941
|
-
}
|
|
51183
|
+
const input = parsedOrUsage(() => o.input ? parseJsonOrFile(o.input, "--input") : {});
|
|
51184
|
+
const waitSeconds = parsedOrUsage(() => parseIntFlag(o.wait, "--wait"));
|
|
51185
|
+
const budgetCredits = parsedOrUsage(() => parseIntegerFlag(o.budgetCredits, "--budget-credits", {
|
|
51186
|
+
min: 1
|
|
51187
|
+
}));
|
|
50942
51188
|
if (waitSeconds !== void 0 && (waitSeconds < 0 || waitSeconds > 55)) {
|
|
50943
|
-
|
|
50944
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51189
|
+
throw CliError.usage("--wait must be 0..55 (a server long-poll; the CLI raises its own deadline to wait+10 s)");
|
|
50945
51190
|
}
|
|
50946
51191
|
const tags = o.tag === void 0 ? void 0 : Array.isArray(o.tag) ? o.tag : [
|
|
50947
51192
|
o.tag
|
|
50948
51193
|
];
|
|
50949
|
-
if (tags && tags.length > 10)
|
|
50950
|
-
|
|
50951
|
-
|
|
50952
|
-
|
|
51194
|
+
if (tags && tags.length > 10) throw CliError.usage("--tag: at most 10 tags");
|
|
51195
|
+
const wf = isDefinitionId(name) ? {
|
|
51196
|
+
id: name,
|
|
51197
|
+
name
|
|
51198
|
+
} : await resolveWorkflow(ctx, name);
|
|
50953
51199
|
let workflowVersionId;
|
|
50954
51200
|
if (o.workflowVersion) {
|
|
50955
51201
|
const ref = await resolveVersionRef(ctx, wf, o.workflowVersion, "start");
|
|
@@ -51021,8 +51267,7 @@ async function runsCore(ctx, o) {
|
|
|
51021
51267
|
try {
|
|
51022
51268
|
limit = parseIntFlag(o.limit, "--limit");
|
|
51023
51269
|
} catch (e) {
|
|
51024
|
-
|
|
51025
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51270
|
+
throw CliError.usage(`${e.message}`);
|
|
51026
51271
|
}
|
|
51027
51272
|
const res = await ctx.api.getRuns({
|
|
51028
51273
|
workflowId,
|
|
@@ -51160,6 +51405,8 @@ function printRun(run, withSteps) {
|
|
|
51160
51405
|
console.log(`
|
|
51161
51406
|
\u23F8\uFE0F Paused \u2014 run budget reached (${budgetCopy(run)}):`);
|
|
51162
51407
|
console.log(` lua workflows raise-budget ${id} --credits <n>`);
|
|
51408
|
+
} else if (kind === "billing") {
|
|
51409
|
+
for (const line of billingParkLines(run)) console.log(line);
|
|
51163
51410
|
} else {
|
|
51164
51411
|
console.log(` Gate: ${kind}${run.gate.reason ? ` (${run.gate.reason})` : ""}${run.gate.since ? ` since ${when(run.gate.since)}` : ""}`);
|
|
51165
51412
|
}
|
|
@@ -51208,6 +51455,23 @@ function printRun(run, withSteps) {
|
|
|
51208
51455
|
}
|
|
51209
51456
|
}
|
|
51210
51457
|
__name(printRun, "printRun");
|
|
51458
|
+
function billingParkLines(run) {
|
|
51459
|
+
const id = runIdOf(run);
|
|
51460
|
+
const gate = run.gate ?? {
|
|
51461
|
+
kind: "billing"
|
|
51462
|
+
};
|
|
51463
|
+
const what = gate.code === "out_of_actions" ? "the workspace is out of actions" : "the workspace has no credits left";
|
|
51464
|
+
const step3 = gate.stepId ? ` before step ${gate.stepId}` : "";
|
|
51465
|
+
const out = [
|
|
51466
|
+
`
|
|
51467
|
+
\u23F8\uFE0F Paused \u2014 payment required (${what})${step3}:`
|
|
51468
|
+
];
|
|
51469
|
+
out.push(" top up the workspace (or ask a workspace admin to) \u2014 the run resumes on its own within a few minutes of the top-up");
|
|
51470
|
+
out.push(` to resume it right away after topping up: lua workflows retry-step ${id} --step ${gate.stepId ?? "<stepId>"}`);
|
|
51471
|
+
if (typeof gate.expiresAt === "number") out.push(` still unpaid at ${when(gate.expiresAt)} \u21D2 the run fails`);
|
|
51472
|
+
return out;
|
|
51473
|
+
}
|
|
51474
|
+
__name(billingParkLines, "billingParkLines");
|
|
51211
51475
|
function stepAttemptLines(s) {
|
|
51212
51476
|
const out = [];
|
|
51213
51477
|
const cause = stepFailureLine(s.error);
|
|
@@ -51315,15 +51579,8 @@ function attemptCountersLine(c) {
|
|
|
51315
51579
|
}
|
|
51316
51580
|
__name(attemptCountersLine, "attemptCountersLine");
|
|
51317
51581
|
async function watchCore(ctx, runId, o) {
|
|
51318
|
-
|
|
51319
|
-
|
|
51320
|
-
try {
|
|
51321
|
-
afterSeq = parseIntFlag(o.after, "--after");
|
|
51322
|
-
timeoutS = parseIntFlag(o.timeout, "--timeout");
|
|
51323
|
-
} catch (e) {
|
|
51324
|
-
console.error(`\u274C ${e.message}`);
|
|
51325
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51326
|
-
}
|
|
51582
|
+
const afterSeq = parsedOrUsage(() => parseIntFlag(o.after, "--after"));
|
|
51583
|
+
const timeoutS = parsedOrUsage(() => parseIntFlag(o.timeout, "--timeout"));
|
|
51327
51584
|
const controller = new AbortController();
|
|
51328
51585
|
let timedOut = false;
|
|
51329
51586
|
const timer = timeoutS ? setTimeout(() => (timedOut = true, controller.abort()), timeoutS * 1e3) : void 0;
|
|
@@ -51332,7 +51589,7 @@ async function watchCore(ctx, runId, o) {
|
|
|
51332
51589
|
let lastEventId = afterSeq !== void 0 ? String(afterSeq) : void 0;
|
|
51333
51590
|
let exit;
|
|
51334
51591
|
let reconnects = 0;
|
|
51335
|
-
const
|
|
51592
|
+
const state3 = createWatchState();
|
|
51336
51593
|
try {
|
|
51337
51594
|
while (exit === void 0 && !controller.signal.aborted) {
|
|
51338
51595
|
const res = await ctx.api.watchEvents(runId, {
|
|
@@ -51347,7 +51604,7 @@ async function watchCore(ctx, runId, o) {
|
|
|
51347
51604
|
let sawEnd = false;
|
|
51348
51605
|
for await (const frame of res.data) {
|
|
51349
51606
|
if (frame.id !== void 0) lastEventId = frame.id;
|
|
51350
|
-
const verdict = handleWatchFrame(ctx, runId, frame, o,
|
|
51607
|
+
const verdict = await handleWatchFrame(ctx, runId, frame, o, state3);
|
|
51351
51608
|
if (verdict === "reconnect") break;
|
|
51352
51609
|
if (typeof verdict === "number") {
|
|
51353
51610
|
exit = verdict;
|
|
@@ -51357,10 +51614,10 @@ async function watchCore(ctx, runId, o) {
|
|
|
51357
51614
|
}
|
|
51358
51615
|
if (exit !== void 0 || controller.signal.aborted || sawEnd) break;
|
|
51359
51616
|
reconnects += 1;
|
|
51360
|
-
|
|
51361
|
-
|
|
51362
|
-
|
|
51363
|
-
}
|
|
51617
|
+
resetWatchReplay(state3);
|
|
51618
|
+
if (reconnects > 20) throw new CliError("error", "watch: too many reconnects", {
|
|
51619
|
+
exitCode: WORKFLOW_EXIT.API
|
|
51620
|
+
});
|
|
51364
51621
|
if (!ctx.json) console.error(`\u2026 reconnecting (Last-Event-ID ${lastEventId ?? "none"})`);
|
|
51365
51622
|
await new Promise((r) => setTimeout(r, Math.min(5e3, 250 * 2 ** reconnects)));
|
|
51366
51623
|
}
|
|
@@ -51385,7 +51642,55 @@ function throttledLine(throttled) {
|
|
|
51385
51642
|
].map(([k, n2]) => `${k} \xD7${n2}`).join(" \xB7 ")}`;
|
|
51386
51643
|
}
|
|
51387
51644
|
__name(throttledLine, "throttledLine");
|
|
51388
|
-
function
|
|
51645
|
+
function createWatchState() {
|
|
51646
|
+
return {
|
|
51647
|
+
throttled: /* @__PURE__ */ new Map(),
|
|
51648
|
+
signalNames: /* @__PURE__ */ new Map()
|
|
51649
|
+
};
|
|
51650
|
+
}
|
|
51651
|
+
__name(createWatchState, "createWatchState");
|
|
51652
|
+
function resetWatchReplay(state3) {
|
|
51653
|
+
state3.truth = void 0;
|
|
51654
|
+
state3.pending = void 0;
|
|
51655
|
+
}
|
|
51656
|
+
__name(resetWatchReplay, "resetWatchReplay");
|
|
51657
|
+
async function readWatchTruth(ctx, runId) {
|
|
51658
|
+
try {
|
|
51659
|
+
const res = await ctx.api.getRun(runId);
|
|
51660
|
+
if (!res?.success || !res.data) return null;
|
|
51661
|
+
const run = res.data;
|
|
51662
|
+
return {
|
|
51663
|
+
parked: run.status === "suspended" || run.status === "gated",
|
|
51664
|
+
watermark: typeof run.eventSeq === "number" && Number.isFinite(run.eventSeq) ? run.eventSeq : void 0
|
|
51665
|
+
};
|
|
51666
|
+
} catch {
|
|
51667
|
+
return null;
|
|
51668
|
+
}
|
|
51669
|
+
}
|
|
51670
|
+
__name(readWatchTruth, "readWatchTruth");
|
|
51671
|
+
function frameSeq(frame, ev) {
|
|
51672
|
+
const fromId = frame.id === void 0 ? NaN : Number(frame.id);
|
|
51673
|
+
if (Number.isFinite(fromId)) return fromId;
|
|
51674
|
+
return typeof ev.seq === "number" ? ev.seq : void 0;
|
|
51675
|
+
}
|
|
51676
|
+
__name(frameSeq, "frameSeq");
|
|
51677
|
+
async function watchBoundary(ctx, runId, state3, seq, line, code, emit2) {
|
|
51678
|
+
if (state3.truth === void 0 || state3.truth !== null && state3.truth.watermark === void 0) {
|
|
51679
|
+
state3.truth = await readWatchTruth(ctx, runId);
|
|
51680
|
+
}
|
|
51681
|
+
const truth = state3.truth;
|
|
51682
|
+
if (truth === null) return emit2(line, code);
|
|
51683
|
+
if (truth.watermark === void 0 || seq === void 0) return truth.parked ? emit2(line, code) : void 0;
|
|
51684
|
+
if (seq > truth.watermark) return emit2(line, code);
|
|
51685
|
+
if (!truth.parked) return void 0;
|
|
51686
|
+
state3.pending = {
|
|
51687
|
+
line,
|
|
51688
|
+
code
|
|
51689
|
+
};
|
|
51690
|
+
return void 0;
|
|
51691
|
+
}
|
|
51692
|
+
__name(watchBoundary, "watchBoundary");
|
|
51693
|
+
async function handleWatchFrame(ctx, runId, frame, o, state3) {
|
|
51389
51694
|
const data = frame.data ?? {};
|
|
51390
51695
|
if (o.events || ctx.json) console.log(JSON.stringify({
|
|
51391
51696
|
id: frame.id,
|
|
@@ -51398,10 +51703,17 @@ function handleWatchFrame(ctx, runId, frame, o, throttled) {
|
|
|
51398
51703
|
if (!ctx.json) console.error(" --wait-for-human: still following \u2014 Ctrl+C or --timeout to stop");
|
|
51399
51704
|
return void 0;
|
|
51400
51705
|
}, "humanBoundary");
|
|
51706
|
+
const flushPending = /* @__PURE__ */ __name(() => {
|
|
51707
|
+
const pending = state3.pending;
|
|
51708
|
+
if (!pending) return void 0;
|
|
51709
|
+
state3.pending = void 0;
|
|
51710
|
+
return humanBoundary(pending.line, pending.code);
|
|
51711
|
+
}, "flushPending");
|
|
51401
51712
|
switch (frame.event) {
|
|
51402
51713
|
case "heartbeat":
|
|
51403
|
-
return
|
|
51714
|
+
return flushPending();
|
|
51404
51715
|
case "reconnect":
|
|
51716
|
+
resetWatchReplay(state3);
|
|
51405
51717
|
return "reconnect";
|
|
51406
51718
|
case "error": {
|
|
51407
51719
|
const code = String(data.code ?? "unknown");
|
|
@@ -51418,10 +51730,15 @@ function handleWatchFrame(ctx, runId, frame, o, throttled) {
|
|
|
51418
51730
|
const type = frame.event || ev.type;
|
|
51419
51731
|
if (type === "step.throttled") {
|
|
51420
51732
|
const kind = String(ev.data?.kind ?? "throttled");
|
|
51421
|
-
throttled.set(kind, (throttled.get(kind) ?? 0) + 1);
|
|
51422
|
-
if (!ctx.json && !o.events) process.stdout.write(`\r ${throttledLine(throttled)}`);
|
|
51733
|
+
state3.throttled.set(kind, (state3.throttled.get(kind) ?? 0) + 1);
|
|
51734
|
+
if (!ctx.json && !o.events) process.stdout.write(`\r ${throttledLine(state3.throttled)}`);
|
|
51423
51735
|
return void 0;
|
|
51424
51736
|
}
|
|
51737
|
+
if (type === "step.suspended") {
|
|
51738
|
+
const d = ev.data;
|
|
51739
|
+
const stepId = ev.stepId ?? (typeof d?.stepId === "string" ? d.stepId : void 0);
|
|
51740
|
+
if (stepId && typeof d?.signalName === "string") state3.signalNames.set(stepId, d.signalName);
|
|
51741
|
+
}
|
|
51425
51742
|
if (!ctx.json && !o.events) {
|
|
51426
51743
|
const at = clockOf(ev.ts);
|
|
51427
51744
|
const subrun = subrunEventDetail({
|
|
@@ -51431,39 +51748,58 @@ function handleWatchFrame(ctx, runId, frame, o, throttled) {
|
|
|
51431
51748
|
const detail = subrun ? ` \xB7 ${subrun}` : ev.data ? ` ${JSON.stringify(scrubEventData(ev.data)).slice(0, 160)}` : "";
|
|
51432
51749
|
console.log(`[${at}] ${type}${ev.stepId ? ` \xB7 ${ev.stepId}` : ""}${detail}`);
|
|
51433
51750
|
}
|
|
51434
|
-
if (type === "run.
|
|
51435
|
-
|
|
51436
|
-
|
|
51437
|
-
|
|
51438
|
-
|
|
51439
|
-
|
|
51440
|
-
|
|
51441
|
-
|
|
51442
|
-
|
|
51443
|
-
|
|
51444
|
-
return humanBoundary(`\u23F8\uFE0F run budget reached \u2014 lua workflows raise-budget ${runId} --credits <n> (lua workflows status ${runId} says what a credit buys)`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51445
|
-
}
|
|
51446
|
-
return humanBoundary(`\u23F8\uFE0F run gated (${gate ?? "consent"}) \u2014 approve it from the desktop; then: lua workflows watch ${runId}`, WORKFLOW_EXIT.RUN_GATED);
|
|
51447
|
-
}
|
|
51448
|
-
if (type === "run.suspended") {
|
|
51449
|
-
const kind = ev.data?.kind;
|
|
51450
|
-
const stepId = ev.data?.stepId ?? ev.stepId;
|
|
51451
|
-
if (kind === "approval" || kind === "input" || kind === "signal") {
|
|
51452
|
-
const verb = kind === "approval" ? `lua workflows approve ${runId} --approval <id> --decision approve|deny` : kind === "input" ? `lua workflows resume ${runId} --step ${stepId ?? "<stepId>"} --data <json>` : `lua workflows signal ${runId} <name> --payload <json>`;
|
|
51453
|
-
return humanBoundary(`\u23F8\uFE0F run waits for a person (${kind}${stepId ? ` \xB7 ${stepId}` : ""}) \u2014 ${verb}; then: lua workflows watch ${runId}`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51454
|
-
}
|
|
51455
|
-
}
|
|
51456
|
-
if (type === "run.budget_parked") {
|
|
51457
|
-
return humanBoundary(`\u23F8\uFE0F run budget reached \u2014 lua workflows raise-budget ${runId} --credits <n> (lua workflows status ${runId} says what a credit buys)`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51458
|
-
}
|
|
51459
|
-
if (type === "run.completed") return WORKFLOW_EXIT.OK;
|
|
51460
|
-
if (type === "run.failed" || type === "run.timed_out") return WORKFLOW_EXIT.RUN_FAILED;
|
|
51461
|
-
if (type === "run.cancelled" || type === "run.abandoned") return WORKFLOW_EXIT.RUN_CANCELLED;
|
|
51751
|
+
if (type === "run.resumed") state3.pending = void 0;
|
|
51752
|
+
const seq = frameSeq(frame, ev);
|
|
51753
|
+
const boundary = /* @__PURE__ */ __name((line, code) => watchBoundary(ctx, runId, state3, seq, line, code, humanBoundary), "boundary");
|
|
51754
|
+
const verdict = await boundaryVerdict(runId, {
|
|
51755
|
+
...ev,
|
|
51756
|
+
type
|
|
51757
|
+
}, state3, boundary);
|
|
51758
|
+
if (verdict !== void 0) return verdict;
|
|
51759
|
+
const watermark = state3.truth?.watermark;
|
|
51760
|
+
if (watermark !== void 0 && seq !== void 0 && seq >= watermark) return flushPending();
|
|
51462
51761
|
return void 0;
|
|
51463
51762
|
}
|
|
51464
51763
|
}
|
|
51465
51764
|
}
|
|
51466
51765
|
__name(handleWatchFrame, "handleWatchFrame");
|
|
51766
|
+
async function boundaryVerdict(runId, ev, state3, boundary) {
|
|
51767
|
+
const type = ev.type;
|
|
51768
|
+
if (type === "run.gated") {
|
|
51769
|
+
const gate = ev.data?.gate;
|
|
51770
|
+
const stepId = ev.data?.stepId;
|
|
51771
|
+
if (gate === "exception") {
|
|
51772
|
+
return boundary(`\u26A0\uFE0F run parked on an exception gate \u2014 a human decides next: lua workflows status ${runId}`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51773
|
+
}
|
|
51774
|
+
if (gate === "billing") {
|
|
51775
|
+
return boundary(`\u23F8\uFE0F run parked on a billing gate \u2014 top up the workspace; it resumes within a few minutes (right away: lua workflows retry-step ${runId} --step ${stepId ?? "<stepId>"})`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51776
|
+
}
|
|
51777
|
+
if (gate === "budget") {
|
|
51778
|
+
return boundary(`\u23F8\uFE0F run budget reached \u2014 lua workflows raise-budget ${runId} --credits <n> (lua workflows status ${runId} says what a credit buys)`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51779
|
+
}
|
|
51780
|
+
return boundary(`\u23F8\uFE0F run gated (${gate ?? "consent"}) \u2014 approve it from the desktop; then: lua workflows watch ${runId}`, WORKFLOW_EXIT.RUN_GATED);
|
|
51781
|
+
}
|
|
51782
|
+
if (type === "run.suspended") {
|
|
51783
|
+
const kind = ev.data?.kind;
|
|
51784
|
+
const stepId = ev.data?.stepId ?? ev.stepId;
|
|
51785
|
+
if (kind === "billing") {
|
|
51786
|
+
return boundary(`\u23F8\uFE0F run parked on a billing gate \u2014 top up the workspace; it resumes within a few minutes (right away: lua workflows retry-step ${runId} --step ${stepId ?? "<stepId>"})`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51787
|
+
}
|
|
51788
|
+
if (kind === "approval" || kind === "input" || kind === "signal") {
|
|
51789
|
+
const signalName = stepId ? state3.signalNames.get(stepId) : void 0;
|
|
51790
|
+
const verb = kind === "approval" ? `lua workflows approve ${runId} --approval <id> --decision approve|deny` : kind === "input" ? `lua workflows resume ${runId} --step ${stepId ?? "<stepId>"} --data <json>` : `lua workflows signal ${runId} ${signalName ?? "<name>"} --payload <json>`;
|
|
51791
|
+
return boundary(`\u23F8\uFE0F run waits for a person (${kind}${stepId ? ` \xB7 ${stepId}` : ""}) \u2014 ${verb}; then: lua workflows watch ${runId}`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51792
|
+
}
|
|
51793
|
+
}
|
|
51794
|
+
if (type === "run.budget_parked") {
|
|
51795
|
+
return boundary(`\u23F8\uFE0F run budget reached \u2014 lua workflows raise-budget ${runId} --credits <n> (lua workflows status ${runId} says what a credit buys)`, WORKFLOW_EXIT.RUN_PARKED);
|
|
51796
|
+
}
|
|
51797
|
+
if (type === "run.completed") return WORKFLOW_EXIT.OK;
|
|
51798
|
+
if (type === "run.failed" || type === "run.timed_out") return WORKFLOW_EXIT.RUN_FAILED;
|
|
51799
|
+
if (type === "run.cancelled" || type === "run.abandoned") return WORKFLOW_EXIT.RUN_CANCELLED;
|
|
51800
|
+
return void 0;
|
|
51801
|
+
}
|
|
51802
|
+
__name(boundaryVerdict, "boundaryVerdict");
|
|
51467
51803
|
async function cancelCore(ctx, runId, o) {
|
|
51468
51804
|
const res = await ctx.api.cancelRun(runId, {
|
|
51469
51805
|
mode: o.force ? "force" : "request",
|
|
@@ -51486,45 +51822,48 @@ async function cancelCore(ctx, runId, o) {
|
|
|
51486
51822
|
}
|
|
51487
51823
|
__name(cancelCore, "cancelCore");
|
|
51488
51824
|
async function resumeCore(ctx, runId, o) {
|
|
51489
|
-
if (!o.step)
|
|
51490
|
-
|
|
51491
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51492
|
-
}
|
|
51493
|
-
let resumeData = {};
|
|
51494
|
-
try {
|
|
51495
|
-
if (o.data) resumeData = parseJsonOrFile(o.data, "--data");
|
|
51496
|
-
} catch (e) {
|
|
51497
|
-
console.error(`\u274C ${e.message}`);
|
|
51498
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51499
|
-
}
|
|
51825
|
+
if (!o.step) throw CliError.usage("resume: --step <id> is required");
|
|
51826
|
+
const resumeData = parsedOrUsage(() => o.data ? parseJsonOrFile(o.data, "--data") : {});
|
|
51500
51827
|
const res = await ctx.api.resumeRun(runId, o.step, {
|
|
51501
51828
|
resumeData
|
|
51502
51829
|
});
|
|
51503
|
-
const resumeCode = !res.success ? res.error?.code ?? res.error?.error : void 0;
|
|
51504
|
-
const resumeDetail = res.error;
|
|
51505
|
-
if (!ctx.json && res.error?.statusCode === 400 && resumeCode === "RESUME_SCHEMA_INVALID") {
|
|
51506
|
-
console.error(`\u274C resume rejected \u2014 --data does not match the resumeSchema step "${resumeDetail?.stepId ?? o.step}" declares:`);
|
|
51507
|
-
for (const issue of resumeDetail?.issues ?? []) console.error(` \u2022 ${issue.path || "/"}: ${issue.message ?? "invalid"}`);
|
|
51508
|
-
console.error(" fix the data and resume again (the step is still waiting for input)");
|
|
51509
|
-
} else if (!ctx.json && res.error?.statusCode === 422 && resumeCode === "RESUME_SCHEMA_UNCOMPILABLE") {
|
|
51510
|
-
console.error(`\u274C resume could not be checked \u2014 the resumeSchema step "${resumeDetail?.stepId ?? o.step}" declares does not compile:`);
|
|
51511
|
-
for (const issue of resumeDetail?.issues ?? []) console.error(` \u2022 ${issue.message ?? "schema does not compile"}`);
|
|
51512
|
-
console.error(" this is a workflow definition defect, not a data problem \u2014 fix the `resumeSchema` on the step in the workflow source, push a new version, then resume again");
|
|
51513
|
-
}
|
|
51514
51830
|
if (!res.success || !res.data) {
|
|
51515
51831
|
const code = res.error?.code ?? res.error?.error;
|
|
51516
|
-
|
|
51517
|
-
|
|
51518
|
-
|
|
51519
|
-
|
|
51520
|
-
|
|
51521
|
-
|
|
51522
|
-
|
|
51523
|
-
|
|
51524
|
-
|
|
51525
|
-
|
|
51832
|
+
const status = res.error?.statusCode;
|
|
51833
|
+
const stepOf3 = res.error?.stepId ?? o.step;
|
|
51834
|
+
let detail = {};
|
|
51835
|
+
if (status === 400 && code === "RESUME_SCHEMA_INVALID") {
|
|
51836
|
+
detail = {
|
|
51837
|
+
message: `resume rejected \u2014 --data does not match the resumeSchema step "${stepOf3}" declares`,
|
|
51838
|
+
issues: res.error?.issues,
|
|
51839
|
+
hint: "fix the data and resume again (the step is still waiting for input)"
|
|
51840
|
+
};
|
|
51841
|
+
} else if (status === 422 && code === "RESUME_SCHEMA_UNCOMPILABLE") {
|
|
51842
|
+
detail = {
|
|
51843
|
+
message: `resume could not be checked \u2014 the resumeSchema step "${stepOf3}" declares does not compile`,
|
|
51844
|
+
issues: (res.error?.issues ?? []).map((issue) => ({
|
|
51845
|
+
message: issue.message ?? "schema does not compile"
|
|
51846
|
+
})),
|
|
51847
|
+
hint: "this is a workflow definition defect, not a data problem \u2014 fix the `resumeSchema` on the step in the workflow source, push a new version, then resume again"
|
|
51848
|
+
};
|
|
51849
|
+
} else if (status === 404 && code === "STEP_NOT_FOUND") {
|
|
51850
|
+
detail = {
|
|
51851
|
+
message: `step "${o.step}" does not exist on run ${runId} \u2014 list its steps: lua workflows status ${runId} --steps`
|
|
51852
|
+
};
|
|
51853
|
+
} else if (status === 409 && (code === "approval_requires_human" || code === "APPROVAL_REQUIRES_HUMAN")) {
|
|
51854
|
+
detail = {
|
|
51855
|
+
message: `step "${o.step}" is an approval \u2014 resolve it with: lua workflows approve ${runId} --approval ${o.step} --decision approve`
|
|
51856
|
+
};
|
|
51857
|
+
} else if (status === 409 && (code === "use_signal_route" || code === "USE_SIGNAL_ROUTE")) {
|
|
51858
|
+
detail = {
|
|
51859
|
+
message: `step "${o.step}" waits for a signal \u2014 deliver it with: lua workflows signal ${runId} <name> --payload '{}'`
|
|
51860
|
+
};
|
|
51861
|
+
} else if (status === 409 && code === "NOT_SUSPENDED") {
|
|
51862
|
+
detail = {
|
|
51863
|
+
message: `step "${o.step}" is not suspended${res.error?.status ? ` (it is ${res.error.status})` : ""} \u2014 nothing to resume: lua workflows status ${runId} --steps`
|
|
51864
|
+
};
|
|
51526
51865
|
}
|
|
51527
|
-
return apiFailure(ctx, res, "resume");
|
|
51866
|
+
return apiFailure(ctx, res, "resume", detail);
|
|
51528
51867
|
}
|
|
51529
51868
|
emitJson(ctx, res);
|
|
51530
51869
|
if (!ctx.json) {
|
|
@@ -51539,8 +51878,7 @@ async function resumeCore(ctx, runId, o) {
|
|
|
51539
51878
|
__name(resumeCore, "resumeCore");
|
|
51540
51879
|
async function retryStepCore(ctx, runId, o) {
|
|
51541
51880
|
if (!o.step) {
|
|
51542
|
-
|
|
51543
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51881
|
+
throw CliError.usage("--step <id> is required: lua workflows retry-step <runId> --step <id> [--note <text>]");
|
|
51544
51882
|
}
|
|
51545
51883
|
const res = await ctx.api.retryStep(runId, o.step, {
|
|
51546
51884
|
...o.note ? {
|
|
@@ -51548,21 +51886,30 @@ async function retryStepCore(ctx, runId, o) {
|
|
|
51548
51886
|
} : {}
|
|
51549
51887
|
});
|
|
51550
51888
|
if (!res.success || !res.data) {
|
|
51889
|
+
let detail = {};
|
|
51551
51890
|
const code = res.error?.code ?? res.error?.error;
|
|
51552
|
-
if (
|
|
51553
|
-
|
|
51554
|
-
|
|
51555
|
-
|
|
51556
|
-
|
|
51891
|
+
if (res.error?.statusCode === 404 && code === "STEP_NOT_FOUND") {
|
|
51892
|
+
detail = {
|
|
51893
|
+
message: `step "${o.step}" does not exist on run ${runId} \u2014 list its steps: lua workflows status ${runId} --steps`
|
|
51894
|
+
};
|
|
51895
|
+
} else if (res.error?.statusCode === 409) {
|
|
51896
|
+
if (code === "STEP_NOT_PARKED" || code === "step_not_parked") detail = {
|
|
51897
|
+
message: `step "${o.step}" is not parked (running, pending or already re-armed) \u2014 nothing to retry`
|
|
51898
|
+
};
|
|
51899
|
+
else if (code === "RUN_TERMINAL" || code === "run_terminal") detail = {
|
|
51900
|
+
message: `run ${runId} is terminal \u2014 start a new run instead`
|
|
51901
|
+
};
|
|
51557
51902
|
else if (code === "STEP_RETRY_CAP" || code === "step_retry_cap") {
|
|
51558
51903
|
const cap = res.error;
|
|
51559
51904
|
const at = typeof cap?.attempt === "number" && typeof cap?.maxAttempts === "number" ? ` (attempt ${cap.attempt} of ${cap.maxAttempts})` : "";
|
|
51560
|
-
|
|
51561
|
-
|
|
51562
|
-
|
|
51905
|
+
detail = {
|
|
51906
|
+
message: `step "${o.step}" has reached the retry cap${at} \u2014 resolve it or repair the run`,
|
|
51907
|
+
hint: `lua workflows resolve-step ${runId} --step ${o.step} --outcome skip|complete|fail
|
|
51908
|
+
to start a repair run instead, decide it from the desktop run page`
|
|
51909
|
+
};
|
|
51563
51910
|
}
|
|
51564
51911
|
}
|
|
51565
|
-
return apiFailure(ctx, res, "retry-step");
|
|
51912
|
+
return apiFailure(ctx, res, "retry-step", detail);
|
|
51566
51913
|
}
|
|
51567
51914
|
emitJson(ctx, res);
|
|
51568
51915
|
if (!ctx.json) {
|
|
@@ -51585,29 +51932,24 @@ __name(refusalIssues, "refusalIssues");
|
|
|
51585
51932
|
async function resolveStepCore(ctx, runId, o) {
|
|
51586
51933
|
const usage = "lua workflows resolve-step <runId> --step <id> --outcome skip|complete|fail [--output <json|@file>] [--note <text>]";
|
|
51587
51934
|
if (!o.step) {
|
|
51588
|
-
|
|
51589
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51935
|
+
throw CliError.usage(`--step <id> is required: ${usage}`);
|
|
51590
51936
|
}
|
|
51591
51937
|
const raw = (o.outcome ?? o.action)?.trim().toLowerCase();
|
|
51592
51938
|
if (raw !== "skip" && raw !== "complete" && raw !== "fail") {
|
|
51593
|
-
|
|
51594
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51939
|
+
throw CliError.usage(`--outcome must be skip|complete|fail${raw ? ` (got "${raw}")` : ""}: ${usage}`);
|
|
51595
51940
|
}
|
|
51596
51941
|
const outcome = raw;
|
|
51597
51942
|
let output;
|
|
51598
51943
|
try {
|
|
51599
51944
|
if (o.output !== void 0) output = parseJsonOrFile(o.output, "--output");
|
|
51600
51945
|
} catch (e) {
|
|
51601
|
-
|
|
51602
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51946
|
+
throw CliError.usage(`${e.message}`);
|
|
51603
51947
|
}
|
|
51604
51948
|
if (outcome === "complete" && output === void 0) {
|
|
51605
|
-
|
|
51606
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51949
|
+
throw CliError.usage(`--outcome complete needs --output <json|@file> (the output the step would have produced): ${usage}`);
|
|
51607
51950
|
}
|
|
51608
51951
|
if (outcome !== "complete" && output !== void 0) {
|
|
51609
|
-
|
|
51610
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51952
|
+
throw CliError.usage(`--output rides with --outcome complete only (a ${outcome} carries no output)`);
|
|
51611
51953
|
}
|
|
51612
51954
|
const dto = {
|
|
51613
51955
|
outcome,
|
|
@@ -51620,27 +51962,43 @@ async function resolveStepCore(ctx, runId, o) {
|
|
|
51620
51962
|
};
|
|
51621
51963
|
const res = await ctx.api.resolveStep(runId, o.step, dto);
|
|
51622
51964
|
if (!res.success || !res.data) {
|
|
51965
|
+
let detail = {};
|
|
51623
51966
|
const err = res.error;
|
|
51624
51967
|
const code = err?.code ?? err?.error;
|
|
51625
51968
|
const status = err?.statusCode;
|
|
51626
|
-
if (
|
|
51969
|
+
if (err) {
|
|
51627
51970
|
if (status === 404 && code === "STEP_NOT_FOUND") {
|
|
51628
|
-
|
|
51971
|
+
detail = {
|
|
51972
|
+
message: `step "${o.step}" does not exist on run ${runId} \u2014 list its steps: lua workflows status ${runId} --steps`
|
|
51973
|
+
};
|
|
51629
51974
|
} else if (status === 409 && (code === "STEP_NOT_PARKED" || code === "step_not_parked")) {
|
|
51630
|
-
|
|
51975
|
+
detail = {
|
|
51976
|
+
message: `step "${o.step}" is not parked (running, pending or already decided) \u2014 nothing to resolve`
|
|
51977
|
+
};
|
|
51631
51978
|
} else if (status === 409 && (code === "RUN_TERMINAL" || code === "run_terminal")) {
|
|
51632
|
-
|
|
51979
|
+
detail = {
|
|
51980
|
+
message: `run ${runId} is terminal \u2014 start a new run instead`
|
|
51981
|
+
};
|
|
51633
51982
|
} else if (status === 400 && code === "RESOLVE_OUTPUT_INVALID") {
|
|
51634
|
-
|
|
51635
|
-
|
|
51983
|
+
detail = {
|
|
51984
|
+
message: `--output does not satisfy the outputSchema of step "${o.step}"`,
|
|
51985
|
+
issues: refusalIssues(err).map((i) => ({
|
|
51986
|
+
path: i.path ?? "$",
|
|
51987
|
+
message: i.message ?? i.code
|
|
51988
|
+
}))
|
|
51989
|
+
};
|
|
51636
51990
|
} else if (status === 403 && code === "APPROVAL_REQUIRES_HUMAN") {
|
|
51637
|
-
|
|
51991
|
+
detail = {
|
|
51992
|
+
message: "resolve-step is a person's decision \u2014 sign in (lua login) instead of an API key"
|
|
51993
|
+
};
|
|
51638
51994
|
} else if (status === 413 && code === "OUTPUT_TOO_LARGE") {
|
|
51639
51995
|
const { bytes, maxBytes } = err;
|
|
51640
|
-
|
|
51996
|
+
detail = {
|
|
51997
|
+
message: `--output is over the cap (${bytes ?? "?"} of ${maxBytes ?? 262144} bytes serialized)`
|
|
51998
|
+
};
|
|
51641
51999
|
}
|
|
51642
52000
|
}
|
|
51643
|
-
return apiFailure(ctx, res, "resolve-step");
|
|
52001
|
+
return apiFailure(ctx, res, "resolve-step", detail);
|
|
51644
52002
|
}
|
|
51645
52003
|
emitJson(ctx, res);
|
|
51646
52004
|
if (!ctx.json) {
|
|
@@ -51702,24 +52060,33 @@ async function raiseBudgetCore(ctx, runId, o) {
|
|
|
51702
52060
|
}
|
|
51703
52061
|
const res = await ctx.api.raiseBudget(runId, dto);
|
|
51704
52062
|
if (!res.success || !res.data) {
|
|
52063
|
+
let detail = {};
|
|
51705
52064
|
const err = res.error;
|
|
51706
52065
|
const code = err?.code ?? err?.error;
|
|
51707
52066
|
const status = err?.statusCode;
|
|
51708
|
-
if (
|
|
52067
|
+
if (err) {
|
|
51709
52068
|
if (status === 400 && code === "CAP_EXCEEDED") {
|
|
51710
52069
|
const { cap, value: value3, ceiling } = err;
|
|
51711
|
-
|
|
52070
|
+
detail = {
|
|
52071
|
+
message: `${budgetCapFlag(cap)} ${value3 ?? "?"} is above the org ceiling${ceiling !== void 0 ? ` (${ceiling})` : ""} \u2014 ask an org admin to raise the org cap, or cancel the run`
|
|
52072
|
+
};
|
|
51712
52073
|
} else if (status === 400 && code === "VALIDATION_FAILED") {
|
|
51713
|
-
|
|
51714
|
-
|
|
52074
|
+
detail = {
|
|
52075
|
+
issues: refusalIssues(err),
|
|
52076
|
+
hint: `the raise must be above the current cap \u2014 lua workflows status ${runId} shows it`
|
|
52077
|
+
};
|
|
51715
52078
|
} else if (status === 409 && code === "BUDGET_NOT_RAISABLE") {
|
|
51716
52079
|
const { status: runStatus, notRaisableReason } = err;
|
|
51717
|
-
|
|
52080
|
+
detail = {
|
|
52081
|
+
message: notRaisableReason === "raise_cap" ? `run ${runId} has reached its raise cap \u2014 cancel it, or start a new run with a larger --budget-credits` : `run ${runId} is ${runStatus ?? "not parked on its budget"} \u2014 only a run parked on its budget takes a raise`
|
|
52082
|
+
};
|
|
51718
52083
|
} else if (status === 403 && code === "NOT_RUN_CREATOR") {
|
|
51719
|
-
|
|
52084
|
+
detail = {
|
|
52085
|
+
message: "only the run creator or an org admin can raise a run budget"
|
|
52086
|
+
};
|
|
51720
52087
|
}
|
|
51721
52088
|
}
|
|
51722
|
-
return apiFailure(ctx, res, "raise-budget");
|
|
52089
|
+
return apiFailure(ctx, res, "raise-budget", detail);
|
|
51723
52090
|
}
|
|
51724
52091
|
emitJson(ctx, res);
|
|
51725
52092
|
if (!ctx.json) {
|
|
@@ -51746,24 +52113,20 @@ function approveResultLine(d) {
|
|
|
51746
52113
|
__name(approveResultLine, "approveResultLine");
|
|
51747
52114
|
async function approveCore(ctx, runId, o) {
|
|
51748
52115
|
if (!o.approval) {
|
|
51749
|
-
|
|
51750
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52116
|
+
throw CliError.usage("approve: --approval <id> is required");
|
|
51751
52117
|
}
|
|
51752
52118
|
const decision = o.decision ?? "approve";
|
|
51753
52119
|
if (decision !== "approve" && decision !== "deny") {
|
|
51754
|
-
|
|
51755
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52120
|
+
throw CliError.usage("approve: --decision must be approve|deny");
|
|
51756
52121
|
}
|
|
51757
52122
|
let editedPayload;
|
|
51758
52123
|
try {
|
|
51759
52124
|
if (o.edit) editedPayload = parseJsonOrFile(o.edit, "--edit");
|
|
51760
52125
|
} catch (e) {
|
|
51761
|
-
|
|
51762
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52126
|
+
throw CliError.usage(`${e.message}`);
|
|
51763
52127
|
}
|
|
51764
52128
|
if (editedPayload !== void 0 && !o.fingerprint) {
|
|
51765
|
-
|
|
51766
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52129
|
+
throw CliError.usage("approve: --fingerprint <f> is mandatory with --edit (the payloadFingerprint from approval-payload)");
|
|
51767
52130
|
}
|
|
51768
52131
|
const res = await ctx.api.resolveApproval(runId, o.approval, {
|
|
51769
52132
|
decision,
|
|
@@ -51772,15 +52135,22 @@ async function approveCore(ctx, runId, o) {
|
|
|
51772
52135
|
expectedFingerprint: o.fingerprint
|
|
51773
52136
|
});
|
|
51774
52137
|
if (!res.success || !res.data) {
|
|
52138
|
+
let detail = {};
|
|
51775
52139
|
const code = res.error?.code ?? res.error?.error;
|
|
51776
|
-
if (
|
|
51777
|
-
|
|
51778
|
-
|
|
51779
|
-
|
|
51780
|
-
} else if (
|
|
51781
|
-
|
|
52140
|
+
if (res.error?.statusCode === 404 && code === "APPROVAL_NOT_FOUND") {
|
|
52141
|
+
detail = {
|
|
52142
|
+
message: `approval "${o.approval}" not found on run ${runId} \u2014 pass the pending approval's wfa_\u2026 id: lua workflows status ${runId} --steps --json shows it as the suspended step's suspend.approvalId`
|
|
52143
|
+
};
|
|
52144
|
+
} else if (res.error?.statusCode === 409 && code === "PAYLOAD_MISMATCH") {
|
|
52145
|
+
detail = {
|
|
52146
|
+
message: `the payload changed since you looked \u2014 refetch: lua workflows approval-payload ${runId} --approval ${o.approval}`
|
|
52147
|
+
};
|
|
52148
|
+
} else if (res.error?.statusCode === 403 && code === "STEP_UP_REQUIRED") {
|
|
52149
|
+
detail = {
|
|
52150
|
+
message: "approve from the desktop with a fresh login (step-up required)"
|
|
52151
|
+
};
|
|
51782
52152
|
}
|
|
51783
|
-
return apiFailure(ctx, res, "approve");
|
|
52153
|
+
return apiFailure(ctx, res, "approve", detail);
|
|
51784
52154
|
}
|
|
51785
52155
|
emitJson(ctx, res);
|
|
51786
52156
|
if (!ctx.json) {
|
|
@@ -51794,8 +52164,7 @@ var indentBlock = /* @__PURE__ */ __name((text, pad2 = " ") => text.split("\
|
|
|
51794
52164
|
var APPROVAL_PAYLOAD_PAGE_MAX = 100;
|
|
51795
52165
|
async function approvalPayloadCore(ctx, runId, o) {
|
|
51796
52166
|
if (!o.approval) {
|
|
51797
|
-
|
|
51798
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52167
|
+
throw CliError.usage("approval-payload: --approval <id> is required \u2014 lua workflows approval-payload <runId> --approval <wfa_\u2026> [--path <array.path>]");
|
|
51799
52168
|
}
|
|
51800
52169
|
let limit;
|
|
51801
52170
|
try {
|
|
@@ -51808,8 +52177,7 @@ async function approvalPayloadCore(ctx, runId, o) {
|
|
|
51808
52177
|
throw e;
|
|
51809
52178
|
}
|
|
51810
52179
|
if ((o.cursor || limit !== void 0) && !o.path) {
|
|
51811
|
-
|
|
51812
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52180
|
+
throw CliError.usage("approval-payload: --cursor / --limit page one array \u2014 pass --path <array.path> with them");
|
|
51813
52181
|
}
|
|
51814
52182
|
const res = await ctx.api.getApprovalPayload(runId, o.approval, {
|
|
51815
52183
|
path: o.path,
|
|
@@ -51817,13 +52185,18 @@ async function approvalPayloadCore(ctx, runId, o) {
|
|
|
51817
52185
|
limit
|
|
51818
52186
|
});
|
|
51819
52187
|
if (!res.success || !res.data) {
|
|
52188
|
+
let detail = {};
|
|
51820
52189
|
const code = res.error?.code ?? res.error?.error;
|
|
51821
|
-
if (
|
|
51822
|
-
|
|
51823
|
-
|
|
51824
|
-
|
|
52190
|
+
if (res.error?.statusCode === 404 && code === "APPROVAL_NOT_FOUND") {
|
|
52191
|
+
detail = {
|
|
52192
|
+
message: `approval "${o.approval}" not found on run ${runId} \u2014 lua workflows status ${runId} --steps --json shows the suspended step's suspend.approvalId`
|
|
52193
|
+
};
|
|
52194
|
+
} else if (res.error?.statusCode === 413 && code === "PAYLOAD_PAGE_REQUIRED") {
|
|
52195
|
+
detail = {
|
|
52196
|
+
message: "the payload is too large to read whole \u2014 page an array with --path <array.path> [--limit <n>] [--cursor <c>]"
|
|
52197
|
+
};
|
|
51825
52198
|
}
|
|
51826
|
-
return apiFailure(ctx, res, "approval-payload");
|
|
52199
|
+
return apiFailure(ctx, res, "approval-payload", detail);
|
|
51827
52200
|
}
|
|
51828
52201
|
emitJson(ctx, res);
|
|
51829
52202
|
if (!ctx.json) {
|
|
@@ -51887,16 +52260,9 @@ function reservedSecretKeyPaths(value3, path25 = "", depth = 0, out = []) {
|
|
|
51887
52260
|
__name(reservedSecretKeyPaths, "reservedSecretKeyPaths");
|
|
51888
52261
|
async function signalCore(ctx, runId, name, o) {
|
|
51889
52262
|
if (!name) {
|
|
51890
|
-
|
|
51891
|
-
return WORKFLOW_EXIT.USAGE;
|
|
51892
|
-
}
|
|
51893
|
-
let payload;
|
|
51894
|
-
try {
|
|
51895
|
-
if (o.payload) payload = parseJsonOrFile(o.payload, "--payload");
|
|
51896
|
-
} catch (e) {
|
|
51897
|
-
console.error(`\u274C ${e.message}`);
|
|
51898
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52263
|
+
throw CliError.usage("signal: a signal name is required", "lua workflows signal <runId> <name> [--payload <json|@file>]");
|
|
51899
52264
|
}
|
|
52265
|
+
const payload = parsedOrUsage(() => o.payload ? parseJsonOrFile(o.payload, "--payload") : void 0);
|
|
51900
52266
|
const reserved = reservedSecretKeyPaths(payload);
|
|
51901
52267
|
if (reserved.length > 0) {
|
|
51902
52268
|
const many = reserved.length > 1;
|
|
@@ -51908,22 +52274,24 @@ async function signalCore(ctx, runId, name, o) {
|
|
|
51908
52274
|
});
|
|
51909
52275
|
if (!res.success || !res.data) {
|
|
51910
52276
|
const code = res.error?.code ?? res.error?.error;
|
|
51911
|
-
|
|
51912
|
-
|
|
51913
|
-
|
|
51914
|
-
|
|
51915
|
-
|
|
51916
|
-
|
|
51917
|
-
|
|
51918
|
-
|
|
51919
|
-
|
|
51920
|
-
|
|
51921
|
-
|
|
51922
|
-
|
|
51923
|
-
|
|
51924
|
-
|
|
52277
|
+
const where = res.error?.stepId ? `step "${res.error.stepId}"` : "the waiting step";
|
|
52278
|
+
let detail = {};
|
|
52279
|
+
if (res.error?.statusCode === 400 && code === "SIGNAL_SCHEMA_INVALID") {
|
|
52280
|
+
detail = {
|
|
52281
|
+
message: `signal "${name}" rejected \u2014 the payload does not match the schema ${where} declares`,
|
|
52282
|
+
issues: res.error?.issues,
|
|
52283
|
+
hint: "fix the payload and send it again (a --dedupe-key is not consumed by a rejected signal)"
|
|
52284
|
+
};
|
|
52285
|
+
} else if (res.error?.statusCode === 422 && code === "SIGNAL_SCHEMA_UNCOMPILABLE") {
|
|
52286
|
+
detail = {
|
|
52287
|
+
message: `signal "${name}" could not be checked \u2014 the schema ${where} declares does not compile`,
|
|
52288
|
+
issues: (res.error?.issues ?? []).map((issue) => ({
|
|
52289
|
+
message: issue.message ?? "schema does not compile"
|
|
52290
|
+
})),
|
|
52291
|
+
hint: "this is a workflow definition defect, not a payload problem \u2014 fix the `schema` on the waitForSignal node in the workflow source, push a new version, then send the signal again"
|
|
52292
|
+
};
|
|
51925
52293
|
}
|
|
51926
|
-
return apiFailure(ctx, res, "signal");
|
|
52294
|
+
return apiFailure(ctx, res, "signal", detail);
|
|
51927
52295
|
}
|
|
51928
52296
|
emitJson(ctx, res);
|
|
51929
52297
|
const r = res.data;
|
|
@@ -51936,8 +52304,7 @@ async function signalCore(ctx, runId, name, o) {
|
|
|
51936
52304
|
__name(signalCore, "signalCore");
|
|
51937
52305
|
async function replayCore(ctx, runId, o) {
|
|
51938
52306
|
if (!o.local) {
|
|
51939
|
-
|
|
51940
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52307
|
+
throw CliError.usage("replay: only `--local` is available (server-side replay is not a v1 route)");
|
|
51941
52308
|
}
|
|
51942
52309
|
const runRes = await ctx.api.getRun(runId);
|
|
51943
52310
|
if (!runRes.success || !runRes.data) return apiFailure(ctx, runRes, "replay");
|
|
@@ -51946,8 +52313,7 @@ async function replayCore(ctx, runId, o) {
|
|
|
51946
52313
|
try {
|
|
51947
52314
|
manifestWorkflows = getPrimitivesByKind(loadManifest(), PrimitiveKind.WORKFLOW);
|
|
51948
52315
|
} catch (e) {
|
|
51949
|
-
|
|
51950
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52316
|
+
throw CliError.usage(`replay --local needs a compiled project: ${e.message}`);
|
|
51951
52317
|
}
|
|
51952
52318
|
const wf = (o.workflowName ? manifestWorkflows.find((w) => w.name === o.workflowName) : void 0) ?? manifestWorkflows.find((w) => w.graphHash === run.graphHash);
|
|
51953
52319
|
if (!wf) {
|
|
@@ -52193,11 +52559,11 @@ async function deleteRunCore(ctx, runId, o) {
|
|
|
52193
52559
|
const res = await ctx.api.eraseRun(runId);
|
|
52194
52560
|
if (!res.success || !res.data) {
|
|
52195
52561
|
const code = res.error?.code ?? res.error?.error;
|
|
52196
|
-
if (
|
|
52562
|
+
if (res.error?.statusCode === 409 && code === "RUN_NOT_TERMINAL") {
|
|
52197
52563
|
const status = res.error.status;
|
|
52198
|
-
|
|
52199
|
-
|
|
52200
|
-
|
|
52564
|
+
return apiFailure(ctx, res, "delete-run", {
|
|
52565
|
+
message: `run is \`${status ?? "live"}\`; cancel it first: lua workflows cancel ${runId}`
|
|
52566
|
+
});
|
|
52201
52567
|
}
|
|
52202
52568
|
return apiFailure(ctx, res, "delete-run");
|
|
52203
52569
|
}
|
|
@@ -52315,17 +52681,14 @@ async function archiveRunsCore(ctx, o) {
|
|
|
52315
52681
|
const now = Date.now();
|
|
52316
52682
|
const since = parseSinceFlag(o.since, now);
|
|
52317
52683
|
if (!Number.isFinite(since)) {
|
|
52318
|
-
|
|
52319
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52684
|
+
throw CliError.usage("archive-runs: --since <iso|dur> is required (e.g. --since 8d)");
|
|
52320
52685
|
}
|
|
52321
52686
|
const until = o.until ? Date.parse(o.until) : void 0;
|
|
52322
52687
|
if (o.until && !Number.isFinite(until)) {
|
|
52323
|
-
|
|
52324
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52688
|
+
throw CliError.usage(`archive-runs: --until is not an ISO timestamp ("${o.until}")`);
|
|
52325
52689
|
}
|
|
52326
52690
|
if (!o.out) {
|
|
52327
|
-
|
|
52328
|
-
return WORKFLOW_EXIT.USAGE;
|
|
52691
|
+
throw CliError.usage("archive-runs: --out <dir> is required");
|
|
52329
52692
|
}
|
|
52330
52693
|
if (/^(s3|gs):\/\//.test(o.out)) {
|
|
52331
52694
|
console.error(`\u274C archive-runs: remote sinks (${o.out}) need the org storage connection (--connection) \u2014 not wired in this build; archive to a local dir and sync it`);
|
|
@@ -52589,11 +52952,14 @@ async function workspaceCore(ctx, runId, o) {
|
|
|
52589
52952
|
note: o.note
|
|
52590
52953
|
} : {});
|
|
52591
52954
|
if (!res2.success || !res2.data) {
|
|
52592
|
-
|
|
52955
|
+
let detail = {};
|
|
52956
|
+
if (res2.error?.statusCode === 409) {
|
|
52593
52957
|
const stepId = res2.error.stepId;
|
|
52594
|
-
|
|
52958
|
+
detail = {
|
|
52959
|
+
message: `Workspace of ${runId} is in use${stepId ? ` by step ${stepId}` : ""} \u2014 cancel the run or wait for the step to finish`
|
|
52960
|
+
};
|
|
52595
52961
|
}
|
|
52596
|
-
return apiFailure(ctx, res2, "workspace");
|
|
52962
|
+
return apiFailure(ctx, res2, "workspace", detail);
|
|
52597
52963
|
}
|
|
52598
52964
|
emitJson(ctx, res2);
|
|
52599
52965
|
if (!ctx.json) {
|
|
@@ -52674,14 +53040,12 @@ function printJobHeader(v) {
|
|
|
52674
53040
|
__name(printJobHeader, "printJobHeader");
|
|
52675
53041
|
async function jobLogsCore(ctx, runId, stepId, o) {
|
|
52676
53042
|
if (!stepId) {
|
|
52677
|
-
|
|
52678
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53043
|
+
throw CliError.usage(`job-logs: a step id is required \u2014 lua workflows job-logs ${runId} <stepId>`);
|
|
52679
53044
|
}
|
|
52680
53045
|
const attempt = o.attempt !== void 0 && o.attempt !== "" ? Number(o.attempt) : void 0;
|
|
52681
53046
|
const tail = o.tail !== void 0 && o.tail !== "" ? Number(o.tail) : JOB_LOG_TAIL_DEFAULT;
|
|
52682
53047
|
if (attempt !== void 0 && !(Number.isInteger(attempt) && attempt >= 1) || !(Number.isInteger(tail) && tail >= 1 && tail <= JOB_LOG_TAIL_MAX)) {
|
|
52683
|
-
|
|
52684
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53048
|
+
throw CliError.usage(`job-logs: --attempt must be \u2265 1 and --tail an integer in 1..${JOB_LOG_TAIL_MAX}`);
|
|
52685
53049
|
}
|
|
52686
53050
|
let printed = 0;
|
|
52687
53051
|
let first = true;
|
|
@@ -52691,18 +53055,18 @@ async function jobLogsCore(ctx, runId, stepId, o) {
|
|
|
52691
53055
|
tail
|
|
52692
53056
|
});
|
|
52693
53057
|
if (!res.success || !res.data) {
|
|
52694
|
-
|
|
52695
|
-
|
|
52696
|
-
|
|
52697
|
-
|
|
52698
|
-
|
|
52699
|
-
|
|
52700
|
-
|
|
52701
|
-
|
|
52702
|
-
|
|
52703
|
-
|
|
53058
|
+
let detail = {};
|
|
53059
|
+
if (res.error?.statusCode === 404 && res.error?.code === "JOB_NOT_FOUND") {
|
|
53060
|
+
detail = {
|
|
53061
|
+
message: `${stepId} is not a Job-tier step of ${runId} (try: lua workflows jobs ${runId})`
|
|
53062
|
+
};
|
|
53063
|
+
} else if (res.error?.statusCode === 404 && res.error?.code === "JOB_LOGS_NOT_PERSISTED") {
|
|
53064
|
+
detail = {
|
|
53065
|
+
message: `job-logs: ${res.error.message}`,
|
|
53066
|
+
hint: `lua workflows status ${runId} --steps shows the step error; --attempt <n> reads another attempt.`
|
|
53067
|
+
};
|
|
52704
53068
|
}
|
|
52705
|
-
return apiFailure(ctx, res, "job-logs");
|
|
53069
|
+
return apiFailure(ctx, res, "job-logs", detail);
|
|
52706
53070
|
}
|
|
52707
53071
|
const v = res.data;
|
|
52708
53072
|
if (ctx.json && !o.follow) {
|
|
@@ -52965,38 +53329,54 @@ function subVerb(group, noun, raw, verbs) {
|
|
|
52965
53329
|
}
|
|
52966
53330
|
__name(subVerb, "subVerb");
|
|
52967
53331
|
function goalFailure(ctx, res, verb, ref) {
|
|
53332
|
+
let detail = {};
|
|
52968
53333
|
const err = res.error;
|
|
52969
53334
|
const code = err?.code ?? err?.error;
|
|
52970
53335
|
const status = err?.statusCode;
|
|
52971
|
-
if (
|
|
53336
|
+
if (err) {
|
|
52972
53337
|
if (status === 409 && code === "GOAL_NOT_ACTIVE") {
|
|
52973
53338
|
const now = err.status ?? "not active";
|
|
52974
53339
|
const rule = verb === "goals resume" ? "only a paused goal resumes" : verb === "goals pause" ? "only an active goal pauses" : "a done/closed goal stays closed (a lingering cadence Job goes with `lua workflows schedules delete <jobId>`)";
|
|
52975
|
-
|
|
52976
|
-
|
|
53340
|
+
detail = {
|
|
53341
|
+
message: `goal ${ref ?? ""} is ${now} \u2014 ${rule}`,
|
|
53342
|
+
hint: verb === "goals resume" && now === "paused" ? goalRaiseHint(ref ?? "<goalId>") : void 0
|
|
53343
|
+
};
|
|
52977
53344
|
} else if (status === 400 && code === "GOAL_RAISE_BELOW_SPENT") {
|
|
52978
53345
|
const { field, value: value3, spent } = err;
|
|
52979
53346
|
const flag = field === "maxRuns" ? "--max-runs" : "--max-credits";
|
|
52980
53347
|
const used = field === "maxRuns" ? "run(s) already used" : "credit(s) already spent";
|
|
52981
|
-
|
|
53348
|
+
detail = {
|
|
53349
|
+
message: `${flag} ${value3 ?? "?"} is not above the ${spent ?? "?"} ${used} \u2014 raise it past ${spent ?? "?"}`
|
|
53350
|
+
};
|
|
52982
53351
|
} else if (status === 409 && code === "GOAL_VERSION_CONFLICT") {
|
|
52983
53352
|
const at = err.updatedAt;
|
|
52984
|
-
|
|
53353
|
+
detail = {
|
|
53354
|
+
message: `goal ${ref ?? ""} changed since it was read${at ? ` (updatedAt ${at})` : ""} \u2014 re-run lua workflows goals get ${ref ?? "<goalId>"} and retry${at ? ` with --if-match ${at}` : ""}`
|
|
53355
|
+
};
|
|
52985
53356
|
} else if (status === 409 && code === "GOAL_CAP") {
|
|
52986
|
-
|
|
53357
|
+
detail = {
|
|
53358
|
+
message: `goal cap reached (${err.cap ?? "?"} per agent) \u2014 close or finish one first: lua workflows goals list --status active`
|
|
53359
|
+
};
|
|
52987
53360
|
} else if (status === 400 && code === "VALIDATION_FAILED") {
|
|
52988
|
-
|
|
52989
|
-
|
|
53361
|
+
detail = {
|
|
53362
|
+
issues: refusalIssues(err)
|
|
53363
|
+
};
|
|
52990
53364
|
} else if (status === 400 && code === "GOAL_MAX_RUNS_INVALID") {
|
|
52991
|
-
|
|
53365
|
+
detail = {
|
|
53366
|
+
message: `--max-runs must be 1..${GOAL_MAX_RUNS_CAP}`
|
|
53367
|
+
};
|
|
52992
53368
|
} else if (status === 400 && code === "WORKFLOW_NOT_ON_AGENT") {
|
|
52993
|
-
|
|
53369
|
+
detail = {
|
|
53370
|
+
message: `that workflow belongs to another agent \u2014 goals are scoped to ${ctx.agentId}`
|
|
53371
|
+
};
|
|
52994
53372
|
} else if (status === 409 && code === "GOAL_SCHEDULE") {
|
|
52995
53373
|
const goalId = err.goalId ?? "?";
|
|
52996
|
-
|
|
53374
|
+
detail = {
|
|
53375
|
+
message: `GOAL_SCHEDULE: ${goalScheduleRefusal(ref ?? "<jobId>", goalId)}`
|
|
53376
|
+
};
|
|
52997
53377
|
}
|
|
52998
53378
|
}
|
|
52999
|
-
return apiFailure(ctx, res, verb);
|
|
53379
|
+
return apiFailure(ctx, res, verb, detail);
|
|
53000
53380
|
}
|
|
53001
53381
|
__name(goalFailure, "goalFailure");
|
|
53002
53382
|
async function goalsCore(ctx, target, extra, o) {
|
|
@@ -53005,8 +53385,7 @@ async function goalsCore(ctx, target, extra, o) {
|
|
|
53005
53385
|
if (verb === "list") return goalsListCore(ctx, o, extra);
|
|
53006
53386
|
if (verb === "create") return goalsCreateCore(ctx, o, extra);
|
|
53007
53387
|
if (!extra) {
|
|
53008
|
-
|
|
53009
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53388
|
+
throw CliError.usage(`goals ${verb}: a goal id is required \u2014 lua workflows goals ${verb} <goalId>`);
|
|
53010
53389
|
}
|
|
53011
53390
|
if (verb === "get") return goalsGetCore(ctx, extra);
|
|
53012
53391
|
if (verb === "edit") return goalsEditCore(ctx, extra, o);
|
|
@@ -53016,8 +53395,7 @@ async function goalsCore(ctx, target, extra, o) {
|
|
|
53016
53395
|
__name(goalsCore, "goalsCore");
|
|
53017
53396
|
async function goalsListCore(ctx, o, positional) {
|
|
53018
53397
|
if (o.status && !GOAL_STATUSES.includes(o.status)) {
|
|
53019
|
-
|
|
53020
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53398
|
+
throw CliError.usage(`goals list: --status must be ${GOAL_STATUSES.join("|")} (got "${o.status}")`);
|
|
53021
53399
|
}
|
|
53022
53400
|
let limit;
|
|
53023
53401
|
try {
|
|
@@ -53026,8 +53404,7 @@ async function goalsListCore(ctx, o, positional) {
|
|
|
53026
53404
|
max: GOAL_PAGE_LIMIT
|
|
53027
53405
|
});
|
|
53028
53406
|
} catch (e) {
|
|
53029
|
-
|
|
53030
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53407
|
+
throw CliError.usage(`${e.message}`);
|
|
53031
53408
|
}
|
|
53032
53409
|
const list = await loadWorkflowList(ctx);
|
|
53033
53410
|
if (!list) return WORKFLOW_EXIT.API;
|
|
@@ -53188,8 +53565,7 @@ async function goalsEditCore(ctx, goalId, o) {
|
|
|
53188
53565
|
if (Object.keys(dto).filter((k) => k !== "ifMatch").length === 0) throw usage("nothing to change \u2014 pass --objective, --judge-predicate, --cadence | --every, --max-runs, --max-credits <n|none> or --note");
|
|
53189
53566
|
} catch (e) {
|
|
53190
53567
|
if (e instanceof WorkflowLocalUsageError) {
|
|
53191
|
-
|
|
53192
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53568
|
+
throw CliError.usage(`goals edit: ${e.message}`);
|
|
53193
53569
|
}
|
|
53194
53570
|
throw e;
|
|
53195
53571
|
}
|
|
@@ -53221,8 +53597,7 @@ async function goalsRaiseCore(ctx, goalId, o) {
|
|
|
53221
53597
|
if (ifMatch !== void 0) dto.ifMatch = ifMatch;
|
|
53222
53598
|
} catch (e) {
|
|
53223
53599
|
if (e instanceof WorkflowLocalUsageError) {
|
|
53224
|
-
|
|
53225
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53600
|
+
throw CliError.usage(`goals raise: ${e.message}`);
|
|
53226
53601
|
}
|
|
53227
53602
|
throw e;
|
|
53228
53603
|
}
|
|
@@ -53308,20 +53683,16 @@ __name(parseCadenceFlag, "parseCadenceFlag");
|
|
|
53308
53683
|
async function goalsCreateCore(ctx, o, positional) {
|
|
53309
53684
|
const target = positional ?? o.workflowName ?? o.workflow;
|
|
53310
53685
|
if (!target) {
|
|
53311
|
-
|
|
53312
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53686
|
+
throw CliError.usage("goals create: a workflow is required \u2014 lua workflows goals create <workflow> (or -i <workflow>)");
|
|
53313
53687
|
}
|
|
53314
53688
|
if (!o.objective?.trim()) {
|
|
53315
|
-
|
|
53316
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53689
|
+
throw CliError.usage("goals create: --objective <text> is required");
|
|
53317
53690
|
}
|
|
53318
53691
|
if (o.judgeAgent === "") {
|
|
53319
|
-
|
|
53320
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53692
|
+
throw CliError.usage("goals create: --judge-agent is empty \u2014 an unquoted $self is expanded by the shell to nothing; write '$self' (quoted) or self");
|
|
53321
53693
|
}
|
|
53322
53694
|
if (!o.judgePredicate && !o.judgeAgent) {
|
|
53323
|
-
|
|
53324
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53695
|
+
throw CliError.usage("goals create: one of --judge-predicate <spec> | --judge-agent <agentId|'$self'> is required");
|
|
53325
53696
|
}
|
|
53326
53697
|
const usage = /* @__PURE__ */ __name((m) => new WorkflowLocalUsageError("usage", m), "usage");
|
|
53327
53698
|
let dto;
|
|
@@ -53381,8 +53752,7 @@ async function goalsCreateCore(ctx, o, positional) {
|
|
|
53381
53752
|
};
|
|
53382
53753
|
} catch (e) {
|
|
53383
53754
|
if (e instanceof WorkflowLocalUsageError) {
|
|
53384
|
-
|
|
53385
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53755
|
+
throw CliError.usage(`${e.message}`);
|
|
53386
53756
|
}
|
|
53387
53757
|
throw e;
|
|
53388
53758
|
}
|
|
@@ -53424,8 +53794,7 @@ async function schedulesCore(ctx, target, extra, o) {
|
|
|
53424
53794
|
if (verb === "list") return schedulesListCore(ctx, o);
|
|
53425
53795
|
if (verb === "create") return schedulesCreateCore(ctx, o, extra);
|
|
53426
53796
|
if (!extra) {
|
|
53427
|
-
|
|
53428
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53797
|
+
throw CliError.usage(`schedules ${verb}: a schedule (job) id is required \u2014 lua workflows schedules ${verb} <jobId>`);
|
|
53429
53798
|
}
|
|
53430
53799
|
if (verb === "delete") return schedulesDeleteCore(ctx, extra, o);
|
|
53431
53800
|
return schedulesPatchCore(ctx, extra, verb, o);
|
|
@@ -53480,17 +53849,19 @@ async function schedulesDeleteCore(ctx, jobId, o) {
|
|
|
53480
53849
|
const goalRes = await ctx.api.getGoal(goalId);
|
|
53481
53850
|
if (goalRes.success && goalRes.data) goalStatus = goalRes.data.status;
|
|
53482
53851
|
else if (goalRes.error?.statusCode !== 404) {
|
|
53483
|
-
|
|
53484
|
-
|
|
53852
|
+
return apiFailure(ctx, goalRes, "schedules delete", {
|
|
53853
|
+
message: `cannot prove goal ${goalId} of ${jobId} has ended (goal unreadable) \u2014 refusing to delete`
|
|
53854
|
+
});
|
|
53485
53855
|
}
|
|
53486
53856
|
} else {
|
|
53487
53857
|
const goals = await loadGoals(ctx, row2.workflowId);
|
|
53488
53858
|
if (goals.error) {
|
|
53489
|
-
if (!ctx.json) console.error(`\u274C cannot prove ${jobId} is not a goal's cadence (goals unavailable) \u2014 refusing to delete`);
|
|
53490
53859
|
return apiFailure(ctx, {
|
|
53491
53860
|
success: false,
|
|
53492
53861
|
error: goals.error
|
|
53493
|
-
}, "schedules delete"
|
|
53862
|
+
}, "schedules delete", {
|
|
53863
|
+
message: `cannot prove ${jobId} is not a goal's cadence (goals unavailable) \u2014 refusing to delete`
|
|
53864
|
+
});
|
|
53494
53865
|
}
|
|
53495
53866
|
const owner = goals.items.find((g) => g.jobId === jobId);
|
|
53496
53867
|
goalId = owner?.goalId;
|
|
@@ -53541,8 +53912,7 @@ var SCHEDULE_NOTIFY = [
|
|
|
53541
53912
|
async function schedulesCreateCore(ctx, o, positional) {
|
|
53542
53913
|
const target = positional ?? o.workflowName ?? o.workflow;
|
|
53543
53914
|
if (!target) {
|
|
53544
|
-
|
|
53545
|
-
return WORKFLOW_EXIT.USAGE;
|
|
53915
|
+
throw CliError.usage('schedules create: a workflow is required \u2014 lua workflows schedules create <workflow> --cadence "0 9 * * 1" --timezone Europe/London');
|
|
53546
53916
|
}
|
|
53547
53917
|
let draft;
|
|
53548
53918
|
try {
|
|
@@ -53669,11 +54039,12 @@ async function schedulesPatchCore(ctx, jobId, verb, o) {
|
|
|
53669
54039
|
if (!rowRes.success || !rowRes.data) return apiFailure(ctx, rowRes, label);
|
|
53670
54040
|
const owner = await scheduleGoalOwner(ctx, rowRes.data);
|
|
53671
54041
|
if (owner.error) {
|
|
53672
|
-
if (!ctx.json) console.error(`\u274C cannot prove ${jobId} is not a goal's cadence (goals unavailable) \u2014 refusing to ${verb}`);
|
|
53673
54042
|
return apiFailure(ctx, {
|
|
53674
54043
|
success: false,
|
|
53675
54044
|
error: owner.error
|
|
53676
|
-
}, label
|
|
54045
|
+
}, label, {
|
|
54046
|
+
message: `cannot prove ${jobId} is not a goal's cadence (goals unavailable) \u2014 refusing to ${verb}`
|
|
54047
|
+
});
|
|
53677
54048
|
}
|
|
53678
54049
|
if (owner.goalId) {
|
|
53679
54050
|
const message = `Schedule ${jobId} is the cadence of goal ${owner.goalId} and was NOT changed. Pause or resume the goal instead: lua workflows goals pause ${owner.goalId} / lua workflows goals resume ${owner.goalId} \u2014 a goal's Job follows its goal, never the other way round.`;
|
|
@@ -55353,6 +55724,7 @@ init_cli();
|
|
|
55353
55724
|
// src/api/marketplace.api.service.ts
|
|
55354
55725
|
init_constants();
|
|
55355
55726
|
init_lua_fetch();
|
|
55727
|
+
init_http_client();
|
|
55356
55728
|
init_request_credential();
|
|
55357
55729
|
var MarketplaceApiService = class {
|
|
55358
55730
|
static {
|
|
@@ -55377,8 +55749,7 @@ var MarketplaceApiService = class {
|
|
|
55377
55749
|
headers
|
|
55378
55750
|
});
|
|
55379
55751
|
if (!response.ok) {
|
|
55380
|
-
|
|
55381
|
-
throw new Error(`API Error: ${response.status} ${response.statusText} - ${errorText}`);
|
|
55752
|
+
throw await refusalFromResponse(response);
|
|
55382
55753
|
}
|
|
55383
55754
|
if (response.status === 204) {
|
|
55384
55755
|
return null;
|
|
@@ -55501,6 +55872,7 @@ import { readFileSync as readFileSync14 } from "fs";
|
|
|
55501
55872
|
// src/api/template.api.service.ts
|
|
55502
55873
|
init_constants();
|
|
55503
55874
|
init_lua_fetch();
|
|
55875
|
+
init_http_client();
|
|
55504
55876
|
init_request_credential();
|
|
55505
55877
|
var TemplateApiService = class {
|
|
55506
55878
|
static {
|
|
@@ -55523,8 +55895,7 @@ var TemplateApiService = class {
|
|
|
55523
55895
|
headers
|
|
55524
55896
|
});
|
|
55525
55897
|
if (!response.ok) {
|
|
55526
|
-
|
|
55527
|
-
throw new Error(`API Error: ${response.status} ${response.statusText} - ${errorText}`);
|
|
55898
|
+
throw await refusalFromResponse(response);
|
|
55528
55899
|
}
|
|
55529
55900
|
if (response.status === 204) {
|
|
55530
55901
|
return null;
|
|
@@ -55747,6 +56118,11 @@ function sleep2(ms) {
|
|
|
55747
56118
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
55748
56119
|
}
|
|
55749
56120
|
__name(sleep2, "sleep");
|
|
56121
|
+
function missingVersionOrRethrow(error) {
|
|
56122
|
+
if (CliError.isCliError(error) && error.statusCode === 404) return null;
|
|
56123
|
+
throw error;
|
|
56124
|
+
}
|
|
56125
|
+
__name(missingVersionOrRethrow, "missingVersionOrRethrow");
|
|
55750
56126
|
async function resolveTemplateId(templateApi, options, message) {
|
|
55751
56127
|
if (options.templateId) return options.templateId;
|
|
55752
56128
|
writeProgress("\u{1F504} Loading your templates...");
|
|
@@ -56123,8 +56499,8 @@ async function templateViewAction(templateApi, options) {
|
|
|
56123
56499
|
if (!Number.isFinite(versionNum) || versionNum <= 0) {
|
|
56124
56500
|
throw new Error(`Invalid --version "${options.version}": must be a positive integer.`);
|
|
56125
56501
|
}
|
|
56126
|
-
const version = await templateApi.getVersion(templateId, versionNum).catch(
|
|
56127
|
-
if (!version) throw
|
|
56502
|
+
const version = await templateApi.getVersion(templateId, versionNum).catch(missingVersionOrRethrow);
|
|
56503
|
+
if (!version) throw CliError.notFound(`Version v${versionNum} not found for this template.`);
|
|
56128
56504
|
if (options.json) {
|
|
56129
56505
|
console.log(JSON.stringify(version, null, 2));
|
|
56130
56506
|
return;
|
|
@@ -56288,8 +56664,8 @@ async function templateApplyAction(templateApi, options) {
|
|
|
56288
56664
|
throw new Error("This template has no published versions. Run `lua marketplace template publish` first.");
|
|
56289
56665
|
}
|
|
56290
56666
|
const versionNum = options.version ? Number.parseInt(options.version, 10) : template3.latestVersion;
|
|
56291
|
-
const versionObj = await templateApi.getVersion(templateId, versionNum).catch(
|
|
56292
|
-
if (!versionObj) throw
|
|
56667
|
+
const versionObj = await templateApi.getVersion(templateId, versionNum).catch(missingVersionOrRethrow);
|
|
56668
|
+
if (!versionObj) throw CliError.notFound(`Version v${versionNum} not found for this template.`);
|
|
56293
56669
|
if (!options.force) {
|
|
56294
56670
|
console.log(`
|
|
56295
56671
|
Apply plan:`);
|
|
@@ -56540,45 +56916,57 @@ var SKILL_ACTION_LABELS = {
|
|
|
56540
56916
|
org: "View this organization's owned skills"
|
|
56541
56917
|
};
|
|
56542
56918
|
async function marketplaceCommand(noun, action, options = {}) {
|
|
56543
|
-
return withErrorHandling(
|
|
56544
|
-
|
|
56545
|
-
|
|
56546
|
-
|
|
56547
|
-
|
|
56548
|
-
|
|
56549
|
-
|
|
56550
|
-
|
|
56551
|
-
|
|
56552
|
-
message: "What would you like to browse?",
|
|
56553
|
-
choices: [
|
|
56554
|
-
{
|
|
56555
|
-
name: "Skills",
|
|
56556
|
-
value: "skill"
|
|
56557
|
-
},
|
|
56558
|
-
{
|
|
56559
|
-
name: "Agent templates",
|
|
56560
|
-
value: "template"
|
|
56561
|
-
},
|
|
56562
|
-
{
|
|
56563
|
-
name: "Exit",
|
|
56564
|
-
value: "exit"
|
|
56565
|
-
}
|
|
56566
|
-
]
|
|
56567
|
-
}
|
|
56568
|
-
]);
|
|
56569
|
-
if (!domainAnswer || domainAnswer.domain === "exit") {
|
|
56570
|
-
console.log("\n\u{1F44B} Goodbye!\n");
|
|
56571
|
-
return;
|
|
56572
|
-
}
|
|
56573
|
-
domain = domainAnswer.domain;
|
|
56574
|
-
}
|
|
56575
|
-
if (domain === "template") {
|
|
56576
|
-
return templateCommand(action, options);
|
|
56919
|
+
return withErrorHandling(
|
|
56920
|
+
async () => {
|
|
56921
|
+
await marketplaceDispatch(noun, action, options);
|
|
56922
|
+
},
|
|
56923
|
+
"marketplace",
|
|
56924
|
+
// LUA-803: under `--json` an escaped refusal (a template 403 / 404, a network failure) is the typed envelope on
|
|
56925
|
+
// stdout, not the `✖` line.
|
|
56926
|
+
{
|
|
56927
|
+
json: /* @__PURE__ */ __name(() => !!options.json, "json")
|
|
56577
56928
|
}
|
|
56578
|
-
|
|
56579
|
-
}, "marketplace");
|
|
56929
|
+
);
|
|
56580
56930
|
}
|
|
56581
56931
|
__name(marketplaceCommand, "marketplaceCommand");
|
|
56932
|
+
async function marketplaceDispatch(noun, action, options) {
|
|
56933
|
+
let domain;
|
|
56934
|
+
if (noun) {
|
|
56935
|
+
domain = validateOrSuggest("marketplace.noun", noun);
|
|
56936
|
+
} else {
|
|
56937
|
+
const domainAnswer = await safePrompt([
|
|
56938
|
+
{
|
|
56939
|
+
type: "list",
|
|
56940
|
+
name: "domain",
|
|
56941
|
+
message: "What would you like to browse?",
|
|
56942
|
+
choices: [
|
|
56943
|
+
{
|
|
56944
|
+
name: "Skills",
|
|
56945
|
+
value: "skill"
|
|
56946
|
+
},
|
|
56947
|
+
{
|
|
56948
|
+
name: "Agent templates",
|
|
56949
|
+
value: "template"
|
|
56950
|
+
},
|
|
56951
|
+
{
|
|
56952
|
+
name: "Exit",
|
|
56953
|
+
value: "exit"
|
|
56954
|
+
}
|
|
56955
|
+
]
|
|
56956
|
+
}
|
|
56957
|
+
]);
|
|
56958
|
+
if (!domainAnswer || domainAnswer.domain === "exit") {
|
|
56959
|
+
console.log("\n\u{1F44B} Goodbye!\n");
|
|
56960
|
+
return;
|
|
56961
|
+
}
|
|
56962
|
+
domain = domainAnswer.domain;
|
|
56963
|
+
}
|
|
56964
|
+
if (domain === "template") {
|
|
56965
|
+
return templateCommand(action, options);
|
|
56966
|
+
}
|
|
56967
|
+
return skillMarketplaceCommand(action, options);
|
|
56968
|
+
}
|
|
56969
|
+
__name(marketplaceDispatch, "marketplaceDispatch");
|
|
56582
56970
|
async function skillMarketplaceCommand(action, options = {}) {
|
|
56583
56971
|
const { config, apiKey } = await initializeCommand();
|
|
56584
56972
|
const marketplaceApi = new MarketplaceApiService(apiKey, config.agent?.orgId);
|
|
@@ -64712,7 +65100,7 @@ Examples:
|
|
|
64712
65100
|
$ lua init --from-agent-id baseAgent_agent_xxx Duplicate agent + scaffold project
|
|
64713
65101
|
$ lua init --from-agent-id baseAgent_agent_xxx --org-id <id> Cross-org duplicate
|
|
64714
65102
|
`).action(initCommand);
|
|
64715
|
-
program2.command("compile").description("\u{1F4E6} Compile skill to deployable format").option("--verbose", "Show detailed progress output").option("--debug", "Enable debug mode with extra verbose logging and temp file preservation").option("--sync", "
|
|
65103
|
+
program2.command("compile").description("\u{1F4E6} Compile skill to deployable format").option("--verbose", "Show detailed progress output").option("--debug", "Enable debug mode with extra verbose logging and temp file preservation").option("--sync", "Check for drift against the server before compiling (reads only \u2014 nothing is written)").action((opts) => compileCommand({
|
|
64716
65104
|
...opts,
|
|
64717
65105
|
topLevel: true
|
|
64718
65106
|
}));
|