@meistrari/chat-nuxt 4.7.1-rc.0 → 4.8.0-rc.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/README.md +60 -1
- package/dist/module.json +1 -1
- package/dist/runtime/conversations/composables/conversations.d.ts +2 -0
- package/dist/runtime/conversations/composables/conversations.js +2 -0
- package/dist/runtime/embed/components/chat-embed-inner.d.vue.ts +10 -10
- package/dist/runtime/embed/components/chat-embed-inner.vue +67 -112
- package/dist/runtime/embed/components/chat-embed-inner.vue.d.ts +10 -10
- package/dist/runtime/embed/components/chat-embed.vue +2 -0
- package/dist/runtime/embed/components/meistrari-chat-embed.vue +2 -0
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.d.vue.ts +7 -3
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue +4 -1
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue.d.ts +7 -3
- package/dist/runtime/embed/composables/embed-config.d.ts +3 -0
- package/dist/runtime/embed/composables/embed-config.js +4 -0
- package/dist/runtime/embed/execution-controls.d.ts +26 -0
- package/dist/runtime/embed/execution-controls.js +18 -0
- package/dist/runtime/embed/feature-config.d.ts +4 -1
- package/dist/runtime/embed/feature-config.js +5 -3
- package/dist/runtime/embed/types.d.ts +3 -0
- package/dist/runtime/lightweight/messages/composables/chat.d.ts +8 -1
- package/dist/runtime/messages/components/chat-execution-mode-selector.d.vue.ts +17 -0
- package/dist/runtime/messages/components/chat-execution-mode-selector.vue +40 -0
- package/dist/runtime/messages/components/chat-execution-mode-selector.vue.d.ts +17 -0
- package/dist/runtime/messages/components/chat-message-input.d.vue.ts +4 -0
- package/dist/runtime/messages/components/chat-message-input.vue +14 -1
- package/dist/runtime/messages/components/chat-message-input.vue.d.ts +4 -0
- package/dist/runtime/messages/composables/chat.d.ts +10 -2
- package/dist/runtime/messages/composables/chat.js +37 -3
- package/dist/runtime/messages/composables/outbound-queue.d.ts +2 -0
- package/dist/runtime/messages/conversation-timeline.js +10 -0
- package/dist/runtime/types/embed.d.ts +1 -0
- package/dist/runtime/types/schemas/chat/conversation-runtime.d.ts +10 -0
- package/dist/runtime/types/schemas/chat/conversation-runtime.js +2 -1
- package/dist/runtime/types/schemas/chat/conversations.d.ts +19 -0
- package/dist/runtime/types/schemas/chat/conversations.js +7 -0
- package/dist/runtime/types/schemas/chat/messages.d.ts +33 -0
- package/dist/runtime/types/schemas/chat/messages.js +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,6 +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 / Aprofundar), or `advanced` (model and effort pickers). See below |
|
|
104
105
|
| `defaultReasoningEffort` | `ChatReasoningEffort` | Automatic (`null`) | Initial reasoning effort for untouched drafts. Explicit user choices (including automatic) take precedence |
|
|
105
106
|
| `conversationCreatorFilter` | `'all' \| 'mine'` | — | Controlled sidebar creator filter; use with `v-model:conversation-creator-filter` when the host changes it at runtime |
|
|
106
107
|
| `hideConversationCreatorFilter` | `boolean` | `false` | Hide the creator selector without changing the active filter |
|
|
@@ -109,7 +110,7 @@ Declared in `src/runtime/embed/types.ts`; prop, feature-flag, and event payload
|
|
|
109
110
|
| `telaAgentInputs` | `TelaAgentExecutionInput[] \| null` | `undefined` | Inputs sent with each Tela agent run; hides the variables panel when non-null |
|
|
110
111
|
| `workspaceSettings` | `WorkspaceSettings \| null` | `null` | Override settings from host app; not accepted in Tela agent mode |
|
|
111
112
|
| `user` | `ChatActor \| null` | `null` | Override current user display info; not accepted in Tela agent mode |
|
|
112
|
-
| `features` | `Partial<ChatFeatureConfig>` | `{}` | Toggle `showUsageTab`, `showDebugOption`, `showCancelButton`, `showTtft`, `chatOutboundQueue`, `showPromptInputHints`, `showModelSelector`, and `showReasoningEffortSelector`; all released features default to `true` |
|
|
113
|
+
| `features` | `Partial<ChatFeatureConfig>` | `{}` | Toggle `showUsageTab`, `showDebugOption`, `showCancelButton`, `showTtft`, `chatOutboundQueue`, `showPromptInputHints`, `showModelSelector`, and `showReasoningEffortSelector`; all released features default to `true`. The two picker flags are deprecated in favor of `executionControls` |
|
|
113
114
|
| `loadingMessages` | `readonly string[] \| null` | Default chat messages | Override pending-response messages |
|
|
114
115
|
| `loadingMessagesMode` | `'ordered' \| 'random' \| null` | `'ordered'` | Rotate custom messages in order or at random; only applies when `loadingMessages` has a non-empty message |
|
|
115
116
|
| `labels` | `Partial<ChatLabels>` | Portuguese defaults | Override conversation-search text; see [UI labels](docs/guides/embedding.md#ui-labels) for supported keys and surfaces |
|
|
@@ -181,3 +182,61 @@ Peer dependencies:
|
|
|
181
182
|
|---------|---------|---------|
|
|
182
183
|
| `nuxt` | `^3.17.0 \|\| ^4.0.0` | Host framework |
|
|
183
184
|
| `vue` | `^3.5.0` | Host Vue runtime |
|
|
185
|
+
|
|
186
|
+
### Execution controls
|
|
187
|
+
|
|
188
|
+
`executionControls` selects how users configure a response. Omit it to preserve
|
|
189
|
+
existing behavior, including `features.showModelSelector` and
|
|
190
|
+
`features.showReasoningEffortSelector`. Both legacy fields remain supported and
|
|
191
|
+
are marked `@deprecated` for editor guidance. When `executionControls` is present,
|
|
192
|
+
it takes precedence over both legacy flags as a whole.
|
|
193
|
+
|
|
194
|
+
```vue
|
|
195
|
+
<MeistrariChatEmbed
|
|
196
|
+
:execution-controls="{
|
|
197
|
+
mode: 'simple',
|
|
198
|
+
profiles: {
|
|
199
|
+
default: { model: standardModelId, reasoningEffort: 'medium' },
|
|
200
|
+
deep: { model: deepModelId, reasoningEffort: 'high' },
|
|
201
|
+
},
|
|
202
|
+
}"
|
|
203
|
+
/>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Supply model IDs available to the configured agent and effort levels supported
|
|
207
|
+
by those models. Both profiles may use the same model. An explicit `null` effort
|
|
208
|
+
uses the agent's configured effort. Profile selection keeps both settings local
|
|
209
|
+
until the next send or fresh retry. That request persists the settings and records
|
|
210
|
+
each changed field in the conversation history. Reloading discards unsent choices;
|
|
211
|
+
a rejected admission restores the prior persisted settings.
|
|
212
|
+
|
|
213
|
+
In `simple` mode, new conversations start with the `default` profile, regardless
|
|
214
|
+
of `defaultModel` and `defaultReasoningEffort`. A selection stays within the current
|
|
215
|
+
conversation. Changing control modes preserves explicit draft choices. Starting
|
|
216
|
+
a new conversation discards a simple selection even if the controls have since
|
|
217
|
+
been hidden or switched to advanced mode. If only one field is manually changed in advanced mode, the remaining simple
|
|
218
|
+
selection still causes both fields to reset for a new conversation. Manually
|
|
219
|
+
replacing both fields in advanced mode retains the existing behavior of carrying
|
|
220
|
+
them over to new conversations.
|
|
221
|
+
Restored conversations keep their settings: the control shows
|
|
222
|
+
**Personalizado** when the saved model and effort do not match either profile.
|
|
223
|
+
The menu still offers only **Padrão** and **Aprofundar**. Changes apply to subsequent
|
|
224
|
+
messages and do not regenerate earlier responses. If profiles are identical,
|
|
225
|
+
**Padrão** wins the label match.
|
|
226
|
+
|
|
227
|
+
In `hidden` and `advanced` modes, the existing model and effort defaults and saved
|
|
228
|
+
conversation settings retain their behavior. Hiding controls does not force a
|
|
229
|
+
model or effort. `availableModels` continues to filter the advanced model picker;
|
|
230
|
+
it does not filter or rewrite the simple profiles.
|
|
231
|
+
|
|
232
|
+
| Legacy configuration | Replacement |
|
|
233
|
+
| --- | --- |
|
|
234
|
+
| Both picker flags `false` | `{ mode: 'hidden' }` |
|
|
235
|
+
| Both picker flags `true` | `{ mode: 'advanced' }` |
|
|
236
|
+
| Only effort picker `false` | `{ mode: 'advanced', showReasoningEffortSelector: false }` |
|
|
237
|
+
| Only model picker `false` | `{ mode: 'advanced', showModelSelector: false }` |
|
|
238
|
+
|
|
239
|
+
Advanced picker flags default to `true`. Import `ChatExecutionControls` and
|
|
240
|
+
`ChatExecutionProfile` from `@meistrari/chat-nuxt/types/embed` when declaring host
|
|
241
|
+
configuration separately. `defaultModel` and `defaultReasoningEffort` are not
|
|
242
|
+
deprecated.
|
package/dist/module.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ChatExecutionProfile } from '../../embed/execution-controls.js';
|
|
1
2
|
import type { DeepReadonly } from 'vue';
|
|
2
3
|
import type { Conversation, ConversationWithMessages, CreateConversationRequest } from '../../types/schemas/chat/conversations.js';
|
|
3
4
|
import type { ChatReasoningEffort } from '../../types/schemas/chat/models.js';
|
|
@@ -14,6 +15,7 @@ export declare function useConversations(): {
|
|
|
14
15
|
renameConversation: (id: string, title: string) => Promise<boolean>;
|
|
15
16
|
updateConversationModel: (id: string, model: string | null) => Promise<boolean>;
|
|
16
17
|
updateConversationReasoningEffort: (id: string, reasoningEffort: ChatReasoningEffort | null) => Promise<boolean>;
|
|
18
|
+
updateConversationExecutionProfile: (id: string, profile: ChatExecutionProfile) => Promise<boolean>;
|
|
17
19
|
moveConversationToGroup: (id: string, groupId: string | null) => Promise<boolean>;
|
|
18
20
|
duplicateConversation: (id: string) => Promise<ConversationWithMessages | null>;
|
|
19
21
|
forkConversation: (id: string, messageId: string) => Promise<ConversationWithMessages | null>;
|
|
@@ -505,6 +505,7 @@ export function useConversations() {
|
|
|
505
505
|
};
|
|
506
506
|
const updateConversationModel = (id, model) => patchConversationSetting(id, { model }, "Erro ao atualizar modelo da conversa");
|
|
507
507
|
const updateConversationReasoningEffort = (id, reasoningEffort) => patchConversationSetting(id, { reasoningEffort }, "Erro ao atualizar o esfor\xE7o de racioc\xEDnio da conversa");
|
|
508
|
+
const updateConversationExecutionProfile = (id, profile) => patchConversationSetting(id, profile, "Erro ao atualizar o modo de resposta da conversa");
|
|
508
509
|
const forkConversation = async (id, messageId) => {
|
|
509
510
|
error.value = null;
|
|
510
511
|
const statusToast = useStatusToast();
|
|
@@ -561,6 +562,7 @@ export function useConversations() {
|
|
|
561
562
|
renameConversation,
|
|
562
563
|
updateConversationModel,
|
|
563
564
|
updateConversationReasoningEffort,
|
|
565
|
+
updateConversationExecutionProfile,
|
|
564
566
|
moveConversationToGroup,
|
|
565
567
|
duplicateConversation,
|
|
566
568
|
forkConversation,
|
|
@@ -19,27 +19,27 @@ type __VLS_Props = {
|
|
|
19
19
|
user?: EmbedUser | null;
|
|
20
20
|
features?: Partial<ChatFeatureConfig>;
|
|
21
21
|
};
|
|
22
|
-
declare var __VLS_14: {},
|
|
22
|
+
declare var __VLS_14: {}, __VLS_92: {}, __VLS_105: {
|
|
23
23
|
message: useChatAuth;
|
|
24
|
-
},
|
|
24
|
+
}, __VLS_118: {}, __VLS_127: {}, __VLS_191: {}, __VLS_210: {
|
|
25
25
|
message: useChatAuth;
|
|
26
|
-
},
|
|
26
|
+
}, __VLS_223: {};
|
|
27
27
|
type __VLS_Slots = {} & {
|
|
28
28
|
'sidebar-bottom'?: (props: typeof __VLS_14) => any;
|
|
29
29
|
} & {
|
|
30
|
-
'composer-bottom'?: (props: typeof
|
|
30
|
+
'composer-bottom'?: (props: typeof __VLS_92) => any;
|
|
31
31
|
} & {
|
|
32
|
-
'failed-message-actions'?: (props: typeof
|
|
32
|
+
'failed-message-actions'?: (props: typeof __VLS_105) => any;
|
|
33
33
|
} & {
|
|
34
|
-
'composer-bottom'?: (props: typeof
|
|
34
|
+
'composer-bottom'?: (props: typeof __VLS_118) => any;
|
|
35
35
|
} & {
|
|
36
|
-
'topbar-leading'?: (props: typeof
|
|
36
|
+
'topbar-leading'?: (props: typeof __VLS_127) => any;
|
|
37
37
|
} & {
|
|
38
|
-
'composer-bottom'?: (props: typeof
|
|
38
|
+
'composer-bottom'?: (props: typeof __VLS_191) => any;
|
|
39
39
|
} & {
|
|
40
|
-
'failed-message-actions'?: (props: typeof
|
|
40
|
+
'failed-message-actions'?: (props: typeof __VLS_210) => any;
|
|
41
41
|
} & {
|
|
42
|
-
'composer-bottom'?: (props: typeof
|
|
42
|
+
'composer-bottom'?: (props: typeof __VLS_223) => any;
|
|
43
43
|
};
|
|
44
44
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
45
45
|
"update:conversationId": (value: string | null) => any;
|
|
@@ -23,10 +23,6 @@ import {
|
|
|
23
23
|
resolveTelaAgentInputs,
|
|
24
24
|
useChat
|
|
25
25
|
} from "../../messages/composables/chat";
|
|
26
|
-
import {
|
|
27
|
-
ensureConversationUsesSelectedModel,
|
|
28
|
-
MODEL_UPDATE_FAILED_MESSAGE
|
|
29
|
-
} from "../../messages/model-availability";
|
|
30
26
|
import { useChatAction } from "../../messages/composables/chat-action";
|
|
31
27
|
import { useChatApi } from "../../shared/composables/chat-api";
|
|
32
28
|
import { useConversationFiles } from "../../files/composables/conversation-files";
|
|
@@ -95,8 +91,6 @@ const {
|
|
|
95
91
|
createConversation,
|
|
96
92
|
deleteConversation,
|
|
97
93
|
renameConversation,
|
|
98
|
-
updateConversationModel,
|
|
99
|
-
updateConversationReasoningEffort,
|
|
100
94
|
duplicateConversation,
|
|
101
95
|
forkConversation,
|
|
102
96
|
moveConversationToGroup,
|
|
@@ -173,7 +167,7 @@ const {
|
|
|
173
167
|
setPendingConversationGroup,
|
|
174
168
|
clearPendingConversationGroup
|
|
175
169
|
} = usePendingConversationGroup();
|
|
176
|
-
const resolvedFeatures = computed(() => resolveChatFeatures(props.features));
|
|
170
|
+
const resolvedFeatures = computed(() => resolveChatFeatures(props.features, embedConfig?.executionControls?.value));
|
|
177
171
|
const dropZoneRef = ref(null);
|
|
178
172
|
const activeTab = ref("chat");
|
|
179
173
|
const answerTarget = ref(null);
|
|
@@ -226,9 +220,7 @@ const {
|
|
|
226
220
|
loadConversation,
|
|
227
221
|
setConversation,
|
|
228
222
|
adoptConversation,
|
|
229
|
-
setConversationModel,
|
|
230
223
|
pendingModelSelection,
|
|
231
|
-
setConversationReasoningEffort,
|
|
232
224
|
pendingReasoningEffortSelection,
|
|
233
225
|
sendMessage,
|
|
234
226
|
flushOutboundQueue,
|
|
@@ -245,89 +237,43 @@ const {
|
|
|
245
237
|
onQueuedSendFailed: restoreQueuedSend
|
|
246
238
|
});
|
|
247
239
|
const agentWake = harnessAdapter?.requiresSandboxWake === false ? null : useAgentWake();
|
|
248
|
-
const modelUpdateInFlight = ref(null);
|
|
249
|
-
const reasoningEffortUpdateInFlight = ref(null);
|
|
250
|
-
const REASONING_EFFORT_UPDATE_FAILED_MESSAGE = "N\xE3o foi poss\xEDvel atualizar o esfor\xE7o de racioc\xEDnio da conversa";
|
|
251
240
|
watch(chatError, (message) => {
|
|
252
241
|
if (message)
|
|
253
242
|
statusToast.update({ text: message, icon: "i-ph-warning" });
|
|
254
243
|
});
|
|
255
244
|
const { total, files: conversationFiles, loading: conversationFilesLoading } = useConversationFiles(activeConversationId);
|
|
256
|
-
function persistConversationModel(conversation, value, wakeAgent) {
|
|
257
|
-
const previousModel = conversation.model;
|
|
258
|
-
setConversationModel(value);
|
|
259
|
-
const update = updateConversationModel(conversation.id, value).then(async (updated) => {
|
|
260
|
-
if (!updated && currentConversation.value?.id === conversation.id && currentConversation.value.model === value) {
|
|
261
|
-
setConversationModel(previousModel);
|
|
262
|
-
} else if (agentWake && updated && value && wakeAgent && !chatApi.conversationV2Enabled) {
|
|
263
|
-
if (conversation.threadSessionId)
|
|
264
|
-
await agentWake.ensureReady(conversation.threadSessionId, value);
|
|
265
|
-
else
|
|
266
|
-
await agentWake.wake(void 0, value);
|
|
267
|
-
}
|
|
268
|
-
return updated;
|
|
269
|
-
});
|
|
270
|
-
const trackedUpdate = update.finally(() => {
|
|
271
|
-
if (modelUpdateInFlight.value === trackedUpdate)
|
|
272
|
-
modelUpdateInFlight.value = null;
|
|
273
|
-
});
|
|
274
|
-
modelUpdateInFlight.value = trackedUpdate;
|
|
275
|
-
return trackedUpdate;
|
|
276
|
-
}
|
|
277
|
-
async function waitForPendingModelUpdate() {
|
|
278
|
-
while (modelUpdateInFlight.value) {
|
|
279
|
-
const update = modelUpdateInFlight.value;
|
|
280
|
-
if (!await update)
|
|
281
|
-
throw new Error(MODEL_UPDATE_FAILED_MESSAGE);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
function persistConversationReasoningEffort(conversation, value) {
|
|
285
|
-
const previousEffort = conversation.reasoningEffort ?? null;
|
|
286
|
-
setConversationReasoningEffort(value);
|
|
287
|
-
const update = updateConversationReasoningEffort(conversation.id, value).then((updated) => {
|
|
288
|
-
if (!updated && currentConversation.value?.id === conversation.id && (currentConversation.value.reasoningEffort ?? null) === value) {
|
|
289
|
-
setConversationReasoningEffort(previousEffort);
|
|
290
|
-
}
|
|
291
|
-
return updated;
|
|
292
|
-
});
|
|
293
|
-
const trackedUpdate = update.finally(() => {
|
|
294
|
-
if (reasoningEffortUpdateInFlight.value === trackedUpdate)
|
|
295
|
-
reasoningEffortUpdateInFlight.value = null;
|
|
296
|
-
});
|
|
297
|
-
reasoningEffortUpdateInFlight.value = trackedUpdate;
|
|
298
|
-
return trackedUpdate;
|
|
299
|
-
}
|
|
300
|
-
async function waitForPendingReasoningEffortUpdate() {
|
|
301
|
-
while (reasoningEffortUpdateInFlight.value) {
|
|
302
|
-
const update = reasoningEffortUpdateInFlight.value;
|
|
303
|
-
if (!await update)
|
|
304
|
-
throw new Error(REASONING_EFFORT_UPDATE_FAILED_MESSAGE);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
245
|
function resolveSelectedModel(value) {
|
|
308
246
|
return nativeModels ? nativeModels.resolve(value) : value;
|
|
309
247
|
}
|
|
248
|
+
const draftModel = ref(void 0);
|
|
249
|
+
const draftReasoningEffort = ref(void 0);
|
|
250
|
+
watch(() => currentConversation.value?.id, () => {
|
|
251
|
+
draftModel.value = void 0;
|
|
252
|
+
draftReasoningEffort.value = void 0;
|
|
253
|
+
}, { flush: "sync" });
|
|
310
254
|
const selectedModel = computed({
|
|
311
|
-
get: () => resolveSelectedModel(
|
|
312
|
-
currentConversation.value ? currentConversation.value.model : pendingModelSelection.value
|
|
313
|
-
),
|
|
255
|
+
get: () => resolveSelectedModel(draftModel.value !== void 0 ? draftModel.value : currentConversation.value ? currentConversation.value.model : pendingModelSelection.value),
|
|
314
256
|
set: (value) => {
|
|
315
|
-
const
|
|
316
|
-
pendingModelSelection.value =
|
|
317
|
-
|
|
318
|
-
if (conversation && conversation.model !== resolvedValue)
|
|
319
|
-
void persistConversationModel(conversation, resolvedValue, true);
|
|
257
|
+
const resolved = resolveSelectedModel(value);
|
|
258
|
+
pendingModelSelection.value = resolved;
|
|
259
|
+
draftModel.value = resolved;
|
|
320
260
|
}
|
|
321
261
|
});
|
|
322
262
|
const selectedReasoningEffort = computed({
|
|
323
|
-
get: () => currentConversation.value ? currentConversation.value.reasoningEffort ?? null : pendingReasoningEffortSelection.value,
|
|
263
|
+
get: () => draftReasoningEffort.value !== void 0 ? draftReasoningEffort.value : currentConversation.value ? currentConversation.value.reasoningEffort ?? null : pendingReasoningEffortSelection.value,
|
|
324
264
|
set: (value) => {
|
|
325
265
|
pendingReasoningEffortSelection.value = value;
|
|
326
|
-
|
|
327
|
-
if (conversation && (conversation.reasoningEffort ?? null) !== value)
|
|
328
|
-
void persistConversationReasoningEffort(conversation, value);
|
|
266
|
+
draftReasoningEffort.value = value;
|
|
329
267
|
}
|
|
330
268
|
});
|
|
269
|
+
function selectExecutionProfile(profile) {
|
|
270
|
+
draftModel.value = resolveSelectedModel(profile.model);
|
|
271
|
+
draftReasoningEffort.value = profile.reasoningEffort;
|
|
272
|
+
if (!currentConversation.value) {
|
|
273
|
+
pendingModelSelection.value = draftModel.value;
|
|
274
|
+
pendingReasoningEffortSelection.value = profile.reasoningEffort;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
331
277
|
const filesCount = computed(() => total.value);
|
|
332
278
|
const showDetailsPanel = computed(() => !!currentConversation.value && !isMobile.value && !props.compact);
|
|
333
279
|
const detailsConversationId = computed(() => activeConversationId.value ?? currentConversation.value?.id ?? null);
|
|
@@ -413,6 +359,8 @@ async function ensureConversationLoaded(conversationId) {
|
|
|
413
359
|
}
|
|
414
360
|
}
|
|
415
361
|
function resetConversation(shouldEmit = true) {
|
|
362
|
+
draftModel.value = void 0;
|
|
363
|
+
draftReasoningEffort.value = void 0;
|
|
416
364
|
clearConversation();
|
|
417
365
|
agentWake?.consume();
|
|
418
366
|
if (agentWake && !chatApi.conversationV2Enabled)
|
|
@@ -594,14 +542,14 @@ async function handleSend(content, files, agentInputs) {
|
|
|
594
542
|
restoreQueuedSend({ content: prepared?.retryContent?.() ?? content, files, agentInputs: resolvedAgentInputs });
|
|
595
543
|
}
|
|
596
544
|
async function dispatchMessage(outbound, files, resolvedAgentInputs) {
|
|
545
|
+
const executionSettings = { model: selectedModel.value, reasoningEffort: selectedReasoningEffort.value };
|
|
597
546
|
if (props.sendBlocked)
|
|
598
547
|
return false;
|
|
599
548
|
let claimedWakeSessionId;
|
|
600
549
|
const sent = await sendMessage(outbound, files.length > 0 ? files : void 0, resolvedAgentInputs, async (signal) => {
|
|
601
550
|
if (!activeConversationId.value || !currentConversation.value) {
|
|
602
551
|
const conversation2 = await createConversation({
|
|
603
|
-
|
|
604
|
-
reasoningEffort: selectedReasoningEffort.value,
|
|
552
|
+
...executionSettings,
|
|
605
553
|
...resolvedAgentInputs !== void 0 ? { agentInputs: resolvedAgentInputs } : {}
|
|
606
554
|
});
|
|
607
555
|
if (!conversation2)
|
|
@@ -612,36 +560,29 @@ async function dispatchMessage(outbound, files, resolvedAgentInputs) {
|
|
|
612
560
|
adoptConversation(grouped ? { ...conversation2, groupId } : conversation2);
|
|
613
561
|
updateConversationId(conversation2.id);
|
|
614
562
|
}
|
|
615
|
-
await waitForPendingModelUpdate();
|
|
616
|
-
await waitForPendingReasoningEffortUpdate();
|
|
617
563
|
const conversation = currentConversation.value;
|
|
618
564
|
if (!conversation)
|
|
619
565
|
throw new Error("Erro ao preparar conversa");
|
|
620
|
-
await (nativeModels?.ensureSelectedModel ?? ensureConversationUsesSelectedModel)(
|
|
621
|
-
conversation.model,
|
|
622
|
-
selectedModel.value,
|
|
623
|
-
(value) => persistConversationModel(conversation, value, false)
|
|
624
|
-
);
|
|
625
566
|
if (!agentWake || chatApi.conversationV2Enabled)
|
|
626
|
-
return {};
|
|
567
|
+
return { executionSettings };
|
|
627
568
|
if (conversation.threadSessionId && resolvedFeatures.value.chatOutboundQueue) {
|
|
628
|
-
const wake = await agentWake.ensureReady(conversation.threadSessionId,
|
|
569
|
+
const wake = await agentWake.ensureReady(conversation.threadSessionId, executionSettings.model);
|
|
629
570
|
if (wake.status !== "ready") {
|
|
630
571
|
if (wake.wokenSandbox && !wake.wokenSandbox.rewakeable)
|
|
631
|
-
return { defer: true };
|
|
572
|
+
return { defer: true, executionSettings };
|
|
632
573
|
throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
|
|
633
574
|
}
|
|
634
|
-
return {};
|
|
575
|
+
return { executionSettings };
|
|
635
576
|
}
|
|
636
577
|
if (!conversation.threadSessionId) {
|
|
637
578
|
await agentWake.waitUntilSettled(signal);
|
|
638
579
|
if (agentWake.state.value === "idle")
|
|
639
|
-
await agentWake.wake(void 0,
|
|
580
|
+
await agentWake.wake(void 0, executionSettings.model);
|
|
640
581
|
}
|
|
641
582
|
claimedWakeSessionId = claimableWakeSessionId();
|
|
642
583
|
if (!conversation.threadSessionId && !claimedWakeSessionId)
|
|
643
584
|
throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
|
|
644
|
-
return claimedWakeSessionId ? { wakeSessionId: claimedWakeSessionId } : {};
|
|
585
|
+
return { executionSettings, ...claimedWakeSessionId ? { wakeSessionId: claimedWakeSessionId } : {} };
|
|
645
586
|
});
|
|
646
587
|
if (sent && claimedWakeSessionId)
|
|
647
588
|
agentWake?.consume();
|
|
@@ -684,26 +625,21 @@ async function handleCancel() {
|
|
|
684
625
|
await cancelConversation();
|
|
685
626
|
}
|
|
686
627
|
async function handleRetry(messageId) {
|
|
628
|
+
const executionSettings = { model: selectedModel.value, reasoningEffort: selectedReasoningEffort.value };
|
|
687
629
|
await retryMessage(messageId, async () => {
|
|
688
|
-
await waitForPendingModelUpdate();
|
|
689
|
-
await waitForPendingReasoningEffortUpdate();
|
|
690
630
|
const conversation = currentConversation.value;
|
|
691
631
|
if (!conversation)
|
|
692
632
|
throw new Error("Erro ao preparar conversa");
|
|
693
|
-
await (nativeModels?.ensureSelectedModel ?? ensureConversationUsesSelectedModel)(
|
|
694
|
-
conversation.model,
|
|
695
|
-
selectedModel.value,
|
|
696
|
-
(value) => persistConversationModel(conversation, value, false)
|
|
697
|
-
);
|
|
698
633
|
if (!agentWake || chatApi.conversationV2Enabled)
|
|
699
|
-
return;
|
|
634
|
+
return { executionSettings };
|
|
700
635
|
if (conversation.threadSessionId) {
|
|
701
|
-
const wake = await agentWake.ensureReady(conversation.threadSessionId,
|
|
636
|
+
const wake = await agentWake.ensureReady(conversation.threadSessionId, executionSettings.model);
|
|
702
637
|
if (wake.status !== "ready")
|
|
703
638
|
throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
|
|
704
639
|
} else {
|
|
705
640
|
agentWake.consume();
|
|
706
641
|
}
|
|
642
|
+
return { executionSettings };
|
|
707
643
|
});
|
|
708
644
|
}
|
|
709
645
|
async function handleNewConversation(groupId) {
|
|
@@ -790,30 +726,35 @@ function handleShare(conversationId) {
|
|
|
790
726
|
if (id)
|
|
791
727
|
void copyConversationLink(id);
|
|
792
728
|
}
|
|
793
|
-
const
|
|
729
|
+
const persistedConversationEvents = shallowRef([]);
|
|
794
730
|
const displayConversationEvents = computed(() => [...new Map([
|
|
795
|
-
...
|
|
731
|
+
...persistedConversationEvents.value,
|
|
796
732
|
...props.conversationEvents ?? []
|
|
797
733
|
].filter((event) => event.conversationId === currentConversation.value?.id).map((event) => [event.id, event])).values()]);
|
|
798
734
|
watch([
|
|
799
735
|
() => currentConversation.value?.id,
|
|
800
|
-
() => JSON.stringify(chatApi.withChatHeaders().headers)
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
736
|
+
() => JSON.stringify(chatApi.withChatHeaders().headers),
|
|
737
|
+
() => JSON.stringify(messages.value.filter((message) => message.role === "user").map((message) => [message.id, message.createdAt, message.externalUuid])),
|
|
738
|
+
() => isPolling.value
|
|
739
|
+
], async ([conversationId], previous, onCleanup) => {
|
|
740
|
+
if (conversationId !== previous?.[0] || JSON.stringify(chatApi.withChatHeaders().headers) !== previous?.[1])
|
|
741
|
+
persistedConversationEvents.value = [];
|
|
742
|
+
if (!conversationId)
|
|
804
743
|
return;
|
|
805
|
-
|
|
806
|
-
onCleanup(() =>
|
|
744
|
+
let current = true;
|
|
745
|
+
onCleanup(() => {
|
|
746
|
+
current = false;
|
|
747
|
+
});
|
|
807
748
|
try {
|
|
808
749
|
const { events } = await $fetch(
|
|
809
750
|
chatApi.path(`/conversations/${conversationId}/events`),
|
|
810
|
-
chatApi.withChatHeaders(
|
|
751
|
+
chatApi.withChatHeaders()
|
|
811
752
|
);
|
|
812
|
-
if (
|
|
813
|
-
|
|
753
|
+
if (current)
|
|
754
|
+
persistedConversationEvents.value = events;
|
|
814
755
|
} catch {
|
|
815
|
-
if (
|
|
816
|
-
statusToast.update({ text: "Erro ao carregar
|
|
756
|
+
if (current)
|
|
757
|
+
statusToast.update({ text: "Erro ao carregar os eventos da conversa", icon: "i-ph-warning" });
|
|
817
758
|
}
|
|
818
759
|
}, { immediate: true });
|
|
819
760
|
const forking = ref(false);
|
|
@@ -1005,6 +946,7 @@ async function handleDelete() {
|
|
|
1005
946
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1006
947
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1007
948
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
949
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
1008
950
|
:show-debug-option="resolvedFeatures.showDebugOption"
|
|
1009
951
|
:show-outdated-badge="showOutdatedBadge"
|
|
1010
952
|
:show-outdated-banner="showOutdatedBanner"
|
|
@@ -1012,6 +954,7 @@ async function handleDelete() {
|
|
|
1012
954
|
:workspace-logo="workspaceLogo"
|
|
1013
955
|
:workspace-name="workspaceName"
|
|
1014
956
|
:workspace-settings="effectiveWorkspaceSettings"
|
|
957
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1015
958
|
@cancel="handleCancel"
|
|
1016
959
|
@cancel-editing="cancelEditing"
|
|
1017
960
|
@copy-link="handleShare()"
|
|
@@ -1048,6 +991,8 @@ async function handleDelete() {
|
|
|
1048
991
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1049
992
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1050
993
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
994
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
995
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1051
996
|
/>
|
|
1052
997
|
</template>
|
|
1053
998
|
|
|
@@ -1093,7 +1038,9 @@ async function handleDelete() {
|
|
|
1093
1038
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1094
1039
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1095
1040
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
1041
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
1096
1042
|
centered
|
|
1043
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1097
1044
|
@send="handleSend"
|
|
1098
1045
|
@cancel="handleCancel"
|
|
1099
1046
|
/>
|
|
@@ -1147,7 +1094,9 @@ async function handleDelete() {
|
|
|
1147
1094
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1148
1095
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1149
1096
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
1097
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
1150
1098
|
has-disclaimer
|
|
1099
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1151
1100
|
@send="handleSend"
|
|
1152
1101
|
@cancel="handleCancel"
|
|
1153
1102
|
/>
|
|
@@ -1246,6 +1195,8 @@ async function handleDelete() {
|
|
|
1246
1195
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1247
1196
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1248
1197
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
1198
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
1199
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1249
1200
|
/>
|
|
1250
1201
|
</TelaChatBody>
|
|
1251
1202
|
|
|
@@ -1297,7 +1248,9 @@ async function handleDelete() {
|
|
|
1297
1248
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1298
1249
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1299
1250
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
1251
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
1300
1252
|
centered
|
|
1253
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1301
1254
|
@send="handleSend"
|
|
1302
1255
|
@cancel="handleCancel"
|
|
1303
1256
|
/>
|
|
@@ -1354,7 +1307,9 @@ async function handleDelete() {
|
|
|
1354
1307
|
:show-cancel-button="resolvedFeatures.showCancelButton"
|
|
1355
1308
|
:hide-model-selector="!resolvedFeatures.showModelSelector"
|
|
1356
1309
|
:hide-reasoning-effort-selector="!resolvedFeatures.showReasoningEffortSelector"
|
|
1310
|
+
:execution-controls-disabled="!!modelUpdateInFlight || !!reasoningEffortUpdateInFlight"
|
|
1357
1311
|
has-disclaimer
|
|
1312
|
+
@select-execution-profile="selectExecutionProfile"
|
|
1358
1313
|
@send="handleSend"
|
|
1359
1314
|
@cancel="handleCancel"
|
|
1360
1315
|
/>
|
|
@@ -19,27 +19,27 @@ type __VLS_Props = {
|
|
|
19
19
|
user?: EmbedUser | null;
|
|
20
20
|
features?: Partial<ChatFeatureConfig>;
|
|
21
21
|
};
|
|
22
|
-
declare var __VLS_14: {},
|
|
22
|
+
declare var __VLS_14: {}, __VLS_92: {}, __VLS_105: {
|
|
23
23
|
message: useChatAuth;
|
|
24
|
-
},
|
|
24
|
+
}, __VLS_118: {}, __VLS_127: {}, __VLS_191: {}, __VLS_210: {
|
|
25
25
|
message: useChatAuth;
|
|
26
|
-
},
|
|
26
|
+
}, __VLS_223: {};
|
|
27
27
|
type __VLS_Slots = {} & {
|
|
28
28
|
'sidebar-bottom'?: (props: typeof __VLS_14) => any;
|
|
29
29
|
} & {
|
|
30
|
-
'composer-bottom'?: (props: typeof
|
|
30
|
+
'composer-bottom'?: (props: typeof __VLS_92) => any;
|
|
31
31
|
} & {
|
|
32
|
-
'failed-message-actions'?: (props: typeof
|
|
32
|
+
'failed-message-actions'?: (props: typeof __VLS_105) => any;
|
|
33
33
|
} & {
|
|
34
|
-
'composer-bottom'?: (props: typeof
|
|
34
|
+
'composer-bottom'?: (props: typeof __VLS_118) => any;
|
|
35
35
|
} & {
|
|
36
|
-
'topbar-leading'?: (props: typeof
|
|
36
|
+
'topbar-leading'?: (props: typeof __VLS_127) => any;
|
|
37
37
|
} & {
|
|
38
|
-
'composer-bottom'?: (props: typeof
|
|
38
|
+
'composer-bottom'?: (props: typeof __VLS_191) => any;
|
|
39
39
|
} & {
|
|
40
|
-
'failed-message-actions'?: (props: typeof
|
|
40
|
+
'failed-message-actions'?: (props: typeof __VLS_210) => any;
|
|
41
41
|
} & {
|
|
42
|
-
'composer-bottom'?: (props: typeof
|
|
42
|
+
'composer-bottom'?: (props: typeof __VLS_223) => any;
|
|
43
43
|
};
|
|
44
44
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
45
45
|
"update:conversationId": (value: string | null) => any;
|
|
@@ -20,6 +20,7 @@ const props = defineProps({
|
|
|
20
20
|
defaultConversationCreatorFilter: { type: null, required: false },
|
|
21
21
|
availableModels: { type: Array, required: false },
|
|
22
22
|
defaultModel: { type: String, required: false },
|
|
23
|
+
executionControls: { type: Object, required: false },
|
|
23
24
|
defaultReasoningEffort: { type: null, required: false },
|
|
24
25
|
conversationCreatorFilter: { type: null, required: false },
|
|
25
26
|
hideConversationCreatorFilter: { type: Boolean, required: false },
|
|
@@ -86,6 +87,7 @@ provideEmbedConfig({
|
|
|
86
87
|
conversationScope: normalizedConversationScope,
|
|
87
88
|
defaultConversationCreatorFilter: computed(() => props.defaultConversationCreatorFilter),
|
|
88
89
|
availableModels: computed(() => props.availableModels),
|
|
90
|
+
executionControls: computed(() => props.executionControls),
|
|
89
91
|
defaultModel: computed(() => props.defaultModel),
|
|
90
92
|
defaultReasoningEffort: computed(() => props.defaultReasoningEffort),
|
|
91
93
|
conversationCreatorFilter: computed(() => props.conversationCreatorFilter),
|
|
@@ -12,6 +12,7 @@ const { hideSidebar = void 0, syncBrowserState = true, closeOnOutsideClick = tru
|
|
|
12
12
|
defaultConversationCreatorFilter: { type: null, required: false },
|
|
13
13
|
availableModels: { type: Array, required: false },
|
|
14
14
|
defaultModel: { type: String, required: false },
|
|
15
|
+
executionControls: { type: Object, required: false },
|
|
15
16
|
defaultReasoningEffort: { type: null, required: false },
|
|
16
17
|
conversationCreatorFilter: { type: null, required: false },
|
|
17
18
|
hideConversationCreatorFilter: { type: Boolean, required: false },
|
|
@@ -78,6 +79,7 @@ const sharedEmbedProps = computed(() => ({
|
|
|
78
79
|
conversationScope: props.conversationScope,
|
|
79
80
|
defaultConversationCreatorFilter: props.defaultConversationCreatorFilter,
|
|
80
81
|
availableModels: props.availableModels,
|
|
82
|
+
executionControls: props.executionControls,
|
|
81
83
|
defaultModel: props.defaultModel,
|
|
82
84
|
defaultReasoningEffort: props.defaultReasoningEffort,
|
|
83
85
|
conversationCreatorFilter: props.conversationCreatorFilter,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ChatExecutionProfile } from '../../execution-controls.js';
|
|
1
2
|
import type { DeepReadonly } from 'vue';
|
|
2
3
|
import type { Conversation, ConversationWithMessages, Message } from '../../../types/schemas/chat/conversations.js';
|
|
3
4
|
import type { ConversationFile } from '../../../types/schemas/chat/files.js';
|
|
@@ -35,6 +36,7 @@ type __VLS_Props = {
|
|
|
35
36
|
showCancelButton?: boolean;
|
|
36
37
|
hideModelSelector?: boolean;
|
|
37
38
|
hideReasoningEffortSelector?: boolean;
|
|
39
|
+
executionControlsDisabled?: boolean;
|
|
38
40
|
showDebugOption?: boolean;
|
|
39
41
|
showOutdatedBadge?: boolean;
|
|
40
42
|
showOutdatedBanner?: boolean;
|
|
@@ -49,13 +51,13 @@ type __VLS_ModelProps = {
|
|
|
49
51
|
'selectedReasoningEffort'?: ChatReasoningEffort | null;
|
|
50
52
|
};
|
|
51
53
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
52
|
-
declare var __VLS_54: {},
|
|
54
|
+
declare var __VLS_54: {}, __VLS_100: {}, __VLS_102: {};
|
|
53
55
|
type __VLS_Slots = {} & {
|
|
54
56
|
loading?: (props: typeof __VLS_54) => any;
|
|
55
57
|
} & {
|
|
56
|
-
empty?: (props: typeof
|
|
58
|
+
empty?: (props: typeof __VLS_100) => any;
|
|
57
59
|
} & {
|
|
58
|
-
default?: (props: typeof
|
|
60
|
+
default?: (props: typeof __VLS_102) => any;
|
|
59
61
|
};
|
|
60
62
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
61
63
|
"update:selectedModel": (value: string | null) => any;
|
|
@@ -71,6 +73,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
71
73
|
selectConversation: (id: string) => any;
|
|
72
74
|
settings: () => any;
|
|
73
75
|
send: (content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any;
|
|
76
|
+
selectExecutionProfile: (profile: ChatExecutionProfile) => any;
|
|
74
77
|
tabChange: (tab: TopbarTab) => any;
|
|
75
78
|
newConversation: (groupId?: string | null | undefined) => any;
|
|
76
79
|
switchWorkspace: () => any;
|
|
@@ -92,6 +95,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
92
95
|
onSelectConversation?: ((id: string) => any) | undefined;
|
|
93
96
|
onSettings?: (() => any) | undefined;
|
|
94
97
|
onSend?: ((content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any) | undefined;
|
|
98
|
+
onSelectExecutionProfile?: ((profile: ChatExecutionProfile) => any) | undefined;
|
|
95
99
|
"onUpdate:selectedModel"?: ((value: string | null) => any) | undefined;
|
|
96
100
|
"onUpdate:selectedReasoningEffort"?: ((value: any) => any) | undefined;
|
|
97
101
|
onTabChange?: ((tab: TopbarTab) => any) | undefined;
|