@meistrari/chat-nuxt 4.8.0-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 +4 -2
- package/dist/module.json +1 -1
- package/dist/runtime/embed/components/chat-embed-inner.vue +48 -135
- package/dist/runtime/lightweight/messages/composables/chat.d.ts +4 -1
- package/dist/runtime/messages/composables/chat.d.ts +5 -2
- package/dist/runtime/messages/composables/chat.js +10 -2
- package/dist/runtime/messages/composables/outbound-queue.d.ts +2 -0
- package/dist/runtime/messages/conversation-timeline.js +10 -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
|
@@ -205,8 +205,10 @@ it takes precedence over both legacy flags as a whole.
|
|
|
205
205
|
|
|
206
206
|
Supply model IDs available to the configured agent and effort levels supported
|
|
207
207
|
by those models. Both profiles may use the same model. An explicit `null` effort
|
|
208
|
-
uses the agent's configured effort. Profile selection
|
|
209
|
-
|
|
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.
|
|
210
212
|
|
|
211
213
|
In `simple` mode, new conversations start with the `default` profile, regardless
|
|
212
214
|
of `defaultModel` and `defaultReasoningEffort`. A selection stays within the current
|
package/dist/module.json
CHANGED
|
@@ -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,9 +91,6 @@ const {
|
|
|
95
91
|
createConversation,
|
|
96
92
|
deleteConversation,
|
|
97
93
|
renameConversation,
|
|
98
|
-
updateConversationModel,
|
|
99
|
-
updateConversationReasoningEffort,
|
|
100
|
-
updateConversationExecutionProfile,
|
|
101
94
|
duplicateConversation,
|
|
102
95
|
forkConversation,
|
|
103
96
|
moveConversationToGroup,
|
|
@@ -227,10 +220,7 @@ const {
|
|
|
227
220
|
loadConversation,
|
|
228
221
|
setConversation,
|
|
229
222
|
adoptConversation,
|
|
230
|
-
setConversationModel,
|
|
231
223
|
pendingModelSelection,
|
|
232
|
-
setConversationReasoningEffort,
|
|
233
|
-
setConversationExecutionProfile,
|
|
234
224
|
pendingReasoningEffortSelection,
|
|
235
225
|
sendMessage,
|
|
236
226
|
flushOutboundQueue,
|
|
@@ -247,114 +237,42 @@ const {
|
|
|
247
237
|
onQueuedSendFailed: restoreQueuedSend
|
|
248
238
|
});
|
|
249
239
|
const agentWake = harnessAdapter?.requiresSandboxWake === false ? null : useAgentWake();
|
|
250
|
-
const modelUpdateInFlight = ref(null);
|
|
251
|
-
const reasoningEffortUpdateInFlight = ref(null);
|
|
252
|
-
const REASONING_EFFORT_UPDATE_FAILED_MESSAGE = "N\xE3o foi poss\xEDvel atualizar o esfor\xE7o de racioc\xEDnio da conversa";
|
|
253
240
|
watch(chatError, (message) => {
|
|
254
241
|
if (message)
|
|
255
242
|
statusToast.update({ text: message, icon: "i-ph-warning" });
|
|
256
243
|
});
|
|
257
244
|
const { total, files: conversationFiles, loading: conversationFilesLoading } = useConversationFiles(activeConversationId);
|
|
258
|
-
function persistConversationModel(conversation, value, wakeAgent) {
|
|
259
|
-
const previousModel = conversation.model;
|
|
260
|
-
setConversationModel(value);
|
|
261
|
-
const update = updateConversationModel(conversation.id, value).then(async (updated) => {
|
|
262
|
-
if (!updated && currentConversation.value?.id === conversation.id && currentConversation.value.model === value) {
|
|
263
|
-
setConversationModel(previousModel);
|
|
264
|
-
} else if (agentWake && updated && value && wakeAgent && !chatApi.conversationV2Enabled) {
|
|
265
|
-
if (conversation.threadSessionId)
|
|
266
|
-
await agentWake.ensureReady(conversation.threadSessionId, value);
|
|
267
|
-
else
|
|
268
|
-
await agentWake.wake(void 0, value);
|
|
269
|
-
}
|
|
270
|
-
return updated;
|
|
271
|
-
});
|
|
272
|
-
const trackedUpdate = update.finally(() => {
|
|
273
|
-
if (modelUpdateInFlight.value === trackedUpdate)
|
|
274
|
-
modelUpdateInFlight.value = null;
|
|
275
|
-
});
|
|
276
|
-
modelUpdateInFlight.value = trackedUpdate;
|
|
277
|
-
return trackedUpdate;
|
|
278
|
-
}
|
|
279
|
-
async function waitForPendingModelUpdate() {
|
|
280
|
-
while (modelUpdateInFlight.value) {
|
|
281
|
-
const update = modelUpdateInFlight.value;
|
|
282
|
-
if (!await update)
|
|
283
|
-
throw new Error(MODEL_UPDATE_FAILED_MESSAGE);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
function persistConversationReasoningEffort(conversation, value) {
|
|
287
|
-
const previousEffort = conversation.reasoningEffort ?? null;
|
|
288
|
-
setConversationReasoningEffort(value);
|
|
289
|
-
const update = updateConversationReasoningEffort(conversation.id, value).then((updated) => {
|
|
290
|
-
if (!updated && currentConversation.value?.id === conversation.id && (currentConversation.value.reasoningEffort ?? null) === value) {
|
|
291
|
-
setConversationReasoningEffort(previousEffort);
|
|
292
|
-
}
|
|
293
|
-
return updated;
|
|
294
|
-
});
|
|
295
|
-
const trackedUpdate = update.finally(() => {
|
|
296
|
-
if (reasoningEffortUpdateInFlight.value === trackedUpdate)
|
|
297
|
-
reasoningEffortUpdateInFlight.value = null;
|
|
298
|
-
});
|
|
299
|
-
reasoningEffortUpdateInFlight.value = trackedUpdate;
|
|
300
|
-
return trackedUpdate;
|
|
301
|
-
}
|
|
302
|
-
async function waitForPendingReasoningEffortUpdate() {
|
|
303
|
-
while (reasoningEffortUpdateInFlight.value) {
|
|
304
|
-
const update = reasoningEffortUpdateInFlight.value;
|
|
305
|
-
if (!await update)
|
|
306
|
-
throw new Error(REASONING_EFFORT_UPDATE_FAILED_MESSAGE);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
245
|
function resolveSelectedModel(value) {
|
|
310
246
|
return nativeModels ? nativeModels.resolve(value) : value;
|
|
311
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" });
|
|
312
254
|
const selectedModel = computed({
|
|
313
|
-
get: () => resolveSelectedModel(
|
|
314
|
-
currentConversation.value ? currentConversation.value.model : pendingModelSelection.value
|
|
315
|
-
),
|
|
255
|
+
get: () => resolveSelectedModel(draftModel.value !== void 0 ? draftModel.value : currentConversation.value ? currentConversation.value.model : pendingModelSelection.value),
|
|
316
256
|
set: (value) => {
|
|
317
|
-
const
|
|
318
|
-
pendingModelSelection.value =
|
|
319
|
-
|
|
320
|
-
if (conversation && conversation.model !== resolvedValue)
|
|
321
|
-
void persistConversationModel(conversation, resolvedValue, true);
|
|
257
|
+
const resolved = resolveSelectedModel(value);
|
|
258
|
+
pendingModelSelection.value = resolved;
|
|
259
|
+
draftModel.value = resolved;
|
|
322
260
|
}
|
|
323
261
|
});
|
|
324
262
|
const selectedReasoningEffort = computed({
|
|
325
|
-
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,
|
|
326
264
|
set: (value) => {
|
|
327
265
|
pendingReasoningEffortSelection.value = value;
|
|
328
|
-
|
|
329
|
-
if (conversation && (conversation.reasoningEffort ?? null) !== value)
|
|
330
|
-
void persistConversationReasoningEffort(conversation, value);
|
|
266
|
+
draftReasoningEffort.value = value;
|
|
331
267
|
}
|
|
332
268
|
});
|
|
333
269
|
function selectExecutionProfile(profile) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
pendingModelSelection.value = profile.model;
|
|
270
|
+
draftModel.value = resolveSelectedModel(profile.model);
|
|
271
|
+
draftReasoningEffort.value = profile.reasoningEffort;
|
|
272
|
+
if (!currentConversation.value) {
|
|
273
|
+
pendingModelSelection.value = draftModel.value;
|
|
339
274
|
pendingReasoningEffortSelection.value = profile.reasoningEffort;
|
|
340
|
-
return;
|
|
341
275
|
}
|
|
342
|
-
const previous = { model: conversation.model, reasoningEffort: conversation.reasoningEffort ?? null };
|
|
343
|
-
setConversationExecutionProfile(profile);
|
|
344
|
-
const update = updateConversationExecutionProfile(conversation.id, profile).then((updated) => {
|
|
345
|
-
if (!updated) {
|
|
346
|
-
if (currentConversation.value?.id === conversation.id && currentConversation.value.model === profile.model && (currentConversation.value.reasoningEffort ?? null) === profile.reasoningEffort) {
|
|
347
|
-
setConversationExecutionProfile(previous);
|
|
348
|
-
}
|
|
349
|
-
statusToast.update({ text: "N\xE3o foi poss\xEDvel atualizar o modo de resposta da conversa", icon: "i-ph-warning" });
|
|
350
|
-
}
|
|
351
|
-
return updated;
|
|
352
|
-
});
|
|
353
|
-
const trackedUpdate = update.finally(() => {
|
|
354
|
-
if (modelUpdateInFlight.value === trackedUpdate)
|
|
355
|
-
modelUpdateInFlight.value = null;
|
|
356
|
-
});
|
|
357
|
-
modelUpdateInFlight.value = trackedUpdate;
|
|
358
276
|
}
|
|
359
277
|
const filesCount = computed(() => total.value);
|
|
360
278
|
const showDetailsPanel = computed(() => !!currentConversation.value && !isMobile.value && !props.compact);
|
|
@@ -441,6 +359,8 @@ async function ensureConversationLoaded(conversationId) {
|
|
|
441
359
|
}
|
|
442
360
|
}
|
|
443
361
|
function resetConversation(shouldEmit = true) {
|
|
362
|
+
draftModel.value = void 0;
|
|
363
|
+
draftReasoningEffort.value = void 0;
|
|
444
364
|
clearConversation();
|
|
445
365
|
agentWake?.consume();
|
|
446
366
|
if (agentWake && !chatApi.conversationV2Enabled)
|
|
@@ -622,14 +542,14 @@ async function handleSend(content, files, agentInputs) {
|
|
|
622
542
|
restoreQueuedSend({ content: prepared?.retryContent?.() ?? content, files, agentInputs: resolvedAgentInputs });
|
|
623
543
|
}
|
|
624
544
|
async function dispatchMessage(outbound, files, resolvedAgentInputs) {
|
|
545
|
+
const executionSettings = { model: selectedModel.value, reasoningEffort: selectedReasoningEffort.value };
|
|
625
546
|
if (props.sendBlocked)
|
|
626
547
|
return false;
|
|
627
548
|
let claimedWakeSessionId;
|
|
628
549
|
const sent = await sendMessage(outbound, files.length > 0 ? files : void 0, resolvedAgentInputs, async (signal) => {
|
|
629
550
|
if (!activeConversationId.value || !currentConversation.value) {
|
|
630
551
|
const conversation2 = await createConversation({
|
|
631
|
-
|
|
632
|
-
reasoningEffort: selectedReasoningEffort.value,
|
|
552
|
+
...executionSettings,
|
|
633
553
|
...resolvedAgentInputs !== void 0 ? { agentInputs: resolvedAgentInputs } : {}
|
|
634
554
|
});
|
|
635
555
|
if (!conversation2)
|
|
@@ -640,36 +560,29 @@ async function dispatchMessage(outbound, files, resolvedAgentInputs) {
|
|
|
640
560
|
adoptConversation(grouped ? { ...conversation2, groupId } : conversation2);
|
|
641
561
|
updateConversationId(conversation2.id);
|
|
642
562
|
}
|
|
643
|
-
await waitForPendingModelUpdate();
|
|
644
|
-
await waitForPendingReasoningEffortUpdate();
|
|
645
563
|
const conversation = currentConversation.value;
|
|
646
564
|
if (!conversation)
|
|
647
565
|
throw new Error("Erro ao preparar conversa");
|
|
648
|
-
await (nativeModels?.ensureSelectedModel ?? ensureConversationUsesSelectedModel)(
|
|
649
|
-
conversation.model,
|
|
650
|
-
selectedModel.value,
|
|
651
|
-
(value) => persistConversationModel(conversation, value, false)
|
|
652
|
-
);
|
|
653
566
|
if (!agentWake || chatApi.conversationV2Enabled)
|
|
654
|
-
return {};
|
|
567
|
+
return { executionSettings };
|
|
655
568
|
if (conversation.threadSessionId && resolvedFeatures.value.chatOutboundQueue) {
|
|
656
|
-
const wake = await agentWake.ensureReady(conversation.threadSessionId,
|
|
569
|
+
const wake = await agentWake.ensureReady(conversation.threadSessionId, executionSettings.model);
|
|
657
570
|
if (wake.status !== "ready") {
|
|
658
571
|
if (wake.wokenSandbox && !wake.wokenSandbox.rewakeable)
|
|
659
|
-
return { defer: true };
|
|
572
|
+
return { defer: true, executionSettings };
|
|
660
573
|
throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
|
|
661
574
|
}
|
|
662
|
-
return {};
|
|
575
|
+
return { executionSettings };
|
|
663
576
|
}
|
|
664
577
|
if (!conversation.threadSessionId) {
|
|
665
578
|
await agentWake.waitUntilSettled(signal);
|
|
666
579
|
if (agentWake.state.value === "idle")
|
|
667
|
-
await agentWake.wake(void 0,
|
|
580
|
+
await agentWake.wake(void 0, executionSettings.model);
|
|
668
581
|
}
|
|
669
582
|
claimedWakeSessionId = claimableWakeSessionId();
|
|
670
583
|
if (!conversation.threadSessionId && !claimedWakeSessionId)
|
|
671
584
|
throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
|
|
672
|
-
return claimedWakeSessionId ? { wakeSessionId: claimedWakeSessionId } : {};
|
|
585
|
+
return { executionSettings, ...claimedWakeSessionId ? { wakeSessionId: claimedWakeSessionId } : {} };
|
|
673
586
|
});
|
|
674
587
|
if (sent && claimedWakeSessionId)
|
|
675
588
|
agentWake?.consume();
|
|
@@ -712,26 +625,21 @@ async function handleCancel() {
|
|
|
712
625
|
await cancelConversation();
|
|
713
626
|
}
|
|
714
627
|
async function handleRetry(messageId) {
|
|
628
|
+
const executionSettings = { model: selectedModel.value, reasoningEffort: selectedReasoningEffort.value };
|
|
715
629
|
await retryMessage(messageId, async () => {
|
|
716
|
-
await waitForPendingModelUpdate();
|
|
717
|
-
await waitForPendingReasoningEffortUpdate();
|
|
718
630
|
const conversation = currentConversation.value;
|
|
719
631
|
if (!conversation)
|
|
720
632
|
throw new Error("Erro ao preparar conversa");
|
|
721
|
-
await (nativeModels?.ensureSelectedModel ?? ensureConversationUsesSelectedModel)(
|
|
722
|
-
conversation.model,
|
|
723
|
-
selectedModel.value,
|
|
724
|
-
(value) => persistConversationModel(conversation, value, false)
|
|
725
|
-
);
|
|
726
633
|
if (!agentWake || chatApi.conversationV2Enabled)
|
|
727
|
-
return;
|
|
634
|
+
return { executionSettings };
|
|
728
635
|
if (conversation.threadSessionId) {
|
|
729
|
-
const wake = await agentWake.ensureReady(conversation.threadSessionId,
|
|
636
|
+
const wake = await agentWake.ensureReady(conversation.threadSessionId, executionSettings.model);
|
|
730
637
|
if (wake.status !== "ready")
|
|
731
638
|
throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
|
|
732
639
|
} else {
|
|
733
640
|
agentWake.consume();
|
|
734
641
|
}
|
|
642
|
+
return { executionSettings };
|
|
735
643
|
});
|
|
736
644
|
}
|
|
737
645
|
async function handleNewConversation(groupId) {
|
|
@@ -818,30 +726,35 @@ function handleShare(conversationId) {
|
|
|
818
726
|
if (id)
|
|
819
727
|
void copyConversationLink(id);
|
|
820
728
|
}
|
|
821
|
-
const
|
|
729
|
+
const persistedConversationEvents = shallowRef([]);
|
|
822
730
|
const displayConversationEvents = computed(() => [...new Map([
|
|
823
|
-
...
|
|
731
|
+
...persistedConversationEvents.value,
|
|
824
732
|
...props.conversationEvents ?? []
|
|
825
733
|
].filter((event) => event.conversationId === currentConversation.value?.id).map((event) => [event.id, event])).values()]);
|
|
826
734
|
watch([
|
|
827
735
|
() => currentConversation.value?.id,
|
|
828
|
-
() => JSON.stringify(chatApi.withChatHeaders().headers)
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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)
|
|
832
743
|
return;
|
|
833
|
-
|
|
834
|
-
onCleanup(() =>
|
|
744
|
+
let current = true;
|
|
745
|
+
onCleanup(() => {
|
|
746
|
+
current = false;
|
|
747
|
+
});
|
|
835
748
|
try {
|
|
836
749
|
const { events } = await $fetch(
|
|
837
750
|
chatApi.path(`/conversations/${conversationId}/events`),
|
|
838
|
-
chatApi.withChatHeaders(
|
|
751
|
+
chatApi.withChatHeaders()
|
|
839
752
|
);
|
|
840
|
-
if (
|
|
841
|
-
|
|
753
|
+
if (current)
|
|
754
|
+
persistedConversationEvents.value = events;
|
|
842
755
|
} catch {
|
|
843
|
-
if (
|
|
844
|
-
statusToast.update({ text: "Erro ao carregar
|
|
756
|
+
if (current)
|
|
757
|
+
statusToast.update({ text: "Erro ao carregar os eventos da conversa", icon: "i-ph-warning" });
|
|
845
758
|
}
|
|
846
759
|
}, { immediate: true });
|
|
847
760
|
const forking = ref(false);
|
|
@@ -33,10 +33,13 @@ export declare function useChat(options?: Parameters<typeof useSharedChat>[0]):
|
|
|
33
33
|
sendMessage: (content: string, files?: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[], prepare?: (signal: AbortSignal) => Promise<{
|
|
34
34
|
wakeSessionId?: string;
|
|
35
35
|
defer?: boolean;
|
|
36
|
+
executionSettings?: ExecutionSettings;
|
|
36
37
|
}>, queuedSend?: import("../../../messages/composables/outbound-queue.js").QueuedSend) => Promise<Message | null>;
|
|
37
38
|
flushOutboundQueue: (wakeSessionId?: string) => Promise<Message | null>;
|
|
38
39
|
failOutboundQueue: (message: string) => boolean;
|
|
39
|
-
retryMessage: (messageId: string, prepare?: () => Promise<
|
|
40
|
+
retryMessage: (messageId: string, prepare?: () => Promise<{
|
|
41
|
+
executionSettings?: ExecutionSettings;
|
|
42
|
+
} | void>) => Promise<boolean>;
|
|
40
43
|
cancelConversation: () => Promise<boolean>;
|
|
41
44
|
startPolling: () => void;
|
|
42
45
|
reconnect: () => void;
|
|
@@ -4,7 +4,7 @@ import { type DeepReadonly, type MaybeRefOrGetter, type Ref } from 'vue';
|
|
|
4
4
|
import type { Conversation, ConversationWithMessages, Message } from '../../types/schemas/chat/conversations.js';
|
|
5
5
|
import { type ChatReasoningEffort } from '../../types/schemas/chat/models.js';
|
|
6
6
|
import type { FileUploadInput, MessageFile } from '../../types/schemas/chat/files.js';
|
|
7
|
-
import type { SendMessageBody } from '../../types/schemas/chat/messages.js';
|
|
7
|
+
import type { ExecutionSettings, SendMessageBody } from '../../types/schemas/chat/messages.js';
|
|
8
8
|
import type { TelaAgentExecutionInput } from '../../types/schemas/integrations/tela-agent-api.js';
|
|
9
9
|
import { useDirectStream } from './use-direct-stream.js';
|
|
10
10
|
import { type QueuedSend } from './outbound-queue.js';
|
|
@@ -56,10 +56,13 @@ export declare function useChat(options?: {
|
|
|
56
56
|
sendMessage: (content: string, files?: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[], prepare?: (signal: AbortSignal) => Promise<{
|
|
57
57
|
wakeSessionId?: string;
|
|
58
58
|
defer?: boolean;
|
|
59
|
+
executionSettings?: ExecutionSettings;
|
|
59
60
|
}>, queuedSend?: QueuedSend) => Promise<Message | null>;
|
|
60
61
|
flushOutboundQueue: (wakeSessionId?: string) => Promise<Message | null>;
|
|
61
62
|
failOutboundQueue: (message: string) => boolean;
|
|
62
|
-
retryMessage: (messageId: string, prepare?: () => Promise<
|
|
63
|
+
retryMessage: (messageId: string, prepare?: () => Promise<{
|
|
64
|
+
executionSettings?: ExecutionSettings;
|
|
65
|
+
} | void>) => Promise<boolean>;
|
|
63
66
|
cancelConversation: () => Promise<boolean>;
|
|
64
67
|
startPolling: () => void;
|
|
65
68
|
reconnect: () => void;
|
|
@@ -565,6 +565,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
565
565
|
messages.value = [...messages.value, optimisticUserMessage, optimisticAssistantMessage];
|
|
566
566
|
const controller = new AbortController();
|
|
567
567
|
gateController = controller;
|
|
568
|
+
let executionSettings = queuedSend?.executionSettings;
|
|
568
569
|
let v2AdmissionRequested = false;
|
|
569
570
|
try {
|
|
570
571
|
let wakeSessionId = queuedSend?.wakeSessionId;
|
|
@@ -573,6 +574,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
573
574
|
gateHolding.value = true;
|
|
574
575
|
try {
|
|
575
576
|
const prepared = await prepare(controller.signal);
|
|
577
|
+
executionSettings = prepared.executionSettings;
|
|
576
578
|
wakeSessionId = prepared.wakeSessionId;
|
|
577
579
|
defer = prepared.defer === true;
|
|
578
580
|
} finally {
|
|
@@ -589,6 +591,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
589
591
|
content,
|
|
590
592
|
files,
|
|
591
593
|
agentInputs,
|
|
594
|
+
executionSettings,
|
|
592
595
|
wakeSessionId,
|
|
593
596
|
optimisticIds: { user: optimisticUserMessage.id, assistant: optimisticAssistantMessage.id },
|
|
594
597
|
queuedAt: Date.now(),
|
|
@@ -601,6 +604,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
601
604
|
const resolvedAgentInputs = resolveTelaAgentInputs(agentInputs, embedConfig?.telaAgentInputs?.value);
|
|
602
605
|
const body = {
|
|
603
606
|
content,
|
|
607
|
+
...executionSettings ? { executionSettings } : {},
|
|
604
608
|
files,
|
|
605
609
|
...resolvedAgentInputs !== void 0 ? { agentInputs: resolvedAgentInputs } : {},
|
|
606
610
|
...wakeSessionId ? { wakeSessionId } : {},
|
|
@@ -630,6 +634,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
630
634
|
let response;
|
|
631
635
|
if (chatApi.conversationV2Enabled) {
|
|
632
636
|
const v2Body = {
|
|
637
|
+
...executionSettings ? { executionSettings } : {},
|
|
633
638
|
messageId: optimisticUserMessage.id,
|
|
634
639
|
content,
|
|
635
640
|
files,
|
|
@@ -696,6 +701,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
696
701
|
content,
|
|
697
702
|
files,
|
|
698
703
|
agentInputs,
|
|
704
|
+
executionSettings,
|
|
699
705
|
wakeSessionId: void 0,
|
|
700
706
|
optimisticIds: { user: optimisticUserMessage.id, assistant: optimisticAssistantMessage.id },
|
|
701
707
|
queuedAt,
|
|
@@ -719,6 +725,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
719
725
|
content,
|
|
720
726
|
files,
|
|
721
727
|
agentInputs,
|
|
728
|
+
executionSettings,
|
|
722
729
|
wakeSessionId: queuedSend?.wakeSessionId,
|
|
723
730
|
optimisticIds: { user: optimisticUserMessage.id, assistant: optimisticAssistantMessage.id },
|
|
724
731
|
queuedAt: queuedSend?.queuedAt ?? Date.now(),
|
|
@@ -917,8 +924,9 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
917
924
|
error.value = null;
|
|
918
925
|
let retry = null;
|
|
919
926
|
try {
|
|
927
|
+
let prepared;
|
|
920
928
|
if (prepare)
|
|
921
|
-
await prepare();
|
|
929
|
+
prepared = await prepare();
|
|
922
930
|
if (currentConversation.value?.id !== conversationId)
|
|
923
931
|
return false;
|
|
924
932
|
retry = beginAssistantMessageRetry(messages.value, messageId);
|
|
@@ -929,7 +937,7 @@ export function useChat(options = {}, adapter = {}) {
|
|
|
929
937
|
directStream.beginMessage();
|
|
930
938
|
const retriedMessage = await $fetch(
|
|
931
939
|
chatApi.path(`/conversations/${conversationId}/messages/${messageId}/retry`),
|
|
932
|
-
chatApi.withChatHeaders({ method: "POST" })
|
|
940
|
+
chatApi.withChatHeaders({ method: "POST", ...prepared?.executionSettings ? { body: { executionSettings: prepared.executionSettings } } : {} })
|
|
933
941
|
);
|
|
934
942
|
if (currentConversation.value?.id !== conversationId)
|
|
935
943
|
return true;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { ExecutionSettings } from '../../types/schemas/chat/messages.js';
|
|
1
2
|
import type { FileUploadInput } from '../../types/schemas/chat/files.js';
|
|
2
3
|
import type { TelaAgentExecutionInput } from '../../types/schemas/integrations/tela-agent-api.js';
|
|
3
4
|
import type { ComputedRef } from 'vue';
|
|
4
5
|
export interface QueuedSend {
|
|
6
|
+
executionSettings?: ExecutionSettings;
|
|
5
7
|
content: string;
|
|
6
8
|
files: FileUploadInput[] | undefined;
|
|
7
9
|
agentInputs: TelaAgentExecutionInput[] | undefined;
|
|
@@ -22,6 +22,16 @@ export function mergeConversationTimeline(messages, events = []) {
|
|
|
22
22
|
return left.kind === "event" ? -1 : 1;
|
|
23
23
|
return left.id.localeCompare(right.id);
|
|
24
24
|
});
|
|
25
|
+
for (const item of [...items]) {
|
|
26
|
+
if (item.kind !== "event" || !["model_changed", "reasoning_effort_changed"].includes(item.value.type))
|
|
27
|
+
continue;
|
|
28
|
+
const messageIndex = items.findIndex((candidate) => candidate.kind === "message" && candidate.id === item.value.payload.messageId && candidate.value.conversationId === item.value.conversationId);
|
|
29
|
+
if (messageIndex === -1)
|
|
30
|
+
continue;
|
|
31
|
+
items.splice(items.indexOf(item), 1);
|
|
32
|
+
const targetIndex = items.findIndex((candidate) => candidate.kind === "message" && candidate.id === item.value.payload.messageId);
|
|
33
|
+
items.splice(targetIndex, 0, item);
|
|
34
|
+
}
|
|
25
35
|
for (const event of events ?? []) {
|
|
26
36
|
const source = getConversationForkSource(event);
|
|
27
37
|
if (!source)
|
|
@@ -82,6 +82,16 @@ export declare const sendMessageV2BodySchema: z.ZodObject<{
|
|
|
82
82
|
sinceSendMs: z.ZodNumber;
|
|
83
83
|
standInOutputAtMs: z.ZodOptional<z.ZodNumber>;
|
|
84
84
|
}, z.core.$strict>>;
|
|
85
|
+
executionSettings: z.ZodOptional<z.ZodObject<{
|
|
86
|
+
model: z.ZodNullable<z.ZodString>;
|
|
87
|
+
reasoningEffort: z.ZodNullable<z.ZodEnum<{
|
|
88
|
+
low: "low";
|
|
89
|
+
medium: "medium";
|
|
90
|
+
high: "high";
|
|
91
|
+
xhigh: "xhigh";
|
|
92
|
+
max: "max";
|
|
93
|
+
}>>;
|
|
94
|
+
}, z.core.$strict>>;
|
|
85
95
|
}, z.core.$strict>;
|
|
86
96
|
export type SendMessageV2Body = z.infer<typeof sendMessageV2BodySchema>;
|
|
87
97
|
export declare const sendMessageV2ResponseSchema: z.ZodObject<{
|
|
@@ -2,7 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { telaAgentExecutionInputSchema } from '../integrations/tela-agent-api';
|
|
3
3
|
import { messageSchema } from './conversations';
|
|
4
4
|
import { fileUploadInputSchema } from './files';
|
|
5
|
-
import { sendMessageClientTimingSchema } from './messages';
|
|
5
|
+
import { executionSettingsSchema, sendMessageClientTimingSchema } from './messages';
|
|
6
6
|
export const conversationRuntimeStateSchema = z.enum(['blocked', 'waiting_messages']);
|
|
7
7
|
export const turnRuntimeStateNameSchema = z.enum([
|
|
8
8
|
'accepted',
|
|
@@ -33,6 +33,7 @@ export const sendMessageV2BodySchema = z.strictObject({
|
|
|
33
33
|
files: z.array(fileUploadInputSchema).optional(),
|
|
34
34
|
agentInputs: z.array(telaAgentExecutionInputSchema).optional(),
|
|
35
35
|
clientTiming: sendMessageClientTimingSchema.optional(),
|
|
36
|
+
executionSettings: executionSettingsSchema.optional(),
|
|
36
37
|
});
|
|
37
38
|
export const sendMessageV2ResponseSchema = z.object({
|
|
38
39
|
userMessage: messageSchema,
|
|
@@ -317,6 +317,25 @@ export declare const agentInputsChangedConversationEventSchema: z.ZodObject<{
|
|
|
317
317
|
}, z.core.$strict>;
|
|
318
318
|
}, z.core.$strip>;
|
|
319
319
|
export type AgentInputsChangedConversationEvent = z.infer<typeof agentInputsChangedConversationEventSchema>;
|
|
320
|
+
export declare const executionSettingsChangedPayloadSchema: z.ZodObject<{
|
|
321
|
+
messageId: z.ZodString;
|
|
322
|
+
previousModel: z.ZodNullable<z.ZodString>;
|
|
323
|
+
model: z.ZodNullable<z.ZodString>;
|
|
324
|
+
previousReasoningEffort: z.ZodNullable<z.ZodEnum<{
|
|
325
|
+
low: "low";
|
|
326
|
+
medium: "medium";
|
|
327
|
+
high: "high";
|
|
328
|
+
xhigh: "xhigh";
|
|
329
|
+
max: "max";
|
|
330
|
+
}>>;
|
|
331
|
+
reasoningEffort: z.ZodNullable<z.ZodEnum<{
|
|
332
|
+
low: "low";
|
|
333
|
+
medium: "medium";
|
|
334
|
+
high: "high";
|
|
335
|
+
xhigh: "xhigh";
|
|
336
|
+
max: "max";
|
|
337
|
+
}>>;
|
|
338
|
+
}, z.core.$strip>;
|
|
320
339
|
export declare const conversationEventsResponseSchema: z.ZodObject<{
|
|
321
340
|
events: z.ZodArray<z.ZodObject<{
|
|
322
341
|
id: z.ZodString;
|
|
@@ -86,6 +86,13 @@ export const agentInputsChangedConversationEventSchema = conversationEventSchema
|
|
|
86
86
|
agentInputs: z.array(telaAgentExecutionInputSchema),
|
|
87
87
|
}),
|
|
88
88
|
});
|
|
89
|
+
export const executionSettingsChangedPayloadSchema = z.object({
|
|
90
|
+
messageId: z.string().uuid(),
|
|
91
|
+
previousModel: z.string().nullable(),
|
|
92
|
+
model: z.string().nullable(),
|
|
93
|
+
previousReasoningEffort: chatReasoningEffortSchema.nullable(),
|
|
94
|
+
reasoningEffort: chatReasoningEffortSchema.nullable(),
|
|
95
|
+
});
|
|
89
96
|
export const conversationEventsResponseSchema = z.object({
|
|
90
97
|
events: z.array(conversationEventSchema),
|
|
91
98
|
});
|
|
@@ -50,8 +50,41 @@ export declare const sendMessageClientTimingSchema: z.ZodObject<{
|
|
|
50
50
|
standInOutputAtMs: z.ZodOptional<z.ZodNumber>;
|
|
51
51
|
}, z.core.$strict>;
|
|
52
52
|
export type SendMessageClientTiming = z.infer<typeof sendMessageClientTimingSchema>;
|
|
53
|
+
export declare const executionSettingsSchema: z.ZodObject<{
|
|
54
|
+
model: z.ZodNullable<z.ZodString>;
|
|
55
|
+
reasoningEffort: z.ZodNullable<z.ZodEnum<{
|
|
56
|
+
low: "low";
|
|
57
|
+
medium: "medium";
|
|
58
|
+
high: "high";
|
|
59
|
+
xhigh: "xhigh";
|
|
60
|
+
max: "max";
|
|
61
|
+
}>>;
|
|
62
|
+
}, z.core.$strict>;
|
|
63
|
+
export type ExecutionSettings = z.infer<typeof executionSettingsSchema>;
|
|
64
|
+
export declare const retryMessageBodySchema: z.ZodObject<{
|
|
65
|
+
executionSettings: z.ZodOptional<z.ZodObject<{
|
|
66
|
+
model: z.ZodNullable<z.ZodString>;
|
|
67
|
+
reasoningEffort: z.ZodNullable<z.ZodEnum<{
|
|
68
|
+
low: "low";
|
|
69
|
+
medium: "medium";
|
|
70
|
+
high: "high";
|
|
71
|
+
xhigh: "xhigh";
|
|
72
|
+
max: "max";
|
|
73
|
+
}>>;
|
|
74
|
+
}, z.core.$strict>>;
|
|
75
|
+
}, z.core.$strict>;
|
|
53
76
|
export declare const sendMessageBodySchema: z.ZodObject<{
|
|
54
77
|
content: z.ZodString;
|
|
78
|
+
executionSettings: z.ZodOptional<z.ZodObject<{
|
|
79
|
+
model: z.ZodNullable<z.ZodString>;
|
|
80
|
+
reasoningEffort: z.ZodNullable<z.ZodEnum<{
|
|
81
|
+
low: "low";
|
|
82
|
+
medium: "medium";
|
|
83
|
+
high: "high";
|
|
84
|
+
xhigh: "xhigh";
|
|
85
|
+
max: "max";
|
|
86
|
+
}>>;
|
|
87
|
+
}, z.core.$strict>>;
|
|
55
88
|
files: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
56
89
|
url: z.ZodString;
|
|
57
90
|
name: z.ZodString;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { telaAgentExecutionInputSchema, wokenSandboxStatusSchema } from '../integrations/tela-agent-api';
|
|
3
|
+
import { chatModelSchema, chatReasoningEffortSchema } from './models';
|
|
3
4
|
import { messageSchema } from './conversations';
|
|
4
5
|
import { fileUploadInputSchema, messageFileSchema } from './files';
|
|
5
6
|
import { messageRoleSchema, messageStatusSchema } from './primitives';
|
|
@@ -45,8 +46,16 @@ export const sendMessageClientTimingSchema = z.strictObject({
|
|
|
45
46
|
*/
|
|
46
47
|
standInOutputAtMs: z.number().int().min(0).max(600_000).optional(),
|
|
47
48
|
});
|
|
49
|
+
export const executionSettingsSchema = z.strictObject({
|
|
50
|
+
model: chatModelSchema.nullable(),
|
|
51
|
+
reasoningEffort: chatReasoningEffortSchema.nullable(),
|
|
52
|
+
});
|
|
53
|
+
export const retryMessageBodySchema = z.strictObject({
|
|
54
|
+
executionSettings: executionSettingsSchema.optional(),
|
|
55
|
+
});
|
|
48
56
|
export const sendMessageBodySchema = z.strictObject({
|
|
49
57
|
content: z.string(),
|
|
58
|
+
executionSettings: executionSettingsSchema.optional(),
|
|
50
59
|
files: z.array(fileUploadInputSchema).optional(),
|
|
51
60
|
agentInputs: z.array(telaAgentExecutionInputSchema).optional(),
|
|
52
61
|
wakeSessionId: z.string().uuid().optional(),
|