openmates 0.27.0-alpha.20 → 0.27.0-alpha.22

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.
@@ -194,8 +194,8 @@ import { chmodSync, closeSync, fsyncSync, mkdirSync, openSync, readFileSync, ren
194
194
  import { join } from "path";
195
195
  var digest = (value) => createHash("sha256").update(value).digest("hex");
196
196
  var shortenTaskText = (value, length) => {
197
- const text5 = value.replace(/\s+/g, " ").trim();
198
- return text5.length <= length ? text5 : `${text5.slice(0, length - 1)}\u2026`;
197
+ const text6 = value.replace(/\s+/g, " ").trim();
198
+ return text6.length <= length ? text6 : `${text6.slice(0, length - 1)}\u2026`;
199
199
  };
200
200
  function atomicPrivateFile(path2, content) {
201
201
  const temporary = `${path2}.${randomUUID()}.tmp`;
@@ -403,7 +403,7 @@ async function lockTaskDeliveryRecord(directory, id) {
403
403
  }
404
404
 
405
405
  // src/taskMutationDelivery.ts
406
- var digest2 = (text5) => createHash3("sha256").update(text5).digest("hex");
406
+ var digest2 = (text6) => createHash3("sha256").update(text6).digest("hex");
407
407
  var stable = (value) => JSON.stringify(value, (_key, item) => item && !Array.isArray(item) && typeof item === "object" ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b))) : item);
408
408
  function reconcileMutation(mutation, current) {
409
409
  if (mutation.kind === "delete") {
@@ -576,9 +576,9 @@ function collectGeneratedFiles(value) {
576
576
  const filename = suppliedName ? safeName(suppliedName) : `openmates-${safeName(assetId ?? "generated")}.${extension}`;
577
577
  files.push({ url, filename, assetId });
578
578
  };
579
- const visit = (node) => {
579
+ const visit2 = (node) => {
580
580
  if (Array.isArray(node)) {
581
- node.forEach(visit);
581
+ node.forEach(visit2);
582
582
  return;
583
583
  }
584
584
  const data = record(node);
@@ -596,9 +596,9 @@ function collectGeneratedFiles(value) {
596
596
  if (meta && text(meta.download_url)) add(meta, data, text(meta.variant) ?? "original");
597
597
  }
598
598
  }
599
- for (const field of RESULT_FIELDS) if (data[field] !== void 0) visit(data[field]);
599
+ for (const field of RESULT_FIELDS) if (data[field] !== void 0) visit2(data[field]);
600
600
  };
601
- visit(value);
601
+ visit2(value);
602
602
  return files;
603
603
  }
604
604
  function fetchGeneratedFile(url) {
@@ -766,10 +766,10 @@ function assertCodexClaimCaller(threadId, currentThread = process.env.CODEX_THRE
766
766
  }
767
767
 
768
768
  // ../secret-scanner/src/identifierRanges.ts
769
- function codingIdentifierRanges(text5) {
769
+ function codingIdentifierRanges(text6) {
770
770
  const ranges = [];
771
771
  const identifiers2 = /\b[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\b|\b[\da-f]{40,64}\b|\[[A-Z][A-Z\d_]*\]/gi;
772
- for (const match of Array.from(text5.matchAll(identifiers2))) {
772
+ for (const match of Array.from(text6.matchAll(identifiers2))) {
773
773
  ranges.push({ start: match.index, end: match.index + match[0].length });
774
774
  }
775
775
  return ranges;
@@ -1247,16 +1247,16 @@ var PII_TYPE_TO_CATEGORY = {
1247
1247
  USER_AT_HOSTNAME: "user_at_hostname",
1248
1248
  MAC_ADDRESS: "mac_addresses"
1249
1249
  };
1250
- function detectPII(text5, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
1250
+ function detectPII(text6, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
1251
1251
  const options = excludedIdsOrOptions instanceof Set ? { excludedIds: excludedIdsOrOptions } : excludedIdsOrOptions;
1252
1252
  const excludedIds = options.excludedIds ?? /* @__PURE__ */ new Set();
1253
1253
  const disabledCategories = options.disabledCategories ?? /* @__PURE__ */ new Set();
1254
1254
  const personalEntries = options.personalDataEntries ?? [];
1255
- if (!text5 || text5.length < MIN_PII_TEXT_LENGTH && personalEntries.length === 0)
1255
+ if (!text6 || text6.length < MIN_PII_TEXT_LENGTH && personalEntries.length === 0)
1256
1256
  return [];
1257
1257
  const matches2 = [];
1258
1258
  const coveredRanges = [];
1259
- const identifierRanges = codingIdentifierRanges(text5);
1259
+ const identifierRanges = codingIdentifierRanges(text6);
1260
1260
  const typeCounts = {};
1261
1261
  const hasExclusions = excludedIds.size > 0;
1262
1262
  const hasDisabledCategories = disabledCategories.size > 0;
@@ -1264,14 +1264,14 @@ function detectPII(text5, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
1264
1264
  const urlExclusionZones = [];
1265
1265
  URL_EXCLUSION_REGEX.lastIndex = 0;
1266
1266
  let urlMatch;
1267
- while ((urlMatch = URL_EXCLUSION_REGEX.exec(text5)) !== null) {
1267
+ while ((urlMatch = URL_EXCLUSION_REGEX.exec(text6)) !== null) {
1268
1268
  urlExclusionZones.push({
1269
1269
  start: urlMatch.index,
1270
1270
  end: urlMatch.index + urlMatch[0].length
1271
1271
  });
1272
1272
  }
1273
1273
  const hasUrlExclusions = urlExclusionZones.length > 0;
1274
- if (text5.length >= MIN_PII_TEXT_LENGTH) {
1274
+ if (text6.length >= MIN_PII_TEXT_LENGTH) {
1275
1275
  for (const pattern of PII_PATTERNS) {
1276
1276
  if (hasDisabledCategories) {
1277
1277
  const category = PII_TYPE_TO_CATEGORY[pattern.type];
@@ -1279,7 +1279,7 @@ function detectPII(text5, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
1279
1279
  }
1280
1280
  pattern.regex.lastIndex = 0;
1281
1281
  let regexMatch;
1282
- while ((regexMatch = pattern.regex.exec(text5)) !== null) {
1282
+ while ((regexMatch = pattern.regex.exec(text6)) !== null) {
1283
1283
  const matchText = regexMatch[0];
1284
1284
  const startIndex = regexMatch.index;
1285
1285
  const endIndex = startIndex + matchText.length;
@@ -1325,7 +1325,7 @@ function detectPII(text5, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
1325
1325
  }
1326
1326
  }
1327
1327
  for (const searchText of textsToSearch) {
1328
- const lowerText = text5.toLowerCase();
1328
+ const lowerText = text6.toLowerCase();
1329
1329
  const lowerSearch = searchText.toLowerCase();
1330
1330
  let searchFrom = 0;
1331
1331
  while (searchFrom < lowerText.length) {
@@ -1337,7 +1337,7 @@ function detectPII(text5, excludedIdsOrOptions = /* @__PURE__ */ new Set()) {
1337
1337
  (range) => startIndex >= range.start && startIndex < range.end || endIndex > range.start && endIndex <= range.end || startIndex <= range.start && endIndex >= range.end
1338
1338
  );
1339
1339
  if (!overlaps) {
1340
- const matchText = text5.substring(startIndex, endIndex);
1340
+ const matchText = text6.substring(startIndex, endIndex);
1341
1341
  const matchId = `pii-PERSONAL_DATA-${entry.id}-${startIndex}`;
1342
1342
  if (!hasExclusions || !excludedIds.has(matchId)) {
1343
1343
  const placeholder = entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`;
@@ -1438,8 +1438,8 @@ var ProjectFilePrivacy = class {
1438
1438
  }
1439
1439
  if (this.values.size + this.conflicts.length > 1e4) fail("pii_mapping_limit");
1440
1440
  }
1441
- restoreText(text5) {
1442
- return text5.replace(TOKEN, (token) => {
1441
+ restoreText(text6) {
1442
+ return text6.replace(TOKEN, (token) => {
1443
1443
  if (this.ambiguous.has(token)) fail("pii_mapping_ambiguous");
1444
1444
  const mapping = this.values.get(token);
1445
1445
  const customToken = this.options.detection?.personalDataEntries?.some((entry) => (entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`) === token);
@@ -1477,28 +1477,28 @@ var ProjectFilePrivacy = class {
1477
1477
  this.addMappings([{ placeholder, original, type }]);
1478
1478
  return placeholder;
1479
1479
  }
1480
- redactText(text5, enhanced = []) {
1480
+ redactText(text6, enhanced = []) {
1481
1481
  const ranges = [];
1482
- const tokens = Array.from(text5.matchAll(TOKEN)).map((match) => ({ start: match.index, end: match.index + match[0].length }));
1482
+ const tokens = Array.from(text6.matchAll(TOKEN)).map((match) => ({ start: match.index, end: match.index + match[0].length }));
1483
1483
  for (const range of tokens) {
1484
- const literal = text5.slice(range.start, range.end);
1484
+ const literal = text6.slice(range.start, range.end);
1485
1485
  if (!(this.options.preserveMappedTokens && this.values.has(literal)) && (this.values.has(literal) || GENERATED_TOKEN.test(literal) || legacyToken(literal))) ranges.push(range);
1486
1486
  }
1487
1487
  const overlaps = (start, end) => [...tokens, ...ranges].some((r) => start < r.end && end > r.start);
1488
1488
  for (const mapping of Array.from(this.values.values()).sort((a, b) => b.original.length - a.original.length)) {
1489
- let start = text5.indexOf(mapping.original);
1489
+ let start = text6.indexOf(mapping.original);
1490
1490
  while (start !== -1) {
1491
1491
  const end = start + mapping.original.length;
1492
1492
  if (!overlaps(start, end)) ranges.push({ start, end, type: mapping.type });
1493
- start = text5.indexOf(mapping.original, end);
1493
+ start = text6.indexOf(mapping.original, end);
1494
1494
  }
1495
1495
  }
1496
1496
  if (this.options.enabled !== false) {
1497
- for (const match of detectPII(text5, this.options.detection)) {
1497
+ for (const match of detectPII(text6, this.options.detection)) {
1498
1498
  if (!overlaps(match.startIndex, match.endIndex)) ranges.push({ start: match.startIndex, end: match.endIndex, type: match.type });
1499
1499
  }
1500
1500
  for (const range of enhanced) {
1501
- if (!Number.isInteger(range.start) || !Number.isInteger(range.end) || range.start < 0 || range.end <= range.start || range.end > text5.length) fail("pii_invalid_semantic_range");
1501
+ if (!Number.isInteger(range.start) || !Number.isInteger(range.end) || range.start < 0 || range.end <= range.start || range.end > text6.length) fail("pii_invalid_semantic_range");
1502
1502
  let fragments = [{ ...range }];
1503
1503
  for (const shield of [...tokens, ...ranges]) fragments = fragments.flatMap((part) => {
1504
1504
  if (part.start >= shield.end || part.end <= shield.start) return [part];
@@ -1513,30 +1513,30 @@ var ProjectFilePrivacy = class {
1513
1513
  let cursor = 0;
1514
1514
  let result = "";
1515
1515
  for (const range of ranges.sort((a, b) => a.start - b.start)) {
1516
- result += text5.slice(cursor, range.start);
1517
- result += text5.slice(range.start, range.end).split(/(\r?\n)/).map((part) => !part || /^(?:\r?\n)$/.test(part) ? part : this.token(part, range.type)).join("");
1516
+ result += text6.slice(cursor, range.start);
1517
+ result += text6.slice(range.start, range.end).split(/(\r?\n)/).map((part) => !part || /^(?:\r?\n)$/.test(part) ? part : this.token(part, range.type)).join("");
1518
1518
  cursor = range.end;
1519
1519
  }
1520
- return result + text5.slice(cursor);
1520
+ return result + text6.slice(cursor);
1521
1521
  }
1522
1522
  async redactResult(value) {
1523
- const visit = async (item) => {
1523
+ const visit2 = async (item) => {
1524
1524
  if (typeof item === "string") return this.redactText(item, this.options.enabled !== false && this.options.detectEnhanced ? await this.options.detectEnhanced(item) : []);
1525
1525
  if (Array.isArray(item)) {
1526
1526
  const result2 = [];
1527
- for (const child of item) result2.push(await visit(child));
1527
+ for (const child of item) result2.push(await visit2(child));
1528
1528
  return result2;
1529
1529
  }
1530
1530
  if (item && typeof item === "object") {
1531
1531
  const result2 = {};
1532
1532
  for (const [key, child] of Object.entries(item)) {
1533
- result2[key] = ["expected_base", "content_hash", "proposal_commitment"].includes(key) ? child : await visit(child);
1533
+ result2[key] = ["expected_base", "content_hash", "proposal_commitment"].includes(key) ? child : await visit2(child);
1534
1534
  }
1535
1535
  return result2;
1536
1536
  }
1537
1537
  return item;
1538
1538
  };
1539
- const result = await visit(value);
1539
+ const result = await visit2(value);
1540
1540
  const save = this.savePending.catch(() => {
1541
1541
  }).then(() => this.options.save([...Array.from(this.values.values()), ...this.conflicts]));
1542
1542
  this.savePending = save;
@@ -1556,26 +1556,26 @@ var LABELS = {
1556
1556
  private_date: { type: "OTHER", category: "birthdays" },
1557
1557
  private_url: { type: "OTHER", category: "private_urls" }
1558
1558
  };
1559
- function convertNativePrivacyRanges(text5, spans, disabled = /* @__PURE__ */ new Set()) {
1559
+ function convertNativePrivacyRanges(text6, spans, disabled = /* @__PURE__ */ new Set()) {
1560
1560
  const offsets = /* @__PURE__ */ new Map([[0, 0]]);
1561
1561
  let bytes2 = 0;
1562
1562
  let units = 0;
1563
- for (const character of text5) {
1563
+ for (const character of text6) {
1564
1564
  if (character.length === 1 && /[\uD800-\uDFFF]/.test(character)) throw privacyError("privacy_invalid_unicode");
1565
1565
  bytes2 += Buffer.byteLength(character);
1566
1566
  units += character.length;
1567
1567
  offsets.set(bytes2, units);
1568
1568
  }
1569
- const protectedRanges = codingIdentifierRanges(text5);
1569
+ const protectedRanges = codingIdentifierRanges(text6);
1570
1570
  const result = [];
1571
1571
  for (const span of spans) {
1572
1572
  const label3 = LABELS[span.label];
1573
1573
  const start = offsets.get(span.start), end = offsets.get(span.end);
1574
1574
  if (!label3 || !Number.isInteger(span.start) || !Number.isInteger(span.end) || start === void 0 || end === void 0 || end <= start) throw privacyError("privacy_invalid_semantic_range");
1575
1575
  if (disabled.has(label3.category) || span.label === "secret" && disabled.has("api_keys")) continue;
1576
- const context = text5.slice(Math.max(0, start - 60), Math.min(text5.length, end + 60));
1576
+ const context = text6.slice(Math.max(0, start - 60), Math.min(text6.length, end + 60));
1577
1577
  const explicitSecret = /\b(?:password|secret|credential|api[_ -]?key|token)\b/i.test(context);
1578
- if (protectedRanges.some((r) => start < r.end && end > r.start) && !(span.label === "secret" && explicitSecret && !text5.slice(start, end).startsWith("["))) continue;
1578
+ if (protectedRanges.some((r) => start < r.end && end > r.start) && !(span.label === "secret" && explicitSecret && !text6.slice(start, end).startsWith("["))) continue;
1579
1579
  if ((span.label === "private_date" || span.label === "account_number") && /\b(?:commit|sha|hash|build|release|branch|timestamp|version)\b/i.test(context) && !/\b(?:birth|birthday|born|dob|account|iban)\b/i.test(context)) continue;
1580
1580
  result.push({ start, end, type: label3.type });
1581
1581
  }
@@ -1591,30 +1591,30 @@ function privacyDetectionOptions(memories) {
1591
1591
  })
1592
1592
  } };
1593
1593
  }
1594
- async function scanEnhancedText(text5, scope2, disabled = /* @__PURE__ */ new Set(), progress) {
1594
+ async function scanEnhancedText(text6, scope2, disabled = /* @__PURE__ */ new Set(), progress) {
1595
1595
  const preferences = await readPrivacyPreferences();
1596
- if (!text5 || !enhancedScopeEnabled(preferences, scope2)) return [];
1596
+ if (!text6 || !enhancedScopeEnabled(preferences, scope2)) return [];
1597
1597
  try {
1598
1598
  await ensurePrivacyDaemon();
1599
1599
  const ranges = [];
1600
- for (let start = 0; start < text5.length; start += 8192) {
1601
- let from = Math.max(0, start - 1024), end = Math.min(text5.length, start + 9216);
1602
- if (from > 0 && /[\uDC00-\uDFFF]/.test(text5[from])) from--;
1603
- if (end < text5.length && /[\uDC00-\uDFFF]/.test(text5[end])) end++;
1604
- progress?.(start, text5.length);
1605
- const window = text5.slice(from, end);
1600
+ for (let start = 0; start < text6.length; start += 8192) {
1601
+ let from = Math.max(0, start - 1024), end = Math.min(text6.length, start + 9216);
1602
+ if (from > 0 && /[\uDC00-\uDFFF]/.test(text6[from])) from--;
1603
+ if (end < text6.length && /[\uDC00-\uDFFF]/.test(text6[end])) end++;
1604
+ progress?.(start, text6.length);
1605
+ const window = text6.slice(from, end);
1606
1606
  const result = await privacyRpc({ op: "scan", text: window, scope: privacyProfile(), idleSeconds: preferences.idleSeconds });
1607
1607
  if (!Array.isArray(result.spans)) throw privacyError("privacy_worker_protocol_failed");
1608
1608
  ranges.push(...convertNativePrivacyRanges(window, result.spans, disabled).map((r) => ({ ...r, start: r.start + from, end: r.end + from })));
1609
1609
  }
1610
- progress?.(text5.length, text5.length);
1610
+ progress?.(text6.length, text6.length);
1611
1611
  return ranges;
1612
1612
  } catch (error) {
1613
1613
  await stopPrivacyDaemon();
1614
1614
  throw error;
1615
1615
  }
1616
1616
  }
1617
- async function prepareCliMessagePrivacy(text5, memories, existing = [], scope2 = { kind: "message" }, progress) {
1617
+ async function prepareCliMessagePrivacy(text6, memories, existing = [], scope2 = { kind: "message" }, progress) {
1618
1618
  const options = privacyDetectionOptions(memories);
1619
1619
  let mappings = existing;
1620
1620
  const privacy = new ProjectFilePrivacy({
@@ -1626,7 +1626,7 @@ async function prepareCliMessagePrivacy(text5, memories, existing = [], scope2 =
1626
1626
  },
1627
1627
  detectEnhanced: (value) => scanEnhancedText(value, scope2, options.detection.disabledCategories, progress)
1628
1628
  });
1629
- const message = await privacy.redactResult(text5);
1629
+ const message = await privacy.redactResult(text6);
1630
1630
  return { message, mappings: mappings.map((mapping) => ({ ...mapping, type: mapping.type ?? "OTHER" })) };
1631
1631
  }
1632
1632
 
@@ -1646,9 +1646,9 @@ function buildMemoryRequestMessage(params) {
1646
1646
  if (!params.requestId || !params.userMessageId) {
1647
1647
  throw new Error("Memory requests require stable request and user-message identities");
1648
1648
  }
1649
- const keys = Array.from(new Set(params.requestedKeys)).sort();
1649
+ const keys2 = Array.from(new Set(params.requestedKeys)).sort();
1650
1650
  const categories = [];
1651
- for (const key of keys) {
1651
+ for (const key of keys2) {
1652
1652
  const separator = key.indexOf("-");
1653
1653
  if (separator <= 0 || separator === key.length - 1) {
1654
1654
  throw new Error(`Invalid memory category key: ${key}`);
@@ -1664,7 +1664,7 @@ function buildMemoryRequestMessage(params) {
1664
1664
  type: REQUEST_TYPE,
1665
1665
  user_message_id: params.userMessageId,
1666
1666
  request_id: params.requestId,
1667
- requested_keys: keys,
1667
+ requested_keys: keys2,
1668
1668
  categories,
1669
1669
  count_semantics_version: COUNT_SEMANTICS_VERSION
1670
1670
  };
@@ -1733,6 +1733,227 @@ function coalesceMemoryRequestMessages(messages) {
1733
1733
  return result;
1734
1734
  }
1735
1735
 
1736
+ // ../ui/src/utils/projectFilePatch.ts
1737
+ var ProjectFilePatchError = class extends Error {
1738
+ constructor(message) {
1739
+ super(message);
1740
+ this.name = "ProjectFilePatchError";
1741
+ }
1742
+ };
1743
+ var HEADER = /^(---|\+\+\+) ([^\t]+)(?:\t.*)?$/;
1744
+ var HUNK = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(?: .*)?$/;
1745
+ function applyProjectFilePatch(original, unifiedDiff, expectedPath) {
1746
+ if (!unifiedDiff || unifiedDiff.includes("\0") || unifiedDiff.includes("\r")) {
1747
+ throw new ProjectFilePatchError("Patch must be a non-empty LF unified diff");
1748
+ }
1749
+ const rows2 = unifiedDiff.split("\n");
1750
+ if (rows2.at(-1) === "") rows2.pop();
1751
+ if (rows2.length < 3) throw new ProjectFilePatchError("Patch is missing file headers or hunks");
1752
+ const oldHeader = HEADER.exec(rows2[0] ?? "");
1753
+ const newHeader = HEADER.exec(rows2[1] ?? "");
1754
+ if (!oldHeader || oldHeader[1] !== "---" || !newHeader || newHeader[1] !== "+++") {
1755
+ throw new ProjectFilePatchError("Patch must start with one old and one new file header");
1756
+ }
1757
+ const oldPath = normalizeHeaderPath(oldHeader[2] ?? "");
1758
+ const newPath = normalizeHeaderPath(newHeader[2] ?? "");
1759
+ if (oldPath === "/dev/null" || newPath === "/dev/null") {
1760
+ throw new ProjectFilePatchError("Update patches cannot create or delete files");
1761
+ }
1762
+ if (expectedPath && (oldPath !== expectedPath || newPath !== expectedPath)) {
1763
+ throw new ProjectFilePatchError("Patch file headers do not match the requested path");
1764
+ }
1765
+ const hunks = [];
1766
+ let row = 2;
1767
+ while (row < rows2.length) {
1768
+ const match = HUNK.exec(rows2[row] ?? "");
1769
+ if (!match) throw new ProjectFilePatchError("Patch contains data outside a valid hunk");
1770
+ const hunk = {
1771
+ oldStart: parseCoordinate(match[1]),
1772
+ oldCount: match[2] === void 0 ? 1 : parseCoordinate(match[2]),
1773
+ newStart: parseCoordinate(match[3]),
1774
+ newCount: match[4] === void 0 ? 1 : parseCoordinate(match[4]),
1775
+ lines: []
1776
+ };
1777
+ row += 1;
1778
+ let oldSeen = 0;
1779
+ let newSeen = 0;
1780
+ while (row < rows2.length && !rows2[row]?.startsWith("@@ ")) {
1781
+ const value = rows2[row] ?? "";
1782
+ if (value === "\") {
1783
+ const previous = hunk.lines.at(-1);
1784
+ if (!previous || !previous.line.hasNewline) {
1785
+ throw new ProjectFilePatchError("Misplaced no-newline marker");
1786
+ }
1787
+ previous.line.hasNewline = false;
1788
+ row += 1;
1789
+ continue;
1790
+ }
1791
+ const prefix = value[0];
1792
+ if (prefix !== " " && prefix !== "-" && prefix !== "+") {
1793
+ throw new ProjectFilePatchError("Every hunk line must have a unified-diff prefix");
1794
+ }
1795
+ const kind = prefix === " " ? "context" : prefix === "-" ? "remove" : "add";
1796
+ hunk.lines.push({ kind, line: { value: value.slice(1), hasNewline: true } });
1797
+ if (kind !== "add") oldSeen += 1;
1798
+ if (kind !== "remove") newSeen += 1;
1799
+ row += 1;
1800
+ }
1801
+ if (oldSeen !== hunk.oldCount || newSeen !== hunk.newCount) {
1802
+ throw new ProjectFilePatchError("Hunk line counts do not match its header");
1803
+ }
1804
+ hunks.push(hunk);
1805
+ }
1806
+ if (hunks.length === 0) throw new ProjectFilePatchError("Patch has no hunks");
1807
+ const source = splitContentLines(original);
1808
+ const output = [];
1809
+ let sourceIndex = 0;
1810
+ let outputLine = 1;
1811
+ for (const hunk of hunks) {
1812
+ const expectedSourceIndex = hunk.oldCount === 0 ? hunk.oldStart : hunk.oldStart - 1;
1813
+ const expectedOutputLine = hunk.newCount === 0 ? hunk.newStart + 1 : hunk.newStart;
1814
+ if (expectedSourceIndex < sourceIndex || expectedSourceIndex > source.length) {
1815
+ throw new ProjectFilePatchError("Patch hunks overlap or are outside the source");
1816
+ }
1817
+ while (sourceIndex < expectedSourceIndex) {
1818
+ output.push(source[sourceIndex]);
1819
+ sourceIndex += 1;
1820
+ outputLine += 1;
1821
+ }
1822
+ if (outputLine !== expectedOutputLine) {
1823
+ throw new ProjectFilePatchError("Patch new-file coordinates are inconsistent");
1824
+ }
1825
+ for (const item of hunk.lines) {
1826
+ if (item.kind !== "add") {
1827
+ const actual = source[sourceIndex];
1828
+ if (!actual || actual.value !== item.line.value || actual.hasNewline !== item.line.hasNewline) {
1829
+ throw new ProjectFilePatchError("Patch context does not match the source exactly");
1830
+ }
1831
+ sourceIndex += 1;
1832
+ }
1833
+ if (item.kind !== "remove") {
1834
+ output.push({ ...item.line });
1835
+ outputLine += 1;
1836
+ }
1837
+ }
1838
+ }
1839
+ output.push(...source.slice(sourceIndex));
1840
+ validateNewlinePlacement(output);
1841
+ return {
1842
+ content: output.map((line) => line.value + (line.hasNewline ? "\n" : "")).join(""),
1843
+ appliedDiff: unifiedDiff,
1844
+ oldPath,
1845
+ newPath
1846
+ };
1847
+ }
1848
+ function parseCoordinate(value) {
1849
+ const number = Number(value);
1850
+ if (!Number.isSafeInteger(number) || number < 0) throw new ProjectFilePatchError("Invalid hunk coordinate");
1851
+ return number;
1852
+ }
1853
+ function normalizeHeaderPath(value) {
1854
+ if (value === "/dev/null") return value;
1855
+ if (value.startsWith("a/") || value.startsWith("b/")) return value.slice(2);
1856
+ return value;
1857
+ }
1858
+ function splitContentLines(content) {
1859
+ if (content === "") return [];
1860
+ const lines = [];
1861
+ let start = 0;
1862
+ for (let index = 0; index < content.length; index += 1) {
1863
+ if (content[index] !== "\n") continue;
1864
+ lines.push({ value: content.slice(start, index), hasNewline: true });
1865
+ start = index + 1;
1866
+ }
1867
+ if (start < content.length) lines.push({ value: content.slice(start), hasNewline: false });
1868
+ return lines;
1869
+ }
1870
+ function validateNewlinePlacement(lines) {
1871
+ for (let index = 0; index < lines.length - 1; index += 1) {
1872
+ if (!lines[index]?.hasNewline) throw new ProjectFilePatchError("No-newline marker is only valid at end of file");
1873
+ }
1874
+ }
1875
+
1876
+ // ../ui/src/utils/embedVersionReconstruction.ts
1877
+ async function reconstructVersionRows(rows2, decrypt) {
1878
+ const sorted2 = [...rows2].sort((a, b) => a.version_number - b.version_number);
1879
+ let content = null;
1880
+ let expected = sorted2[0]?.version_number ?? 1;
1881
+ for (const row of sorted2) {
1882
+ if (!Number.isSafeInteger(row.version_number) || row.version_number < 1 || row.version_number !== expected) {
1883
+ throw new Error("Version chain is incomplete");
1884
+ }
1885
+ expected += 1;
1886
+ if (row.encrypted_snapshot) {
1887
+ content = await decrypt(row.encrypted_snapshot);
1888
+ if (content === null) throw new Error("Version snapshot could not be decrypted");
1889
+ } else {
1890
+ if (content === null) throw new Error("Version history is missing the initial snapshot");
1891
+ if (!row.encrypted_patch) throw new Error("Version patch is missing");
1892
+ const patch = await decrypt(row.encrypted_patch);
1893
+ if (patch === null) throw new Error("Version patch could not be decrypted");
1894
+ content = applyVersionPatch(content, patch);
1895
+ }
1896
+ }
1897
+ if (content === null) throw new Error("Version history is missing the initial snapshot");
1898
+ return content;
1899
+ }
1900
+ function applyVersionPatch(content, patch) {
1901
+ if (patch.includes("\")) {
1902
+ const withHeaders = patch.startsWith("@@ ") ? `--- version
1903
+ +++ version
1904
+ ${patch}` : patch;
1905
+ return applyProjectFilePatch(content, withHeaders).content;
1906
+ }
1907
+ const source = content === "" ? [] : content.split("\n");
1908
+ const lines = patch.split("\n");
1909
+ if (lines.at(-1) === "") lines.pop();
1910
+ let index = 0;
1911
+ if (lines[0]?.startsWith("--- ") && lines[1]?.startsWith("+++ ")) index = 2;
1912
+ const output = [];
1913
+ let sourceIndex = 0;
1914
+ let hunkCount = 0;
1915
+ while (index < lines.length) {
1916
+ const header2 = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(?: .*)?$/.exec(lines[index] ?? "");
1917
+ if (!header2) throw new Error("Version patch contains an invalid hunk");
1918
+ const oldStart = Number(header2[1]);
1919
+ const oldCount = header2[2] === void 0 ? 1 : Number(header2[2]);
1920
+ const newStart = Number(header2[3]);
1921
+ const newCount = header2[4] === void 0 ? 1 : Number(header2[4]);
1922
+ const start = oldCount === 0 ? oldStart : oldStart - 1;
1923
+ const outputStart = newCount === 0 ? newStart : newStart - 1;
1924
+ if (![oldStart, oldCount, newStart, newCount].every(Number.isSafeInteger) || start < sourceIndex || start > source.length) throw new Error("Version patch hunks overlap or exceed content");
1925
+ output.push(...source.slice(sourceIndex, start));
1926
+ if (output.length !== outputStart) throw new Error("Version patch coordinates do not match content");
1927
+ sourceIndex = start;
1928
+ let removed = 0;
1929
+ let added = 0;
1930
+ index += 1;
1931
+ while (index < lines.length && !lines[index]?.startsWith("@@ ")) {
1932
+ const line = lines[index] ?? "";
1933
+ if (line === "\") {
1934
+ index += 1;
1935
+ continue;
1936
+ }
1937
+ if (![" ", "-", "+"].includes(line[0] ?? "")) throw new Error("Version patch has an invalid line");
1938
+ if (line[0] !== "+") {
1939
+ if (source[sourceIndex] !== line.slice(1)) throw new Error("Version patch context does not match local content");
1940
+ sourceIndex += 1;
1941
+ removed += 1;
1942
+ }
1943
+ if (line[0] !== "-") {
1944
+ output.push(line.slice(1));
1945
+ added += 1;
1946
+ }
1947
+ index += 1;
1948
+ }
1949
+ if (removed !== oldCount || added !== newCount) throw new Error("Version patch line counts do not match its header");
1950
+ hunkCount += 1;
1951
+ }
1952
+ if (hunkCount === 0) throw new Error("Version patch has no hunks");
1953
+ output.push(...source.slice(sourceIndex));
1954
+ return output.join("\n");
1955
+ }
1956
+
1736
1957
  // src/accountImport.ts
1737
1958
  import { createDecipheriv, createHash as createHash4, scryptSync } from "crypto";
1738
1959
  import JSZip from "jszip";
@@ -2025,7 +2246,7 @@ async function parseOpenCodeImportBuffer(payload, sourceName = "opencode-session
2025
2246
  if (role !== "user" && role !== "assistant") continue;
2026
2247
  const parts = Array.isArray(message.parts) ? message.parts.filter((part) => Boolean(part && typeof part === "object")) : [];
2027
2248
  const textParts = parts.filter((part) => part.type === "text" && part.ignored !== true && typeof part.text === "string");
2028
- const content = textParts.map((part) => String(part.text)).filter((text5) => text5.trim()).join("\n");
2249
+ const content = textParts.map((part) => String(part.text)).filter((text6) => text6.trim()).join("\n");
2029
2250
  if (content.trim()) {
2030
2251
  const time2 = messageInfo.time && typeof messageInfo.time === "object" ? messageInfo.time : {};
2031
2252
  messages.push({
@@ -2863,146 +3084,6 @@ function createProjectFileJobExecutor(options) {
2863
3084
  } };
2864
3085
  }
2865
3086
 
2866
- // ../ui/src/utils/projectFilePatch.ts
2867
- var ProjectFilePatchError = class extends Error {
2868
- constructor(message) {
2869
- super(message);
2870
- this.name = "ProjectFilePatchError";
2871
- }
2872
- };
2873
- var HEADER = /^(---|\+\+\+) ([^\t]+)(?:\t.*)?$/;
2874
- var HUNK = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(?: .*)?$/;
2875
- function applyProjectFilePatch(original, unifiedDiff, expectedPath) {
2876
- if (!unifiedDiff || unifiedDiff.includes("\0") || unifiedDiff.includes("\r")) {
2877
- throw new ProjectFilePatchError("Patch must be a non-empty LF unified diff");
2878
- }
2879
- const rows2 = unifiedDiff.split("\n");
2880
- if (rows2.at(-1) === "") rows2.pop();
2881
- if (rows2.length < 3) throw new ProjectFilePatchError("Patch is missing file headers or hunks");
2882
- const oldHeader = HEADER.exec(rows2[0] ?? "");
2883
- const newHeader = HEADER.exec(rows2[1] ?? "");
2884
- if (!oldHeader || oldHeader[1] !== "---" || !newHeader || newHeader[1] !== "+++") {
2885
- throw new ProjectFilePatchError("Patch must start with one old and one new file header");
2886
- }
2887
- const oldPath = normalizeHeaderPath(oldHeader[2] ?? "");
2888
- const newPath = normalizeHeaderPath(newHeader[2] ?? "");
2889
- if (oldPath === "/dev/null" || newPath === "/dev/null") {
2890
- throw new ProjectFilePatchError("Update patches cannot create or delete files");
2891
- }
2892
- if (expectedPath && (oldPath !== expectedPath || newPath !== expectedPath)) {
2893
- throw new ProjectFilePatchError("Patch file headers do not match the requested path");
2894
- }
2895
- const hunks = [];
2896
- let row = 2;
2897
- while (row < rows2.length) {
2898
- const match = HUNK.exec(rows2[row] ?? "");
2899
- if (!match) throw new ProjectFilePatchError("Patch contains data outside a valid hunk");
2900
- const hunk = {
2901
- oldStart: parseCoordinate(match[1]),
2902
- oldCount: match[2] === void 0 ? 1 : parseCoordinate(match[2]),
2903
- newStart: parseCoordinate(match[3]),
2904
- newCount: match[4] === void 0 ? 1 : parseCoordinate(match[4]),
2905
- lines: []
2906
- };
2907
- row += 1;
2908
- let oldSeen = 0;
2909
- let newSeen = 0;
2910
- while (row < rows2.length && !rows2[row]?.startsWith("@@ ")) {
2911
- const value = rows2[row] ?? "";
2912
- if (value === "\") {
2913
- const previous = hunk.lines.at(-1);
2914
- if (!previous || !previous.line.hasNewline) {
2915
- throw new ProjectFilePatchError("Misplaced no-newline marker");
2916
- }
2917
- previous.line.hasNewline = false;
2918
- row += 1;
2919
- continue;
2920
- }
2921
- const prefix = value[0];
2922
- if (prefix !== " " && prefix !== "-" && prefix !== "+") {
2923
- throw new ProjectFilePatchError("Every hunk line must have a unified-diff prefix");
2924
- }
2925
- const kind = prefix === " " ? "context" : prefix === "-" ? "remove" : "add";
2926
- hunk.lines.push({ kind, line: { value: value.slice(1), hasNewline: true } });
2927
- if (kind !== "add") oldSeen += 1;
2928
- if (kind !== "remove") newSeen += 1;
2929
- row += 1;
2930
- }
2931
- if (oldSeen !== hunk.oldCount || newSeen !== hunk.newCount) {
2932
- throw new ProjectFilePatchError("Hunk line counts do not match its header");
2933
- }
2934
- hunks.push(hunk);
2935
- }
2936
- if (hunks.length === 0) throw new ProjectFilePatchError("Patch has no hunks");
2937
- const source = splitContentLines(original);
2938
- const output = [];
2939
- let sourceIndex = 0;
2940
- let outputLine = 1;
2941
- for (const hunk of hunks) {
2942
- const expectedSourceIndex = hunk.oldCount === 0 ? hunk.oldStart : hunk.oldStart - 1;
2943
- const expectedOutputLine = hunk.newCount === 0 ? hunk.newStart + 1 : hunk.newStart;
2944
- if (expectedSourceIndex < sourceIndex || expectedSourceIndex > source.length) {
2945
- throw new ProjectFilePatchError("Patch hunks overlap or are outside the source");
2946
- }
2947
- while (sourceIndex < expectedSourceIndex) {
2948
- output.push(source[sourceIndex]);
2949
- sourceIndex += 1;
2950
- outputLine += 1;
2951
- }
2952
- if (outputLine !== expectedOutputLine) {
2953
- throw new ProjectFilePatchError("Patch new-file coordinates are inconsistent");
2954
- }
2955
- for (const item of hunk.lines) {
2956
- if (item.kind !== "add") {
2957
- const actual = source[sourceIndex];
2958
- if (!actual || actual.value !== item.line.value || actual.hasNewline !== item.line.hasNewline) {
2959
- throw new ProjectFilePatchError("Patch context does not match the source exactly");
2960
- }
2961
- sourceIndex += 1;
2962
- }
2963
- if (item.kind !== "remove") {
2964
- output.push({ ...item.line });
2965
- outputLine += 1;
2966
- }
2967
- }
2968
- }
2969
- output.push(...source.slice(sourceIndex));
2970
- validateNewlinePlacement(output);
2971
- return {
2972
- content: output.map((line) => line.value + (line.hasNewline ? "\n" : "")).join(""),
2973
- appliedDiff: unifiedDiff,
2974
- oldPath,
2975
- newPath
2976
- };
2977
- }
2978
- function parseCoordinate(value) {
2979
- const number = Number(value);
2980
- if (!Number.isSafeInteger(number) || number < 0) throw new ProjectFilePatchError("Invalid hunk coordinate");
2981
- return number;
2982
- }
2983
- function normalizeHeaderPath(value) {
2984
- if (value === "/dev/null") return value;
2985
- if (value.startsWith("a/") || value.startsWith("b/")) return value.slice(2);
2986
- return value;
2987
- }
2988
- function splitContentLines(content) {
2989
- if (content === "") return [];
2990
- const lines = [];
2991
- let start = 0;
2992
- for (let index = 0; index < content.length; index += 1) {
2993
- if (content[index] !== "\n") continue;
2994
- lines.push({ value: content.slice(start, index), hasNewline: true });
2995
- start = index + 1;
2996
- }
2997
- if (start < content.length) lines.push({ value: content.slice(start), hasNewline: false });
2998
- return lines;
2999
- }
3000
- function validateNewlinePlacement(lines) {
3001
- for (let index = 0; index < lines.length - 1; index += 1) {
3002
- if (!lines[index]?.hasNewline) throw new ProjectFilePatchError("No-newline marker is only valid at end of file");
3003
- }
3004
- }
3005
-
3006
3087
  // ../ui/src/utils/projectSearchProtocol.ts
3007
3088
  var ProjectSearchProtocolError = class extends Error {
3008
3089
  code;
@@ -3102,7 +3183,7 @@ function matchesProjectSearchQuery(value, request) {
3102
3183
  function matchesProjectSearchGlob(path2, glob) {
3103
3184
  if (!glob) return true;
3104
3185
  const memo = /* @__PURE__ */ new Map();
3105
- const visit = (pathIndex, globIndex) => {
3186
+ const visit2 = (pathIndex, globIndex) => {
3106
3187
  const key = `${pathIndex}:${globIndex}`;
3107
3188
  const cached = memo.get(key);
3108
3189
  if (cached !== void 0) return cached;
@@ -3110,23 +3191,23 @@ function matchesProjectSearchGlob(path2, glob) {
3110
3191
  if (globIndex === glob.length) {
3111
3192
  matched = pathIndex === path2.length;
3112
3193
  } else if (glob.startsWith("**/", globIndex)) {
3113
- matched = visit(pathIndex, globIndex + 3);
3194
+ matched = visit2(pathIndex, globIndex + 3);
3114
3195
  for (let index = pathIndex; !matched && index < path2.length; index += 1) {
3115
- if (path2[index] === "/") matched = visit(index + 1, globIndex + 3);
3196
+ if (path2[index] === "/") matched = visit2(index + 1, globIndex + 3);
3116
3197
  }
3117
3198
  } else if (glob.startsWith("**", globIndex)) {
3118
- matched = visit(pathIndex, globIndex + 2) || pathIndex < path2.length && visit(pathIndex + 1, globIndex);
3199
+ matched = visit2(pathIndex, globIndex + 2) || pathIndex < path2.length && visit2(pathIndex + 1, globIndex);
3119
3200
  } else if (glob[globIndex] === "*") {
3120
- matched = visit(pathIndex, globIndex + 1) || pathIndex < path2.length && path2[pathIndex] !== "/" && visit(pathIndex + 1, globIndex);
3201
+ matched = visit2(pathIndex, globIndex + 1) || pathIndex < path2.length && path2[pathIndex] !== "/" && visit2(pathIndex + 1, globIndex);
3121
3202
  } else if (glob[globIndex] === "?") {
3122
- matched = pathIndex < path2.length && path2[pathIndex] !== "/" && visit(pathIndex + 1, globIndex + 1);
3203
+ matched = pathIndex < path2.length && path2[pathIndex] !== "/" && visit2(pathIndex + 1, globIndex + 1);
3123
3204
  } else {
3124
- matched = pathIndex < path2.length && path2[pathIndex] === glob[globIndex] && visit(pathIndex + 1, globIndex + 1);
3205
+ matched = pathIndex < path2.length && path2[pathIndex] === glob[globIndex] && visit2(pathIndex + 1, globIndex + 1);
3125
3206
  }
3126
3207
  memo.set(key, matched);
3127
3208
  return matched;
3128
3209
  };
3129
- return visit(0, 0);
3210
+ return visit2(0, 0);
3130
3211
  }
3131
3212
  function isProtectedProjectReadPath(value) {
3132
3213
  const normalized = value.replace(/\\/g, "/").replace(/^\.\//, "").toLowerCase();
@@ -3832,8 +3913,8 @@ async function activateCliProjectFocus(client2, projectId, chatId, teamId, activ
3832
3913
  const key = await client2.decryptProjectKey(detail.project, context);
3833
3914
  if (!settings.encrypted_settings || settings.selection_required) throw new Error("Choose this Project's write policy in Project settings before starting work.");
3834
3915
  if (isCurrent && !isCurrent()) return;
3835
- const text5 = await decryptWithAesGcmCombined(settings.encrypted_settings, key);
3836
- const focus = text5 ? JSON.parse(text5).default_focus : void 0;
3916
+ const text6 = await decryptWithAesGcmCombined(settings.encrypted_settings, key);
3917
+ const focus = text6 ? JSON.parse(text6).default_focus : void 0;
3837
3918
  if (!focus?.focus_id || typeof focus.instructions !== "string") throw new Error("The Project's default focus is unavailable.");
3838
3919
  if (isCurrent && !isCurrent()) return;
3839
3920
  await client2.activateProjectFocus(projectId, {
@@ -3898,7 +3979,7 @@ function registerCliProjectFileExecutor(options) {
3898
3979
  key: options.chatKey,
3899
3980
  mappings: [...history.messages.flatMap((message) => message.piiMappings ?? []), ...options.piiMappings ?? []],
3900
3981
  ...detection,
3901
- detectEnhanced: (text5) => scanEnhancedText(text5, { kind: "project", projectId: job.project_id }, detection.detection.disabledCategories),
3982
+ detectEnhanced: (text6) => scanEnhancedText(text6, { kind: "project", projectId: job.project_id }, detection.detection.disabledCategories),
3902
3983
  read: async () => {
3903
3984
  try {
3904
3985
  return await readFile(path2, "utf8");
@@ -4351,13 +4432,13 @@ var RemoteCommandOutputAccumulator = class {
4351
4432
  return { text: this.#text, coverage: "full", sequence_gap: false, upstream_truncated: false, omitted_chars: 0 };
4352
4433
  }
4353
4434
  const half = Math.max(0, Math.floor((MAX_COMPLETION_CHARS - OMISSION_MARKER.length) / 2));
4354
- const text5 = this.#text.length <= MAX_COMPLETION_CHARS ? this.#text : `${this.#text.slice(0, half)}${OMISSION_MARKER}${this.#text.slice(-half)}`;
4435
+ const text6 = this.#text.length <= MAX_COMPLETION_CHARS ? this.#text : `${this.#text.slice(0, half)}${OMISSION_MARKER}${this.#text.slice(-half)}`;
4355
4436
  return {
4356
- text: text5,
4437
+ text: text6,
4357
4438
  coverage: "selected_excerpt",
4358
4439
  sequence_gap: this.#sequenceGap,
4359
4440
  upstream_truncated: true,
4360
- omitted_chars: Math.max(0, this.#inputChars - text5.length + (text5.includes(OMISSION_MARKER) ? OMISSION_MARKER.length : 0))
4441
+ omitted_chars: Math.max(0, this.#inputChars - text6.length + (text6.includes(OMISSION_MARKER) ? OMISSION_MARKER.length : 0))
4361
4442
  };
4362
4443
  }
4363
4444
  };
@@ -4884,6 +4965,7 @@ var OpenMatesWsClient = class {
4884
4965
  const clientCapabilities = [
4885
4966
  "canonical_embed_receipts_v1",
4886
4967
  "typed_recovery_outputs_v2",
4968
+ "agentic-storage-v2",
4887
4969
  ...options.taskUpdateJobs !== false ? ["task_update_jobs"] : [],
4888
4970
  ...options.projectFileJobs === true ? ["project_file_jobs"] : [],
4889
4971
  ...options.remoteCommandJobs === true ? ["remote_command_jobs"] : []
@@ -5372,8 +5454,8 @@ var OpenMatesWsClient = class {
5372
5454
  if (!content || typeof content !== "object") return "";
5373
5455
  try {
5374
5456
  const root = content;
5375
- const text5 = root.content?.[0]?.content?.[0]?.text;
5376
- return typeof text5 === "string" ? text5 : "";
5457
+ const text6 = root.content?.[0]?.content?.[0]?.text;
5458
+ return typeof text6 === "string" ? text6 : "";
5377
5459
  } catch {
5378
5460
  return "";
5379
5461
  }
@@ -6025,21 +6107,98 @@ function registerChatContextEvents(options) {
6025
6107
  }
6026
6108
 
6027
6109
  // src/cliJevContext.ts
6028
- import { parse as parseYaml } from "yaml";
6110
+ import { parseDocument as parseDocument2, isAlias, visit } from "yaml";
6111
+
6112
+ // ../projectFocusDocument.ts
6113
+ function invalid() {
6114
+ throw new Error("invalid_focus_document");
6115
+ }
6116
+ function object(value) {
6117
+ if (!value || typeof value !== "object" || Array.isArray(value)) return invalid();
6118
+ return value;
6119
+ }
6120
+ function keys(value, allowed) {
6121
+ if (Object.keys(value).some((key) => !allowed.includes(key))) invalid();
6122
+ }
6123
+ function text4(value, limit) {
6124
+ if (typeof value !== "string" || !value.trim() || value.length > limit) return invalid();
6125
+ return value;
6126
+ }
6127
+ function identifier3(value, canonical) {
6128
+ const result = text4(value, canonical ? 64 : 80);
6129
+ if (!(canonical ? /^[a-z][a-z0-9_-]{0,63}$/ : /^[a-zA-Z0-9_-]{1,80}$/).test(result)) invalid();
6130
+ return result;
6131
+ }
6132
+ function unique(ids) {
6133
+ if (new Set(ids).size !== ids.length) invalid();
6134
+ }
6135
+ function projectFocusDocumentFromMetadata(metadata, body) {
6136
+ const header2 = object(metadata);
6137
+ keys(header2, ["name", "title", "description", "when_to_use", "preprocessor_hint", "preprocessor-hint", "phases_version", "phases"]);
6138
+ const names = [header2.name, header2.title].filter((value) => value !== void 0);
6139
+ const hints = [header2.when_to_use, header2.preprocessor_hint, header2["preprocessor-hint"]].filter((value) => value !== void 0);
6140
+ if (names.length !== 1 || hints.length !== 1) invalid();
6141
+ const common = {
6142
+ name: text4(names[0], 200),
6143
+ description: text4(header2.description, 2e3),
6144
+ when_to_use: text4(hints[0], 2e3),
6145
+ instructions: text4(body.trim(), 64e3)
6146
+ };
6147
+ const phases = header2.phases === void 0 ? [] : header2.phases;
6148
+ if (!Array.isArray(phases) || phases.length > 16) invalid();
6149
+ if (Object.prototype.hasOwnProperty.call(header2, "phases_version")) {
6150
+ if (header2.phases_version !== 1 || !phases.length) invalid();
6151
+ const canonical = phases.map((raw) => {
6152
+ const phase = object(raw);
6153
+ keys(phase, ["id", "title", "instructions", "requirements"]);
6154
+ const requirements = phase.requirements;
6155
+ if (!Array.isArray(requirements) || !requirements.length || requirements.length > 24) invalid();
6156
+ const gates = requirements.map((rawRequirement) => {
6157
+ const requirement = object(rawRequirement);
6158
+ keys(requirement, ["id", "text", "type"]);
6159
+ if (requirement.type !== void 0 && (typeof requirement.type !== "string" || !["semantic", "user_confirmation"].includes(requirement.type))) invalid();
6160
+ return {
6161
+ id: identifier3(requirement.id, true),
6162
+ text: text4(requirement.text, 4e3),
6163
+ ...requirement.type === void 0 ? {} : { type: requirement.type }
6164
+ };
6165
+ });
6166
+ unique(gates.map((gate) => gate.id));
6167
+ return {
6168
+ id: identifier3(phase.id, true),
6169
+ title: text4(phase.title, 200),
6170
+ instructions: text4(phase.instructions, 16e3),
6171
+ requirements: gates
6172
+ };
6173
+ });
6174
+ unique(canonical.map((phase) => phase.id));
6175
+ return { ...common, phases_version: 1, phases: canonical };
6176
+ }
6177
+ const legacy = phases.map((raw) => {
6178
+ const phase = object(raw);
6179
+ keys(phase, ["id", "name", "instructions"]);
6180
+ return { id: identifier3(phase.id, false), name: text4(phase.name, 120), instructions: text4(phase.instructions, 16e3) };
6181
+ });
6182
+ unique(legacy.map((phase) => phase.id));
6183
+ return { ...common, phases: legacy };
6184
+ }
6185
+
6186
+ // src/cliJevContext.ts
6029
6187
  import { createHash as createHash8 } from "crypto";
6030
6188
  function parseFocusAuthoringDocument(document) {
6031
- if (document.length > 96e3) throw new Error("Project Focus definition exceeds the limit.");
6032
- const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/.exec(document);
6033
- if (!match) throw new Error("Project Focus is missing its Markdown definition.");
6034
- const header2 = parseYaml(match[1], { schema: "core", uniqueKeys: true, maxAliasCount: 0 });
6035
- const name = header2.name ?? header2.title;
6036
- const when = header2.when_to_use ?? header2.preprocessor_hint ?? header2["preprocessor-hint"];
6037
- if (typeof name !== "string" || typeof header2.description !== "string" || typeof when !== "string") throw new Error("Project Focus metadata is incomplete.");
6038
- const phases = Array.isArray(header2.phases) ? header2.phases.map((value) => {
6039
- if (typeof value.id !== "string" || typeof (value.name ?? value.title) !== "string" || typeof value.instructions !== "string") throw new Error("Project Focus phase metadata is incomplete.");
6040
- return { id: value.id, name: String(value.name ?? value.title), instructions: value.instructions };
6041
- }) : [];
6042
- return { name, description: header2.description, when_to_use: when, instructions: match[2].trim(), phases };
6189
+ if (document.length > 96e3) throw new Error("invalid_focus_document");
6190
+ const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/.exec(document);
6191
+ if (!match) throw new Error("invalid_focus_document");
6192
+ try {
6193
+ const parsed = parseDocument2(match[1], { schema: "core", uniqueKeys: true });
6194
+ if (parsed.errors.length) throw new Error("invalid_focus_document");
6195
+ visit(parsed, (_key, node) => {
6196
+ if (isAlias(node)) throw new Error("invalid_focus_document");
6197
+ });
6198
+ return projectFocusDocumentFromMetadata(parsed.toJS({ maxAliasCount: 0 }), match[2]);
6199
+ } catch {
6200
+ throw new Error("invalid_focus_document");
6201
+ }
6043
6202
  }
6044
6203
  async function discoverCliProjectCandidates(client2, options) {
6045
6204
  const records = (await client2.listProjects(options)).filter((record8) => !record8.archived).slice(0, 40);
@@ -6057,7 +6216,7 @@ async function discoverCliProjectCandidates(client2, options) {
6057
6216
  }));
6058
6217
  return entries.filter((entry) => entry !== null);
6059
6218
  }
6060
- async function loadActiveCliProjectContext(client2, chatId, text5) {
6219
+ async function loadActiveCliProjectContext(client2, chatId, text6) {
6061
6220
  const active = await client2.getActiveProjectFocus(chatId);
6062
6221
  if (!active) return {};
6063
6222
  const options = { teamId: active.team_id, personal: !active.team_id };
@@ -6113,9 +6272,9 @@ async function loadActiveCliProjectContext(client2, chatId, text5) {
6113
6272
  if (title && description) candidates.push({ kind: "folder", id: folder.folder_id, title: title.slice(0, 200), description: description.slice(0, 640), when_to_use: "", revision: revision(folder) });
6114
6273
  }
6115
6274
  let selected = [];
6116
- if (text5?.trim() && candidates.length) selected = await client2.selectProjectContext(
6275
+ if (text6?.trim() && candidates.length) selected = await client2.selectProjectContext(
6117
6276
  active.project_id,
6118
- { chat_id: chatId, text: text5.slice(0, 8e3), candidates: candidates.slice(0, 24) },
6277
+ { chat_id: chatId, text: text6.slice(0, 8e3), candidates: candidates.slice(0, 24) },
6119
6278
  options
6120
6279
  );
6121
6280
  const specialistId = active.specialist_focus_id?.startsWith(`project-focus:${active.project_id}:`) ? active.specialist_focus_id.split(":")[2] : active.specialist_focus_id;
@@ -6260,7 +6419,7 @@ async function collectRelatedCliTaskContext(client2, chatId, options, records, n
6260
6419
  }
6261
6420
  return candidates;
6262
6421
  }
6263
- async function prepareCliJevContext(client2, chatId, options, supplied = {}, text5) {
6422
+ async function prepareCliJevContext(client2, chatId, options, supplied = {}, text6) {
6264
6423
  let candidates = [];
6265
6424
  let active = {};
6266
6425
  let tasks = [];
@@ -6271,7 +6430,7 @@ async function prepareCliJevContext(client2, chatId, options, supplied = {}, tex
6271
6430
  candidates = value;
6272
6431
  }).catch(() => {
6273
6432
  }),
6274
- loadActiveCliProjectContext(client2, chatId, text5).then((value) => {
6433
+ loadActiveCliProjectContext(client2, chatId, text6).then((value) => {
6275
6434
  active = value;
6276
6435
  }).catch(() => {
6277
6436
  }),
@@ -6476,8 +6635,8 @@ async function startCliProjectAuthoring(client2, recommendation, history) {
6476
6635
  const key = await client2.decryptProjectKey(detail.project, options);
6477
6636
  for (const item of detail.items.filter((item2) => item2.item_type === "workflow" && !item2.deleted_target_state)) {
6478
6637
  if (await decryptWithAesGcmCombined(item.target_id_encrypted, key) !== recommendation.target_id) continue;
6479
- const text5 = item.encrypted_metadata ? await decryptWithAesGcmCombined(item.encrypted_metadata, key) : null;
6480
- const metadata = text5 ? JSON.parse(text5) : {};
6638
+ const text6 = item.encrypted_metadata ? await decryptWithAesGcmCombined(item.encrypted_metadata, key) : null;
6639
+ const metadata = text6 ? JSON.parse(text6) : {};
6481
6640
  if (metadata.remote_workflow_file && typeof metadata.remote_workflow_file === "object") remoteBinding = metadata.remote_workflow_file;
6482
6641
  break;
6483
6642
  }
@@ -7151,8 +7310,8 @@ function parseDelimitedLine(line, delimiter) {
7151
7310
  cells2.push(current);
7152
7311
  return cells2;
7153
7312
  }
7154
- function delimitedTextToMarkdownTable(text5, delimiter) {
7155
- const rows2 = text5.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0).map((line) => parseDelimitedLine(line, delimiter));
7313
+ function delimitedTextToMarkdownTable(text6, delimiter) {
7314
+ const rows2 = text6.split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0).map((line) => parseDelimitedLine(line, delimiter));
7156
7315
  if (rows2.length === 0) return "";
7157
7316
  const maxCols = Math.max(...rows2.map((row) => row.length));
7158
7317
  const normalized = rows2.map((row) => {
@@ -7199,7 +7358,7 @@ async function docxBufferToHtml(buffer) {
7199
7358
  const zip = await JSZip2.loadAsync(buffer);
7200
7359
  const documentXml = await zip.file("word/document.xml")?.async("string");
7201
7360
  if (!documentXml) return "";
7202
- const paragraphs = getXmlBlocks(documentXml, "p").map(getTextFromDocxParagraph).map((text5) => text5.trim()).filter(Boolean);
7361
+ const paragraphs = getXmlBlocks(documentXml, "p").map(getTextFromDocxParagraph).map((text6) => text6.trim()).filter(Boolean);
7203
7362
  return paragraphs.map((paragraph) => `<p>${escapeHtml(paragraph)}</p>`).join("\n");
7204
7363
  }
7205
7364
  function columnLettersToIndex(letters) {
@@ -8038,8 +8197,8 @@ function splitLongParagraph(paragraph) {
8038
8197
  if (remainder) chunks.push(remainder);
8039
8198
  return chunks;
8040
8199
  }
8041
- function fallback(text5, language) {
8042
- if (!language.toLowerCase().startsWith("de")) return text5;
8200
+ function fallback(text6, language) {
8201
+ if (!language.toLowerCase().startsWith("de")) return text6;
8043
8202
  const german = {
8044
8203
  "Search results are available.": "Suchergebnisse sind verf\xFCgbar.",
8045
8204
  "I used the News Search skill.": "Ich habe die News-Suche verwendet.",
@@ -8048,7 +8207,7 @@ function fallback(text5, language) {
8048
8207
  "A code example is available.": "Ein Codebeispiel ist verf\xFCgbar.",
8049
8208
  "A table is available.": "Eine Tabelle ist verf\xFCgbar."
8050
8209
  };
8051
- return german[text5] ?? text5;
8210
+ return german[text6] ?? text6;
8052
8211
  }
8053
8212
  function projectFence(markdown, language) {
8054
8213
  const body = markdown.replace(/^```[^\n]*\n|\n?```$/g, "").trim();
@@ -8130,8 +8289,8 @@ function rejectProtonCredentialFlags(argsOrFlags) {
8130
8289
  throw new Error(`${rejected.split("=")[0]} is not allowed. Bridge credentials must be read privately from Proton Bridge or a hidden prompt.`);
8131
8290
  }
8132
8291
  }
8133
- function redactProtonBridgeSecrets(text5) {
8134
- return text5.replace(CREDENTIAL_VALUE_RE, "$1<redacted>");
8292
+ function redactProtonBridgeSecrets(text6) {
8293
+ return text6.replace(CREDENTIAL_VALUE_RE, "$1<redacted>");
8135
8294
  }
8136
8295
  function containsCredentialLikeField(value) {
8137
8296
  return containsCredentialLikeKey(value);
@@ -8528,7 +8687,7 @@ async function searchProtonBridgeImap(credentials, arguments_) {
8528
8687
  const limit = clampLimit(arguments_.limit);
8529
8688
  const imap = await openTextSocket(credentials.imapHost, credentials.imapPort, IMAP_COMMAND_TIMEOUT_MS);
8530
8689
  try {
8531
- await imap.readUntil((text5) => /^\* OK/im.test(text5));
8690
+ await imap.readUntil((text6) => /^\* OK/im.test(text6));
8532
8691
  await imap.command(`LOGIN ${quoteImap(credentials.imapUsername)} ${quoteImap(credentials.imapPassword)}`);
8533
8692
  await imap.command(`SELECT ${quoteImap(mailbox)}`);
8534
8693
  const searchResponse = await imap.command(buildImapSearchCommand({ query, startDate, endDate }));
@@ -8576,22 +8735,22 @@ async function sendProtonBridgeSmtp(credentials, payload) {
8576
8735
  const messageId = `<om-${randomUUID7()}@local.openmates>`;
8577
8736
  const smtp = await openTextSocket(credentials.smtpHost, credentials.smtpPort, SMTP_COMMAND_TIMEOUT_MS);
8578
8737
  try {
8579
- await smtp.readUntil((text5) => /^220[ -]/m.test(text5));
8580
- await smtp.rawCommand("EHLO openmates.local", (text5) => /^250\s/m.test(text5), /^250[ -]/m);
8738
+ await smtp.readUntil((text6) => /^220[ -]/m.test(text6));
8739
+ await smtp.rawCommand("EHLO openmates.local", (text6) => /^250\s/m.test(text6), /^250[ -]/m);
8581
8740
  const auth = Buffer.from(`\0${credentials.smtpUsername || credentials.imapUsername}\0${credentials.smtpPassword || credentials.imapPassword}`).toString("base64");
8582
8741
  try {
8583
- await smtp.rawCommand(`AUTH PLAIN ${auth}`, (text5) => /^235[ -]/m.test(text5), /^235[ -]/m);
8742
+ await smtp.rawCommand(`AUTH PLAIN ${auth}`, (text6) => /^235[ -]/m.test(text6), /^235[ -]/m);
8584
8743
  } catch {
8585
8744
  throw new Error("Local SMTP authentication failed.");
8586
8745
  }
8587
- await smtp.rawCommand(`MAIL FROM:<${from}>`, (text5) => /^250[ -]/m.test(text5), /^250[ -]/m);
8746
+ await smtp.rawCommand(`MAIL FROM:<${from}>`, (text6) => /^250[ -]/m.test(text6), /^250[ -]/m);
8588
8747
  for (const recipient of to) {
8589
- await smtp.rawCommand(`RCPT TO:<${recipient}>`, (text5) => /^250[ -]/m.test(text5), /^250[ -]/m);
8748
+ await smtp.rawCommand(`RCPT TO:<${recipient}>`, (text6) => /^250[ -]/m.test(text6), /^250[ -]/m);
8590
8749
  }
8591
- await smtp.rawCommand("DATA", (text5) => /^354[ -]/m.test(text5), /^354[ -]/m);
8750
+ await smtp.rawCommand("DATA", (text6) => /^354[ -]/m.test(text6), /^354[ -]/m);
8592
8751
  await smtp.rawCommand(`${buildSmtpMessage({ from, to, subject, bodyText, messageId })}\r
8593
- .`, (text5) => /^250[ -]/m.test(text5), /^250[ -]/m);
8594
- await smtp.rawCommand("QUIT", (text5) => /^221[ -]/m.test(text5), /^221[ -]/m).catch(() => void 0);
8752
+ .`, (text6) => /^250[ -]/m.test(text6), /^250[ -]/m);
8753
+ await smtp.rawCommand("QUIT", (text6) => /^221[ -]/m.test(text6), /^221[ -]/m).catch(() => void 0);
8595
8754
  return { provider: PROTON_BRIDGE_PROVIDER_ID, message_id: messageId, delivered: true };
8596
8755
  } finally {
8597
8756
  smtp.close();
@@ -8703,7 +8862,7 @@ async function openTextSocket(host, port, timeoutMs) {
8703
8862
  buffer = "";
8704
8863
  socket.write(`${tag} ${command}\r
8705
8864
  `);
8706
- const response = await waitForSocketText(socket, () => buffer, (text5) => marker.test(text5), timeoutMs);
8865
+ const response = await waitForSocketText(socket, () => buffer, (text6) => marker.test(text6), timeoutMs);
8707
8866
  if (expected && !expected.test(response)) {
8708
8867
  throw new Error(`Local mail command failed: ${redactProtonBridgeSecrets(response.split(/\r?\n/).slice(-2).join(" "))}`);
8709
8868
  }
@@ -8729,8 +8888,8 @@ async function waitForSocketText(socket, getBuffer, done, timeoutMs) {
8729
8888
  return await new Promise((resolve17, reject) => {
8730
8889
  const timer = setTimeout(() => cleanup(() => reject(new Error("Timed out waiting for local mail server response."))), timeoutMs);
8731
8890
  const check = () => {
8732
- const text5 = getBuffer();
8733
- if (done(text5)) cleanup(() => resolve17(text5));
8891
+ const text6 = getBuffer();
8892
+ if (done(text6)) cleanup(() => resolve17(text6));
8734
8893
  };
8735
8894
  const onData = () => check();
8736
8895
  const onError = (error) => cleanup(() => reject(error));
@@ -8809,8 +8968,8 @@ function splitBridgeInfoSections(output) {
8809
8968
  }
8810
8969
  return sections;
8811
8970
  }
8812
- function firstValue(map, ...keys) {
8813
- for (const key of keys) {
8971
+ function firstValue(map, ...keys2) {
8972
+ for (const key of keys2) {
8814
8973
  const value = map.get(normalizeKey(key));
8815
8974
  if (value) return value;
8816
8975
  }
@@ -8907,8 +9066,8 @@ async function promptHidden(prompt) {
8907
9066
  return await new Promise((resolve17, reject) => {
8908
9067
  let value = "";
8909
9068
  const onData = (chunk) => {
8910
- const text5 = chunk.toString("utf8");
8911
- for (const char of text5) {
9069
+ const text6 = chunk.toString("utf8");
9070
+ for (const char of text6) {
8912
9071
  if (char === "") {
8913
9072
  cleanup();
8914
9073
  reject(new Error("Bridge credential prompt cancelled."));
@@ -10610,8 +10769,8 @@ var MATE_NAMES = {
10610
10769
  general_knowledge: "George",
10611
10770
  onboarding_support: "Suki"
10612
10771
  };
10613
- function stripLegacySuggestionPrefix(text5) {
10614
- return text5.replace(/^\s*\[[^\]]+\]\s*/, "").trim();
10772
+ function stripLegacySuggestionPrefix(text6) {
10773
+ return text6.replace(/^\s*\[[^\]]+\]\s*/, "").trim();
10615
10774
  }
10616
10775
  var CLOUD_API_URL = "https://api.openmates.org";
10617
10776
  var DEFAULT_API_URL = process.env.OPENMATES_API_URL ?? CLOUD_API_URL;
@@ -10672,45 +10831,13 @@ var BLOCKED_SETTINGS_MUTATE_PATHS = /* @__PURE__ */ new Set([
10672
10831
  "/v1/settings/verify-action-code",
10673
10832
  "/v1/settings/user/disable-2fa"
10674
10833
  ]);
10675
- function applyUnifiedDiffForEmbedVersion(content, patch) {
10676
- const contentLines = content.split("\n");
10677
- const lines = patch.split("\n");
10678
- const hunks = [];
10679
- let current = null;
10680
- for (const line of lines) {
10681
- const match = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
10682
- if (match) {
10683
- if (current) hunks.push(current);
10684
- current = { start: Number(match[1]) - 1, oldLines: [], newLines: [] };
10685
- continue;
10686
- }
10687
- if (!current) continue;
10688
- if (line.startsWith(" ")) {
10689
- current.oldLines.push(line.slice(1));
10690
- current.newLines.push(line.slice(1));
10691
- } else if (line.startsWith("-")) {
10692
- current.oldLines.push(line.slice(1));
10693
- } else if (line.startsWith("+")) {
10694
- current.newLines.push(line.slice(1));
10695
- }
10696
- }
10697
- if (current) hunks.push(current);
10698
- for (const hunk of hunks.sort((a, b) => b.start - a.start)) {
10699
- const actual = contentLines.slice(hunk.start, hunk.start + hunk.oldLines.length);
10700
- if (actual.join("\n") !== hunk.oldLines.join("\n")) {
10701
- throw new Error("Version patch context does not match local content");
10702
- }
10703
- contentLines.splice(hunk.start, hunk.oldLines.length, ...hunk.newLines);
10704
- }
10705
- return contentLines.join("\n");
10706
- }
10707
10834
  function buildUnifiedDiffForEmbedRestore(currentContent, restoredContent, currentVersion, newVersion) {
10708
- const currentLines = currentContent.split("\n");
10709
- const restoredLines = restoredContent.split("\n");
10835
+ const currentLines = currentContent ? currentContent.split("\n") : [];
10836
+ const restoredLines = restoredContent ? restoredContent.split("\n") : [];
10710
10837
  return [
10711
10838
  `--- v${currentVersion}`,
10712
10839
  `+++ v${newVersion}`,
10713
- `@@ -1,${Math.max(1, currentLines.length)} +1,${Math.max(1, restoredLines.length)} @@`,
10840
+ `@@ -${currentLines.length ? 1 : 0},${currentLines.length} +${restoredLines.length ? 1 : 0},${restoredLines.length} @@`,
10714
10841
  ...currentLines.map((line) => `-${line}`),
10715
10842
  ...restoredLines.map((line) => `+${line}`)
10716
10843
  ].join("\n");
@@ -11311,7 +11438,11 @@ var OpenMatesClient = class _OpenMatesClient {
11311
11438
  artifact,
11312
11439
  imported_at: Math.floor(Date.now() / 1e3)
11313
11440
  }, this.getCliRequestHeaders());
11314
- if (!response.ok) throw new Error(`Team import failed with HTTP ${response.status}`);
11441
+ if (!response.ok) {
11442
+ const detail = response.data?.detail;
11443
+ const explanation = typeof detail === "string" && detail.length <= 500 ? `: ${detail}` : "";
11444
+ throw new Error(`Team import failed with HTTP ${response.status}${explanation}`);
11445
+ }
11315
11446
  return response.data;
11316
11447
  }
11317
11448
  async updateTeamMemberRole(teamId, memberUserId, role) {
@@ -14184,7 +14315,7 @@ var OpenMatesClient = class _OpenMatesClient {
14184
14315
  historicalContent = await decryptWithAesGcmCombined(versionRow.encrypted_snapshot, embedKey);
14185
14316
  } else if (typeof versionRow.encrypted_patch === "string" && historicalContent !== null) {
14186
14317
  const patch = await decryptWithAesGcmCombined(versionRow.encrypted_patch, embedKey);
14187
- historicalContent = applyUnifiedDiffForEmbedVersion(historicalContent, patch ?? "");
14318
+ historicalContent = applyVersionPatch(historicalContent, patch ?? "");
14188
14319
  } else {
14189
14320
  throw new Error("Canonical recovery embed history lacks a starting snapshot.");
14190
14321
  }
@@ -14314,7 +14445,7 @@ var OpenMatesClient = class _OpenMatesClient {
14314
14445
  return types;
14315
14446
  };
14316
14447
  const existingTypes = await verifiedKeyTypes(keyPage.data?.embed_keys ?? []);
14317
- const keys = [
14448
+ const keys2 = [
14318
14449
  {
14319
14450
  hashed_embed_id: hashedKeySubject,
14320
14451
  key_type: "master",
@@ -14332,7 +14463,7 @@ var OpenMatesClient = class _OpenMatesClient {
14332
14463
  created_at: now
14333
14464
  }
14334
14465
  ].filter((key) => !existingTypes.has(key.key_type));
14335
- if (keys.length > 0) {
14466
+ if (keys2.length > 0) {
14336
14467
  const requestId = randomUUID9();
14337
14468
  const receipt = ws.waitForMessage("store_embed_keys_confirmed", (value) => value.request_id === requestId, 3e4);
14338
14469
  void receipt.catch(() => {
@@ -14340,10 +14471,10 @@ var OpenMatesClient = class _OpenMatesClient {
14340
14471
  await ws.sendAsync("store_embed_keys", {
14341
14472
  request_id: requestId,
14342
14473
  recovery_record_id: output.record_id,
14343
- keys
14474
+ keys: keys2
14344
14475
  });
14345
14476
  const result2 = (await receipt).payload;
14346
- if (result2.failed_count !== 0 || result2.created_count !== keys.length || result2.requested_count !== keys.length) {
14477
+ if (result2.failed_count !== 0 || result2.created_count !== keys2.length || result2.requested_count !== keys2.length) {
14347
14478
  throw new Error("Recovery embed key wrappers were not exactly confirmed.");
14348
14479
  }
14349
14480
  const durable = await this.http.get(
@@ -16034,7 +16165,7 @@ var OpenMatesClient = class _OpenMatesClient {
16034
16165
  embedKey
16035
16166
  );
16036
16167
  const encryptedTextPreview = embed.text_preview ? await encryptWithAesGcmCombined(embed.text_preview, embedKey) : void 0;
16037
- const keys = !isChild ? [
16168
+ const keys2 = !isChild ? [
16038
16169
  {
16039
16170
  hashed_embed_id: hashedEmbedId,
16040
16171
  key_type: "master",
@@ -16087,7 +16218,7 @@ var OpenMatesClient = class _OpenMatesClient {
16087
16218
  updated_at: updatedAt
16088
16219
  });
16089
16220
  await storeConfirmed;
16090
- if (keys.length > 0) {
16221
+ if (keys2.length > 0) {
16091
16222
  const keysRequestId = randomUUID9();
16092
16223
  const keysConfirmed = params.ws.waitForMessage(
16093
16224
  "store_embed_keys_confirmed",
@@ -16097,9 +16228,9 @@ var OpenMatesClient = class _OpenMatesClient {
16097
16228
  },
16098
16229
  3e4
16099
16230
  );
16100
- await params.ws.sendAsync("store_embed_keys", { request_id: keysRequestId, keys });
16231
+ await params.ws.sendAsync("store_embed_keys", { request_id: keysRequestId, keys: keys2 });
16101
16232
  const keysReceipt = (await keysConfirmed).payload;
16102
- if (keysReceipt.failed_count !== 0 || keysReceipt.created_count !== keys.length) {
16233
+ if (keysReceipt.failed_count !== 0 || keysReceipt.created_count !== keys2.length) {
16103
16234
  throw new Error(`Embed ${embed.embed_id} key wrappers were not durably stored.`);
16104
16235
  }
16105
16236
  }
@@ -17166,11 +17297,11 @@ var OpenMatesClient = class _OpenMatesClient {
17166
17297
  }
17167
17298
  return response.data.events ?? [];
17168
17299
  }
17169
- async followUpWorkflowInput(sessionId, text5) {
17300
+ async followUpWorkflowInput(sessionId, text6) {
17170
17301
  this.requireSession();
17171
17302
  const response = await this.http.post(
17172
17303
  `/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`,
17173
- { text: text5 },
17304
+ { text: text6 },
17174
17305
  this.getCliRequestHeaders()
17175
17306
  );
17176
17307
  if (!response.ok || !response.data.session) {
@@ -19539,8 +19670,12 @@ Required: ${schema.required.join(", ")}`
19539
19670
  if (!response.ok || !response.data) {
19540
19671
  throw new Error(this.formatEmbedVersionError(response.data, `Failed to load embed version ${version} (HTTP ${response.status})`));
19541
19672
  }
19542
- if (typeof response.data.content === "string" || !Array.isArray(response.data.rows)) {
19543
- return response.data;
19673
+ if (response.data.embed_id !== embedId || response.data.version_number !== version) {
19674
+ throw new Error("Version response does not match the selected version");
19675
+ }
19676
+ if (typeof response.data.content === "string") return response.data;
19677
+ if (!Array.isArray(response.data.rows) || response.data.rows.at(-1)?.version_number !== version) {
19678
+ throw new Error("Version response does not match the selected version");
19544
19679
  }
19545
19680
  const content = await this.reconstructEncryptedEmbedVersion(embedId, response.data.rows, context);
19546
19681
  if (response.data.rows.length > 32 && response.data.readonly === false) {
@@ -19693,22 +19828,7 @@ Required: ${schema.required.join(", ")}`
19693
19828
  if (!embedKey) {
19694
19829
  throw new Error("Could not resolve embed encryption key for version history.");
19695
19830
  }
19696
- const sortedRows = [...rows2].sort((a, b) => a.version_number - b.version_number);
19697
- let content = null;
19698
- for (const row of sortedRows) {
19699
- if (row.encrypted_snapshot) {
19700
- content = await decryptWithAesGcmCombined(row.encrypted_snapshot, embedKey);
19701
- continue;
19702
- }
19703
- if (row.encrypted_patch && content !== null) {
19704
- const patch = await decryptWithAesGcmCombined(row.encrypted_patch, embedKey);
19705
- content = applyUnifiedDiffForEmbedVersion(content, patch ?? "");
19706
- }
19707
- }
19708
- if (content === null) {
19709
- throw new Error("Version history is missing the initial snapshot");
19710
- }
19711
- return content;
19831
+ return reconstructVersionRows(rows2, (ciphertext) => decryptWithAesGcmCombined(ciphertext, embedKey));
19712
19832
  }
19713
19833
  async resolveVersionEmbedKey(embedId, context) {
19714
19834
  if (context?.projectId) {
@@ -20623,6 +20743,7 @@ Required: ${schema.required.join(", ")}`
20623
20743
  return {
20624
20744
  "User-Agent": this.getCliUserAgent(),
20625
20745
  "X-OpenMates-SDK": "cli",
20746
+ "X-OpenMates-Client-Capabilities": "agentic-storage-v2",
20626
20747
  "X-OpenMates-Device-Identity": this.getCliApiKeyDeviceIdentity(),
20627
20748
  Origin: deriveAppUrl(this.apiUrl)
20628
20749
  };
@@ -27727,6 +27848,7 @@ var OpenMates = class {
27727
27848
  Authorization: `Bearer ${splitApiKeyCredential(this.apiKey ?? "").bearer}`,
27728
27849
  Origin: sdkOrigin(this.apiUrl),
27729
27850
  "X-OpenMates-SDK": this.sdkName,
27851
+ "X-OpenMates-Client-Capabilities": "agentic-storage-v2",
27730
27852
  "X-OpenMates-Device-Identity": this.deviceId
27731
27853
  };
27732
27854
  if (hasBody) {
@@ -27738,6 +27860,7 @@ var OpenMates = class {
27738
27860
  return {
27739
27861
  Accept: "application/json",
27740
27862
  "X-OpenMates-SDK": this.sdkName,
27863
+ "X-OpenMates-Client-Capabilities": "agentic-storage-v2",
27741
27864
  "X-OpenMates-Device-Identity": this.deviceId
27742
27865
  };
27743
27866
  }
@@ -30806,8 +30929,8 @@ var OpenMatesWorkflows = class {
30806
30929
  const response = await this.client.get(`/v1/workflows/input/${encodeURIComponent(sessionId)}/events?after_event_id=${encodeURIComponent(String(afterEventId))}`);
30807
30930
  return response.events ?? [];
30808
30931
  }
30809
- async followUpInput(sessionId, text5) {
30810
- const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text: text5 });
30932
+ async followUpInput(sessionId, text6) {
30933
+ const response = await this.client.request(`/v1/workflows/input/${encodeURIComponent(sessionId)}/follow-up`, { text: text6 });
30811
30934
  if (!response.session) throw new OpenMatesApiError(500, { detail: "Workflow input response missing session" });
30812
30935
  return response.session;
30813
30936
  }
@@ -31131,8 +31254,8 @@ var OpenMatesEmbeds = class {
31131
31254
  }
31132
31255
  async share(embedId, options = {}) {
31133
31256
  const shown = await this.show(embedId);
31134
- const keys = Array.isArray(shown.embed_keys) ? shown.embed_keys : [];
31135
- const embedKey = await this.client.resolveEmbedKeyForShare(keys, embedId);
31257
+ const keys2 = Array.isArray(shown.embed_keys) ? shown.embed_keys : [];
31258
+ const embedKey = await this.client.resolveEmbedKeyForShare(keys2, embedId);
31136
31259
  if (!embedKey) throw new OpenMatesConfigError("Unable to resolve embed key for share link");
31137
31260
  const blob = await generateEmbedShareBlob(embedId, embedKey, options.expires ?? 0, options.password);
31138
31261
  return { url: buildEmbedShareUrl(this.client.webOrigin(), embedId, blob) };
@@ -31552,7 +31675,7 @@ import { fileURLToPath as fileURLToPath4 } from "url";
31552
31675
  import { basename as basename9, dirname as dirname17, join as join28 } from "path";
31553
31676
  import { createHash as createHash29, randomBytes as randomBytes13, randomUUID as randomUUID23 } from "crypto";
31554
31677
  import { arch as arch2, platform as platform2 } from "os";
31555
- import { parse as parseYaml2, parseDocument as parseYamlDocument, stringify as stringifyYaml } from "yaml";
31678
+ import { parse as parseYaml, parseDocument as parseYamlDocument, stringify as stringifyYaml } from "yaml";
31556
31679
 
31557
31680
  // ../workflowFile.ts
31558
31681
  var WORKFLOW_FILE_MAX_BYTES = 1048576;
@@ -31630,15 +31753,15 @@ var CREDENTIAL_SUFFIXES = [
31630
31753
  function record4(value) {
31631
31754
  return value !== null && typeof value === "object" && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
31632
31755
  }
31633
- function onlyKeys(value, keys, path2) {
31756
+ function onlyKeys(value, keys2, path2) {
31634
31757
  for (const key of Object.keys(value)) {
31635
- if (!keys.includes(key)) throw new Error(`Unsupported Workflow file field: ${path2}.${key}.`);
31758
+ if (!keys2.includes(key)) throw new Error(`Unsupported Workflow file field: ${path2}.${key}.`);
31636
31759
  }
31637
31760
  }
31638
31761
  function assertPortable(value) {
31639
31762
  let remaining = 5e4;
31640
31763
  const active = /* @__PURE__ */ new Set();
31641
- function visit(item, path2, depth) {
31764
+ function visit2(item, path2, depth) {
31642
31765
  if (--remaining < 0 || depth > 64) throw new Error("Workflow file is too complex.");
31643
31766
  if (typeof item === "number" && !Number.isFinite(item)) throw new Error("Workflow file contains an invalid number.");
31644
31767
  if (item === null || ["string", "boolean", "number"].includes(typeof item)) return;
@@ -31646,32 +31769,32 @@ function assertPortable(value) {
31646
31769
  if (active.has(item)) throw new Error("Workflow file contains a circular reference.");
31647
31770
  active.add(item);
31648
31771
  if (Array.isArray(item)) {
31649
- item.forEach((child, i) => visit(child, `${path2}[${i}]`, depth + 1));
31772
+ item.forEach((child, i) => visit2(child, `${path2}[${i}]`, depth + 1));
31650
31773
  } else {
31651
31774
  for (const [key, child] of Object.entries(item)) {
31652
31775
  const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
31653
31776
  if (["__proto__", "constructor", "prototype"].includes(key) || FORBIDDEN_KEYS.has(normalized) || CREDENTIAL_SUFFIXES.some((suffix) => normalized.endsWith(suffix))) {
31654
31777
  throw new Error(`Workflow file contains an account-specific or private field at ${path2}.${key}.`);
31655
31778
  }
31656
- visit(child, `${path2}.${key}`, depth + 1);
31779
+ visit2(child, `${path2}.${key}`, depth + 1);
31657
31780
  }
31658
31781
  }
31659
31782
  active.delete(item);
31660
31783
  }
31661
- visit(value, "$", 0);
31784
+ visit2(value, "$", 0);
31662
31785
  }
31663
31786
  function remapGraph(graph, ids) {
31664
31787
  const escaped = Array.from(ids.keys()).sort((a, b) => b.length - a.length).map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
31665
31788
  const references = escaped.length ? new RegExp(`(\\$nodes\\.|\\{\\{\\s*steps\\.|\\$items\\.|\\{\\{\\s*items\\.)(${escaped.join("|")})(?=[.}\\s]|$)`, "g") : null;
31666
- function visit(value) {
31789
+ function visit2(value) {
31667
31790
  if (typeof value === "string") return references ? value.replace(references, (_match, prefix, id) => prefix + ids.get(id)) : value;
31668
- if (Array.isArray(value)) return value.map((item) => visit(item));
31669
- if (record4(value)) return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, visit(child)]));
31791
+ if (Array.isArray(value)) return value.map((item) => visit2(item));
31792
+ if (record4(value)) return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, visit2(child)]));
31670
31793
  return value;
31671
31794
  }
31672
- const mapped = visit(graph);
31795
+ const mapped = visit2(graph);
31673
31796
  if (graph.ui_layout) mapped.ui_layout = Object.fromEntries(
31674
- Object.entries(graph.ui_layout).map(([key, child]) => [ids.get(key) ?? key, visit(child)])
31797
+ Object.entries(graph.ui_layout).map(([key, child]) => [ids.get(key) ?? key, visit2(child)])
31675
31798
  );
31676
31799
  mapped.trigger_node_id = graph.trigger_node_id ? ids.get(graph.trigger_node_id) ?? graph.trigger_node_id : null;
31677
31800
  mapped.nodes.forEach((node, i) => {
@@ -32077,27 +32200,27 @@ var SecretRegistry = class {
32077
32200
  textsToAdd.push(entry.textToHide);
32078
32201
  }
32079
32202
  if (entry.additionalTexts) {
32080
- for (const text5 of entry.additionalTexts) {
32081
- if (text5 && text5.trim().length > 0) {
32082
- textsToAdd.push(text5);
32203
+ for (const text6 of entry.additionalTexts) {
32204
+ if (text6 && text6.trim().length > 0) {
32205
+ textsToAdd.push(text6);
32083
32206
  }
32084
32207
  }
32085
32208
  }
32086
- for (const text5 of textsToAdd) {
32209
+ for (const text6 of textsToAdd) {
32087
32210
  const placeholder = entry.replaceWith.startsWith("[") ? entry.replaceWith : `[${entry.replaceWith}]`;
32088
32211
  const regEntry = {
32089
- value: text5,
32212
+ value: text6,
32090
32213
  token: placeholder,
32091
32214
  source: "settings",
32092
32215
  name: entry.id,
32093
32216
  type: "PERSONAL_DATA",
32094
- length: text5.length
32217
+ length: text6.length
32095
32218
  };
32096
- this.entries.set(text5, regEntry);
32097
- this.usedPlaceholders.set(placeholder, text5);
32098
- const lower = text5.toLowerCase();
32099
- if (lower !== text5) {
32100
- this.variantToOriginal.set(lower, text5);
32219
+ this.entries.set(text6, regEntry);
32220
+ this.usedPlaceholders.set(placeholder, text6);
32221
+ const lower = text6.toLowerCase();
32222
+ if (lower !== text6) {
32223
+ this.variantToOriginal.set(lower, text6);
32101
32224
  }
32102
32225
  }
32103
32226
  this.automaton = null;
@@ -32151,12 +32274,12 @@ var SecretRegistry = class {
32151
32274
  * @param text Text to scan
32152
32275
  * @returns Array of secret mappings for all matches found
32153
32276
  */
32154
- findAll(text5) {
32277
+ findAll(text6) {
32155
32278
  if (this.entries.size === 0) return [];
32156
32279
  if (!this.automaton) {
32157
32280
  this.buildAutomaton();
32158
32281
  }
32159
- const results = this.automaton.search(text5);
32282
+ const results = this.automaton.search(text6);
32160
32283
  const mappings = [];
32161
32284
  const coveredRanges = [];
32162
32285
  const sortedResults = [];
@@ -32361,17 +32484,17 @@ var SecretScanner = class {
32361
32484
  * @param text Text to scan and redact
32362
32485
  * @returns Object with redacted text and mappings for restoration
32363
32486
  */
32364
- redact(text5) {
32365
- if (!text5) return { redacted: text5, mappings: [] };
32487
+ redact(text6) {
32488
+ if (!text6) return { redacted: text6, mappings: [] };
32366
32489
  const allMappings = [];
32367
32490
  const coveredRanges = [];
32368
- const urlExclusionZones = getUrlExclusionZones(text5);
32369
- const identifierRanges = codingIdentifierRanges(text5);
32491
+ const urlExclusionZones = getUrlExclusionZones(text6);
32492
+ const identifierRanges = codingIdentifierRanges(text6);
32370
32493
  if (this.options.enableRegistryDetection && this.registry.size > 0) {
32371
- const registryMappings = this.registry.findAll(text5);
32494
+ const registryMappings = this.registry.findAll(text6);
32372
32495
  for (const mapping of registryMappings) {
32373
32496
  let searchFrom = 0;
32374
- const searchText = text5.toLowerCase();
32497
+ const searchText = text6.toLowerCase();
32375
32498
  const matchLower = mapping.original.toLowerCase();
32376
32499
  while (searchFrom < searchText.length) {
32377
32500
  const idx = searchText.indexOf(matchLower, searchFrom);
@@ -32387,7 +32510,7 @@ var SecretScanner = class {
32387
32510
  for (const pattern of [...SECRET_PATTERNS, ...GENERAL_PII_PATTERNS]) {
32388
32511
  pattern.regex.lastIndex = 0;
32389
32512
  let match;
32390
- while ((match = pattern.regex.exec(text5)) !== null) {
32513
+ while ((match = pattern.regex.exec(text6)) !== null) {
32391
32514
  const matchText = match[0];
32392
32515
  const startIndex = match.index;
32393
32516
  const endIndex = startIndex + matchText.length;
@@ -32418,7 +32541,7 @@ var SecretScanner = class {
32418
32541
  }
32419
32542
  }
32420
32543
  }
32421
- let redacted = text5;
32544
+ let redacted = text6;
32422
32545
  const sortedMappings = [...allMappings].sort(
32423
32546
  (a, b) => b.original.length - a.original.length
32424
32547
  );
@@ -32447,9 +32570,9 @@ var SecretScanner = class {
32447
32570
  * @param mappings Mappings from a previous redact() call
32448
32571
  * @returns Text with placeholders replaced by original values
32449
32572
  */
32450
- restore(text5, mappings) {
32451
- if (!text5 || !mappings || mappings.length === 0) return text5;
32452
- let result = text5;
32573
+ restore(text6, mappings) {
32574
+ if (!text6 || !mappings || mappings.length === 0) return text6;
32575
+ let result = text6;
32453
32576
  for (const mapping of mappings) {
32454
32577
  result = result.split(mapping.placeholder).join(mapping.original);
32455
32578
  }
@@ -32468,11 +32591,11 @@ var SecretScanner = class {
32468
32591
  function escapeRegExp2(string3) {
32469
32592
  return string3.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32470
32593
  }
32471
- function getUrlExclusionZones(text5) {
32594
+ function getUrlExclusionZones(text6) {
32472
32595
  const urlExclusionRegex = /https?:\/\/[^\s]+/g;
32473
32596
  const zones = [];
32474
32597
  let match;
32475
- while ((match = urlExclusionRegex.exec(text5)) !== null) {
32598
+ while ((match = urlExclusionRegex.exec(text6)) !== null) {
32476
32599
  zones.push({ start: match.index, end: match.index + match[0].length });
32477
32600
  }
32478
32601
  return zones;
@@ -32549,18 +32672,18 @@ var OutputRedactor = class {
32549
32672
  * @param text Text to scan
32550
32673
  * @returns Redacted text with placeholders
32551
32674
  */
32552
- redact(text5) {
32553
- return this.redactWithMappings(text5).redacted;
32675
+ redact(text6) {
32676
+ return this.redactWithMappings(text6).redacted;
32554
32677
  }
32555
32678
  /**
32556
32679
  * Redact and return both redacted text and mappings.
32557
32680
  * Used when we need to store mappings alongside message data.
32558
32681
  */
32559
- redactWithMappings(text5) {
32560
- if (!text5 || !this.initialized || !this.privacyEnabled) {
32561
- return { redacted: text5, mappings: [] };
32682
+ redactWithMappings(text6) {
32683
+ if (!text6 || !this.initialized || !this.privacyEnabled) {
32684
+ return { redacted: text6, mappings: [] };
32562
32685
  }
32563
- const result = this.scanner.redact(text5);
32686
+ const result = this.scanner.redact(text6);
32564
32687
  const excluded = result.mappings.filter((m) => this.disabledCategories.has(PII_TYPE_TO_CATEGORY[m.type] ?? ""));
32565
32688
  if (excluded.length) {
32566
32689
  result.redacted = this.scanner.restore(result.redacted, excluded);
@@ -32575,9 +32698,9 @@ var OutputRedactor = class {
32575
32698
  * Restore placeholders back to original values.
32576
32699
  * Only uses mappings from this session (never from external sources).
32577
32700
  */
32578
- restore(text5) {
32579
- if (!text5 || this.sessionMappings.size === 0) return text5;
32580
- return this.scanner.restore(text5, Array.from(this.sessionMappings.values()));
32701
+ restore(text6) {
32702
+ if (!text6 || this.sessionMappings.size === 0) return text6;
32703
+ return this.scanner.restore(text6, Array.from(this.sessionMappings.values()));
32581
32704
  }
32582
32705
  /** Mappings accumulated while preparing attachments and this message. */
32583
32706
  getMappings() {
@@ -32636,8 +32759,8 @@ function createWebsiteEmbed(url) {
32636
32759
  status: "finished"
32637
32760
  };
32638
32761
  }
32639
- function replaceUrlsInText(text5, embeds) {
32640
- return text5.replace(URL_PATTERN, (rawUrl) => {
32762
+ function replaceUrlsInText(text6, embeds) {
32763
+ return text6.replace(URL_PATTERN, (rawUrl) => {
32641
32764
  const { url, suffix } = trimTrailingUrlPunctuation(rawUrl);
32642
32765
  if (!url) return rawUrl;
32643
32766
  try {
@@ -33637,12 +33760,12 @@ function renderAudioTranscribePreview(c, ln) {
33637
33760
  const language = str(c.language) ?? "";
33638
33761
  if (duration) ln(`\x1B[2mDuration: ${duration}\x1B[0m`);
33639
33762
  if (language) ln(`\x1B[2mLanguage: ${language}\x1B[0m`);
33640
- const text5 = str(c.text) ?? str(c.transcript) ?? "";
33641
- if (text5) ln(trunc(text5, 60));
33763
+ const text6 = str(c.text) ?? str(c.transcript) ?? "";
33764
+ if (text6) ln(trunc(text6, 60));
33642
33765
  }
33643
33766
  function renderAudioTranscribeFullscreen(c) {
33644
- const text5 = str(c.text) ?? str(c.transcript) ?? "";
33645
- if (text5) console.log(text5);
33767
+ const text6 = str(c.text) ?? str(c.transcript) ?? "";
33768
+ if (text6) console.log(text6);
33646
33769
  else console.log("No transcript available.");
33647
33770
  }
33648
33771
  function renderByDirectType(embed, c, ln) {
@@ -33875,8 +33998,8 @@ function renderDirectTypeFullscreen(embed, c) {
33875
33998
 
33876
33999
  `);
33877
34000
  if (html) {
33878
- const text5 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
33879
- console.log(text5);
34001
+ const text6 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
34002
+ console.log(text6);
33880
34003
  }
33881
34004
  break;
33882
34005
  }
@@ -33887,8 +34010,8 @@ function renderDirectTypeFullscreen(embed, c) {
33887
34010
 
33888
34011
  `);
33889
34012
  if (html) {
33890
- const text5 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
33891
- console.log(text5);
34013
+ const text6 = html.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
34014
+ console.log(text6);
33892
34015
  }
33893
34016
  break;
33894
34017
  }
@@ -34039,18 +34162,18 @@ function mindMapOutline(document, maxNodes = 100) {
34039
34162
  }
34040
34163
  const lines = [];
34041
34164
  const visited = /* @__PURE__ */ new Set();
34042
- const visit = (nodeId, depth) => {
34165
+ const visit2 = (nodeId, depth) => {
34043
34166
  if (visited.size >= maxNodes || visited.has(nodeId)) return;
34044
34167
  const node = nodesById.get(nodeId);
34045
34168
  if (!node) return;
34046
34169
  visited.add(nodeId);
34047
34170
  lines.push(`${" ".repeat(depth)}- ${node.label}`);
34048
- for (const childId of node.children ?? []) visit(childId, depth + 1);
34171
+ for (const childId of node.children ?? []) visit2(childId, depth + 1);
34049
34172
  };
34050
- visit(document.rootId, 0);
34173
+ visit2(document.rootId, 0);
34051
34174
  for (const node of document.nodes) {
34052
34175
  if (visited.size >= maxNodes) break;
34053
- if (!visited.has(node.id)) visit(node.id, 0);
34176
+ if (!visited.has(node.id)) visit2(node.id, 0);
34054
34177
  }
34055
34178
  return lines.join("\n");
34056
34179
  }
@@ -34435,13 +34558,13 @@ function unsetEnvValue(content, key) {
34435
34558
  }).join("\n").replace(/\n*$/, "")}
34436
34559
  `;
34437
34560
  }
34438
- function unique(items) {
34561
+ function unique2(items) {
34439
34562
  return [...new Set(items.map((item) => item.trim()).filter(Boolean))];
34440
34563
  }
34441
34564
  function csv(value) {
34442
34565
  if (value === void 0) return [];
34443
- if (Array.isArray(value)) return unique(value.flatMap((item) => item.split(",")));
34444
- return unique(value.split(","));
34566
+ if (Array.isArray(value)) return unique2(value.flatMap((item) => item.split(",")));
34567
+ return unique2(value.split(","));
34445
34568
  }
34446
34569
  function parseServerRole(value) {
34447
34570
  if (!value) return "core";
@@ -34515,7 +34638,7 @@ function planServerRuntime(input) {
34515
34638
  const profileServices = role === "core" ? [...CORE_OBSERVABILITY_BY_PROFILE[coreProfile]] : [];
34516
34639
  if (role === "core" && input.withAlerts) profileServices.push("alertmanager");
34517
34640
  const webappServices = input.includeWebapp === false ? [] : ["webapp"];
34518
- const defaultServices = role === "core" ? unique([...definition.requiredServices, ...CORE_WORKER_SERVICES, "admin-sidecar", ...profileServices, ...webappServices]) : unique([...definition.requiredServices, ...definition.optionalServices]);
34641
+ const defaultServices = role === "core" ? unique2([...definition.requiredServices, ...CORE_WORKER_SERVICES, "admin-sidecar", ...profileServices, ...webappServices]) : unique2([...definition.requiredServices, ...definition.optionalServices]);
34519
34642
  return {
34520
34643
  role,
34521
34644
  profile,
@@ -34803,7 +34926,7 @@ function planRuntimeMonitoringServices(input) {
34803
34926
  "",
34804
34927
  "[Timer]",
34805
34928
  "OnBootSec=2min",
34806
- "OnUnitActiveSec=5min",
34929
+ "OnUnitActiveSec=1min",
34807
34930
  "Persistent=true",
34808
34931
  `Unit=${serviceName}`,
34809
34932
  "",
@@ -34863,6 +34986,60 @@ function validateServerEnvironmentTarget(command, environment) {
34863
34986
  throw new Error("Unknown server environment target; use shared-dev for explicit server administration.");
34864
34987
  }
34865
34988
 
34989
+ // src/serverStorageMigration.ts
34990
+ function parseStorageMigrationOutcome(value) {
34991
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
34992
+ return { status: "paused", reason: "migration_coordinator_response_invalid" };
34993
+ }
34994
+ const row = value;
34995
+ if (!["pending", "paused", "reader_enabled", "prune_enabled", "not_applicable"].includes(String(row.status))) {
34996
+ return { status: "paused", reason: "migration_coordinator_response_invalid" };
34997
+ }
34998
+ const result = { status: row.status };
34999
+ if (typeof row.reason === "string" && /^[a-z_]{1,80}$/.test(row.reason)) result.reason = row.reason;
35000
+ if (typeof row.source_commit === "string" && /^[a-f0-9]{40}$/.test(row.source_commit)) result.source_commit = row.source_commit;
35001
+ if (Number.isInteger(row.retry_seconds) && Number(row.retry_seconds) > 0 && Number(row.retry_seconds) <= 86400) {
35002
+ result.retry_seconds = Number(row.retry_seconds);
35003
+ }
35004
+ return result;
35005
+ }
35006
+ function parseStorageMigrationProgress(value) {
35007
+ const row = value && typeof value === "object" && !Array.isArray(value) ? value : {};
35008
+ const result = { automatic: parseStorageMigrationOutcome(row.automatic) };
35009
+ if (row.legacy_full_graph !== void 0) result.legacy_full_graph = parseStorageMigrationOutcome(row.legacy_full_graph);
35010
+ const fields = {
35011
+ message_segments: ["copying", "verified", "reader_active"],
35012
+ message_pages: ["read_enabled", "pruned"],
35013
+ version_rows: ["copied", "reader_active", "pruned", "stale"]
35014
+ };
35015
+ for (const [name, names] of Object.entries(fields)) {
35016
+ const counts = row[name];
35017
+ if (!counts || typeof counts !== "object" || Array.isArray(counts)) continue;
35018
+ const selected = {};
35019
+ for (const key of names) {
35020
+ const count = counts[key];
35021
+ if (typeof count === "number" && Number.isSafeInteger(count) && count >= 0) selected[key] = count;
35022
+ }
35023
+ result[name] = selected;
35024
+ }
35025
+ return result;
35026
+ }
35027
+ function storageMigrationCommand(composePrefix, operation, sourceRevision) {
35028
+ if (sourceRevision !== void 0 && !/^[a-f0-9]{40}$/i.test(sourceRevision)) {
35029
+ throw new Error("source_revision_unavailable");
35030
+ }
35031
+ return [
35032
+ ...composePrefix,
35033
+ "exec",
35034
+ "-T",
35035
+ ...sourceRevision ? ["-e", `BUILD_COMMIT_SHA=${sourceRevision.toLowerCase()}`] : [],
35036
+ "api",
35037
+ "python",
35038
+ "/app/scripts/storage_rollout.py",
35039
+ operation
35040
+ ];
35041
+ }
35042
+
34866
35043
  // src/serverBackupArchive.ts
34867
35044
  import { execFileSync as execFileSync2 } from "child_process";
34868
35045
  import { chmodSync as chmodSync4, lstatSync as lstatSync2, readdirSync as readdirSync4, renameSync as renameSync3, rmSync as rmSync4 } from "fs";
@@ -34898,7 +35075,7 @@ import { createHash as createHash16 } from "crypto";
34898
35075
  import { accessSync, constants as constants2, existsSync as existsSync9, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync10, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
34899
35076
  import { tmpdir } from "os";
34900
35077
  import { dirname as dirname7, join as join12 } from "path";
34901
- var hash2 = (text5) => createHash16("sha256").update(text5).digest("hex");
35078
+ var hash2 = (text6) => createHash16("sha256").update(text6).digest("hex");
34902
35079
  function resolveCaddyProfile(role, explicit, previous) {
34903
35080
  if (explicit === void 0) return previous ?? "self-host";
34904
35081
  if (role !== "upload" || explicit !== "official-upload") throw new Error("caddy_profile_unsupported");
@@ -37301,6 +37478,100 @@ function sourceUpdateMetadata(installPath) {
37301
37478
  }
37302
37479
  };
37303
37480
  }
37481
+ function runAutomaticStorageMigration(installPath, role, installMode, withOverrides) {
37482
+ if (role !== "core") return { status: "not_applicable" };
37483
+ if (!shouldAutoInstallRuntimeMonitoringServices(process.env)) {
37484
+ return { status: "paused", reason: "inventory_refresh_service_disabled", retry_seconds: 60 };
37485
+ }
37486
+ if (!refreshStorageRuntimeInventory(installPath, role, installMode, withOverrides)) {
37487
+ return { status: "paused", reason: "runtime_inventory_refresh_unavailable", retry_seconds: 60 };
37488
+ }
37489
+ let sourceRevision;
37490
+ if (installMode === "source") {
37491
+ if (exec("git status --porcelain", installPath).trim()) {
37492
+ return { status: "pending", reason: "source_worktree_unverified" };
37493
+ }
37494
+ const revision = exec("git rev-parse HEAD", installPath).trim();
37495
+ if (!/^[a-f0-9]{40}$/i.test(revision)) {
37496
+ return { status: "pending", reason: "source_revision_unavailable" };
37497
+ }
37498
+ sourceRevision = revision;
37499
+ }
37500
+ const args = storageMigrationCommand(composeArgs(installPath, withOverrides, installMode, role), "auto", sourceRevision);
37501
+ const result = spawnSync("docker", args, {
37502
+ cwd: installPath,
37503
+ encoding: "utf8",
37504
+ timeout: 45e3,
37505
+ stdio: ["ignore", "pipe", "pipe"],
37506
+ maxBuffer: 64 * 1024
37507
+ });
37508
+ if (result.error || result.status !== 0) {
37509
+ return { status: "paused", reason: "migration_coordinator_unavailable" };
37510
+ }
37511
+ try {
37512
+ return parseStorageMigrationOutcome(JSON.parse(result.stdout.trim()));
37513
+ } catch {
37514
+ }
37515
+ return { status: "paused", reason: "migration_coordinator_response_invalid" };
37516
+ }
37517
+ function refreshStorageRuntimeInventory(installPath, role, installMode, withOverrides) {
37518
+ if (role !== "core") return true;
37519
+ if (installMode === "source" && exec("git status --porcelain", installPath).trim()) return false;
37520
+ try {
37521
+ const containers = execFileSync4(
37522
+ "docker",
37523
+ [...composeArgs(installPath, withOverrides, installMode, role), "ps", "--all", "-q", "api"],
37524
+ { cwd: installPath, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 15e3 }
37525
+ ).trim().split(/\s+/).filter(Boolean);
37526
+ if (containers.length < 1 || containers.length > 128 || new Set(containers).size !== containers.length || containers.some((id) => !/^[a-f0-9]{12,64}$/.test(id))) return false;
37527
+ const cohort = [];
37528
+ for (const container of containers) {
37529
+ const output = execFileSync4(
37530
+ "docker",
37531
+ ["exec", container, "python", "/app/scripts/storage_runtime_inventory.py", "inspect"],
37532
+ { cwd: installPath, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 15e3, maxBuffer: 64 * 1024 }
37533
+ );
37534
+ cohort.push(JSON.parse(output.trim()));
37535
+ }
37536
+ const result = spawnSync(
37537
+ "docker",
37538
+ ["exec", "-i", containers[0], "python", "/app/scripts/storage_runtime_inventory.py", "publish"],
37539
+ {
37540
+ cwd: installPath,
37541
+ encoding: "utf8",
37542
+ input: JSON.stringify(cohort),
37543
+ timeout: 45e3,
37544
+ stdio: ["pipe", "pipe", "pipe"],
37545
+ maxBuffer: 64 * 1024
37546
+ }
37547
+ );
37548
+ if (result.error || result.status !== 0) return false;
37549
+ const published = JSON.parse(result.stdout.trim());
37550
+ return published.status === "published";
37551
+ } catch {
37552
+ return false;
37553
+ }
37554
+ }
37555
+ function readStorageMigrationProgress(installPath, role, installMode, withOverrides) {
37556
+ if (role !== "core") return { automatic: { status: "not_applicable" } };
37557
+ const result = spawnSync("docker", storageMigrationCommand(
37558
+ composeArgs(installPath, withOverrides, installMode, role),
37559
+ "status"
37560
+ ), {
37561
+ cwd: installPath,
37562
+ encoding: "utf8",
37563
+ timeout: 45e3,
37564
+ stdio: ["ignore", "pipe", "pipe"],
37565
+ maxBuffer: 64 * 1024
37566
+ });
37567
+ if (!result.error && result.status === 0) {
37568
+ try {
37569
+ return parseStorageMigrationProgress(JSON.parse(result.stdout.trim()));
37570
+ } catch {
37571
+ }
37572
+ }
37573
+ return { automatic: { status: "paused", reason: "migration_coordinator_unavailable", retry_seconds: 60 } };
37574
+ }
37304
37575
  function copyIfExists(source, destination) {
37305
37576
  if (!existsSync11(source)) return;
37306
37577
  mkdirSync12(dirname9(destination), { recursive: true });
@@ -37810,8 +38081,31 @@ async function serverStatus(flags) {
37810
38081
  args.push("--format", "json");
37811
38082
  }
37812
38083
  if (selection.requested) args.push(...selection.services);
38084
+ if (flags.json === true) {
38085
+ const output = execFileSync4("docker", args, { cwd: installPath, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
38086
+ const containers = [];
38087
+ if (output) {
38088
+ if (output.startsWith("[")) containers.push(...JSON.parse(output));
38089
+ else for (const line of output.split("\n")) containers.push(JSON.parse(line));
38090
+ }
38091
+ printJson({
38092
+ command: "status",
38093
+ path: installPath,
38094
+ role,
38095
+ containers,
38096
+ storageMigration: readStorageMigrationProgress(installPath, role, getInstallMode(installPath, config), withOverrides)
38097
+ });
38098
+ return;
38099
+ }
37813
38100
  const code = await runInteractive("docker", args, installPath);
37814
38101
  if (code !== 0) process.exit(code);
38102
+ const migration = readStorageMigrationProgress(installPath, role, getInstallMode(installPath, config), withOverrides);
38103
+ const outcome = migration.automatic;
38104
+ console.log(`Storage migration: ${outcome.status}${outcome.reason ? ` (${outcome.reason})` : ""}${outcome.retry_seconds ? `; retry in ${outcome.retry_seconds}s` : ""}`);
38105
+ if (migration.legacy_full_graph) console.log(`Legacy full graph migration: ${migration.legacy_full_graph.status} (${migration.legacy_full_graph.reason ?? "policy_pending"})`);
38106
+ if (migration.message_segments) console.log(`Message segments: ${JSON.stringify(migration.message_segments)}`);
38107
+ if (migration.message_pages) console.log(`Message pages: ${JSON.stringify(migration.message_pages)}`);
38108
+ if (migration.version_rows) console.log(`Version rows: ${JSON.stringify(migration.version_rows)}`);
37815
38109
  }
37816
38110
  async function serverStart(flags) {
37817
38111
  requireDocker();
@@ -38485,6 +38779,8 @@ async function installRuntimeMonitoringServices(installPath, role) {
38485
38779
  execSync("systemctl daemon-reload", { stdio: "pipe" });
38486
38780
  const timers = files.filter(([name]) => name.endsWith(".timer")).map(([name]) => name);
38487
38781
  execSync(`systemctl enable --now ${timers.map(shellQuote).join(" ")}`, { stdio: "pipe" });
38782
+ execFileSync4("systemctl", ["restart", plan.timerName], { stdio: "pipe" });
38783
+ execFileSync4("systemctl", ["--no-block", "try-restart", plan.serviceName], { stdio: "pipe" });
38488
38784
  for (const timer of timers) execFileSync4("systemctl", ["is-active", "--quiet", timer], { stdio: "pipe" });
38489
38785
  }
38490
38786
  async function autoInstallRuntimeMonitoringServices(installPath, role) {
@@ -38856,6 +39152,8 @@ async function serverUpdate(client2, rest, flags) {
38856
39152
  await runInteractive("docker", [...composeArgs(installPath, withOverrides, installMode, role), "ps"], installPath);
38857
39153
  throw error;
38858
39154
  }
39155
+ const automaticStorageMigration2 = runAutomaticStorageMigration(installPath, role, installMode, withOverrides);
39156
+ console.error(`Storage migration: ${automaticStorageMigration2.status}${automaticStorageMigration2.reason ? ` (${automaticStorageMigration2.reason})` : ""}`);
38859
39157
  if (config) {
38860
39158
  saveServerConfig({ ...config, imageTag: target.tag, imageChannel: target.channel });
38861
39159
  }
@@ -38893,6 +39191,7 @@ async function serverUpdate(client2, rest, flags) {
38893
39191
  checks: successfulRuntimeOutput2?.checks ?? [],
38894
39192
  runtimeCompletedAt: successfulRuntimeOutput2?.completed_at,
38895
39193
  quickTest: quickTest2,
39194
+ automaticStorageMigration: automaticStorageMigration2,
38896
39195
  completionEmailDelivery: completion3.delivery
38897
39196
  });
38898
39197
  if (flags.json === true) {
@@ -38922,6 +39221,7 @@ async function serverUpdate(client2, rest, flags) {
38922
39221
  checks: successfulRuntimeOutput2?.checks ?? [],
38923
39222
  runtimeCompletedAt: successfulRuntimeOutput2?.completed_at,
38924
39223
  quickTest: quickTest2,
39224
+ automaticStorageMigration: automaticStorageMigration2,
38925
39225
  completionEmailDelivery: completion2.delivery,
38926
39226
  completionEmailDeliveryId: completion2.deliveryId,
38927
39227
  completionEmailPendingAt: completion2.deliveryPendingAt,
@@ -38937,6 +39237,7 @@ async function serverUpdate(client2, rest, flags) {
38937
39237
  runtimeVerification: successfulRuntimeOutput2,
38938
39238
  caddy: caddy2,
38939
39239
  quickTest: quickTest2,
39240
+ automaticStorageMigration: automaticStorageMigration2,
38940
39241
  completionEmailDelivery: completion2.delivery,
38941
39242
  completedAt: completion2.completedAt
38942
39243
  });
@@ -39001,8 +39302,16 @@ async function serverUpdate(client2, rest, flags) {
39001
39302
  );
39002
39303
  }
39003
39304
  }
39305
+ let sourceBuildRevision = "";
39306
+ try {
39307
+ if (!exec("git status --porcelain", installPath).trim()) {
39308
+ const revision = exec("git rev-parse HEAD", installPath).trim();
39309
+ if (/^[a-f0-9]{40}$/i.test(revision)) sourceBuildRevision = revision.toLowerCase();
39310
+ }
39311
+ } catch {
39312
+ }
39004
39313
  const buildArgs = appendSelectedServices(
39005
- [...composeArgs(installPath, withOverrides, installMode, role), "build"],
39314
+ [...composeArgs(installPath, withOverrides, installMode, role), "build", "--build-arg", `BUILD_COMMIT_SHA=${sourceBuildRevision}`],
39006
39315
  coreSetupPlan.pullOrBuildServices,
39007
39316
  filterRequested
39008
39317
  );
@@ -39069,6 +39378,8 @@ async function serverUpdate(client2, rest, flags) {
39069
39378
  await runInteractive("docker", [...composeArgs(installPath, withOverrides, installMode, role), "ps"], installPath);
39070
39379
  throw error;
39071
39380
  }
39381
+ const automaticStorageMigration = runAutomaticStorageMigration(installPath, role, installMode, withOverrides);
39382
+ console.error(`Storage migration: ${automaticStorageMigration.status}${automaticStorageMigration.reason ? ` (${automaticStorageMigration.reason})` : ""}`);
39072
39383
  try {
39073
39384
  await autoInstallRuntimeMonitoringServices(installPath, role);
39074
39385
  } catch (error) {
@@ -39095,6 +39406,7 @@ async function serverUpdate(client2, rest, flags) {
39095
39406
  checks: successfulRuntimeOutput?.checks ?? [],
39096
39407
  runtimeCompletedAt: successfulRuntimeOutput?.completed_at,
39097
39408
  quickTest,
39409
+ automaticStorageMigration,
39098
39410
  completionEmailDelivery: completion2.delivery
39099
39411
  });
39100
39412
  if (flags.json === true) {
@@ -39122,6 +39434,7 @@ async function serverUpdate(client2, rest, flags) {
39122
39434
  checks: successfulRuntimeOutput?.checks ?? [],
39123
39435
  runtimeCompletedAt: successfulRuntimeOutput?.completed_at,
39124
39436
  quickTest,
39437
+ automaticStorageMigration,
39125
39438
  completionEmailDelivery: completion.delivery,
39126
39439
  completionEmailDeliveryId: completion.deliveryId,
39127
39440
  completionEmailPendingAt: completion.deliveryPendingAt,
@@ -39138,6 +39451,7 @@ async function serverUpdate(client2, rest, flags) {
39138
39451
  runtimeVerification: successfulRuntimeOutput,
39139
39452
  caddy,
39140
39453
  quickTest,
39454
+ automaticStorageMigration,
39141
39455
  completionEmailDelivery: completion.delivery,
39142
39456
  completedAt: completion.completedAt
39143
39457
  });
@@ -39294,7 +39608,23 @@ async function serverMonitoring(rest, flags) {
39294
39608
  let output;
39295
39609
  try {
39296
39610
  requireDocker();
39611
+ const inventoryRefreshed = refreshStorageRuntimeInventory(
39612
+ installPath,
39613
+ role,
39614
+ getInstallMode(installPath, config),
39615
+ config?.composeProfile === "full"
39616
+ );
39297
39617
  output = runRuntimeVerification(installPath, role, config);
39618
+ if (!inventoryRefreshed) {
39619
+ output.checks.push({
39620
+ id: "core.storage_migration_inventory",
39621
+ status: "failed",
39622
+ required: false,
39623
+ duration_ms: 0,
39624
+ failureClass: "configuration",
39625
+ sanitized_reason: "runtime_inventory_refresh_unavailable"
39626
+ });
39627
+ }
39298
39628
  } catch (error) {
39299
39629
  console.error(`Runtime verifier unavailable: ${error instanceof Error ? error.name : "UnknownError"}`);
39300
39630
  output = {
@@ -40016,8 +40346,8 @@ ${entry.category}:`);
40016
40346
  if (action === "edit") {
40017
40347
  const category = rest[1];
40018
40348
  if (category) {
40019
- const keys = entries.filter((entry) => entry.category === category).map((entry) => entry.key);
40020
- console.error(keys.length ? `Focused ${category} keys: ${keys.join(", ")}` : `No existing ${category} keys found; opening canonical .env.`);
40349
+ const keys2 = entries.filter((entry) => entry.category === category).map((entry) => entry.key);
40350
+ console.error(keys2.length ? `Focused ${category} keys: ${keys2.join(", ")}` : `No existing ${category} keys found; opening canonical .env.`);
40021
40351
  }
40022
40352
  const backupPath = backupEnvFile(installPath);
40023
40353
  if (backupPath) console.error(`Backup: ${backupPath}`);
@@ -40327,10 +40657,10 @@ async function buildCodeRunRequestsFromFlags(flags) {
40327
40657
  for (const url of toList(flags.url)) {
40328
40658
  const response = await fetch(url);
40329
40659
  if (!response.ok) throw new Error(`Failed to download Code Run URL ${redactUrl(url)} (HTTP ${response.status})`);
40330
- const text5 = await response.text();
40660
+ const text6 = await response.text();
40331
40661
  const urlPath = new URL(url).pathname;
40332
40662
  const sandboxPath = normalizeCodeRunPath(entry || basename3(urlPath) || "main.txt");
40333
- const buffer = Buffer.from(text5, "utf8");
40663
+ const buffer = Buffer.from(text6, "utf8");
40334
40664
  addFile({
40335
40665
  path: sandboxPath,
40336
40666
  content_base64: buffer.toString("base64"),
@@ -40340,9 +40670,9 @@ async function buildCodeRunRequestsFromFlags(flags) {
40340
40670
  }, buffer.byteLength);
40341
40671
  }
40342
40672
  if (flags.repo) {
40343
- await addGithubRepoFiles(flags.repo, toList(flags.include), async (path2, text5) => {
40673
+ await addGithubRepoFiles(flags.repo, toList(flags.include), async (path2, text6) => {
40344
40674
  const sandboxPath = normalizeCodeRunPath(path2);
40345
- const buffer = Buffer.from(text5, "utf8");
40675
+ const buffer = Buffer.from(text6, "utf8");
40346
40676
  addFile({
40347
40677
  path: sandboxPath,
40348
40678
  content_base64: buffer.toString("base64"),
@@ -57970,8 +58300,8 @@ function decodeEmbedContent(content) {
57970
58300
  }
57971
58301
  return parseFlatToonFields(content);
57972
58302
  }
57973
- function stringField3(record8, keys) {
57974
- for (const key of keys) {
58303
+ function stringField3(record8, keys2) {
58304
+ for (const key of keys2) {
57975
58305
  const value = cleanString(record8[key]);
57976
58306
  if (value) return value;
57977
58307
  }
@@ -84359,8 +84689,8 @@ function parseSuites(value) {
84359
84689
  const suites = value.split(",").map((suite) => suite.trim()).filter(Boolean);
84360
84690
  if (suites.includes("all")) return ["quick", "extensive"];
84361
84691
  const allowed = /* @__PURE__ */ new Set(["quick", "extensive"]);
84362
- const invalid = suites.filter((suite) => !allowed.has(suite));
84363
- if (invalid.length > 0 || suites.length === 0) {
84692
+ const invalid2 = suites.filter((suite) => !allowed.has(suite));
84693
+ if (invalid2.length > 0 || suites.length === 0) {
84364
84694
  throw new Error("Invalid --suite. Use quick, extensive, or all.");
84365
84695
  }
84366
84696
  return [...new Set(suites)];
@@ -84933,13 +85263,13 @@ function parseJudgment(answer) {
84933
85263
  return { score: null, reason: null };
84934
85264
  }
84935
85265
  }
84936
- function extractJsonObject(text5) {
84937
- const fenced = text5.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
85266
+ function extractJsonObject(text6) {
85267
+ const fenced = text6.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
84938
85268
  if (fenced) return fenced[1];
84939
- const start = text5.indexOf("{");
84940
- const end = text5.lastIndexOf("}");
85269
+ const start = text6.indexOf("{");
85270
+ const end = text6.lastIndexOf("}");
84941
85271
  if (start === -1 || end === -1 || end <= start) return null;
84942
- return text5.slice(start, end + 1);
85272
+ return text6.slice(start, end + 1);
84943
85273
  }
84944
85274
  function loadPricingForModels(models) {
84945
85275
  const availablePricing = loadProviderPricing();
@@ -84968,21 +85298,21 @@ function loadProviderPricing() {
84968
85298
  for (const fileName of readdirSync6(providersDir)) {
84969
85299
  if (!fileName.endsWith(".yml")) continue;
84970
85300
  const filePath = join16(providersDir, fileName);
84971
- const text5 = readFileSync13(filePath, "utf-8");
84972
- const provider = parseProviderId(text5) ?? fileName.replace(/\.yml$/, "");
84973
- for (const modelPricing of parseModelPricing(text5, provider)) {
85301
+ const text6 = readFileSync13(filePath, "utf-8");
85302
+ const provider = parseProviderId(text6) ?? fileName.replace(/\.yml$/, "");
85303
+ for (const modelPricing of parseModelPricing(text6, provider)) {
84974
85304
  pricing.set(`${modelPricing.provider}/${modelPricing.modelId}`, modelPricing);
84975
85305
  pricing.set(modelPricing.modelId, modelPricing);
84976
85306
  }
84977
85307
  }
84978
85308
  return pricing;
84979
85309
  }
84980
- function parseProviderId(text5) {
84981
- const match = text5.match(/^provider_id:\s*["']?([^"'\n]+)["']?/m);
85310
+ function parseProviderId(text6) {
85311
+ const match = text6.match(/^provider_id:\s*["']?([^"'\n]+)["']?/m);
84982
85312
  return match?.[1]?.trim() ?? null;
84983
85313
  }
84984
- function parseModelPricing(text5, provider) {
84985
- const lines = text5.split("\n");
85314
+ function parseModelPricing(text6, provider) {
85315
+ const lines = text6.split("\n");
84986
85316
  const results = [];
84987
85317
  let modelId = null;
84988
85318
  let inModel = false;
@@ -85544,10 +85874,10 @@ var TuiTerminal = class {
85544
85874
  const tail = rows2.length < this.height ? `\x1B[${rows2.length + 1};1H\x1B[J` : "";
85545
85875
  this.output.write(`\x1B[?2026h${body}${tail}\x1B[?2026l`);
85546
85876
  }
85547
- receiveInput(text5) {
85877
+ receiveInput(text6) {
85548
85878
  if (this.inputTimer) clearTimeout(this.inputTimer);
85549
85879
  this.inputTimer = null;
85550
- this.pendingInput += text5;
85880
+ this.pendingInput += text6;
85551
85881
  const marker = this.paste ? "\x1B[201~" : "\x1B[200~";
85552
85882
  const found = this.pendingInput.indexOf(marker);
85553
85883
  if (found >= 0) {
@@ -85575,10 +85905,10 @@ var TuiTerminal = class {
85575
85905
  }, 30);
85576
85906
  }
85577
85907
  /** Consume SGR mouse reports without letting clicks become composer text. */
85578
- dispatchInput(text5) {
85908
+ dispatchInput(text6) {
85579
85909
  if (this.mouseTimer) clearTimeout(this.mouseTimer);
85580
85910
  this.mouseTimer = null;
85581
- const input = this.pendingMouse + text5;
85911
+ const input = this.pendingMouse + text6;
85582
85912
  this.pendingMouse = "";
85583
85913
  let offset = 0;
85584
85914
  while (offset < input.length) {
@@ -85977,25 +86307,25 @@ function wrapCells(value, width) {
85977
86307
  width = Math.max(1, width);
85978
86308
  const result = [];
85979
86309
  for (const line of terminalText(value).split("\n")) {
85980
- let text5 = "", used = 0;
86310
+ let text6 = "", used = 0;
85981
86311
  for (const { segment } of segments.segment(line)) {
85982
86312
  const size = graphemeWidth(segment);
85983
86313
  if (size > width) {
85984
- if (text5) result.push(text5);
86314
+ if (text6) result.push(text6);
85985
86315
  result.push("?");
85986
- text5 = "";
86316
+ text6 = "";
85987
86317
  used = 0;
85988
86318
  continue;
85989
86319
  }
85990
86320
  if (used + size > width) {
85991
- result.push(text5);
85992
- text5 = "";
86321
+ result.push(text6);
86322
+ text6 = "";
85993
86323
  used = 0;
85994
86324
  }
85995
- text5 += segment;
86325
+ text6 += segment;
85996
86326
  used += size;
85997
86327
  }
85998
- result.push(text5);
86328
+ result.push(text6);
85999
86329
  }
86000
86330
  return result;
86001
86331
  }
@@ -86649,8 +86979,8 @@ var NODE_FIELDS = {
86649
86979
  custom_code: ["code"]
86650
86980
  };
86651
86981
  function compact(value, max = 80) {
86652
- const text5 = typeof value === "string" ? value : Array.isArray(value) ? value.map((item) => compact(item, max)).join(", ") : value && typeof value === "object" ? Object.entries(value).map(([key, item]) => `${key.replaceAll("_", " ")}: ${compact(item, max)}`).join(" \xB7 ") : String(value);
86653
- const oneLine3 = text5.replace(/\s+/g, " ");
86982
+ const text6 = typeof value === "string" ? value : Array.isArray(value) ? value.map((item) => compact(item, max)).join(", ") : value && typeof value === "object" ? Object.entries(value).map(([key, item]) => `${key.replaceAll("_", " ")}: ${compact(item, max)}`).join(" \xB7 ") : String(value);
86983
+ const oneLine3 = text6.replace(/\s+/g, " ");
86654
86984
  return truncateCells(oneLine3, max);
86655
86985
  }
86656
86986
  function label2(node) {
@@ -86845,7 +87175,7 @@ function buildWorkflowNodeForm(workflow, node, kind = "workflow-node") {
86845
87175
  }
86846
87176
  return [key];
86847
87177
  });
86848
- const keys = [.../* @__PURE__ */ new Set([...schemaKeys, ...currentKeys])];
87178
+ const keys2 = [.../* @__PURE__ */ new Set([...schemaKeys, ...currentKeys])];
86849
87179
  return {
86850
87180
  kind,
86851
87181
  title: `Edit ${label2(node)}`,
@@ -86853,7 +87183,7 @@ function buildWorkflowNodeForm(workflow, node, kind = "workflow-node") {
86853
87183
  fieldIndex: 0,
86854
87184
  fields: [
86855
87185
  { name: "title", label: "Node title", value: node.title ?? "" },
86856
- ...keys.map((key) => {
87186
+ ...keys2.map((key) => {
86857
87187
  const value = valueAt(config, key);
86858
87188
  return { name: `config.${key}`, label: key.replaceAll("_", " "), value: fieldValue(value), multiline: typeof value === "object" || /(?:message|body|prompt|code)$/i.test(key) };
86859
87189
  })
@@ -87218,8 +87548,8 @@ function tuiChatSidebarRows(state) {
87218
87548
  group.push(chat);
87219
87549
  groups2.set(key, group);
87220
87550
  }
87221
- const keys = [...CHAT_TIME_GROUPS.filter((key) => groups2.has(key)), ...[...groups2.keys()].filter((key) => !CHAT_TIME_GROUPS.some((standard) => standard === key))];
87222
- for (const key of keys) {
87551
+ const keys2 = [...CHAT_TIME_GROUPS.filter((key) => groups2.has(key)), ...[...groups2.keys()].filter((key) => !CHAT_TIME_GROUPS.some((standard) => standard === key))];
87552
+ for (const key of keys2) {
87223
87553
  const label3 = { today: "Today", yesterday: "Yesterday", previous_7_days: "Previous 7 days", previous_30_days: "Previous 30 days" }[key] ?? new Date(Number(key.split("_")[1]), Number(key.split("_")[2]) - 1).toLocaleDateString("en", { month: "long", year: "numeric" });
87224
87554
  rows2.push({ kind: "section", label: label3 });
87225
87555
  rows2.push(...groups2.get(key).map((chat) => ({
@@ -87413,7 +87743,7 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
87413
87743
  const title = state.activeChat?.title && state.workspace === "chats" ? ` \xB7 ${state.activeChat.title}` : "";
87414
87744
  const nav = contentWidth >= 90 ? `OpenMates ${labels}${title}` : `OpenMates [${titleCase(state.workspace)}] ${state.sidebarOpen ? "Sidebar open" : "Ctrl+B sidebar"}${title}`;
87415
87745
  const inputWidth = Math.max(1, contentWidth - 6);
87416
- const inputLines = state.input.split("\n").flatMap((text5) => wrapCells(text5, inputWidth));
87746
+ const inputLines = state.input.split("\n").flatMap((text6) => wrapCells(text6, inputWidth));
87417
87747
  const showComposer = state.workspace !== "apps" || state.focus === "composer" || Boolean(state.input);
87418
87748
  const composerRows = showComposer ? Math.min(3, Math.max(1, inputLines.length)) : 0;
87419
87749
  const bodyHeight = Math.max(1, height - 2 - (showComposer ? composerRows + 3 : 1));
@@ -87468,8 +87798,8 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
87468
87798
  let remaining = span;
87469
87799
  rendered = "";
87470
87800
  for (const part of style.spans) {
87471
- const text5 = truncateCells(terminalText(part.text).replace(/\n/g, " "), remaining), size = cells(text5);
87472
- rendered += part.background ? backgroundLine(text5, size, part.background, mode, part.bold) : text5;
87801
+ const text6 = truncateCells(terminalText(part.text).replace(/\n/g, " "), remaining), size = cells(text6);
87802
+ rendered += part.background ? backgroundLine(text6, size, part.background, mode, part.bold) : text6;
87473
87803
  remaining -= size;
87474
87804
  if (!remaining) break;
87475
87805
  }
@@ -87486,12 +87816,12 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
87486
87816
  const hintColor = state.focus === "composer" ? "#a0a0a0" : "#ff553b";
87487
87817
  const composer = [];
87488
87818
  if (showComposer) {
87489
- const inputRows = inputLines.slice(-composerRows).map((text5, i) => `${i ? " " : "> "}${text5 || (!state.input ? placeholder : "")}`);
87490
- if (contentWidth < 6) composer.push(...inputRows.map((text5) => place(padCells(text5, contentWidth))), place(foreground(padCells(hint, contentWidth), hintColor, mode)), place(" ".repeat(contentWidth)), place(" ".repeat(contentWidth)));
87819
+ const inputRows = inputLines.slice(-composerRows).map((text6, i) => `${i ? " " : "> "}${text6 || (!state.input ? placeholder : "")}`);
87820
+ if (contentWidth < 6) composer.push(...inputRows.map((text6) => place(padCells(text6, contentWidth))), place(foreground(padCells(hint, contentWidth), hintColor, mode)), place(" ".repeat(contentWidth)), place(" ".repeat(contentWidth)));
87491
87821
  else {
87492
87822
  const edge = (left, right) => place(foreground(left + line.repeat(contentWidth - 2) + right, "#6b6b6b", mode));
87493
- const inputRow = (text5, color) => place(foreground(vertical, "#6b6b6b", mode) + " " + foreground(padCells(text5, contentWidth - 4), color ?? "#e6e6e6", mode) + " " + foreground(vertical, "#6b6b6b", mode));
87494
- composer.push(edge(ascii ? "+" : "\u256D", ascii ? "+" : "\u256E"), ...inputRows.map((text5) => inputRow(text5)), inputRow(hint, hintColor), edge(ascii ? "+" : "\u2570", ascii ? "+" : "\u256F"));
87823
+ const inputRow = (text6, color) => place(foreground(vertical, "#6b6b6b", mode) + " " + foreground(padCells(text6, contentWidth - 4), color ?? "#e6e6e6", mode) + " " + foreground(vertical, "#6b6b6b", mode));
87824
+ composer.push(edge(ascii ? "+" : "\u256D", ascii ? "+" : "\u256E"), ...inputRows.map((text6) => inputRow(text6)), inputRow(hint, hintColor), edge(ascii ? "+" : "\u2570", ascii ? "+" : "\u256F"));
87495
87825
  }
87496
87826
  }
87497
87827
  const frame = [
@@ -87543,8 +87873,8 @@ function renderCardCarousel(cards, width, selectedIndex, focused) {
87543
87873
  return { text: spans.map((span) => span.text).join(""), spans };
87544
87874
  });
87545
87875
  }
87546
- function centeredCarouselText(text5, width) {
87547
- const value = truncateCells(text5, width);
87876
+ function centeredCarouselText(text6, width) {
87877
+ const value = truncateCells(text6, width);
87548
87878
  return " ".repeat(Math.max(0, Math.floor((width - cells(value)) / 2))) + value;
87549
87879
  }
87550
87880
 
@@ -87824,7 +88154,7 @@ function homeHeader(state, width, height) {
87824
88154
  const title = inspiration?.feature?.title || inspiration?.title || "Daily inspiration";
87825
88155
  const banner = [centered2(`DAILY INSPIRATION ${state.focus === "inspiration" ? "\u2039 Enter open \u203A" : "\u2039 Ctrl+O explore \u203A"}`, width), "", ...parts.map((line) => centered2(line, width)), centered2(title, width)];
87826
88156
  while (banner.length < rows2) banner.push("");
87827
- banner.forEach((text5) => result.push({ text: text5, background: gradient.start }));
88157
+ banner.forEach((text6) => result.push({ text: text6, background: gradient.start }));
87828
88158
  result.push("", { text: centered2(state.workspace === "apps" ? prompts.apps : state.username ? `Hey ${state.username}!` : "Hey there!", width), bold: true });
87829
88159
  if (state.workspace !== "chats" || !homeChatItems(state).length) result.push({ text: centered2(state.workspace === "apps" ? "Use your apps directly and return to saved results." : prompts[state.workspace], width), color: "#cfcfcf" });
87830
88160
  result.push("");
@@ -87860,14 +88190,14 @@ function renderHomeChatCards(state, width, height) {
87860
88190
  import { randomBytes as randomBytes10, randomUUID as randomUUID18 } from "crypto";
87861
88191
 
87862
88192
  // ../ui/src/components/apps/appsSkillFormUtils.ts
87863
- var object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
88193
+ var object2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
87864
88194
  var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
87865
88195
  var pathParts = (path2) => path2.split(".").filter(Boolean).map((part) => part.endsWith("[]") ? part.slice(0, -2) : part);
87866
88196
  function resolveSkillSchema(schema, root, seen = /* @__PURE__ */ new Set()) {
87867
88197
  if (schema.$ref) {
87868
88198
  const reference = schema.$ref;
87869
88199
  if (!reference.startsWith("#/") || seen.has(reference)) return schema;
87870
- const resolved = reference.slice(2).split("/").reduce((value, part) => object(value)[part.replace(/~1/g, "/").replace(/~0/g, "~")], root);
88200
+ const resolved = reference.slice(2).split("/").reduce((value, part) => object2(value)[part.replace(/~1/g, "/").replace(/~0/g, "~")], root);
87871
88201
  if (!resolved || typeof resolved !== "object") return schema;
87872
88202
  return resolveSkillSchema({ ...resolved, ...schema, $ref: void 0 }, root, /* @__PURE__ */ new Set([...Array.from(seen), reference]));
87873
88203
  }
@@ -87881,7 +88211,7 @@ function resolveSkillSchema(schema, root, seen = /* @__PURE__ */ new Set()) {
87881
88211
  function getSkillPath(input, path2) {
87882
88212
  let cursor = input;
87883
88213
  for (const part of path2.split(".").filter(Boolean)) {
87884
- cursor = object(cursor)[part.replace(/\[\]$/, "")];
88214
+ cursor = object2(cursor)[part.replace(/\[\]$/, "")];
87885
88215
  if (part.endsWith("[]")) cursor = Array.isArray(cursor) ? cursor[0] : void 0;
87886
88216
  }
87887
88217
  return cursor;
@@ -87892,7 +88222,7 @@ function setSkillPath(input, path2, value) {
87892
88222
  if (index === parts.length) return value;
87893
88223
  const part = parts[index];
87894
88224
  const key = part.replace(/\[\]$/, "");
87895
- const parent = { ...object(current) };
88225
+ const parent = { ...object2(current) };
87896
88226
  if (part.endsWith("[]")) {
87897
88227
  const entries = Array.isArray(parent[key]) ? [...parent[key]] : [];
87898
88228
  entries[0] = update(entries[0], index + 1);
@@ -87915,17 +88245,17 @@ function prepareSkillInput(schema, input, timezone, now = /* @__PURE__ */ new Da
87915
88245
  const isoDate = (ordinal) => new Date(ordinal * 864e5).toISOString().slice(0, 10);
87916
88246
  function walk(node, value) {
87917
88247
  const resolved = resolveSkillSchema(node, schema);
87918
- const token = object(value).$date;
88248
+ const token = object2(value).$date;
87919
88249
  if (typeof token === "string") {
87920
88250
  const weekday = (new Date(today * 864e5).getUTCDay() + 6) % 7;
87921
88251
  const ordinal = token === "today" || token === "today_end" || token === "next_seven_days_start" ? today : token === "next_seven_days_end" ? today + 6 : token === "next_week_start" ? today + 7 - weekday : token === "next_week_end" ? today + 13 - weekday : null;
87922
88252
  if (ordinal === null) return value;
87923
88253
  const date = isoDate(ordinal);
87924
- return object(value).format === "datetime" || resolved.format === "date-time" ? `${date}T${token.endsWith("_end") ? "23:59:59" : "00:00:00"}[${timezone}]` : date;
88254
+ return object2(value).format === "datetime" || resolved.format === "date-time" ? `${date}T${token.endsWith("_end") ? "23:59:59" : "00:00:00"}[${timezone}]` : date;
87925
88255
  }
87926
88256
  if (resolved.type === "array" && Array.isArray(value)) return value.map((item) => walk(resolved.items ?? {}, item));
87927
88257
  if ((resolved.type === "object" || resolved.properties) && value && typeof value === "object" && !Array.isArray(value)) {
87928
- const prepared = { ...object(value) };
88258
+ const prepared = { ...object2(value) };
87929
88259
  for (const [name, child] of Object.entries(resolved.properties ?? {})) {
87930
88260
  if (own(prepared, name)) prepared[name] = walk(child, prepared[name]);
87931
88261
  }
@@ -87958,7 +88288,7 @@ function validateSkillInput(schema, input) {
87958
88288
  issues.push({ path: path2, code: "type" });
87959
88289
  return;
87960
88290
  }
87961
- for (const [name, child] of Object.entries(field.properties ?? {})) walk(child, object(value)[name], path2 ? `${path2}.${name}` : name, (field.required ?? []).includes(name));
88291
+ for (const [name, child] of Object.entries(field.properties ?? {})) walk(child, object2(value)[name], path2 ? `${path2}.${name}` : name, (field.required ?? []).includes(name));
87962
88292
  } else if (field.type === "array") {
87963
88293
  if (!Array.isArray(value)) {
87964
88294
  issues.push({ path: path2, code: "type" });
@@ -88505,21 +88835,21 @@ function embedPreview(embedId, type, content, appId, skillId, action, width) {
88505
88835
  }
88506
88836
  function readableFields(value, width) {
88507
88837
  const lines = [];
88508
- function visit(label3, item, indent) {
88838
+ function visit2(label3, item, indent) {
88509
88839
  if (Array.isArray(item)) {
88510
88840
  lines.push(`${indent}${label3} (${item.length})`);
88511
- item.forEach((entry, index) => visit(`${index + 1}.`, entry, `${indent} `));
88841
+ item.forEach((entry, index) => visit2(`${index + 1}.`, entry, `${indent} `));
88512
88842
  } else if (item && typeof item === "object") {
88513
88843
  lines.push(`${indent}${label3}`);
88514
- for (const [key, entry] of Object.entries(item)) visit(readableLabel(key), entry, `${indent} `);
88844
+ for (const [key, entry] of Object.entries(item)) visit2(readableLabel(key), entry, `${indent} `);
88515
88845
  } else {
88516
- const text5 = item === null ? "None" : typeof item === "boolean" ? item ? "Yes" : "No" : String(item);
88517
- const [first = "", ...rest] = text5.split("\n");
88846
+ const text6 = item === null ? "None" : typeof item === "boolean" ? item ? "Yes" : "No" : String(item);
88847
+ const [first = "", ...rest] = text6.split("\n");
88518
88848
  lines.push(`${indent}${label3} ${first}`);
88519
88849
  lines.push(...rest.map((line) => `${indent} ${line}`));
88520
88850
  }
88521
88851
  }
88522
- for (const [key, item] of Object.entries(value)) visit(`${readableLabel(key)}:`, item, "");
88852
+ for (const [key, item] of Object.entries(value)) visit2(`${readableLabel(key)}:`, item, "");
88523
88853
  return lines.flatMap((line) => textLines(line, width));
88524
88854
  }
88525
88855
  function readableLabel(key) {
@@ -88714,7 +89044,7 @@ function renderTuiFrame(state, width, height, options = {}) {
88714
89044
  return renderWorkspaceFrame(state, width, height, renderBody(state, bodyWidth, height), { ...options, stickyRows, headerRows: state.screen === "chat" || state.screen === "example" ? renderChatHeader(state, bodyWidth).length : void 0 });
88715
89045
  }
88716
89046
  function coloredHero(lines, rows2, gradient = PRIMARY_GRADIENT) {
88717
- return lines.map((text5, index) => index < rows2 ? { text: text5, background: gradient.start } : text5);
89047
+ return lines.map((text6, index) => index < rows2 ? { text: text6, background: gradient.start } : text6);
88718
89048
  }
88719
89049
  var blueHero = (lines, rows2) => coloredHero(lines, rows2);
88720
89050
  function homeCards(lines, width, gradients) {
@@ -88726,7 +89056,7 @@ function homeCards(lines, width, gradients) {
88726
89056
  }
88727
89057
  return groups.filter((group) => group.length).flatMap((group, index) => {
88728
89058
  const cardWidth = Math.min(width, Math.max(...group.map(cells))), inset = Math.max(0, Math.floor((width - cardWidth) / 2));
88729
- return [...group.map((text5) => ({ text: text5, background: (gradients[index] ?? PRIMARY_GRADIENT).start, inset })), ""];
89059
+ return [...group.map((text6) => ({ text: text6, background: (gradients[index] ?? PRIMARY_GRADIENT).start, inset })), ""];
88730
89060
  });
88731
89061
  }
88732
89062
  function renderBody(state, width, height) {
@@ -89080,9 +89410,9 @@ function required(value) {
89080
89410
  return value;
89081
89411
  }
89082
89412
  function authoringReplacementPatch(path2, original, content) {
89083
- const lines = (text5, prefix) => {
89084
- if (!text5) return { count: 0, rows: [] };
89085
- const parts = text5.split("\n");
89413
+ const lines = (text6, prefix) => {
89414
+ if (!text6) return { count: 0, rows: [] };
89415
+ const parts = text6.split("\n");
89086
89416
  const newline = parts.at(-1) === "";
89087
89417
  if (newline) parts.pop();
89088
89418
  const rows2 = parts.map((line) => prefix + line);
@@ -89187,8 +89517,8 @@ async function persistCliProjectAuthoringJob(client2, job, approvedDigest) {
89187
89517
  for (const row of detail.items) {
89188
89518
  if (!["embed", "upload"].includes(row.item_type) || row.deleted_target_state) continue;
89189
89519
  const target = await decryptWithAesGcmCombined(row.target_id_encrypted, projectKey);
89190
- const text5 = row.encrypted_metadata ? await decryptWithAesGcmCombined(row.encrypted_metadata, projectKey) : null;
89191
- const meta = text5 ? record6(JSON.parse(text5)) : {};
89520
+ const text6 = row.encrypted_metadata ? await decryptWithAesGcmCombined(row.encrypted_metadata, projectKey) : null;
89521
+ const meta = text6 ? record6(JSON.parse(text6)) : {};
89192
89522
  const filePath = meta.path ?? meta.file_path ?? meta.filename ?? meta.display_path;
89193
89523
  if (target && typeof filePath === "string") files.push({ embedId: target, path: filePath });
89194
89524
  }
@@ -89869,8 +90199,8 @@ async function handleWorkspaceCommand(context, command) {
89869
90199
  if (request !== state.routeVersion) return true;
89870
90200
  state.detailTitle = embed.textPreview || (embed.appId ? `${embed.appId}${embed.skillId ? `/${embed.skillId}` : ""}` : embed.type?.replaceAll("_", " ")) || "Embed";
89871
90201
  const body = embed.content;
89872
- const text5 = ["code", "markdown", "content", "text", "transcript"].map((key) => body?.[key]).find((value) => typeof value === "string");
89873
- state.detailLines = typeof text5 === "string" ? text5.split("\n") : formatEmbedPreviewLines(embed, 100);
90202
+ const text6 = ["code", "markdown", "content", "text", "transcript"].map((key) => body?.[key]).find((value) => typeof value === "string");
90203
+ state.detailLines = typeof text6 === "string" ? text6.split("\n") : formatEmbedPreviewLines(embed, 100);
89874
90204
  }
89875
90205
  render();
89876
90206
  return true;
@@ -90369,10 +90699,10 @@ async function handleWorkspaceKey(context, chunk, key) {
90369
90699
  state.filter = "";
90370
90700
  }
90371
90701
  } else if (file) {
90372
- const text5 = await readTuiProjectFile(context.client, project, file);
90702
+ const text6 = await readTuiProjectFile(context.client, project, file);
90373
90703
  if (request === state.routeVersion && state.activeProject?.id === project.id) {
90374
90704
  state.detailTitle = file.name;
90375
- state.detailLines = text5.split("\n");
90705
+ state.detailLines = text6.split("\n");
90376
90706
  state.screen = "embed";
90377
90707
  state.scrollOffset = 0;
90378
90708
  }
@@ -90457,9 +90787,9 @@ async function handleWorkspaceKey(context, chunk, key) {
90457
90787
  return true;
90458
90788
  }
90459
90789
  if (key.name === "return" && state.screen === "chats" && state.input.trim()) {
90460
- const text5 = state.input.trim();
90790
+ const text6 = state.input.trim();
90461
90791
  newChat(state);
90462
- await context.send(text5);
90792
+ await context.send(text6);
90463
90793
  return true;
90464
90794
  }
90465
90795
  const cursor = state.inputCursor ?? state.input.length;
@@ -90501,9 +90831,9 @@ async function handleWorkspaceKey(context, chunk, key) {
90501
90831
  return true;
90502
90832
  }
90503
90833
  if (key.name === "paste" || !key.ctrl && !key.meta && chunk && chunk >= " ") {
90504
- const text5 = terminalText(chunk);
90505
- state.input = state.input.slice(0, cursor) + text5 + state.input.slice(cursor);
90506
- state.inputCursor = cursor + text5.length;
90834
+ const text6 = terminalText(chunk);
90835
+ state.input = state.input.slice(0, cursor) + text6 + state.input.slice(cursor);
90836
+ state.inputCursor = cursor + text6.length;
90507
90837
  rememberDraft(state);
90508
90838
  render();
90509
90839
  return true;
@@ -90884,13 +91214,13 @@ async function handleEnter(params) {
90884
91214
  render();
90885
91215
  return;
90886
91216
  }
90887
- const text5 = state.input.trim();
90888
- if (!text5) return;
90889
- if (text5.startsWith("/")) {
90890
- await handleCommand({ command: text5, state, client: client2, terminal, render, finish });
91217
+ const text6 = state.input.trim();
91218
+ if (!text6) return;
91219
+ if (text6.startsWith("/")) {
91220
+ await handleCommand({ command: text6, state, client: client2, terminal, render, finish });
90891
91221
  return;
90892
91222
  }
90893
- await sendTuiMessage({ message: text5, state, client: client2, render });
91223
+ await sendTuiMessage({ message: text6, state, client: client2, render });
90894
91224
  }
90895
91225
  async function handleCommand(params) {
90896
91226
  const { command, state, client: client2, terminal, render, finish } = params;
@@ -95138,11 +95468,11 @@ function validateSummary(value) {
95138
95468
  if (item.protocol_version !== 1) throw new Error("Invalid remote command protocol version");
95139
95469
  return {
95140
95470
  protocol_version: 1,
95141
- execution_id: identifier3(item.execution_id, "execution_id"),
95142
- chat_id: identifier3(item.chat_id, "chat_id"),
95143
- project_id: identifier3(item.project_id, "project_id"),
95144
- source_id: identifier3(item.source_id, "source_id"),
95145
- state: text4(item.state, "state"),
95471
+ execution_id: identifier4(item.execution_id, "execution_id"),
95472
+ chat_id: identifier4(item.chat_id, "chat_id"),
95473
+ project_id: identifier4(item.project_id, "project_id"),
95474
+ source_id: identifier4(item.source_id, "source_id"),
95475
+ state: text5(item.state, "state"),
95146
95476
  last_sequence: integer3(item.last_sequence ?? -1, "last_sequence", -1),
95147
95477
  lease_expires_at: integer3(item.lease_expires_at ?? 0, "lease_expires_at", 0)
95148
95478
  };
@@ -95154,16 +95484,16 @@ function validateClaimedRequest(value, summary, binding, sourceSessionId) {
95154
95484
  return {
95155
95485
  ...item,
95156
95486
  protocol_version: 1,
95157
- execution_id: identifier3(item.execution_id, "execution_id"),
95158
- chat_id: identifier3(item.chat_id, "chat_id"),
95159
- project_id: identifier3(item.project_id, "project_id"),
95160
- source_id: identifier3(item.source_id, "source_id"),
95161
- state: text4(item.state, "state"),
95162
- encrypted_request: text4(item.encrypted_request, "encrypted_request"),
95163
- request_digest: text4(item.request_digest, "request_digest"),
95487
+ execution_id: identifier4(item.execution_id, "execution_id"),
95488
+ chat_id: identifier4(item.chat_id, "chat_id"),
95489
+ project_id: identifier4(item.project_id, "project_id"),
95490
+ source_id: identifier4(item.source_id, "source_id"),
95491
+ state: text5(item.state, "state"),
95492
+ encrypted_request: text5(item.encrypted_request, "encrypted_request"),
95493
+ request_digest: text5(item.request_digest, "request_digest"),
95164
95494
  approval,
95165
95495
  key_epoch: integer3(item.key_epoch, "key_epoch", 1),
95166
- lease_token: text4(item.lease_token, "lease_token"),
95496
+ lease_token: text5(item.lease_token, "lease_token"),
95167
95497
  lease_generation: integer3(item.lease_generation, "lease_generation", 1),
95168
95498
  lease_expires_at: integer3(item.lease_expires_at, "lease_expires_at", 1),
95169
95499
  last_sequence: integer3(item.last_sequence ?? -1, "last_sequence", -1),
@@ -95176,7 +95506,7 @@ function validateLeaseResponse(value, executionId) {
95176
95506
  return {
95177
95507
  ...item,
95178
95508
  execution_id: executionId,
95179
- lease_token: text4(item.lease_token, "lease_token"),
95509
+ lease_token: text5(item.lease_token, "lease_token"),
95180
95510
  lease_generation: integer3(item.lease_generation, "lease_generation", 1),
95181
95511
  lease_expires_at: integer3(item.lease_expires_at, "lease_expires_at", 1),
95182
95512
  last_sequence: integer3(item.last_sequence ?? -1, "last_sequence", -1),
@@ -95191,10 +95521,10 @@ function parsePortableRequest(plaintext) {
95191
95521
  const policy = parsePolicy(item.policy);
95192
95522
  const request = {
95193
95523
  protocol_version: 1,
95194
- execution_id: identifier3(item.execution_id, "execution_id"),
95195
- chat_id: identifier3(item.chat_id, "chat_id"),
95196
- project_id: identifier3(item.project_id, "project_id"),
95197
- source_id: identifier3(item.source_id, "source_id"),
95524
+ execution_id: identifier4(item.execution_id, "execution_id"),
95525
+ chat_id: identifier4(item.chat_id, "chat_id"),
95526
+ project_id: identifier4(item.project_id, "project_id"),
95527
+ source_id: identifier4(item.source_id, "source_id"),
95198
95528
  policy,
95199
95529
  approval: parseApproval(item.approval)
95200
95530
  };
@@ -95220,12 +95550,12 @@ function parsePolicy(value) {
95220
95550
  if (!Array.isArray(policy.credential_profiles) || policy.credential_profiles.some((item) => typeof item !== "string")) throw new Error("Invalid credential profiles");
95221
95551
  return {
95222
95552
  argv: [...policy.argv],
95223
- cwd: text4(policy.cwd, "cwd"),
95553
+ cwd: text5(policy.cwd, "cwd"),
95224
95554
  mode: oneOf3(policy.mode, ["foreground", "background"], "mode"),
95225
95555
  source_access: oneOf3(policy.source_access, ["read_only", "read_write"], "source_access"),
95226
95556
  deadline_ms: integer3(policy.deadline_ms, "deadline_ms", 100),
95227
95557
  writable_profiles: [...policy.writable_profiles],
95228
- network_profile: policy.network_profile === null ? null : text4(policy.network_profile, "network_profile"),
95558
+ network_profile: policy.network_profile === null ? null : text5(policy.network_profile, "network_profile"),
95229
95559
  credential_profiles: [...policy.credential_profiles]
95230
95560
  };
95231
95561
  }
@@ -95239,7 +95569,7 @@ function parseApproval(value) {
95239
95569
  if (approval.kind !== "preset" || typeof approval.definition_digest !== "string" || !/^[a-f0-9]{64}$/i.test(approval.definition_digest)) throw new Error("Invalid preset approval");
95240
95570
  return {
95241
95571
  kind: "preset",
95242
- preset_id: identifier3(approval.preset_id, "preset_id"),
95572
+ preset_id: identifier4(approval.preset_id, "preset_id"),
95243
95573
  definition_digest: approval.definition_digest
95244
95574
  };
95245
95575
  }
@@ -95254,16 +95584,16 @@ function validateTrustedGrants(value) {
95254
95584
  }
95255
95585
  const result = {
95256
95586
  writable_targets: value.writable_targets.map((item) => ({
95257
- profile_id: identifier3(item.profile_id, "writable profile"),
95258
- host_path: text4(item.host_path, "writable host path")
95587
+ profile_id: identifier4(item.profile_id, "writable profile"),
95588
+ host_path: text5(item.host_path, "writable host path")
95259
95589
  })),
95260
95590
  network_profiles: value.network_profiles.map((item) => {
95261
95591
  if (!Array.isArray(item.destinations) || item.destinations.some((destination) => typeof destination !== "string")) {
95262
95592
  throw new RemoteCommandError("resource_not_granted", "Trusted network grant is invalid");
95263
95593
  }
95264
95594
  return {
95265
- profile_id: identifier3(item.profile_id, "network profile"),
95266
- destinations: item.destinations.map((destination) => text4(destination, "network destination"))
95595
+ profile_id: identifier4(item.profile_id, "network profile"),
95596
+ destinations: item.destinations.map((destination) => text5(destination, "network destination"))
95267
95597
  };
95268
95598
  }),
95269
95599
  credential_profiles: value.credential_profiles.map((item) => {
@@ -95271,7 +95601,7 @@ function validateTrustedGrants(value) {
95271
95601
  throw new RemoteCommandError("credential_unavailable", "Trusted credential grant is invalid");
95272
95602
  }
95273
95603
  return {
95274
- profile_id: identifier3(item.profile_id, "credential profile"),
95604
+ profile_id: identifier4(item.profile_id, "credential profile"),
95275
95605
  environment: { ...item.environment }
95276
95606
  };
95277
95607
  })
@@ -95347,14 +95677,14 @@ function record7(value, context) {
95347
95677
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`Invalid ${context}`);
95348
95678
  return value;
95349
95679
  }
95350
- function exactKeys2(value, keys) {
95351
- if (Object.keys(value).length !== keys.length || Object.keys(value).some((key) => !keys.includes(key))) throw new Error("Remote command request contains unexpected fields");
95680
+ function exactKeys2(value, keys2) {
95681
+ if (Object.keys(value).length !== keys2.length || Object.keys(value).some((key) => !keys2.includes(key))) throw new Error("Remote command request contains unexpected fields");
95352
95682
  }
95353
- function identifier3(value, context) {
95683
+ function identifier4(value, context) {
95354
95684
  if (typeof value !== "string" || !IDENTIFIER3.test(value)) throw new Error(`Invalid ${context}`);
95355
95685
  return value;
95356
95686
  }
95357
- function text4(value, context) {
95687
+ function text5(value, context) {
95358
95688
  if (typeof value !== "string" || !value || value.length > 1048576 || value.includes("\0")) throw new Error(`Invalid ${context}`);
95359
95689
  return value;
95360
95690
  }
@@ -95436,7 +95766,7 @@ function resolveRemoteAccessRoots(pathFlag, cwd = process.cwd()) {
95436
95766
  function discoverRemoteAccessRepositories(roots) {
95437
95767
  const repositoryRoots = /* @__PURE__ */ new Set();
95438
95768
  const permissionDenied = [];
95439
- const visit = (directory, approvedRoot) => {
95769
+ const visit2 = (directory, approvedRoot) => {
95440
95770
  let entries;
95441
95771
  try {
95442
95772
  entries = readdirSync12(directory, { withFileTypes: true });
@@ -95453,10 +95783,10 @@ function discoverRemoteAccessRepositories(roots) {
95453
95783
  }
95454
95784
  for (const entry of entries) {
95455
95785
  if (entry.name === ".git" || entry.isSymbolicLink() || !entry.isDirectory()) continue;
95456
- visit(join25(directory, entry.name), approvedRoot);
95786
+ visit2(join25(directory, entry.name), approvedRoot);
95457
95787
  }
95458
95788
  };
95459
- for (const root of roots) visit(root, root);
95789
+ for (const root of roots) visit2(root, root);
95460
95790
  return {
95461
95791
  repositories: [...repositoryRoots].sort().map((rootPath) => ({ rootPath, displayName: rootPath.split(/[\\/]/).filter(Boolean).pop() ?? rootPath })),
95462
95792
  permissionDenied: permissionDenied.sort()
@@ -97178,15 +97508,15 @@ function validateWorkRecoveryDocument(value) {
97178
97508
  }
97179
97509
  const visiting = /* @__PURE__ */ new Set();
97180
97510
  const visited = /* @__PURE__ */ new Set();
97181
- const visit = (node) => {
97511
+ const visit2 = (node) => {
97182
97512
  if (visiting.has(node)) throw new Error(`Work recovery dependency cycle includes ${node}.`);
97183
97513
  if (visited.has(node)) return;
97184
97514
  visiting.add(node);
97185
- for (const next of graph.get(node) ?? []) visit(next);
97515
+ for (const next of graph.get(node) ?? []) visit2(next);
97186
97516
  visiting.delete(node);
97187
97517
  visited.add(node);
97188
97518
  };
97189
- for (const node of graph.keys()) visit(node);
97519
+ for (const node of graph.keys()) visit2(node);
97190
97520
  }
97191
97521
  function findRecoveryConflicts(document, projectId, current) {
97192
97522
  if (document.project.project_id !== projectId) return [{ kind: "plan", id: document.project.project_id, reason: "wrong_project" }];
@@ -99364,10 +99694,10 @@ async function handlePlans(client2, subcommand, rest, flags, redactor) {
99364
99694
  else console.log(`Plan success criterion updated: ${updated.criterion_id}`);
99365
99695
  return;
99366
99696
  }
99367
- const text5 = requiredStringFlag(flags.text ?? rest.slice(2).join(" "), "--text <criterion>");
99697
+ const text6 = requiredStringFlag(flags.text ?? rest.slice(2).join(" "), "--text <criterion>");
99368
99698
  const criterion = await buildCreatePlanCriterionInput(plan, masterKey, {
99369
99699
  criterionId: typeof flags.id === "string" ? flags.id : void 0,
99370
- text: text5,
99700
+ text: text6,
99371
99701
  type: typeof flags.type === "string" ? flags.type : void 0,
99372
99702
  status: typeof flags.status === "string" ? flags.status : void 0,
99373
99703
  required: flags.required === true ? true : flags.optional === true ? false : void 0,
@@ -99642,7 +99972,7 @@ async function handleWorkRecovery(client2, subcommand, rest, flags) {
99642
99972
  if (subcommand === "validate" || subcommand === "restore") {
99643
99973
  const path2 = requiredStringFlag(flags.file ?? rest[0], "--file <projection.yml>");
99644
99974
  if (!existsSync24(path2)) throw new Error(`Recovery projection does not exist: ${path2}`);
99645
- const document = parseYaml2(readFileSync22(path2, "utf8"));
99975
+ const document = parseYaml(readFileSync22(path2, "utf8"));
99646
99976
  validateWorkRecoveryDocument(document);
99647
99977
  if (subcommand === "validate") {
99648
99978
  if (flags.json === true) printJson2({ valid: true });
@@ -101130,8 +101460,8 @@ function taskAssignFlag(flags) {
101130
101460
  return typeof flags.assign === "string" ? flags.assign : typeof flags.assignee === "string" ? flags.assignee : void 0;
101131
101461
  }
101132
101462
  function labelFlags(flags, ...names) {
101133
- const keys = names.length > 0 ? names : ["label", "labels", "tag", "tags"];
101134
- return normalizeLabels(keys.flatMap((key) => splitCsvFlag(flags[key])));
101463
+ const keys2 = names.length > 0 ? names : ["label", "labels", "tag", "tags"];
101464
+ return normalizeLabels(keys2.flatMap((key) => splitCsvFlag(flags[key])));
101135
101465
  }
101136
101466
  async function handleRemoteAccess(client2, subcommand, rest, flags) {
101137
101467
  if (!subcommand || subcommand === "help" || flags.help === true) {
@@ -101540,11 +101870,11 @@ async function handleIdeaBucket(client2, subcommand, rest, flags) {
101540
101870
  return;
101541
101871
  }
101542
101872
  if (subcommand === "add") {
101543
- const text5 = rest.join(" ").trim();
101544
- if (!text5) throw new Error("Missing IdeaBucket text for add.");
101873
+ const text6 = rest.join(" ").trim();
101874
+ if (!text6) throw new Error("Missing IdeaBucket text for add.");
101545
101875
  const scheduledSendAt = typeof flags["scheduled-at"] === "string" ? parseUnixSecondsFlag(flags["scheduled-at"], "--scheduled-at") : void 0;
101546
101876
  printJson2(await client2.addIdeaBucketText({
101547
- text: text5,
101877
+ text: text6,
101548
101878
  chatId: typeof flags.chat === "string" ? flags.chat : void 0,
101549
101879
  bucketId: typeof flags.bucket === "string" ? flags.bucket : void 0,
101550
101880
  scheduledSendAt,
@@ -101638,11 +101968,11 @@ function renderRemoteCommandEvent(event) {
101638
101968
  if (event.event_kind === "output") {
101639
101969
  const raw = typeof event.payload.text === "string" ? event.payload.text : "";
101640
101970
  const limit = 24e3;
101641
- const text5 = escapeTerminalControls(raw.slice(0, limit));
101971
+ const text6 = escapeTerminalControls(raw.slice(0, limit));
101642
101972
  const omitted = raw.length > limit ? `
101643
101973
  [${raw.length - limit} characters omitted from this display]` : "";
101644
101974
  return `Unreviewed command output (inert) ${identity2}:
101645
- ${text5}${omitted}`;
101975
+ ${text6}${omitted}`;
101646
101976
  }
101647
101977
  if (event.event_kind === "output_truncated") {
101648
101978
  return `Command output was truncated upstream (${identity2}); displayed output does not cover the full process transcript.`;
@@ -101656,9 +101986,9 @@ ${text5}${omitted}`;
101656
101986
  var EXPLICIT_PROJECT_MENTION = /@project:([A-Za-z0-9](?:[A-Za-z0-9_-]|\.(?=[A-Za-z0-9]))*)/gi;
101657
101987
  function extractExplicitProjectMentions(message) {
101658
101988
  const matches2 = Array.from(message.matchAll(EXPLICIT_PROJECT_MENTION), (match) => match[1]);
101659
- const unique2 = /* @__PURE__ */ new Map();
101660
- for (const target of matches2) unique2.set(target.toLocaleLowerCase("en-US"), target);
101661
- return [...unique2.values()];
101989
+ const unique3 = /* @__PURE__ */ new Map();
101990
+ for (const target of matches2) unique3.set(target.toLocaleLowerCase("en-US"), target);
101991
+ return [...unique3.values()];
101662
101992
  }
101663
101993
  async function resolveExplicitChatProject(client2, masterKey, message, flags, context) {
101664
101994
  const mentions = extractExplicitProjectMentions(message);
@@ -102321,19 +102651,19 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
102321
102651
  if (embed.type === "app_skill_use" && embed.appId === "videos" && (embed.skillId === "get_transcript" || embed.skillId === "get-transcript") && embed.content) {
102322
102652
  const results = embed.content.results ?? embed.content.data ?? [];
102323
102653
  if (Array.isArray(results) && results.length > 0) {
102324
- let text5 = "";
102654
+ let text6 = "";
102325
102655
  for (const r of results) {
102326
102656
  const meta = r.metadata;
102327
- if (meta?.title) text5 += `# ${meta.title}
102657
+ if (meta?.title) text6 += `# ${meta.title}
102328
102658
 
102329
102659
  `;
102330
- if (r.url) text5 += `Source: ${r.url}
102660
+ if (r.url) text6 += `Source: ${r.url}
102331
102661
 
102332
102662
  `;
102333
- text5 += String(
102663
+ text6 += String(
102334
102664
  r.transcript ?? r.formatted_transcript ?? r.text ?? r.content ?? ""
102335
102665
  );
102336
- text5 += "\n\n---\n\n";
102666
+ text6 += "\n\n---\n\n";
102337
102667
  }
102338
102668
  let fname = `${eid.slice(0, 8)}_transcript.md`;
102339
102669
  const firstMeta = results[0]?.metadata;
@@ -102343,7 +102673,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
102343
102673
  transcriptEmbeds.push({
102344
102674
  embedId: eid,
102345
102675
  filename: fname,
102346
- content: text5
102676
+ content: text6
102347
102677
  });
102348
102678
  }
102349
102679
  }
@@ -103026,8 +103356,8 @@ async function syncCliBoundWorkflowFiles(client2, workflow, flags) {
103026
103356
  const contents = await client2.listProjectItems(project.projectId, context);
103027
103357
  for (const item of contents.items.filter((item2) => item2.item_type === "workflow")) {
103028
103358
  if (await decryptOptionalProjectField2(item.target_id_encrypted, project.projectKey) !== workflow.id) continue;
103029
- const text5 = await decryptOptionalProjectField2(item.encrypted_metadata, project.projectKey);
103030
- const metadata = text5 ? JSON.parse(text5) : {};
103359
+ const text6 = await decryptOptionalProjectField2(item.encrypted_metadata, project.projectKey);
103360
+ const metadata = text6 ? JSON.parse(text6) : {};
103031
103361
  const binding = metadata.remote_workflow_file;
103032
103362
  if (!binding) continue;
103033
103363
  const source = (await client2.listProjectSources(project.projectId, context)).find((item2) => item2.source_id === binding.source_id);
@@ -103317,10 +103647,10 @@ async function handleWorkflows(client2, subcommand, rest, flags, redactor) {
103317
103647
  return;
103318
103648
  }
103319
103649
  if (subcommand === "input") {
103320
- const text5 = typeof flags.text === "string" ? flags.text : rest.join(" ").trim();
103321
- if (!text5) throw new Error('Missing workflow input text. Example: openmates workflows ask "alert me if it rains"');
103650
+ const text6 = typeof flags.text === "string" ? flags.text : rest.join(" ").trim();
103651
+ if (!text6) throw new Error('Missing workflow input text. Example: openmates workflows ask "alert me if it rains"');
103322
103652
  const session = await client2.startWorkflowInput({
103323
- text: text5,
103653
+ text: text6,
103324
103654
  selectedWorkflowId: typeof flags["workflow-id"] === "string" ? flags["workflow-id"] : void 0,
103325
103655
  selectedProjectId: typeof flags["project-id"] === "string" ? flags["project-id"] : void 0,
103326
103656
  timezone: typeof flags.timezone === "string" ? flags.timezone : Intl.DateTimeFormat().resolvedOptions().timeZone,
@@ -103367,9 +103697,9 @@ async function handleWorkflows(client2, subcommand, rest, flags, redactor) {
103367
103697
  }
103368
103698
  if (subcommand === "input-follow-up") {
103369
103699
  const sessionId = rest[0];
103370
- const text5 = typeof flags.text === "string" ? flags.text : rest.slice(1).join(" ").trim();
103371
- if (!sessionId || !text5) throw new Error('Missing session ID or text. Example: openmates workflows input-follow-up <session-id> "make it weekdays only"');
103372
- const session = await client2.followUpWorkflowInput(sessionId, text5);
103700
+ const text6 = typeof flags.text === "string" ? flags.text : rest.slice(1).join(" ").trim();
103701
+ if (!sessionId || !text6) throw new Error('Missing session ID or text. Example: openmates workflows input-follow-up <session-id> "make it weekdays only"');
103702
+ const session = await client2.followUpWorkflowInput(sessionId, text6);
103373
103703
  if (flags.json === true) {
103374
103704
  printJson2(session);
103375
103705
  } else {
@@ -104562,10 +104892,10 @@ async function streamCodeRunToTerminal(url, jsonMode) {
104562
104892
  const payload = message.payload ?? {};
104563
104893
  if (message.type === "code_run_event") {
104564
104894
  const kind = String(payload.kind ?? "status");
104565
- const text5 = String(payload.text ?? "");
104895
+ const text6 = String(payload.text ?? "");
104566
104896
  if (!jsonMode) {
104567
- if (kind === "stdout") process.stdout.write(text5);
104568
- else process.stderr.write(text5);
104897
+ if (kind === "stdout") process.stdout.write(text6);
104898
+ else process.stderr.write(text6);
104569
104899
  }
104570
104900
  } else if (message.type === "code_run_update") {
104571
104901
  lastStatus = { ...lastStatus, ...payload };
@@ -105354,8 +105684,8 @@ function parseChatImportPayload(raw) {
105354
105684
  return parsed;
105355
105685
  }
105356
105686
  if (parsed && typeof parsed === "object") {
105357
- const object2 = parsed;
105358
- if (object2.chat || object2.messages) return { chats: [normalizeImportedChat(object2)] };
105687
+ const object3 = parsed;
105688
+ if (object3.chat || object3.messages) return { chats: [normalizeImportedChat(object3)] };
105359
105689
  }
105360
105690
  throw new Error("JSON import must contain a chats array, a chat object, or messages.");
105361
105691
  }
@@ -107038,8 +107368,8 @@ function resolveApiKey(flags) {
107038
107368
  function printJson2(value) {
107039
107369
  console.log(JSON.stringify(value, null, 2));
107040
107370
  }
107041
- function header(text5) {
107042
- process.stdout.write(`\x1B[1m${text5}\x1B[0m
107371
+ function header(text6) {
107372
+ process.stdout.write(`\x1B[1m${text6}\x1B[0m
107043
107373
  `);
107044
107374
  }
107045
107375
  function kv(key, value, keyWidth = 16) {
@@ -107805,15 +108135,15 @@ async function acceptChatTaskProposals(client2, chatId, proposals, fallbackText)
107805
108135
  }
107806
108136
  return accepted;
107807
108137
  }
107808
- function buildTaskProposalFallbackText(text5) {
108138
+ function buildTaskProposalFallbackText(text6) {
107809
108139
  const seen = /* @__PURE__ */ new Set();
107810
- const bulletLines = text5.split("\n").map((line) => line.trim()).filter((line) => /^[-*•]\s+/.test(line)).map((line) => line.replace(/^([-*•]\s*)\[[ xX]\]\s*/, "$1")).filter((line) => {
108140
+ const bulletLines = text6.split("\n").map((line) => line.trim()).filter((line) => /^[-*•]\s+/.test(line)).map((line) => line.replace(/^([-*•]\s*)\[[ xX]\]\s*/, "$1")).filter((line) => {
107811
108141
  const key = line.replace(/^[-*•]\s+/, "").trim().toLowerCase();
107812
108142
  if (seen.has(key)) return false;
107813
108143
  seen.add(key);
107814
108144
  return true;
107815
108145
  });
107816
- return bulletLines.length > 0 ? bulletLines.join("\n") : text5;
108146
+ return bulletLines.length > 0 ? bulletLines.join("\n") : text6;
107817
108147
  }
107818
108148
  function printIncognitoNoHistoryNotice(json) {
107819
108149
  const message = "Incognito chats are not stored. There is no incognito history to show or clear.";
@@ -107847,8 +108177,8 @@ function renderEmbedFromMeta(embedId, meta) {
107847
108177
  process.stdout.write(`\x1B[2m\u2514\u2500 openmates embeds show ${shortId}\x1B[0m
107848
108178
  `);
107849
108179
  }
107850
- async function renderMessageText(text5, embedRefIndex, client2) {
107851
- const lines = text5.split("\n");
108180
+ async function renderMessageText(text6, embedRefIndex, client2) {
108181
+ const lines = text6.split("\n");
107852
108182
  const outputLines = [];
107853
108183
  for (const line of lines) {
107854
108184
  const blockMatch = line.match(/^\s*\[!?\]\(embed:([^)]+)\)\s*$/);
@@ -108272,8 +108602,8 @@ No example chats are linked to ${label3} yet.`);
108272
108602
  console.log(`All examples: openmates apps examples ${appId}${skillId ? ` ${skillId}` : ""}`);
108273
108603
  }
108274
108604
  }
108275
- function wrapText(text5, width) {
108276
- const words = text5.split(" ");
108605
+ function wrapText(text6, width) {
108606
+ const words = text6.split(" ");
108277
108607
  const lines = [];
108278
108608
  let current = "";
108279
108609
  for (const w of words) {