openmates 0.16.0-alpha.8 → 0.16.0-alpha.9

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.
@@ -45451,6 +45451,420 @@ var ALL_EXAMPLE_CHATS = [
45451
45451
  audioSpeakFriendlyWelcomeMessageChat
45452
45452
  ].sort((a, b) => a.metadata.order - b.metadata.order);
45453
45453
 
45454
+ // ../ui/src/demo_chats/exampleChatFiles.ts
45455
+ var FILE_LIKE_TYPES = /* @__PURE__ */ new Set([
45456
+ "audio",
45457
+ "audio-recording",
45458
+ "code",
45459
+ "code-code",
45460
+ "design",
45461
+ "diagram",
45462
+ "docs",
45463
+ "docs-doc",
45464
+ "document",
45465
+ "image",
45466
+ "images-image",
45467
+ "mind-map",
45468
+ "mind_map",
45469
+ "model3d",
45470
+ "music",
45471
+ "notebook",
45472
+ "pcb_schematic",
45473
+ "pdf",
45474
+ "recording",
45475
+ "remotion-video",
45476
+ "sheet",
45477
+ "sheets",
45478
+ "sheets-sheet",
45479
+ "spreadsheet",
45480
+ "svg",
45481
+ "video"
45482
+ ]);
45483
+ var URL_FIELDS = [
45484
+ "downloadUrl",
45485
+ "download_url",
45486
+ "file_url",
45487
+ "previewAudioUrl",
45488
+ "preview_audio_url",
45489
+ "previewImageUrl",
45490
+ "preview_image_url",
45491
+ "previewVideoUrl",
45492
+ "preview_video_url",
45493
+ "src",
45494
+ "url",
45495
+ "video_url"
45496
+ ];
45497
+ var AUDIO_URL_FIELDS = [
45498
+ "downloadUrl",
45499
+ "download_url",
45500
+ "file_url",
45501
+ "previewAudioUrl",
45502
+ "preview_audio_url",
45503
+ "src",
45504
+ "url"
45505
+ ];
45506
+ var VIDEO_URL_FIELDS = [
45507
+ "downloadUrl",
45508
+ "download_url",
45509
+ "file_url",
45510
+ "previewVideoUrl",
45511
+ "preview_video_url",
45512
+ "video_url",
45513
+ "src",
45514
+ "url",
45515
+ "previewImageUrl",
45516
+ "preview_image_url"
45517
+ ];
45518
+ var IMAGE_URL_FIELDS = [
45519
+ "downloadUrl",
45520
+ "download_url",
45521
+ "file_url",
45522
+ "previewImageUrl",
45523
+ "preview_image_url",
45524
+ "src",
45525
+ "url"
45526
+ ];
45527
+ var FILENAME_FIELDS = [
45528
+ "filename",
45529
+ "file_name",
45530
+ "file_path",
45531
+ "original_filename"
45532
+ ];
45533
+ var MIME_EXTENSION = {
45534
+ "application/pdf": "pdf",
45535
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
45536
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
45537
+ "audio/mpeg": "mp3",
45538
+ "audio/wav": "wav",
45539
+ "image/jpeg": "jpg",
45540
+ "image/png": "png",
45541
+ "image/svg+xml": "svg",
45542
+ "image/webp": "webp",
45543
+ "model/gltf-binary": "glb",
45544
+ "text/html": "html",
45545
+ "text/markdown": "md",
45546
+ "text/plain": "txt",
45547
+ "video/mp4": "mp4"
45548
+ };
45549
+ function isRecord2(value) {
45550
+ return typeof value === "object" && value !== null && !Array.isArray(value);
45551
+ }
45552
+ function normalizeEmbedId(embedId) {
45553
+ return embedId.startsWith("embed:") ? embedId.slice("embed:".length) : embedId;
45554
+ }
45555
+ function cleanString(value) {
45556
+ if (typeof value !== "string") return "";
45557
+ const trimmed = stripQuotes(value.trim());
45558
+ if (!trimmed || trimmed === "null" || trimmed === "undefined") return "";
45559
+ return trimmed;
45560
+ }
45561
+ function stripQuotes(value) {
45562
+ const first = value[0];
45563
+ if ((first === '"' || first === "'") && value.endsWith(first)) {
45564
+ return value.slice(1, -1).replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\'/g, "'");
45565
+ }
45566
+ return value;
45567
+ }
45568
+ function numberValue2(value) {
45569
+ if (typeof value === "number" && Number.isFinite(value)) return value;
45570
+ if (typeof value !== "string" || value.trim() === "") return null;
45571
+ const parsed = Number(value);
45572
+ return Number.isFinite(parsed) ? parsed : null;
45573
+ }
45574
+ function parseFlatToonFields(content) {
45575
+ const fields = {};
45576
+ for (const line of content.split("\n")) {
45577
+ if (!line || /^\s/.test(line)) continue;
45578
+ const separatorIndex = line.indexOf(":");
45579
+ if (separatorIndex <= 0) continue;
45580
+ const key = line.slice(0, separatorIndex).trim();
45581
+ const value = line.slice(separatorIndex + 1).trim();
45582
+ if (!key || value === "") continue;
45583
+ fields[key] = stripQuotes(value);
45584
+ }
45585
+ return fields;
45586
+ }
45587
+ function decodeEmbedContent(content) {
45588
+ if (isRecord2(content)) return { ...content };
45589
+ if (typeof content !== "string" || !content.trim()) return {};
45590
+ const trimmed = content.trim();
45591
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
45592
+ try {
45593
+ const parsed = JSON.parse(trimmed);
45594
+ return isRecord2(parsed) ? parsed : {};
45595
+ } catch {
45596
+ return parseFlatToonFields(content);
45597
+ }
45598
+ }
45599
+ return parseFlatToonFields(content);
45600
+ }
45601
+ function stringField2(record, keys) {
45602
+ for (const key of keys) {
45603
+ const value = cleanString(record[key]);
45604
+ if (value) return value;
45605
+ }
45606
+ return "";
45607
+ }
45608
+ function basenameFromUrl(url) {
45609
+ if (url.startsWith("data:")) return "";
45610
+ const withoutQuery = url.split(/[?#]/)[0] || "";
45611
+ return withoutQuery.split("/").pop()?.replace(/[^a-zA-Z0-9._-]/g, "_") ?? "";
45612
+ }
45613
+ function extensionFromUrl(url) {
45614
+ const basename4 = basenameFromUrl(url);
45615
+ const dotIndex = basename4.lastIndexOf(".");
45616
+ return dotIndex > 0 ? basename4.slice(dotIndex + 1).toLowerCase() : "";
45617
+ }
45618
+ function extensionFromLanguage(language) {
45619
+ const normalized = language.toLowerCase();
45620
+ const map = {
45621
+ bash: "sh",
45622
+ css: "css",
45623
+ dockerfile: "Dockerfile",
45624
+ html: "html",
45625
+ javascript: "js",
45626
+ json: "json",
45627
+ markdown: "md",
45628
+ python: "py",
45629
+ rust: "rs",
45630
+ svelte: "svelte",
45631
+ text: "txt",
45632
+ typescript: "ts",
45633
+ yaml: "yml"
45634
+ };
45635
+ return (map[normalized] ?? normalized.replace(/[^a-z0-9]/g, "")) || "txt";
45636
+ }
45637
+ function nestedFormatFromToon(content) {
45638
+ if (typeof content !== "string") return "";
45639
+ const match = content.match(/\n\s+format:\s*([^\n]+)/);
45640
+ return cleanString(match?.[1]);
45641
+ }
45642
+ function urlForType(type, record) {
45643
+ if (type.includes("video") || type === "remotion-video") return stringField2(record, VIDEO_URL_FIELDS);
45644
+ if (type.includes("audio") || type === "music" || type === "recording") return stringField2(record, AUDIO_URL_FIELDS);
45645
+ if (type.includes("image") || type === "svg") return stringField2(record, IMAGE_URL_FIELDS);
45646
+ return stringField2(record, URL_FIELDS);
45647
+ }
45648
+ function inferFallbackExtension(type, record, content) {
45649
+ const mimeType = stringField2(record, ["mime_type", "file_type", "mimeType"]);
45650
+ if (mimeType && MIME_EXTENSION[mimeType]) return MIME_EXTENSION[mimeType];
45651
+ const urlExtension = extensionFromUrl(urlForType(type, record));
45652
+ if (urlExtension) return urlExtension;
45653
+ const nestedFormat = nestedFormatFromToon(content);
45654
+ if (nestedFormat) return nestedFormat;
45655
+ if (type.includes("video")) return "mp4";
45656
+ if (type.includes("audio") || type === "music" || type === "recording") return "mp3";
45657
+ if (type.includes("image")) return "png";
45658
+ if (type.includes("pdf")) return "pdf";
45659
+ if (type.includes("doc") || type === "document") return "docx";
45660
+ if (type.includes("sheet") || type === "spreadsheet") return "xlsx";
45661
+ if (type === "model3d") return "glb";
45662
+ if (type.includes("code") || type === "notebook" || type === "pcb_schematic") {
45663
+ return extensionFromLanguage(stringField2(record, ["language"]));
45664
+ }
45665
+ return "txt";
45666
+ }
45667
+ function inferTitle(embedId, type, record, content) {
45668
+ const url = urlForType(type, record);
45669
+ const urlBasename = basenameFromUrl(url);
45670
+ const filename = stringField2(record, FILENAME_FIELDS);
45671
+ if ((type.includes("video") || type === "music" || type === "audio") && urlBasename) {
45672
+ return urlBasename;
45673
+ }
45674
+ if (filename) return filename.replace(/[/\\]/g, "_");
45675
+ if (urlBasename) return urlBasename;
45676
+ const title = stringField2(record, ["title"]);
45677
+ if (title) {
45678
+ const extension2 = inferFallbackExtension(type, record, content);
45679
+ return `${title.replace(/[^a-zA-Z0-9._ -]/g, "_").trim()}.${extension2}`;
45680
+ }
45681
+ const extension = inferFallbackExtension(type, record, content);
45682
+ return `${type || "file"}-${embedId.slice(0, 8)}.${extension}`;
45683
+ }
45684
+ function inferNodeType(title, type) {
45685
+ const lowerTitle = title.toLowerCase();
45686
+ if (type.includes("pdf") || lowerTitle.endsWith(".pdf")) return "pdf";
45687
+ if (type.includes("image") || /\.(png|jpe?g|gif|webp|svg|avif|heic|heif)$/.test(lowerTitle)) return "image";
45688
+ if (type.includes("video") || /\.(mp4|mov|webm|m4v)$/.test(lowerTitle)) return "video";
45689
+ if (type.includes("audio") || type === "music" || type === "recording" || /\.(mp3|wav|m4a|ogg|webm)$/.test(lowerTitle)) return "recording";
45690
+ if (type.includes("sheet") || type === "spreadsheet" || /\.(csv|xlsx?|ods)$/.test(lowerTitle)) return "sheets-sheet";
45691
+ if (type.includes("doc") || type === "document" || /\.(docx?|odt|rtf)$/.test(lowerTitle)) return "docs-doc";
45692
+ if (type === "model3d" || /\.(glb|gltf|obj|stl)$/.test(lowerTitle)) return "model3d";
45693
+ if (type.includes("code") || type === "notebook" || type === "pcb_schematic") return "code-code";
45694
+ return "file";
45695
+ }
45696
+ function iconNameForNodeType(nodeType) {
45697
+ if (nodeType === "pdf") return "pdf";
45698
+ if (nodeType === "image") return "image";
45699
+ if (nodeType === "video") return "video";
45700
+ if (nodeType === "recording") return "audio";
45701
+ if (nodeType === "sheets-sheet") return "sheets";
45702
+ if (nodeType === "docs-doc") return "document";
45703
+ if (nodeType === "code-code") return "coding";
45704
+ if (nodeType === "model3d") return "3dmodels";
45705
+ return "files";
45706
+ }
45707
+ function labelForNodeType(nodeType, type) {
45708
+ if (nodeType === "pdf") return "PDF";
45709
+ if (nodeType === "image") return "Image";
45710
+ if (nodeType === "video") return "Video";
45711
+ if (nodeType === "recording") return type === "music" ? "Music" : "Audio";
45712
+ if (nodeType === "sheets-sheet") return "Sheet";
45713
+ if (nodeType === "docs-doc") return "Document";
45714
+ if (nodeType === "code-code") return type === "notebook" ? "Notebook" : "Code file";
45715
+ if (nodeType === "model3d") return "3D model";
45716
+ return "File";
45717
+ }
45718
+ function formatBytes(bytes) {
45719
+ if (!bytes || bytes <= 0) return "";
45720
+ if (bytes < 1024) return `${bytes} B`;
45721
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(bytes < 10 * 1024 ? 1 : 0)} KB`;
45722
+ return `${(bytes / (1024 * 1024)).toFixed(bytes < 10 * 1024 * 1024 ? 1 : 0)} MB`;
45723
+ }
45724
+ function plural(value, singular, pluralLabel = `${singular}s`) {
45725
+ return `${value} ${value === 1 ? singular : pluralLabel}`;
45726
+ }
45727
+ function buildMetadata(nodeType, type, record) {
45728
+ const parts = [labelForNodeType(nodeType, type)];
45729
+ const lineCount = numberValue2(record.line_count ?? record.lineCount);
45730
+ const pageCount = numberValue2(record.page_count ?? record.pageCount);
45731
+ const wordCount = numberValue2(record.word_count ?? record.wordCount);
45732
+ const duration = numberValue2(record.duration_seconds ?? record.durationSeconds);
45733
+ const size = numberValue2(record.byte_length ?? record.size_bytes ?? record.sizeBytes);
45734
+ if (lineCount) parts.push(plural(lineCount, "line"));
45735
+ if (pageCount) parts.push(plural(pageCount, "page"));
45736
+ if (wordCount) parts.push(plural(wordCount, "word"));
45737
+ if (duration) parts.push(`${duration.toFixed(duration < 10 ? 1 : 0)}s`);
45738
+ const sizeLabel = formatBytes(size);
45739
+ if (sizeLabel) parts.push(sizeLabel);
45740
+ return parts.join(" | ");
45741
+ }
45742
+ function isSupportedPublicUrl(url) {
45743
+ return url.startsWith("/") || url.startsWith("data:") || /^https?:\/\//i.test(url);
45744
+ }
45745
+ function extractEmbedIdsFromContent(content) {
45746
+ const decoded = decodeEmbedContent(content);
45747
+ const rawIds = decoded.embed_ids ?? decoded.embedIds;
45748
+ const ids = typeof rawIds === "string" ? rawIds.split(/[|,]/) : rawIds;
45749
+ if (!Array.isArray(ids)) return [];
45750
+ return ids.map((id) => cleanString(id)).filter(Boolean).map(normalizeEmbedId);
45751
+ }
45752
+ function buildEmbedLookup(embeds) {
45753
+ const lookup = /* @__PURE__ */ new Map();
45754
+ for (const embed of embeds) {
45755
+ if (!embed.embed_id) continue;
45756
+ lookup.set(normalizeEmbedId(embed.embed_id), embed);
45757
+ }
45758
+ return lookup;
45759
+ }
45760
+ function buildEmbedRefLookup(embeds) {
45761
+ const lookup = /* @__PURE__ */ new Map();
45762
+ for (const embed of embeds) {
45763
+ const embedId = normalizeEmbedId(embed.embed_id);
45764
+ lookup.set(embedId, embedId);
45765
+ lookup.set(`embed:${embedId}`, embedId);
45766
+ const decoded = decodeEmbedContent(embed.content);
45767
+ const embedRef = stringField2(decoded, ["embed_ref", "embedRef"]);
45768
+ if (embedRef) {
45769
+ lookup.set(embedRef, embedId);
45770
+ lookup.set(`embed:${embedRef}`, embedId);
45771
+ }
45772
+ }
45773
+ return lookup;
45774
+ }
45775
+ function extractReferencedExampleEmbedIds(messages, embeds) {
45776
+ const refLookup = buildEmbedRefLookup(embeds);
45777
+ const ids = /* @__PURE__ */ new Set();
45778
+ const jsonBlockRe = /```(?:json_embed|json)\s*([\s\S]*?)\s*```/g;
45779
+ const inlineEmbedRe = /embed:([a-zA-Z0-9_.:-]+)/g;
45780
+ for (const message of messages) {
45781
+ const content = message.content ?? "";
45782
+ for (const match of Array.from(content.matchAll(jsonBlockRe))) {
45783
+ try {
45784
+ const parsed = JSON.parse(match[1].trim());
45785
+ const embedId = cleanString(parsed.embed_id ?? parsed.embedId);
45786
+ const resolved = refLookup.get(embedId) ?? refLookup.get(`embed:${embedId}`) ?? embedId;
45787
+ if (resolved) ids.add(normalizeEmbedId(resolved));
45788
+ } catch {
45789
+ }
45790
+ }
45791
+ for (const match of Array.from(content.matchAll(inlineEmbedRe))) {
45792
+ const rawRef = match[1];
45793
+ const resolved = refLookup.get(rawRef) ?? refLookup.get(`embed:${rawRef}`) ?? rawRef;
45794
+ if (resolved) ids.add(normalizeEmbedId(resolved));
45795
+ }
45796
+ }
45797
+ return Array.from(ids);
45798
+ }
45799
+ function expandEmbedIds(embedIds, embeds) {
45800
+ const lookup = buildEmbedLookup(embeds);
45801
+ const seen = /* @__PURE__ */ new Set();
45802
+ const queue = [...embedIds.map(normalizeEmbedId)];
45803
+ while (queue.length > 0) {
45804
+ const embedId = queue.shift();
45805
+ if (!embedId || seen.has(embedId)) continue;
45806
+ seen.add(embedId);
45807
+ const embed = lookup.get(embedId);
45808
+ if (!embed) continue;
45809
+ const childIds = [
45810
+ ...embed.embed_ids ?? [],
45811
+ ...extractEmbedIdsFromContent(embed.content)
45812
+ ];
45813
+ for (const childId of childIds) {
45814
+ const normalizedChildId = normalizeEmbedId(childId);
45815
+ if (normalizedChildId && !seen.has(normalizedChildId)) queue.push(normalizedChildId);
45816
+ }
45817
+ }
45818
+ return Array.from(seen);
45819
+ }
45820
+ function getEmbedFileReferences(embed) {
45821
+ const embedId = cleanString(embed.embed_id ?? embed.embedId ?? embed.id);
45822
+ if (!embedId) return [];
45823
+ const decoded = decodeEmbedContent(embed.content);
45824
+ const type = (stringField2(decoded, ["type", "embed_type", "embedType"]) || cleanString(embed.type) || "file").toLowerCase();
45825
+ if (!FILE_LIKE_TYPES.has(type)) return [];
45826
+ const title = inferTitle(embedId, type, decoded, embed.content);
45827
+ const nodeType = inferNodeType(title, type);
45828
+ const url = urlForType(type, decoded);
45829
+ const mimeType = stringField2(decoded, ["mime_type", "file_type", "mimeType"]);
45830
+ const createdAt = numberValue2(embed.created_at ?? embed.createdAt) ?? 0;
45831
+ return [{
45832
+ embedId: normalizeEmbedId(embedId),
45833
+ contentRef: `embed:${normalizeEmbedId(embedId)}`,
45834
+ title,
45835
+ subtitle: labelForNodeType(nodeType, type),
45836
+ type,
45837
+ nodeType,
45838
+ iconName: iconNameForNodeType(nodeType),
45839
+ createdAt,
45840
+ updatedAt: createdAt,
45841
+ metadata: buildMetadata(nodeType, type, decoded),
45842
+ appId: stringField2(decoded, ["app_id", "appId"]) || cleanString(embed.app_id ?? embed.appId) || null,
45843
+ skillId: stringField2(decoded, ["skill_id", "skillId"]) || cleanString(embed.skill_id ?? embed.skillId) || null,
45844
+ url: url && isSupportedPublicUrl(url) ? url : null,
45845
+ mimeType: mimeType || null
45846
+ }];
45847
+ }
45848
+ function collectExampleChatFileReferences(embeds, messages = []) {
45849
+ if (embeds.length === 0) return [];
45850
+ const lookup = buildEmbedLookup(embeds);
45851
+ const referencedIds = extractReferencedExampleEmbedIds(messages, embeds);
45852
+ const candidateIds = referencedIds.length > 0 ? expandEmbedIds(referencedIds, embeds) : embeds.map((embed) => normalizeEmbedId(embed.embed_id));
45853
+ const rows = [];
45854
+ const seen = /* @__PURE__ */ new Set();
45855
+ for (const embedId of candidateIds) {
45856
+ const embed = lookup.get(embedId);
45857
+ if (!embed) continue;
45858
+ for (const row of getEmbedFileReferences(embed)) {
45859
+ const key = `${row.embedId}:${row.title}`.toLowerCase();
45860
+ if (seen.has(key)) continue;
45861
+ rows.push(row);
45862
+ seen.add(key);
45863
+ }
45864
+ }
45865
+ return rows;
45866
+ }
45867
+
45454
45868
  // ../ui/src/i18n/locales/en.json
45455
45869
  var en_default = {
45456
45870
  activity: {
@@ -66318,8 +66732,10 @@ function getExampleChatConversation(query) {
66318
66732
  category: message.category ?? chat.category,
66319
66733
  modelName: message.model_name ?? null,
66320
66734
  createdAt: message.created_at,
66321
- embedIds: []
66735
+ embedIds: extractReferencedExampleEmbedIds([message], chat.embeds)
66322
66736
  })),
66737
+ embeds: chat.embeds,
66738
+ files: collectExampleChatFileReferences(chat.embeds, chat.messages),
66323
66739
  followUpSuggestions: chat.follow_up_suggestions.map(translate)
66324
66740
  };
66325
66741
  }
@@ -70212,7 +70628,7 @@ async function requestProjectRemoteOperation(options) {
70212
70628
  throw new ProjectRequesterError("source_offline", "The selected Project source is offline.");
70213
70629
  }
70214
70630
  const timeoutMs = options.timeoutMs ?? REMOTE_PROTOCOL_TIMEOUT_MS;
70215
- let sourceSessionId = stringField2(options.source, "source_session_id");
70631
+ let sourceSessionId = stringField3(options.source, "source_session_id");
70216
70632
  let keyEpoch = numberField(options.source, "key_epoch");
70217
70633
  let routingIdentity = null;
70218
70634
  if (!sourceSessionId || !keyEpoch) {
@@ -70364,7 +70780,7 @@ function parseJsonObject(value) {
70364
70780
  }
70365
70781
  throw new ProjectRequesterError("invalid_remote_payload", "The Project source returned an invalid payload.");
70366
70782
  }
70367
- function stringField2(value, key) {
70783
+ function stringField3(value, key) {
70368
70784
  return typeof value[key] === "string" && value[key] ? value[key] : null;
70369
70785
  }
70370
70786
  function numberField(value, key) {
@@ -71297,7 +71713,7 @@ function splitTaskAskInstruction(instruction) {
71297
71713
  const suffix = instruction.includes(":") ? instruction.split(":").slice(1).join(":") : instruction;
71298
71714
  return suffix.split(/[,;]\s*/).map((title) => title.trim()).filter(Boolean).map((title) => ({ title }));
71299
71715
  }
71300
- function isRecord2(value) {
71716
+ function isRecord3(value) {
71301
71717
  return typeof value === "object" && value !== null && !Array.isArray(value);
71302
71718
  }
71303
71719
  function isPrivateCliOutputKey(key) {
@@ -71305,7 +71721,7 @@ function isPrivateCliOutputKey(key) {
71305
71721
  }
71306
71722
  function sanitizeWorkspaceAskOutput(value) {
71307
71723
  if (Array.isArray(value)) return value.map((item) => sanitizeWorkspaceAskOutput(item));
71308
- if (!isRecord2(value)) return value;
71724
+ if (!isRecord3(value)) return value;
71309
71725
  const sanitized = {};
71310
71726
  for (const [key, nested] of Object.entries(value)) {
71311
71727
  if (isPrivateCliOutputKey(key)) continue;
@@ -71315,20 +71731,20 @@ function sanitizeWorkspaceAskOutput(value) {
71315
71731
  }
71316
71732
  async function prepareTaskAskOutput(result, masterKey) {
71317
71733
  const output = sanitizeWorkspaceAskOutput(result);
71318
- if (isRecord2(result.task)) {
71734
+ if (isRecord3(result.task)) {
71319
71735
  output.task = taskToJson(await decryptUserTask(result.task, masterKey));
71320
71736
  }
71321
- if (Array.isArray(result.tasks) && result.tasks.every(isRecord2)) {
71737
+ if (Array.isArray(result.tasks) && result.tasks.every(isRecord3)) {
71322
71738
  output.tasks = (await decryptUserTasks(result.tasks, masterKey)).map(taskToJson);
71323
71739
  }
71324
71740
  return output;
71325
71741
  }
71326
71742
  async function preparePlanAskOutput(result, masterKey) {
71327
71743
  const output = sanitizeWorkspaceAskOutput(result);
71328
- if (isRecord2(result.plan)) {
71744
+ if (isRecord3(result.plan)) {
71329
71745
  output.plan = planToJson(await decryptUserPlan(result.plan, masterKey));
71330
71746
  }
71331
- if (Array.isArray(result.plans) && result.plans.every(isRecord2)) {
71747
+ if (Array.isArray(result.plans) && result.plans.every(isRecord3)) {
71332
71748
  output.plans = (await decryptUserPlans(result.plans, masterKey)).map(planToJson);
71333
71749
  }
71334
71750
  return output;
@@ -73642,6 +74058,28 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
73642
74058
  }
73643
74059
  return;
73644
74060
  }
74061
+ if (subcommand === "files") {
74062
+ const chatId = rest[0];
74063
+ if (!chatId) {
74064
+ throw new Error("Missing chat ID. Usage: openmates chats files <chat-id> [--json]");
74065
+ }
74066
+ const resolvedId = chatId.toLowerCase() === "last" ? "__last__" : chatId;
74067
+ if (apiKey) {
74068
+ throw new Error("Chat file listing through --api-key is not supported; use an authenticated CLI session so encrypted chat embeds can be decrypted locally.");
74069
+ }
74070
+ if (!client.hasSession()) {
74071
+ const example = resolveExampleChatForOpen(resolvedId === "__last__" ? "1" : resolvedId);
74072
+ if (!example) {
74073
+ throw new Error(`Example chat '${chatId}' not found. Run 'openmates chats list' to see available examples.`);
74074
+ }
74075
+ printChatFiles(example.chat, example.files, flags, { example: true });
74076
+ return;
74077
+ }
74078
+ const { chat, messages } = await client.getChatMessages(resolvedId, teamContext);
74079
+ const result = await loadChatFileReferencesForCli(client, messages);
74080
+ printChatFiles(chat, result.files, flags, { errors: result.errors });
74081
+ return;
74082
+ }
73645
74083
  if (subcommand === "messages") {
73646
74084
  const chatId = rest[0];
73647
74085
  if (!chatId) {
@@ -74618,6 +75056,113 @@ function resolveExampleChatForOpen(target) {
74618
75056
  }
74619
75057
  return getExampleChatConversation(target);
74620
75058
  }
75059
+ function collectMessageEmbedIdsForFiles(messages) {
75060
+ const ids = /* @__PURE__ */ new Set();
75061
+ const inlineEmbedRefRe = /embed:([a-zA-Z0-9_.:-]+)/g;
75062
+ for (const message of messages) {
75063
+ for (const embedId of message.embedIds ?? []) {
75064
+ if (embedId) ids.add(embedId);
75065
+ }
75066
+ for (const match of Array.from((message.content ?? "").matchAll(inlineEmbedRefRe))) {
75067
+ if (match[1]) ids.add(match[1]);
75068
+ }
75069
+ for (const segment of parseMessageSegments(message.content ?? "")) {
75070
+ if (segment.type === "embed" && segment.value) ids.add(segment.value);
75071
+ }
75072
+ }
75073
+ return Array.from(ids);
75074
+ }
75075
+ function fileReferenceKey(file) {
75076
+ return `${file.embedId}:${file.title}`.toLowerCase();
75077
+ }
75078
+ function chatFileReferenceFromEmbed(embed) {
75079
+ return getEmbedFileReferences({
75080
+ embedId: embed.embedId,
75081
+ type: embed.type,
75082
+ content: embed.content,
75083
+ appId: embed.appId,
75084
+ skillId: embed.skillId,
75085
+ createdAt: embed.createdAt
75086
+ });
75087
+ }
75088
+ async function loadChatFileReferencesForCli(client, messages) {
75089
+ const queue = collectMessageEmbedIdsForFiles(messages);
75090
+ const visitedEmbeds = /* @__PURE__ */ new Set();
75091
+ const seenFiles = /* @__PURE__ */ new Set();
75092
+ const files = [];
75093
+ const errors = [];
75094
+ while (queue.length > 0) {
75095
+ const embedId = queue.shift();
75096
+ if (!embedId || visitedEmbeds.has(embedId)) continue;
75097
+ visitedEmbeds.add(embedId);
75098
+ try {
75099
+ const embed = await client.getEmbed(embedId);
75100
+ for (const file of chatFileReferenceFromEmbed(embed)) {
75101
+ const key = fileReferenceKey(file);
75102
+ if (seenFiles.has(key)) continue;
75103
+ files.push(file);
75104
+ seenFiles.add(key);
75105
+ }
75106
+ for (const childId of extractEmbedIdsFromContent(embed.content)) {
75107
+ if (childId && !visitedEmbeds.has(childId)) queue.push(childId);
75108
+ }
75109
+ } catch (error) {
75110
+ errors.push({
75111
+ embed_id: embedId,
75112
+ message: error instanceof Error ? error.message : String(error)
75113
+ });
75114
+ }
75115
+ }
75116
+ return { files, errors };
75117
+ }
75118
+ function chatFileToJson(file) {
75119
+ return {
75120
+ embed_id: file.embedId,
75121
+ content_ref: file.contentRef,
75122
+ title: file.title,
75123
+ type: file.type,
75124
+ node_type: file.nodeType,
75125
+ metadata: file.metadata,
75126
+ app_id: file.appId,
75127
+ skill_id: file.skillId,
75128
+ url: file.url,
75129
+ mime_type: file.mimeType
75130
+ };
75131
+ }
75132
+ function printChatFiles(chat, files, flags, options = {}) {
75133
+ if (flags.json === true) {
75134
+ printJson2({
75135
+ chat_id: chat.id,
75136
+ title: chat.title,
75137
+ source: options.example ? "example" : "chat",
75138
+ count: files.length,
75139
+ files: files.map(chatFileToJson),
75140
+ errors: options.errors ?? []
75141
+ });
75142
+ return;
75143
+ }
75144
+ const title = chat.title ?? chat.shortId ?? chat.id;
75145
+ header(`Files for ${title}`);
75146
+ if (options.example) {
75147
+ process.stdout.write("\x1B[2mPublic example chat files are resolved from bundled static embed metadata.\x1B[0m\n");
75148
+ }
75149
+ if (files.length === 0) {
75150
+ process.stdout.write("\x1B[2mNo files found for this chat.\x1B[0m\n");
75151
+ } else {
75152
+ for (const file of files) {
75153
+ const appSkill = [file.appId, file.skillId].filter(Boolean).join("/");
75154
+ const suffix = appSkill ? ` \x1B[2m${appSkill}\x1B[0m` : "";
75155
+ process.stdout.write(` \x1B[1m${file.title}\x1B[0m \x1B[2m${file.metadata}\x1B[0m${suffix}
75156
+ `);
75157
+ process.stdout.write(` \x1B[2m${file.contentRef}${file.url ? ` ${file.url}` : ""}\x1B[0m
75158
+ `);
75159
+ }
75160
+ }
75161
+ for (const error of options.errors ?? []) {
75162
+ process.stderr.write(`Warning: could not inspect embed ${error.embed_id}: ${error.message}
75163
+ `);
75164
+ }
75165
+ }
74621
75166
  async function openUrl(url) {
74622
75167
  const { exec: exec2 } = await import("child_process");
74623
75168
  const platform4 = process.platform;
@@ -80652,6 +81197,7 @@ function printChatsHelp() {
80652
81197
  openmates chats list [--limit <n>] [--page <n>] [--json]
80653
81198
  openmates chats show <chat-id> [--raw] [--json] [--all]
80654
81199
  openmates chats messages <chat-id> [--json]
81200
+ openmates chats files <chat-id> [--json]
80655
81201
  openmates chats <chat-id> add-to-project <project-id> [--folder <folder-id>] [--openmates-only|--repo-copy|--remote-cache-copy|--remote-copy] [--json]
80656
81202
  openmates chats <chat-id> remove-from-project <project-id> [--json]
80657
81203
  openmates chats fork <chat-id> --from-message <message-id> [--title <title>] [--json]
@@ -80679,6 +81225,11 @@ Options for 'show':
80679
81225
  --raw Show raw decrypted message content without rendering embeds
80680
81226
  or cleaning embed references. Useful for debugging.
80681
81227
 
81228
+ Options for 'files':
81229
+ Lists uploaded and generated files connected to a saved or public example chat.
81230
+ Saved chats require an authenticated CLI session so encrypted embeds can be
81231
+ decrypted locally. Public examples also work while logged out.
81232
+
80682
81233
  Options for 'fork', 'rewind', and 'retry':
80683
81234
  --from-message <id> Message boundary for non-destructive fork.
80684
81235
  --to-message <id> Message boundary to keep when rewinding.
@@ -80756,6 +81307,8 @@ Examples:
80756
81307
  openmates chats open gigantic-airplanes-transporting-rocket-parts
80757
81308
  openmates chats show d262cb68
80758
81309
  openmates chats messages d262cb68
81310
+ openmates chats files d262cb68
81311
+ openmates chats files example-audio-speak-friendly-welcome-message --json
80759
81312
  openmates chats fork d262cb68 --from-message 8f4e2a1c --title "Clean branch"
80760
81313
  openmates chats rewind d262cb68 --to-message 8f4e2a1c --send "Continue from here" --yes
80761
81314
  openmates chats retry d262cb68 --yes
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  requireExactConfirmation,
9
9
  resolveProjectContext,
10
10
  serializeToYaml
11
- } from "./chunk-JICSO2HA.js";
11
+ } from "./chunk-QLNFHEEW.js";
12
12
  import "./chunk-IWKP55ZB.js";
13
13
  import "./chunk-MLWBMJEN.js";
14
14
  export {
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  renderPlanList,
40
40
  renderSupportInfo,
41
41
  serializeToYaml
42
- } from "./chunk-JICSO2HA.js";
42
+ } from "./chunk-QLNFHEEW.js";
43
43
  import "./chunk-IWKP55ZB.js";
44
44
  import "./chunk-MLWBMJEN.js";
45
45
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmates",
3
- "version": "0.16.0-alpha.8",
3
+ "version": "0.16.0-alpha.9",
4
4
  "description": "OpenMates CLI and SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",