@meistrari/chat-nuxt 4.10.0-rc.9 → 4.10.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 +8 -6
- package/dist/module.json +1 -1
- package/dist/runtime/conversations/components/chat-conversation-export-modal.d.vue.ts +10 -0
- package/dist/runtime/conversations/components/chat-conversation-export-modal.vue +142 -0
- package/dist/runtime/conversations/components/chat-conversation-export-modal.vue.d.ts +10 -0
- package/dist/runtime/conversations/components/chat-conversation-list.vue +8 -1
- package/dist/runtime/conversations/components/chat-export-document.d.vue.ts +7 -0
- package/dist/runtime/conversations/components/chat-export-document.vue +26 -0
- package/dist/runtime/conversations/components/chat-export-document.vue.d.ts +7 -0
- package/dist/runtime/conversations/components/chat-export-file.d.vue.ts +9 -0
- package/dist/runtime/conversations/components/chat-export-file.vue +12 -0
- package/dist/runtime/conversations/components/chat-export-file.vue.d.ts +9 -0
- package/dist/runtime/conversations/components/chat-export-message.d.vue.ts +7 -0
- package/dist/runtime/conversations/components/chat-export-message.vue +84 -0
- package/dist/runtime/conversations/components/chat-export-message.vue.d.ts +7 -0
- package/dist/runtime/conversations/components/chat-export-openui.d.vue.ts +9 -0
- package/dist/runtime/conversations/components/chat-export-openui.vue +19 -0
- package/dist/runtime/conversations/components/chat-export-openui.vue.d.ts +9 -0
- package/dist/runtime/conversations/components/chat-export-questions.d.vue.ts +19 -0
- package/dist/runtime/conversations/components/chat-export-questions.vue +22 -0
- package/dist/runtime/conversations/components/chat-export-questions.vue.d.ts +19 -0
- package/dist/runtime/conversations/composables/conversation-list.d.ts +2 -1
- package/dist/runtime/conversations/composables/conversation-list.js +4 -13
- package/dist/runtime/conversations/export-document.d.ts +1 -0
- package/dist/runtime/conversations/export-document.js +154 -0
- package/dist/runtime/conversations/export.d.ts +4 -0
- package/dist/runtime/conversations/export.js +69 -4
- package/dist/runtime/embed/components/chat-embed-inner.vue +93 -8
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.d.vue.ts +1 -0
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue +2 -0
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue.d.ts +1 -0
- package/dist/runtime/embed/execution-controls.d.ts +2 -1
- package/dist/runtime/embed/execution-controls.js +2 -2
- package/dist/runtime/messages/components/chat-execution-mode-selector.vue +10 -6
- package/dist/runtime/messages/components/chat-message-bubble.vue +7 -0
- package/dist/runtime/messages/components/chat-message-input.d.vue.ts +2 -0
- package/dist/runtime/messages/components/chat-message-input.vue +18 -1
- package/dist/runtime/messages/components/chat-message-input.vue.d.ts +2 -0
- package/dist/runtime/messages/composables/chat.d.ts +15 -0
- package/dist/runtime/messages/composables/chat.js +59 -8
- package/dist/runtime/messages/composer-draft.d.ts +16 -0
- package/dist/runtime/messages/composer-draft.js +61 -0
- package/dist/runtime/messages/composer-pending-send.d.ts +8 -0
- package/dist/runtime/messages/composer-pending-send.js +34 -0
- package/dist/runtime/messages/conversation-timeline.js +1 -1
- package/dist/runtime/server/utils/chat-api-proxy.d.ts +1 -1
- package/dist/runtime/types/composer.d.ts +6 -0
- package/dist/runtime/types/schemas/chat/v3.d.ts +83 -0
- package/dist/runtime/types/schemas/chat/v3.js +28 -1
- package/dist/runtime/types/schemas/integrations/agent-events.d.ts +16 -0
- package/dist/runtime/types/schemas/integrations/agent-events.js +12 -0
- package/dist/runtime/types/schemas/integrations/slack-apps.d.ts +53 -0
- package/dist/runtime/types/schemas/integrations/slack-apps.js +6 -0
- package/dist/runtime/types/schemas/integrations/slack-identity.d.ts +26 -0
- package/dist/runtime/types/schemas/integrations/slack-identity.js +23 -0
- package/dist/runtime/types/schemas/integrations/tela-api.d.ts +11 -0
- package/dist/runtime/types/schemas/integrations/tela-api.js +8 -0
- package/dist/runtime/types/schemas/integrations/tela-auth.d.ts +39 -0
- package/dist/runtime/types/schemas/integrations/tela-auth.js +12 -0
- package/dist/runtime/types/schemas/slack/apps.d.ts +144 -0
- package/dist/runtime/types/schemas/slack/apps.js +53 -0
- package/dist/runtime/types/schemas/slack/identities.d.ts +58 -0
- package/dist/runtime/types/schemas/slack/identities.js +19 -0
- package/dist/runtime/types/schemas/slack/installations.d.ts +39 -0
- package/dist/runtime/types/schemas/slack/installations.js +18 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ Declared in `src/runtime/embed/types.ts`; prop, feature-flag, and event payload
|
|
|
101
101
|
| `defaultConversationCreatorFilter` | `'all' \| 'mine'` | `'all'` | Initial sidebar creator filter: every conversation in scope, or only the current user's |
|
|
102
102
|
| `availableModels` | `AvailableChatModels` | Harness catalog | Visual filter and ordering for catalog options. Unknown ids are omitted; if no ids match, the full catalog is shown. Does not change defaults, restored selections or execution. The Agent validates availability |
|
|
103
103
|
| `defaultModel` | `ChatModel` | Package default | Initial model for untouched drafts. Explicit selections and existing conversations take precedence; `availableModels` only filters the selector |
|
|
104
|
-
| `executionControls` | `ChatExecutionControls` | Legacy feature flags | Choose `hidden`, `simple` (Padrão /
|
|
104
|
+
| `executionControls` | `ChatExecutionControls` | Legacy feature flags | Choose `hidden`, `simple` (Padrão / Aprofundado, plus optional Intensivo), or `advanced` (model and effort pickers). See below |
|
|
105
105
|
| `defaultReasoningEffort` | `ChatReasoningEffort` | Automatic (`null`) | Initial reasoning effort for untouched drafts. Explicit user choices (including automatic) take precedence |
|
|
106
106
|
| `conversationCreatorFilter` | `'all' \| 'mine'` | — | Controlled sidebar creator filter; use with `v-model:conversation-creator-filter` when the host changes it at runtime |
|
|
107
107
|
| `hideConversationCreatorFilter` | `boolean` | `false` | Hide the creator selector without changing the active filter |
|
|
@@ -197,14 +197,16 @@ it takes precedence over both legacy flags as a whole.
|
|
|
197
197
|
mode: 'simple',
|
|
198
198
|
profiles: {
|
|
199
199
|
default: { model: standardModelId, reasoningEffort: 'medium' },
|
|
200
|
-
deep: { model: deepModelId, reasoningEffort: '
|
|
200
|
+
deep: { model: deepModelId, reasoningEffort: 'medium' },
|
|
201
|
+
intensive: { model: deepModelId, reasoningEffort: 'xhigh' },
|
|
201
202
|
},
|
|
202
203
|
}"
|
|
203
204
|
/>
|
|
204
205
|
```
|
|
205
206
|
|
|
206
207
|
Supply model IDs available to the configured agent and effort levels supported
|
|
207
|
-
by those models.
|
|
208
|
+
by those models. The `intensive` profile is optional: omit it to keep a two-mode
|
|
209
|
+
menu. All profiles may use the same model. An explicit `null` effort
|
|
208
210
|
uses the agent's configured effort. Profile selection keeps both settings local
|
|
209
211
|
until the next send or fresh retry. That request persists the settings and records
|
|
210
212
|
each changed field in the conversation history. Reloading discards unsent choices;
|
|
@@ -219,10 +221,10 @@ selection still causes both fields to reset for a new conversation. Manually
|
|
|
219
221
|
replacing both fields in advanced mode retains the existing behavior of carrying
|
|
220
222
|
them over to new conversations.
|
|
221
223
|
Restored conversations keep their settings: the control shows
|
|
222
|
-
**Personalizado** when the saved model and effort do not match
|
|
223
|
-
The menu
|
|
224
|
+
**Personalizado** when the saved model and effort do not match any configured profile.
|
|
225
|
+
The menu offers **Padrão** and **Aprofundado**, plus **Intensivo** when configured. Changes apply to subsequent
|
|
224
226
|
messages and do not regenerate earlier responses. If profiles are identical,
|
|
225
|
-
**Padrão** wins the label match
|
|
227
|
+
**Padrão** wins the label match, followed by **Aprofundado**, then **Intensivo**.
|
|
226
228
|
|
|
227
229
|
In `hidden` and `advanced` modes, the existing model and effort defaults and saved
|
|
228
230
|
conversation settings retain their behavior. Hiding controls does not force a
|
package/dist/module.json
CHANGED
|
@@ -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
|
+
close: () => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
|
+
onClose?: (() => any) | undefined;
|
|
8
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { getFileIcon } from "../../files/icons";
|
|
3
|
+
import { useChatApi } from "../../shared/composables/chat-api";
|
|
4
|
+
import { captureConversationDocument } from "../export-document";
|
|
5
|
+
import { conversationExportFilename, downloadConversationFile, exportConversationToMarkdown, renderedConversationToText } from "../export";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
conversationId: { type: String, required: true }
|
|
8
|
+
});
|
|
9
|
+
const emit = defineEmits(["close"]);
|
|
10
|
+
const chatApi = useChatApi();
|
|
11
|
+
const format = ref("pdf");
|
|
12
|
+
const preparing = ref(false);
|
|
13
|
+
const error = ref(null);
|
|
14
|
+
const conversation = shallowRef(null);
|
|
15
|
+
const documentContainer = ref(null);
|
|
16
|
+
let controller = null;
|
|
17
|
+
const formats = [
|
|
18
|
+
{ value: "pdf", label: "PDF", extension: ".pdf", mimeType: "application/pdf", description: "Formatado, com os widgets renderizados." },
|
|
19
|
+
{ value: "txt", label: "Texto", extension: ".txt", mimeType: "text/plain", description: "Texto simples, com o conte\xFAdo dos widgets." },
|
|
20
|
+
{ value: "md", label: "Markdown", extension: ".md", mimeType: "text/markdown", description: "Com o c\xF3digo original dos widgets." }
|
|
21
|
+
];
|
|
22
|
+
onBeforeUnmount(() => controller?.abort());
|
|
23
|
+
function close() {
|
|
24
|
+
controller?.abort();
|
|
25
|
+
emit("close");
|
|
26
|
+
}
|
|
27
|
+
async function exportConversation() {
|
|
28
|
+
if (preparing.value)
|
|
29
|
+
return;
|
|
30
|
+
preparing.value = true;
|
|
31
|
+
error.value = null;
|
|
32
|
+
controller = new AbortController();
|
|
33
|
+
const signal = controller.signal;
|
|
34
|
+
const selectedFormat = format.value;
|
|
35
|
+
try {
|
|
36
|
+
const data = await $fetch(chatApi.path(`/conversations/${props.conversationId}`), chatApi.withChatHeaders({ signal }));
|
|
37
|
+
signal.throwIfAborted();
|
|
38
|
+
if (selectedFormat === "md") {
|
|
39
|
+
exportConversationToMarkdown(data);
|
|
40
|
+
} else {
|
|
41
|
+
conversation.value = data;
|
|
42
|
+
await nextTick();
|
|
43
|
+
const root = documentContainer.value?.querySelector("[data-export-document]");
|
|
44
|
+
if (!root)
|
|
45
|
+
throw new Error("N\xE3o foi poss\xEDvel preparar a conversa.");
|
|
46
|
+
const html = await captureConversationDocument(root, signal, selectedFormat === "pdf");
|
|
47
|
+
const blob = selectedFormat === "txt" ? new Blob([renderedConversationToText(html)], { type: "text/plain;charset=utf-8" }) : await $fetch(chatApi.path(`/conversations/${props.conversationId}/export/pdf`), chatApi.withChatHeaders({
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: { html },
|
|
50
|
+
responseType: "blob",
|
|
51
|
+
signal,
|
|
52
|
+
retry: 0,
|
|
53
|
+
timeout: 45e3
|
|
54
|
+
}));
|
|
55
|
+
signal.throwIfAborted();
|
|
56
|
+
downloadConversationFile(blob, conversationExportFilename(data.title, selectedFormat));
|
|
57
|
+
}
|
|
58
|
+
emit("close");
|
|
59
|
+
} catch (cause) {
|
|
60
|
+
if (signal.aborted)
|
|
61
|
+
return;
|
|
62
|
+
const status = cause.statusCode;
|
|
63
|
+
error.value = status === 429 ? "H\xE1 outra exporta\xE7\xE3o de PDF em andamento. Aguarde um momento e tente novamente." : status === 413 ? "Esta conversa excede o tamanho permitido para PDF. Voc\xEA pode export\xE1-la como texto ou Markdown." : status === 504 ? "A gera\xE7\xE3o do PDF demorou mais que o esperado. Tente novamente." : "N\xE3o foi poss\xEDvel exportar a conversa. Tente novamente.";
|
|
64
|
+
} finally {
|
|
65
|
+
preparing.value = false;
|
|
66
|
+
conversation.value = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<TelaModal
|
|
73
|
+
:model-value="true"
|
|
74
|
+
modal-width="md"
|
|
75
|
+
:compact="true"
|
|
76
|
+
:hide-dividers="true"
|
|
77
|
+
:is-close-icon="false"
|
|
78
|
+
class="chat-sidebar-floating"
|
|
79
|
+
@update:model-value="(value) => {
|
|
80
|
+
if (!value) close();
|
|
81
|
+
}"
|
|
82
|
+
>
|
|
83
|
+
<div flex="~ col" w-full gap-20px>
|
|
84
|
+
<div flex items-start justify-between gap-16px>
|
|
85
|
+
<div flex="~ col" gap-2px>
|
|
86
|
+
<h4 heading-h4-semibold text-primary>
|
|
87
|
+
Exportar conversa
|
|
88
|
+
</h4>
|
|
89
|
+
<p body-14-regular text-secondary>
|
|
90
|
+
Escolha o formato do arquivo.
|
|
91
|
+
</p>
|
|
92
|
+
</div>
|
|
93
|
+
<TelaIconButton icon="i-ph-x" size="sm" color="secondary" aria-label="Fechar exportação" shrink-0 @click="close" />
|
|
94
|
+
</div>
|
|
95
|
+
<TelaRadioGroupRoot v-model="format" :disabled="preparing" aria-label="Formato do arquivo" flex="~ col" gap-8px w-full>
|
|
96
|
+
<label
|
|
97
|
+
v-for="option in formats"
|
|
98
|
+
:key="option.value"
|
|
99
|
+
flex items-center gap-12px rounded-12px p-12px transition-colors duration-40
|
|
100
|
+
:class="[
|
|
101
|
+
format === option.value ? 'bg-gray-50 b-1px b-gray-700' : 'b-1px b-gray-200 hover:bg-gray-50',
|
|
102
|
+
preparing ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'
|
|
103
|
+
]"
|
|
104
|
+
>
|
|
105
|
+
<img :src="getFileIcon(option.mimeType)" alt="" size-32px shrink-0>
|
|
106
|
+
<span flex="~ col" gap-2px flex-1 min-w-0>
|
|
107
|
+
<span flex items-baseline gap-6px>
|
|
108
|
+
<span body-14-semibold text-primary>{{ option.label }}</span>
|
|
109
|
+
<span body-12-regular text-tertiary>{{ option.extension }}</span>
|
|
110
|
+
</span>
|
|
111
|
+
<span body-12-regular text-secondary>{{ option.description }}</span>
|
|
112
|
+
</span>
|
|
113
|
+
<TelaRadioGroupItem :value="option.value" shrink-0 />
|
|
114
|
+
</label>
|
|
115
|
+
</TelaRadioGroupRoot>
|
|
116
|
+
<div v-if="error" role="alert" flex items-start gap-8px rounded-8px p-12px bg-red-50 b=".5px red-200">
|
|
117
|
+
<span i-ph-warning-circle-fill text-16px text-red-600 shrink-0 mt-2px />
|
|
118
|
+
<p body-14-regular text-red-700>
|
|
119
|
+
{{ error }}
|
|
120
|
+
</p>
|
|
121
|
+
</div>
|
|
122
|
+
<div flex items-center justify-end gap-8px>
|
|
123
|
+
<p v-if="preparing" role="status" body-12-regular text-tertiary mr-auto>
|
|
124
|
+
Preparando arquivo…
|
|
125
|
+
</p>
|
|
126
|
+
<TelaButton variant="secondary" @click="close">
|
|
127
|
+
Cancelar
|
|
128
|
+
</TelaButton>
|
|
129
|
+
<TelaButton icon="i-ph-download-simple" leading :loading="preparing" @click="exportConversation">
|
|
130
|
+
Exportar
|
|
131
|
+
</TelaButton>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</TelaModal>
|
|
135
|
+
<div v-if="conversation" ref="documentContainer" aria-hidden="true" inert class="chat-export-container">
|
|
136
|
+
<ChatExportDocument :conversation="conversation" />
|
|
137
|
+
</div>
|
|
138
|
+
</template>
|
|
139
|
+
|
|
140
|
+
<style scoped>
|
|
141
|
+
.chat-export-container{left:-10000px;pointer-events:none;position:fixed;top:0;width:672px}
|
|
142
|
+
</style>
|
|
@@ -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
|
+
close: () => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
7
|
+
onClose?: (() => any) | undefined;
|
|
8
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
@@ -42,6 +42,7 @@ const {
|
|
|
42
42
|
handleRename,
|
|
43
43
|
handleDuplicate,
|
|
44
44
|
handleExport,
|
|
45
|
+
exportConversationId,
|
|
45
46
|
handleConversationDragStart,
|
|
46
47
|
clearDragState,
|
|
47
48
|
handleDragEnter,
|
|
@@ -313,7 +314,7 @@ function dropTargetClass(row) {
|
|
|
313
314
|
Pastas
|
|
314
315
|
</span>
|
|
315
316
|
<TelaIconButton
|
|
316
|
-
icon="i-ph-plus"
|
|
317
|
+
icon="i-ph-folder-plus"
|
|
317
318
|
color="secondary"
|
|
318
319
|
size="sm"
|
|
319
320
|
button-class="p-3px! rounded-6px!"
|
|
@@ -498,6 +499,12 @@ function dropTargetClass(row) {
|
|
|
498
499
|
{{ deleteGroupConversationsConfirmationMessage }}
|
|
499
500
|
</TelaConfirmationModal>
|
|
500
501
|
|
|
502
|
+
<ChatConversationExportModal
|
|
503
|
+
v-if="exportConversationId"
|
|
504
|
+
:conversation-id="exportConversationId"
|
|
505
|
+
@close="exportConversationId = null"
|
|
506
|
+
/>
|
|
507
|
+
|
|
501
508
|
<ChatConversationDebugModal
|
|
502
509
|
:open="!!debugConversation"
|
|
503
510
|
:conversation="debugConversation"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConversationWithMessages } from '../../types/schemas/chat/conversations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
conversation: ConversationWithMessages;
|
|
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,26 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
conversation: { type: null, required: true }
|
|
4
|
+
});
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div class="chat-export-document" data-export-document>
|
|
9
|
+
<header mb-24px>
|
|
10
|
+
<h1 heading-h3-semibold mb-12px>
|
|
11
|
+
{{ conversation.title || "Conversa" }}
|
|
12
|
+
</h1>
|
|
13
|
+
<p body-14-regular>
|
|
14
|
+
Criada por: {{ conversation.createdBy || "Desconhecido" }}
|
|
15
|
+
</p>
|
|
16
|
+
<p body-14-regular>
|
|
17
|
+
Criada em: {{ new Date(conversation.createdAt).toLocaleString("pt-BR") }}
|
|
18
|
+
</p>
|
|
19
|
+
</header>
|
|
20
|
+
<ChatExportMessage v-for="message in conversation.messages" :key="message.id" :message="message" />
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<style scoped>
|
|
25
|
+
.chat-export-document{background:#fff;color:#202020;font-family:Arial,sans-serif;line-height:1.5;overflow-wrap:anywhere;width:672px}.chat-export-document :deep([data-export-message]){margin-bottom:24px}.chat-export-document :deep(button){pointer-events:none}.chat-export-document :deep(*){animation:none!important;text-overflow:clip!important;transition:none!important}.chat-export-document :deep(pre){white-space:pre-wrap}
|
|
26
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConversationWithMessages } from '../../types/schemas/chat/conversations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
conversation: ConversationWithMessages;
|
|
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,9 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
props: {
|
|
3
|
+
name: string;
|
|
4
|
+
vaultRef: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
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>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
props: { type: Object, required: true }
|
|
4
|
+
});
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div data-openui="file-card" border rounded-8px p-12px flex="~ col" gap-4px>
|
|
9
|
+
<span body-14-medium>{{ props.name }}</span>
|
|
10
|
+
<span body-12-regular>{{ props.vaultRef }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
props: {
|
|
3
|
+
name: string;
|
|
4
|
+
vaultRef: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
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>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Message } from '../../types/schemas/chat/conversations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
message: Message;
|
|
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,84 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { UI_LANG_FENCE } from "@meistrari/chat-ui-lang";
|
|
3
|
+
import { useEmbedConfig } from "../../embed/composables/embed-config";
|
|
4
|
+
import { CHAT_MESSAGE_CONTEXT_KEY, CHAT_MESSAGE_SEND_KEY } from "../../types/messages";
|
|
5
|
+
import { OPENUI_MARKDOWN_COMPONENTS_KEY } from "../../rendering/openui/context";
|
|
6
|
+
import { detectFilesInText, parseContentWithFiles } from "../../files/content-detection";
|
|
7
|
+
import { renderEscapedUserMentions } from "../../messages/user-mentions";
|
|
8
|
+
import ChatExportOpenui from "./chat-export-openui.vue";
|
|
9
|
+
import ChatVaultLink from "../../files/components/chat-vault-link.vue";
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
message: { type: null, required: true }
|
|
12
|
+
});
|
|
13
|
+
const embed = useEmbedConfig();
|
|
14
|
+
provide(CHAT_MESSAGE_CONTEXT_KEY, {
|
|
15
|
+
messageId: props.message.id,
|
|
16
|
+
role: props.message.role,
|
|
17
|
+
isLatestMessage: ref(false),
|
|
18
|
+
streaming: ref(false)
|
|
19
|
+
});
|
|
20
|
+
provide(CHAT_MESSAGE_SEND_KEY, async () => false);
|
|
21
|
+
const customComponents = computed(() => ({
|
|
22
|
+
...embed?.customComponents.value ?? {},
|
|
23
|
+
link: ChatVaultLink,
|
|
24
|
+
[UI_LANG_FENCE]: ChatExportOpenui
|
|
25
|
+
}));
|
|
26
|
+
provide(OPENUI_MARKDOWN_COMPONENTS_KEY, customComponents);
|
|
27
|
+
const segments = computed(() => parseContentWithFiles(props.message.content, { preserveMarkdownLinks: true }));
|
|
28
|
+
const attachedFiles = computed(() => {
|
|
29
|
+
if (props.message.role !== "assistant")
|
|
30
|
+
return props.message.files ?? [];
|
|
31
|
+
const seen = new Set(detectFilesInText(props.message.content).map((file) => file.reference.split("#")[0]));
|
|
32
|
+
return (props.message.files ?? []).filter((file) => {
|
|
33
|
+
const references = [file.url, file.vaultReference].filter(Boolean).map((reference) => reference.split("#")[0]);
|
|
34
|
+
const duplicate = references.some((reference) => seen.has(reference));
|
|
35
|
+
references.forEach((reference) => seen.add(reference));
|
|
36
|
+
return !duplicate;
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
const userContent = computed(() => renderEscapedUserMentions(props.message.content.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """)));
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<article data-export-message>
|
|
44
|
+
<h2 heading-h5-semibold mb-8px>
|
|
45
|
+
{{ message.role === "user" ? message.createdBy || "Usu\xE1rio" : "Assistente" }}
|
|
46
|
+
</h2>
|
|
47
|
+
<p body-12-regular mb-12px>
|
|
48
|
+
{{ new Date(message.createdAt).toLocaleString("pt-BR") }}
|
|
49
|
+
</p>
|
|
50
|
+
<div v-if="message.role === 'user'" whitespace-pre-wrap v-html="userContent" />
|
|
51
|
+
<template v-else>
|
|
52
|
+
<template v-for="(segment, index) in segments" :key="index">
|
|
53
|
+
<AppMarkdownRender
|
|
54
|
+
v-if="segment.type === 'text'"
|
|
55
|
+
:content="segment.content"
|
|
56
|
+
:custom-components="customComponents"
|
|
57
|
+
:custom-html-tags="embed?.customHtmlTags.value ?? []"
|
|
58
|
+
:typewriter="false"
|
|
59
|
+
:batch-rendering="false"
|
|
60
|
+
:node-virtual="false"
|
|
61
|
+
:defer-nodes-until-visible="false"
|
|
62
|
+
:render-code-blocks-as-pre="true"
|
|
63
|
+
:fade="false"
|
|
64
|
+
:final="true"
|
|
65
|
+
/>
|
|
66
|
+
<div v-else-if="segment.type === 'file'" border rounded-8px p-12px>
|
|
67
|
+
<p>{{ segment.file.name }}</p>
|
|
68
|
+
<p body-12-regular>
|
|
69
|
+
{{ segment.file.reference }}
|
|
70
|
+
</p>
|
|
71
|
+
</div>
|
|
72
|
+
<p v-else>
|
|
73
|
+
{{ segment.citation.id }}
|
|
74
|
+
</p>
|
|
75
|
+
</template>
|
|
76
|
+
</template>
|
|
77
|
+
<div v-for="(file, index) in attachedFiles" :key="index" border rounded-8px p-12px mt-12px>
|
|
78
|
+
<p>{{ file.name }}</p>
|
|
79
|
+
<p body-12-regular>
|
|
80
|
+
{{ file.vaultReference || file.url }}
|
|
81
|
+
</p>
|
|
82
|
+
</div>
|
|
83
|
+
</article>
|
|
84
|
+
</template>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Message } from '../../types/schemas/chat/conversations.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
message: Message;
|
|
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,9 @@
|
|
|
1
|
+
import type { CustomMarkdownNode } from '../../rendering/markdown/custom-components.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
node: CustomMarkdownNode & {
|
|
4
|
+
code?: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
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>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import OpenuiMarkdownProse from "../../rendering/components/openui/markdown-prose.vue";
|
|
3
|
+
import OpenuiImage from "../../rendering/components/openui/image.vue";
|
|
4
|
+
import OpenuiCitation from "../../rendering/components/openui/citation.vue";
|
|
5
|
+
import ChatExportQuestions from "./chat-export-questions.vue";
|
|
6
|
+
import ChatExportFile from "./chat-export-file.vue";
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
node: { type: Object, required: true }
|
|
9
|
+
});
|
|
10
|
+
const code = computed(() => props.node.code ?? props.node.content ?? "");
|
|
11
|
+
const host = {
|
|
12
|
+
prose: OpenuiMarkdownProse,
|
|
13
|
+
components: { Questions: ChatExportQuestions, FileCard: ChatExportFile, Image: OpenuiImage, Citation: OpenuiCitation }
|
|
14
|
+
};
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<OpenuiWidget :code="code" :complete="true" :interactive="false" :send="async () => false" :host="host" />
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CustomMarkdownNode } from '../../rendering/markdown/custom-components.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
node: CustomMarkdownNode & {
|
|
4
|
+
code?: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
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>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type Question = {
|
|
2
|
+
props?: {
|
|
3
|
+
title?: string;
|
|
4
|
+
options?: {
|
|
5
|
+
props?: {
|
|
6
|
+
label?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
};
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
type __VLS_Props = {
|
|
13
|
+
props: {
|
|
14
|
+
questions?: Question[];
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
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>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
props: { type: Object, required: true }
|
|
4
|
+
});
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<section data-openui="questions" flex="~ col" gap-16px>
|
|
9
|
+
<div v-for="(question, index) in props.questions ?? []" :key="index">
|
|
10
|
+
<p body-14-medium>
|
|
11
|
+
{{ question.props?.title }}
|
|
12
|
+
</p>
|
|
13
|
+
<ul pl-20px>
|
|
14
|
+
<li v-for="(option, optionIndex) in question.props?.options ?? []" :key="optionIndex" body-14-regular>
|
|
15
|
+
{{ option.props?.label }}<template v-if="option.props?.description">
|
|
16
|
+
— {{ option.props.description }}
|
|
17
|
+
</template>
|
|
18
|
+
</li>
|
|
19
|
+
</ul>
|
|
20
|
+
</div>
|
|
21
|
+
</section>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type Question = {
|
|
2
|
+
props?: {
|
|
3
|
+
title?: string;
|
|
4
|
+
options?: {
|
|
5
|
+
props?: {
|
|
6
|
+
label?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
};
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
type __VLS_Props = {
|
|
13
|
+
props: {
|
|
14
|
+
questions?: Question[];
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
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>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
@@ -111,7 +111,8 @@ export declare function useConversationList(options: ConversationListOptions): {
|
|
|
111
111
|
handleDelete: (id: string) => Promise<void>;
|
|
112
112
|
handleRename: (id: string, title: string) => Promise<void>;
|
|
113
113
|
handleDuplicate: (id: string) => Promise<void>;
|
|
114
|
-
handleExport: (id: string) =>
|
|
114
|
+
handleExport: (id: string) => void;
|
|
115
|
+
exportConversationId: any;
|
|
115
116
|
handleConversationDragStart: (id: string) => void;
|
|
116
117
|
clearDragState: () => void;
|
|
117
118
|
handleDragEnter: (groupId: string | null) => void;
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import { useChatAuth } from "#chat-auth";
|
|
2
|
-
import { exportConversationToMarkdown } from "../export.js";
|
|
3
2
|
import { groupConversationsByGroup } from "../groups.js";
|
|
4
3
|
import { conversationListSkeletonRows } from "../list-skeleton.js";
|
|
5
4
|
import { filterConversationsByTitle } from "../search.js";
|
|
6
5
|
import { resolveChatStateScope } from "../scope.js";
|
|
7
6
|
import { useChat } from "../../messages/composables/chat.js";
|
|
8
|
-
import { useChatApi } from "../../shared/composables/chat-api.js";
|
|
9
7
|
import { useConversationGroups } from "./conversation-groups.js";
|
|
10
8
|
import { useConversations } from "./conversations.js";
|
|
11
9
|
import { useConversationActions } from "./conversation-actions.js";
|
|
12
10
|
import { useEmbedConfig } from "../../embed/composables/embed-config.js";
|
|
13
11
|
const DRAG_OPEN_GROUP_DELAY_MS = 400;
|
|
14
12
|
export function useConversationList(options) {
|
|
15
|
-
const chatApi = useChatApi();
|
|
16
13
|
const embedConfig = useEmbedConfig();
|
|
17
14
|
const { activeOrganization } = useChatAuth();
|
|
18
15
|
const { deleteConversation, renameConversation, duplicateConversation, moveConversationToGroup } = useConversations();
|
|
19
16
|
const { copyConversationLink } = useConversationActions();
|
|
20
17
|
const { groups, fetchGroups, createGroup, deleteGroup, renameGroup, error: groupError, pendingRenameGroupId } = useConversationGroups();
|
|
21
18
|
const { setConversation, currentConversation } = useChat();
|
|
19
|
+
const exportConversationId = ref(null);
|
|
22
20
|
const debugConversationId = ref(null);
|
|
23
21
|
const debugConversation = computed(() => {
|
|
24
22
|
const id = debugConversationId.value;
|
|
@@ -423,16 +421,8 @@ export function useConversationList(options) {
|
|
|
423
421
|
}
|
|
424
422
|
}
|
|
425
423
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const conversation = await $fetch(
|
|
429
|
-
chatApi.path(`/conversations/${id}`),
|
|
430
|
-
chatApi.withChatHeaders()
|
|
431
|
-
);
|
|
432
|
-
exportConversationToMarkdown(conversation);
|
|
433
|
-
} catch (err) {
|
|
434
|
-
console.error("Failed to export conversation:", err);
|
|
435
|
-
}
|
|
424
|
+
function handleExport(id) {
|
|
425
|
+
exportConversationId.value = id;
|
|
436
426
|
}
|
|
437
427
|
function handleConversationDragStart(id) {
|
|
438
428
|
draggedConversationId.value = id;
|
|
@@ -598,6 +588,7 @@ export function useConversationList(options) {
|
|
|
598
588
|
handleRename,
|
|
599
589
|
handleDuplicate,
|
|
600
590
|
handleExport,
|
|
591
|
+
exportConversationId,
|
|
601
592
|
handleConversationDragStart,
|
|
602
593
|
clearDragState,
|
|
603
594
|
handleDragEnter,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function captureConversationDocument(root: HTMLElement, signal: AbortSignal, includeImages: boolean): Promise<string>;
|