@meistrari/chat-nuxt 3.14.0-rc.2 → 3.14.0-rc.4
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/dist/module.json +1 -1
- package/dist/runtime/assets/css/markstream.css +1 -1
- package/dist/runtime/citations/components/chat-url-citation.d.vue.ts +7 -0
- package/dist/runtime/citations/components/chat-url-citation.vue +74 -0
- package/dist/runtime/citations/components/chat-url-citation.vue.d.ts +7 -0
- package/dist/runtime/citations/url-citation.d.ts +8 -0
- package/dist/runtime/citations/url-citation.js +32 -0
- package/dist/runtime/files/components/chat-vault-link.vue +12 -5
- package/dist/runtime/messages/components/chat-debug-workbench.vue +20 -2
- package/dist/runtime/messages/components/chat-message-bubble.vue +1 -2
- package/dist/runtime/messages/components/chat-message-list.d.vue.ts +4 -1
- package/dist/runtime/messages/components/chat-message-list.vue +77 -42
- package/dist/runtime/messages/components/chat-message-list.vue.d.ts +4 -1
- package/dist/runtime/messages/components/reasoning/chat-reasoning-collapsible-content.d.vue.ts +16 -0
- package/dist/runtime/messages/components/reasoning/chat-reasoning-collapsible-content.vue +25 -0
- package/dist/runtime/messages/components/reasoning/chat-reasoning-collapsible-content.vue.d.ts +16 -0
- package/dist/runtime/messages/components/reasoning/chat-reasoning-message.d.vue.ts +0 -4
- package/dist/runtime/messages/components/reasoning/chat-reasoning-message.vue +44 -59
- package/dist/runtime/messages/components/reasoning/chat-reasoning-message.vue.d.ts +0 -4
- package/dist/runtime/messages/components/reasoning/chat-reasoning-steps.d.vue.ts +1 -5
- package/dist/runtime/messages/components/reasoning/chat-reasoning-steps.vue +4 -26
- package/dist/runtime/messages/components/reasoning/chat-reasoning-steps.vue.d.ts +1 -5
- package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.d.vue.ts +0 -1
- package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.vue +44 -84
- package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.vue.d.ts +0 -1
- package/dist/runtime/messages/components/reasoning/chat-reasoning-tool-row.d.vue.ts +20 -0
- package/dist/runtime/messages/components/reasoning/chat-reasoning-tool-row.vue +91 -0
- package/dist/runtime/messages/components/reasoning/chat-reasoning-tool-row.vue.d.ts +20 -0
- package/dist/runtime/messages/components/widgets/chat-bash-widget.vue +33 -39
- package/dist/runtime/messages/components/widgets/chat-doc-sdk-widget.vue +19 -31
- package/dist/runtime/messages/components/widgets/chat-generic-tool-widget.vue +139 -213
- package/dist/runtime/messages/components/widgets/chat-grep-widget.vue +53 -61
- package/dist/runtime/messages/components/widgets/chat-read-widget.d.vue.ts +1 -0
- package/dist/runtime/messages/components/widgets/chat-read-widget.vue +57 -43
- package/dist/runtime/messages/components/widgets/chat-read-widget.vue.d.ts +1 -0
- package/dist/runtime/messages/components/widgets/chat-tela-skill-widget.vue +25 -42
- package/dist/runtime/messages/components/widgets/chat-thinking-widget.vue +11 -30
- package/dist/runtime/messages/components/widgets/chat-tool-section.d.vue.ts +23 -0
- package/dist/runtime/messages/components/widgets/chat-tool-section.vue +38 -0
- package/dist/runtime/messages/components/widgets/chat-tool-section.vue.d.ts +23 -0
- package/dist/runtime/messages/components/widgets/chat-web-search-widget.vue +22 -37
- package/dist/runtime/messages/components/widgets/chat-workstation-query-widget.vue +44 -54
- package/dist/runtime/messages/components/widgets/chat-write-widget.vue +23 -35
- package/dist/runtime/messages/composables/chat-scroll-stickiness.d.ts +28 -0
- package/dist/runtime/messages/composables/chat-scroll-stickiness.js +181 -0
- package/dist/runtime/messages/debug/chat-debug-scenarios.js +742 -2
- package/dist/runtime/messages/debug/use-chat-debug-diagnostics.d.ts +4 -0
- package/dist/runtime/messages/debug/use-chat-debug-diagnostics.js +19 -2
- package/dist/runtime/messages/reasoning-step-key.d.ts +2 -0
- package/dist/runtime/messages/reasoning-step-key.js +5 -0
- package/dist/runtime/messages/tool-registry.d.ts +1 -0
- package/dist/runtime/messages/tool-registry.js +29 -2
- package/dist/runtime/server/api/citation-favicon.get.d.ts +2 -0
- package/dist/runtime/server/api/citation-favicon.get.js +47 -0
- package/package.json +2 -2
package/dist/module.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.markstream-vue{color:#171717;font-family:Inter,"Inter Fallback: Arial",sans-serif;font-size:16px;font-weight:400;letter-spacing:-.15px;line-height:24px;--list-item-marker:#a3a3a3;--list-item-counter-marker:#262626}.markstream-vue code,.markstream-vue kbd,.markstream-vue pre,.markstream-vue samp{font-family:Geist Mono Variable,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:13px;font-variation-settings:normal;line-height:1.5}.markstream-vue ol,.markstream-vue ul{margin:8px 0;padding-left:1.5em}.markstream-vue .hr-node{border-color:#e5e5e5;border-top-width:.5px;margin-bottom:24px;margin-top:24px}.markstream-vue .strong-node{font-weight:580}.markstream-vue .list-node.list-node{margin-bottom:8px;margin-left:4px;margin-top:8px;padding-left:1em}.markstream-vue ul{list-style:disc;list-style-position:outside}.markstream-vue ol{list-style:decimal;list-style-position:outside}.markstream-vue li{margin:4px 0}.markstream-vue .paragraph-node{margin:0}.markstream-vue .my-8{margin-bottom:8px;margin-top:8px}.markstream-vue .heading-node.heading-1,.markstream-vue h1{font-size:24px;font-weight:540;letter-spacing:-.8px;line-height:28px;margin:24px 0 16px}.markstream-vue .heading-node.heading-2,.markstream-vue h2{font-size:20px;font-weight:540;letter-spacing:-.5px;line-height:24px;margin:20px 0 12px}.markstream-vue .heading-node.heading-3,.markstream-vue h3{font-size:20px;font-weight:540;letter-spacing:-.5px;line-height:24px;margin:16px 0 8px}.markstream-vue .heading-node.heading-4,.markstream-vue h4{font-size:16px;font-weight:540;letter-spacing:-.2px;line-height:20px;margin:12px 0 6px}.markstream-vue .heading-node.heading-5,.markstream-vue h5{font-size:14px;font-weight:540;letter-spacing:-.15px;line-height:16px;margin:8px 0 4px}.markstream-vue .heading-node.heading-6,.markstream-vue h6{font-size:12px;font-weight:540;letter-spacing:-.1px;line-height:14px;margin:8px 0 4px}.markstream-vue [class*=tooltip],[class*=tooltip-element]{background-color:var(--neutral-900,#1a1a1a)!important;border-radius:4px;color:#fff!important;font-size:12px;padding:4px 8px}.mention-tag{align-items:center;border-radius:9999px;display:inline-flex;font-size:.875em;font-weight:500;gap:4px;padding:2px 8px;vertical-align:middle;white-space:nowrap}.mention-tag-file{background-color:rgba(127,189,247,.12);color:#7fbdf7}.mention-tag-skill{background-color:rgba(155,111,222,.12);color:#9b6fde}.mention-tag-canvas{background-color:rgba(234,161,65,.12);color:#d4882e}.mention-tag>span[class*=i-ph]{flex-shrink:0}
|
|
1
|
+
.markstream-vue{color:#171717;font-family:Inter,"Inter Fallback: Arial",sans-serif;font-size:16px;font-weight:400;letter-spacing:-.15px;line-height:24px;--list-item-marker:#a3a3a3;--list-item-counter-marker:#262626}.markstream-vue code,.markstream-vue kbd,.markstream-vue pre,.markstream-vue samp{font-family:Geist Mono Variable,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:13px;font-variation-settings:normal;line-height:1.5}.markstream-vue ol,.markstream-vue ul{margin:8px 0;padding-left:1.5em}.markstream-vue .hr-node{border-color:#e5e5e5;border-top-width:.5px;margin-bottom:24px;margin-top:24px}.markstream-vue .strong-node{font-weight:580}.markstream-vue .list-node.list-node{margin-bottom:8px;margin-left:4px;margin-top:8px;padding-left:1em}.markstream-vue ul{list-style:disc;list-style-position:outside}.markstream-vue ol{list-style:decimal;list-style-position:outside}.markstream-vue li{margin:4px 0}.markstream-vue .paragraph-node{margin:0}.markstream-vue>.node-slot[data-node-type=paragraph]:not(:first-child){margin-top:12px}.markstream-vue .my-8{margin-bottom:8px;margin-top:8px}.markstream-vue .heading-node.heading-1,.markstream-vue h1{font-size:24px;font-weight:540;letter-spacing:-.8px;line-height:28px;margin:24px 0 16px}.markstream-vue .heading-node.heading-2,.markstream-vue h2{font-size:20px;font-weight:540;letter-spacing:-.5px;line-height:24px;margin:20px 0 12px}.markstream-vue .heading-node.heading-3,.markstream-vue h3{font-size:20px;font-weight:540;letter-spacing:-.5px;line-height:24px;margin:16px 0 8px}.markstream-vue .heading-node.heading-4,.markstream-vue h4{font-size:16px;font-weight:540;letter-spacing:-.2px;line-height:20px;margin:12px 0 6px}.markstream-vue .heading-node.heading-5,.markstream-vue h5{font-size:14px;font-weight:540;letter-spacing:-.15px;line-height:16px;margin:8px 0 4px}.markstream-vue .heading-node.heading-6,.markstream-vue h6{font-size:12px;font-weight:540;letter-spacing:-.1px;line-height:14px;margin:8px 0 4px}.markstream-vue [class*=tooltip],[class*=tooltip-element]{background-color:var(--neutral-900,#1a1a1a)!important;border-radius:4px;color:#fff!important;font-size:12px;padding:4px 8px}.mention-tag{align-items:center;border-radius:9999px;display:inline-flex;font-size:.875em;font-weight:500;gap:4px;padding:2px 8px;vertical-align:middle;white-space:nowrap}.mention-tag-file{background-color:rgba(127,189,247,.12);color:#7fbdf7}.mention-tag-skill{background-color:rgba(155,111,222,.12);color:#9b6fde}.mention-tag-canvas{background-color:rgba(234,161,65,.12);color:#d4882e}.mention-tag>span[class*=i-ph]{flex-shrink:0}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UrlCitationPreview } from '../url-citation.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
citation: UrlCitationPreview;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
citation: { type: Object, required: true }
|
|
4
|
+
});
|
|
5
|
+
const faviconFailed = ref(false);
|
|
6
|
+
const shouldLoadFavicon = ref(false);
|
|
7
|
+
function activatePreviewAssets() {
|
|
8
|
+
shouldLoadFavicon.value = true;
|
|
9
|
+
}
|
|
10
|
+
const accessibleLabel = computed(() => `${props.citation.sourceLabel}: ${props.citation.title}`);
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<TelaHoverCard
|
|
15
|
+
align="start"
|
|
16
|
+
side="top"
|
|
17
|
+
:side-offset="8"
|
|
18
|
+
:open-delay="160"
|
|
19
|
+
:close-delay="100"
|
|
20
|
+
>
|
|
21
|
+
<a
|
|
22
|
+
:href="citation.href"
|
|
23
|
+
target="_blank"
|
|
24
|
+
rel="noopener noreferrer"
|
|
25
|
+
class="url-citation-pill"
|
|
26
|
+
body-11-medium
|
|
27
|
+
:aria-label="accessibleLabel"
|
|
28
|
+
@pointerenter="activatePreviewAssets"
|
|
29
|
+
@focus="activatePreviewAssets"
|
|
30
|
+
>
|
|
31
|
+
<img
|
|
32
|
+
v-if="shouldLoadFavicon && !faviconFailed"
|
|
33
|
+
:src="citation.faviconUrl"
|
|
34
|
+
alt=""
|
|
35
|
+
class="url-citation-favicon"
|
|
36
|
+
referrerpolicy="no-referrer"
|
|
37
|
+
@error="faviconFailed = true"
|
|
38
|
+
>
|
|
39
|
+
<span v-else i-ph-globe-simple class="url-citation-fallback" aria-hidden="true" />
|
|
40
|
+
<span>{{ citation.sourceLabel }}</span>
|
|
41
|
+
</a>
|
|
42
|
+
|
|
43
|
+
<template #content>
|
|
44
|
+
<div class="url-citation-card" bg-white flex="~ col" gap-10px p-12px>
|
|
45
|
+
<div flex items-center gap-7px min-w-0>
|
|
46
|
+
<img
|
|
47
|
+
v-if="shouldLoadFavicon && !faviconFailed"
|
|
48
|
+
:src="citation.faviconUrl"
|
|
49
|
+
alt=""
|
|
50
|
+
class="url-citation-card__favicon"
|
|
51
|
+
referrerpolicy="no-referrer"
|
|
52
|
+
@error="faviconFailed = true"
|
|
53
|
+
>
|
|
54
|
+
<span v-else i-ph-globe-simple class="url-citation-card__fallback" aria-hidden="true" />
|
|
55
|
+
<span body-12-medium text-secondary truncate>
|
|
56
|
+
{{ citation.sourceLabel }}
|
|
57
|
+
</span>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<p body-14-medium text-primary m-0 class="url-citation-card__title">
|
|
61
|
+
{{ citation.title }}
|
|
62
|
+
</p>
|
|
63
|
+
|
|
64
|
+
<p body-11-regular text-tertiary m-0 truncate>
|
|
65
|
+
{{ citation.displayUrl }}
|
|
66
|
+
</p>
|
|
67
|
+
</div>
|
|
68
|
+
</template>
|
|
69
|
+
</TelaHoverCard>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<style scoped>
|
|
73
|
+
.url-citation-pill{align-items:center;background:#f5f5f5;border-radius:999px;box-shadow:inset 0 0 0 .5px rgb(0 0 0/8%);box-sizing:border-box;color:#404040;display:inline-flex;gap:4px;height:20px;line-height:1;padding:1px 7px 1px 5px;text-decoration:none;transition:background-color .15s ease,transform .12s cubic-bezier(.2,0,0,1);vertical-align:middle;white-space:nowrap}.url-citation-pill:hover{background:#e5e5e5}.url-citation-pill:active{transform:scale(.98)}.url-citation-pill:focus-visible{outline:2px solid rgba(59,130,246,.55);outline-offset:2px}.url-citation-fallback,.url-citation-favicon{border-radius:50%;flex:0 0 12px;height:12px;width:12px}.url-citation-favicon{background:#fff;-o-object-fit:contain;object-fit:contain}.url-citation-fallback{color:#737373}.url-citation-card{border-radius:12px;box-shadow:0 0 0 .5px rgba(0,0,0,.1),0 12px 32px rgba(0,0,0,.12),0 2px 6px rgb(0 0 0/6%);width:min(320px,calc(100vw - 16px))}.url-citation-card__fallback,.url-citation-card__favicon{border-radius:50%;flex:0 0 18px;height:18px;width:18px}.url-citation-card__favicon{-o-object-fit:contain;object-fit:contain}.url-citation-card__fallback{color:#737373}.url-citation-card__title{text-wrap:balance}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UrlCitationPreview } from '../url-citation.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
citation: UrlCitationPreview;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface UrlCitationPreview {
|
|
2
|
+
href: string;
|
|
3
|
+
faviconUrl: string;
|
|
4
|
+
sourceLabel: string;
|
|
5
|
+
title: string;
|
|
6
|
+
displayUrl: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseUrlCitation(href: string, label: string, markdownTitle?: string | null): UrlCitationPreview | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const URL_CITATION_MARKER = "#citation";
|
|
2
|
+
const FAVICON_PROXY_PATH = "/api/citation-favicon";
|
|
3
|
+
function titleCase(value) {
|
|
4
|
+
return value.replace(/[-_]+/g, " ").replace(/\b\p{L}/gu, (letter) => letter.toLocaleUpperCase());
|
|
5
|
+
}
|
|
6
|
+
function sourceLabelFor(hostname) {
|
|
7
|
+
const parts = hostname.replace(/^www\./i, "").split(".");
|
|
8
|
+
const compoundSuffix = parts.slice(-2).join(".");
|
|
9
|
+
const suffixParts = (/* @__PURE__ */ new Set(["co.uk", "com.au", "com.br", "com.mx", "com.tr", "co.jp"])).has(compoundSuffix) ? 2 : 1;
|
|
10
|
+
const brandIndex = Math.max(0, parts.length - suffixParts - 1);
|
|
11
|
+
return titleCase(parts[brandIndex] || hostname);
|
|
12
|
+
}
|
|
13
|
+
export function parseUrlCitation(href, label, markdownTitle) {
|
|
14
|
+
if (!href.endsWith(URL_CITATION_MARKER))
|
|
15
|
+
return null;
|
|
16
|
+
const cleanHref = href.slice(0, -URL_CITATION_MARKER.length);
|
|
17
|
+
let url;
|
|
18
|
+
try {
|
|
19
|
+
url = new URL(cleanHref);
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
24
|
+
return null;
|
|
25
|
+
return {
|
|
26
|
+
href: url.href,
|
|
27
|
+
faviconUrl: `${FAVICON_PROXY_PATH}?domain=${encodeURIComponent(url.hostname)}`,
|
|
28
|
+
sourceLabel: sourceLabelFor(url.hostname),
|
|
29
|
+
title: markdownTitle?.trim() || label.trim() || url.hostname,
|
|
30
|
+
displayUrl: `${url.hostname}${url.pathname}${url.search}${url.hash}`
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { parseCitationUrl } from "../../citations/citation-links";
|
|
3
|
+
import ChatUrlCitation from "../../citations/components/chat-url-citation.vue";
|
|
4
|
+
import { parseUrlCitation } from "../../citations/url-citation";
|
|
3
5
|
import { useEmbedConfig } from "../../embed/composables/embed-config";
|
|
4
6
|
import { detectFileFromUrl } from "../content-detection";
|
|
5
7
|
const props = defineProps({
|
|
@@ -9,17 +11,18 @@ const props = defineProps({
|
|
|
9
11
|
});
|
|
10
12
|
const embedConfig = useEmbedConfig();
|
|
11
13
|
const detectedFile = computed(() => detectFileFromUrl(props.node.href));
|
|
12
|
-
const detectedCitation = computed(() => {
|
|
13
|
-
if (!embedConfig?.citations.value)
|
|
14
|
-
return null;
|
|
15
|
-
return parseCitationUrl(props.node.href);
|
|
16
|
-
});
|
|
17
14
|
const linkText = computed(() => {
|
|
18
15
|
if (props.node.children?.length > 0) {
|
|
19
16
|
return props.node.children.map((c) => c.raw).join("");
|
|
20
17
|
}
|
|
21
18
|
return props.node.text || props.node.href;
|
|
22
19
|
});
|
|
20
|
+
const detectedCitation = computed(() => {
|
|
21
|
+
if (!embedConfig?.citations.value)
|
|
22
|
+
return null;
|
|
23
|
+
return parseCitationUrl(props.node.href);
|
|
24
|
+
});
|
|
25
|
+
const detectedUrlCitation = computed(() => parseUrlCitation(props.node.href, linkText.value, props.node.title));
|
|
23
26
|
</script>
|
|
24
27
|
|
|
25
28
|
<template>
|
|
@@ -36,6 +39,10 @@ const linkText = computed(() => {
|
|
|
36
39
|
:citation="detectedCitation"
|
|
37
40
|
:label="linkText"
|
|
38
41
|
/>
|
|
42
|
+
<ChatUrlCitation
|
|
43
|
+
v-else-if="detectedUrlCitation"
|
|
44
|
+
:citation="detectedUrlCitation"
|
|
45
|
+
/>
|
|
39
46
|
<a
|
|
40
47
|
v-else
|
|
41
48
|
:href="node.href"
|
|
@@ -6,6 +6,7 @@ import { useChatDebugDiagnostics } from "../debug/use-chat-debug-diagnostics";
|
|
|
6
6
|
import { formatChatDebugTime as formatTime, useChatDebugPlayback } from "../debug/use-chat-debug-playback";
|
|
7
7
|
const scenarios = createChatDebugScenarios();
|
|
8
8
|
const viewportWidth = ref("default");
|
|
9
|
+
const conversationVariant = ref("widget");
|
|
9
10
|
const showBounds = ref(false);
|
|
10
11
|
const rootRef = ref(null);
|
|
11
12
|
const stageRef = ref(null);
|
|
@@ -66,6 +67,10 @@ const viewportOptions = [
|
|
|
66
67
|
{ id: "default", label: "Default" },
|
|
67
68
|
{ id: "wide", label: "Wide" }
|
|
68
69
|
];
|
|
70
|
+
const conversationVariantOptions = [
|
|
71
|
+
{ id: "widget", label: "Widget" },
|
|
72
|
+
{ id: "page", label: "Page" }
|
|
73
|
+
];
|
|
69
74
|
function eventToneClass(tone) {
|
|
70
75
|
return {
|
|
71
76
|
neutral: "bg-gray-400",
|
|
@@ -144,6 +149,19 @@ function eventToneClass(tone) {
|
|
|
144
149
|
<span>{{ playbackState.messages.length }} messages</span>
|
|
145
150
|
</div>
|
|
146
151
|
<div flex items-center gap-12px>
|
|
152
|
+
<div flex items-center gap-10px>
|
|
153
|
+
<button
|
|
154
|
+
v-for="option in conversationVariantOptions"
|
|
155
|
+
:key="option.id"
|
|
156
|
+
type="button"
|
|
157
|
+
body-11-regular
|
|
158
|
+
:class="conversationVariant === option.id ? 'text-primary' : 'text-tertiary hover:text-secondary'"
|
|
159
|
+
transition-colors
|
|
160
|
+
@click="conversationVariant = option.id"
|
|
161
|
+
>
|
|
162
|
+
{{ option.label }}
|
|
163
|
+
</button>
|
|
164
|
+
</div>
|
|
147
165
|
<div flex items-center gap-10px>
|
|
148
166
|
<button
|
|
149
167
|
v-for="option in viewportOptions"
|
|
@@ -177,13 +195,13 @@ function eventToneClass(tone) {
|
|
|
177
195
|
showBounds && 'chat-under-test--bounded'
|
|
178
196
|
]"
|
|
179
197
|
>
|
|
180
|
-
<TelaChatBody variant="
|
|
198
|
+
<TelaChatBody :key="conversationVariant" :variant="conversationVariant" h-full>
|
|
181
199
|
<ChatMessageList
|
|
182
200
|
:messages="playbackState.messages"
|
|
183
201
|
:loading="playbackState.loading"
|
|
184
202
|
:streaming-active-message-id="playbackState.streamingActiveMessageId"
|
|
185
203
|
:preparing-steps="playbackState.preparingSteps"
|
|
186
|
-
variant="
|
|
204
|
+
:variant="conversationVariant"
|
|
187
205
|
@retry="stepEvent(-1)"
|
|
188
206
|
/>
|
|
189
207
|
</TelaChatBody>
|
|
@@ -188,7 +188,6 @@ const hasDetectedFiles = computed(() => contentSegments.value.some((s) => s.type
|
|
|
188
188
|
<ChatReasoningThought
|
|
189
189
|
v-if="hasReasoning || preparingSteps?.length && !message.content || isPending && !streamActive"
|
|
190
190
|
:reasoning-data="message.reasoningData ?? []"
|
|
191
|
-
:animate="wasEverPending"
|
|
192
191
|
:completed="!isPending"
|
|
193
192
|
:preparing-steps="preparingSteps"
|
|
194
193
|
:created-at="message.createdAt"
|
|
@@ -196,7 +195,7 @@ const hasDetectedFiles = computed(() => contentSegments.value.some((s) => s.type
|
|
|
196
195
|
/>
|
|
197
196
|
|
|
198
197
|
<div
|
|
199
|
-
v-if="
|
|
198
|
+
v-if="message.content && (!isPending || streamActive)"
|
|
200
199
|
max-w-prose
|
|
201
200
|
:class="[
|
|
202
201
|
isFailed ? 'flex gap-12px items-start bg-subtle border border-solid rounded-12px w-full' : 'rounded-12px code-theme'
|
|
@@ -12,7 +12,10 @@ type __VLS_Props = {
|
|
|
12
12
|
preparingSteps?: readonly string[] | null;
|
|
13
13
|
showTtft?: boolean;
|
|
14
14
|
};
|
|
15
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
15
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
16
|
+
isPinned: import("vue").Ref<boolean, boolean>;
|
|
17
|
+
scrollToBottom: () => void;
|
|
18
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
16
19
|
retry: (messageId: string) => any;
|
|
17
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
18
21
|
onRetry?: ((messageId: string) => any) | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useChatScrollStickiness } from "../composables/chat-scroll-stickiness";
|
|
2
3
|
const props = defineProps({
|
|
3
4
|
messages: { type: Array, required: true },
|
|
4
5
|
loading: { type: Boolean, required: false },
|
|
@@ -9,60 +10,94 @@ const props = defineProps({
|
|
|
9
10
|
});
|
|
10
11
|
const emit = defineEmits(["retry"]);
|
|
11
12
|
const conversationRef = ref(null);
|
|
13
|
+
const { isPinned, scrollToBottom } = useChatScrollStickiness(conversationRef);
|
|
12
14
|
const skeletonMessages = [
|
|
13
15
|
{ id: "user-1", align: "end", width: "58%", height: "44px" },
|
|
14
16
|
{ id: "assistant-1", align: "start", width: "92%", height: "116px" },
|
|
15
17
|
{ id: "user-2", align: "end", width: "46%", height: "44px" },
|
|
16
18
|
{ id: "assistant-2", align: "start", width: "84%", height: "92px" }
|
|
17
19
|
];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
let knownMessageIds = new Set(props.messages.map((message) => message.id));
|
|
21
|
+
watch(() => props.messages.map((message) => `${message.id}:${message.role}`).join("|"), () => {
|
|
22
|
+
const hasNewUserMessage = props.messages.some(
|
|
23
|
+
(message) => message.role === "user" && !knownMessageIds.has(message.id)
|
|
24
|
+
);
|
|
25
|
+
knownMessageIds = new Set(props.messages.map((message) => message.id));
|
|
26
|
+
if (hasNewUserMessage)
|
|
27
|
+
scrollToBottom();
|
|
28
|
+
});
|
|
29
|
+
defineExpose({
|
|
30
|
+
isPinned,
|
|
23
31
|
scrollToBottom
|
|
24
|
-
);
|
|
25
|
-
onMounted(scrollToBottom);
|
|
32
|
+
});
|
|
26
33
|
</script>
|
|
27
34
|
|
|
28
35
|
<template>
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
:
|
|
36
|
+
<div
|
|
37
|
+
class="chat-message-list"
|
|
38
|
+
:data-variant="variant ?? 'page'"
|
|
39
|
+
flex="~ col"
|
|
40
|
+
flex-1
|
|
41
|
+
min-h-0
|
|
42
|
+
relative
|
|
43
|
+
>
|
|
44
|
+
<TelaChatConversation
|
|
45
|
+
ref="conversationRef"
|
|
46
|
+
:class="{
|
|
32
47
|
'pt-72px!': (variant ?? 'page') === 'page',
|
|
33
48
|
'pt-72px pb-24px px-16px': variant === 'mobile'
|
|
34
49
|
}"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
>
|
|
51
|
+
<TelaChatConversationContent class="max-w-700px! min-h-full">
|
|
52
|
+
<template v-if="loading">
|
|
53
|
+
<div
|
|
54
|
+
v-for="message in skeletonMessages"
|
|
55
|
+
:key="message.id"
|
|
56
|
+
flex
|
|
57
|
+
:class="message.align === 'end' ? 'justify-end' : 'justify-start'"
|
|
58
|
+
>
|
|
59
|
+
<TelaSkeleton :style="{ width: message.width, height: message.height }" />
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<template v-else>
|
|
64
|
+
<ChatMessageBubble
|
|
65
|
+
v-for="message in messages"
|
|
66
|
+
:key="message.id"
|
|
67
|
+
:message="message"
|
|
68
|
+
:stream-active="message.id === streamingActiveMessageId"
|
|
69
|
+
:preparing-steps="message.role === 'assistant' && message.status === 'pending' ? preparingSteps : null"
|
|
70
|
+
:show-ttft="showTtft"
|
|
71
|
+
@retry="emit('retry', $event)"
|
|
72
|
+
/>
|
|
73
|
+
<p
|
|
74
|
+
v-if="messages.length > 0"
|
|
75
|
+
mt-auto mb--6px
|
|
76
|
+
text-center body-11-regular text-tertiary
|
|
77
|
+
>
|
|
78
|
+
As respostas podem conter erros. Verifique documentos originais.
|
|
79
|
+
</p>
|
|
80
|
+
</template>
|
|
81
|
+
</TelaChatConversationContent>
|
|
82
|
+
</TelaChatConversation>
|
|
47
83
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
As respostas podem conter erros. Verifique documentos originais.
|
|
64
|
-
</p>
|
|
65
|
-
</template>
|
|
66
|
-
</TelaChatConversationContent>
|
|
67
|
-
</TelaChatConversation>
|
|
84
|
+
<Transition name="jump-to-latest">
|
|
85
|
+
<button
|
|
86
|
+
v-if="!isPinned"
|
|
87
|
+
type="button"
|
|
88
|
+
class="chat-message-list__jump"
|
|
89
|
+
bg
|
|
90
|
+
b=".5px border-default"
|
|
91
|
+
aria-label="Ir para a mensagem mais recente"
|
|
92
|
+
title="Ir para a mensagem mais recente"
|
|
93
|
+
@click="scrollToBottom"
|
|
94
|
+
>
|
|
95
|
+
<TelaIcon name="i-ph-arrow-down" size="16px" color="icon-secondary" />
|
|
96
|
+
</button>
|
|
97
|
+
</Transition>
|
|
98
|
+
</div>
|
|
68
99
|
</template>
|
|
100
|
+
|
|
101
|
+
<style scoped>
|
|
102
|
+
.chat-message-list>:deep([data-chat-conversation]){flex:1 1 0%;min-height:0;overflow-y:auto}.chat-message-list__jump{align-items:center;border-radius:999px;bottom:16px;box-shadow:0 3px 12px rgba(0,0,0,.1);cursor:pointer;display:inline-flex;height:32px;justify-content:center;left:50%;position:absolute;transform:translateX(-50%);width:32px;z-index:2}.jump-to-latest-enter-active,.jump-to-latest-leave-active{transition:opacity .12s ease,transform .12s ease}.jump-to-latest-enter-from,.jump-to-latest-leave-to{opacity:0;transform:translateX(-50%) translateY(4px)}
|
|
103
|
+
</style>
|
|
@@ -12,7 +12,10 @@ type __VLS_Props = {
|
|
|
12
12
|
preparingSteps?: readonly string[] | null;
|
|
13
13
|
showTtft?: boolean;
|
|
14
14
|
};
|
|
15
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
15
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
16
|
+
isPinned: import("vue").Ref<boolean, boolean>;
|
|
17
|
+
scrollToBottom: () => void;
|
|
18
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
16
19
|
retry: (messageId: string) => any;
|
|
17
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
18
21
|
onRetry?: ((messageId: string) => any) | undefined;
|
package/dist/runtime/messages/components/reasoning/chat-reasoning-collapsible-content.d.vue.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
12
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
13
|
+
new (): {
|
|
14
|
+
$slots: S;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
open: { type: Boolean, required: true }
|
|
4
|
+
});
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div
|
|
9
|
+
class="chat-reasoning-collapsible-content"
|
|
10
|
+
:data-state="open ? 'open' : 'closed'"
|
|
11
|
+
data-chat-disclosure-motion
|
|
12
|
+
>
|
|
13
|
+
<TelaCollapsibleContent
|
|
14
|
+
:force-mount="true"
|
|
15
|
+
:inert="open ? void 0 : true"
|
|
16
|
+
:aria-hidden="!open"
|
|
17
|
+
>
|
|
18
|
+
<slot />
|
|
19
|
+
</TelaCollapsibleContent>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
.chat-reasoning-collapsible-content{display:grid;grid-template-rows:1fr;transition:grid-template-rows .2s cubic-bezier(.2,0,0,1)}.chat-reasoning-collapsible-content[data-state=closed]{grid-template-rows:0fr}.chat-reasoning-collapsible-content>[data-collapsible-content]{animation:none!important;height:auto;min-height:0;overflow:hidden}.chat-reasoning-collapsible-content [data-collapsible-content]>div{opacity:1;transform:translateY(0);transition:opacity .14s cubic-bezier(.2,0,0,1) 40ms,transform .18s cubic-bezier(.2,0,0,1);will-change:opacity,transform}.chat-reasoning-collapsible-content[data-state=closed] [data-collapsible-content]>div{opacity:0;transform:translateY(-2px);transition:opacity .1s cubic-bezier(.2,0,0,1),transform .16s cubic-bezier(.2,0,0,1)}@media (prefers-reduced-motion:reduce){.chat-reasoning-collapsible-content,.chat-reasoning-collapsible-content [data-collapsible-content]>div{transition-delay:0s;transition-duration:0s}}
|
|
25
|
+
</style>
|
package/dist/runtime/messages/components/reasoning/chat-reasoning-collapsible-content.vue.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
open: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
12
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
13
|
+
new (): {
|
|
14
|
+
$slots: S;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { ReasoningStep } from '../../reasoning.js';
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
step: ReasoningStep;
|
|
4
|
-
stepNumber: number;
|
|
5
|
-
isFirst?: boolean;
|
|
6
|
-
isLast?: boolean;
|
|
7
4
|
isActive?: boolean;
|
|
8
|
-
isPreviewMode?: boolean;
|
|
9
5
|
completed?: boolean;
|
|
10
6
|
};
|
|
11
7
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|