@runtypelabs/persona 3.19.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.
- package/README.md +44 -1
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-cwY5HaFD.d.cts → types-CWPIj66R.d.cts} +19 -1
- package/dist/animations/{types-cwY5HaFD.d.ts → types-CWPIj66R.d.ts} +19 -1
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/index.cjs +46 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -4
- package/dist/index.d.ts +122 -4
- package/dist/index.global.js +79 -79
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +46 -46
- package/dist/index.js.map +1 -1
- package/dist/theme-editor.cjs +340 -11
- package/dist/theme-editor.d.cts +92 -1
- package/dist/theme-editor.d.ts +92 -1
- package/dist/theme-editor.js +340 -11
- package/package.json +1 -1
- package/src/client.test.ts +521 -0
- package/src/client.ts +150 -1
- package/src/components/message-bubble.test.ts +192 -0
- package/src/components/message-bubble.ts +200 -0
- package/src/index.ts +1 -0
- package/src/session.test.ts +123 -0
- package/src/session.ts +58 -4
- package/src/types.ts +102 -2
- package/src/ui.ts +18 -0
- package/src/utils/component-middleware.test.ts +134 -0
- package/src/utils/component-middleware.ts +44 -13
package/dist/theme-editor.cjs
CHANGED
|
@@ -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}`;
|
|
@@ -7505,7 +7610,8 @@ var AgentWidgetSession = class _AgentWidgetSession {
|
|
|
7505
7610
|
createdAt,
|
|
7506
7611
|
sequence,
|
|
7507
7612
|
streaming = false,
|
|
7508
|
-
voiceProcessing
|
|
7613
|
+
voiceProcessing,
|
|
7614
|
+
rawContent
|
|
7509
7615
|
} = options;
|
|
7510
7616
|
const messageId = id != null ? id : role === "user" ? generateUserMessageId() : role === "assistant" ? generateAssistantMessageId() : `system-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
7511
7617
|
const message = {
|
|
@@ -7518,7 +7624,8 @@ var AgentWidgetSession = class _AgentWidgetSession {
|
|
|
7518
7624
|
// Only include optional fields if provided
|
|
7519
7625
|
...llmContent !== void 0 && { llmContent },
|
|
7520
7626
|
...contentParts !== void 0 && { contentParts },
|
|
7521
|
-
...voiceProcessing !== void 0 && { voiceProcessing }
|
|
7627
|
+
...voiceProcessing !== void 0 && { voiceProcessing },
|
|
7628
|
+
...rawContent !== void 0 && { rawContent }
|
|
7522
7629
|
};
|
|
7523
7630
|
this.upsertMessage(message);
|
|
7524
7631
|
return message;
|
|
@@ -7583,7 +7690,9 @@ var AgentWidgetSession = class _AgentWidgetSession {
|
|
|
7583
7690
|
id,
|
|
7584
7691
|
createdAt,
|
|
7585
7692
|
sequence,
|
|
7586
|
-
streaming = false
|
|
7693
|
+
streaming = false,
|
|
7694
|
+
voiceProcessing,
|
|
7695
|
+
rawContent
|
|
7587
7696
|
} = options;
|
|
7588
7697
|
const messageId = id != null ? id : role === "user" ? generateUserMessageId() : role === "assistant" ? generateAssistantMessageId() : `system-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
7589
7698
|
const message = {
|
|
@@ -7594,7 +7703,9 @@ var AgentWidgetSession = class _AgentWidgetSession {
|
|
|
7594
7703
|
sequence: sequence != null ? sequence : this.nextSequence(),
|
|
7595
7704
|
streaming,
|
|
7596
7705
|
...llmContent !== void 0 && { llmContent },
|
|
7597
|
-
...contentParts !== void 0 && { contentParts }
|
|
7706
|
+
...contentParts !== void 0 && { contentParts },
|
|
7707
|
+
...voiceProcessing !== void 0 && { voiceProcessing },
|
|
7708
|
+
...rawContent !== void 0 && { rawContent }
|
|
7598
7709
|
};
|
|
7599
7710
|
results.push(message);
|
|
7600
7711
|
}
|
|
@@ -7602,6 +7713,48 @@ var AgentWidgetSession = class _AgentWidgetSession {
|
|
|
7602
7713
|
this.callbacks.onMessagesChanged([...this.messages]);
|
|
7603
7714
|
return results;
|
|
7604
7715
|
}
|
|
7716
|
+
/**
|
|
7717
|
+
* Convenience method for injecting a registered component directive as
|
|
7718
|
+
* an assistant message — the same shape Persona produces from a streamed
|
|
7719
|
+
* `{ "text": "...", "component": "...", "props": {...} }` payload.
|
|
7720
|
+
*
|
|
7721
|
+
* Sets `content` to `text`, `rawContent` to the JSON directive (so
|
|
7722
|
+
* `extractComponentDirectiveFromMessage` can find it), and forwards
|
|
7723
|
+
* `llmContent` / `id` / `createdAt` / `sequence`.
|
|
7724
|
+
*
|
|
7725
|
+
* @example
|
|
7726
|
+
* session.injectComponentDirective({
|
|
7727
|
+
* component: "DynamicForm",
|
|
7728
|
+
* props: { title: "Book a demo", fields: [...] },
|
|
7729
|
+
* text: "Share your details to book a demo.",
|
|
7730
|
+
* llmContent: "[Showed booking form]"
|
|
7731
|
+
* });
|
|
7732
|
+
*/
|
|
7733
|
+
injectComponentDirective(options) {
|
|
7734
|
+
const {
|
|
7735
|
+
component,
|
|
7736
|
+
props = {},
|
|
7737
|
+
text = "",
|
|
7738
|
+
llmContent,
|
|
7739
|
+
id,
|
|
7740
|
+
createdAt,
|
|
7741
|
+
sequence
|
|
7742
|
+
} = options;
|
|
7743
|
+
const directive = {
|
|
7744
|
+
text,
|
|
7745
|
+
component,
|
|
7746
|
+
props
|
|
7747
|
+
};
|
|
7748
|
+
return this.injectMessage({
|
|
7749
|
+
role: "assistant",
|
|
7750
|
+
content: text,
|
|
7751
|
+
rawContent: JSON.stringify(directive),
|
|
7752
|
+
...llmContent !== void 0 && { llmContent },
|
|
7753
|
+
...id !== void 0 && { id },
|
|
7754
|
+
...createdAt !== void 0 && { createdAt },
|
|
7755
|
+
...sequence !== void 0 && { sequence }
|
|
7756
|
+
});
|
|
7757
|
+
}
|
|
7605
7758
|
async sendMessage(rawInput, options) {
|
|
7606
7759
|
var _a, _b, _c, _d, _e;
|
|
7607
7760
|
const input = rawInput.trim();
|
|
@@ -11074,6 +11227,19 @@ var isSafeImageSrc = (src) => {
|
|
|
11074
11227
|
if (!src.includes(":")) return true;
|
|
11075
11228
|
return false;
|
|
11076
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
|
+
};
|
|
11077
11243
|
var MESSAGE_IMAGE_PREVIEW_MAX_WIDTH_PX = 320;
|
|
11078
11244
|
var MESSAGE_IMAGE_PREVIEW_MAX_HEIGHT_PX = 320;
|
|
11079
11245
|
var getMessageImageParts = (message) => {
|
|
@@ -11084,6 +11250,24 @@ var getMessageImageParts = (message) => {
|
|
|
11084
11250
|
(part) => part.type === "image" && typeof part.image === "string" && part.image.trim().length > 0
|
|
11085
11251
|
);
|
|
11086
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
|
+
};
|
|
11087
11271
|
var createMessageImagePreviews = (imageParts, hasVisibleText, onPreviewFailed) => {
|
|
11088
11272
|
if (imageParts.length === 0) return null;
|
|
11089
11273
|
try {
|
|
@@ -11152,6 +11336,109 @@ var createMessageImagePreviews = (imageParts, hasVisibleText, onPreviewFailed) =
|
|
|
11152
11336
|
return null;
|
|
11153
11337
|
}
|
|
11154
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
|
+
};
|
|
11155
11442
|
var createTypingIndicator = () => {
|
|
11156
11443
|
const container = document.createElement("div");
|
|
11157
11444
|
container.className = "persona-flex persona-items-center persona-space-x-1 persona-h-5 persona-mt-2";
|
|
@@ -11482,6 +11769,27 @@ var createStandardBubble = (message, transform, layoutConfig, actionsConfig, act
|
|
|
11482
11769
|
textContentDiv.style.display = "";
|
|
11483
11770
|
}
|
|
11484
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
|
+
}
|
|
11485
11793
|
bubble.appendChild(contentDiv);
|
|
11486
11794
|
if (showTimestamp && timestampPosition === "below" && message.createdAt) {
|
|
11487
11795
|
const timestamp = createTimestamp(message, timestampConfig);
|
|
@@ -15326,24 +15634,39 @@ function renderComponentDirective(directive, options) {
|
|
|
15326
15634
|
return null;
|
|
15327
15635
|
}
|
|
15328
15636
|
}
|
|
15637
|
+
function selectDirectiveSource(message) {
|
|
15638
|
+
if (typeof message.rawContent === "string" && message.rawContent.length > 0) {
|
|
15639
|
+
return message.rawContent;
|
|
15640
|
+
}
|
|
15641
|
+
if (typeof message.content === "string") {
|
|
15642
|
+
const trimmed = message.content.trim();
|
|
15643
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
15644
|
+
return message.content;
|
|
15645
|
+
}
|
|
15646
|
+
}
|
|
15647
|
+
return null;
|
|
15648
|
+
}
|
|
15329
15649
|
function hasComponentDirective(message) {
|
|
15330
|
-
|
|
15650
|
+
const source = selectDirectiveSource(message);
|
|
15651
|
+
if (!source) return false;
|
|
15331
15652
|
try {
|
|
15332
|
-
const parsed = JSON.parse(
|
|
15653
|
+
const parsed = JSON.parse(source);
|
|
15333
15654
|
return typeof parsed === "object" && parsed !== null && "component" in parsed && typeof parsed.component === "string";
|
|
15334
15655
|
} catch {
|
|
15335
15656
|
return false;
|
|
15336
15657
|
}
|
|
15337
15658
|
}
|
|
15338
15659
|
function extractComponentDirectiveFromMessage(message) {
|
|
15339
|
-
|
|
15660
|
+
const source = selectDirectiveSource(message);
|
|
15661
|
+
if (!source) return null;
|
|
15340
15662
|
try {
|
|
15341
|
-
const parsed = JSON.parse(
|
|
15663
|
+
const parsed = JSON.parse(source);
|
|
15342
15664
|
if (typeof parsed === "object" && parsed !== null && "component" in parsed && typeof parsed.component === "string") {
|
|
15665
|
+
const directive = parsed;
|
|
15343
15666
|
return {
|
|
15344
|
-
component:
|
|
15345
|
-
props:
|
|
15346
|
-
raw:
|
|
15667
|
+
component: directive.component,
|
|
15668
|
+
props: directive.props && typeof directive.props === "object" && directive.props !== null ? directive.props : {},
|
|
15669
|
+
raw: source
|
|
15347
15670
|
};
|
|
15348
15671
|
}
|
|
15349
15672
|
} catch {
|
|
@@ -20743,6 +21066,12 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
|
|
|
20743
21066
|
}
|
|
20744
21067
|
return session.injectMessageBatch(optionsList);
|
|
20745
21068
|
},
|
|
21069
|
+
injectComponentDirective(options) {
|
|
21070
|
+
if (!open && isPanelToggleable()) {
|
|
21071
|
+
setOpenState(true, "system");
|
|
21072
|
+
}
|
|
21073
|
+
return session.injectComponentDirective(options);
|
|
21074
|
+
},
|
|
20746
21075
|
/** @deprecated Use injectMessage() instead */
|
|
20747
21076
|
injectTestMessage(event) {
|
|
20748
21077
|
if (!open && isPanelToggleable()) {
|
package/dist/theme-editor.d.cts
CHANGED
|
@@ -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
|
*/
|
|
@@ -4097,6 +4115,22 @@ type InjectMessageOptions = {
|
|
|
4097
4115
|
* Consumers can detect this in `messageTransform` to render custom UI.
|
|
4098
4116
|
*/
|
|
4099
4117
|
voiceProcessing?: boolean;
|
|
4118
|
+
/**
|
|
4119
|
+
* Raw structured payload (typically a JSON string) representing the
|
|
4120
|
+
* full directive that produced this message — e.g. `{ "text": "...",
|
|
4121
|
+
* "component": "Foo", "props": {...} }`.
|
|
4122
|
+
*
|
|
4123
|
+
* Mirrors the field populated by stream parsers during normal LLM
|
|
4124
|
+
* responses. Set this when injecting a message that should render as a
|
|
4125
|
+
* component directive (`hasComponentDirective` /
|
|
4126
|
+
* `extractComponentDirectiveFromMessage` look at `rawContent` first).
|
|
4127
|
+
*
|
|
4128
|
+
* Priority for the API payload remains:
|
|
4129
|
+
* `contentParts > llmContent > rawContent > content`. Pass `llmContent`
|
|
4130
|
+
* alongside `rawContent` if the LLM should see something other than the
|
|
4131
|
+
* raw directive.
|
|
4132
|
+
*/
|
|
4133
|
+
rawContent?: string;
|
|
4100
4134
|
};
|
|
4101
4135
|
/**
|
|
4102
4136
|
* Options for injecting assistant messages (most common case).
|
|
@@ -4113,6 +4147,57 @@ type InjectUserMessageOptions = Omit<InjectMessageOptions, "role">;
|
|
|
4113
4147
|
* Role defaults to 'system'.
|
|
4114
4148
|
*/
|
|
4115
4149
|
type InjectSystemMessageOptions = Omit<InjectMessageOptions, "role">;
|
|
4150
|
+
/**
|
|
4151
|
+
* Options for injecting an assistant message that renders as a component
|
|
4152
|
+
* directive — sugar over `injectAssistantMessage` for the common case of
|
|
4153
|
+
* "render this registered component, same as if the LLM had emitted it".
|
|
4154
|
+
*
|
|
4155
|
+
* Equivalent to calling `injectAssistantMessage({ content: text, rawContent:
|
|
4156
|
+
* JSON.stringify({ text, component, props }), llmContent })`.
|
|
4157
|
+
*
|
|
4158
|
+
* @example
|
|
4159
|
+
* widget.injectComponentDirective({
|
|
4160
|
+
* component: "DynamicForm",
|
|
4161
|
+
* props: { title: "Book a demo", fields: [...] },
|
|
4162
|
+
* text: "Share your details to book a demo.",
|
|
4163
|
+
* llmContent: "[Showed booking form]"
|
|
4164
|
+
* });
|
|
4165
|
+
*/
|
|
4166
|
+
type InjectComponentDirectiveOptions = {
|
|
4167
|
+
/**
|
|
4168
|
+
* Name of a renderer registered via `componentRegistry.register(...)`.
|
|
4169
|
+
*/
|
|
4170
|
+
component: string;
|
|
4171
|
+
/**
|
|
4172
|
+
* Props passed to the component renderer.
|
|
4173
|
+
*/
|
|
4174
|
+
props?: Record<string, unknown>;
|
|
4175
|
+
/**
|
|
4176
|
+
* Bubble copy displayed above (or with) the rendered component.
|
|
4177
|
+
* Mirrors the `text` field in a streamed JSON directive.
|
|
4178
|
+
* @default ""
|
|
4179
|
+
*/
|
|
4180
|
+
text?: string;
|
|
4181
|
+
/**
|
|
4182
|
+
* Content sent to the LLM in API requests. When omitted, the raw
|
|
4183
|
+
* directive JSON is what the LLM would see (per the standard
|
|
4184
|
+
* priority chain). Provide a redacted/short version to avoid sending
|
|
4185
|
+
* the full directive in subsequent turns.
|
|
4186
|
+
*/
|
|
4187
|
+
llmContent?: string;
|
|
4188
|
+
/**
|
|
4189
|
+
* Optional message ID. If omitted, an assistant id is auto-generated.
|
|
4190
|
+
*/
|
|
4191
|
+
id?: string;
|
|
4192
|
+
/**
|
|
4193
|
+
* Optional creation timestamp (ISO string). If omitted, uses current time.
|
|
4194
|
+
*/
|
|
4195
|
+
createdAt?: string;
|
|
4196
|
+
/**
|
|
4197
|
+
* Optional sequence number for ordering.
|
|
4198
|
+
*/
|
|
4199
|
+
sequence?: number;
|
|
4200
|
+
};
|
|
4116
4201
|
type PersonaArtifactRecord = {
|
|
4117
4202
|
id: string;
|
|
4118
4203
|
artifactType: PersonaArtifactKind;
|
|
@@ -4480,6 +4565,12 @@ type Controller = {
|
|
|
4480
4565
|
* Inject multiple messages in a single batch with one sort and one render pass.
|
|
4481
4566
|
*/
|
|
4482
4567
|
injectMessageBatch: (optionsList: InjectMessageOptions[]) => AgentWidgetMessage[];
|
|
4568
|
+
/**
|
|
4569
|
+
* Convenience method for injecting an assistant message that renders as a
|
|
4570
|
+
* registered component — same shape Persona produces from a streamed
|
|
4571
|
+
* `{ "text": "...", "component": "...", "props": {...} }` payload.
|
|
4572
|
+
*/
|
|
4573
|
+
injectComponentDirective: (options: InjectComponentDirectiveOptions) => AgentWidgetMessage;
|
|
4483
4574
|
/**
|
|
4484
4575
|
* @deprecated Use injectMessage() instead.
|
|
4485
4576
|
*/
|
package/dist/theme-editor.d.ts
CHANGED
|
@@ -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
|
*/
|
|
@@ -4097,6 +4115,22 @@ type InjectMessageOptions = {
|
|
|
4097
4115
|
* Consumers can detect this in `messageTransform` to render custom UI.
|
|
4098
4116
|
*/
|
|
4099
4117
|
voiceProcessing?: boolean;
|
|
4118
|
+
/**
|
|
4119
|
+
* Raw structured payload (typically a JSON string) representing the
|
|
4120
|
+
* full directive that produced this message — e.g. `{ "text": "...",
|
|
4121
|
+
* "component": "Foo", "props": {...} }`.
|
|
4122
|
+
*
|
|
4123
|
+
* Mirrors the field populated by stream parsers during normal LLM
|
|
4124
|
+
* responses. Set this when injecting a message that should render as a
|
|
4125
|
+
* component directive (`hasComponentDirective` /
|
|
4126
|
+
* `extractComponentDirectiveFromMessage` look at `rawContent` first).
|
|
4127
|
+
*
|
|
4128
|
+
* Priority for the API payload remains:
|
|
4129
|
+
* `contentParts > llmContent > rawContent > content`. Pass `llmContent`
|
|
4130
|
+
* alongside `rawContent` if the LLM should see something other than the
|
|
4131
|
+
* raw directive.
|
|
4132
|
+
*/
|
|
4133
|
+
rawContent?: string;
|
|
4100
4134
|
};
|
|
4101
4135
|
/**
|
|
4102
4136
|
* Options for injecting assistant messages (most common case).
|
|
@@ -4113,6 +4147,57 @@ type InjectUserMessageOptions = Omit<InjectMessageOptions, "role">;
|
|
|
4113
4147
|
* Role defaults to 'system'.
|
|
4114
4148
|
*/
|
|
4115
4149
|
type InjectSystemMessageOptions = Omit<InjectMessageOptions, "role">;
|
|
4150
|
+
/**
|
|
4151
|
+
* Options for injecting an assistant message that renders as a component
|
|
4152
|
+
* directive — sugar over `injectAssistantMessage` for the common case of
|
|
4153
|
+
* "render this registered component, same as if the LLM had emitted it".
|
|
4154
|
+
*
|
|
4155
|
+
* Equivalent to calling `injectAssistantMessage({ content: text, rawContent:
|
|
4156
|
+
* JSON.stringify({ text, component, props }), llmContent })`.
|
|
4157
|
+
*
|
|
4158
|
+
* @example
|
|
4159
|
+
* widget.injectComponentDirective({
|
|
4160
|
+
* component: "DynamicForm",
|
|
4161
|
+
* props: { title: "Book a demo", fields: [...] },
|
|
4162
|
+
* text: "Share your details to book a demo.",
|
|
4163
|
+
* llmContent: "[Showed booking form]"
|
|
4164
|
+
* });
|
|
4165
|
+
*/
|
|
4166
|
+
type InjectComponentDirectiveOptions = {
|
|
4167
|
+
/**
|
|
4168
|
+
* Name of a renderer registered via `componentRegistry.register(...)`.
|
|
4169
|
+
*/
|
|
4170
|
+
component: string;
|
|
4171
|
+
/**
|
|
4172
|
+
* Props passed to the component renderer.
|
|
4173
|
+
*/
|
|
4174
|
+
props?: Record<string, unknown>;
|
|
4175
|
+
/**
|
|
4176
|
+
* Bubble copy displayed above (or with) the rendered component.
|
|
4177
|
+
* Mirrors the `text` field in a streamed JSON directive.
|
|
4178
|
+
* @default ""
|
|
4179
|
+
*/
|
|
4180
|
+
text?: string;
|
|
4181
|
+
/**
|
|
4182
|
+
* Content sent to the LLM in API requests. When omitted, the raw
|
|
4183
|
+
* directive JSON is what the LLM would see (per the standard
|
|
4184
|
+
* priority chain). Provide a redacted/short version to avoid sending
|
|
4185
|
+
* the full directive in subsequent turns.
|
|
4186
|
+
*/
|
|
4187
|
+
llmContent?: string;
|
|
4188
|
+
/**
|
|
4189
|
+
* Optional message ID. If omitted, an assistant id is auto-generated.
|
|
4190
|
+
*/
|
|
4191
|
+
id?: string;
|
|
4192
|
+
/**
|
|
4193
|
+
* Optional creation timestamp (ISO string). If omitted, uses current time.
|
|
4194
|
+
*/
|
|
4195
|
+
createdAt?: string;
|
|
4196
|
+
/**
|
|
4197
|
+
* Optional sequence number for ordering.
|
|
4198
|
+
*/
|
|
4199
|
+
sequence?: number;
|
|
4200
|
+
};
|
|
4116
4201
|
type PersonaArtifactRecord = {
|
|
4117
4202
|
id: string;
|
|
4118
4203
|
artifactType: PersonaArtifactKind;
|
|
@@ -4480,6 +4565,12 @@ type Controller = {
|
|
|
4480
4565
|
* Inject multiple messages in a single batch with one sort and one render pass.
|
|
4481
4566
|
*/
|
|
4482
4567
|
injectMessageBatch: (optionsList: InjectMessageOptions[]) => AgentWidgetMessage[];
|
|
4568
|
+
/**
|
|
4569
|
+
* Convenience method for injecting an assistant message that renders as a
|
|
4570
|
+
* registered component — same shape Persona produces from a streamed
|
|
4571
|
+
* `{ "text": "...", "component": "...", "props": {...} }` payload.
|
|
4572
|
+
*/
|
|
4573
|
+
injectComponentDirective: (options: InjectComponentDirectiveOptions) => AgentWidgetMessage;
|
|
4483
4574
|
/**
|
|
4484
4575
|
* @deprecated Use injectMessage() instead.
|
|
4485
4576
|
*/
|