@meistrari/chat-nuxt 1.7.0 → 1.8.1
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/module.mjs +2 -0
- package/dist/runtime/components/MeistrariChatEmbed.vue +5 -1
- package/dist/runtime/components/chat/bash-widget.vue +3 -3
- package/dist/runtime/components/chat/doc-sdk-widget.vue +3 -3
- package/dist/runtime/components/chat/files-view.vue +3 -64
- package/dist/runtime/components/chat/generic-tool-widget.vue +3 -3
- package/dist/runtime/components/chat/grep-widget.vue +3 -3
- package/dist/runtime/components/chat/message-bubble.vue +1 -1
- package/dist/runtime/components/chat/message-input.d.vue.ts +2 -0
- package/dist/runtime/components/chat/message-input.vue +21 -5
- package/dist/runtime/components/chat/message-input.vue.d.ts +2 -0
- package/dist/runtime/components/chat/message-list.vue +1 -1
- package/dist/runtime/components/chat/mobile/files/file-preview.d.vue.ts +11 -0
- package/dist/runtime/components/chat/mobile/files/file-preview.vue +112 -0
- package/dist/runtime/components/chat/mobile/files/file-preview.vue.d.ts +11 -0
- package/dist/runtime/components/chat/mobile/files/files-view.d.vue.ts +10 -0
- package/dist/runtime/components/chat/mobile/files/files-view.vue +384 -0
- package/dist/runtime/components/chat/mobile/files/files-view.vue.d.ts +10 -0
- package/dist/runtime/components/chat/mobile/home/header.d.vue.ts +19 -0
- package/dist/runtime/components/chat/mobile/home/header.vue +55 -0
- package/dist/runtime/components/chat/mobile/home/header.vue.d.ts +19 -0
- package/dist/runtime/components/chat/mobile/home/recents.d.vue.ts +14 -0
- package/dist/runtime/components/chat/mobile/home/recents.vue +48 -0
- package/dist/runtime/components/chat/mobile/home/recents.vue.d.ts +14 -0
- package/dist/runtime/components/chat/mobile/home/suggestions.d.vue.ts +7 -0
- package/dist/runtime/components/chat/mobile/home/suggestions.vue +31 -0
- package/dist/runtime/components/chat/mobile/home/suggestions.vue.d.ts +7 -0
- package/dist/runtime/components/chat/mobile/primitives/bottom-sheet.d.vue.ts +21 -0
- package/dist/runtime/components/chat/mobile/primitives/bottom-sheet.vue +48 -0
- package/dist/runtime/components/chat/mobile/primitives/bottom-sheet.vue.d.ts +21 -0
- package/dist/runtime/components/chat/mobile/primitives/info-bubble.d.vue.ts +6 -0
- package/dist/runtime/components/chat/mobile/primitives/info-bubble.vue +50 -0
- package/dist/runtime/components/chat/mobile/primitives/info-bubble.vue.d.ts +6 -0
- package/dist/runtime/components/chat/mobile/shell/drawer.d.vue.ts +22 -0
- package/dist/runtime/components/chat/mobile/shell/drawer.vue +143 -0
- package/dist/runtime/components/chat/mobile/shell/drawer.vue.d.ts +22 -0
- package/dist/runtime/components/chat/mobile/shell/header.d.vue.ts +40 -0
- package/dist/runtime/components/chat/mobile/shell/header.vue +139 -0
- package/dist/runtime/components/chat/mobile/shell/header.vue.d.ts +40 -0
- package/dist/runtime/components/chat/mobile/shell/outdated-settings-sheet.d.vue.ts +14 -0
- package/dist/runtime/components/chat/mobile/shell/outdated-settings-sheet.vue +47 -0
- package/dist/runtime/components/chat/mobile/shell/outdated-settings-sheet.vue.d.ts +14 -0
- package/dist/runtime/components/chat/mobile/shell/shell.d.vue.ts +122 -0
- package/dist/runtime/components/chat/mobile/shell/shell.vue +283 -0
- package/dist/runtime/components/chat/mobile/shell/shell.vue.d.ts +122 -0
- package/dist/runtime/components/chat/mobile/shell/workspace-sheet.d.vue.ts +19 -0
- package/dist/runtime/components/chat/mobile/shell/workspace-sheet.vue +51 -0
- package/dist/runtime/components/chat/mobile/shell/workspace-sheet.vue.d.ts +19 -0
- package/dist/runtime/components/chat/mobile/usage/usage-view.d.vue.ts +8 -0
- package/dist/runtime/components/chat/mobile/usage/usage-view.vue +243 -0
- package/dist/runtime/components/chat/mobile/usage/usage-view.vue.d.ts +8 -0
- package/dist/runtime/components/chat/model-selector.vue +6 -0
- package/dist/runtime/components/chat/read-widget.vue +3 -3
- package/dist/runtime/components/chat/reasoning-step-item.vue +1 -1
- package/dist/runtime/components/chat/reasoning-steps.vue +1 -1
- package/dist/runtime/components/chat/reasoning-thought.vue +2 -3
- package/dist/runtime/components/chat/tela-skill-widget.vue +3 -3
- package/dist/runtime/components/chat/thinking-widget.vue +3 -3
- package/dist/runtime/components/chat/usage-view.vue +20 -101
- package/dist/runtime/components/chat/web-search-widget.vue +3 -3
- package/dist/runtime/components/chat/workstation-query-widget.vue +6 -6
- package/dist/runtime/components/chat/write-widget.vue +3 -3
- package/dist/runtime/composables/useConversationFileDownloads.d.ts +6 -0
- package/dist/runtime/composables/useConversationFileDownloads.js +50 -0
- package/dist/runtime/composables/useConversationUsage.d.ts +13 -0
- package/dist/runtime/composables/useConversationUsage.js +121 -0
- package/dist/runtime/composables/useEmbedConfig.d.ts +2 -0
- package/dist/runtime/composables/useEmbedConfig.js +4 -0
- package/dist/runtime/composables/useMentionAutocomplete.d.ts +6 -0
- package/dist/runtime/composables/useMentionAutocomplete.js +71 -23
- package/dist/runtime/composables/usePdf.js +2 -2
- package/dist/runtime/composables/useWorkspaceSwitchModal.d.ts +5 -0
- package/dist/runtime/composables/useWorkspaceSwitchModal.js +14 -0
- package/dist/runtime/embed/components/ChatConfigurationModal.vue +119 -13
- package/dist/runtime/embed/components/ChatEmbed.vue +4 -0
- package/dist/runtime/embed/components/ChatEmbedInner.d.vue.ts +2 -0
- package/dist/runtime/embed/components/ChatEmbedInner.vue +201 -11
- package/dist/runtime/embed/components/ChatEmbedInner.vue.d.ts +2 -0
- package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.d.vue.ts +34 -0
- package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.vue +95 -0
- package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.vue.d.ts +34 -0
- package/dist/runtime/server/api/conversations/[id]/messages/[messageId]/retry.post.js +3 -1
- package/dist/runtime/server/api/conversations/[id]/messages/index.get.js +29 -5
- package/dist/runtime/server/utils/conversation-agent-turn.js +4 -0
- package/dist/runtime/server/utils/conversation-message-sync.d.ts +8 -2
- package/dist/runtime/server/utils/conversation-message-sync.js +52 -6
- package/dist/runtime/types/chat-auth.d.ts +1 -0
- package/dist/runtime/types/embed.d.ts +2 -0
- package/dist/runtime/utils/breakpoints.d.ts +1 -0
- package/dist/runtime/utils/breakpoints.js +1 -0
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -196,6 +196,7 @@ export function useChatAuth() {
|
|
|
196
196
|
return {
|
|
197
197
|
user: auth.user,
|
|
198
198
|
activeOrganization: auth.activeOrganization,
|
|
199
|
+
logout: auth.logout,
|
|
199
200
|
getToken: auth.getToken,
|
|
200
201
|
getAvailableOrganizations: auth.getAvailableOrganizations,
|
|
201
202
|
switchOrganization: auth.switchOrganization,
|
|
@@ -241,6 +242,7 @@ export function useChatAuth() {
|
|
|
241
242
|
return {
|
|
242
243
|
user: session.user,
|
|
243
244
|
activeOrganization: organization.activeOrganization,
|
|
245
|
+
logout: session.signOut,
|
|
244
246
|
getToken: session.getToken,
|
|
245
247
|
getAvailableOrganizations: organization.listOrganizations,
|
|
246
248
|
switchOrganization: organization.setActiveOrganization,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
defineProps({
|
|
2
|
+
const props = defineProps({
|
|
3
3
|
conversationId: { type: [String, null], required: false },
|
|
4
4
|
initialConversationId: { type: [String, null], required: false },
|
|
5
5
|
conversationScope: { type: [String, null], required: false },
|
|
6
6
|
hideSidebar: { type: Boolean, required: false },
|
|
7
|
+
hideSettings: { type: Boolean, required: false },
|
|
7
8
|
loadingMessages: { type: [Array, null], required: false },
|
|
8
9
|
loadingMessagesMode: { type: [String, null], required: false },
|
|
9
10
|
customComponents: { type: Object, required: false },
|
|
@@ -15,6 +16,7 @@ defineProps({
|
|
|
15
16
|
features: { type: Object, required: false }
|
|
16
17
|
});
|
|
17
18
|
defineEmits(["update:conversationId", "action"]);
|
|
19
|
+
const hideSettings = computed(() => props.hideSettings ?? false);
|
|
18
20
|
</script>
|
|
19
21
|
|
|
20
22
|
<template>
|
|
@@ -26,6 +28,7 @@ defineEmits(["update:conversationId", "action"]);
|
|
|
26
28
|
:initial-conversation-id="initialConversationId"
|
|
27
29
|
:conversation-scope="conversationScope"
|
|
28
30
|
:hide-sidebar="hideSidebar"
|
|
31
|
+
:hide-settings="hideSettings"
|
|
29
32
|
:features="features"
|
|
30
33
|
:loading-messages="loadingMessages"
|
|
31
34
|
:loading-messages-mode="loadingMessagesMode"
|
|
@@ -42,6 +45,7 @@ defineEmits(["update:conversationId", "action"]);
|
|
|
42
45
|
:initial-conversation-id="initialConversationId"
|
|
43
46
|
:conversation-scope="conversationScope"
|
|
44
47
|
:hide-sidebar="hideSidebar"
|
|
48
|
+
:hide-settings="hideSettings"
|
|
45
49
|
:features="features"
|
|
46
50
|
:loading-messages="loadingMessages"
|
|
47
51
|
:loading-messages-mode="loadingMessagesMode"
|
|
@@ -31,15 +31,15 @@ const isOutputCode = computed(() => {
|
|
|
31
31
|
<template>
|
|
32
32
|
<div class="bg-subtle rounded-16px border border-gray-200">
|
|
33
33
|
<!-- Header -->
|
|
34
|
-
<div class="px-
|
|
35
|
-
<h3 class="text-
|
|
34
|
+
<div class="px-16px py-16px flex items-center justify-between">
|
|
35
|
+
<h3 class="text-16px font-580 leading-20px tracking-[-0.3px] text-primary truncate">
|
|
36
36
|
Bash
|
|
37
37
|
</h3>
|
|
38
38
|
<TelaStatus :variant="statusVariant" :label="statusLabel" />
|
|
39
39
|
</div>
|
|
40
40
|
|
|
41
41
|
<!-- Content -->
|
|
42
|
-
<div v-if="toolResult" class="px-
|
|
42
|
+
<div v-if="toolResult" class="px-16px pb-16px space-y-16px">
|
|
43
43
|
<!-- Command section -->
|
|
44
44
|
<div>
|
|
45
45
|
<div class="text-14px font-580 leading-16px tracking-[-0.15px] text-gray-700 mb-2">
|
|
@@ -31,15 +31,15 @@ const isOutputCode = computed(() => {
|
|
|
31
31
|
<template>
|
|
32
32
|
<div class="bg-subtle rounded-16px border border-gray-200">
|
|
33
33
|
<!-- Header -->
|
|
34
|
-
<div class="px-
|
|
35
|
-
<h3 class="text-
|
|
34
|
+
<div class="px-16px py-16px flex items-center justify-between">
|
|
35
|
+
<h3 class="text-16px font-580 leading-20px tracking-[-0.3px] text-primary">
|
|
36
36
|
{{ skillName }}
|
|
37
37
|
</h3>
|
|
38
38
|
<TelaStatus :variant="statusVariant" :label="statusLabel" />
|
|
39
39
|
</div>
|
|
40
40
|
|
|
41
41
|
<!-- Content -->
|
|
42
|
-
<div v-if="toolResult" class="px-
|
|
42
|
+
<div v-if="toolResult" class="px-16px pb-16px space-y-16px">
|
|
43
43
|
<!-- Result -->
|
|
44
44
|
<div>
|
|
45
45
|
<div class="text-14px font-580 leading-16px tracking-[-0.15px] text-gray-700 mb-2">
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { useClipboard } from "@vueuse/core";
|
|
3
2
|
import { formatFileSize, formatUploadDate, getFileIcon, getFileTypeLabel } from "../../utils/file";
|
|
4
3
|
const props = defineProps({
|
|
5
4
|
conversationId: { type: String, required: true }
|
|
@@ -8,7 +7,7 @@ const conversationIdRef = computed(() => props.conversationId);
|
|
|
8
7
|
const { files, loading } = useConversationFiles(conversationIdRef);
|
|
9
8
|
const { openPreview, updatePreview, setError } = useFilePreviewPanel();
|
|
10
9
|
const { getCached, fetchUrlAsBase64, setCache } = useMediaCache();
|
|
11
|
-
const {
|
|
10
|
+
const { downloadFile, copyFileLink } = useConversationFileDownloads();
|
|
12
11
|
const searchQuery = ref("");
|
|
13
12
|
const fileTypeFilter = ref(null);
|
|
14
13
|
const currentRequestId = ref(0);
|
|
@@ -144,77 +143,17 @@ async function handleFileClick(file) {
|
|
|
144
143
|
});
|
|
145
144
|
}
|
|
146
145
|
}
|
|
147
|
-
const statusToast = useStatusToast();
|
|
148
|
-
async function handleDownload(file) {
|
|
149
|
-
statusToast.update({
|
|
150
|
-
text: "Baixando arquivo...",
|
|
151
|
-
loading: true
|
|
152
|
-
});
|
|
153
|
-
try {
|
|
154
|
-
let downloadUrl = file.url;
|
|
155
|
-
if (file.url.startsWith("vault://")) {
|
|
156
|
-
const { url } = await $fetch("/api/vault/resolve", {
|
|
157
|
-
method: "POST",
|
|
158
|
-
body: { reference: file.url }
|
|
159
|
-
});
|
|
160
|
-
downloadUrl = url;
|
|
161
|
-
}
|
|
162
|
-
const response = await fetch(downloadUrl);
|
|
163
|
-
const blob = await response.blob();
|
|
164
|
-
const blobUrl = URL.createObjectURL(blob);
|
|
165
|
-
const link = document.createElement("a");
|
|
166
|
-
link.href = blobUrl;
|
|
167
|
-
link.download = file.name;
|
|
168
|
-
document.body.appendChild(link);
|
|
169
|
-
link.click();
|
|
170
|
-
document.body.removeChild(link);
|
|
171
|
-
URL.revokeObjectURL(blobUrl);
|
|
172
|
-
statusToast.update({
|
|
173
|
-
text: "Download conclu\xEDdo",
|
|
174
|
-
icon: "i-ph-check"
|
|
175
|
-
});
|
|
176
|
-
} catch (error) {
|
|
177
|
-
console.error("Failed to download file:", error);
|
|
178
|
-
statusToast.update({
|
|
179
|
-
text: "Erro ao baixar arquivo",
|
|
180
|
-
icon: "i-ph-warning"
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
async function handleCopyLink(file) {
|
|
185
|
-
try {
|
|
186
|
-
let publicUrl = file.url;
|
|
187
|
-
if (file.url.startsWith("vault://")) {
|
|
188
|
-
const { url } = await $fetch("/api/vault/resolve", {
|
|
189
|
-
method: "POST",
|
|
190
|
-
body: { reference: file.url }
|
|
191
|
-
});
|
|
192
|
-
publicUrl = url;
|
|
193
|
-
}
|
|
194
|
-
await copy(publicUrl);
|
|
195
|
-
statusToast.update({
|
|
196
|
-
text: "Link copiado",
|
|
197
|
-
icon: "i-ph-check"
|
|
198
|
-
});
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.error("Failed to copy link:", error);
|
|
201
|
-
statusToast.update({
|
|
202
|
-
text: "Erro ao copiar link",
|
|
203
|
-
icon: "i-ph-warning"
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
146
|
function getFileMenuItems(file) {
|
|
208
147
|
return [
|
|
209
148
|
{
|
|
210
149
|
label: "Copiar link",
|
|
211
150
|
icon: "i-ph-link",
|
|
212
|
-
click: () =>
|
|
151
|
+
click: () => copyFileLink(file)
|
|
213
152
|
},
|
|
214
153
|
{
|
|
215
154
|
label: "Baixar",
|
|
216
155
|
icon: "i-ph-download-simple",
|
|
217
|
-
click: () =>
|
|
156
|
+
click: () => downloadFile(file)
|
|
218
157
|
}
|
|
219
158
|
];
|
|
220
159
|
}
|
|
@@ -84,15 +84,15 @@ const isEmptyMessage = computed(() => {
|
|
|
84
84
|
<template>
|
|
85
85
|
<div class="bg-subtle rounded-16px border border-gray-200">
|
|
86
86
|
<!-- Header -->
|
|
87
|
-
<div class="px-
|
|
88
|
-
<h3 class="text-
|
|
87
|
+
<div class="px-16px py-16px flex items-center justify-between">
|
|
88
|
+
<h3 class="text-16px font-580 leading-20px tracking-[-0.3px] text-primary truncate">
|
|
89
89
|
{{ name }}
|
|
90
90
|
</h3>
|
|
91
91
|
<TelaStatus :variant="statusVariant" :label="statusLabel" />
|
|
92
92
|
</div>
|
|
93
93
|
|
|
94
94
|
<!-- Content -->
|
|
95
|
-
<div v-if="hasContent" class="px-
|
|
95
|
+
<div v-if="hasContent" class="px-16px pb-16px space-y-16px">
|
|
96
96
|
<!-- Parameters section -->
|
|
97
97
|
<div v-if="input && Object.keys(input).length > 0">
|
|
98
98
|
<!-- Special handling for TodoWrite tool -->
|
|
@@ -122,9 +122,9 @@ function highlightMatch(content) {
|
|
|
122
122
|
<template>
|
|
123
123
|
<div class="bg-subtle rounded-16px border border-gray-200">
|
|
124
124
|
<!-- Header -->
|
|
125
|
-
<div class="px-
|
|
125
|
+
<div class="px-16px py-16px flex items-center justify-between">
|
|
126
126
|
<div class="flex-1 min-w-0">
|
|
127
|
-
<h3 class="text-
|
|
127
|
+
<h3 class="text-16px font-580 leading-20px tracking-[-0.3px] text-primary truncate">
|
|
128
128
|
Grep
|
|
129
129
|
</h3>
|
|
130
130
|
<p class="text-12px text-secondary truncate mt-2px">
|
|
@@ -136,7 +136,7 @@ function highlightMatch(content) {
|
|
|
136
136
|
</div>
|
|
137
137
|
|
|
138
138
|
<!-- Content -->
|
|
139
|
-
<div v-if="toolResult" class="px-
|
|
139
|
+
<div v-if="toolResult" class="px-16px pb-16px space-y-16px">
|
|
140
140
|
<!-- Search info -->
|
|
141
141
|
<div>
|
|
142
142
|
<div class="text-14px font-580 leading-16px tracking-[-0.15px] text-gray-700 mb-2">
|
|
@@ -201,7 +201,7 @@ const hasDetectedFiles = computed(() => contentSegments.value.some((s) => s.type
|
|
|
201
201
|
v-if="hasReasoning || isPending"
|
|
202
202
|
:reasoning-data="message.reasoningData ?? []"
|
|
203
203
|
:animate="wasEverPending"
|
|
204
|
-
:completed="
|
|
204
|
+
:completed="!isPending"
|
|
205
205
|
:created-at="message.createdAt"
|
|
206
206
|
:updated-at="message.updatedAt"
|
|
207
207
|
/>
|
|
@@ -20,12 +20,14 @@ type __VLS_Props = {
|
|
|
20
20
|
showCancelButton?: boolean;
|
|
21
21
|
};
|
|
22
22
|
declare function addFiles(files: File[], inputName?: string): void;
|
|
23
|
+
declare function setDraft(text: string): void;
|
|
23
24
|
type __VLS_ModelProps = {
|
|
24
25
|
'model'?: ModelOption;
|
|
25
26
|
};
|
|
26
27
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
27
28
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
28
29
|
addFiles: typeof addFiles;
|
|
30
|
+
setDraft: typeof setDraft;
|
|
29
31
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
30
32
|
"update:model": (value: "claude-sonnet-4-5" | "claude-sonnet-4-6" | "claude-haiku-4-5" | "claude-opus-4-5" | "claude-opus-4-6") => any;
|
|
31
33
|
} & {
|
|
@@ -395,14 +395,31 @@ function addFiles(files, inputName) {
|
|
|
395
395
|
});
|
|
396
396
|
queueFiles(validFiles, inputName);
|
|
397
397
|
}
|
|
398
|
+
function setDraft(text) {
|
|
399
|
+
content.value = text;
|
|
400
|
+
if (editorRef.value) {
|
|
401
|
+
editorRef.value.textContent = text;
|
|
402
|
+
const range = document.createRange();
|
|
403
|
+
range.selectNodeContents(editorRef.value);
|
|
404
|
+
range.collapse(false);
|
|
405
|
+
const selection = window.getSelection();
|
|
406
|
+
selection?.removeAllRanges();
|
|
407
|
+
if (range)
|
|
408
|
+
selection?.addRange(range);
|
|
409
|
+
}
|
|
410
|
+
nextTick(() => {
|
|
411
|
+
editorRef.value?.focus();
|
|
412
|
+
});
|
|
413
|
+
}
|
|
398
414
|
defineExpose({
|
|
399
|
-
addFiles
|
|
415
|
+
addFiles,
|
|
416
|
+
setDraft
|
|
400
417
|
});
|
|
401
418
|
</script>
|
|
402
419
|
|
|
403
420
|
<template>
|
|
404
|
-
<div :class="centered ? '' : hasDisclaimer ? 'px-24px' : 'px-24px pb-24px'" bg-transparent>
|
|
405
|
-
<div :class="centered ? 'w-700px' : 'max-w-800px'" mx-auto>
|
|
421
|
+
<div :class="centered ? 'w-full' : hasDisclaimer ? 'px-24px' : 'px-24px pb-24px'" bg-transparent>
|
|
422
|
+
<div :class="centered ? 'w-full max-w-700px' : 'max-w-800px'" mx-auto>
|
|
406
423
|
<Transition name="agent-inputs-panel-motion" mode="out-in" appear>
|
|
407
424
|
<div
|
|
408
425
|
v-if="hasAgentInputs"
|
|
@@ -511,7 +528,6 @@ defineExpose({
|
|
|
511
528
|
</Transition>
|
|
512
529
|
</div>
|
|
513
530
|
</Transition>
|
|
514
|
-
|
|
515
531
|
<div v-if="pendingFiles.length > 0" flex flex-wrap gap-8px mb-12px>
|
|
516
532
|
<div
|
|
517
533
|
v-for="pendingFile in pendingFiles"
|
|
@@ -668,5 +684,5 @@ defineExpose({
|
|
|
668
684
|
</template>
|
|
669
685
|
|
|
670
686
|
<style scoped>
|
|
671
|
-
.input-container{border:.5px solid #e5e7eb;box-shadow:0 3px 10px 0 hsla(0,0%,64%,.08),0 12px 20px 0 hsla(0,0%,64%,.06);position:relative;z-index:2}.input-locked{background:var(--Base-Gray-gray-100,#f3f4f6);border:.5px solid var(--Base-Neutral-neutral-300,#d9d9d9);box-shadow:0 12px 20px 0 hsla(0,0%,64%,.06)}.agent-inputs-panel{box-shadow:0 3px 10px 0 hsla(0,0%,64%,.06);position:relative;transform-origin:bottom center;will-change:max-height,opacity,transform,filter;z-index:1}.agent-inputs-panel-motion-enter-active,.agent-inputs-panel-motion-leave-active{overflow:hidden;transition:max-height .26s cubic-bezier(.2,.8,.2,1),opacity .18s ease,transform .26s cubic-bezier(.2,.8,.2,1),filter .22s ease}.agent-inputs-panel-motion-enter-from,.agent-inputs-panel-motion-leave-to{filter:blur(2px);max-height:0;opacity:0;transform:translateY(46px) scale(.985)}.agent-inputs-panel-motion-enter-to,.agent-inputs-panel-motion-leave-from{filter:blur(0);max-height:560px;opacity:1;transform:translateY(0) scale(1)}.agent-inputs-content{transform-origin:bottom center;will-change:max-height,opacity,transform,filter}.agent-inputs-content-enter-active,.agent-inputs-content-leave-active{overflow:hidden;transition:max-height .22s cubic-bezier(.2,.8,.2,1),opacity .16s ease,transform .22s cubic-bezier(.2,.8,.2,1),filter .22s ease}.agent-inputs-content-enter-from,.agent-inputs-content-leave-to{filter:blur(2px);max-height:0;opacity:0;transform:translateY(14px) scale(.985)}.agent-inputs-content-enter-to,.agent-inputs-content-leave-from{filter:blur(0);max-height:900px;opacity:1;transform:translateY(0) scale(1)}.agent-text-input{border:.5px solid #e5e7eb;border-radius:8px;color:#111827;font-size:13px;line-height:18px;min-height:64px;outline:none;padding:8px 10px;resize:vertical;width:100%}.agent-text-input:focus{border-color:#d1d5db}.agent-text-input:disabled{background-color:#f3f4f6;cursor:not-allowed}.agent-file-variable-select{background:#fff;border:.5px solid #d1d5db;border-radius:6px;color:#374151;font-size:12px;height:28px;max-width:160px;outline:none;padding:0 8px}.editor-content{caret-color:#111827;color:#111827;max-height:200px;outline:none;overflow-y:auto;white-space:pre-wrap;word-break:break-word}.editor-content.is-empty:before{color:#bdc4cc;content:attr(data-placeholder);float:left;height:0;pointer-events:none}.icon-button:disabled{cursor:not-allowed;opacity:.5}.custom-scrollbar{scrollbar-color:#d1d5db transparent;scrollbar-width:thin}.custom-scrollbar::-webkit-scrollbar{width:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:3px}.stop-button{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;position:relative;transition:opacity .15s ease;width:32px}.stop-button:hover{opacity:.8}.stop-button-ring{border:2px solid #e5e7eb;border-radius:50%;inset:0;position:absolute}.stop-button-ring:before{animation:spin 1s linear infinite;border:2px solid transparent;border-radius:50%;border-top-color:#111827;content:"";inset:-2px;position:absolute}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
|
687
|
+
.input-container{border:.5px solid #e5e7eb;box-shadow:0 3px 10px 0 hsla(0,0%,64%,.08),0 12px 20px 0 hsla(0,0%,64%,.06);position:relative;z-index:2}.input-locked{background:var(--Base-Gray-gray-100,#f3f4f6);border:.5px solid var(--Base-Neutral-neutral-300,#d9d9d9);box-shadow:0 12px 20px 0 hsla(0,0%,64%,.06)}.agent-inputs-panel{box-shadow:0 3px 10px 0 hsla(0,0%,64%,.06);position:relative;transform-origin:bottom center;will-change:max-height,opacity,transform,filter;z-index:1}.agent-inputs-panel-motion-enter-active,.agent-inputs-panel-motion-leave-active{overflow:hidden;transition:max-height .26s cubic-bezier(.2,.8,.2,1),opacity .18s ease,transform .26s cubic-bezier(.2,.8,.2,1),filter .22s ease}.agent-inputs-panel-motion-enter-from,.agent-inputs-panel-motion-leave-to{filter:blur(2px);max-height:0;opacity:0;transform:translateY(46px) scale(.985)}.agent-inputs-panel-motion-enter-to,.agent-inputs-panel-motion-leave-from{filter:blur(0);max-height:560px;opacity:1;transform:translateY(0) scale(1)}.agent-inputs-content{transform-origin:bottom center;will-change:max-height,opacity,transform,filter}.agent-inputs-content-enter-active,.agent-inputs-content-leave-active{overflow:hidden;transition:max-height .22s cubic-bezier(.2,.8,.2,1),opacity .16s ease,transform .22s cubic-bezier(.2,.8,.2,1),filter .22s ease}.agent-inputs-content-enter-from,.agent-inputs-content-leave-to{filter:blur(2px);max-height:0;opacity:0;transform:translateY(14px) scale(.985)}.agent-inputs-content-enter-to,.agent-inputs-content-leave-from{filter:blur(0);max-height:900px;opacity:1;transform:translateY(0) scale(1)}.agent-text-input{border:.5px solid #e5e7eb;border-radius:8px;color:#111827;font-size:13px;line-height:18px;min-height:64px;outline:none;padding:8px 10px;resize:vertical;width:100%}.agent-text-input:focus{border-color:#d1d5db}.agent-text-input:disabled{background-color:#f3f4f6;cursor:not-allowed}.agent-file-variable-select{background:#fff;border:.5px solid #d1d5db;border-radius:6px;color:#374151;font-size:12px;height:28px;max-width:160px;outline:none;padding:0 8px}.editor-content{caret-color:#111827;color:#111827;max-height:200px;outline:none;overflow-y:auto;white-space:pre-wrap;word-break:break-word}.editor-content.is-empty:before{color:#bdc4cc;content:attr(data-placeholder);float:left;height:0;pointer-events:none}.icon-button:disabled{cursor:not-allowed;opacity:.5}.custom-scrollbar{scrollbar-color:#d1d5db transparent;scrollbar-width:thin}.custom-scrollbar::-webkit-scrollbar{width:6px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:3px}@media (max-width:480px){.custom-scrollbar{scrollbar-width:none}.custom-scrollbar::-webkit-scrollbar{display:none}}.stop-button{align-items:center;background:transparent;border:none;cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;position:relative;transition:opacity .15s ease;width:32px}.stop-button:hover{opacity:.8}.stop-button-ring{border:2px solid #e5e7eb;border-radius:50%;inset:0;position:absolute}.stop-button-ring:before{animation:spin 1s linear infinite;border:2px solid transparent;border-radius:50%;border-top-color:#111827;content:"";inset:-2px;position:absolute}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
|
672
688
|
</style>
|
|
@@ -20,12 +20,14 @@ type __VLS_Props = {
|
|
|
20
20
|
showCancelButton?: boolean;
|
|
21
21
|
};
|
|
22
22
|
declare function addFiles(files: File[], inputName?: string): void;
|
|
23
|
+
declare function setDraft(text: string): void;
|
|
23
24
|
type __VLS_ModelProps = {
|
|
24
25
|
'model'?: ModelOption;
|
|
25
26
|
};
|
|
26
27
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
27
28
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
28
29
|
addFiles: typeof addFiles;
|
|
30
|
+
setDraft: typeof setDraft;
|
|
29
31
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
30
32
|
"update:model": (value: "claude-sonnet-4-5" | "claude-sonnet-4-6" | "claude-haiku-4-5" | "claude-opus-4-5" | "claude-opus-4-6") => any;
|
|
31
33
|
} & {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConversationFile } from '#chat-runtime/types/chat';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
file: ConversationFile | null;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
6
|
+
close: () => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
8
|
+
onClose?: (() => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { onKeyStroke } from "@vueuse/core";
|
|
3
|
+
import { formatFileSize, getFileTypeLabel, normalizeMimeType } from "#chat-runtime/utils/file";
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
file: { type: null, required: true }
|
|
6
|
+
});
|
|
7
|
+
const emit = defineEmits(["close"]);
|
|
8
|
+
const { resolveDownloadUrl, downloadFile } = useConversationFileDownloads();
|
|
9
|
+
const normalizedMimeType = computed(() => normalizeMimeType(props.file?.mimeType ?? ""));
|
|
10
|
+
const isImage = computed(() => normalizedMimeType.value.startsWith("image/"));
|
|
11
|
+
const resolvedUrl = ref(null);
|
|
12
|
+
const resolving = ref(false);
|
|
13
|
+
watch(() => props.file, async (file) => {
|
|
14
|
+
resolvedUrl.value = null;
|
|
15
|
+
if (!file) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!file.url.startsWith("vault://")) {
|
|
19
|
+
resolvedUrl.value = file.url;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
resolving.value = true;
|
|
23
|
+
try {
|
|
24
|
+
const url = await resolveDownloadUrl(file);
|
|
25
|
+
if (props.file?.id === file.id) {
|
|
26
|
+
resolvedUrl.value = url;
|
|
27
|
+
}
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error("Failed to resolve preview URL", err);
|
|
30
|
+
} finally {
|
|
31
|
+
resolving.value = false;
|
|
32
|
+
}
|
|
33
|
+
}, { immediate: true });
|
|
34
|
+
onKeyStroke("Escape", () => {
|
|
35
|
+
if (props.file) {
|
|
36
|
+
emit("close");
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
function handleDownload() {
|
|
40
|
+
if (props.file) {
|
|
41
|
+
void downloadFile(props.file);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<template>
|
|
47
|
+
<Transition name="preview">
|
|
48
|
+
<div
|
|
49
|
+
v-if="file"
|
|
50
|
+
class="preview"
|
|
51
|
+
:class="isImage ? 'preview--image' : 'preview--surface'"
|
|
52
|
+
role="dialog"
|
|
53
|
+
aria-modal="true"
|
|
54
|
+
>
|
|
55
|
+
<div class="preview__topbar" :class="isImage ? 'preview__topbar--dark' : 'preview__topbar--light'">
|
|
56
|
+
<button
|
|
57
|
+
class="preview__icon-btn"
|
|
58
|
+
aria-label="Fechar"
|
|
59
|
+
@click="emit('close')"
|
|
60
|
+
>
|
|
61
|
+
<span i-ph-x />
|
|
62
|
+
</button>
|
|
63
|
+
|
|
64
|
+
<div flex="~ col 1" min-w-0 px-8px>
|
|
65
|
+
<span class="preview__title" truncate>{{ file.name }}</span>
|
|
66
|
+
<span class="preview__meta" truncate>
|
|
67
|
+
{{ getFileTypeLabel(file.mimeType) }}<template v-if="file.size">
|
|
68
|
+
· {{ formatFileSize(file.size) }}
|
|
69
|
+
</template>
|
|
70
|
+
</span>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<button
|
|
74
|
+
class="preview__icon-btn"
|
|
75
|
+
aria-label="Baixar"
|
|
76
|
+
@click="handleDownload"
|
|
77
|
+
>
|
|
78
|
+
<span i-ph-download-simple />
|
|
79
|
+
</button>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div class="preview__body">
|
|
83
|
+
<div v-if="resolving && !resolvedUrl" flex items-center justify-center h-full w-full>
|
|
84
|
+
<span
|
|
85
|
+
i-ph-spinner animate-spin text-32px
|
|
86
|
+
:class="isImage ? 'text-white' : 'text-neutral-400'"
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<img
|
|
91
|
+
v-else-if="isImage && resolvedUrl"
|
|
92
|
+
:src="resolvedUrl"
|
|
93
|
+
:alt="file.name"
|
|
94
|
+
class="preview__image"
|
|
95
|
+
>
|
|
96
|
+
|
|
97
|
+
<RenderersArtifactDisplay
|
|
98
|
+
v-else-if="resolvedUrl"
|
|
99
|
+
:url="resolvedUrl"
|
|
100
|
+
:mime-type="normalizedMimeType"
|
|
101
|
+
:name="file.name"
|
|
102
|
+
class="preview__renderer"
|
|
103
|
+
@download="handleDownload"
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</Transition>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<style scoped>
|
|
111
|
+
.preview{display:flex;flex-direction:column;inset:0;position:absolute;z-index:50}.preview--image{background:#0a0a0b}.preview--surface{background:#fff}.preview-enter-active,.preview-leave-active{transition:transform .26s cubic-bezier(.2,.8,.2,1)}.preview-enter-from,.preview-leave-to{transform:translateY(100%)}.preview__topbar{align-items:center;display:flex;flex-shrink:0;gap:4px;padding:10px 10px 8px}.preview__topbar--dark{background:rgba(0,0,0,.4);color:#fff}.preview__topbar--light{border-bottom:.5px solid #e8e8e8;color:#171717}.preview__icon-btn{align-items:center;background:transparent;border-radius:8px;color:inherit;display:inline-flex;font-size:20px;height:32px;justify-content:center;transition:background .15s;width:32px}.preview__icon-btn:hover{background:hsla(0,0%,100%,.08)}.preview--surface .preview__icon-btn:hover{background:rgba(0,0,0,.05)}.preview__title{display:block;font-size:14px;font-weight:600;letter-spacing:-.15px;line-height:18px}.preview__meta{display:block;font-size:11px;line-height:14px;opacity:.8}.preview__body{align-items:center;display:flex;flex:1;justify-content:center;min-height:0;overflow:auto}.preview--image .preview__body{overflow:hidden}.preview__image{max-height:100%;max-width:100%;-o-object-fit:contain;object-fit:contain}.preview__renderer{display:block;min-height:100%;width:100%}
|
|
112
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConversationFile } from '#chat-runtime/types/chat';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
file: ConversationFile | null;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
6
|
+
close: () => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
8
|
+
onClose?: (() => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: typeof __VLS_export;
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
conversationId: string;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
5
|
+
viewInChat: () => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
|
+
onViewInChat?: (() => any) | undefined;
|
|
8
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|