diff --git a/inception/inception-assistant/src/main/ts/src/AssistantPanel.svelte b/inception/inception-assistant/src/main/ts/src/AssistantPanel.svelte
index 2fc05db91a..ad3740bc00 100644
--- a/inception/inception-assistant/src/main/ts/src/AssistantPanel.svelte
+++ b/inception/inception-assistant/src/main/ts/src/AssistantPanel.svelte
@@ -78,6 +78,13 @@
let utteranceQueue: SpeechSynthesisUtterance[] = [];
let isSpeaking = false;
+ // Our canonical reference format
+ const refIdReplacementPattern = /\s*{{ref::([\w-]+)}}(\.*)/g
+
+ // Some models (deepseek-r1) can't be bothered to properly use our reference syntax
+ // and keep referring to documents using the "Document XXXXXXXX" syntax...
+ const docIdReplacementPattern = /\s*[Dd]ocument[\s,]+([0-9a-f]{8})(\.*)/g
+
marked.setOptions({
breaks: true,
gfm: true,
@@ -323,6 +330,43 @@
chatContainer.scrollHeight - threshold;
}
+ function copyToClipboard(message: MTextMessage) {
+ let usedReferences = {};
+ let text = message.message.replace(
+ refIdReplacementPattern,
+ (match: string, refId: string, dots: string) => {
+ const refSelector = (ref) => ref.id === refId;
+ const reference = message.references.find(refSelector);
+ const refNum = message.references.findIndex(refSelector) + 1;
+
+ if (reference) {
+ usedReferences[refNum] = reference;
+ return `[^${refNum}]`;
+ }
+
+ return match;
+ },
+ );
+
+ if (Object.keys(usedReferences).length > 0) {
+ text += "\n\nReferences:";
+ }
+
+ for (let refNum in usedReferences) {
+ const reference = usedReferences[refNum];
+ text += `\n[^${refNum}]: ${reference.documentName} (score: ${reference.score.toFixed(4)})`;
+ }
+
+ navigator.clipboard.writeText(text).then(
+ () => {
+ console.log("Copied to clipboard successfully!");
+ },
+ (err) => {
+ console.error("Could not copy text: ", err);
+ }
+ );
+ }
+
onMount(async () => {
connect();
});
@@ -346,43 +390,31 @@
const rawHtml = marked(trimmedMessage) as string;
var pureHtml = DOMPurify.sanitize(rawHtml, { RETURN_DOM: false });
- var refNum = 0;
-
- function replaceReferences(text, pattern) {
- return text.replace(
- pattern,
- (match, refId, dots) => {
- const reference = message.references.find(
- (ref) => ref.id === refId,
- );
- if (reference) {
- refNum++;
- return `${dots}${refNum}`;
- }
-
- // If no matching reference is found, keep the original text
- // console.trace(
- // `Reference with id ${refId} not found in message ${message.id}`
- // );
- return match;
- },
- );
- }
-
- // Our canonical reference format
- const refIdReplacementPattern = /\s*{{ref::([\w-]+)}}(\.*)/g
-
- // Some models (deepseek-r1) can't be bothered to properly use our reference syntax
- // and keep referring to documents using the "Document XXXXXXXX" syntax...
- const docIdReplacementPattern = /\s*[Dd]ocument[\s,]+([0-9a-f]{8})(\.*)/g
// Replace all references with the respective reference link
- pureHtml = replaceReferences(pureHtml, refIdReplacementPattern);
- pureHtml = replaceReferences(pureHtml, docIdReplacementPattern);
+ pureHtml = replaceReferencesWithHtmlLinks(message, pureHtml, refIdReplacementPattern);
+ pureHtml = replaceReferencesWithHtmlLinks(message, pureHtml, docIdReplacementPattern);
return pureHtml;
}
+ function replaceReferencesWithHtmlLinks(message, text, pattern) {
+ return text.replace(
+ pattern,
+ (match: string, refId: string, dots: string) => {
+ const refSelector = (ref) => ref.id === refId;
+ const reference = message.references.find(refSelector);
+ const refNum = message.references.findIndex(refSelector) + 1;
+
+ if (reference) {
+ return `${dots}${refNum}`;
+ }
+
+ return match;
+ },
+ );
+ }
+
function escapeXML(str) {
return str.replace(/[<>&'"]/g, (char) => {
switch (char) {
@@ -484,6 +516,14 @@
{/if}
{message.actor ? message.actor : message.role}
+ {#if !message.internal}
+
+ {/if}
{#if message.internal}
{#if message.performance}
-