lua-cli 3.38.0 → 3.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ import { zodToJsonSchema } from "zod-to-json-schema";
8
8
  import { z } from "zod";
9
9
  import { z as z2 } from "zod";
10
10
  import { z as z3 } from "zod";
11
+ import { z as z4 } from "zod";
11
12
  var __defProp2 = Object.defineProperty;
12
13
  var __name2 = /* @__PURE__ */ __name((target, value3) => __defProp2(target, "name", { value: value3, configurable: true }), "__name");
13
14
  var PLUMBING_THREAD_CHANNELS = [
@@ -184,9 +185,9 @@ __name2(isMcpDraftCreateTool, "isMcpDraftCreateTool");
184
185
  function mcpSendSiblingForDraftTool(tool, availableToolIds) {
185
186
  const candidates = [
186
187
  ...availableToolIds
187
- ].filter((id) => id.endsWith(REVIEWABLE_MCP_SEND_TOOL_SUFFIX)).map((id) => ({
188
- id,
189
- serverName: id.slice(0, -REVIEWABLE_MCP_SEND_TOOL_SUFFIX.length)
188
+ ].filter((id2) => id2.endsWith(REVIEWABLE_MCP_SEND_TOOL_SUFFIX)).map((id2) => ({
189
+ id: id2,
190
+ serverName: id2.slice(0, -REVIEWABLE_MCP_SEND_TOOL_SUFFIX.length)
190
191
  })).filter(({ serverName }) => tool.startsWith(`${serverName}_`)).sort((a, b) => b.serverName.length - a.serverName.length);
191
192
  return candidates[0]?.id;
192
193
  }
@@ -367,8 +368,8 @@ __name(transformChatHistoryContentParts, "transformChatHistoryContentParts");
367
368
  __name2(transformChatHistoryContentParts, "transformChatHistoryContentParts");
368
369
  var RICH_PARTS_MESSAGE_ID_PREFIX = "rich-parts:";
369
370
  var SCREENSHOT_MESSAGE_ID_PREFIX = "screenshot:";
370
- function isSyntheticSideRow(id) {
371
- return id.startsWith(SCREENSHOT_MESSAGE_ID_PREFIX) || id.startsWith(RICH_PARTS_MESSAGE_ID_PREFIX);
371
+ function isSyntheticSideRow(id2) {
372
+ return id2.startsWith(SCREENSHOT_MESSAGE_ID_PREFIX) || id2.startsWith(RICH_PARTS_MESSAGE_ID_PREFIX);
372
373
  }
373
374
  __name(isSyntheticSideRow, "isSyntheticSideRow");
374
375
  __name2(isSyntheticSideRow, "isSyntheticSideRow");
@@ -664,6 +665,199 @@ var BROWSER_COMMANDS = [
664
665
  }
665
666
  ];
666
667
  var BROWSER_COMMAND_NAMES = BROWSER_COMMANDS.map((c) => c.name);
668
+ var LOG_FIELDS_MAX_KEYS = 32;
669
+ var LOG_FIELD_MAX_VALUE_BYTES = 1024;
670
+ var LOG_FIELDS_MAX_BYTES = 8192;
671
+ var LOG_FIELD_KEY_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
672
+ var LOG_FIELD_SECRET_SHAPED_KEY_PATTERNS = Object.freeze([
673
+ /^api_[0-9a-f]{24,}$/,
674
+ /^gh[pousr]_[a-z0-9]{36}$/,
675
+ /^(?:sk|rk|pk)_(?:live|test)_[a-z0-9]{16,}$/,
676
+ /^lua_hc_[a-z0-9]{20,}/,
677
+ /^lua_sk_[a-z0-9]{20,}/
678
+ ]);
679
+ var LOG_FIELDS_CLAMPED_KEY = "lua_fields_clamped";
680
+ var LOG_FIELD_ARRAY_COUNT_SUFFIX = ".count";
681
+ var LuaLogFieldsError = class _LuaLogFieldsError extends Error {
682
+ static {
683
+ __name(this, "_LuaLogFieldsError");
684
+ }
685
+ static {
686
+ __name2(this, "LuaLogFieldsError");
687
+ }
688
+ constructor(message) {
689
+ super(message);
690
+ this.name = "LuaLogFieldsError";
691
+ Object.setPrototypeOf(this, _LuaLogFieldsError.prototype);
692
+ }
693
+ };
694
+ function utf8WidthAt(value3, index) {
695
+ const code = value3.charCodeAt(index);
696
+ if (code < 128) return {
697
+ bytes: 1,
698
+ units: 1
699
+ };
700
+ if (code < 2048) return {
701
+ bytes: 2,
702
+ units: 1
703
+ };
704
+ if (code >= 55296 && code <= 56319) {
705
+ const next = value3.charCodeAt(index + 1);
706
+ if (next >= 56320 && next <= 57343) return {
707
+ bytes: 4,
708
+ units: 2
709
+ };
710
+ }
711
+ return {
712
+ bytes: 3,
713
+ units: 1
714
+ };
715
+ }
716
+ __name(utf8WidthAt, "utf8WidthAt");
717
+ __name2(utf8WidthAt, "utf8WidthAt");
718
+ function utf8ByteLength(value3) {
719
+ let bytes = 0;
720
+ for (let i = 0; i < value3.length; ) {
721
+ const width = utf8WidthAt(value3, i);
722
+ bytes += width.bytes;
723
+ i += width.units;
724
+ }
725
+ return bytes;
726
+ }
727
+ __name(utf8ByteLength, "utf8ByteLength");
728
+ __name2(utf8ByteLength, "utf8ByteLength");
729
+ function clampUtf8(value3, maxBytes) {
730
+ let bytes = 0;
731
+ for (let i = 0; i < value3.length; ) {
732
+ const width = utf8WidthAt(value3, i);
733
+ if (bytes + width.bytes > maxBytes) return value3.slice(0, i);
734
+ bytes += width.bytes;
735
+ i += width.units;
736
+ }
737
+ return value3;
738
+ }
739
+ __name(clampUtf8, "clampUtf8");
740
+ __name2(clampUtf8, "clampUtf8");
741
+ function mapBytes(fields, withMark) {
742
+ return utf8ByteLength(JSON.stringify(withMark ? {
743
+ ...fields,
744
+ [LOG_FIELDS_CLAMPED_KEY]: true
745
+ } : fields));
746
+ }
747
+ __name(mapBytes, "mapBytes");
748
+ __name2(mapBytes, "mapBytes");
749
+ function withValueCap(fields, capBytes) {
750
+ const out = {};
751
+ for (const [key, value3] of Object.entries(fields)) {
752
+ out[key] = typeof value3 === "string" ? clampUtf8(value3, capBytes) : value3;
753
+ }
754
+ return out;
755
+ }
756
+ __name(withValueCap, "withValueCap");
757
+ __name2(withValueCap, "withValueCap");
758
+ function describeValue(value3) {
759
+ if (value3 === null) return "null";
760
+ if (value3 === void 0) return "undefined";
761
+ if (Array.isArray(value3)) return "an array";
762
+ return typeof value3 === "object" ? "an object" : `a ${typeof value3}`;
763
+ }
764
+ __name(describeValue, "describeValue");
765
+ __name2(describeValue, "describeValue");
766
+ function assertValidLogFieldKey(key) {
767
+ if (!LOG_FIELD_KEY_PATTERN.test(key)) {
768
+ throw new LuaLogFieldsError(`log fields: key \`${key}\` is not allowed \u2014 a key must match ${LOG_FIELD_KEY_PATTERN.source} (lower-case, starts with a letter, then letters/digits/underscore, at most 64 characters)`);
769
+ }
770
+ if (LOG_FIELD_SECRET_SHAPED_KEY_PATTERNS.some((pattern) => pattern.test(key))) {
771
+ throw new LuaLogFieldsError(`log fields: key \`${key}\` is not allowed \u2014 it has the shape of a credential that the log-drain scrubber masks in values; a field KEY is never scrubbed, so it may never carry a secret shape`);
772
+ }
773
+ if (key === LOG_FIELDS_CLAMPED_KEY) {
774
+ throw new LuaLogFieldsError(`log fields: key \`${key}\` is reserved \u2014 the platform sets it to mark a field map it had to clamp`);
775
+ }
776
+ }
777
+ __name(assertValidLogFieldKey, "assertValidLogFieldKey");
778
+ __name2(assertValidLogFieldKey, "assertValidLogFieldKey");
779
+ function normalizeLogFields(fields) {
780
+ if (fields === void 0 || fields === null) return void 0;
781
+ if (typeof fields !== "object" || Array.isArray(fields)) {
782
+ throw new LuaLogFieldsError(`log fields: expected a plain object of fields, received ${describeValue(fields)}`);
783
+ }
784
+ const entries = Object.entries(fields);
785
+ if (entries.length > LOG_FIELDS_MAX_KEYS) {
786
+ throw new LuaLogFieldsError(`log fields: ${entries.length} keys exceeds the cap of ${LOG_FIELDS_MAX_KEYS} keys per call`);
787
+ }
788
+ const out = {};
789
+ for (const [key, value3] of entries) {
790
+ assertValidLogFieldKey(key);
791
+ if (typeof value3 === "string" || typeof value3 === "boolean") {
792
+ out[key] = value3;
793
+ continue;
794
+ }
795
+ if (typeof value3 === "number") {
796
+ if (!Number.isFinite(value3)) {
797
+ throw new LuaLogFieldsError(`log fields: \`${key}\` must be a finite number \u2014 NaN and Infinity have no JSON form`);
798
+ }
799
+ out[key] = value3;
800
+ continue;
801
+ }
802
+ if (Array.isArray(value3)) {
803
+ const parts = [];
804
+ for (const element of value3) {
805
+ if (typeof element !== "string") {
806
+ throw new LuaLogFieldsError(`log fields: \`${key}\` is an array, so every element must be a string (found ${describeValue(element)})`);
807
+ }
808
+ if (element.includes(",")) {
809
+ throw new LuaLogFieldsError(`log fields: \`${key}\` \u2014 an array element may not contain a comma; elements are comma-joined into one value (with \`${key}${LOG_FIELD_ARRAY_COUNT_SUFFIX}\` beside it), so a comma inside one would be indistinguishable from the separator`);
810
+ }
811
+ parts.push(element);
812
+ }
813
+ out[key] = parts.join(",");
814
+ out[`${key}${LOG_FIELD_ARRAY_COUNT_SUFFIX}`] = parts.length;
815
+ continue;
816
+ }
817
+ throw new LuaLogFieldsError(`log fields: \`${key}\` must be a string, number, boolean or string[] \u2014 received ${describeValue(value3)}` + (value3 !== null && typeof value3 === "object" ? " (nested objects are not supported)" : ""));
818
+ }
819
+ const keys = Object.keys(out);
820
+ if (keys.length === 0) return void 0;
821
+ if (keys.length > LOG_FIELDS_MAX_KEYS) {
822
+ throw new LuaLogFieldsError(`log fields: ${keys.length} keys exceeds the cap of ${LOG_FIELDS_MAX_KEYS} keys per call \u2014 an array field also contributes its \`${LOG_FIELD_ARRAY_COUNT_SUFFIX.slice(1)}\` sibling`);
823
+ }
824
+ if (clampLogFields(out)) out[LOG_FIELDS_CLAMPED_KEY] = true;
825
+ return out;
826
+ }
827
+ __name(normalizeLogFields, "normalizeLogFields");
828
+ __name2(normalizeLogFields, "normalizeLogFields");
829
+ function clampLogFields(out) {
830
+ let clamped = false;
831
+ for (const [key, value3] of Object.entries(out)) {
832
+ if (typeof value3 !== "string") continue;
833
+ const capped = clampUtf8(value3, LOG_FIELD_MAX_VALUE_BYTES);
834
+ if (capped !== value3) {
835
+ out[key] = capped;
836
+ clamped = true;
837
+ }
838
+ }
839
+ if (mapBytes(out, clamped) <= LOG_FIELDS_MAX_BYTES) return clamped;
840
+ const base = {
841
+ ...out
842
+ };
843
+ let low = 0;
844
+ let high = LOG_FIELD_MAX_VALUE_BYTES;
845
+ let best = 0;
846
+ while (low <= high) {
847
+ const mid = Math.floor((low + high) / 2);
848
+ if (mapBytes(withValueCap(base, mid), true) <= LOG_FIELDS_MAX_BYTES) {
849
+ best = mid;
850
+ low = mid + 1;
851
+ } else {
852
+ high = mid - 1;
853
+ }
854
+ }
855
+ const fitted = withValueCap(base, best);
856
+ for (const key of Object.keys(out)) out[key] = fitted[key];
857
+ return true;
858
+ }
859
+ __name(clampLogFields, "clampLogFields");
860
+ __name2(clampLogFields, "clampLogFields");
667
861
  var DESKTOP_FILE_COMMANDS = [
668
862
  "files_roots",
669
863
  "files_stat",
@@ -925,14 +1119,14 @@ function workflowContainerRunsHitlArm(container) {
925
1119
  }
926
1120
  __name(workflowContainerRunsHitlArm, "workflowContainerRunsHitlArm");
927
1121
  __name2(workflowContainerRunsHitlArm, "workflowContainerRunsHitlArm");
928
- function workflowHitlArmUnsupportedMessage(type, id, container) {
1122
+ function workflowHitlArmUnsupportedMessage(type, id2, container) {
929
1123
  const legal = WORKFLOW_HITL_ARM_CONTAINERS.map((c) => `\`${c}\``).join(" / ");
930
- return `the engine does not run \`${type}\` inside a \`${container}\` yet (node "${id}") \u2014 place it at the top level, as a ${legal} arm, or inside a child \`workflow\``;
1124
+ return `the engine does not run \`${type}\` inside a \`${container}\` yet (node "${id2}") \u2014 place it at the top level, as a ${legal} arm, or inside a child \`workflow\``;
931
1125
  }
932
1126
  __name(workflowHitlArmUnsupportedMessage, "workflowHitlArmUnsupportedMessage");
933
1127
  __name2(workflowHitlArmUnsupportedMessage, "workflowHitlArmUnsupportedMessage");
934
- function workflowHitlArmShapeMessage(type, id, shape) {
935
- return shape === "mapped-arm" ? `\`${type}\` arm "${id}" takes the previous output as its payload \u2014 it cannot head a [mapping, step] chain; map before the container instead` : `a chunked foreach hands each child a slice of items, not one \u2014 \`${type}\` body "${id}" takes one item; drop \`chunk\``;
1128
+ function workflowHitlArmShapeMessage(type, id2, shape) {
1129
+ return shape === "mapped-arm" ? `\`${type}\` arm "${id2}" takes the previous output as its payload \u2014 it cannot head a [mapping, step] chain; map before the container instead` : `a chunked foreach hands each child a slice of items, not one \u2014 \`${type}\` body "${id2}" takes one item; drop \`chunk\``;
936
1130
  }
937
1131
  __name(workflowHitlArmShapeMessage, "workflowHitlArmShapeMessage");
938
1132
  __name2(workflowHitlArmShapeMessage, "workflowHitlArmShapeMessage");
@@ -1227,6 +1421,112 @@ var AGENT_LOG_SOURCES = [
1227
1421
  "workflow-script",
1228
1422
  "workflow"
1229
1423
  ];
1424
+ var AGENT_LOG_FIELDS_MAX_WIRE_KEYS = LOG_FIELDS_MAX_KEYS + 1;
1425
+ function utf8Bytes(value3) {
1426
+ let bytes = 0;
1427
+ for (let i = 0; i < value3.length; ) {
1428
+ const code = value3.charCodeAt(i);
1429
+ if (code < 128) {
1430
+ bytes += 1;
1431
+ i += 1;
1432
+ } else if (code < 2048) {
1433
+ bytes += 2;
1434
+ i += 1;
1435
+ } else if (code >= 55296 && code <= 56319) {
1436
+ const next = value3.charCodeAt(i + 1);
1437
+ if (next >= 56320 && next <= 57343) {
1438
+ bytes += 4;
1439
+ i += 2;
1440
+ } else {
1441
+ bytes += 3;
1442
+ i += 1;
1443
+ }
1444
+ } else {
1445
+ bytes += 3;
1446
+ i += 1;
1447
+ }
1448
+ }
1449
+ return bytes;
1450
+ }
1451
+ __name(utf8Bytes, "utf8Bytes");
1452
+ __name2(utf8Bytes, "utf8Bytes");
1453
+ function isPlainFieldKey(key) {
1454
+ if (!LOG_FIELD_KEY_PATTERN.test(key)) return false;
1455
+ return !LOG_FIELD_SECRET_SHAPED_KEY_PATTERNS.some((pattern) => pattern.test(key));
1456
+ }
1457
+ __name(isPlainFieldKey, "isPlainFieldKey");
1458
+ __name2(isPlainFieldKey, "isPlainFieldKey");
1459
+ function describeAgentLogFieldsViolation(value3) {
1460
+ if (typeof value3 !== "object" || value3 === null || Array.isArray(value3)) {
1461
+ return "fields must be an object";
1462
+ }
1463
+ const entries = Object.entries(value3);
1464
+ let userKeys = 0;
1465
+ for (const [key, entry] of entries) {
1466
+ if (key === LOG_FIELDS_CLAMPED_KEY) {
1467
+ if (entry !== true) return `fields.${key} must be true`;
1468
+ continue;
1469
+ }
1470
+ userKeys += 1;
1471
+ if (key.endsWith(LOG_FIELD_ARRAY_COUNT_SUFFIX)) {
1472
+ const base = key.slice(0, -LOG_FIELD_ARRAY_COUNT_SUFFIX.length);
1473
+ if (!isPlainFieldKey(base)) return `fields key \`${key}\` is not a legal field key`;
1474
+ if (typeof entry !== "number" || !Number.isFinite(entry)) {
1475
+ return `fields.${key} must be a finite number`;
1476
+ }
1477
+ continue;
1478
+ }
1479
+ if (!isPlainFieldKey(key)) return `fields key \`${key}\` is not a legal field key`;
1480
+ if (typeof entry === "string") {
1481
+ if (utf8Bytes(entry) > LOG_FIELD_MAX_VALUE_BYTES) {
1482
+ return `fields.${key} exceeds ${LOG_FIELD_MAX_VALUE_BYTES} bytes`;
1483
+ }
1484
+ continue;
1485
+ }
1486
+ if (typeof entry === "boolean") continue;
1487
+ if (typeof entry === "number") {
1488
+ if (!Number.isFinite(entry)) return `fields.${key} must be a finite number`;
1489
+ continue;
1490
+ }
1491
+ return `fields.${key} must be a string, number or boolean`;
1492
+ }
1493
+ if (userKeys > LOG_FIELDS_MAX_KEYS) {
1494
+ return `fields has ${userKeys} keys, over the cap of ${LOG_FIELDS_MAX_KEYS}`;
1495
+ }
1496
+ if (utf8Bytes(JSON.stringify(value3)) > LOG_FIELDS_MAX_BYTES) {
1497
+ return `fields exceeds ${LOG_FIELDS_MAX_BYTES} bytes`;
1498
+ }
1499
+ return void 0;
1500
+ }
1501
+ __name(describeAgentLogFieldsViolation, "describeAgentLogFieldsViolation");
1502
+ __name2(describeAgentLogFieldsViolation, "describeAgentLogFieldsViolation");
1503
+ function isAgentLogFields(value3) {
1504
+ return describeAgentLogFieldsViolation(value3) === void 0;
1505
+ }
1506
+ __name(isAgentLogFields, "isAgentLogFields");
1507
+ __name2(isAgentLogFields, "isAgentLogFields");
1508
+ var LOG_DRAIN_TYPES_PHASE1 = [
1509
+ "http",
1510
+ "otlp",
1511
+ "datadog",
1512
+ "betterstack"
1513
+ ];
1514
+ var LOG_DRAIN_TYPES_PHASE2 = [
1515
+ "splunk",
1516
+ "loki",
1517
+ "axiom",
1518
+ "newrelic",
1519
+ "sumologic"
1520
+ ];
1521
+ var LOG_DRAIN_TYPES_IMPLEMENTED = [
1522
+ ...LOG_DRAIN_TYPES_PHASE1,
1523
+ ...LOG_DRAIN_TYPES_PHASE2,
1524
+ // RECONCILE-4 (W4-4). `s3` is implemented (H4 / PRO-1887) but is NOT in
1525
+ // `LOG_DRAIN_TYPES_PHASE2`, because its own flag opens it and `*` must not. It
1526
+ // belongs here all the same: this list is what a CLIENT may offer, and the server
1527
+ // remains the authority that answers 422 with the live list.
1528
+ "s3"
1529
+ ];
1230
1530
  var LOG_DRAIN_SOURCES = [
1231
1531
  ...AGENT_LOG_SOURCES,
1232
1532
  "execution",
@@ -1235,7 +1535,10 @@ var LOG_DRAIN_SOURCES = [
1235
1535
  "trigger-execution",
1236
1536
  "job-execution",
1237
1537
  "workflow-run",
1238
- "workflow-audit"
1538
+ "workflow-audit",
1539
+ // PRO-1884 (H2). Appended AFTER 'workflow-audit' so the enum stays additive and
1540
+ // no existing member changes position.
1541
+ "voice-call"
1239
1542
  ];
1240
1543
  var LOG_DRAIN_MAX_PER_ORG = 5;
1241
1544
  var LOG_DRAIN_MAX_PER_ORG_ENTERPRISE = 10;
@@ -1244,8 +1547,26 @@ function maxDrainsForTier(tier) {
1244
1547
  }
1245
1548
  __name(maxDrainsForTier, "maxDrainsForTier");
1246
1549
  __name2(maxDrainsForTier, "maxDrainsForTier");
1550
+ var LOG_DRAIN_DATADOG_SITES = [
1551
+ "datadoghq.com",
1552
+ "datadoghq.eu",
1553
+ "us3.datadoghq.com",
1554
+ "us5.datadoghq.com",
1555
+ "ap1.datadoghq.com",
1556
+ "ddog-gov.com"
1557
+ ];
1558
+ var LOG_DRAIN_NEWRELIC_SITES = [
1559
+ "log-api.newrelic.com",
1560
+ "log-api.eu.newrelic.com",
1561
+ "log-api.jp.newrelic.com"
1562
+ ];
1247
1563
  var LOG_DRAIN_ENDPOINT_TEMPLATES = {
1248
- datadog: "https://http-intake.logs.{site}/api/v2/logs"
1564
+ datadog: "https://http-intake.logs.{site}/api/v2/logs",
1565
+ newrelic: "https://{site}/log/v1"
1566
+ };
1567
+ var LOG_DRAIN_PRESET_SITES = {
1568
+ datadog: LOG_DRAIN_DATADOG_SITES,
1569
+ newrelic: LOG_DRAIN_NEWRELIC_SITES
1249
1570
  };
1250
1571
  function resolvePresetEndpoint(type, site) {
1251
1572
  const template3 = LOG_DRAIN_ENDPOINT_TEMPLATES[type];
@@ -1254,6 +1575,233 @@ function resolvePresetEndpoint(type, site) {
1254
1575
  }
1255
1576
  __name(resolvePresetEndpoint, "resolvePresetEndpoint");
1256
1577
  __name2(resolvePresetEndpoint, "resolvePresetEndpoint");
1578
+ var LOG_DRAIN_BUCKET_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;
1579
+ var LOG_DRAIN_BUCKET_HOST_PATTERNS = Object.freeze({
1580
+ aws: [
1581
+ // virtual-host style, regional and legacy global
1582
+ /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]\.s3(\.dualstack)?(\.[a-z0-9-]+)?\.amazonaws\.com$/,
1583
+ // path style
1584
+ /^s3(\.dualstack)?(\.[a-z0-9-]+)?\.amazonaws\.com$/
1585
+ ],
1586
+ r2: [
1587
+ /^[a-f0-9]{32}\.r2\.cloudflarestorage\.com$/
1588
+ ],
1589
+ gcs: [
1590
+ /^storage\.googleapis\.com$/
1591
+ ]
1592
+ });
1593
+ function isLogDrainBucketHostAllowed(provider, host) {
1594
+ const normalized = host.trim().toLowerCase().replace(/^\[|\]$/g, "");
1595
+ if (!normalized) return false;
1596
+ return (LOG_DRAIN_BUCKET_HOST_PATTERNS[provider] ?? []).some((pattern) => pattern.test(normalized));
1597
+ }
1598
+ __name(isLogDrainBucketHostAllowed, "isLogDrainBucketHostAllowed");
1599
+ __name2(isLogDrainBucketHostAllowed, "isLogDrainBucketHostAllowed");
1600
+ function resolveDrainBucketEndpoint(bucket) {
1601
+ if (!LOG_DRAIN_BUCKET_NAME_PATTERN.test(bucket.bucket)) {
1602
+ throw new Error("log drain bucket name is not a valid S3 bucket label");
1603
+ }
1604
+ if (bucket.provider === "aws") {
1605
+ const region = bucket.region.trim().toLowerCase();
1606
+ if (!/^[a-z0-9-]{1,32}$/.test(region)) throw new Error("log drain bucket region is not an AWS region");
1607
+ return `https://${bucket.bucket}.s3.${region}.amazonaws.com`;
1608
+ }
1609
+ if (!bucket.endpoint) throw new Error(`log drain '${bucket.provider}' bucket requires an endpoint`);
1610
+ let url;
1611
+ try {
1612
+ url = new URL(bucket.endpoint);
1613
+ } catch {
1614
+ throw new Error(`log drain '${bucket.provider}' bucket endpoint is not an absolute URL`);
1615
+ }
1616
+ if (url.protocol !== "https:") throw new Error(`log drain '${bucket.provider}' bucket endpoint must be https`);
1617
+ return `https://${url.host}/${bucket.bucket}`;
1618
+ }
1619
+ __name(resolveDrainBucketEndpoint, "resolveDrainBucketEndpoint");
1620
+ __name2(resolveDrainBucketEndpoint, "resolveDrainBucketEndpoint");
1621
+ function drainBucketUsesPathStyle(provider) {
1622
+ return provider !== "aws";
1623
+ }
1624
+ __name(drainBucketUsesPathStyle, "drainBucketUsesPathStyle");
1625
+ __name2(drainBucketUsesPathStyle, "drainBucketUsesPathStyle");
1626
+ function presetIntakeHosts(type) {
1627
+ const template3 = LOG_DRAIN_ENDPOINT_TEMPLATES[type];
1628
+ const sites = LOG_DRAIN_PRESET_SITES[type];
1629
+ if (!template3 || !sites) return [];
1630
+ const hosts = [];
1631
+ for (const site of sites) {
1632
+ try {
1633
+ hosts.push(new URL(template3.replace("{site}", site)).hostname.toLowerCase());
1634
+ } catch {
1635
+ }
1636
+ }
1637
+ return hosts;
1638
+ }
1639
+ __name(presetIntakeHosts, "presetIntakeHosts");
1640
+ __name2(presetIntakeHosts, "presetIntakeHosts");
1641
+ var LOG_DRAIN_PRESET_HOST_SUFFIXES = {
1642
+ axiom: [
1643
+ ".axiom.co"
1644
+ ],
1645
+ sumologic: [
1646
+ ".sumologic.com"
1647
+ ]
1648
+ };
1649
+ function presetHostAllowlist(type) {
1650
+ return [
1651
+ ...presetIntakeHosts(type),
1652
+ ...LOG_DRAIN_PRESET_HOST_SUFFIXES[type] ?? []
1653
+ ];
1654
+ }
1655
+ __name(presetHostAllowlist, "presetHostAllowlist");
1656
+ __name2(presetHostAllowlist, "presetHostAllowlist");
1657
+ function drainHostAllowlistAllows(allowlist, host) {
1658
+ const needle = host.toLowerCase();
1659
+ return allowlist.some((raw) => {
1660
+ const entry = raw.toLowerCase();
1661
+ if (entry.startsWith(".")) return needle === entry.slice(1) || needle.endsWith(entry);
1662
+ return entry === needle;
1663
+ });
1664
+ }
1665
+ __name(drainHostAllowlistAllows, "drainHostAllowlistAllows");
1666
+ __name2(drainHostAllowlistAllows, "drainHostAllowlistAllows");
1667
+ function drainDestinationIsVendorPinned(type) {
1668
+ if (LOG_DRAIN_ENDPOINT_TEMPLATES[type]) return true;
1669
+ return presetHostAllowlist(type).length > 0;
1670
+ }
1671
+ __name(drainDestinationIsVendorPinned, "drainDestinationIsVendorPinned");
1672
+ __name2(drainDestinationIsVendorPinned, "drainDestinationIsVendorPinned");
1673
+ function drainVerificationOwnership(input) {
1674
+ if (input.proved === true) return "verified";
1675
+ if (input.mode === "test-post" && drainDestinationIsVendorPinned(input.type)) return "verified";
1676
+ return "reachability-only";
1677
+ }
1678
+ __name(drainVerificationOwnership, "drainVerificationOwnership");
1679
+ __name2(drainVerificationOwnership, "drainVerificationOwnership");
1680
+ function drainOwnershipOrDefault(ownership) {
1681
+ return ownership === "verified" ? "verified" : "reachability-only";
1682
+ }
1683
+ __name(drainOwnershipOrDefault, "drainOwnershipOrDefault");
1684
+ __name2(drainOwnershipOrDefault, "drainOwnershipOrDefault");
1685
+ var DRAIN_CONTENT_ACK_ERROR_CODE = "DRAIN_CONTENT_ACK_REQUIRED";
1686
+ var DRAIN_CONTENT_ACK_FIELD = "includeContentAck";
1687
+ var DrainContentAckRequiredError = class extends Error {
1688
+ static {
1689
+ __name(this, "DrainContentAckRequiredError");
1690
+ }
1691
+ static {
1692
+ __name2(this, "DrainContentAckRequiredError");
1693
+ }
1694
+ code = DRAIN_CONTENT_ACK_ERROR_CODE;
1695
+ field = DRAIN_CONTENT_ACK_FIELD;
1696
+ constructor() {
1697
+ super("includeContent ships end-user message content to a third party; set includeContentAck: true to confirm.");
1698
+ this.name = "DrainContentAckRequiredError";
1699
+ }
1700
+ };
1701
+ function assertDrainContentAck(input) {
1702
+ const turningOn = input.next === true && input.was !== true;
1703
+ if (!turningOn) return void 0;
1704
+ if (input.ack !== true) throw new DrainContentAckRequiredError();
1705
+ return {
1706
+ by: input.actor,
1707
+ source: input.source,
1708
+ at: input.at,
1709
+ ...input.inheritedFrom ? {
1710
+ inheritedFrom: input.inheritedFrom
1711
+ } : {}
1712
+ };
1713
+ }
1714
+ __name(assertDrainContentAck, "assertDrainContentAck");
1715
+ __name2(assertDrainContentAck, "assertDrainContentAck");
1716
+ var LOG_DRAIN_PRESET_PATHS = {
1717
+ // https://docs.splunk.com/Documentation/Splunk/latest/Data/HECExamples
1718
+ splunk: {
1719
+ path: "/services/collector/event"
1720
+ },
1721
+ // https://grafana.com/docs/loki/latest/reference/loki-http-api/#ingest-logs
1722
+ loki: {
1723
+ path: "/loki/api/v1/push"
1724
+ },
1725
+ // https://axiom.co/docs/restapi/endpoints/ingestIntoDataset
1726
+ axiom: {
1727
+ path: "/v1/datasets",
1728
+ segment: "dataset",
1729
+ suffix: "/ingest"
1730
+ },
1731
+ // https://help.sumologic.com/docs/send-data/hosted-collectors/http-source/logs-metrics/upload-logs/
1732
+ sumologic: {
1733
+ path: "/receiver/v1/http",
1734
+ segment: "token"
1735
+ }
1736
+ };
1737
+ var PRESET_SEGMENT_RE = /^[A-Za-z0-9._~%=+-]{1,512}$/;
1738
+ function composePresetEndpoint(type, endpoint) {
1739
+ const rule = LOG_DRAIN_PRESET_PATHS[type];
1740
+ if (!rule) return void 0;
1741
+ let url;
1742
+ try {
1743
+ url = new URL(endpoint);
1744
+ } catch {
1745
+ return {
1746
+ ok: false,
1747
+ reason: "invalid_url"
1748
+ };
1749
+ }
1750
+ if (url.protocol !== "https:" || !url.hostname) return {
1751
+ ok: false,
1752
+ reason: "invalid_url"
1753
+ };
1754
+ const origin = url.origin;
1755
+ const path = url.pathname.replace(/\/+$/, "");
1756
+ if (!rule.segment) {
1757
+ const base2 = path.endsWith(rule.path) ? path.slice(0, path.length - rule.path.length) : path;
1758
+ return {
1759
+ ok: true,
1760
+ endpoint: `${origin}${base2}${rule.path}`
1761
+ };
1762
+ }
1763
+ const marker = `${rule.path}/`;
1764
+ const at = path.indexOf(marker);
1765
+ if (at < 0) {
1766
+ return {
1767
+ ok: false,
1768
+ reason: rule.segment === "dataset" ? "missing_dataset" : "missing_token"
1769
+ };
1770
+ }
1771
+ const base = path.slice(0, at);
1772
+ const afterMarker = path.slice(at + marker.length);
1773
+ const rest = rule.suffix && afterMarker.endsWith(rule.suffix) ? afterMarker.slice(0, afterMarker.length - rule.suffix.length) : afterMarker;
1774
+ if (!rest || rest.includes("/")) {
1775
+ return {
1776
+ ok: false,
1777
+ reason: rule.segment === "dataset" ? "missing_dataset" : "missing_token"
1778
+ };
1779
+ }
1780
+ if (!PRESET_SEGMENT_RE.test(rest)) return {
1781
+ ok: false,
1782
+ reason: "bad_segment"
1783
+ };
1784
+ if (rule.segment === "dataset") {
1785
+ return {
1786
+ ok: true,
1787
+ endpoint: `${origin}${base}${rule.path}/${rest}${rule.suffix ?? ""}`,
1788
+ dataset: rest
1789
+ };
1790
+ }
1791
+ return {
1792
+ ok: true,
1793
+ endpoint: `${origin}${base}${rule.path}/`,
1794
+ token: rest
1795
+ };
1796
+ }
1797
+ __name(composePresetEndpoint, "composePresetEndpoint");
1798
+ __name2(composePresetEndpoint, "composePresetEndpoint");
1799
+ function joinPresetEndpointToken(endpoint, token) {
1800
+ if (typeof token !== "string" || !PRESET_SEGMENT_RE.test(token)) return endpoint;
1801
+ return endpoint.endsWith("/") ? `${endpoint}${token}` : `${endpoint}/${token}`;
1802
+ }
1803
+ __name(joinPresetEndpointToken, "joinPresetEndpointToken");
1804
+ __name2(joinPresetEndpointToken, "joinPresetEndpointToken");
1257
1805
  var LOG_DRAIN_QUOTAS = {
1258
1806
  team: {
1259
1807
  eventsPerDay: 1e6,
@@ -1332,6 +1880,358 @@ function logDrainQuotaDroppedSeverities(degradation) {
1332
1880
  }
1333
1881
  __name(logDrainQuotaDroppedSeverities, "logDrainQuotaDroppedSeverities");
1334
1882
  __name2(logDrainQuotaDroppedSeverities, "logDrainQuotaDroppedSeverities");
1883
+ var LOG_EXPORT_SOURCES = [
1884
+ ...AGENT_LOG_SOURCES,
1885
+ "execution"
1886
+ ];
1887
+ var LOG_EXPORT_MAX_WINDOW_DAYS = 31;
1888
+ var LOG_EXPORT_MAX_WINDOW_MS = LOG_EXPORT_MAX_WINDOW_DAYS * 24 * 60 * 60 * 1e3;
1889
+ var LOG_EXPORT_URL_TTL_SECONDS = 24 * 60 * 60;
1890
+ var LOG_EXPORT_FILE_RETENTION_DAYS = 7;
1891
+ var LOG_EXPORT_FILE_RETENTION_MS = LOG_EXPORT_FILE_RETENTION_DAYS * 24 * 60 * 60 * 1e3;
1892
+ var LOG_EXPORT_PART_MAX_BYTES = 256 * 1024 * 1024;
1893
+ function isLogExportSource(source) {
1894
+ return LOG_EXPORT_SOURCES.includes(source);
1895
+ }
1896
+ __name(isLogExportSource, "isLogExportSource");
1897
+ __name2(isLogExportSource, "isLogExportSource");
1898
+ var LOG_DRAIN_NOTICE_RATE_LIMIT_MS = 60 * 6e4;
1899
+ var LOG_DRAIN_VERIFICATION_STALE_MS = 24 * 60 * 6e4;
1900
+ var LOG_DRAIN_DIGEST_INTERVAL_MS = 24 * 60 * 6e4;
1901
+ var LOG_DRAIN_DIGEST_MAX_ENTRIES = 50;
1902
+ var LOG_DRAIN_NOTICE_ERROR_MAX_CHARS = 200;
1903
+ function clamp(value3, max) {
1904
+ if (typeof value3 !== "string") return void 0;
1905
+ const trimmed = value3.trim();
1906
+ if (!trimmed) return void 0;
1907
+ return trimmed.length <= max ? trimmed : `${trimmed.slice(0, max - 1)}\u2026`;
1908
+ }
1909
+ __name(clamp, "clamp");
1910
+ __name2(clamp, "clamp");
1911
+ function numberOr(value3, fallback) {
1912
+ return typeof value3 === "number" && Number.isFinite(value3) ? value3 : fallback;
1913
+ }
1914
+ __name(numberOr, "numberOr");
1915
+ __name2(numberOr, "numberOr");
1916
+ function isoOr(value3) {
1917
+ return typeof value3 === "string" && value3.length > 0 ? value3 : void 0;
1918
+ }
1919
+ __name(isoOr, "isoOr");
1920
+ __name2(isoOr, "isoOr");
1921
+ function logDrainNoticeView(drain, now) {
1922
+ const health = drain.health ?? {};
1923
+ const quota = drain.quota;
1924
+ const view = {
1925
+ id: String(drain.id ?? ""),
1926
+ name: String(drain.name ?? ""),
1927
+ type: drain.type,
1928
+ state: drain.state,
1929
+ deliveredCount24h: numberOr(health.deliveredCount24h, 0),
1930
+ droppedCount24h: numberOr(health.droppedCount24h, 0),
1931
+ rejectedCount24h: numberOr(health.rejectedCount24h, 0),
1932
+ backlog: numberOr(health.backlog, 0),
1933
+ quotaRatio: quota ? logDrainQuotaRatio(quota, now) : 0
1934
+ };
1935
+ if (health.pauseReason) view.pauseReason = health.pauseReason;
1936
+ const lastError = clamp(health.lastError, LOG_DRAIN_NOTICE_ERROR_MAX_CHARS);
1937
+ if (lastError) view.lastError = lastError;
1938
+ if (typeof health.lastStatusCode === "number") view.lastStatusCode = health.lastStatusCode;
1939
+ const lastSuccessAt = isoOr(health.lastSuccessAt);
1940
+ if (lastSuccessAt) view.lastSuccessAt = lastSuccessAt;
1941
+ const lastFailureAt = isoOr(health.lastFailureAt);
1942
+ if (lastFailureAt) view.lastFailureAt = lastFailureAt;
1943
+ const resetsAt = isoOr(quota?.resetsAt);
1944
+ if (resetsAt) view.quotaResetsAt = resetsAt;
1945
+ return view;
1946
+ }
1947
+ __name(logDrainNoticeView, "logDrainNoticeView");
1948
+ __name2(logDrainNoticeView, "logDrainNoticeView");
1949
+ function logDrainHealthCardPath(orgId, drainId) {
1950
+ return `/orgs/${encodeURIComponent(orgId)}/log-drains/${encodeURIComponent(drainId)}`;
1951
+ }
1952
+ __name(logDrainHealthCardPath, "logDrainHealthCardPath");
1953
+ __name2(logDrainHealthCardPath, "logDrainHealthCardPath");
1954
+ function percent(ratio) {
1955
+ if (!Number.isFinite(ratio) || ratio <= 0) return "0%";
1956
+ return `${Math.round(ratio * 100)}%`;
1957
+ }
1958
+ __name(percent, "percent");
1959
+ __name2(percent, "percent");
1960
+ function becauseClause(view) {
1961
+ const bits = [];
1962
+ if (view.lastStatusCode) bits.push(`HTTP ${view.lastStatusCode}`);
1963
+ if (view.lastError) bits.push(view.lastError);
1964
+ return bits.length ? ` Last error: ${bits.join(" \u2014 ")}.` : "";
1965
+ }
1966
+ __name(becauseClause, "becauseClause");
1967
+ __name2(becauseClause, "becauseClause");
1968
+ function logDrainNoticeCopy(payload) {
1969
+ const view = payload.drain;
1970
+ const name = view.name || view.id;
1971
+ const backlog = view.backlog > 0 ? ` ${view.backlog.toLocaleString("en-US")} records are buffered.` : "";
1972
+ switch (payload.kind) {
1973
+ case "failing":
1974
+ return {
1975
+ title: name,
1976
+ subject: `Log drain "${name}" is failing`,
1977
+ previewLine: "Failing \u2014 15 minutes without a successful delivery",
1978
+ summary: `The log drain "${name}" (${view.type}) has gone 15 minutes without a successful delivery and is now failing.${becauseClause(view)}${backlog} Records keep buffering; the drain pauses itself after 24 hours without a success.`,
1979
+ status: "failed",
1980
+ priority: "high"
1981
+ };
1982
+ case "paused_auto":
1983
+ return {
1984
+ title: name,
1985
+ subject: `Log drain "${name}" was paused`,
1986
+ previewLine: "Paused \u2014 24 hours without a successful delivery",
1987
+ summary: `The log drain "${name}" (${view.type}) was paused automatically after 24 hours without a successful delivery.${becauseClause(view)}${backlog} Nothing is being sent while it is paused, and the buffer is delivered on resume. Fix the destination, then resume it from the drain's health card or with \`lua drains resume ${view.id}\`.`,
1988
+ status: "failed",
1989
+ priority: "high"
1990
+ };
1991
+ case "paused_quota":
1992
+ return {
1993
+ title: name,
1994
+ subject: `Log drain "${name}" was paused \u2014 daily quota exhausted`,
1995
+ previewLine: `Paused \u2014 ${percent(view.quotaRatio)} of the daily allowance used`,
1996
+ summary: `The log drain "${name}" (${view.type}) reached ${percent(view.quotaRatio)} of its daily allowance and was paused.${backlog} Records keep buffering. The allowance resets${view.quotaResetsAt ? ` at ${view.quotaResetsAt}` : " at 00:00 UTC"}; narrow the drain's sources or raise the plan's limit to stop it happening again, then resume it with \`lua drains resume ${view.id}\`.`,
1997
+ status: "failed",
1998
+ priority: "high"
1999
+ };
2000
+ case "quota_warning":
2001
+ return {
2002
+ title: name,
2003
+ subject: `Log drain "${name}" has used 80% of its daily allowance`,
2004
+ previewLine: `${percent(view.quotaRatio)} of the daily allowance used`,
2005
+ summary: `The log drain "${name}" (${view.type}) has used ${percent(view.quotaRatio)} of today's allowance. Past 100% debug records are dropped, past 125% info records as well, and at 150% the drain pauses. The allowance resets${view.quotaResetsAt ? ` at ${view.quotaResetsAt}` : " at 00:00 UTC"}.`,
2006
+ status: "failed",
2007
+ priority: "normal"
2008
+ };
2009
+ case "dropped": {
2010
+ const dropped = payload.droppedCount ?? view.droppedCount24h;
2011
+ return {
2012
+ title: name,
2013
+ subject: `Log drain "${name}" is dropping records`,
2014
+ previewLine: `${dropped.toLocaleString("en-US")} records dropped`,
2015
+ summary: `The log drain "${name}" (${view.type}) dropped ${dropped.toLocaleString("en-US")} records because its buffer filled up faster than the destination accepted them.${becauseClause(view)} The gap is reported in band on the next successful batch, so the range is recoverable from the destination itself.`,
2016
+ status: "failed",
2017
+ priority: "high"
2018
+ };
2019
+ }
2020
+ case "verification_pending":
2021
+ return {
2022
+ title: name,
2023
+ subject: `Log drain "${name}" is still unverified`,
2024
+ previewLine: "Unverified after 24 hours \u2014 nothing is being delivered",
2025
+ summary: `The log drain "${name}" (${view.type}) was created more than 24 hours ago and has never completed verification, so nothing is being delivered to it.${becauseClause(view)} Run \`lua drains verify ${view.id}\` once the destination echoes the verification token.`,
2026
+ status: "failed",
2027
+ priority: "normal"
2028
+ };
2029
+ default: {
2030
+ const exhaustive = payload.kind;
2031
+ throw new Error(`unhandled log-drain notice kind: ${String(exhaustive)}`);
2032
+ }
2033
+ }
2034
+ }
2035
+ __name(logDrainNoticeCopy, "logDrainNoticeCopy");
2036
+ __name2(logDrainNoticeCopy, "logDrainNoticeCopy");
2037
+ function logDrainNoticeLabel(kind) {
2038
+ switch (kind) {
2039
+ case "failing":
2040
+ return "failing";
2041
+ case "paused_auto":
2042
+ return "paused (no success for 24 h)";
2043
+ case "paused_quota":
2044
+ return "paused (daily allowance exhausted)";
2045
+ case "quota_warning":
2046
+ return "80% of the daily allowance used";
2047
+ case "dropped":
2048
+ return "dropping records";
2049
+ case "verification_pending":
2050
+ return "still unverified";
2051
+ default: {
2052
+ const exhaustive = kind;
2053
+ throw new Error(`unhandled log-drain notice kind: ${String(exhaustive)}`);
2054
+ }
2055
+ }
2056
+ }
2057
+ __name(logDrainNoticeLabel, "logDrainNoticeLabel");
2058
+ __name2(logDrainNoticeLabel, "logDrainNoticeLabel");
2059
+ function logDrainNoticeDigestCopy(payload) {
2060
+ const entries = [
2061
+ ...payload.entries ?? []
2062
+ ].sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : 0).slice(0, LOG_DRAIN_DIGEST_MAX_ENTRIES);
2063
+ const drains = new Set(entries.map((entry) => entry.drainId));
2064
+ const noun = `${entries.length} notice${entries.length === 1 ? "" : "s"}`;
2065
+ const across = `${drains.size} drain${drains.size === 1 ? "" : "s"}`;
2066
+ const lines = entries.map((entry) => `${entry.drainName || entry.drainId} \u2014 ${logDrainNoticeLabel(entry.kind)}`);
2067
+ return {
2068
+ title: "Log drains \u2014 daily summary",
2069
+ subject: `Log drains \u2014 ${noun} in the last day`,
2070
+ previewLine: `${noun} across ${across}`,
2071
+ summary: `${noun} across ${across} in the last day: ${lines.join("; ")}.`,
2072
+ status: "failed",
2073
+ priority: "normal"
2074
+ };
2075
+ }
2076
+ __name(logDrainNoticeDigestCopy, "logDrainNoticeDigestCopy");
2077
+ __name2(logDrainNoticeDigestCopy, "logDrainNoticeDigestCopy");
2078
+ var LOG_DRAIN_USAGE_LINE_ITEM = "log_drain_events";
2079
+ var LOG_DRAIN_BYTES_PER_GIB = 1024 ** 3;
2080
+ var DEFAULT_LOG_DRAIN_PLAN_CONFIG = {
2081
+ version: 1,
2082
+ tiers: {
2083
+ team: {
2084
+ ...LOG_DRAIN_QUOTAS.team
2085
+ },
2086
+ business: {
2087
+ ...LOG_DRAIN_QUOTAS.business
2088
+ },
2089
+ enterprise: {
2090
+ ...LOG_DRAIN_QUOTAS.enterprise
2091
+ }
2092
+ },
2093
+ pricing: {
2094
+ team: {
2095
+ includedEventsPerMonth: 0,
2096
+ includedBytesPerMonth: 0,
2097
+ usdPerMillionEvents: 0,
2098
+ usdPerGiB: 0
2099
+ },
2100
+ business: {
2101
+ includedEventsPerMonth: 0,
2102
+ includedBytesPerMonth: 0,
2103
+ usdPerMillionEvents: 0,
2104
+ usdPerGiB: 0
2105
+ },
2106
+ enterprise: {
2107
+ includedEventsPerMonth: 0,
2108
+ includedBytesPerMonth: 0,
2109
+ usdPerMillionEvents: 0,
2110
+ usdPerGiB: 0
2111
+ }
2112
+ }
2113
+ };
2114
+ var TIERS = [
2115
+ "team",
2116
+ "business",
2117
+ "enterprise"
2118
+ ];
2119
+ function finiteNonNegative(value3) {
2120
+ return typeof value3 === "number" && Number.isFinite(value3) && value3 >= 0 ? value3 : void 0;
2121
+ }
2122
+ __name(finiteNonNegative, "finiteNonNegative");
2123
+ __name2(finiteNonNegative, "finiteNonNegative");
2124
+ function mergeLimits(base, stored) {
2125
+ const patch = stored ?? {};
2126
+ return {
2127
+ eventsPerDay: finiteNonNegative(patch.eventsPerDay) ?? base.eventsPerDay,
2128
+ bytesPerDay: finiteNonNegative(patch.bytesPerDay) ?? base.bytesPerDay
2129
+ };
2130
+ }
2131
+ __name(mergeLimits, "mergeLimits");
2132
+ __name2(mergeLimits, "mergeLimits");
2133
+ function mergeCard(base, stored) {
2134
+ const patch = stored ?? {};
2135
+ return {
2136
+ includedEventsPerMonth: finiteNonNegative(patch.includedEventsPerMonth) ?? base.includedEventsPerMonth,
2137
+ includedBytesPerMonth: finiteNonNegative(patch.includedBytesPerMonth) ?? base.includedBytesPerMonth,
2138
+ usdPerMillionEvents: finiteNonNegative(patch.usdPerMillionEvents) ?? base.usdPerMillionEvents,
2139
+ usdPerGiB: finiteNonNegative(patch.usdPerGiB) ?? base.usdPerGiB
2140
+ };
2141
+ }
2142
+ __name(mergeCard, "mergeCard");
2143
+ __name2(mergeCard, "mergeCard");
2144
+ function resolveStoredLogDrainPlanConfig(stored) {
2145
+ const values = stored;
2146
+ if (!values || typeof values.version !== "number" || !Number.isFinite(values.version)) {
2147
+ return DEFAULT_LOG_DRAIN_PLAN_CONFIG;
2148
+ }
2149
+ const tiers = {};
2150
+ const pricing = {};
2151
+ for (const tier of TIERS) {
2152
+ tiers[tier] = mergeLimits(DEFAULT_LOG_DRAIN_PLAN_CONFIG.tiers[tier], values.tiers?.[tier]);
2153
+ pricing[tier] = mergeCard(DEFAULT_LOG_DRAIN_PLAN_CONFIG.pricing[tier], values.pricing?.[tier]);
2154
+ }
2155
+ const orgs = {};
2156
+ for (const [orgId, override] of Object.entries(values.orgs ?? {})) {
2157
+ if (!orgId || !override || typeof override !== "object") continue;
2158
+ const row = {};
2159
+ if (override.tier && TIERS.includes(override.tier)) row.tier = override.tier;
2160
+ const events = finiteNonNegative(override.eventsPerDay);
2161
+ const bytes = finiteNonNegative(override.bytesPerDay);
2162
+ if (events !== void 0) row.eventsPerDay = events;
2163
+ if (bytes !== void 0) row.bytesPerDay = bytes;
2164
+ if (override.pricing && typeof override.pricing === "object") row.pricing = {
2165
+ ...override.pricing
2166
+ };
2167
+ if (Object.keys(row).length) orgs[orgId] = row;
2168
+ }
2169
+ return {
2170
+ version: values.version,
2171
+ tiers,
2172
+ pricing,
2173
+ ...Object.keys(orgs).length ? {
2174
+ orgs
2175
+ } : {}
2176
+ };
2177
+ }
2178
+ __name(resolveStoredLogDrainPlanConfig, "resolveStoredLogDrainPlanConfig");
2179
+ __name2(resolveStoredLogDrainPlanConfig, "resolveStoredLogDrainPlanConfig");
2180
+ function logDrainPlanTierOverride(config, orgId) {
2181
+ return orgId ? config.orgs?.[orgId]?.tier : void 0;
2182
+ }
2183
+ __name(logDrainPlanTierOverride, "logDrainPlanTierOverride");
2184
+ __name2(logDrainPlanTierOverride, "logDrainPlanTierOverride");
2185
+ function logDrainQuotaLimitsFor(config, orgId, tier) {
2186
+ const base = config.tiers[tier] ?? config.tiers.team ?? LOG_DRAIN_QUOTAS.team;
2187
+ const override = orgId ? config.orgs?.[orgId] : void 0;
2188
+ if (!override) return {
2189
+ ...base
2190
+ };
2191
+ return {
2192
+ eventsPerDay: override.eventsPerDay ?? base.eventsPerDay,
2193
+ bytesPerDay: override.bytesPerDay ?? base.bytesPerDay
2194
+ };
2195
+ }
2196
+ __name(logDrainQuotaLimitsFor, "logDrainQuotaLimitsFor");
2197
+ __name2(logDrainQuotaLimitsFor, "logDrainQuotaLimitsFor");
2198
+ function logDrainPriceCardFor(config, orgId, tier) {
2199
+ const base = config.pricing[tier] ?? config.pricing.team ?? DEFAULT_LOG_DRAIN_PLAN_CONFIG.pricing.team;
2200
+ const override = orgId ? config.orgs?.[orgId]?.pricing : void 0;
2201
+ return override ? mergeCard(base, override) : {
2202
+ ...base
2203
+ };
2204
+ }
2205
+ __name(logDrainPriceCardFor, "logDrainPriceCardFor");
2206
+ __name2(logDrainPriceCardFor, "logDrainPriceCardFor");
2207
+ function priceDrainUsage(totals, card, tier) {
2208
+ const billableRecords = Math.max(0, Math.floor(finiteNonNegative(totals?.billableRecords) ?? 0));
2209
+ const billableBytes = Math.max(0, Math.floor(finiteNonNegative(totals?.billableBytes) ?? 0));
2210
+ const includedEvents = card.includedEventsPerMonth;
2211
+ const includedBytes = card.includedBytesPerMonth;
2212
+ const overageEvents = Math.max(0, billableRecords - includedEvents);
2213
+ const overageBytes = Math.max(0, billableBytes - includedBytes);
2214
+ const eventsUsd = overageEvents / 1e6 * card.usdPerMillionEvents;
2215
+ const bytesUsd = overageBytes / LOG_DRAIN_BYTES_PER_GIB * card.usdPerGiB;
2216
+ const unpriced = card.usdPerMillionEvents === 0 && card.usdPerGiB === 0;
2217
+ const round = /* @__PURE__ */ __name2((usd) => Math.round(usd * 100) / 100, "round");
2218
+ return {
2219
+ lineItem: LOG_DRAIN_USAGE_LINE_ITEM,
2220
+ tier,
2221
+ billableRecords,
2222
+ billableBytes,
2223
+ includedEvents,
2224
+ includedBytes,
2225
+ overageEvents,
2226
+ overageBytes,
2227
+ eventsUsd: round(eventsUsd),
2228
+ bytesUsd: round(bytesUsd),
2229
+ usd: round(Math.max(eventsUsd, bytesUsd)),
2230
+ unpriced
2231
+ };
2232
+ }
2233
+ __name(priceDrainUsage, "priceDrainUsage");
2234
+ __name2(priceDrainUsage, "priceDrainUsage");
1335
2235
  var LOG_CURSOR_MAX_LENGTH = 512;
1336
2236
  var LOG_CURSOR_MAX_ID_LENGTH = 128;
1337
2237
  var LOG_RELATIVE_TIME_PATTERN = /^(\d{1,9})([smhd])$/;
@@ -1361,12 +2261,12 @@ function decodeLogCursor(raw) {
1361
2261
  return null;
1362
2262
  }
1363
2263
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
1364
- const { t, id } = parsed;
2264
+ const { t, id: id2 } = parsed;
1365
2265
  if (typeof t !== "number" || !Number.isSafeInteger(t) || t < 0) return null;
1366
- if (typeof id !== "string" || !id || id.length > LOG_CURSOR_MAX_ID_LENGTH) return null;
2266
+ if (typeof id2 !== "string" || !id2 || id2.length > LOG_CURSOR_MAX_ID_LENGTH) return null;
1367
2267
  return {
1368
2268
  t,
1369
- id
2269
+ id: id2
1370
2270
  };
1371
2271
  }
1372
2272
  __name(decodeLogCursor, "decodeLogCursor");
@@ -2232,64 +3132,64 @@ function hasCapability(profiles, profileId, required) {
2232
3132
  }
2233
3133
  __name(hasCapability, "hasCapability");
2234
3134
  __name2(hasCapability, "hasCapability");
2235
- function workflowJobId(id) {
2236
- switch (id.kind) {
3135
+ function workflowJobId(id2) {
3136
+ switch (id2.kind) {
2237
3137
  case "start":
2238
- return `wft_${id.runId}_0`;
3138
+ return `wft_${id2.runId}_0`;
2239
3139
  case "start-redrive":
2240
- return `wft_${id.runId}_start_r${id.now}`;
3140
+ return `wft_${id2.runId}_start_r${id2.now}`;
2241
3141
  case "tick":
2242
- return `wft_${id.runId}_${id.seq}`;
3142
+ return `wft_${id2.runId}_${id2.seq}`;
2243
3143
  case "timer":
2244
- return `wft_${id.runId}_timer_${id.stepId}_${id.attempt}`;
3144
+ return `wft_${id2.runId}_timer_${id2.stepId}_${id2.attempt}`;
2245
3145
  case "timer-remainder":
2246
- return `wft_${id.runId}_timer_${id.stepId}_${id.attempt}_r${id.now}`;
3146
+ return `wft_${id2.runId}_timer_${id2.stepId}_${id2.attempt}_r${id2.now}`;
2247
3147
  case "timer-deferral":
2248
- return `wft_${id.runId}_timer_${id.stepId}_${id.attempt}_d${id.now}`;
3148
+ return `wft_${id2.runId}_timer_${id2.stepId}_${id2.attempt}_d${id2.now}`;
2249
3149
  case "timer-sibling":
2250
- return `wft_${id.runId}_timer_${id.stepId}_${id.attempt}_w${id.now}`;
3150
+ return `wft_${id2.runId}_timer_${id2.stepId}_${id2.attempt}_w${id2.now}`;
2251
3151
  case "retry":
2252
- return `wft_${id.runId}_retry_${id.stepId}_${id.attempt}`;
3152
+ return `wft_${id2.runId}_retry_${id2.stepId}_${id2.attempt}`;
2253
3153
  case "respawn":
2254
- return `wft_${id.runId}_respawn_${id.stepId}_${id.attempt}_s${id.segment}_r${id.now}`;
3154
+ return `wft_${id2.runId}_respawn_${id2.stepId}_${id2.attempt}_s${id2.segment}_r${id2.now}`;
2255
3155
  case "redrive":
2256
- return `wft_${id.runId}_redrive_${id.stepId}_${id.attempt}_r${id.now}`;
3156
+ return `wft_${id2.runId}_redrive_${id2.stepId}_${id2.attempt}_r${id2.now}`;
2257
3157
  case "redispatch":
2258
- return `wft_${id.runId}_redispatch_${id.stepId}_${id.attempt}_x${id.executionId ?? "none"}_r${id.now}`;
3158
+ return `wft_${id2.runId}_redispatch_${id2.stepId}_${id2.attempt}_x${id2.executionId ?? "none"}_r${id2.now}`;
2259
3159
  case "expiry":
2260
- return `wft_${id.runId}_expire_${id.stepId}_${id.attempt}_t${id.suspendedAt}${id.hop > 0 ? `_h${id.hop}` : ""}`;
3160
+ return `wft_${id2.runId}_expire_${id2.stepId}_${id2.attempt}_t${id2.suspendedAt}${id2.hop > 0 ? `_h${id2.hop}` : ""}`;
2261
3161
  case "step-terminal":
2262
- return `wft_${id.runId}_term_${id.stepId}_${id.attempt}_r${id.now}`;
3162
+ return `wft_${id2.runId}_term_${id2.stepId}_${id2.attempt}_r${id2.now}`;
2263
3163
  case "handback":
2264
- return `wft_${id.runId}_handback_${id.stepId}_${id.attempt}_${id.now}`;
3164
+ return `wft_${id2.runId}_handback_${id2.stepId}_${id2.attempt}_${id2.now}`;
2265
3165
  case "foreach-rate":
2266
- return `wft_${id.runId}_fe_${id.stepId}_${id.attempt}_${id.bucket}`;
3166
+ return `wft_${id2.runId}_fe_${id2.stepId}_${id2.attempt}_${id2.bucket}`;
2267
3167
  case "budget-expiry":
2268
- return `wft_${id.runId}_expiry_budget_r${id.now}`;
3168
+ return `wft_${id2.runId}_expiry_budget_r${id2.now}`;
2269
3169
  case "budget-resume":
2270
- return `wft_${id.runId}_resume_budget_${id.now}`;
3170
+ return `wft_${id2.runId}_resume_budget_${id2.now}`;
2271
3171
  case "deadline":
2272
- return `wft_${id.runId}_deadline_${id.deadlineAt}`;
3172
+ return `wft_${id2.runId}_deadline_${id2.deadlineAt}`;
2273
3173
  case "deadline-remainder":
2274
- return `wft_${id.runId}_deadline_${id.deadlineAt}_r${id.now}`;
3174
+ return `wft_${id2.runId}_deadline_${id2.deadlineAt}_r${id2.now}`;
2275
3175
  case "readmit":
2276
- return `wft_${id.runId}_readmit_${id.now}`;
3176
+ return `wft_${id2.runId}_readmit_${id2.now}`;
2277
3177
  case "cancel":
2278
- return `wft_${id.runId}_cancel`;
3178
+ return `wft_${id2.runId}_cancel`;
2279
3179
  case "reconcile":
2280
- return `wft_${id.runId}_reconcile_${id.now}`;
3180
+ return `wft_${id2.runId}_reconcile_${id2.now}`;
2281
3181
  case "replay":
2282
- return `wft_${id.runId}_replay_g${id.leaseGeneration}`;
3182
+ return `wft_${id2.runId}_replay_g${id2.leaseGeneration}`;
2283
3183
  case "migration":
2284
- return `wfm_${id.migrationId}`;
3184
+ return `wfm_${id2.migrationId}`;
2285
3185
  default:
2286
- return assertNever(id);
3186
+ return assertNever(id2);
2287
3187
  }
2288
3188
  }
2289
3189
  __name(workflowJobId, "workflowJobId");
2290
3190
  __name2(workflowJobId, "workflowJobId");
2291
- function assertNever(id) {
2292
- throw new Error(`workflowJobId: unknown wake kind ${JSON.stringify(id)}`);
3191
+ function assertNever(id2) {
3192
+ throw new Error(`workflowJobId: unknown wake kind ${JSON.stringify(id2)}`);
2293
3193
  }
2294
3194
  __name(assertNever, "assertNever");
2295
3195
  __name2(assertNever, "assertNever");
@@ -2420,13 +3320,13 @@ var IDEMPOTENCY_HOLDING_STATUSES = [
2420
3320
  ];
2421
3321
  var WORKFLOW_SCHEDULED_RUN_ID_PREFIX = "wfr_sched_";
2422
3322
  var CLOUD_TASK_RUN_ID_PREFIX = "ct_";
2423
- function isCloudTaskRunId(id) {
2424
- return id.startsWith(CLOUD_TASK_RUN_ID_PREFIX);
3323
+ function isCloudTaskRunId(id2) {
3324
+ return id2.startsWith(CLOUD_TASK_RUN_ID_PREFIX);
2425
3325
  }
2426
3326
  __name(isCloudTaskRunId, "isCloudTaskRunId");
2427
3327
  __name2(isCloudTaskRunId, "isCloudTaskRunId");
2428
- function isScheduledWorkflowRunId(id) {
2429
- return id.startsWith(WORKFLOW_SCHEDULED_RUN_ID_PREFIX);
3328
+ function isScheduledWorkflowRunId(id2) {
3329
+ return id2.startsWith(WORKFLOW_SCHEDULED_RUN_ID_PREFIX);
2430
3330
  }
2431
3331
  __name(isScheduledWorkflowRunId, "isScheduledWorkflowRunId");
2432
3332
  __name2(isScheduledWorkflowRunId, "isScheduledWorkflowRunId");
@@ -3210,10 +4110,246 @@ function effectiveAgentFeatures(base, override, rule) {
3210
4110
  }
3211
4111
  __name(effectiveAgentFeatures, "effectiveAgentFeatures");
3212
4112
  __name2(effectiveAgentFeatures, "effectiveAgentFeatures");
4113
+ var ONBOARDING_FLOW_KEY = "alpha-choose-meet";
4114
+ var ONBOARDING_SCHEMA_VERSION = 1;
4115
+ var id = z4.string().min(1).max(80).regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/);
4116
+ var copy = /* @__PURE__ */ __name2((max) => z4.string().max(max), "copy");
4117
+ var onboardingHeadingSchema = z4.discriminatedUnion("kind", [
4118
+ z4.object({
4119
+ kind: z4.literal("plain"),
4120
+ text: copy(240)
4121
+ }).strict(),
4122
+ z4.object({
4123
+ kind: z4.literal("highlighted"),
4124
+ before: copy(240),
4125
+ highlight: copy(240),
4126
+ after: copy(240)
4127
+ }).strict()
4128
+ ]);
4129
+ var onboardingRichTextInlineSchema = z4.discriminatedUnion("kind", [
4130
+ z4.object({
4131
+ kind: z4.literal("text"),
4132
+ text: copy(2e3),
4133
+ marks: z4.array(z4.enum([
4134
+ "bold",
4135
+ "italic"
4136
+ ])).max(2).refine((marks) => new Set(marks).size === marks.length, "Text marks must be unique").optional()
4137
+ }).strict(),
4138
+ z4.object({
4139
+ kind: z4.literal("lineBreak")
4140
+ }).strict()
4141
+ ]);
4142
+ var onboardingRichTextSchema = z4.object({
4143
+ blocks: z4.array(z4.object({
4144
+ kind: z4.literal("paragraph"),
4145
+ content: z4.array(onboardingRichTextInlineSchema).max(100)
4146
+ }).strict()).max(40)
4147
+ }).strict();
4148
+ var onboardingDestinationSchema = z4.discriminatedUnion("kind", [
4149
+ z4.object({
4150
+ kind: z4.literal("question"),
4151
+ questionId: id
4152
+ }).strict(),
4153
+ z4.object({
4154
+ kind: z4.literal("template"),
4155
+ templateContentId: id
4156
+ }).strict(),
4157
+ z4.object({
4158
+ kind: z4.literal("unavailable"),
4159
+ unavailableId: id
4160
+ }).strict()
4161
+ ]);
4162
+ var onboardingArtworkSchema = z4.discriminatedUnion("kind", [
4163
+ z4.object({
4164
+ kind: z4.literal("builtinRing")
4165
+ }).strict(),
4166
+ z4.object({
4167
+ kind: z4.literal("uploaded"),
4168
+ assetId: id,
4169
+ accessibility: z4.discriminatedUnion("kind", [
4170
+ z4.object({
4171
+ kind: z4.literal("decorative")
4172
+ }).strict(),
4173
+ z4.object({
4174
+ kind: z4.literal("described"),
4175
+ altText: copy(500)
4176
+ }).strict()
4177
+ ])
4178
+ }).strict()
4179
+ ]);
4180
+ var onboardingAnswerSchema = z4.object({
4181
+ id,
4182
+ label: copy(160),
4183
+ supportingText: copy(500).optional(),
4184
+ destination: onboardingDestinationSchema.nullable()
4185
+ }).strict();
4186
+ var onboardingQuestionSchema = z4.object({
4187
+ id,
4188
+ heading: onboardingHeadingSchema,
4189
+ helperText: onboardingRichTextSchema.optional(),
4190
+ continueButtonLabel: copy(80),
4191
+ answers: z4.array(onboardingAnswerSchema).max(30)
4192
+ }).strict();
4193
+ var onboardingTemplateSectionSchema = z4.object({
4194
+ id,
4195
+ label: copy(100),
4196
+ body: onboardingRichTextSchema
4197
+ }).strict();
4198
+ var onboardingTemplateContentSchema = z4.object({
4199
+ id,
4200
+ templateId: copy(160),
4201
+ displayName: copy(100),
4202
+ eyebrow: copy(100).optional(),
4203
+ heading: onboardingHeadingSchema,
4204
+ description: onboardingRichTextSchema,
4205
+ badges: z4.array(copy(80)).max(12),
4206
+ sections: z4.array(onboardingTemplateSectionSchema).max(20),
4207
+ artwork: onboardingArtworkSchema,
4208
+ hireButtonLabel: copy(80),
4209
+ changeRoleButtonLabel: copy(80),
4210
+ nextStepText: onboardingRichTextSchema
4211
+ }).strict();
4212
+ var onboardingUnavailableOutcomeSchema = z4.object({
4213
+ id,
4214
+ heading: onboardingHeadingSchema,
4215
+ explanation: onboardingRichTextSchema,
4216
+ backButtonLabel: copy(80),
4217
+ alternative: z4.object({
4218
+ templateContentId: id,
4219
+ introduction: onboardingRichTextSchema,
4220
+ buttonLabel: copy(80)
4221
+ }).strict().optional()
4222
+ }).strict();
4223
+ var onboardingFlowSchema = z4.object({
4224
+ key: z4.literal(ONBOARDING_FLOW_KEY),
4225
+ schemaVersion: z4.literal(ONBOARDING_SCHEMA_VERSION),
4226
+ entryQuestionId: id.nullable(),
4227
+ questions: z4.array(onboardingQuestionSchema).max(100),
4228
+ templateContents: z4.array(onboardingTemplateContentSchema).max(100),
4229
+ unavailableOutcomes: z4.array(onboardingUnavailableOutcomeSchema).max(100)
4230
+ }).strict();
4231
+ var onboardingActorSchema = z4.object({
4232
+ subjectId: z4.string(),
4233
+ email: z4.string().email()
4234
+ }).strict();
4235
+ var onboardingEditorSchema = onboardingActorSchema.extend({
4236
+ editedAt: z4.string().datetime({
4237
+ offset: true
4238
+ })
4239
+ }).strict();
4240
+ var onboardingPublicationSummarySchema = z4.object({
4241
+ publicationId: id,
4242
+ revision: z4.number().int().positive(),
4243
+ sourceDraftVersion: z4.number().int().nonnegative(),
4244
+ contentHash: z4.string().regex(/^[a-f0-9]{64}$/),
4245
+ publishedAt: z4.string().datetime({
4246
+ offset: true
4247
+ }),
4248
+ publishedBy: onboardingActorSchema,
4249
+ questionCount: z4.number().int().nonnegative(),
4250
+ templateCount: z4.number().int().nonnegative(),
4251
+ unavailableCount: z4.number().int().nonnegative()
4252
+ }).strict();
4253
+ var onboardingValidationIssueSchema = z4.object({
4254
+ code: z4.string(),
4255
+ path: z4.string(),
4256
+ message: z4.string()
4257
+ }).strict();
4258
+ var onboardingValidationResponseSchema = z4.discriminatedUnion("valid", [
4259
+ z4.object({
4260
+ valid: z4.literal(true),
4261
+ summary: z4.object({
4262
+ questionCount: z4.number().int().nonnegative(),
4263
+ templateCount: z4.number().int().nonnegative(),
4264
+ unavailableCount: z4.number().int().nonnegative()
4265
+ }).strict()
4266
+ }).strict(),
4267
+ z4.object({
4268
+ valid: z4.literal(false),
4269
+ issues: z4.array(onboardingValidationIssueSchema)
4270
+ }).strict()
4271
+ ]);
4272
+ var onboardingAssetSchema = z4.object({
4273
+ assetId: id,
4274
+ url: z4.string().url(),
4275
+ width: z4.number().int().positive(),
4276
+ height: z4.number().int().positive(),
4277
+ contentType: z4.enum([
4278
+ "image/png",
4279
+ "image/jpeg",
4280
+ "image/webp"
4281
+ ]),
4282
+ bytes: z4.number().int().positive(),
4283
+ sha256: z4.string().regex(/^[a-f0-9]{64}$/),
4284
+ createdAt: z4.string().datetime({
4285
+ offset: true
4286
+ }),
4287
+ uploadedBy: onboardingActorSchema
4288
+ }).strict();
4289
+ var onboardingPublicAssetSchema = onboardingAssetSchema.pick({
4290
+ assetId: true,
4291
+ url: true,
4292
+ width: true,
4293
+ height: true,
4294
+ contentType: true
4295
+ }).strict();
4296
+ var getOnboardingConfigResponseSchema = z4.object({
4297
+ flowKey: z4.literal(ONBOARDING_FLOW_KEY),
4298
+ draftVersion: z4.number().int().nonnegative(),
4299
+ draft: onboardingFlowSchema,
4300
+ assets: z4.array(onboardingAssetSchema),
4301
+ lastEditor: onboardingEditorSchema.nullable(),
4302
+ activePublication: onboardingPublicationSummarySchema.nullable()
4303
+ }).strict();
4304
+ var saveOnboardingDraftRequestSchema = z4.object({
4305
+ expectedDraftVersion: z4.number().int().nonnegative(),
4306
+ draft: onboardingFlowSchema
4307
+ }).strict();
4308
+ var validateOnboardingRequestSchema = z4.object({
4309
+ draft: onboardingFlowSchema
4310
+ }).strict();
4311
+ var publishOnboardingRequestSchema = z4.object({
4312
+ expectedDraftVersion: z4.number().int().nonnegative(),
4313
+ expectedActivePublicationId: id.nullable()
4314
+ }).strict();
4315
+ var rollbackOnboardingRequestSchema = z4.object({
4316
+ publicationId: id,
4317
+ expectedActivePublicationId: id.nullable()
4318
+ }).strict();
4319
+ var onboardingTemplateCatalogItemSchema = z4.object({
4320
+ templateId: z4.string(),
4321
+ name: z4.string(),
4322
+ description: z4.string().optional()
4323
+ }).strict();
4324
+ var getPublishedOnboardingResponseSchema = z4.discriminatedUnion("status", [
4325
+ z4.object({
4326
+ status: z4.literal("available"),
4327
+ publicationId: id,
4328
+ revision: z4.number().int().positive(),
4329
+ contentHash: z4.string().regex(/^[a-f0-9]{64}$/),
4330
+ flow: onboardingFlowSchema,
4331
+ assets: z4.array(onboardingPublicAssetSchema)
4332
+ }).strict(),
4333
+ z4.object({
4334
+ status: z4.literal("unavailable"),
4335
+ reason: z4.literal("not_published"),
4336
+ message: z4.string()
4337
+ }).strict()
4338
+ ]);
4339
+ function parseOnboardingFlow(value3) {
4340
+ return onboardingFlowSchema.parse(value3);
4341
+ }
4342
+ __name(parseOnboardingFlow, "parseOnboardingFlow");
4343
+ __name2(parseOnboardingFlow, "parseOnboardingFlow");
4344
+ function parsePublishedOnboardingResponse(value3) {
4345
+ return getPublishedOnboardingResponseSchema.parse(value3);
4346
+ }
4347
+ __name(parsePublishedOnboardingResponse, "parsePublishedOnboardingResponse");
4348
+ __name2(parsePublishedOnboardingResponse, "parsePublishedOnboardingResponse");
3213
4349
 
3214
4350
  // ../workflow-graph/dist/index.mjs
3215
4351
  import { createHash } from "crypto";
3216
- import { z as z4 } from "zod";
4352
+ import { z as z5 } from "zod";
3217
4353
  import { z as z22 } from "zod";
3218
4354
 
3219
4355
  // ../shared-types/dist/workflow-job-tools.mjs
@@ -3249,9 +4385,9 @@ var WORKFLOW_JOB_DEFAULT_TOOLS = [
3249
4385
  function effectiveJobTools(jobTools, readOnly) {
3250
4386
  const base = jobTools?.length ? jobTools : WORKFLOW_JOB_DEFAULT_TOOLS;
3251
4387
  const out = [];
3252
- for (const id of base) {
3253
- if (readOnly && WORKFLOW_JOB_READ_ONLY_DROPPED.includes(id)) continue;
3254
- if (!out.includes(id)) out.push(id);
4388
+ for (const id2 of base) {
4389
+ if (readOnly && WORKFLOW_JOB_READ_ONLY_DROPPED.includes(id2)) continue;
4390
+ if (!out.includes(id2)) out.push(id2);
3255
4391
  }
3256
4392
  return out;
3257
4393
  }
@@ -3440,9 +4576,9 @@ function malformedMapMembers(cfg) {
3440
4576
  }
3441
4577
  __name(malformedMapMembers, "malformedMapMembers");
3442
4578
  __name4(malformedMapMembers, "malformedMapMembers");
3443
- function mapMemberMalformedMessage(id, m) {
4579
+ function mapMemberMalformedMessage(id2, m) {
3444
4580
  const keys = m.keys.map((k) => `\`${k}\``).join(", ");
3445
- return `"${id}".${m.member} carries descriptor key${m.keys.length === 1 ? "" : "s"} ${keys} but is not an exact binding form ({initData:true, path} | {step, path[, rows]} | {value} | {template} | {requestContextPath} | {knowledge}) \u2014 it is passed to the step verbatim as a literal; fix the descriptor, or wrap it in {value: \u2026} if the literal is intended`;
4581
+ return `"${id2}".${m.member} carries descriptor key${m.keys.length === 1 ? "" : "s"} ${keys} but is not an exact binding form ({initData:true, path} | {step, path[, rows]} | {value} | {template} | {requestContextPath} | {knowledge}) \u2014 it is passed to the step verbatim as a literal; fix the descriptor, or wrap it in {value: \u2026} if the literal is intended`;
3446
4582
  }
3447
4583
  __name(mapMemberMalformedMessage, "mapMemberMalformedMessage");
3448
4584
  __name4(mapMemberMalformedMessage, "mapMemberMalformedMessage");
@@ -3552,8 +4688,8 @@ var rows = /* @__PURE__ */ __name4((s, path, page) => ({
3552
4688
  var fromKnowledge = /* @__PURE__ */ __name4((k) => ({
3553
4689
  knowledge: k
3554
4690
  }), "fromKnowledge");
3555
- var SideEffectsSchema = z4.enum(WORKFLOW_SIDE_EFFECTS);
3556
- var JobResourcesSchema = z4.enum(WORKFLOW_JOB_RESOURCES);
4691
+ var SideEffectsSchema = z5.enum(WORKFLOW_SIDE_EFFECTS);
4692
+ var JobResourcesSchema = z5.enum(WORKFLOW_JOB_RESOURCES);
3557
4693
  var WORKFLOW_MODEL_TEMPLATE_ROOT = "initData";
3558
4694
  var WORKFLOW_MODEL_TEMPLATE_RE = /^\$\{\s*initData\.([A-Za-z0-9_.\-[\]]+)\s*(?:\|([^}]*))?\}$/;
3559
4695
  var PATH_SEGMENT_RE = /^[A-Za-z0-9_-]+(?:\[(?:0|[1-9]\d*)\])*$/;
@@ -3944,13 +5080,13 @@ var SLEEP_UNTIL_REPLACEMENT = Object.freeze({
3944
5080
  type: "sleep",
3945
5081
  duration: 6e4
3946
5082
  });
3947
- function sleepUntilUnsupportedMessage(id) {
3948
- return `the engine does not execute \`sleepUntil\` yet (node "${id}") \u2014 replace it with a \`sleep\` node with a \`duration\` in ms, e.g. { type: 'sleep', id: '${id}', duration: ${SLEEP_UNTIL_REPLACEMENT.duration} }`;
5083
+ function sleepUntilUnsupportedMessage(id2) {
5084
+ return `the engine does not execute \`sleepUntil\` yet (node "${id2}") \u2014 replace it with a \`sleep\` node with a \`duration\` in ms, e.g. { type: 'sleep', id: '${id2}', duration: ${SLEEP_UNTIL_REPLACEMENT.duration} }`;
3949
5085
  }
3950
5086
  __name(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
3951
5087
  __name4(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
3952
- function armSubrunUnsupportedMessage(id, workflowId) {
3953
- return `the engine does not execute the implicit \`${workflowId}\` arm subrun (node "${id}") \u2014 a [map, step] container arm is the step itself with the map as its \`input\` since lua-cli 3.32.4; re-run \`lua compile\` with the current CLI (a hand-written artifact: put the map on the arm node's \`input\` and drop the \`workflow\` wrapper)`;
5088
+ function armSubrunUnsupportedMessage(id2, workflowId) {
5089
+ return `the engine does not execute the implicit \`${workflowId}\` arm subrun (node "${id2}") \u2014 a [map, step] container arm is the step itself with the map as its \`input\` since lua-cli 3.32.4; re-run \`lua compile\` with the current CLI (a hand-written artifact: put the map on the arm node's \`input\` and drop the \`workflow\` wrapper)`;
3954
5090
  }
3955
5091
  __name(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
3956
5092
  __name4(armSubrunUnsupportedMessage, "armSubrunUnsupportedMessage");
@@ -4288,20 +5424,20 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4288
5424
  const seen = /* @__PURE__ */ new Map();
4289
5425
  let nodeCount = 0;
4290
5426
  const upstream = /* @__PURE__ */ new Set();
4291
- const checkId = /* @__PURE__ */ __name4((id, path) => {
5427
+ const checkId = /* @__PURE__ */ __name4((id2, path) => {
4292
5428
  nodeCount += 1;
4293
- if (seen.has(id)) {
4294
- err("duplicate-step-id", `step id "${id}" is declared twice (first at ${seen.get(id)})`, path, id);
5429
+ if (seen.has(id2)) {
5430
+ err("duplicate-step-id", `step id "${id2}" is declared twice (first at ${seen.get(id2)})`, path, id2);
4295
5431
  } else {
4296
- seen.set(id, path);
5432
+ seen.set(id2, path);
4297
5433
  }
4298
5434
  }, "checkId");
4299
5435
  const checkPolicyEnums = /* @__PURE__ */ __name4((node, path) => {
4300
- const id = singleId(node);
5436
+ const id2 = singleId(node);
4301
5437
  const check = /* @__PURE__ */ __name4((member, allowed) => {
4302
5438
  const value22 = node[member];
4303
5439
  if (value22 === void 0 || typeof value22 === "string" && allowed.includes(value22)) return;
4304
- err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path}.${member}`, id);
5440
+ err("invalid-envelope", `\`${member}\` must be ${allowed.map((a) => `'${a}'`).join(" | ")} (got ${JSON.stringify(value22)})`, `${path}.${member}`, id2);
4305
5441
  }, "check");
4306
5442
  check("sideEffects", WORKFLOW_SIDE_EFFECTS);
4307
5443
  check("jobResources", WORKFLOW_JOB_RESOURCES);
@@ -4309,46 +5445,46 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4309
5445
  const checkRetry = /* @__PURE__ */ __name4((node, path) => {
4310
5446
  const r = node.retry;
4311
5447
  if (!r) return;
4312
- const id = singleId(node);
5448
+ const id2 = singleId(node);
4313
5449
  const unknown = unknownWorkflowRetryMembers(r);
4314
- if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path}.retry`, id);
5450
+ if (unknown.length) err("invalid-envelope", workflowRetryUnknownMembersMessage(unknown), `${path}.retry`, id2);
4315
5451
  if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
4316
5452
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
4317
- err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path}.retry.maxAttempts`, id);
5453
+ err(over ? "cap-exceeded" : "invalid-envelope", workflowRetryMaxAttemptsMessage(r.maxAttempts), `${path}.retry.maxAttempts`, id2);
4318
5454
  }
4319
5455
  const backoffs = retryBackoffs();
4320
5456
  if (r.backoff !== void 0 && !backoffs.includes(r.backoff)) {
4321
5457
  const list = backoffs.map((b) => `'${b}'`).join(" | ");
4322
- err("backoff-invalid", `retry.backoff must be ${list}`, `${path}.retry.backoff`, id);
5458
+ err("backoff-invalid", `retry.backoff must be ${list}`, `${path}.retry.backoff`, id2);
4323
5459
  }
4324
5460
  if (r.backoffSeconds !== void 0 && r.backoffSeconds < 0) {
4325
- err("backoff-invalid", "retry.backoffSeconds must be \u2265 0", `${path}.retry.backoffSeconds`, id);
5461
+ err("backoff-invalid", "retry.backoffSeconds must be \u2265 0", `${path}.retry.backoffSeconds`, id2);
4326
5462
  }
4327
5463
  if (r.maxBackoffSeconds !== void 0) {
4328
5464
  if (r.backoff !== "exponential") {
4329
- err("backoff-invalid", "retry.maxBackoffSeconds is only meaningful with backoff:'exponential'", `${path}.retry`, id);
5465
+ err("backoff-invalid", "retry.maxBackoffSeconds is only meaningful with backoff:'exponential'", `${path}.retry`, id2);
4330
5466
  } else if (r.maxBackoffSeconds <= 0 || r.backoffSeconds !== void 0 && r.maxBackoffSeconds < r.backoffSeconds) {
4331
- err("backoff-invalid", "retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds", `${path}.retry.maxBackoffSeconds`, id);
5467
+ err("backoff-invalid", "retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds", `${path}.retry.maxBackoffSeconds`, id2);
4332
5468
  }
4333
5469
  }
4334
5470
  }, "checkRetry");
4335
5471
  const checkTimeout = /* @__PURE__ */ __name4((node, path) => {
4336
5472
  const t = node.timeoutSeconds;
4337
5473
  if (t === void 0) return;
4338
- const id = singleId(node);
5474
+ const id2 = singleId(node);
4339
5475
  if (!Number.isInteger(t) || t < 1) {
4340
- err("timeout-out-of-range", `timeoutSeconds must be an integer \u2265 1 (got ${t})`, `${path}.timeoutSeconds`, id);
5476
+ err("timeout-out-of-range", `timeoutSeconds must be an integer \u2265 1 (got ${t})`, `${path}.timeoutSeconds`, id2);
4341
5477
  return;
4342
5478
  }
4343
5479
  if (node.tier === "job") {
4344
5480
  const cap = node.type === "agent" ? caps.maxJobTimeoutSeconds : caps.maxJobSegmentSeconds;
4345
5481
  if (t > cap) {
4346
- err("job-timeout-exceeds-cap", `timeoutSeconds ${t} exceeds the Job-tier cap of ${cap} s`, `${path}.timeoutSeconds`, id);
5482
+ err("job-timeout-exceeds-cap", `timeoutSeconds ${t} exceeds the Job-tier cap of ${cap} s`, `${path}.timeoutSeconds`, id2);
4347
5483
  } else if (node.type === "agent" && t > caps.maxJobSegmentSeconds && !node.workspace) {
4348
- err("long-job-requires-workspace", `steps longer than 4 h checkpoint to the run workspace \u2014 add workspace:{mount:'rw'} (and workspace on createWorkflow) or split the step`, `${path}.timeoutSeconds`, id);
5484
+ err("long-job-requires-workspace", `steps longer than 4 h checkpoint to the run workspace \u2014 add workspace:{mount:'rw'} (and workspace on createWorkflow) or split the step`, `${path}.timeoutSeconds`, id2);
4349
5485
  }
4350
5486
  } else if (t > caps.maxWorkerTimeoutSeconds) {
4351
- err("timeout-exceeds-tier", `timeoutSeconds ${t} exceeds the worker tier's ${caps.maxWorkerTimeoutSeconds} s \u2014 steps longer than 10 min run on the Job tier: add tier:'job' (up to ${caps.maxJobSegmentSeconds} s)`, `${path}.timeoutSeconds`, id);
5487
+ err("timeout-exceeds-tier", `timeoutSeconds ${t} exceeds the worker tier's ${caps.maxWorkerTimeoutSeconds} s \u2014 steps longer than 10 min run on the Job tier: add tier:'job' (up to ${caps.maxJobSegmentSeconds} s)`, `${path}.timeoutSeconds`, id2);
4352
5488
  }
4353
5489
  }, "checkTimeout");
4354
5490
  const checkSpecialistRole = /* @__PURE__ */ __name4((node, path) => {
@@ -4412,32 +5548,32 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4412
5548
  return void 0;
4413
5549
  }, "jobClassifiablePin");
4414
5550
  const checkTier = /* @__PURE__ */ __name4((node, path) => {
4415
- const id = singleId(node);
5551
+ const id2 = singleId(node);
4416
5552
  if (node.workspace && node.workspace !== "inherit" && node.tier !== void 0 && node.tier !== "job") {
4417
- err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path}.workspace`, id);
5553
+ err("workspace-requires-job-tier", "a step mounting a workspace must be tier:'job'", `${path}.workspace`, id2);
4418
5554
  }
4419
5555
  if (node.harness !== void 0 && node.tier !== "job") {
4420
- err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${path}.harness`, id);
5556
+ err("harness-requires-job-tier", "`harness` is only legal on a tier:'job' agent step", `${path}.harness`, id2);
4421
5557
  }
4422
5558
  const provider = node.type === "agent" ? classifyModelProvider(jobClassifiablePin(node.model)) : null;
4423
5559
  if (node.harness === "claude-code" && provider !== null && provider !== "anthropic") {
4424
- err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${path}.harness`, id);
5560
+ err("harness-provider-mismatch", `harness:'claude-code' needs an Anthropic model (model "${node.type === "agent" ? node.model : ""}" is ${provider})`, `${path}.harness`, id2);
4425
5561
  }
4426
5562
  if (isJobTier(node) && provider !== null && opts.policy?.jobProviders && !opts.policy.jobProviders.includes(provider)) {
4427
- err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path}.model`, id);
5563
+ err("job-tier-provider-unsupported", `model provider '${provider}' is outside LUA_WF_JOB_PROVIDERS [${opts.policy.jobProviders.join(", ")}]`, `${path}.model`, id2);
4428
5564
  }
4429
5565
  }, "checkTier");
4430
5566
  const checkModel = /* @__PURE__ */ __name4((node, path) => {
4431
5567
  if (node.type !== "agent" || typeof node.model !== "string") return;
4432
- const id = singleId(node);
5568
+ const id2 = singleId(node);
4433
5569
  const parsed = parseModelTemplate(node.model);
4434
5570
  if (parsed.kind === "invalid") {
4435
- err("model-template-invalid", parsed.message, `${path}.model`, id);
5571
+ err("model-template-invalid", parsed.message, `${path}.model`, id2);
4436
5572
  return;
4437
5573
  }
4438
5574
  if (parsed.kind === "template" && parsed.template.default === void 0) {
4439
5575
  if (isJobTier(node)) {
4440
- err("model-template-default-required", modelTemplateDefaultRequiredMessage(node.model), `${path}.model`, id);
5576
+ err("model-template-default-required", modelTemplateDefaultRequiredMessage(node.model), `${path}.model`, id2);
4441
5577
  }
4442
5578
  return;
4443
5579
  }
@@ -4450,12 +5586,12 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4450
5586
  if (registry === "unavailable") {
4451
5587
  const trimmed = pin.trim();
4452
5588
  if (trimmed && !normalizeModelId(trimmed, []).ok) {
4453
- warn("model-unresolved", inContext(`model "${trimmed}" could not be checked against the approved-model registry (unavailable at push) \u2014 it dispatches only if it resolves there (a provider/model registry code, or a bare id exactly one approved model carries)`), `${path}.model`, id);
5589
+ warn("model-unresolved", inContext(`model "${trimmed}" could not be checked against the approved-model registry (unavailable at push) \u2014 it dispatches only if it resolves there (a provider/model registry code, or a bare id exactly one approved model carries)`), `${path}.model`, id2);
4454
5590
  }
4455
5591
  return;
4456
5592
  }
4457
5593
  const resolved = normalizeModelId(pin, registry);
4458
- if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path}.model`, id);
5594
+ if (!resolved.ok) err("model-unresolved", inContext(modelUnresolvedMessage(resolved)), `${path}.model`, id2);
4459
5595
  }, "checkModel");
4460
5596
  const checkTaskClass = /* @__PURE__ */ __name4((node, path) => {
4461
5597
  if (node.type !== "agent" || node.taskClass === void 0) return;
@@ -4464,46 +5600,46 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4464
5600
  err("task-class-without-model", `taskClass '${String(node.taskClass)}' needs a \`model\` on a pushed definition \u2014 write a class (model: 'class/fast' | 'class/balanced' | 'class/strong') or an approved provider/model code; nothing maps a task class to a model at dispatch, so a step with neither would run on the agent\u2019s own model`, `${path}.taskClass`, singleId(node));
4465
5601
  }, "checkTaskClass");
4466
5602
  const checkWorkspace = /* @__PURE__ */ __name4((node, path) => {
4467
- const id = singleId(node);
5603
+ const id2 = singleId(node);
4468
5604
  const ws = workspaceOf(node);
4469
5605
  if (isJobTier(node) && opts.policy && opts.policy.jobTier !== true) {
4470
- err("job-tier-disabled", `"${id}" runs on the Job tier but the org's workflowPolicy.jobTier is off \u2014 an org admin enables it (lua features workflows.caps.jobTier true)`, `${path}.tier`, id);
5606
+ err("job-tier-disabled", `"${id2}" runs on the Job tier but the org's workflowPolicy.jobTier is off \u2014 an org admin enables it (lua features workflows.caps.jobTier true)`, `${path}.tier`, id2);
4471
5607
  }
4472
5608
  const tools = jobToolsOf(node);
4473
5609
  if (tools !== void 0) {
4474
5610
  if (!isJobTier(node)) {
4475
- err("job-tools-require-job-tier", "`jobTools` needs tier:'job'", `${path}.jobTools`, id);
5611
+ err("job-tools-require-job-tier", "`jobTools` needs tier:'job'", `${path}.jobTools`, id2);
4476
5612
  }
4477
5613
  const unknown = (Array.isArray(tools) ? tools : [
4478
5614
  tools
4479
5615
  ]).filter((t) => !WORKFLOW_JOB_TOOLS.includes(t));
4480
5616
  if (unknown.length > 0) {
4481
- err("job-tools-unknown", `jobTools ${JSON.stringify(unknown)} outside WORKFLOW_JOB_TOOLS [${WORKFLOW_JOB_TOOLS.join(", ")}]`, `${path}.jobTools`, id);
5617
+ err("job-tools-unknown", `jobTools ${JSON.stringify(unknown)} outside WORKFLOW_JOB_TOOLS [${WORKFLOW_JOB_TOOLS.join(", ")}]`, `${path}.jobTools`, id2);
4482
5618
  }
4483
5619
  if (node.type === "agent" && (Array.isArray(tools) ? tools : [
4484
5620
  tools
4485
5621
  ]).includes("gh")) {
4486
- warn("gh-on-coding-turn", `"${id}" grants the gh tool on a coding turn \u2014 the pod can open/merge PRs on the workspace repo (purpose:'gh' token, pull_requests:write + contents:write)`, `${path}.jobTools`, id);
5622
+ warn("gh-on-coding-turn", `"${id2}" grants the gh tool on a coding turn \u2014 the pod can open/merge PRs on the workspace repo (purpose:'gh' token, pull_requests:write + contents:write)`, `${path}.jobTools`, id2);
4487
5623
  }
4488
5624
  }
4489
5625
  if (node.type === "agent" && ws && ws !== "inherit" && ws.mount === "ro" && Array.isArray(tools) && effectiveJobTools(tools, true).length === 0) {
4490
- warn("ro-step-has-no-tools", `"${id}" mounts the workspace read-only and every jobTool it declares (${JSON.stringify(tools)}) is one the ro mount drops [${WORKFLOW_JOB_READ_ONLY_DROPPED.join(", ")}] \u2014 the coding turn would run with no tools at all; keep a read-only tool (read/glob/grep, gh) or mount rw`, `${path}.jobTools`, id);
5626
+ warn("ro-step-has-no-tools", `"${id2}" mounts the workspace read-only and every jobTool it declares (${JSON.stringify(tools)}) is one the ro mount drops [${WORKFLOW_JOB_READ_ONLY_DROPPED.join(", ")}] \u2014 the coding turn would run with no tools at all; keep a read-only tool (read/glob/grep, gh) or mount rw`, `${path}.jobTools`, id2);
4491
5627
  }
4492
5628
  if (ws && ws !== "inherit") {
4493
5629
  if (!envelopeWorkspace && !opts.mayInherit) {
4494
- err("workspace-not-declared", `"${id}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path}.workspace`, id);
5630
+ err("workspace-not-declared", `"${id2}" mounts a workspace but the workflow declares none \u2014 add workspace:{kind, \u2026} on createWorkflow`, `${path}.workspace`, id2);
4495
5631
  }
4496
5632
  if (ws.isolation === "worktree" && envelopeWorkspace?.kind === "empty") {
4497
- err("worktree-requires-git-workspace", `"${id}": isolation:'worktree' needs a kind:'git' workspace (the envelope declares kind:'empty')`, `${path}.workspace.isolation`, id);
5633
+ err("worktree-requires-git-workspace", `"${id2}": isolation:'worktree' needs a kind:'git' workspace (the envelope declares kind:'empty')`, `${path}.workspace.isolation`, id2);
4498
5634
  }
4499
5635
  }
4500
5636
  if (node.type === "workflow" && ws === "inherit") {
4501
5637
  if (!envelopeWorkspace) {
4502
- err("workspace-inherit-without-parent-workspace", `"${id}": workspace:'inherit' but the parent workflow declares no workspace \u2014 there is nothing to inherit`, `${path}.workspace`, id);
5638
+ err("workspace-inherit-without-parent-workspace", `"${id2}": workspace:'inherit' but the parent workflow declares no workspace \u2014 there is nothing to inherit`, `${path}.workspace`, id2);
4503
5639
  }
4504
5640
  const child = opts.resolveWorkflow?.(node.workflowId);
4505
5641
  if (child?.workspace) {
4506
- err("workspace-inherit-conflict", `"${id}": workspace:'inherit' on "${node.workflowId}", which declares its own workspace`, `${path}.workspace`, id);
5642
+ err("workspace-inherit-conflict", `"${id2}": workspace:'inherit' on "${node.workflowId}", which declares its own workspace`, `${path}.workspace`, id2);
4507
5643
  }
4508
5644
  }
4509
5645
  }, "checkWorkspace");
@@ -4512,20 +5648,20 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4512
5648
  const schema = node.type === "step" ? node.step.outputSchema : node.type === "agent" ? node.outputSchema : void 0;
4513
5649
  if (schema !== void 0) outputSchemas.set(singleId(node), schema);
4514
5650
  }, "recordOutputSchema");
4515
- const checkMapMembers = /* @__PURE__ */ __name4((cfg, basePath, id) => {
5651
+ const checkMapMembers = /* @__PURE__ */ __name4((cfg, basePath, id2) => {
4516
5652
  for (const m of malformedMapMembers(cfg)) {
4517
- warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id, m), `${basePath}.${m.member}`, id);
5653
+ warn(MAP_MEMBER_MALFORMED_CODE, mapMemberMalformedMessage(id2, m), `${basePath}.${m.member}`, id2);
4518
5654
  }
4519
5655
  }, "checkMapMembers");
4520
5656
  const checkInputShape = /* @__PURE__ */ __name4((node, path) => {
4521
5657
  const input = node.input;
4522
5658
  if (input === void 0) return;
4523
- const id = singleId(node);
5659
+ const id2 = singleId(node);
4524
5660
  if (input !== null && typeof input === "object" && !Array.isArray(input)) {
4525
- checkMapMembers(input, `${path}.input`, id);
5661
+ checkMapMembers(input, `${path}.input`, id2);
4526
5662
  return;
4527
5663
  }
4528
- err("invalid-envelope", `\`input\` must be an object map \u2014 each member a binding descriptor ({initData:true, path} | {step, path} | {value} | {template} | {requestContextPath}) or a JSON literal (got ${JSON.stringify(input)})`, `${path}.input`, id);
5664
+ err("invalid-envelope", `\`input\` must be an object map \u2014 each member a binding descriptor ({initData:true, path} | {step, path} | {value} | {template} | {requestContextPath}) or a JSON literal (got ${JSON.stringify(input)})`, `${path}.input`, id2);
4529
5665
  }, "checkInputShape");
4530
5666
  const checkBodyInput = /* @__PURE__ */ __name4((body, path, container) => {
4531
5667
  if (body.type === "workflow" || body.input === void 0) return;
@@ -4816,7 +5952,7 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
4816
5952
  default:
4817
5953
  err("invalid-envelope", `unknown entry type "${entry.type}"`, path);
4818
5954
  }
4819
- for (const id of declared) upstream.add(id);
5955
+ for (const id2 of declared) upstream.add(id2);
4820
5956
  });
4821
5957
  if (nodeCount > caps.maxNodes) {
4822
5958
  err("cap-exceeded", `${nodeCount} nodes exceeds the static cap of ${caps.maxNodes}`, "definition.graph");
@@ -4941,19 +6077,19 @@ var containerIdOf = /* @__PURE__ */ __name4((type, entryIndex) => `${type}@${ent
4941
6077
  function compilePlan(g) {
4942
6078
  const steps = {};
4943
6079
  const order = [];
4944
- const addNode = /* @__PURE__ */ __name4((id, node) => {
4945
- if (id in steps) {
4946
- throw new WorkflowPlanError("duplicate-step-id", `Duplicate step id "${id}" in definition.graph`);
6080
+ const addNode = /* @__PURE__ */ __name4((id2, node) => {
6081
+ if (id2 in steps) {
6082
+ throw new WorkflowPlanError("duplicate-step-id", `Duplicate step id "${id2}" in definition.graph`);
4947
6083
  }
4948
- steps[id] = node;
4949
- order.push(id);
6084
+ steps[id2] = node;
6085
+ order.push(id2);
4950
6086
  }, "addNode");
4951
6087
  let prevTails = [];
4952
6088
  const foreachJoinToEntry = /* @__PURE__ */ new Map();
4953
6089
  g.definition.graph.forEach((entry, entryIndex) => {
4954
6090
  if (isArmStep(entry)) {
4955
- const id = armStepId(entry);
4956
- addNode(id, {
6091
+ const id2 = armStepId(entry);
6092
+ addNode(id2, {
4957
6093
  kind: armStepKind(entry),
4958
6094
  dependsOn: prevTails,
4959
6095
  downstream: [],
@@ -4961,7 +6097,7 @@ function compilePlan(g) {
4961
6097
  entry
4962
6098
  });
4963
6099
  prevTails = [
4964
- id
6100
+ id2
4965
6101
  ];
4966
6102
  return;
4967
6103
  }
@@ -5100,10 +6236,10 @@ function compilePlan(g) {
5100
6236
  throw new WorkflowPlanError("unknown-entry-type", `Unknown graph entry type "${entry.type}" at definition.graph[${entryIndex}]`);
5101
6237
  }
5102
6238
  });
5103
- for (const id of order) {
5104
- for (const dep of steps[id].dependsOn) {
6239
+ for (const id2 of order) {
6240
+ for (const dep of steps[id2].dependsOn) {
5105
6241
  const target = steps[dep] ?? (foreachJoinToEntry.has(dep) ? steps[foreachJoinToEntry.get(dep)] : void 0);
5106
- target?.downstream.push(id);
6242
+ target?.downstream.push(id2);
5107
6243
  }
5108
6244
  }
5109
6245
  return {
@@ -5292,17 +6428,17 @@ __name(renderRef, "renderRef");
5292
6428
  __name4(renderRef, "renderRef");
5293
6429
  var stepIdOf = /* @__PURE__ */ __name4((s) => typeof s === "string" ? s : s.id, "stepIdOf");
5294
6430
  function step(s) {
5295
- const id = stepIdOf(s);
6431
+ const id2 = stepIdOf(s);
5296
6432
  return {
5297
6433
  path: /* @__PURE__ */ __name4((p) => ({
5298
- path: p === "" ? `stepResults.${id}` : `stepResults.${id}.${p}`
6434
+ path: p === "" ? `stepResults.${id2}` : `stepResults.${id2}.${p}`
5299
6435
  }), "path")
5300
6436
  };
5301
6437
  }
5302
6438
  __name(step, "step");
5303
6439
  __name4(step, "step");
5304
- function stepOf(id) {
5305
- return step(id);
6440
+ function stepOf(id2) {
6441
+ return step(id2);
5306
6442
  }
5307
6443
  __name(stepOf, "stepOf");
5308
6444
  __name4(stepOf, "stepOf");
@@ -5508,18 +6644,18 @@ function resolvePlacements(calls) {
5508
6644
  const declared = /* @__PURE__ */ new Map();
5509
6645
  const placedBy = /* @__PURE__ */ new Map();
5510
6646
  const allIds = /* @__PURE__ */ new Map();
5511
- const claimId = /* @__PURE__ */ __name4((id, callIndex) => {
5512
- const first = allIds.get(id);
6647
+ const claimId = /* @__PURE__ */ __name4((id2, callIndex) => {
6648
+ const first = allIds.get(id2);
5513
6649
  if (first !== void 0 && first !== callIndex) {
5514
6650
  issues.push({
5515
6651
  code: "duplicate-step-id",
5516
- message: `step id "${id}" is declared more than once (calls #${first} and #${callIndex})`,
6652
+ message: `step id "${id2}" is declared more than once (calls #${first} and #${callIndex})`,
5517
6653
  callIndex,
5518
- stepId: id
6654
+ stepId: id2
5519
6655
  });
5520
6656
  return;
5521
6657
  }
5522
- allIds.set(id, callIndex);
6658
+ allIds.set(id2, callIndex);
5523
6659
  }, "claimId");
5524
6660
  calls.forEach((call, i) => {
5525
6661
  switch (call.kind) {
@@ -5531,7 +6667,7 @@ function resolvePlacements(calls) {
5531
6667
  });
5532
6668
  break;
5533
6669
  case "entry":
5534
- for (const id of entryIds(call.entry)) claimId(id, i);
6670
+ for (const id2 of entryIds(call.entry)) claimId(id2, i);
5535
6671
  break;
5536
6672
  case "parallel":
5537
6673
  for (const arm of call.arms) if ("node" in arm) claimId(nodeIdOf(arm.node), i);
@@ -5550,42 +6686,42 @@ function resolvePlacements(calls) {
5550
6686
  });
5551
6687
  const armMapPlacementIssue = /* @__PURE__ */ __name4((node, ref, i, container) => {
5552
6688
  if (!ref.armMap || node.type === "mapping" || isHitlNode2(node)) return void 0;
5553
- const id = nodeIdOf(node);
6689
+ const id2 = nodeIdOf(node);
5554
6690
  if ((container === "foreach" || container === "loop") && node.type !== "workflow") {
5555
6691
  return {
5556
6692
  code: "mapping-placement",
5557
- message: container === "foreach" ? `foreach body "${id}": a [map, step] body is not supported \u2014 the body receives each item as its input; map the items before the foreach instead (foreach(step, { items: \u2026 }) or a .map() before it)` : `loop body "${id}": a [map, step] body is not supported \u2014 the body receives the previous output as its input; put the .map() before the loop instead`,
6693
+ message: container === "foreach" ? `foreach body "${id2}": a [map, step] body is not supported \u2014 the body receives each item as its input; map the items before the foreach instead (foreach(step, { items: \u2026 }) or a .map() before it)` : `loop body "${id2}": a [map, step] body is not supported \u2014 the body receives the previous output as its input; put the .map() before the loop instead`,
5558
6694
  callIndex: i,
5559
- stepId: id
6695
+ stepId: id2
5560
6696
  };
5561
6697
  }
5562
6698
  if (node.input !== void 0) {
5563
6699
  return {
5564
6700
  code: "mapping-placement",
5565
- message: `"${id}": the [map, step] arm mapping and the node's own input map would both bind its input \u2014 keep one (drop the arm map, or the \`input\` on the declaration)`,
6701
+ message: `"${id2}": the [map, step] arm mapping and the node's own input map would both bind its input \u2014 keep one (drop the arm map, or the \`input\` on the declaration)`,
5566
6702
  callIndex: i,
5567
- stepId: id
6703
+ stepId: id2
5568
6704
  };
5569
6705
  }
5570
6706
  return void 0;
5571
6707
  }, "armMapPlacementIssue");
5572
6708
  const hitlPlacementIssue = /* @__PURE__ */ __name4((node, ref, i, container) => {
5573
6709
  if (!isHitlNode2(node)) return void 0;
5574
- const id = node.id;
6710
+ const id2 = node.id;
5575
6711
  if (ref.armMap) {
5576
6712
  return {
5577
6713
  code: "node-type-unsupported-in-container",
5578
- message: workflowHitlArmShapeMessage(node.type, id, "mapped-arm"),
6714
+ message: workflowHitlArmShapeMessage(node.type, id2, "mapped-arm"),
5579
6715
  callIndex: i,
5580
- stepId: id
6716
+ stepId: id2
5581
6717
  };
5582
6718
  }
5583
6719
  if (container !== "place" && !workflowContainerRunsHitlArm(container)) {
5584
6720
  return {
5585
6721
  code: "node-type-unsupported-in-container",
5586
- message: workflowHitlArmUnsupportedMessage(node.type, id, container),
6722
+ message: workflowHitlArmUnsupportedMessage(node.type, id2, container),
5587
6723
  callIndex: i,
5588
- stepId: id
6724
+ stepId: id2
5589
6725
  };
5590
6726
  }
5591
6727
  return void 0;
@@ -5691,8 +6827,8 @@ function resolvePlacements(calls) {
5691
6827
  graph.push(call.entry);
5692
6828
  return;
5693
6829
  case "declare": {
5694
- const id = nodeIdOf(call.node);
5695
- if (placedBy.has(id)) return;
6830
+ const id2 = nodeIdOf(call.node);
6831
+ if (placedBy.has(id2)) return;
5696
6832
  graph.push(call.node);
5697
6833
  return;
5698
6834
  }
@@ -5843,14 +6979,14 @@ function seedLedgerFromRun(run, steps, targetPlan, opts = {}) {
5843
6979
  const seeded = [];
5844
6980
  const unseeded = [];
5845
6981
  const known = new Set(Object.keys(targetPlan.steps));
5846
- const parentOf = /* @__PURE__ */ __name4((id) => {
5847
- const m = /^(.*)(\[\d+\]|#\d+)$/.exec(id);
6982
+ const parentOf = /* @__PURE__ */ __name4((id2) => {
6983
+ const m = /^(.*)(\[\d+\]|#\d+)$/.exec(id2);
5848
6984
  return m ? m[1] : void 0;
5849
6985
  }, "parentOf");
5850
- const dependsOf = /* @__PURE__ */ __name4((id) => {
5851
- const node = targetPlan.steps[id];
6986
+ const dependsOf = /* @__PURE__ */ __name4((id2) => {
6987
+ const node = targetPlan.steps[id2];
5852
6988
  if (node) return node.dependsOn;
5853
- const parent = parentOf(id);
6989
+ const parent = parentOf(id2);
5854
6990
  return parent && targetPlan.steps[parent] ? [
5855
6991
  parent
5856
6992
  ] : [];
@@ -5863,23 +6999,23 @@ function seedLedgerFromRun(run, steps, targetPlan, opts = {}) {
5863
6999
  walk2.push(s.stepId);
5864
7000
  }
5865
7001
  }
5866
- for (const id of walk2) {
5867
- const row = byId.get(id);
7002
+ for (const id2 of walk2) {
7003
+ const row = byId.get(id2);
5868
7004
  if (!row || row.status !== "completed") continue;
5869
- if (!dependsOf(id).every((d) => seededIds.has(d))) {
5870
- unseeded.push(id);
7005
+ if (!dependsOf(id2).every((d) => seededIds.has(d))) {
7006
+ unseeded.push(id2);
5871
7007
  continue;
5872
7008
  }
5873
- seededIds.add(id);
7009
+ seededIds.add(id2);
5874
7010
  seeded.push({
5875
- stepId: id,
7011
+ stepId: id2,
5876
7012
  output: row.output,
5877
7013
  attempt: row.attempt ?? 1,
5878
7014
  effects: row.effects ?? {}
5879
7015
  });
5880
7016
  }
5881
7017
  const dropped = steps.filter((s) => s.status === "completed" && !known.has(s.stepId) && !(parentOf(s.stepId) && known.has(parentOf(s.stepId)))).map((s) => s.stepId);
5882
- const firstPending = targetPlan.order.find((id) => !seededIds.has(id));
7018
+ const firstPending = targetPlan.order.find((id2) => !seededIds.has(id2));
5883
7019
  const graphChanged = !!(opts.targetGraphHash && run.graphHash && opts.targetGraphHash !== run.graphHash);
5884
7020
  return {
5885
7021
  sourceRunId: run.id,
@@ -5952,37 +7088,37 @@ function replayLedger(g, ledger) {
5952
7088
  startedAt: 0,
5953
7089
  ...ledger.requestContext
5954
7090
  };
5955
- const ctxFor = /* @__PURE__ */ __name4((id) => ({
7091
+ const ctxFor = /* @__PURE__ */ __name4((id2) => ({
5956
7092
  initData: ledger.initData,
5957
- stepResults: ancestorResults(plan, id, rows22),
7093
+ stepResults: ancestorResults(plan, id2, rows22),
5958
7094
  state: ledger.state ?? {},
5959
7095
  requestContext
5960
7096
  }), "ctxFor");
5961
7097
  const verdicts = [];
5962
- for (const id of plan.order) {
5963
- const node = plan.steps[id];
5964
- const recorded = rows22.get(id);
7098
+ for (const id2 of plan.order) {
7099
+ const node = plan.steps[id2];
7100
+ const recorded = rows22.get(id2);
5965
7101
  if (!recorded || recorded.status === "pending" || recorded.status === "skipped") continue;
5966
7102
  if (node.kind === "branch") {
5967
7103
  const entry = node.entry;
5968
- const taken = selectBranchArms(branchSpecFromConditional(entry), ctxFor(id));
7104
+ const taken = selectBranchArms(branchSpecFromConditional(entry), ctxFor(id2));
5969
7105
  const recordedTaken = recorded.taken ?? inferTaken(entry, rows22);
5970
7106
  verdicts.push({
5971
- stepId: id,
7107
+ stepId: id2,
5972
7108
  kind: "branch",
5973
7109
  recorded: recordedTaken,
5974
7110
  local: taken,
5975
7111
  diverged: canonical(recordedTaken) !== canonical(taken)
5976
7112
  });
5977
- } else if (node.kind === "map" && !id.endsWith(".join") && recorded.status === "completed") {
7113
+ } else if (node.kind === "map" && !id2.endsWith(".join") && recorded.status === "completed") {
5978
7114
  const entry = node.entry;
5979
- const resolved = resolveMapping(parseMapConfig(entry.mapConfig, id), ctxFor(id));
7115
+ const resolved = resolveMapping(parseMapConfig(entry.mapConfig, id2), ctxFor(id2));
5980
7116
  const local = "error" in resolved ? {
5981
7117
  error: resolved.error,
5982
7118
  key: resolved.key
5983
7119
  } : resolved.value;
5984
7120
  verdicts.push({
5985
- stepId: id,
7121
+ stepId: id2,
5986
7122
  kind: "map",
5987
7123
  recorded: recorded.output,
5988
7124
  local,
@@ -5991,11 +7127,11 @@ function replayLedger(g, ledger) {
5991
7127
  } else if (node.kind === "foreach") {
5992
7128
  const entry = node.entry;
5993
7129
  const source = node.dependsOn[0];
5994
- const items = source ? ctxFor(id).stepResults[source] : void 0;
7130
+ const items = source ? ctxFor(id2).stepResults[source] : void 0;
5995
7131
  const local = Array.isArray(items) ? items.length : void 0;
5996
7132
  const recordedCount = recorded.itemCount ?? countChildren(entry, rows22);
5997
7133
  verdicts.push({
5998
- stepId: id,
7134
+ stepId: id2,
5999
7135
  kind: "foreach",
6000
7136
  recorded: recordedCount,
6001
7137
  local,
@@ -6004,7 +7140,7 @@ function replayLedger(g, ledger) {
6004
7140
  } else if (node.kind === "subrun" && recorded.status === "completed" && recorded.child) {
6005
7141
  const local = subrunSettledOutput(recorded.child);
6006
7142
  verdicts.push({
6007
- stepId: id,
7143
+ stepId: id2,
6008
7144
  kind: "subrun",
6009
7145
  recorded: recorded.output,
6010
7146
  local,
@@ -6020,7 +7156,7 @@ function replayLedger(g, ledger) {
6020
7156
  __name(replayLedger, "replayLedger");
6021
7157
  __name4(replayLedger, "replayLedger");
6022
7158
  var JOIN = ".join";
6023
- var entryOfJoin = /* @__PURE__ */ __name4((id) => id.endsWith(JOIN) ? id.slice(0, -JOIN.length) : void 0, "entryOfJoin");
7159
+ var entryOfJoin = /* @__PURE__ */ __name4((id2) => id2.endsWith(JOIN) ? id2.slice(0, -JOIN.length) : void 0, "entryOfJoin");
6024
7160
  function replayResultOf(row, node) {
6025
7161
  if (!row) return void 0;
6026
7162
  if (row.status === "completed") return {
@@ -6036,7 +7172,7 @@ function replayResultOf(row, node) {
6036
7172
  }
6037
7173
  __name(replayResultOf, "replayResultOf");
6038
7174
  __name4(replayResultOf, "replayResultOf");
6039
- function ancestorResults(plan, id, rows22) {
7175
+ function ancestorResults(plan, id2, rows22) {
6040
7176
  const out = {};
6041
7177
  const joinAliased = /* @__PURE__ */ new Set();
6042
7178
  const seen = /* @__PURE__ */ new Set();
@@ -6085,7 +7221,7 @@ function ancestorResults(plan, id, rows22) {
6085
7221
  walk2(node.dependsOn);
6086
7222
  }
6087
7223
  }, "walk");
6088
- walk2(plan.steps[id]?.dependsOn ?? []);
7224
+ walk2(plan.steps[id2]?.dependsOn ?? []);
6089
7225
  return out;
6090
7226
  }
6091
7227
  __name(ancestorResults, "ancestorResults");
@@ -6097,8 +7233,8 @@ function inferTaken(entry, rows22) {
6097
7233
  entry.otherwise
6098
7234
  ] : []
6099
7235
  ];
6100
- return arms.map(branchArmId).filter((id) => {
6101
- const r = rows22.get(id);
7236
+ return arms.map(branchArmId).filter((id2) => {
7237
+ const r = rows22.get(id2);
6102
7238
  return r !== void 0 && r.status !== "skipped" && r.status !== "pending";
6103
7239
  });
6104
7240
  }
@@ -6107,7 +7243,7 @@ __name4(inferTaken, "inferTaken");
6107
7243
  function countChildren(entry, rows22) {
6108
7244
  const body = branchArmId(entry.step);
6109
7245
  let n2 = 0;
6110
- for (const id of rows22.keys()) if (id.startsWith(`${body}[`)) n2 += 1;
7246
+ for (const id2 of rows22.keys()) if (id2.startsWith(`${body}[`)) n2 += 1;
6111
7247
  return n2;
6112
7248
  }
6113
7249
  __name(countChildren, "countChildren");
@@ -7553,8 +8689,8 @@ function step2(s) {
7553
8689
  return step(typeof s === "string" ? s : s.id);
7554
8690
  }
7555
8691
  __name(step2, "step");
7556
- function stepOf2(id) {
7557
- return stepOf(id);
8692
+ function stepOf2(id2) {
8693
+ return stepOf(id2);
7558
8694
  }
7559
8695
  __name(stepOf2, "stepOf");
7560
8696
  var init2 = init;
@@ -7645,16 +8781,16 @@ var assertPredicate = /* @__PURE__ */ __name((p, where) => {
7645
8781
  if (!isPredicate(p)) throw new LuaWorkflowBuildError("closure-predicate", `${where}: not a LuaPredicate`, "build predicates with eq/gt/inSet/exists/and/or/not");
7646
8782
  return p;
7647
8783
  }, "assertPredicate");
7648
- var assertRetry = /* @__PURE__ */ __name((r, id) => {
8784
+ var assertRetry = /* @__PURE__ */ __name((r, id2) => {
7649
8785
  if (!r) return;
7650
8786
  if (!isWithinWorkflowRetryAttempts(r.maxAttempts)) {
7651
8787
  const over = typeof r.maxAttempts === "number" && r.maxAttempts > WORKFLOW_RETRY_MAX_ATTEMPTS;
7652
- throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
8788
+ throw new LuaWorkflowBuildError(over ? "cap-exceeded" : "invalid-envelope", `"${id2}": ${workflowRetryMaxAttemptsMessage(r.maxAttempts)}`);
7653
8789
  }
7654
- if (r.backoff !== void 0 && !WORKFLOW_RETRY_BACKOFFS.includes(r.backoff)) throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.backoff must be ${WORKFLOW_RETRY_BACKOFFS.map((b) => `'${b}'`).join(" | ")}`);
8790
+ if (r.backoff !== void 0 && !WORKFLOW_RETRY_BACKOFFS.includes(r.backoff)) throw new LuaWorkflowBuildError("backoff-invalid", `"${id2}": retry.backoff must be ${WORKFLOW_RETRY_BACKOFFS.map((b) => `'${b}'`).join(" | ")}`);
7655
8791
  if (r.maxBackoffSeconds !== void 0) {
7656
- if (r.backoff !== "exponential") throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.maxBackoffSeconds is only meaningful with backoff:'exponential'`);
7657
- if (r.maxBackoffSeconds <= 0 || r.backoffSeconds !== void 0 && r.maxBackoffSeconds < r.backoffSeconds) throw new LuaWorkflowBuildError("backoff-invalid", `"${id}": retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds`);
8792
+ if (r.backoff !== "exponential") throw new LuaWorkflowBuildError("backoff-invalid", `"${id2}": retry.maxBackoffSeconds is only meaningful with backoff:'exponential'`);
8793
+ if (r.maxBackoffSeconds <= 0 || r.backoffSeconds !== void 0 && r.maxBackoffSeconds < r.backoffSeconds) throw new LuaWorkflowBuildError("backoff-invalid", `"${id2}": retry.maxBackoffSeconds must be > 0 and \u2265 backoffSeconds`);
7658
8794
  }
7659
8795
  }, "assertRetry");
7660
8796
  var assertTimeout = /* @__PURE__ */ __name((node) => {
@@ -7926,8 +9062,8 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
7926
9062
  ref: arm
7927
9063
  };
7928
9064
  if (arm && typeof arm === "object" && isHitlEntry(arm)) {
7929
- const id = arm.id;
7930
- throw new LuaWorkflowBuildError("invalid-step", `${where}: an approval / waitForSignal arm is placed by id \u2014 declare it with .approval(${JSON.stringify(id ?? "id")}, \u2026) / .waitForSignal(\u2026) and pass the id string`);
9065
+ const id2 = arm.id;
9066
+ throw new LuaWorkflowBuildError("invalid-step", `${where}: an approval / waitForSignal arm is placed by id \u2014 declare it with .approval(${JSON.stringify(id2 ?? "id")}, \u2026) / .waitForSignal(\u2026) and pass the id string`);
7931
9067
  }
7932
9068
  return {
7933
9069
  node: this.registerStep(arm, where)
@@ -8047,14 +9183,14 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8047
9183
  assertNoClosure(mapping, "map()");
8048
9184
  this.recordEnvRefs(mapping);
8049
9185
  this.mapCount += 1;
8050
- let id = opts?.id;
8051
- if (id === void 0) {
9186
+ let id2 = opts?.id;
9187
+ if (id2 === void 0) {
8052
9188
  this.unnamedMaps += 1;
8053
- id = `map_${this.mapCount}`;
9189
+ id2 = `map_${this.mapCount}`;
8054
9190
  }
8055
9191
  const node = {
8056
9192
  type: "mapping",
8057
- id,
9193
+ id: id2,
8058
9194
  mapConfig: canonicalJson(mapping)
8059
9195
  };
8060
9196
  return this.push({
@@ -8065,12 +9201,12 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8065
9201
  sleep(ms, opts) {
8066
9202
  if (typeof ms !== "number" || !Number.isFinite(ms) || ms < 0) throw new LuaWorkflowBuildError("invalid-envelope", "sleep(ms) takes a literal non-negative number");
8067
9203
  this.sleepCount += 1;
8068
- const id = opts?.id ?? `sleep_${this.sleepCount}`;
9204
+ const id2 = opts?.id ?? `sleep_${this.sleepCount}`;
8069
9205
  return this.push({
8070
9206
  kind: "entry",
8071
9207
  entry: defined({
8072
9208
  type: "sleep",
8073
- id,
9209
+ id: id2,
8074
9210
  duration: ms,
8075
9211
  businessHours: opts?.businessHours
8076
9212
  })
@@ -8078,13 +9214,13 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8078
9214
  }
8079
9215
  sleepUntil(iso, opts) {
8080
9216
  this.sleepCount += 1;
8081
- const id = opts?.id ?? `sleep_${this.sleepCount}`;
9217
+ const id2 = opts?.id ?? `sleep_${this.sleepCount}`;
8082
9218
  if (typeof iso === "string") {
8083
9219
  return this.push({
8084
9220
  kind: "entry",
8085
9221
  entry: defined({
8086
9222
  type: "sleepUntil",
8087
- id,
9223
+ id: id2,
8088
9224
  date: iso,
8089
9225
  businessHours: opts?.businessHours,
8090
9226
  round: opts?.round
@@ -8097,7 +9233,7 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8097
9233
  kind: "entry",
8098
9234
  entry: {
8099
9235
  type: "mapping",
8100
- id: `${id}_at`,
9236
+ id: `${id2}_at`,
8101
9237
  mapConfig: canonicalJson({
8102
9238
  date: {
8103
9239
  template: iso.template
@@ -8109,9 +9245,9 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8109
9245
  kind: "entry",
8110
9246
  entry: defined({
8111
9247
  type: "sleepUntil",
8112
- id,
9248
+ id: id2,
8113
9249
  dateFrom: {
8114
- step: `${id}_at`,
9250
+ step: `${id2}_at`,
8115
9251
  path: "date"
8116
9252
  },
8117
9253
  businessHours: opts?.businessHours,
@@ -8119,35 +9255,35 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8119
9255
  })
8120
9256
  });
8121
9257
  }
8122
- agentStep(id, opts) {
8123
- this.assertId(id, "agentStep()");
9258
+ agentStep(id2, opts) {
9259
+ this.assertId(id2, "agentStep()");
8124
9260
  if (!opts || typeof opts.agentId !== "string" && !(opts.agentId && typeof opts.agentId === "object" && "__envRef" in opts.agentId)) {
8125
- throw new LuaWorkflowBuildError("invalid-envelope", `agentStep("${id}") needs an agentId`);
9261
+ throw new LuaWorkflowBuildError("invalid-envelope", `agentStep("${id2}") needs an agentId`);
8126
9262
  }
8127
9263
  const tier = opts.tier ?? (opts.workspace ? "job" : void 0);
8128
- if (opts.workspace && opts.tier !== void 0 && opts.tier !== "job") throw new LuaWorkflowBuildError("workspace-requires-job-tier", `"${id}": a step mounting a workspace must be tier:'job'`);
8129
- if (opts.harness !== void 0 && tier !== "job") throw new LuaWorkflowBuildError("harness-requires-job-tier", `"${id}": harness is only legal on a tier:'job' agent step`);
8130
- if (opts.toolScope?.jobTools && tier !== "job") throw new LuaWorkflowBuildError("cap-exceeded", `"${id}": toolScope.jobTools require tier:'job' (job-tools-require-job-tier)`);
9264
+ if (opts.workspace && opts.tier !== void 0 && opts.tier !== "job") throw new LuaWorkflowBuildError("workspace-requires-job-tier", `"${id2}": a step mounting a workspace must be tier:'job'`);
9265
+ if (opts.harness !== void 0 && tier !== "job") throw new LuaWorkflowBuildError("harness-requires-job-tier", `"${id2}": harness is only legal on a tier:'job' agent step`);
9266
+ if (opts.toolScope?.jobTools && tier !== "job") throw new LuaWorkflowBuildError("cap-exceeded", `"${id2}": toolScope.jobTools require tier:'job' (job-tools-require-job-tier)`);
8131
9267
  for (const m of WORKFLOW_JOB_RANGE_MEMBERS) {
8132
9268
  if (opts[m] === void 0) continue;
8133
- if (tier !== "job") throw new LuaWorkflowBuildError("max-turns-requires-job-tier", `"${id}": ${m} is only legal on a tier:'job' agent step`);
9269
+ if (tier !== "job") throw new LuaWorkflowBuildError("max-turns-requires-job-tier", `"${id2}": ${m} is only legal on a tier:'job' agent step`);
8134
9270
  if (!isWithinWorkflowJobRange(m, opts[m])) {
8135
9271
  const { min, max } = WORKFLOW_JOB_RANGES[m];
8136
- throw new LuaWorkflowBuildError("max-turns-invalid", `"${id}": ${m} must be an integer ${min}..${max}`);
9272
+ throw new LuaWorkflowBuildError("max-turns-invalid", `"${id2}": ${m} must be an integer ${min}..${max}`);
8137
9273
  }
8138
9274
  }
8139
9275
  assertTimeout({
8140
- id,
9276
+ id: id2,
8141
9277
  timeoutSeconds: opts.timeoutSeconds,
8142
9278
  tier,
8143
9279
  workspace: opts.workspace,
8144
9280
  kind: "agent"
8145
9281
  });
8146
- assertRetry(opts.retry, id);
9282
+ assertRetry(opts.retry, id2);
8147
9283
  this.recordEnvRefs(opts.agentId, opts.prompt);
8148
9284
  const node = defined({
8149
9285
  type: "agent",
8150
- id,
9286
+ id: id2,
8151
9287
  agentId: opts.agentId,
8152
9288
  promptTemplate: templateText(opts.prompt),
8153
9289
  outputSchema: schemaToJson(opts.outputSchema),
@@ -8175,30 +9311,30 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8175
9311
  node
8176
9312
  });
8177
9313
  }
8178
- specialistStep(id, opts) {
8179
- this.assertId(id, "specialistStep()");
9314
+ specialistStep(id2, opts) {
9315
+ this.assertId(id2, "specialistStep()");
8180
9316
  const role = opts?.role;
8181
- if (!role || typeof role !== "object") throw new LuaWorkflowBuildError("invalid-envelope", `specialistStep("${id}") needs a role`);
9317
+ if (!role || typeof role !== "object") throw new LuaWorkflowBuildError("invalid-envelope", `specialistStep("${id2}") needs a role`);
8182
9318
  if (role.ref !== void 0 && (role.name !== void 0 || role.instructions !== void 0 || role.tools !== void 0)) {
8183
- throw new LuaWorkflowBuildError("role-ref-and-inline", `"${id}": role is EITHER { ref } OR the inline { name, instructions, tools } shape`);
9319
+ throw new LuaWorkflowBuildError("role-ref-and-inline", `"${id2}": role is EITHER { ref } OR the inline { name, instructions, tools } shape`);
8184
9320
  }
8185
9321
  if (role.ref === void 0) {
8186
9322
  if (typeof role.instructions !== "string" || role.instructions.length > WORKFLOW_SPECIALIST_ROLE_MAX_INSTRUCTIONS) {
8187
- throw new LuaWorkflowBuildError("ephemeral-role-too-long", `"${id}": role.instructions must be \u2264 ${WORKFLOW_SPECIALIST_ROLE_MAX_INSTRUCTIONS} chars`);
9323
+ throw new LuaWorkflowBuildError("ephemeral-role-too-long", `"${id2}": role.instructions must be \u2264 ${WORKFLOW_SPECIALIST_ROLE_MAX_INSTRUCTIONS} chars`);
8188
9324
  }
8189
- if (!Array.isArray(role.tools)) throw new LuaWorkflowBuildError("invalid-envelope", `"${id}": role.tools must be an array ([] = no tools)`);
8190
- if (role.tools.length > 64) throw new LuaWorkflowBuildError("cap-exceeded", `"${id}": role.tools exceeds 64 entries`);
9325
+ if (!Array.isArray(role.tools)) throw new LuaWorkflowBuildError("invalid-envelope", `"${id2}": role.tools must be an array ([] = no tools)`);
9326
+ if (role.tools.length > 64) throw new LuaWorkflowBuildError("cap-exceeded", `"${id2}": role.tools exceeds 64 entries`);
8191
9327
  }
8192
9328
  assertTimeout({
8193
- id,
9329
+ id: id2,
8194
9330
  timeoutSeconds: opts.timeoutSeconds,
8195
9331
  kind: "agent"
8196
9332
  });
8197
- assertRetry(opts.retry, id);
9333
+ assertRetry(opts.retry, id2);
8198
9334
  this.recordEnvRefs(opts.prompt);
8199
9335
  const node = defined({
8200
9336
  type: "agent",
8201
- id,
9337
+ id: id2,
8202
9338
  agentId: "$self",
8203
9339
  role: role.ref !== void 0 ? {
8204
9340
  ref: role.ref
@@ -8221,20 +9357,20 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8221
9357
  node
8222
9358
  });
8223
9359
  }
8224
- toolStep(id, tool, opts = {}) {
8225
- this.assertId(id, "toolStep()");
8226
- if (!tool || typeof tool !== "object" || typeof tool.name !== "string") throw new LuaWorkflowBuildError("invalid-envelope", `toolStep("${id}") needs a LuaTool`);
8227
- assertNoClosure(opts.input, `toolStep("${id}").input`);
9360
+ toolStep(id2, tool, opts = {}) {
9361
+ this.assertId(id2, "toolStep()");
9362
+ if (!tool || typeof tool !== "object" || typeof tool.name !== "string") throw new LuaWorkflowBuildError("invalid-envelope", `toolStep("${id2}") needs a LuaTool`);
9363
+ assertNoClosure(opts.input, `toolStep("${id2}").input`);
8228
9364
  this.recordEnvRefs(opts.input);
8229
9365
  assertTimeout({
8230
- id,
9366
+ id: id2,
8231
9367
  timeoutSeconds: opts.timeoutSeconds,
8232
9368
  kind: "tool"
8233
9369
  });
8234
- assertRetry(opts.retry, id);
9370
+ assertRetry(opts.retry, id2);
8235
9371
  const node = defined({
8236
9372
  type: "tool",
8237
- id,
9373
+ id: id2,
8238
9374
  toolId: tool.name,
8239
9375
  input: opts.input,
8240
9376
  timeoutSeconds: opts.timeoutSeconds,
@@ -8248,34 +9384,34 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8248
9384
  node
8249
9385
  });
8250
9386
  }
8251
- approval(id, opts) {
8252
- this.assertId(id, "approval()");
8253
- if (!opts || typeof opts.title !== "string") throw new LuaWorkflowBuildError("invalid-envelope", `approval("${id}") needs a title`);
9387
+ approval(id2, opts) {
9388
+ this.assertId(id2, "approval()");
9389
+ if (!opts || typeof opts.title !== "string") throw new LuaWorkflowBuildError("invalid-envelope", `approval("${id2}") needs a title`);
8254
9390
  if (opts.approver === "creator" && opts.excludeInitiator === true) {
8255
- throw new LuaWorkflowBuildError("approver-excludes-only-candidate", `"${id}": approver:'creator' with excludeInitiator:true always excludes the only candidate`);
9391
+ throw new LuaWorkflowBuildError("approver-excludes-only-candidate", `"${id2}": approver:'creator' with excludeInitiator:true always excludes the only candidate`);
8256
9392
  }
8257
9393
  const editable = approvalEditable(opts);
8258
- if (opts.fourEyes !== void 0 && !editable) throw new LuaWorkflowBuildError("four-eyes-requires-editable", `"${id}": \`fourEyes\` requires editable:true`);
9394
+ if (opts.fourEyes !== void 0 && !editable) throw new LuaWorkflowBuildError("four-eyes-requires-editable", `"${id2}": \`fourEyes\` requires editable:true`);
8259
9395
  if (opts.editable === false && Array.isArray(opts.editablePaths) && opts.editablePaths.length > 0) {
8260
- throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": \`editablePaths\` beside editable:false is contradictory \u2014 drop the paths or set editable:true`);
9396
+ throw new LuaWorkflowBuildError("editable-path-invalid", `"${id2}": \`editablePaths\` beside editable:false is contradictory \u2014 drop the paths or set editable:true`);
8261
9397
  } else if ((opts.editablePaths !== void 0 || opts.editedPayloadSchema !== void 0) && !editable) {
8262
- throw new LuaWorkflowBuildError("editable-path-invalid", `"${id}": \`editablePaths\` / \`editedPayloadSchema\` require editable:true (a non-empty editablePaths implies it)`);
9398
+ throw new LuaWorkflowBuildError("editable-path-invalid", `"${id2}": \`editablePaths\` / \`editedPayloadSchema\` require editable:true (a non-empty editablePaths implies it)`);
8263
9399
  }
8264
9400
  for (const p of opts.editablePaths ?? []) {
8265
- 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`);
9401
+ if (!EDITABLE_PATH_RE2.test(p)) throw new LuaWorkflowBuildError("editable-path-invalid", `"${id2}": editablePaths entry "${p}" is outside the grammar seg(.seg)* with [*]/[n] selectors`);
8266
9402
  }
8267
9403
  if (Array.isArray(opts.onTimeout)) {
8268
9404
  const chain = opts.onTimeout;
8269
9405
  const hops = chain.filter((h) => typeof h === "object");
8270
- if (hops.length > 3) throw new LuaWorkflowBuildError("escalation-chain-too-long", `"${id}": an onTimeout chain carries at most 3 escalation hops`);
9406
+ if (hops.length > 3) throw new LuaWorkflowBuildError("escalation-chain-too-long", `"${id2}": an onTimeout chain carries at most 3 escalation hops`);
8271
9407
  const last = chain[chain.length - 1];
8272
- if (last === void 0 || typeof last === "object") throw new LuaWorkflowBuildError("escalation-chain-not-terminal", `"${id}": an onTimeout chain must end in a terminal member`);
9408
+ if (last === void 0 || typeof last === "object") throw new LuaWorkflowBuildError("escalation-chain-not-terminal", `"${id2}": an onTimeout chain must end in a terminal member`);
8273
9409
  }
8274
- if (typeof opts.details === "function") throw new LuaWorkflowBuildError("closure-binding", `approval("${id}").details must be template(...)`);
9410
+ if (typeof opts.details === "function") throw new LuaWorkflowBuildError("closure-binding", `approval("${id2}").details must be template(...)`);
8275
9411
  this.recordEnvRefs(opts.details, opts.timeoutHours, opts.approver);
8276
9412
  const node = defined({
8277
9413
  type: "approval",
8278
- id,
9414
+ id: id2,
8279
9415
  title: opts.title,
8280
9416
  details: opts.details ? templateText(opts.details) : void 0,
8281
9417
  approver: opts.approver,
@@ -8297,13 +9433,13 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8297
9433
  node
8298
9434
  });
8299
9435
  }
8300
- waitForSignal(id, opts) {
8301
- this.assertId(id, "waitForSignal()");
8302
- if (!opts || typeof opts.signal !== "string" || opts.signal.length === 0) throw new LuaWorkflowBuildError("invalid-envelope", `waitForSignal("${id}") needs a signal name`);
9436
+ waitForSignal(id2, opts) {
9437
+ this.assertId(id2, "waitForSignal()");
9438
+ if (!opts || typeof opts.signal !== "string" || opts.signal.length === 0) throw new LuaWorkflowBuildError("invalid-envelope", `waitForSignal("${id2}") needs a signal name`);
8303
9439
  this.recordEnvRefs(opts.timeoutHours);
8304
9440
  const node = defined({
8305
9441
  type: "waitForSignal",
8306
- id,
9442
+ id: id2,
8307
9443
  signal: opts.signal,
8308
9444
  schema: schemaToJson(opts.schema),
8309
9445
  timeoutHours: opts.timeoutHours,
@@ -8316,28 +9452,28 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8316
9452
  node
8317
9453
  });
8318
9454
  }
8319
- workflow(id, ref, input, opts) {
8320
- this.assertId(id, "workflow()");
8321
- assertRetry(opts?.retry, id);
9455
+ workflow(id2, ref, input, opts) {
9456
+ this.assertId(id2, "workflow()");
9457
+ assertRetry(opts?.retry, id2);
8322
9458
  const name = typeof ref === "string" ? ref : ref instanceof LuaWorkflow ? ref.getName() : void 0;
8323
- if (!name) throw new LuaWorkflowBuildError("invalid-envelope", `workflow("${id}") needs a LuaWorkflow or a workflow name`);
9459
+ if (!name) throw new LuaWorkflowBuildError("invalid-envelope", `workflow("${id2}") needs a LuaWorkflow or a workflow name`);
8324
9460
  if (opts?.workspace === "inherit") {
8325
- if (!this.config.workspace) throw new LuaWorkflowBuildError("workspace-inherit-without-parent-workspace", `"${id}": workspace:'inherit' but the parent createWorkflow declares no workspace`);
8326
- if (ref instanceof LuaWorkflow && ref.getConfig().workspace) throw new LuaWorkflowBuildError("workspace-inherit-conflict", `"${id}": workspace:'inherit' on a workflow that declares its own workspace`);
9461
+ if (!this.config.workspace) throw new LuaWorkflowBuildError("workspace-inherit-without-parent-workspace", `"${id2}": workspace:'inherit' but the parent createWorkflow declares no workspace`);
9462
+ if (ref instanceof LuaWorkflow && ref.getConfig().workspace) throw new LuaWorkflowBuildError("workspace-inherit-conflict", `"${id2}": workspace:'inherit' on a workflow that declares its own workspace`);
8327
9463
  }
8328
- assertNoClosure(input, `workflow("${id}").input`);
9464
+ assertNoClosure(input, `workflow("${id2}").input`);
8329
9465
  this.recordEnvRefs(input);
8330
9466
  this.nestedRefs.push(opts?.workspace === "inherit" ? {
8331
- id,
9467
+ id: id2,
8332
9468
  name,
8333
9469
  workspace: "inherit"
8334
9470
  } : {
8335
- id,
9471
+ id: id2,
8336
9472
  name
8337
9473
  });
8338
9474
  const node = defined({
8339
9475
  type: "workflow",
8340
- id,
9476
+ id: id2,
8341
9477
  workflowId: name,
8342
9478
  input,
8343
9479
  workspace: opts?.workspace,
@@ -8416,8 +9552,8 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
8416
9552
  });
8417
9553
  }
8418
9554
  }
8419
- assertId(id, where) {
8420
- if (typeof id !== "string" || !STEP_ID_RE.test(id)) throw new LuaWorkflowBuildError("invalid-step-id", `${where}: id "${String(id)}" must match ${STEP_ID_RE}`);
9555
+ assertId(id2, where) {
9556
+ if (typeof id2 !== "string" || !STEP_ID_RE.test(id2)) throw new LuaWorkflowBuildError("invalid-step-id", `${where}: id "${String(id2)}" must match ${STEP_ID_RE}`);
8421
9557
  }
8422
9558
  };
8423
9559
  var EDITABLE_PATH_RE2 = /^[A-Za-z_][A-Za-z0-9_]*(\[(\*|\d+)\])?(\.[A-Za-z_][A-Za-z0-9_]*(\[(\*|\d+)\])?)*$/;