openmates 0.16.0-alpha.7 → 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.
@@ -45200,7 +45200,7 @@ var audioGenerateProductSuccessChimeChat = {
45200
45200
  content: "example_chats.audio_generate_product_success_chime.message_2",
45201
45201
  created_at: 1786382154,
45202
45202
  user_message_id: "0fe80324-42f5-4b87-9e11-0b0d8f36c9d5",
45203
- response_credits: 17,
45203
+ response_credits: 31,
45204
45204
  category: "general_knowledge",
45205
45205
  model_name: "Gemini 3.5 Flash-Lite"
45206
45206
  }
@@ -45234,6 +45234,23 @@ var audioGenerateProductSuccessChimeChat = {
45234
45234
  created_at: 1786382147,
45235
45235
  updated_at: 1786382147,
45236
45236
  tool_inference_iterations: 1
45237
+ },
45238
+ {
45239
+ id: "example-audio-generate-product-success-chime-usage-2",
45240
+ type: "skill_execution",
45241
+ source: "chat",
45242
+ app_id: "audio",
45243
+ skill_id: "generate",
45244
+ model_used: "elevenlabs/eleven_text_to_sound_v2",
45245
+ credits: 14,
45246
+ server_provider: "ElevenLabs",
45247
+ server_region: "US",
45248
+ chat_id: "example-audio-generate-product-success-chime",
45249
+ message_id: "0fe80324-42f5-4b87-9e11-0b0d8f36c9d5",
45250
+ created_at: 1786382144,
45251
+ updated_at: 1786382144,
45252
+ tool_inference_iterations: 0,
45253
+ code_run_duration_seconds: 0.679
45237
45254
  }
45238
45255
  ],
45239
45256
  metadata: {
@@ -45266,7 +45283,7 @@ var audioSpeakFriendlyWelcomeMessageChat = {
45266
45283
  content: "example_chats.audio_speak_friendly_welcome_message.message_2",
45267
45284
  created_at: 1786382255,
45268
45285
  user_message_id: "b39cb42f-ec3e-45ec-9339-801b54c7cb03",
45269
- response_credits: 18,
45286
+ response_credits: 28,
45270
45287
  category: "onboarding_support",
45271
45288
  model_name: "Gemini 3.5 Flash-Lite"
45272
45289
  }
@@ -45300,6 +45317,23 @@ var audioSpeakFriendlyWelcomeMessageChat = {
45300
45317
  created_at: 1786382249,
45301
45318
  updated_at: 1786382249,
45302
45319
  tool_inference_iterations: 1
45320
+ },
45321
+ {
45322
+ id: "example-audio-speak-friendly-welcome-message-usage-2",
45323
+ type: "skill_execution",
45324
+ source: "chat",
45325
+ app_id: "audio",
45326
+ skill_id: "speak",
45327
+ model_used: "elevenlabs/eleven_flash_v2_5",
45328
+ credits: 10,
45329
+ server_provider: "ElevenLabs",
45330
+ server_region: "US",
45331
+ chat_id: "example-audio-speak-friendly-welcome-message",
45332
+ message_id: "b39cb42f-ec3e-45ec-9339-801b54c7cb03",
45333
+ created_at: 1786382246,
45334
+ updated_at: 1786382246,
45335
+ tool_inference_iterations: 0,
45336
+ code_run_duration_seconds: 4.968
45303
45337
  }
45304
45338
  ],
45305
45339
  metadata: {
@@ -45417,6 +45451,420 @@ var ALL_EXAMPLE_CHATS = [
45417
45451
  audioSpeakFriendlyWelcomeMessageChat
45418
45452
  ].sort((a, b) => a.metadata.order - b.metadata.order);
45419
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
+
45420
45868
  // ../ui/src/i18n/locales/en.json
45421
45869
  var en_default = {
45422
45870
  activity: {
@@ -66284,8 +66732,10 @@ function getExampleChatConversation(query) {
66284
66732
  category: message.category ?? chat.category,
66285
66733
  modelName: message.model_name ?? null,
66286
66734
  createdAt: message.created_at,
66287
- embedIds: []
66735
+ embedIds: extractReferencedExampleEmbedIds([message], chat.embeds)
66288
66736
  })),
66737
+ embeds: chat.embeds,
66738
+ files: collectExampleChatFileReferences(chat.embeds, chat.messages),
66289
66739
  followUpSuggestions: chat.follow_up_suggestions.map(translate)
66290
66740
  };
66291
66741
  }
@@ -70178,7 +70628,7 @@ async function requestProjectRemoteOperation(options) {
70178
70628
  throw new ProjectRequesterError("source_offline", "The selected Project source is offline.");
70179
70629
  }
70180
70630
  const timeoutMs = options.timeoutMs ?? REMOTE_PROTOCOL_TIMEOUT_MS;
70181
- let sourceSessionId = stringField2(options.source, "source_session_id");
70631
+ let sourceSessionId = stringField3(options.source, "source_session_id");
70182
70632
  let keyEpoch = numberField(options.source, "key_epoch");
70183
70633
  let routingIdentity = null;
70184
70634
  if (!sourceSessionId || !keyEpoch) {
@@ -70330,7 +70780,7 @@ function parseJsonObject(value) {
70330
70780
  }
70331
70781
  throw new ProjectRequesterError("invalid_remote_payload", "The Project source returned an invalid payload.");
70332
70782
  }
70333
- function stringField2(value, key) {
70783
+ function stringField3(value, key) {
70334
70784
  return typeof value[key] === "string" && value[key] ? value[key] : null;
70335
70785
  }
70336
70786
  function numberField(value, key) {
@@ -71263,7 +71713,7 @@ function splitTaskAskInstruction(instruction) {
71263
71713
  const suffix = instruction.includes(":") ? instruction.split(":").slice(1).join(":") : instruction;
71264
71714
  return suffix.split(/[,;]\s*/).map((title) => title.trim()).filter(Boolean).map((title) => ({ title }));
71265
71715
  }
71266
- function isRecord2(value) {
71716
+ function isRecord3(value) {
71267
71717
  return typeof value === "object" && value !== null && !Array.isArray(value);
71268
71718
  }
71269
71719
  function isPrivateCliOutputKey(key) {
@@ -71271,7 +71721,7 @@ function isPrivateCliOutputKey(key) {
71271
71721
  }
71272
71722
  function sanitizeWorkspaceAskOutput(value) {
71273
71723
  if (Array.isArray(value)) return value.map((item) => sanitizeWorkspaceAskOutput(item));
71274
- if (!isRecord2(value)) return value;
71724
+ if (!isRecord3(value)) return value;
71275
71725
  const sanitized = {};
71276
71726
  for (const [key, nested] of Object.entries(value)) {
71277
71727
  if (isPrivateCliOutputKey(key)) continue;
@@ -71281,20 +71731,20 @@ function sanitizeWorkspaceAskOutput(value) {
71281
71731
  }
71282
71732
  async function prepareTaskAskOutput(result, masterKey) {
71283
71733
  const output = sanitizeWorkspaceAskOutput(result);
71284
- if (isRecord2(result.task)) {
71734
+ if (isRecord3(result.task)) {
71285
71735
  output.task = taskToJson(await decryptUserTask(result.task, masterKey));
71286
71736
  }
71287
- if (Array.isArray(result.tasks) && result.tasks.every(isRecord2)) {
71737
+ if (Array.isArray(result.tasks) && result.tasks.every(isRecord3)) {
71288
71738
  output.tasks = (await decryptUserTasks(result.tasks, masterKey)).map(taskToJson);
71289
71739
  }
71290
71740
  return output;
71291
71741
  }
71292
71742
  async function preparePlanAskOutput(result, masterKey) {
71293
71743
  const output = sanitizeWorkspaceAskOutput(result);
71294
- if (isRecord2(result.plan)) {
71744
+ if (isRecord3(result.plan)) {
71295
71745
  output.plan = planToJson(await decryptUserPlan(result.plan, masterKey));
71296
71746
  }
71297
- if (Array.isArray(result.plans) && result.plans.every(isRecord2)) {
71747
+ if (Array.isArray(result.plans) && result.plans.every(isRecord3)) {
71298
71748
  output.plans = (await decryptUserPlans(result.plans, masterKey)).map(planToJson);
71299
71749
  }
71300
71750
  return output;
@@ -73608,6 +74058,28 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
73608
74058
  }
73609
74059
  return;
73610
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
+ }
73611
74083
  if (subcommand === "messages") {
73612
74084
  const chatId = rest[0];
73613
74085
  if (!chatId) {
@@ -74584,6 +75056,113 @@ function resolveExampleChatForOpen(target) {
74584
75056
  }
74585
75057
  return getExampleChatConversation(target);
74586
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
+ }
74587
75166
  async function openUrl(url) {
74588
75167
  const { exec: exec2 } = await import("child_process");
74589
75168
  const platform4 = process.platform;
@@ -80618,6 +81197,7 @@ function printChatsHelp() {
80618
81197
  openmates chats list [--limit <n>] [--page <n>] [--json]
80619
81198
  openmates chats show <chat-id> [--raw] [--json] [--all]
80620
81199
  openmates chats messages <chat-id> [--json]
81200
+ openmates chats files <chat-id> [--json]
80621
81201
  openmates chats <chat-id> add-to-project <project-id> [--folder <folder-id>] [--openmates-only|--repo-copy|--remote-cache-copy|--remote-copy] [--json]
80622
81202
  openmates chats <chat-id> remove-from-project <project-id> [--json]
80623
81203
  openmates chats fork <chat-id> --from-message <message-id> [--title <title>] [--json]
@@ -80645,6 +81225,11 @@ Options for 'show':
80645
81225
  --raw Show raw decrypted message content without rendering embeds
80646
81226
  or cleaning embed references. Useful for debugging.
80647
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
+
80648
81233
  Options for 'fork', 'rewind', and 'retry':
80649
81234
  --from-message <id> Message boundary for non-destructive fork.
80650
81235
  --to-message <id> Message boundary to keep when rewinding.
@@ -80722,6 +81307,8 @@ Examples:
80722
81307
  openmates chats open gigantic-airplanes-transporting-rocket-parts
80723
81308
  openmates chats show d262cb68
80724
81309
  openmates chats messages d262cb68
81310
+ openmates chats files d262cb68
81311
+ openmates chats files example-audio-speak-friendly-welcome-message --json
80725
81312
  openmates chats fork d262cb68 --from-message 8f4e2a1c --title "Clean branch"
80726
81313
  openmates chats rewind d262cb68 --to-message 8f4e2a1c --send "Continue from here" --yes
80727
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-Y2VI2HJI.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-Y2VI2HJI.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.7",
3
+ "version": "0.16.0-alpha.9",
4
4
  "description": "OpenMates CLI and SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",