lua-cli 3.32.4 → 3.32.6

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.
@@ -72,6 +72,11 @@ export declare interface ApprovalOptions {
72
72
  /** default 'continue' (denial is data unless 'fail') */
73
73
  onDeny?: WorkflowApprovalOnDeny;
74
74
  businessHours?: WorkflowBusinessHours;
75
+ /**
76
+ * Optional — inferred `true` from a non-empty `editablePaths` (LUA-808 / LUA-825: the validator's `approvalEditable`
77
+ * rule, applied by the builder too); an explicit `false` beside paths is refused as contradictory. Absent with no
78
+ * paths ⇒ `false` (the approver decides, never edits).
79
+ */
75
80
  editable?: boolean;
76
81
  /** grammar: `drafts`, `drafts[*]`, `drafts[*].body`, `drafts[3].body`, `summary.title` */
77
82
  editablePaths?: string[];
@@ -735,6 +735,23 @@ function modelUnresolvedMessage(r) {
735
735
  }
736
736
  __name(modelUnresolvedMessage, "modelUnresolvedMessage");
737
737
  __name2(modelUnresolvedMessage, "modelUnresolvedMessage");
738
+ function providerModelId(code) {
739
+ const requested = typeof code === "string" ? code.trim() : "";
740
+ if (!requested || isModelIdSentinel(requested)) return requested;
741
+ const slash = requested.indexOf("/");
742
+ if (slash <= 0) return requested;
743
+ const provider = requested.slice(0, slash).toLowerCase();
744
+ if (MODEL_ID_BYOK_PROVIDERS.includes(provider)) return requested;
745
+ return requested.slice(slash + 1);
746
+ }
747
+ __name(providerModelId, "providerModelId");
748
+ __name2(providerModelId, "providerModelId");
749
+ var MODEL_SNAPSHOT_SUFFIX = /(?:[-@](?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])|-(?:19|20)\d{2}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01]))$/;
750
+ function providerModelFamily(code) {
751
+ return providerModelId(code).toLowerCase().replace(MODEL_SNAPSHOT_SUFFIX, "");
752
+ }
753
+ __name(providerModelFamily, "providerModelFamily");
754
+ __name2(providerModelFamily, "providerModelFamily");
738
755
  var IMPLICIT_MODEL_SELECTION_SOURCES = [
739
756
  "workspace-default",
740
757
  "platform-default"
@@ -1248,6 +1265,7 @@ var DeviceBindingSchema = z2.object({
1248
1265
  }
1249
1266
  });
1250
1267
  var IdSchema = z2.string().min(1).max(256);
1268
+ var SESSION_AUTH_TIME_MAX_S = 4102444800;
1251
1269
  var PrincipalDescriptorSchema = z2.object({
1252
1270
  subjectType: SubjectTypeSchema,
1253
1271
  subjectId: IdSchema
@@ -1296,7 +1314,8 @@ var GeneralPrincipalContextSchema = z2.object({
1296
1314
  owner: PrincipalOwnerSchema.optional(),
1297
1315
  compatibility: z2.object({
1298
1316
  mode: z2.literal("legacy-owner-delegation")
1299
- }).strict().optional()
1317
+ }).strict().optional(),
1318
+ authTime: z2.number().int().nonnegative().max(SESSION_AUTH_TIME_MAX_S).optional()
1300
1319
  }).strict();
1301
1320
  var DeviceCredentialPrincipalContextSchema = z2.object({
1302
1321
  version: z2.literal(1),
@@ -1362,6 +1381,13 @@ function hasDeviceCredentialType(value3) {
1362
1381
  }
1363
1382
  __name(hasDeviceCredentialType, "hasDeviceCredentialType");
1364
1383
  __name2(hasDeviceCredentialType, "hasDeviceCredentialType");
1384
+ function sessionAuthTime(context) {
1385
+ if (!context || context.credential.type !== "firstPartySession") return void 0;
1386
+ const authTime = context.authTime;
1387
+ return typeof authTime === "number" && Number.isInteger(authTime) && authTime >= 0 && authTime <= SESSION_AUTH_TIME_MAX_S ? authTime : void 0;
1388
+ }
1389
+ __name(sessionAuthTime, "sessionAuthTime");
1390
+ __name2(sessionAuthTime, "sessionAuthTime");
1365
1391
  function isTypedApiKeyPrincipal(context) {
1366
1392
  return context?.subject.subjectType === "apiKey" && context.credential.type === "apiKey" && !context.compatibility;
1367
1393
  }
@@ -1764,6 +1790,47 @@ function scheduledWorkflowRunId(jobId, scheduledTime) {
1764
1790
  }
1765
1791
  __name(scheduledWorkflowRunId, "scheduledWorkflowRunId");
1766
1792
  __name2(scheduledWorkflowRunId, "scheduledWorkflowRunId");
1793
+ var WORKFLOW_SCHEDULE_KEY_MAX = 128;
1794
+ function renderWorkflowScheduleKeyTemplate(template3, ctx) {
1795
+ if (!template3) return void 0;
1796
+ const read = /* @__PURE__ */ __name2((path) => path.split(".").reduce((o, k) => o && typeof o === "object" ? o[k] : void 0, ctx.input), "read");
1797
+ let unresolved = false;
1798
+ const out = template3.replace(/\$\{\s*([a-zA-Z0-9_.]+)\s*\}/g, (_m, expr) => {
1799
+ let v = "";
1800
+ if (expr === "scheduledTime") v = ctx.scheduledTime ?? "";
1801
+ else if (expr.startsWith("input.")) v = read(expr.slice("input.".length));
1802
+ const s = v === void 0 || v === null ? "" : String(v);
1803
+ if (s === "") unresolved = true;
1804
+ return s;
1805
+ });
1806
+ if (unresolved) return void 0;
1807
+ const key = out.slice(0, WORKFLOW_SCHEDULE_KEY_MAX);
1808
+ return key && /^[A-Za-z0-9:_\-.\/]+$/.test(key) ? key : void 0;
1809
+ }
1810
+ __name(renderWorkflowScheduleKeyTemplate, "renderWorkflowScheduleKeyTemplate");
1811
+ __name2(renderWorkflowScheduleKeyTemplate, "renderWorkflowScheduleKeyTemplate");
1812
+ var WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX = "sched:";
1813
+ function scheduledWorkflowIdempotencyKey(jobId, rendered) {
1814
+ const head = `${WORKFLOW_SCHEDULE_IDEMPOTENCY_KEY_PREFIX}${jobId}:`;
1815
+ if (head.length + rendered.length <= WORKFLOW_SCHEDULE_KEY_MAX) return `${head}${rendered}`;
1816
+ const digest = stableKeyDigest(rendered);
1817
+ const room = WORKFLOW_SCHEDULE_KEY_MAX - head.length - digest.length - 1;
1818
+ return `${head}${rendered.slice(0, Math.max(0, room))}~${digest}`;
1819
+ }
1820
+ __name(scheduledWorkflowIdempotencyKey, "scheduledWorkflowIdempotencyKey");
1821
+ __name2(scheduledWorkflowIdempotencyKey, "scheduledWorkflowIdempotencyKey");
1822
+ function stableKeyDigest(s) {
1823
+ let a = 2166136261;
1824
+ let b = 84696351;
1825
+ for (let i = 0; i < s.length; i++) {
1826
+ const c = s.charCodeAt(i);
1827
+ a = Math.imul(a ^ c, 16777619);
1828
+ b = Math.imul(b ^ c, 16777619) ^ b >>> 13;
1829
+ }
1830
+ return (a >>> 0).toString(16).padStart(8, "0") + (b >>> 0).toString(16).padStart(8, "0");
1831
+ }
1832
+ __name(stableKeyDigest, "stableKeyDigest");
1833
+ __name2(stableKeyDigest, "stableKeyDigest");
1767
1834
  var WORKFLOW_OPERATION_ID_PREFIX = "wf:";
1768
1835
  function workflowOperationId(runId, stepId, billingEpoch) {
1769
1836
  return `${WORKFLOW_OPERATION_ID_PREFIX}${runId}:${stepId}:${billingEpoch}`;
@@ -2512,6 +2579,75 @@ function extractSingleJsonValue(text) {
2512
2579
  }
2513
2580
  __name(extractSingleJsonValue, "extractSingleJsonValue");
2514
2581
  __name2(extractSingleJsonValue, "extractSingleJsonValue");
2582
+ var DEFAULT_ON_AGENT_FEATURES = [
2583
+ "workflows",
2584
+ "workflowCompose",
2585
+ "observationalMemory"
2586
+ ];
2587
+ function agentFeatureCatalogDefault(featureName) {
2588
+ return DEFAULT_ON_AGENT_FEATURES.includes(featureName);
2589
+ }
2590
+ __name(agentFeatureCatalogDefault, "agentFeatureCatalogDefault");
2591
+ __name2(agentFeatureCatalogDefault, "agentFeatureCatalogDefault");
2592
+ function hasExplicitFeatureActive(row) {
2593
+ return typeof row?.active === "boolean";
2594
+ }
2595
+ __name(hasExplicitFeatureActive, "hasExplicitFeatureActive");
2596
+ __name2(hasExplicitFeatureActive, "hasExplicitFeatureActive");
2597
+ function effectiveFeatureActive(row, catalogDefault) {
2598
+ return hasExplicitFeatureActive(row) ? row.active : catalogDefault;
2599
+ }
2600
+ __name(effectiveFeatureActive, "effectiveFeatureActive");
2601
+ __name2(effectiveFeatureActive, "effectiveFeatureActive");
2602
+ function resolveEffectiveFeature(row, catalogDefault) {
2603
+ return hasExplicitFeatureActive(row) ? {
2604
+ active: row.active,
2605
+ source: "agent",
2606
+ default: catalogDefault
2607
+ } : {
2608
+ active: catalogDefault,
2609
+ source: "default",
2610
+ default: catalogDefault
2611
+ };
2612
+ }
2613
+ __name(resolveEffectiveFeature, "resolveEffectiveFeature");
2614
+ __name2(resolveEffectiveFeature, "resolveEffectiveFeature");
2615
+ function isFeatureRow(value3) {
2616
+ return typeof value3 === "object" && value3 !== null;
2617
+ }
2618
+ __name(isFeatureRow, "isFeatureRow");
2619
+ __name2(isFeatureRow, "isFeatureRow");
2620
+ function effectiveAgentFeatureRows(base, override) {
2621
+ const merged = /* @__PURE__ */ new Map();
2622
+ for (const [name, row] of Object.entries(base ?? {})) {
2623
+ if (isFeatureRow(row)) merged.set(name, {
2624
+ row,
2625
+ origin: "baseAgent"
2626
+ });
2627
+ }
2628
+ for (const [name, row] of Object.entries(override ?? {})) {
2629
+ if (isFeatureRow(row)) merged.set(name, {
2630
+ row,
2631
+ origin: "subAgent"
2632
+ });
2633
+ }
2634
+ return {
2635
+ rows: Object.fromEntries([
2636
+ ...merged
2637
+ ].map(([name, e]) => [
2638
+ name,
2639
+ e.row
2640
+ ])),
2641
+ origins: Object.fromEntries([
2642
+ ...merged
2643
+ ].map(([name, e]) => [
2644
+ name,
2645
+ e.origin
2646
+ ]))
2647
+ };
2648
+ }
2649
+ __name(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2650
+ __name2(effectiveAgentFeatureRows, "effectiveAgentFeatureRows");
2515
2651
 
2516
2652
  // ../workflow-graph/dist/index.mjs
2517
2653
  import { createHash } from "crypto";
@@ -3114,7 +3250,7 @@ function fillHitl(node) {
3114
3250
  if (a.onTimeout === void 0) a.onTimeout = "deny";
3115
3251
  if (a.onDeny === void 0) a.onDeny = "continue";
3116
3252
  if (a.excludeInitiator === void 0) a.excludeInitiator = false;
3117
- if (a.editable === void 0) a.editable = false;
3253
+ if (a.editable === void 0) a.editable = approvalEditable(a);
3118
3254
  return;
3119
3255
  }
3120
3256
  const w = node;
@@ -3416,7 +3552,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3416
3552
  const id = singleId(node);
3417
3553
  const unknown = unknownWorkflowRetryMembers(r);
3418
3554
  if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path}.retry`, id);
3419
- if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
3555
+ if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
3420
3556
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
3421
3557
  err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path}.retry.maxAttempts`, id);
3422
3558
  }
@@ -3654,7 +3790,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
3654
3790
  }
3655
3791
  const a = node;
3656
3792
  checkId(a.id, path);
3657
- if (a.approver === "creator" && a.excludeInitiator === true) {
3793
+ if ((a.approver ?? "creator") === "creator" && a.excludeInitiator === true) {
3658
3794
  err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path, a.id);
3659
3795
  }
3660
3796
  const editable = approvalEditable(a);
@@ -5218,6 +5354,7 @@ __name3(runErrorIssues, "runErrorIssues");
5218
5354
  function runNextAction(run) {
5219
5355
  if (isTerminalRunStatus(run.status)) return "none";
5220
5356
  if (run.status === "suspended" && run.gate?.kind === "budget") return "raise_budget";
5357
+ if (run.status === "suspended" && run.gate?.kind === "billing") return "top_up";
5221
5358
  if (!run.cancel?.requestedAt) return "none";
5222
5359
  const forceAt = run.cancel.forceAfter ?? run.cancel.requestedAt + FORCE_CANCEL_STALE_MS;
5223
5360
  return Date.now() >= forceAt ? "force" : "cancel_again";
@@ -5254,6 +5391,16 @@ function runCountsFromStepStatuses(statuses) {
5254
5391
  }
5255
5392
  __name(runCountsFromStepStatuses, "runCountsFromStepStatuses");
5256
5393
  __name3(runCountsFromStepStatuses, "runCountsFromStepStatuses");
5394
+ function isBillingHeldStep(row) {
5395
+ return row.status === "ready" && row.billingHold === true;
5396
+ }
5397
+ __name(isBillingHeldStep, "isBillingHeldStep");
5398
+ __name3(isBillingHeldStep, "isBillingHeldStep");
5399
+ function stepEffectiveStatus(row) {
5400
+ return isBillingHeldStep(row) ? "suspended" : row.status;
5401
+ }
5402
+ __name(stepEffectiveStatus, "stepEffectiveStatus");
5403
+ __name3(stepEffectiveStatus, "stepEffectiveStatus");
5257
5404
  var n = /* @__PURE__ */ __name3((v) => typeof v === "number" && Number.isFinite(v) ? v : 0, "n");
5258
5405
  function runCounts(counts) {
5259
5406
  const c = counts ?? {};
@@ -6091,6 +6238,63 @@ function rebaseItemPointer(pointer, itemsPath, index) {
6091
6238
  }
6092
6239
  __name(rebaseItemPointer, "rebaseItemPointer");
6093
6240
  __name3(rebaseItemPointer, "rebaseItemPointer");
6241
+ var WORKFLOW_SCHEDULE_TYPES = [
6242
+ "cron",
6243
+ "interval",
6244
+ "once"
6245
+ ];
6246
+ var WORKFLOW_SCHEDULE_SHAPE_ISSUE = "schedule-shape-invalid";
6247
+ var WORKFLOW_SCHEDULE_SHAPES_HINT = "`schedule` must be one of { type: 'cron', expression: '<5-field cron>', timezone?: '<IANA tz>' } | { type: 'interval', seconds: <n> } | { type: 'once', executeAt: '<ISO-8601>' }";
6248
+ var isObject = /* @__PURE__ */ __name3((v) => typeof v === "object" && v !== null && !Array.isArray(v), "isObject");
6249
+ function validateWorkflowSchedule(schedule, path = "/schedule") {
6250
+ if (schedule === void 0 || schedule === null) return [];
6251
+ const issue = /* @__PURE__ */ __name3((at, detail) => [
6252
+ {
6253
+ code: WORKFLOW_SCHEDULE_SHAPE_ISSUE,
6254
+ severity: "error",
6255
+ path: at,
6256
+ message: `${detail} \u2014 ${WORKFLOW_SCHEDULE_SHAPES_HINT}`
6257
+ }
6258
+ ], "issue");
6259
+ if (!isObject(schedule)) {
6260
+ return issue(path, `\`schedule\` is ${Array.isArray(schedule) ? "an array" : `a ${typeof schedule}`}, not a typed schedule object`);
6261
+ }
6262
+ const type = schedule.type;
6263
+ if (type === void 0) {
6264
+ const keys = Object.keys(schedule);
6265
+ const seen = keys.length ? ` (got { ${keys.join(", ")} })` : " (got {})";
6266
+ return issue(path, `\`schedule\` carries no \`type\` discriminator${seen}`);
6267
+ }
6268
+ if (typeof type !== "string" || !WORKFLOW_SCHEDULE_TYPES.includes(type)) {
6269
+ return issue(path, `\`schedule.type\` ${JSON.stringify(type)} is not one of ${WORKFLOW_SCHEDULE_TYPES.map((t) => `'${t}'`).join(" | ")}`);
6270
+ }
6271
+ switch (type) {
6272
+ case "cron": {
6273
+ if (typeof schedule.expression !== "string" || schedule.expression.trim().length === 0) {
6274
+ return issue(`${path}/expression`, "a { type: 'cron' } schedule needs a non-empty string `expression`");
6275
+ }
6276
+ if (schedule.timezone !== void 0 && (typeof schedule.timezone !== "string" || schedule.timezone.length === 0)) {
6277
+ return issue(`${path}/timezone`, "a { type: 'cron' } schedule's `timezone`, when given, is a non-empty IANA string");
6278
+ }
6279
+ return [];
6280
+ }
6281
+ case "interval": {
6282
+ const s = schedule.seconds;
6283
+ if (typeof s !== "number" || !Number.isFinite(s) || s <= 0) {
6284
+ return issue(`${path}/seconds`, "a { type: 'interval' } schedule needs a positive number `seconds`");
6285
+ }
6286
+ return [];
6287
+ }
6288
+ case "once": {
6289
+ if (typeof schedule.executeAt !== "string" || Number.isNaN(Date.parse(schedule.executeAt))) {
6290
+ return issue(`${path}/executeAt`, "a { type: 'once' } schedule needs an ISO-8601 string `executeAt`");
6291
+ }
6292
+ return [];
6293
+ }
6294
+ }
6295
+ }
6296
+ __name(validateWorkflowSchedule, "validateWorkflowSchedule");
6297
+ __name3(validateWorkflowSchedule, "validateWorkflowSchedule");
6094
6298
  var WORKFLOW_ENV_OVERLAY_MAX_KEYS = 64;
6095
6299
  var WORKFLOW_ENV_OVERLAY_MAX_VALUE_BYTES = 4096;
6096
6300
  var WORKFLOW_ENV_TEMPLATE_SECRET_KEY_RE = /(SECRET|TOKEN|KEY|PASSWORD)$/;
@@ -6532,7 +6736,7 @@ var assertPredicate = /* @__PURE__ */ __name((p, where) => {
6532
6736
  }, "assertPredicate");
6533
6737
  var assertRetry = /* @__PURE__ */ __name((r, id) => {
6534
6738
  if (!r) return;
6535
- if (r.maxAttempts !== void 0 && !isWithinWorkflowRetryAttempts(r.maxAttempts)) {
6739
+ if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
6536
6740
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
6537
6741
  throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
6538
6742
  }
@@ -7127,9 +7331,12 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
7127
7331
  if (opts.approver === "creator" && opts.excludeInitiator === true) {
7128
7332
  throw new LuaWorkflowBuildError("approver-excludes-only-candidate", `"${id}": approver:'creator' with excludeInitiator:true always excludes the only candidate`);
7129
7333
  }
7130
- if (opts.fourEyes !== void 0 && opts.editable !== true) throw new LuaWorkflowBuildError("four-eyes-requires-editable", `"${id}": fourEyes requires editable:true`);
7131
- if ((opts.editablePaths !== void 0 || opts.editedPayloadSchema !== void 0) && opts.editable !== true) {
7132
- throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": editablePaths / editedPayloadSchema require editable:true`);
7334
+ const editable = approvalEditable(opts);
7335
+ if (opts.fourEyes !== void 0 && !editable) throw new LuaWorkflowBuildError("four-eyes-requires-editable", `"${id}": \`fourEyes\` requires editable:true`);
7336
+ if (opts.editable === false && Array.isArray(opts.editablePaths) && opts.editablePaths.length > 0) {
7337
+ throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": \`editablePaths\` beside editable:false is contradictory \u2014 drop the paths or set editable:true`);
7338
+ } else if ((opts.editablePaths !== void 0 || opts.editedPayloadSchema !== void 0) && !editable) {
7339
+ throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": \`editablePaths\` / \`editedPayloadSchema\` require editable:true (a non-empty editablePaths implies it)`);
7133
7340
  }
7134
7341
  for (const p of opts.editablePaths ?? []) {
7135
7342
  if (!EDITABLE_PATH_RE2.test(p)) throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": editablePaths entry "${p}" is outside the grammar seg(.seg)* with [*]/[n] selectors`);