@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 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 sends model and effort in
209
- one update; a failed update restores both values. Sending waits for that update.
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "4.8.0-rc.0",
4
+ "version": "4.8.0-rc.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -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 resolvedValue = resolveSelectedModel(value);
318
- pendingModelSelection.value = resolvedValue;
319
- const conversation = currentConversation.value;
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
- const conversation = currentConversation.value;
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
- if (modelUpdateInFlight.value || reasoningEffortUpdateInFlight.value)
335
- return;
336
- const conversation = currentConversation.value;
337
- if (!conversation) {
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
- model: selectedModel.value,
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, selectedModel.value);
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, selectedModel.value);
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, selectedModel.value);
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 forkEvents = shallowRef([]);
729
+ const persistedConversationEvents = shallowRef([]);
822
730
  const displayConversationEvents = computed(() => [...new Map([
823
- ...forkEvents.value,
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
- ], async ([conversationId], _previous, onCleanup) => {
830
- forkEvents.value = [];
831
- if (!conversationId || !chatApi.conversationV2Enabled)
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
- const controller = new AbortController();
834
- onCleanup(() => controller.abort());
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({ signal: controller.signal })
751
+ chatApi.withChatHeaders()
839
752
  );
840
- if (!controller.signal.aborted)
841
- forkEvents.value = events.filter((event) => event.type === "conversation_forked");
753
+ if (current)
754
+ persistedConversationEvents.value = events;
842
755
  } catch {
843
- if (!controller.signal.aborted)
844
- statusToast.update({ text: "Erro ao carregar a origem da conversa", icon: "i-ph-warning" });
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<void>) => Promise<boolean>;
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<void>) => Promise<boolean>;
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(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
- "version": "4.8.0-rc.0",
3
+ "version": "4.8.0-rc.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {