@runtypelabs/persona 3.20.0 → 3.21.0

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.
@@ -3790,6 +3790,28 @@ var SequenceReorderBuffer = class {
3790
3790
  // src/client.ts
3791
3791
  var DEFAULT_ENDPOINT = "https://api.runtype.com/v1/dispatch";
3792
3792
  var DEFAULT_CLIENT_API_BASE = "https://api.runtype.com";
3793
+ function filenameFromMediaType(mediaType) {
3794
+ var _a, _b;
3795
+ const lower = mediaType.toLowerCase();
3796
+ const knownExtensions = {
3797
+ "application/pdf": "pdf",
3798
+ "application/json": "json",
3799
+ "application/zip": "zip",
3800
+ "text/plain": "txt",
3801
+ "text/csv": "csv",
3802
+ "text/markdown": "md"
3803
+ };
3804
+ const ext = knownExtensions[lower];
3805
+ if (ext) return `attachment.${ext}`;
3806
+ const slash = lower.indexOf("/");
3807
+ if (slash > 0) {
3808
+ const subtype = (_b = (_a = lower.slice(slash + 1).split(";")[0]) == null ? void 0 : _a.trim()) != null ? _b : "";
3809
+ if (subtype && subtype !== "octet-stream" && /^[a-z0-9.+-]+$/i.test(subtype)) {
3810
+ return `attachment.${subtype}`;
3811
+ }
3812
+ }
3813
+ return "attachment";
3814
+ }
3793
3815
  var hasValidContent = (message) => {
3794
3816
  if (message.contentParts && message.contentParts.length > 0) {
3795
3817
  return true;
@@ -5742,6 +5764,89 @@ var AgentWidgetClient = class {
5742
5764
  }
5743
5765
  }
5744
5766
  }
5767
+ } else if (payloadType === "agent_media") {
5768
+ const rawMedia = Array.isArray(payload.media) ? payload.media : [];
5769
+ const mediaContentParts = [];
5770
+ for (const part of rawMedia) {
5771
+ if (!part || typeof part !== "object") continue;
5772
+ const rec = part;
5773
+ const partType = typeof rec.type === "string" ? rec.type : void 0;
5774
+ const rawMediaType = typeof rec.mediaType === "string" ? rec.mediaType.toLowerCase() : "";
5775
+ let src = null;
5776
+ let mediaType = "";
5777
+ if (partType === "media") {
5778
+ const data = typeof rec.data === "string" ? rec.data : void 0;
5779
+ if (!data) continue;
5780
+ mediaType = rawMediaType.length > 0 ? rawMediaType : "application/octet-stream";
5781
+ src = `data:${mediaType};base64,${data}`;
5782
+ } else if (partType === "image-url") {
5783
+ const url = typeof rec.url === "string" ? rec.url : void 0;
5784
+ if (!url) continue;
5785
+ mediaType = rawMediaType;
5786
+ src = url;
5787
+ } else if (partType === "file-url") {
5788
+ const url = typeof rec.url === "string" ? rec.url : void 0;
5789
+ if (!url) continue;
5790
+ mediaType = rawMediaType;
5791
+ src = url;
5792
+ } else {
5793
+ continue;
5794
+ }
5795
+ if (!src) continue;
5796
+ if (partType === "image-url" || mediaType.startsWith("image/")) {
5797
+ mediaContentParts.push({
5798
+ type: "image",
5799
+ image: src,
5800
+ ...mediaType ? { mimeType: mediaType } : {}
5801
+ });
5802
+ } else if (mediaType.startsWith("audio/")) {
5803
+ mediaContentParts.push({
5804
+ type: "audio",
5805
+ audio: src,
5806
+ mimeType: mediaType
5807
+ });
5808
+ } else if (mediaType.startsWith("video/")) {
5809
+ mediaContentParts.push({
5810
+ type: "video",
5811
+ video: src,
5812
+ mimeType: mediaType
5813
+ });
5814
+ } else {
5815
+ const resolvedMediaType = mediaType || "application/octet-stream";
5816
+ mediaContentParts.push({
5817
+ type: "file",
5818
+ data: src,
5819
+ mimeType: resolvedMediaType,
5820
+ filename: filenameFromMediaType(resolvedMediaType)
5821
+ });
5822
+ }
5823
+ }
5824
+ if (mediaContentParts.length > 0) {
5825
+ const seq = nextSequence();
5826
+ const toolCallIdRaw = payload.toolCallId;
5827
+ const mediaIdSuffix = typeof toolCallIdRaw === "string" && toolCallIdRaw.length > 0 ? `${toolCallIdRaw}-${seq}` : String(seq);
5828
+ const mediaMessage = {
5829
+ id: `agent-media-${mediaIdSuffix}`,
5830
+ role: "assistant",
5831
+ content: "",
5832
+ contentParts: mediaContentParts,
5833
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5834
+ streaming: false,
5835
+ sequence: seq,
5836
+ agentMetadata: {
5837
+ executionId: payload.executionId,
5838
+ iteration: payload.iteration
5839
+ }
5840
+ };
5841
+ emitMessage(mediaMessage);
5842
+ const prevAssistant = assistantMessage;
5843
+ if (prevAssistant) {
5844
+ prevAssistant.streaming = false;
5845
+ emitMessage(prevAssistant);
5846
+ }
5847
+ assistantMessage = null;
5848
+ assistantMessageRef.current = null;
5849
+ }
5745
5850
  } else if (payloadType === "agent_iteration_complete") {
5746
5851
  } else if (payloadType === "agent_reflection" || payloadType === "agent_reflect") {
5747
5852
  const reflectionId = `agent-reflection-${payload.executionId}-${payload.iteration}`;
@@ -11122,6 +11227,19 @@ var isSafeImageSrc = (src) => {
11122
11227
  if (!src.includes(":")) return true;
11123
11228
  return false;
11124
11229
  };
11230
+ var isSafeMediaSrc = (src) => {
11231
+ const lower = src.toLowerCase();
11232
+ if (lower.startsWith("javascript:")) return false;
11233
+ if (lower.startsWith("data:text/html")) return false;
11234
+ if (lower.startsWith("data:text/javascript")) return false;
11235
+ if (lower.startsWith("data:text/xml")) return false;
11236
+ if (lower.startsWith("data:application/xhtml")) return false;
11237
+ if (lower.startsWith("data:image/svg+xml")) return false;
11238
+ if (/^(?:https?|blob):/i.test(src)) return true;
11239
+ if (lower.startsWith("data:")) return true;
11240
+ if (!src.includes(":")) return true;
11241
+ return false;
11242
+ };
11125
11243
  var MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX = 320;
11126
11244
  var MESSAGE_IMAGE_PREVIEW_MAX_HEIGHT_PX = 320;
11127
11245
  var getMessageImageParts = (message) => {
@@ -11132,6 +11250,24 @@ var getMessageImageParts = (message) => {
11132
11250
  (part) => part.type === "image" && typeof part.image === "string" && part.image.trim().length > 0
11133
11251
  );
11134
11252
  };
11253
+ var getMessageAudioParts = (message) => {
11254
+ if (!message.contentParts || message.contentParts.length === 0) return [];
11255
+ return message.contentParts.filter(
11256
+ (part) => part.type === "audio" && typeof part.audio === "string" && part.audio.trim().length > 0
11257
+ );
11258
+ };
11259
+ var getMessageVideoParts = (message) => {
11260
+ if (!message.contentParts || message.contentParts.length === 0) return [];
11261
+ return message.contentParts.filter(
11262
+ (part) => part.type === "video" && typeof part.video === "string" && part.video.trim().length > 0
11263
+ );
11264
+ };
11265
+ var getMessageFileParts = (message) => {
11266
+ if (!message.contentParts || message.contentParts.length === 0) return [];
11267
+ return message.contentParts.filter(
11268
+ (part) => part.type === "file" && typeof part.data === "string" && part.data.trim().length > 0
11269
+ );
11270
+ };
11135
11271
  var createMessageImagePreviews = (imageParts, hasVisibleText, onPreviewFailed) => {
11136
11272
  if (imageParts.length === 0) return null;
11137
11273
  try {
@@ -11200,6 +11336,109 @@ var createMessageImagePreviews = (imageParts, hasVisibleText, onPreviewFailed) =
11200
11336
  return null;
11201
11337
  }
11202
11338
  };
11339
+ var createMessageAudioPreviews = (audioParts) => {
11340
+ if (audioParts.length === 0) return null;
11341
+ try {
11342
+ const container = createElement(
11343
+ "div",
11344
+ "persona-flex persona-flex-col persona-gap-2"
11345
+ );
11346
+ container.setAttribute("data-message-attachments", "audio");
11347
+ let visible = 0;
11348
+ audioParts.forEach((part) => {
11349
+ if (!isSafeMediaSrc(part.audio)) return;
11350
+ const audioElement = createElement("audio");
11351
+ audioElement.controls = true;
11352
+ audioElement.preload = "metadata";
11353
+ audioElement.src = part.audio;
11354
+ audioElement.style.display = "block";
11355
+ audioElement.style.width = "100%";
11356
+ audioElement.style.maxWidth = `${MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX}px`;
11357
+ container.appendChild(audioElement);
11358
+ visible += 1;
11359
+ });
11360
+ if (visible === 0) {
11361
+ container.remove();
11362
+ return null;
11363
+ }
11364
+ return container;
11365
+ } catch {
11366
+ return null;
11367
+ }
11368
+ };
11369
+ var createMessageVideoPreviews = (videoParts) => {
11370
+ if (videoParts.length === 0) return null;
11371
+ try {
11372
+ const container = createElement(
11373
+ "div",
11374
+ "persona-flex persona-flex-col persona-gap-2"
11375
+ );
11376
+ container.setAttribute("data-message-attachments", "video");
11377
+ let visible = 0;
11378
+ videoParts.forEach((part) => {
11379
+ if (!isSafeMediaSrc(part.video)) return;
11380
+ const videoElement = createElement("video");
11381
+ videoElement.controls = true;
11382
+ videoElement.preload = "metadata";
11383
+ videoElement.src = part.video;
11384
+ videoElement.style.display = "block";
11385
+ videoElement.style.width = "100%";
11386
+ videoElement.style.maxWidth = `${MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX}px`;
11387
+ videoElement.style.maxHeight = `${MESSAGE_IMAGE_PREVIEW_MAX_HEIGHT_PX}px`;
11388
+ videoElement.style.borderRadius = "10px";
11389
+ videoElement.style.backgroundColor = "var(--persona-attachment-image-bg, var(--persona-container, #f3f4f6))";
11390
+ container.appendChild(videoElement);
11391
+ visible += 1;
11392
+ });
11393
+ if (visible === 0) {
11394
+ container.remove();
11395
+ return null;
11396
+ }
11397
+ return container;
11398
+ } catch {
11399
+ return null;
11400
+ }
11401
+ };
11402
+ var createMessageFilePreviews = (fileParts) => {
11403
+ if (fileParts.length === 0) return null;
11404
+ try {
11405
+ const container = createElement(
11406
+ "div",
11407
+ "persona-flex persona-flex-col persona-gap-2"
11408
+ );
11409
+ container.setAttribute("data-message-attachments", "files");
11410
+ let visible = 0;
11411
+ fileParts.forEach((part) => {
11412
+ if (!isSafeMediaSrc(part.data)) return;
11413
+ const link = createElement("a");
11414
+ link.href = part.data;
11415
+ link.download = part.filename;
11416
+ link.target = "_blank";
11417
+ link.rel = "noopener noreferrer";
11418
+ link.textContent = part.filename;
11419
+ link.className = "persona-message-file-attachment";
11420
+ link.style.display = "inline-flex";
11421
+ link.style.alignItems = "center";
11422
+ link.style.gap = "6px";
11423
+ link.style.padding = "6px 10px";
11424
+ link.style.borderRadius = "8px";
11425
+ link.style.fontSize = "0.875rem";
11426
+ link.style.textDecoration = "underline";
11427
+ link.style.backgroundColor = "var(--persona-attachment-file-bg, var(--persona-container, #f3f4f6))";
11428
+ link.style.border = "1px solid var(--persona-attachment-file-border, var(--persona-border, #e5e7eb))";
11429
+ link.style.color = "inherit";
11430
+ container.appendChild(link);
11431
+ visible += 1;
11432
+ });
11433
+ if (visible === 0) {
11434
+ container.remove();
11435
+ return null;
11436
+ }
11437
+ return container;
11438
+ } catch {
11439
+ return null;
11440
+ }
11441
+ };
11203
11442
  var createTypingIndicator = () => {
11204
11443
  const container = document.createElement("div");
11205
11444
  container.className = "persona-flex persona-items-center persona-space-x-1 persona-h-5 persona-mt-2";
@@ -11530,6 +11769,27 @@ var createStandardBubble = (message, transform, layoutConfig, actionsConfig, act
11530
11769
  textContentDiv.style.display = "";
11531
11770
  }
11532
11771
  }
11772
+ const audioParts = getMessageAudioParts(message);
11773
+ if (audioParts.length > 0) {
11774
+ const audioPreviews = createMessageAudioPreviews(audioParts);
11775
+ if (audioPreviews) {
11776
+ bubble.appendChild(audioPreviews);
11777
+ }
11778
+ }
11779
+ const videoParts = getMessageVideoParts(message);
11780
+ if (videoParts.length > 0) {
11781
+ const videoPreviews = createMessageVideoPreviews(videoParts);
11782
+ if (videoPreviews) {
11783
+ bubble.appendChild(videoPreviews);
11784
+ }
11785
+ }
11786
+ const fileParts = getMessageFileParts(message);
11787
+ if (fileParts.length > 0) {
11788
+ const filePreviews = createMessageFilePreviews(fileParts);
11789
+ if (filePreviews) {
11790
+ bubble.appendChild(filePreviews);
11791
+ }
11792
+ }
11533
11793
  bubble.appendChild(contentDiv);
11534
11794
  if (showTimestamp && timestampPosition === "below" && message.createdAt) {
11535
11795
  const timestamp = createTimestamp(message, timestampConfig);
@@ -728,10 +728,28 @@ type FileContentPart = {
728
728
  mimeType: string;
729
729
  filename: string;
730
730
  };
731
+ /**
732
+ * Audio content part for multi-modal messages
733
+ * Supports base64 data URIs or URLs
734
+ */
735
+ type AudioContentPart = {
736
+ type: 'audio';
737
+ audio: string;
738
+ mimeType?: string;
739
+ };
740
+ /**
741
+ * Video content part for multi-modal messages
742
+ * Supports base64 data URIs or URLs
743
+ */
744
+ type VideoContentPart = {
745
+ type: 'video';
746
+ video: string;
747
+ mimeType?: string;
748
+ };
731
749
  /**
732
750
  * Union type for all content part types
733
751
  */
734
- type ContentPart = TextContentPart | ImageContentPart | FileContentPart;
752
+ type ContentPart = TextContentPart | ImageContentPart | FileContentPart | AudioContentPart | VideoContentPart;
735
753
  /**
736
754
  * Message content can be a simple string or an array of content parts
737
755
  */
@@ -728,10 +728,28 @@ type FileContentPart = {
728
728
  mimeType: string;
729
729
  filename: string;
730
730
  };
731
+ /**
732
+ * Audio content part for multi-modal messages
733
+ * Supports base64 data URIs or URLs
734
+ */
735
+ type AudioContentPart = {
736
+ type: 'audio';
737
+ audio: string;
738
+ mimeType?: string;
739
+ };
740
+ /**
741
+ * Video content part for multi-modal messages
742
+ * Supports base64 data URIs or URLs
743
+ */
744
+ type VideoContentPart = {
745
+ type: 'video';
746
+ video: string;
747
+ mimeType?: string;
748
+ };
731
749
  /**
732
750
  * Union type for all content part types
733
751
  */
734
- type ContentPart = TextContentPart | ImageContentPart | FileContentPart;
752
+ type ContentPart = TextContentPart | ImageContentPart | FileContentPart | AudioContentPart | VideoContentPart;
735
753
  /**
736
754
  * Message content can be a simple string or an array of content parts
737
755
  */
@@ -3679,6 +3679,28 @@ var SequenceReorderBuffer = class {
3679
3679
  // src/client.ts
3680
3680
  var DEFAULT_ENDPOINT = "https://api.runtype.com/v1/dispatch";
3681
3681
  var DEFAULT_CLIENT_API_BASE = "https://api.runtype.com";
3682
+ function filenameFromMediaType(mediaType) {
3683
+ var _a, _b;
3684
+ const lower = mediaType.toLowerCase();
3685
+ const knownExtensions = {
3686
+ "application/pdf": "pdf",
3687
+ "application/json": "json",
3688
+ "application/zip": "zip",
3689
+ "text/plain": "txt",
3690
+ "text/csv": "csv",
3691
+ "text/markdown": "md"
3692
+ };
3693
+ const ext = knownExtensions[lower];
3694
+ if (ext) return `attachment.${ext}`;
3695
+ const slash = lower.indexOf("/");
3696
+ if (slash > 0) {
3697
+ const subtype = (_b = (_a = lower.slice(slash + 1).split(";")[0]) == null ? void 0 : _a.trim()) != null ? _b : "";
3698
+ if (subtype && subtype !== "octet-stream" && /^[a-z0-9.+-]+$/i.test(subtype)) {
3699
+ return `attachment.${subtype}`;
3700
+ }
3701
+ }
3702
+ return "attachment";
3703
+ }
3682
3704
  var hasValidContent = (message) => {
3683
3705
  if (message.contentParts && message.contentParts.length > 0) {
3684
3706
  return true;
@@ -5631,6 +5653,89 @@ var AgentWidgetClient = class {
5631
5653
  }
5632
5654
  }
5633
5655
  }
5656
+ } else if (payloadType === "agent_media") {
5657
+ const rawMedia = Array.isArray(payload.media) ? payload.media : [];
5658
+ const mediaContentParts = [];
5659
+ for (const part of rawMedia) {
5660
+ if (!part || typeof part !== "object") continue;
5661
+ const rec = part;
5662
+ const partType = typeof rec.type === "string" ? rec.type : void 0;
5663
+ const rawMediaType = typeof rec.mediaType === "string" ? rec.mediaType.toLowerCase() : "";
5664
+ let src = null;
5665
+ let mediaType = "";
5666
+ if (partType === "media") {
5667
+ const data = typeof rec.data === "string" ? rec.data : void 0;
5668
+ if (!data) continue;
5669
+ mediaType = rawMediaType.length > 0 ? rawMediaType : "application/octet-stream";
5670
+ src = `data:${mediaType};base64,${data}`;
5671
+ } else if (partType === "image-url") {
5672
+ const url = typeof rec.url === "string" ? rec.url : void 0;
5673
+ if (!url) continue;
5674
+ mediaType = rawMediaType;
5675
+ src = url;
5676
+ } else if (partType === "file-url") {
5677
+ const url = typeof rec.url === "string" ? rec.url : void 0;
5678
+ if (!url) continue;
5679
+ mediaType = rawMediaType;
5680
+ src = url;
5681
+ } else {
5682
+ continue;
5683
+ }
5684
+ if (!src) continue;
5685
+ if (partType === "image-url" || mediaType.startsWith("image/")) {
5686
+ mediaContentParts.push({
5687
+ type: "image",
5688
+ image: src,
5689
+ ...mediaType ? { mimeType: mediaType } : {}
5690
+ });
5691
+ } else if (mediaType.startsWith("audio/")) {
5692
+ mediaContentParts.push({
5693
+ type: "audio",
5694
+ audio: src,
5695
+ mimeType: mediaType
5696
+ });
5697
+ } else if (mediaType.startsWith("video/")) {
5698
+ mediaContentParts.push({
5699
+ type: "video",
5700
+ video: src,
5701
+ mimeType: mediaType
5702
+ });
5703
+ } else {
5704
+ const resolvedMediaType = mediaType || "application/octet-stream";
5705
+ mediaContentParts.push({
5706
+ type: "file",
5707
+ data: src,
5708
+ mimeType: resolvedMediaType,
5709
+ filename: filenameFromMediaType(resolvedMediaType)
5710
+ });
5711
+ }
5712
+ }
5713
+ if (mediaContentParts.length > 0) {
5714
+ const seq = nextSequence();
5715
+ const toolCallIdRaw = payload.toolCallId;
5716
+ const mediaIdSuffix = typeof toolCallIdRaw === "string" && toolCallIdRaw.length > 0 ? `${toolCallIdRaw}-${seq}` : String(seq);
5717
+ const mediaMessage = {
5718
+ id: `agent-media-${mediaIdSuffix}`,
5719
+ role: "assistant",
5720
+ content: "",
5721
+ contentParts: mediaContentParts,
5722
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5723
+ streaming: false,
5724
+ sequence: seq,
5725
+ agentMetadata: {
5726
+ executionId: payload.executionId,
5727
+ iteration: payload.iteration
5728
+ }
5729
+ };
5730
+ emitMessage(mediaMessage);
5731
+ const prevAssistant = assistantMessage;
5732
+ if (prevAssistant) {
5733
+ prevAssistant.streaming = false;
5734
+ emitMessage(prevAssistant);
5735
+ }
5736
+ assistantMessage = null;
5737
+ assistantMessageRef.current = null;
5738
+ }
5634
5739
  } else if (payloadType === "agent_iteration_complete") {
5635
5740
  } else if (payloadType === "agent_reflection" || payloadType === "agent_reflect") {
5636
5741
  const reflectionId = `agent-reflection-${payload.executionId}-${payload.iteration}`;
@@ -11125,6 +11230,19 @@ var isSafeImageSrc = (src) => {
11125
11230
  if (!src.includes(":")) return true;
11126
11231
  return false;
11127
11232
  };
11233
+ var isSafeMediaSrc = (src) => {
11234
+ const lower = src.toLowerCase();
11235
+ if (lower.startsWith("javascript:")) return false;
11236
+ if (lower.startsWith("data:text/html")) return false;
11237
+ if (lower.startsWith("data:text/javascript")) return false;
11238
+ if (lower.startsWith("data:text/xml")) return false;
11239
+ if (lower.startsWith("data:application/xhtml")) return false;
11240
+ if (lower.startsWith("data:image/svg+xml")) return false;
11241
+ if (/^(?:https?|blob):/i.test(src)) return true;
11242
+ if (lower.startsWith("data:")) return true;
11243
+ if (!src.includes(":")) return true;
11244
+ return false;
11245
+ };
11128
11246
  var MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX = 320;
11129
11247
  var MESSAGE_IMAGE_PREVIEW_MAX_HEIGHT_PX = 320;
11130
11248
  var getMessageImageParts = (message) => {
@@ -11135,6 +11253,24 @@ var getMessageImageParts = (message) => {
11135
11253
  (part) => part.type === "image" && typeof part.image === "string" && part.image.trim().length > 0
11136
11254
  );
11137
11255
  };
11256
+ var getMessageAudioParts = (message) => {
11257
+ if (!message.contentParts || message.contentParts.length === 0) return [];
11258
+ return message.contentParts.filter(
11259
+ (part) => part.type === "audio" && typeof part.audio === "string" && part.audio.trim().length > 0
11260
+ );
11261
+ };
11262
+ var getMessageVideoParts = (message) => {
11263
+ if (!message.contentParts || message.contentParts.length === 0) return [];
11264
+ return message.contentParts.filter(
11265
+ (part) => part.type === "video" && typeof part.video === "string" && part.video.trim().length > 0
11266
+ );
11267
+ };
11268
+ var getMessageFileParts = (message) => {
11269
+ if (!message.contentParts || message.contentParts.length === 0) return [];
11270
+ return message.contentParts.filter(
11271
+ (part) => part.type === "file" && typeof part.data === "string" && part.data.trim().length > 0
11272
+ );
11273
+ };
11138
11274
  var createMessageImagePreviews = (imageParts, hasVisibleText, onPreviewFailed) => {
11139
11275
  if (imageParts.length === 0) return null;
11140
11276
  try {
@@ -11203,6 +11339,109 @@ var createMessageImagePreviews = (imageParts, hasVisibleText, onPreviewFailed) =
11203
11339
  return null;
11204
11340
  }
11205
11341
  };
11342
+ var createMessageAudioPreviews = (audioParts) => {
11343
+ if (audioParts.length === 0) return null;
11344
+ try {
11345
+ const container = createElement(
11346
+ "div",
11347
+ "persona-flex persona-flex-col persona-gap-2"
11348
+ );
11349
+ container.setAttribute("data-message-attachments", "audio");
11350
+ let visible = 0;
11351
+ audioParts.forEach((part) => {
11352
+ if (!isSafeMediaSrc(part.audio)) return;
11353
+ const audioElement = createElement("audio");
11354
+ audioElement.controls = true;
11355
+ audioElement.preload = "metadata";
11356
+ audioElement.src = part.audio;
11357
+ audioElement.style.display = "block";
11358
+ audioElement.style.width = "100%";
11359
+ audioElement.style.maxWidth = `${MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX}px`;
11360
+ container.appendChild(audioElement);
11361
+ visible += 1;
11362
+ });
11363
+ if (visible === 0) {
11364
+ container.remove();
11365
+ return null;
11366
+ }
11367
+ return container;
11368
+ } catch {
11369
+ return null;
11370
+ }
11371
+ };
11372
+ var createMessageVideoPreviews = (videoParts) => {
11373
+ if (videoParts.length === 0) return null;
11374
+ try {
11375
+ const container = createElement(
11376
+ "div",
11377
+ "persona-flex persona-flex-col persona-gap-2"
11378
+ );
11379
+ container.setAttribute("data-message-attachments", "video");
11380
+ let visible = 0;
11381
+ videoParts.forEach((part) => {
11382
+ if (!isSafeMediaSrc(part.video)) return;
11383
+ const videoElement = createElement("video");
11384
+ videoElement.controls = true;
11385
+ videoElement.preload = "metadata";
11386
+ videoElement.src = part.video;
11387
+ videoElement.style.display = "block";
11388
+ videoElement.style.width = "100%";
11389
+ videoElement.style.maxWidth = `${MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX}px`;
11390
+ videoElement.style.maxHeight = `${MESSAGE_IMAGE_PREVIEW_MAX_HEIGHT_PX}px`;
11391
+ videoElement.style.borderRadius = "10px";
11392
+ videoElement.style.backgroundColor = "var(--persona-attachment-image-bg, var(--persona-container, #f3f4f6))";
11393
+ container.appendChild(videoElement);
11394
+ visible += 1;
11395
+ });
11396
+ if (visible === 0) {
11397
+ container.remove();
11398
+ return null;
11399
+ }
11400
+ return container;
11401
+ } catch {
11402
+ return null;
11403
+ }
11404
+ };
11405
+ var createMessageFilePreviews = (fileParts) => {
11406
+ if (fileParts.length === 0) return null;
11407
+ try {
11408
+ const container = createElement(
11409
+ "div",
11410
+ "persona-flex persona-flex-col persona-gap-2"
11411
+ );
11412
+ container.setAttribute("data-message-attachments", "files");
11413
+ let visible = 0;
11414
+ fileParts.forEach((part) => {
11415
+ if (!isSafeMediaSrc(part.data)) return;
11416
+ const link = createElement("a");
11417
+ link.href = part.data;
11418
+ link.download = part.filename;
11419
+ link.target = "_blank";
11420
+ link.rel = "noopener noreferrer";
11421
+ link.textContent = part.filename;
11422
+ link.className = "persona-message-file-attachment";
11423
+ link.style.display = "inline-flex";
11424
+ link.style.alignItems = "center";
11425
+ link.style.gap = "6px";
11426
+ link.style.padding = "6px 10px";
11427
+ link.style.borderRadius = "8px";
11428
+ link.style.fontSize = "0.875rem";
11429
+ link.style.textDecoration = "underline";
11430
+ link.style.backgroundColor = "var(--persona-attachment-file-bg, var(--persona-container, #f3f4f6))";
11431
+ link.style.border = "1px solid var(--persona-attachment-file-border, var(--persona-border, #e5e7eb))";
11432
+ link.style.color = "inherit";
11433
+ container.appendChild(link);
11434
+ visible += 1;
11435
+ });
11436
+ if (visible === 0) {
11437
+ container.remove();
11438
+ return null;
11439
+ }
11440
+ return container;
11441
+ } catch {
11442
+ return null;
11443
+ }
11444
+ };
11206
11445
  var createTypingIndicator = () => {
11207
11446
  const container = document.createElement("div");
11208
11447
  container.className = "persona-flex persona-items-center persona-space-x-1 persona-h-5 persona-mt-2";
@@ -11533,6 +11772,27 @@ var createStandardBubble = (message, transform, layoutConfig, actionsConfig, act
11533
11772
  textContentDiv.style.display = "";
11534
11773
  }
11535
11774
  }
11775
+ const audioParts = getMessageAudioParts(message);
11776
+ if (audioParts.length > 0) {
11777
+ const audioPreviews = createMessageAudioPreviews(audioParts);
11778
+ if (audioPreviews) {
11779
+ bubble.appendChild(audioPreviews);
11780
+ }
11781
+ }
11782
+ const videoParts = getMessageVideoParts(message);
11783
+ if (videoParts.length > 0) {
11784
+ const videoPreviews = createMessageVideoPreviews(videoParts);
11785
+ if (videoPreviews) {
11786
+ bubble.appendChild(videoPreviews);
11787
+ }
11788
+ }
11789
+ const fileParts = getMessageFileParts(message);
11790
+ if (fileParts.length > 0) {
11791
+ const filePreviews = createMessageFilePreviews(fileParts);
11792
+ if (filePreviews) {
11793
+ bubble.appendChild(filePreviews);
11794
+ }
11795
+ }
11536
11796
  bubble.appendChild(contentDiv);
11537
11797
  if (showTimestamp && timestampPosition === "below" && message.createdAt) {
11538
11798
  const timestamp = createTimestamp(message, timestampConfig);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/persona",
3
- "version": "3.20.0",
3
+ "version": "3.21.0",
4
4
  "description": "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",