@meistrari/chat-nuxt 3.14.2-rc.1 → 3.15.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +3 -0
  2. package/dist/module.d.mts +1 -1
  3. package/dist/module.json +1 -1
  4. package/dist/runtime/conversations/components/chat-conversation-creator-filter.vue +6 -11
  5. package/dist/runtime/conversations/composables/conversation-creator-filter-state.d.ts +12 -0
  6. package/dist/runtime/conversations/composables/conversation-creator-filter-state.js +31 -0
  7. package/dist/runtime/conversations/composables/conversations.js +50 -26
  8. package/dist/runtime/embed/components/chat-embed-inner.d.vue.ts +2 -0
  9. package/dist/runtime/embed/components/chat-embed-inner.vue +73 -34
  10. package/dist/runtime/embed/components/chat-embed-inner.vue.d.ts +2 -0
  11. package/dist/runtime/embed/components/chat-embed.d.vue.ts +4 -2
  12. package/dist/runtime/embed/components/chat-embed.vue +13 -1
  13. package/dist/runtime/embed/components/chat-embed.vue.d.ts +4 -2
  14. package/dist/runtime/embed/components/meistrari-chat-embed.d.vue.ts +4 -2
  15. package/dist/runtime/embed/components/meistrari-chat-embed.vue +15 -1
  16. package/dist/runtime/embed/components/meistrari-chat-embed.vue.d.ts +4 -2
  17. package/dist/runtime/embed/composables/embed-config.d.ts +7 -0
  18. package/dist/runtime/embed/composables/embed-config.js +12 -0
  19. package/dist/runtime/embed/types.d.ts +12 -0
  20. package/dist/runtime/messages/components/chat-model-selector.vue +23 -12
  21. package/dist/runtime/messages/components/widgets/chat-tool-section.d.vue.ts +1 -1
  22. package/dist/runtime/messages/components/widgets/chat-tool-section.vue.d.ts +1 -1
  23. package/dist/runtime/messages/composables/chat.d.ts +1 -1
  24. package/dist/runtime/messages/composables/chat.js +18 -11
  25. package/dist/runtime/messages/model-availability.d.ts +6 -0
  26. package/dist/runtime/messages/model-availability.js +28 -0
  27. package/dist/runtime/types/embed.d.ts +2 -1
  28. package/dist/runtime/types/schemas/chat/conversations.d.ts +2 -0
  29. package/dist/runtime/types/schemas/chat/models.d.ts +2 -1
  30. package/dist/runtime/types/schemas/chat/models.js +1 -0
  31. package/dist/runtime/types/schemas/chat/ui.d.ts +10 -0
  32. package/dist/runtime/types/schemas/chat/ui.js +1 -0
  33. package/dist/runtime/types/schemas/integrations/tela-agent-api.d.ts +1 -0
  34. package/dist/types.d.mts +1 -1
  35. package/package.json +1 -1
package/README.md CHANGED
@@ -55,6 +55,9 @@ Declared in `src/runtime/embed/types.ts`; prop, feature-flag, and event payload
55
55
  | `initialConversationId` | `string \| null` | `null` | Conversation to open once on mount when `conversationId` is uncontrolled |
56
56
  | `conversationScope` | `string \| null` | `null` | Isolate conversation history by technical scope within the current workspace and runtime. Scoped embeds only see same-scope conversations; values are trimmed, blank becomes `null`, and the server accepts 1-200 chars from `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, `/`, `-` |
57
57
  | `defaultConversationCreatorFilter` | `'all' \| 'mine'` | `'all'` | Initial sidebar creator filter: every conversation in scope, or only the current user's |
58
+ | `availableModels` | `AvailableChatModels` | Full catalog | Non-empty ordered list of models this embed may display and execute. A missing or invalid restored selection falls back to the first entry; an empty list fails fast |
59
+ | `conversationCreatorFilter` | `'all' \| 'mine'` | — | Controlled sidebar creator filter; use with `v-model:conversation-creator-filter` when the host changes it at runtime |
60
+ | `hideConversationCreatorFilter` | `boolean` | `false` | Hide the creator selector without changing the active filter |
58
61
  | `telaAgentId` | `string` | — | Use Tela agent mode for this embed |
59
62
  | `telaAgentInputs` | `TelaAgentExecutionInput[] \| null` | `undefined` | Inputs sent with each Tela agent run; hides the variables panel when non-null |
60
63
  | `workspaceSettings` | `WorkspaceSettings \| null` | `null` | Override settings from host app; not accepted in Tela agent mode |
package/dist/module.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ChatMessageStatus } from '../dist/runtime/messages/composables/chat-message-terminal.js';
2
- export { ChatActionPayload, ChatActor, ChatEmbedSharedProps, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackConfig, MessageFeedbackPayload, MessageFeedbackRating, MessageFeedbackSubmitHandler, MessageFeedbackSubmitResult, MessageOverviewResponse, TelaAgentChatEmbedProps, TelaAgentExecutionInput } from '../dist/runtime/types/embed.js';
2
+ export { AvailableChatModels, ChatActionPayload, ChatActor, ChatEmbedSharedProps, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackConfig, MessageFeedbackPayload, MessageFeedbackRating, MessageFeedbackSubmitHandler, MessageFeedbackSubmitResult, MessageOverviewResponse, TelaAgentChatEmbedProps, TelaAgentExecutionInput } from '../dist/runtime/types/embed.js';
3
3
 
4
4
  type ChatNuxtConfigValidationMode = false | 'warn' | 'error';
5
5
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "3.14.2-rc.1",
4
+ "version": "3.15.0-rc.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -2,28 +2,23 @@
2
2
  import { useConversations } from "../composables/conversations";
3
3
  import { conversationCreatorFilterOptions } from "../../types/schemas/chat/ui.js";
4
4
  import { hasConversationCreatorFilterResults } from "../creator-filter";
5
- const { conversationCreatorFilter, conversationCreatorFilterCounts, fetchConversations } = useConversations();
6
- const isUpdating = ref(false);
5
+ import { useEmbedConfig } from "../../embed/composables/embed-config";
6
+ const embedConfig = useEmbedConfig();
7
+ const { conversationCreatorFilter, conversationCreatorFilterCounts } = useConversations();
7
8
  const filterOptions = computed(() => conversationCreatorFilterOptions.map((option) => ({
8
9
  value: option.value,
9
10
  label: `${option.label} ${conversationCreatorFilterCounts.value[option.value]}`
10
11
  })));
11
12
  const showConversationCreatorFilter = computed(
12
- () => hasConversationCreatorFilterResults(conversationCreatorFilterCounts.value)
13
+ () => !embedConfig?.hideConversationCreatorFilter.value && hasConversationCreatorFilterResults(conversationCreatorFilterCounts.value)
13
14
  );
14
15
  function isConversationCreatorFilter(value) {
15
16
  return value === "all" || value === "mine";
16
17
  }
17
- async function handleFilterUpdate(value) {
18
- if (isUpdating.value || !isConversationCreatorFilter(value) || value === conversationCreatorFilter.value)
18
+ function handleFilterUpdate(value) {
19
+ if (!isConversationCreatorFilter(value) || value === conversationCreatorFilter.value)
19
20
  return;
20
21
  conversationCreatorFilter.value = value;
21
- isUpdating.value = true;
22
- try {
23
- await fetchConversations({ force: true });
24
- } finally {
25
- isUpdating.value = false;
26
- }
27
22
  }
28
23
  </script>
29
24
 
@@ -0,0 +1,12 @@
1
+ import type { MaybeRefOrGetter, Ref } from 'vue';
2
+ import type { ConversationCreatorFilter } from '../../types/schemas/chat/primitives.js';
3
+ type ConversationCreatorFilterStateInput = {
4
+ defaultConversationCreatorFilter?: MaybeRefOrGetter<ConversationCreatorFilter | null | undefined>;
5
+ conversationCreatorFilter?: MaybeRefOrGetter<ConversationCreatorFilter | undefined>;
6
+ };
7
+ type ProvideConversationCreatorFilterStateOptions = {
8
+ reuseParent?: boolean;
9
+ };
10
+ export declare function provideConversationCreatorFilterState(input: ConversationCreatorFilterStateInput, options?: ProvideConversationCreatorFilterStateOptions): Ref<ConversationCreatorFilter>;
11
+ export declare function useProvidedConversationCreatorFilterState(): Ref<ConversationCreatorFilter> | null;
12
+ export {};
@@ -0,0 +1,31 @@
1
+ import { getCurrentInstance, inject, provide, ref, toValue, watch } from "vue";
2
+ const CONVERSATION_CREATOR_FILTER_STATE_KEY = Symbol("conversation-creator-filter-state");
3
+ export function provideConversationCreatorFilterState(input, options = {}) {
4
+ const inheritedState = options.reuseParent ? inject(
5
+ CONVERSATION_CREATOR_FILTER_STATE_KEY,
6
+ null
7
+ ) : null;
8
+ if (inheritedState)
9
+ return inheritedState;
10
+ const state = ref(
11
+ toValue(input.conversationCreatorFilter) ?? toValue(input.defaultConversationCreatorFilter) ?? "all"
12
+ );
13
+ watch(
14
+ () => toValue(input.conversationCreatorFilter),
15
+ (controlledFilter) => {
16
+ if (controlledFilter !== void 0)
17
+ state.value = controlledFilter;
18
+ },
19
+ { flush: "sync" }
20
+ );
21
+ provide(CONVERSATION_CREATOR_FILTER_STATE_KEY, state);
22
+ return state;
23
+ }
24
+ export function useProvidedConversationCreatorFilterState() {
25
+ if (!getCurrentInstance())
26
+ return null;
27
+ return inject(
28
+ CONVERSATION_CREATOR_FILTER_STATE_KEY,
29
+ null
30
+ );
31
+ }
@@ -1,6 +1,7 @@
1
1
  import { useChatAuth } from "#chat-auth";
2
2
  import * as Sentry from "@sentry/nuxt";
3
3
  import { resolveChatStateScope } from "../scope.js";
4
+ import { useProvidedConversationCreatorFilterState } from "./conversation-creator-filter-state.js";
4
5
  import { useChatApi } from "../../shared/composables/chat-api.js";
5
6
  import { useEmbedConfig } from "../../embed/composables/embed-config.js";
6
7
  import { useStatusToast } from "../../shared/composables/status-toast.js";
@@ -55,6 +56,7 @@ function createOptimisticConversationId() {
55
56
  return `optimistic-${Date.now()}-${Math.random().toString(36).slice(2)}`;
56
57
  }
57
58
  export function useConversations() {
59
+ const nuxtApp = useNuxtApp();
58
60
  const chatApi = useChatApi();
59
61
  const embedConfig = useEmbedConfig();
60
62
  const { user: authUser, activeOrganization } = useChatAuth();
@@ -68,10 +70,22 @@ export function useConversations() {
68
70
  const metadataBuckets = useState("conversations-metadata", () => ({}));
69
71
  const metadataLoadingBuckets = useState("conversations-metadata-loading", () => ({}));
70
72
  const metadataFetchedBuckets = useState("conversations-metadata-fetched", () => ({}));
71
- const conversationCreatorFilter = useState(
73
+ const modelUpdateTails = nuxtApp._chatConversationModelUpdateTails ??= /* @__PURE__ */ new Map();
74
+ const providedConversationCreatorFilter = useProvidedConversationCreatorFilterState();
75
+ const conversationCreatorFilter = providedConversationCreatorFilter ?? useState(
72
76
  "conversation-creator-filter",
73
77
  () => embedConfig?.defaultConversationCreatorFilter?.value ?? "all"
74
78
  );
79
+ if (!providedConversationCreatorFilter) {
80
+ watch(
81
+ () => embedConfig?.conversationCreatorFilter?.value,
82
+ (controlledFilter) => {
83
+ if (controlledFilter !== void 0)
84
+ conversationCreatorFilter.value = controlledFilter;
85
+ },
86
+ { flush: "sync", immediate: true }
87
+ );
88
+ }
75
89
  const runtimeScope = computed(() => resolveChatStateScope(
76
90
  embedConfig?.workspaceId.value || activeOrganization.value?.id,
77
91
  embedConfig?.telaAgentId.value,
@@ -450,31 +464,41 @@ export function useConversations() {
450
464
  return false;
451
465
  }
452
466
  };
453
- const updateConversationModel = async (id, model) => {
454
- error.value = null;
455
- const requestRuntimeScope = runtimeScope.value;
456
- const affectedScopes = activeAndLoadedRuntimeConversationScopes(requestRuntimeScope);
457
- const conversationSnapshot = snapshotConversationBuckets(affectedScopes);
458
- const conversation = findConversationInLoadedBuckets(id, requestRuntimeScope);
459
- if (conversation)
460
- updateConversationInLoadedBuckets({ ...conversation, model, updatedAt: /* @__PURE__ */ new Date() }, requestRuntimeScope);
461
- try {
462
- const updated = await $fetch(
463
- chatApi.path(`/conversations/${id}`),
464
- chatApi.withChatHeaders({
465
- method: "PATCH",
466
- body: { model }
467
- })
468
- );
469
- updateConversationInLoadedBuckets(updated, requestRuntimeScope);
470
- return true;
471
- } catch (err) {
472
- restoreConversationBuckets(conversationSnapshot, id);
473
- const message = err instanceof Error ? err.message : "Erro ao atualizar modelo da conversa";
474
- error.value = message;
475
- Sentry.captureException(err);
476
- return false;
477
- }
467
+ const updateConversationModel = (id, model) => {
468
+ const previousUpdate = modelUpdateTails.get(id) ?? Promise.resolve(true);
469
+ const update = previousUpdate.catch(() => false).then(async () => {
470
+ error.value = null;
471
+ const requestRuntimeScope = runtimeScope.value;
472
+ const affectedScopes = activeAndLoadedRuntimeConversationScopes(requestRuntimeScope);
473
+ const conversationSnapshot = snapshotConversationBuckets(affectedScopes);
474
+ const conversation = findConversationInLoadedBuckets(id, requestRuntimeScope);
475
+ if (conversation)
476
+ updateConversationInLoadedBuckets({ ...conversation, model, updatedAt: /* @__PURE__ */ new Date() }, requestRuntimeScope);
477
+ try {
478
+ const updated = await $fetch(
479
+ chatApi.path(`/conversations/${id}`),
480
+ chatApi.withChatHeaders({
481
+ method: "PATCH",
482
+ body: { model }
483
+ })
484
+ );
485
+ updateConversationInLoadedBuckets(updated, requestRuntimeScope);
486
+ return true;
487
+ } catch (err) {
488
+ restoreConversationBuckets(conversationSnapshot, id);
489
+ const message = err instanceof Error ? err.message : "Erro ao atualizar modelo da conversa";
490
+ error.value = message;
491
+ Sentry.captureException(err);
492
+ return false;
493
+ }
494
+ });
495
+ const clearUpdate = () => {
496
+ if (modelUpdateTails.get(id) === update)
497
+ modelUpdateTails.delete(id);
498
+ };
499
+ modelUpdateTails.set(id, update);
500
+ void update.then(clearUpdate, clearUpdate);
501
+ return update;
478
502
  };
479
503
  const duplicateConversation = async (id) => {
480
504
  error.value = null;
@@ -19,9 +19,11 @@ type __VLS_Slots = {} & {
19
19
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
20
20
  "update:conversationId": (value: string | null) => any;
21
21
  "update:conversationTitle": (value: string | null) => any;
22
+ "update:conversationCreatorFilter": (value: ConversationCreatorFilter) => any;
22
23
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
23
24
  "onUpdate:conversationId"?: ((value: string | null) => any) | undefined;
24
25
  "onUpdate:conversationTitle"?: ((value: string | null) => any) | undefined;
26
+ "onUpdate:conversationCreatorFilter"?: ((value: ConversationCreatorFilter) => any) | undefined;
25
27
  }>, {
26
28
  hideSettings: boolean;
27
29
  hideSidebar: boolean;
@@ -15,6 +15,11 @@ import {
15
15
  resolveTelaAgentInputs,
16
16
  useChat
17
17
  } from "../../messages/composables/chat";
18
+ import {
19
+ ensureConversationUsesSelectedModel,
20
+ MODEL_UPDATE_FAILED_MESSAGE,
21
+ resolveChatModelSelection
22
+ } from "../../messages/model-availability";
18
23
  import { useChatAction } from "../../messages/composables/chat-action";
19
24
  import { useChatApi } from "../../shared/composables/chat-api";
20
25
  import { useConversationFiles } from "../../files/composables/conversation-files";
@@ -42,7 +47,7 @@ const props = defineProps({
42
47
  user: { type: [Object, null], required: false },
43
48
  features: { type: Object, required: false }
44
49
  });
45
- const emit = defineEmits(["update:conversationId", "update:conversationTitle"]);
50
+ const emit = defineEmits(["update:conversationId", "update:conversationTitle", "update:conversationCreatorFilter"]);
46
51
  const sidebarPosition = computed(() => props.sidebar?.position ?? "left");
47
52
  const sidebarWidth = computed(() => props.sidebar?.width ?? 240);
48
53
  const sidebarBottomHeight = computed(
@@ -77,7 +82,8 @@ const {
77
82
  updateConversationModel,
78
83
  duplicateConversation,
79
84
  moveConversationToGroup,
80
- updateConversationInList
85
+ updateConversationInList,
86
+ conversationCreatorFilter
81
87
  } = useConversations();
82
88
  const { settings: workspaceSettingsState, fetchSettings } = useWorkspaceSettings();
83
89
  const {
@@ -126,6 +132,11 @@ const activeConversationId = ref(
126
132
  );
127
133
  const loadingConversationId = ref(null);
128
134
  const isReady = ref(false);
135
+ watch(conversationCreatorFilter, (filter) => {
136
+ emit("update:conversationCreatorFilter", filter);
137
+ if (isReady.value)
138
+ void fetchConversations({ force: true });
139
+ });
129
140
  const {
130
141
  pendingConversationGroupId,
131
142
  setPendingConversationGroup,
@@ -195,30 +206,45 @@ watch(chatError, (message) => {
195
206
  });
196
207
  const conversationIdRef = computed(() => currentConversation.value?.id ?? null);
197
208
  const { total, files: conversationFiles } = useConversationFiles(conversationIdRef);
209
+ function persistConversationModel(conversation, value, wakeAgent) {
210
+ const previousModel = conversation.model;
211
+ setConversationModel(value);
212
+ const update = updateConversationModel(conversation.id, value).then(async (updated) => {
213
+ if (!updated && currentConversation.value?.id === conversation.id && currentConversation.value.model === value) {
214
+ setConversationModel(previousModel);
215
+ } else if (updated && value && wakeAgent) {
216
+ if (conversation.threadSessionId)
217
+ await agentWake.ensureReady(conversation.threadSessionId, value);
218
+ else
219
+ await agentWake.wake(void 0, value);
220
+ }
221
+ return updated;
222
+ });
223
+ const trackedUpdate = update.finally(() => {
224
+ if (modelUpdateInFlight.value === trackedUpdate)
225
+ modelUpdateInFlight.value = null;
226
+ });
227
+ modelUpdateInFlight.value = trackedUpdate;
228
+ return trackedUpdate;
229
+ }
230
+ async function waitForPendingModelUpdate() {
231
+ while (modelUpdateInFlight.value) {
232
+ const update = modelUpdateInFlight.value;
233
+ if (!await update)
234
+ throw new Error(MODEL_UPDATE_FAILED_MESSAGE);
235
+ }
236
+ }
198
237
  const selectedModel = computed({
199
- get: () => currentConversation.value ? currentConversation.value.model : pendingModelSelection.value,
238
+ get: () => resolveChatModelSelection(
239
+ currentConversation.value ? currentConversation.value.model : pendingModelSelection.value,
240
+ embedConfig?.availableModels.value
241
+ ),
200
242
  set: (value) => {
201
- pendingModelSelection.value = value;
243
+ const resolvedValue = resolveChatModelSelection(value, embedConfig?.availableModels.value);
244
+ pendingModelSelection.value = resolvedValue;
202
245
  const conversation = currentConversation.value;
203
- if (conversation && conversation.model !== value) {
204
- const previousModel = conversation.model;
205
- setConversationModel(value);
206
- const update = updateConversationModel(conversation.id, value).then(async (updated) => {
207
- if (!updated && currentConversation.value?.id === conversation.id && currentConversation.value.model === value) {
208
- setConversationModel(previousModel);
209
- } else if (updated && value) {
210
- if (conversation.threadSessionId)
211
- await agentWake.ensureReady(conversation.threadSessionId, value);
212
- else
213
- await agentWake.wake(void 0, value);
214
- }
215
- return updated;
216
- });
217
- modelUpdateInFlight.value = update.finally(() => {
218
- if (modelUpdateInFlight.value === update)
219
- modelUpdateInFlight.value = null;
220
- });
221
- }
246
+ if (conversation && conversation.model !== resolvedValue)
247
+ void persistConversationModel(conversation, resolvedValue, true);
222
248
  }
223
249
  });
224
250
  const filesCount = computed(() => total.value);
@@ -473,11 +499,15 @@ async function handleSend(content, files, agentInputs) {
473
499
  adoptConversation(grouped ? { ...conversation2, groupId } : conversation2);
474
500
  updateConversationId(conversation2.id);
475
501
  }
476
- if (modelUpdateInFlight.value)
477
- await modelUpdateInFlight.value;
502
+ await waitForPendingModelUpdate();
478
503
  const conversation = currentConversation.value;
479
504
  if (!conversation)
480
505
  throw new Error("Erro ao preparar conversa");
506
+ await ensureConversationUsesSelectedModel(
507
+ conversation.model,
508
+ selectedModel.value,
509
+ (value) => persistConversationModel(conversation, value, false)
510
+ );
481
511
  if (conversation.threadSessionId && resolvedFeatures.value.chatOutboundQueue) {
482
512
  const wake = await agentWake.ensureReady(conversation.threadSessionId, selectedModel.value);
483
513
  if (wake.status !== "ready") {
@@ -529,16 +559,25 @@ async function handleCancel() {
529
559
  await cancelConversation();
530
560
  }
531
561
  async function handleRetry(messageId) {
532
- if (currentConversation.value?.threadSessionId) {
533
- const wake = await agentWake.ensureReady(currentConversation.value.threadSessionId, selectedModel.value);
534
- if (wake.status !== "ready") {
535
- statusToast.update({ text: "N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.", icon: "i-ph-warning" });
536
- return;
562
+ await retryMessage(messageId, async () => {
563
+ await waitForPendingModelUpdate();
564
+ const conversation = currentConversation.value;
565
+ if (!conversation)
566
+ throw new Error("Erro ao preparar conversa");
567
+ await ensureConversationUsesSelectedModel(
568
+ conversation.model,
569
+ selectedModel.value,
570
+ (value) => persistConversationModel(conversation, value, false)
571
+ );
572
+ if (conversation.threadSessionId) {
573
+ const wake = await agentWake.ensureReady(conversation.threadSessionId, selectedModel.value);
574
+ if (wake.status !== "ready")
575
+ throw new Error("N\xE3o foi poss\xEDvel acordar o agente. Tente novamente.");
576
+ } else {
577
+ await agentWake.waitUntilSettled();
537
578
  }
538
- } else {
539
- await agentWake.waitUntilSettled();
540
- }
541
- await retryMessage(messageId, claimableWakeSessionId());
579
+ return claimableWakeSessionId();
580
+ });
542
581
  }
543
582
  async function handleNewConversation(groupId) {
544
583
  setPendingConversationGroup(groupId);
@@ -19,9 +19,11 @@ type __VLS_Slots = {} & {
19
19
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
20
20
  "update:conversationId": (value: string | null) => any;
21
21
  "update:conversationTitle": (value: string | null) => any;
22
+ "update:conversationCreatorFilter": (value: ConversationCreatorFilter) => any;
22
23
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
23
24
  "onUpdate:conversationId"?: ((value: string | null) => any) | undefined;
24
25
  "onUpdate:conversationTitle"?: ((value: string | null) => any) | undefined;
26
+ "onUpdate:conversationCreatorFilter"?: ((value: ConversationCreatorFilter) => any) | undefined;
25
27
  }>, {
26
28
  hideSettings: boolean;
27
29
  hideSidebar: boolean;
@@ -2,9 +2,9 @@ import { useChatAuth } from '#chat-auth';
2
2
  import { type ChatActionPayload } from '../../messages/composables/chat-action.js';
3
3
  import { type MessageFeedbackPayload } from '../../messages/composables/chat-feedback.js';
4
4
  import { type ChatMessageTerminalPayload } from '../../messages/composables/chat-message-terminal.js';
5
- declare var __VLS_12: {};
5
+ declare var __VLS_13: {};
6
6
  type __VLS_Slots = {} & {
7
- 'sidebar-bottom'?: (props: typeof __VLS_12) => any;
7
+ 'sidebar-bottom'?: (props: typeof __VLS_13) => any;
8
8
  };
9
9
  declare const __VLS_base: import("vue").DefineComponent<(import("../types.js").ChatEmbedSharedProps & {
10
10
  telaAgentId?: undefined;
@@ -21,6 +21,7 @@ declare const __VLS_base: import("vue").DefineComponent<(import("../types.js").C
21
21
  } & import("../types.js").ChatEmbedVariantProps), {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
22
22
  "update:conversationId": (value: string | null) => any;
23
23
  "update:conversationTitle": (value: string | null) => any;
24
+ "update:conversationCreatorFilter": (value: "all" | "mine") => any;
24
25
  messageFeedback: (payload: MessageFeedbackPayload) => any;
25
26
  action: (payload: ChatActionPayload) => any;
26
27
  messageTerminal: (payload: ChatMessageTerminalPayload) => any;
@@ -39,6 +40,7 @@ declare const __VLS_base: import("vue").DefineComponent<(import("../types.js").C
39
40
  } & import("../types.js").ChatEmbedVariantProps)> & Readonly<{
40
41
  "onUpdate:conversationId"?: ((value: string | null) => any) | undefined;
41
42
  "onUpdate:conversationTitle"?: ((value: string | null) => any) | undefined;
43
+ "onUpdate:conversationCreatorFilter"?: ((value: "all" | "mine") => any) | undefined;
42
44
  onMessageFeedback?: ((payload: MessageFeedbackPayload) => any) | undefined;
43
45
  onAction?: ((payload: ChatActionPayload) => any) | undefined;
44
46
  onMessageTerminal?: ((payload: ChatMessageTerminalPayload) => any) | undefined;
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { useChatAuth } from "#chat-auth";
3
+ import { provideConversationCreatorFilterState } from "../../conversations/composables/conversation-creator-filter-state";
3
4
  import { provideChatAction } from "../../messages/composables/chat-action";
4
5
  import { provideMessageFeedback } from "../../messages/composables/chat-feedback";
5
6
  import { provideChatMessageTerminal } from "../../messages/composables/chat-message-terminal";
@@ -12,6 +13,9 @@ const props = defineProps({
12
13
  initialConversationId: { type: [String, null], required: false },
13
14
  conversationScope: { type: [String, null], required: false },
14
15
  defaultConversationCreatorFilter: { type: null, required: false },
16
+ availableModels: { type: Array, required: false },
17
+ conversationCreatorFilter: { type: null, required: false },
18
+ hideConversationCreatorFilter: { type: Boolean, required: false },
15
19
  hideSidebar: { type: Boolean, required: false },
16
20
  sidebar: { type: Object, required: false },
17
21
  hideSettings: { type: Boolean, required: false },
@@ -33,7 +37,7 @@ const props = defineProps({
33
37
  defaultOpen: { type: Boolean, required: false },
34
38
  launcherLabel: { type: String, required: false }
35
39
  });
36
- const emit = defineEmits(["update:conversationId", "update:conversationTitle", "action", "messageFeedback", "messageTerminal"]);
40
+ const emit = defineEmits(["update:conversationId", "update:conversationTitle", "update:conversationCreatorFilter", "action", "messageFeedback", "messageTerminal"]);
37
41
  const parentEmbedConfig = useEmbedConfig();
38
42
  const { activeOrganization } = useChatAuth();
39
43
  const workspaceId = computed(() => activeOrganization.value?.id?.trim() ?? "");
@@ -41,14 +45,21 @@ const normalizedTelaAgentId = computed(() => normalizeTelaAgentId(props.telaAgen
41
45
  const normalizedConversationScope = computed(() => normalizeConversationScope(props.conversationScope));
42
46
  const hideSettings = computed(() => props.hideSettings ?? false);
43
47
  const ignoredPropsWarningKey = ref(null);
48
+ provideConversationCreatorFilterState({
49
+ defaultConversationCreatorFilter: () => props.defaultConversationCreatorFilter,
50
+ conversationCreatorFilter: () => props.conversationCreatorFilter
51
+ }, { reuseParent: true });
44
52
  provideEmbedConfig({
45
53
  workspaceId,
46
54
  telaAgentId: normalizedTelaAgentId,
47
55
  conversationScope: normalizedConversationScope,
48
56
  defaultConversationCreatorFilter: computed(() => props.defaultConversationCreatorFilter),
57
+ availableModels: computed(() => props.availableModels),
58
+ conversationCreatorFilter: computed(() => props.conversationCreatorFilter),
49
59
  telaAgentInputs: computed(() => props.telaAgentInputs),
50
60
  workspaceSettings: computed(() => props.workspaceSettings),
51
61
  hideSidebar: computed(() => props.hideSidebar),
62
+ hideConversationCreatorFilter: computed(() => props.hideConversationCreatorFilter),
52
63
  hideSettings,
53
64
  loadingMessages: computed(() => props.loadingMessages),
54
65
  loadingMessagesMode: computed(() => props.loadingMessagesMode),
@@ -108,6 +119,7 @@ provideChatMessageTerminal((payload) => {
108
119
  :features="features"
109
120
  @update:conversation-id="$emit('update:conversationId', $event)"
110
121
  @update:conversation-title="$emit('update:conversationTitle', $event)"
122
+ @update:conversation-creator-filter="$emit('update:conversationCreatorFilter', $event)"
111
123
  >
112
124
  <template v-if="$slots['sidebar-bottom']" #sidebar-bottom>
113
125
  <slot name="sidebar-bottom" />
@@ -2,9 +2,9 @@ import { useChatAuth } from '#chat-auth';
2
2
  import { type ChatActionPayload } from '../../messages/composables/chat-action.js';
3
3
  import { type MessageFeedbackPayload } from '../../messages/composables/chat-feedback.js';
4
4
  import { type ChatMessageTerminalPayload } from '../../messages/composables/chat-message-terminal.js';
5
- declare var __VLS_12: {};
5
+ declare var __VLS_13: {};
6
6
  type __VLS_Slots = {} & {
7
- 'sidebar-bottom'?: (props: typeof __VLS_12) => any;
7
+ 'sidebar-bottom'?: (props: typeof __VLS_13) => any;
8
8
  };
9
9
  declare const __VLS_base: import("vue").DefineComponent<(import("../types.js").ChatEmbedSharedProps & {
10
10
  telaAgentId?: undefined;
@@ -21,6 +21,7 @@ declare const __VLS_base: import("vue").DefineComponent<(import("../types.js").C
21
21
  } & import("../types.js").ChatEmbedVariantProps), {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
22
22
  "update:conversationId": (value: string | null) => any;
23
23
  "update:conversationTitle": (value: string | null) => any;
24
+ "update:conversationCreatorFilter": (value: "all" | "mine") => any;
24
25
  messageFeedback: (payload: MessageFeedbackPayload) => any;
25
26
  action: (payload: ChatActionPayload) => any;
26
27
  messageTerminal: (payload: ChatMessageTerminalPayload) => any;
@@ -39,6 +40,7 @@ declare const __VLS_base: import("vue").DefineComponent<(import("../types.js").C
39
40
  } & import("../types.js").ChatEmbedVariantProps)> & Readonly<{
40
41
  "onUpdate:conversationId"?: ((value: string | null) => any) | undefined;
41
42
  "onUpdate:conversationTitle"?: ((value: string | null) => any) | undefined;
43
+ "onUpdate:conversationCreatorFilter"?: ((value: "all" | "mine") => any) | undefined;
42
44
  onMessageFeedback?: ((payload: MessageFeedbackPayload) => any) | undefined;
43
45
  onAction?: ((payload: ChatActionPayload) => any) | undefined;
44
46
  onMessageTerminal?: ((payload: ChatMessageTerminalPayload) => any) | undefined;
@@ -3,11 +3,13 @@ import type { ChatActionPayload } from '../../messages/composables/chat-action.j
3
3
  import type { MessageFeedbackPayload } from '../../messages/composables/chat-feedback.js';
4
4
  import type { ChatMessageTerminalPayload } from '../../messages/composables/chat-message-terminal.js';
5
5
  import type { ChatFeatureConfig } from '../feature-config.js';
6
- import type { ChatEmbedVariant, ChatEmbedVariantProps, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps } from '../types.js';
6
+ import type { AvailableChatModels, ChatEmbedVariant, ChatEmbedVariantProps, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps } from '../types.js';
7
7
 
8
8
  type MeistrariChatEmbedEmits = {
9
9
  /** Fired when the active conversation changes. Pairs with `v-model:conversation-id`. */
10
10
  'update:conversationId': (value: string | null) => any;
11
+ /** Fired when the active conversation creator filter changes. Pairs with `v-model:conversation-creator-filter`. */
12
+ 'update:conversationCreatorFilter': (value: 'all' | 'mine') => any;
11
13
  /** Fired when the floating widget window opens or closes. Widget variants only. */
12
14
  'update:open': (value: boolean) => any;
13
15
  /** Fired when an assistant message triggers a host-handled action. */
@@ -52,4 +54,4 @@ type MeistrariChatEmbedSlots = SlotsType<{
52
54
  declare const MeistrariChatEmbed: DefineSetupFnComponent<MeistrariChatEmbedProps, MeistrariChatEmbedEmits, MeistrariChatEmbedSlots>;
53
55
 
54
56
  export default MeistrariChatEmbed;
55
- export type { ChatActionPayload, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackPayload, TelaAgentChatEmbedProps };
57
+ export type { AvailableChatModels, ChatActionPayload, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackPayload, TelaAgentChatEmbedProps };
@@ -1,10 +1,14 @@
1
1
  <script setup>
2
2
  import { computed, ref, watch } from "vue";
3
+ import { provideConversationCreatorFilterState } from "../../conversations/composables/conversation-creator-filter-state";
3
4
  const { hideSidebar = void 0, ...props } = defineProps({
4
5
  conversationId: { type: [String, null], required: false },
5
6
  initialConversationId: { type: [String, null], required: false },
6
7
  conversationScope: { type: [String, null], required: false },
7
8
  defaultConversationCreatorFilter: { type: null, required: false },
9
+ availableModels: { type: Array, required: false },
10
+ conversationCreatorFilter: { type: null, required: false },
11
+ hideConversationCreatorFilter: { type: Boolean, required: false },
8
12
  hideSidebar: { type: Boolean, required: false },
9
13
  sidebar: { type: Object, required: false },
10
14
  hideSettings: { type: Boolean, required: false },
@@ -26,8 +30,12 @@ const { hideSidebar = void 0, ...props } = defineProps({
26
30
  defaultOpen: { type: Boolean, required: false },
27
31
  launcherLabel: { type: String, required: false }
28
32
  });
29
- const emit = defineEmits(["update:conversationId", "update:open", "action", "messageFeedback", "messageTerminal"]);
33
+ const emit = defineEmits(["update:conversationId", "update:conversationCreatorFilter", "update:open", "action", "messageFeedback", "messageTerminal"]);
30
34
  defineSlots();
35
+ provideConversationCreatorFilterState({
36
+ defaultConversationCreatorFilter: () => props.defaultConversationCreatorFilter,
37
+ conversationCreatorFilter: () => props.conversationCreatorFilter
38
+ });
31
39
  const hideSettings = computed(() => props.hideSettings ?? false);
32
40
  const variant = computed(() => props.variant ?? "page");
33
41
  const isOpen = ref(props.defaultOpen ?? false);
@@ -55,6 +63,9 @@ const sharedEmbedProps = computed(() => ({
55
63
  initialConversationId: props.initialConversationId,
56
64
  conversationScope: props.conversationScope,
57
65
  defaultConversationCreatorFilter: props.defaultConversationCreatorFilter,
66
+ availableModels: props.availableModels,
67
+ conversationCreatorFilter: props.conversationCreatorFilter,
68
+ hideConversationCreatorFilter: props.hideConversationCreatorFilter,
58
69
  hideSettings: hideSettings.value,
59
70
  suggestions: props.suggestions,
60
71
  features: props.features,
@@ -84,6 +95,7 @@ const widgetEmbedProps = computed(() => ({
84
95
  v-if="variant === 'page'"
85
96
  v-bind="pageEmbedProps"
86
97
  @update:conversation-id="emit('update:conversationId', $event)"
98
+ @update:conversation-creator-filter="emit('update:conversationCreatorFilter', $event)"
87
99
  @action="emit('action', $event)"
88
100
  @message-feedback="emit('messageFeedback', $event)"
89
101
  @message-terminal="emit('messageTerminal', $event)"
@@ -115,6 +127,7 @@ const widgetEmbedProps = computed(() => ({
115
127
  v-bind="widgetEmbedProps"
116
128
  compact
117
129
  @update:conversation-id="handleWidgetConversationIdChange"
130
+ @update:conversation-creator-filter="emit('update:conversationCreatorFilter', $event)"
118
131
  @update:conversation-title="widgetConversationTitle = $event"
119
132
  @action="emit('action', $event)"
120
133
  @message-feedback="emit('messageFeedback', $event)"
@@ -139,6 +152,7 @@ const widgetEmbedProps = computed(() => ({
139
152
  v-bind="widgetEmbedProps"
140
153
  compact
141
154
  @update:conversation-id="handleWidgetConversationIdChange"
155
+ @update:conversation-creator-filter="emit('update:conversationCreatorFilter', $event)"
142
156
  @update:conversation-title="widgetConversationTitle = $event"
143
157
  @action="emit('action', $event)"
144
158
  @message-feedback="emit('messageFeedback', $event)"
@@ -3,11 +3,13 @@ import type { ChatActionPayload } from '../../messages/composables/chat-action.j
3
3
  import type { MessageFeedbackPayload } from '../../messages/composables/chat-feedback.js';
4
4
  import type { ChatMessageTerminalPayload } from '../../messages/composables/chat-message-terminal.js';
5
5
  import type { ChatFeatureConfig } from '../feature-config.js';
6
- import type { ChatEmbedVariant, ChatEmbedVariantProps, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps } from '../types.js';
6
+ import type { AvailableChatModels, ChatEmbedVariant, ChatEmbedVariantProps, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps } from '../types.js';
7
7
 
8
8
  type MeistrariChatEmbedEmits = {
9
9
  /** Fired when the active conversation changes. Pairs with `v-model:conversation-id`. */
10
10
  'update:conversationId': (value: string | null) => any;
11
+ /** Fired when the active conversation creator filter changes. Pairs with `v-model:conversation-creator-filter`. */
12
+ 'update:conversationCreatorFilter': (value: 'all' | 'mine') => any;
11
13
  /** Fired when the floating widget window opens or closes. Widget variants only. */
12
14
  'update:open': (value: boolean) => any;
13
15
  /** Fired when an assistant message triggers a host-handled action. */
@@ -52,4 +54,4 @@ type MeistrariChatEmbedSlots = SlotsType<{
52
54
  declare const MeistrariChatEmbed: DefineSetupFnComponent<MeistrariChatEmbedProps, MeistrariChatEmbedEmits, MeistrariChatEmbedSlots>;
53
55
 
54
56
  export default MeistrariChatEmbed;
55
- export type { ChatActionPayload, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackPayload, TelaAgentChatEmbedProps };
57
+ export type { AvailableChatModels, ChatActionPayload, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackPayload, TelaAgentChatEmbedProps };
@@ -5,6 +5,7 @@ import type { TelaAgentExecutionInput } from '../../types/schemas/integrations/t
5
5
  import type { ChatLoadingMessageMode } from '../loading-messages.js';
6
6
  import type { ChatCitationsConfig } from '../../citations/types.js';
7
7
  import type { MessageFeedbackConfig, MessageFeedbackRating } from '../../messages/composables/chat-feedback.js';
8
+ import type { AvailableChatModels } from '../../messages/model-availability.js';
8
9
  type ConfiguredTelaAgentInputs = DeepReadonly<TelaAgentExecutionInput[]> | null | undefined;
9
10
  type ConfiguredMessageFeedback = Readonly<Record<string, MessageFeedbackRating>> | null | undefined;
10
11
  export type EmbedConfig = {
@@ -12,9 +13,12 @@ export type EmbedConfig = {
12
13
  telaAgentId: Ref<string | null>;
13
14
  conversationScope: Ref<string | null>;
14
15
  defaultConversationCreatorFilter: Ref<ConversationCreatorFilter>;
16
+ availableModels: Ref<AvailableChatModels | undefined>;
17
+ conversationCreatorFilter: Ref<ConversationCreatorFilter | undefined>;
15
18
  telaAgentInputs: Ref<ConfiguredTelaAgentInputs>;
16
19
  workspaceSettings: Ref<DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null | undefined>;
17
20
  hideSidebar: Ref<boolean>;
21
+ hideConversationCreatorFilter: Ref<boolean>;
18
22
  hideSettings: Ref<boolean>;
19
23
  loadingMessages: Ref<readonly string[] | null | undefined>;
20
24
  loadingMessagesMode: Ref<ChatLoadingMessageMode | null | undefined>;
@@ -29,9 +33,12 @@ type EmbedConfigInput = {
29
33
  telaAgentId?: MaybeRefOrGetter<string | null | undefined>;
30
34
  conversationScope?: MaybeRefOrGetter<string | null | undefined>;
31
35
  defaultConversationCreatorFilter?: MaybeRefOrGetter<ConversationCreatorFilter | null | undefined>;
36
+ availableModels?: MaybeRefOrGetter<AvailableChatModels | undefined>;
37
+ conversationCreatorFilter?: MaybeRefOrGetter<ConversationCreatorFilter | undefined>;
32
38
  telaAgentInputs?: MaybeRefOrGetter<ConfiguredTelaAgentInputs>;
33
39
  workspaceSettings?: MaybeRefOrGetter<DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null | undefined>;
34
40
  hideSidebar?: MaybeRefOrGetter<boolean | undefined>;
41
+ hideConversationCreatorFilter?: MaybeRefOrGetter<boolean | undefined>;
35
42
  hideSettings?: MaybeRefOrGetter<boolean | undefined>;
36
43
  loadingMessages?: MaybeRefOrGetter<readonly string[] | null | undefined>;
37
44
  loadingMessagesMode?: MaybeRefOrGetter<ChatLoadingMessageMode | null | undefined>;
@@ -22,9 +22,12 @@ function useGlobalEmbedConfigState() {
22
22
  telaAgentId: useState("chat-embed-config-tela-agent-id", () => null),
23
23
  conversationScope: useState("chat-embed-config-conversation-scope", () => null),
24
24
  defaultConversationCreatorFilter: useState("chat-embed-config-default-conversation-creator-filter", () => void 0),
25
+ availableModels: useState("chat-embed-config-available-models", () => void 0),
26
+ conversationCreatorFilter: useState("chat-embed-config-conversation-creator-filter", () => void 0),
25
27
  telaAgentInputs: useState("chat-embed-config-tela-agent-inputs", () => void 0),
26
28
  workspaceSettings: useState("chat-embed-config-workspace-settings", () => void 0),
27
29
  hideSidebar: useState("chat-embed-config-hide-sidebar", () => void 0),
30
+ hideConversationCreatorFilter: useState("chat-embed-config-hide-conversation-creator-filter", () => void 0),
28
31
  hideSettings: useState("chat-embed-config-hide-settings", () => void 0),
29
32
  loadingMessages: useState("chat-embed-config-loading-messages", () => void 0),
30
33
  loadingMessagesMode: useState("chat-embed-config-loading-messages-mode", () => void 0),
@@ -41,9 +44,12 @@ export function provideEmbedConfig(input, options = {}) {
41
44
  telaAgentId: computed(() => toValue(input.telaAgentId) ?? null),
42
45
  conversationScope: computed(() => normalizeConversationScope(toValue(input.conversationScope))),
43
46
  defaultConversationCreatorFilter: computed(() => toValue(input.defaultConversationCreatorFilter) ?? "all"),
47
+ availableModels: computed(() => toValue(input.availableModels)),
48
+ conversationCreatorFilter: computed(() => toValue(input.conversationCreatorFilter)),
44
49
  telaAgentInputs: computed(() => toValue(input.telaAgentInputs)),
45
50
  workspaceSettings: computed(() => toValue(input.workspaceSettings)),
46
51
  hideSidebar: computed(() => toValue(input.hideSidebar) ?? true),
52
+ hideConversationCreatorFilter: computed(() => toValue(input.hideConversationCreatorFilter) ?? false),
47
53
  hideSettings: computed(() => toValue(input.hideSettings) ?? false),
48
54
  loadingMessages: computed(() => toValue(input.loadingMessages)),
49
55
  loadingMessagesMode: computed(() => toValue(input.loadingMessagesMode)),
@@ -61,9 +67,12 @@ export function provideEmbedConfig(input, options = {}) {
61
67
  globalConfig.telaAgentId.value = config.telaAgentId.value;
62
68
  globalConfig.conversationScope.value = config.conversationScope.value;
63
69
  globalConfig.defaultConversationCreatorFilter.value = config.defaultConversationCreatorFilter.value;
70
+ globalConfig.availableModels.value = config.availableModels.value;
71
+ globalConfig.conversationCreatorFilter.value = config.conversationCreatorFilter.value;
64
72
  globalConfig.telaAgentInputs.value = config.telaAgentInputs.value;
65
73
  globalConfig.workspaceSettings.value = config.workspaceSettings.value;
66
74
  globalConfig.hideSidebar.value = config.hideSidebar.value;
75
+ globalConfig.hideConversationCreatorFilter.value = config.hideConversationCreatorFilter.value;
67
76
  globalConfig.hideSettings.value = config.hideSettings.value;
68
77
  globalConfig.loadingMessages.value = config.loadingMessages.value;
69
78
  globalConfig.loadingMessagesMode.value = config.loadingMessagesMode.value;
@@ -88,9 +97,12 @@ export function useEmbedConfig() {
88
97
  telaAgentId: computed(() => globalConfig.telaAgentId.value),
89
98
  conversationScope: computed(() => globalConfig.conversationScope.value),
90
99
  defaultConversationCreatorFilter: computed(() => globalConfig.defaultConversationCreatorFilter.value ?? "all"),
100
+ availableModels: computed(() => globalConfig.availableModels.value),
101
+ conversationCreatorFilter: computed(() => globalConfig.conversationCreatorFilter.value),
91
102
  telaAgentInputs: computed(() => globalConfig.telaAgentInputs.value),
92
103
  workspaceSettings: computed(() => globalConfig.workspaceSettings.value),
93
104
  hideSidebar: computed(() => globalConfig.hideSidebar.value ?? true),
105
+ hideConversationCreatorFilter: computed(() => globalConfig.hideConversationCreatorFilter.value ?? false),
94
106
  hideSettings: computed(() => globalConfig.hideSettings.value ?? false),
95
107
  loadingMessages: computed(() => globalConfig.loadingMessages.value),
96
108
  loadingMessagesMode: computed(() => globalConfig.loadingMessagesMode.value),
@@ -6,6 +6,8 @@ import type { ChatLoadingMessageMode } from './loading-messages.js';
6
6
  import type { ChatFeatureConfig } from './feature-config.js';
7
7
  import type { ChatCitationsConfig } from '../citations/types.js';
8
8
  import type { MessageFeedbackConfig, MessageFeedbackRating } from '../messages/composables/chat-feedback.js';
9
+ import type { AvailableChatModels } from '../messages/model-availability.js';
10
+ export type { AvailableChatModels } from '../messages/model-availability.js';
9
11
  export type ChatEmbedVariant = 'page' | 'floating' | 'sidepanel';
10
12
  export type ChatSuggestion = {
11
13
  /** Short label rendered on the suggestion pill. */
@@ -55,6 +57,16 @@ export type ChatEmbedSharedProps = {
55
57
  * conversation in scope, `'mine'` shows only those created by the current user.
56
58
  */
57
59
  defaultConversationCreatorFilter?: ConversationCreatorFilter;
60
+ /**
61
+ * Non-empty ordered list of models this embed may display and execute.
62
+ * When omitted, the full chat catalog remains available. The first model is
63
+ * used when a new or restored selection is not allowed by this list.
64
+ */
65
+ availableModels?: AvailableChatModels;
66
+ /** Controlled creator filter. Use with `v-model:conversation-creator-filter` when the host changes it at runtime. */
67
+ conversationCreatorFilter?: ConversationCreatorFilter;
68
+ /** Hide the conversation creator filter while preserving its active value. */
69
+ hideConversationCreatorFilter?: boolean;
58
70
  /** Hide the conversation list and render only the active chat surface. */
59
71
  hideSidebar?: boolean;
60
72
  /** Layout options for the conversation sidebar (edge and `sidebar-bottom` split). */
@@ -1,5 +1,7 @@
1
1
  <script setup>
2
2
  import { chatModelOptions } from "../../types/schemas/chat/ui.js";
3
+ import { useEmbedConfig } from "../../embed/composables/embed-config";
4
+ import { resolveAvailableChatModels } from "../model-availability";
3
5
  import TelaChatIconsAnthropic from "@meistrari/tela-build/components/tela/chat/icons/anthropic.vue";
4
6
  import TelaChatIconsGemini from "@meistrari/tela-build/components/tela/chat/icons/gemini.vue";
5
7
  import TelaChatIconsOpenai from "@meistrari/tela-build/components/tela/chat/icons/openai.vue";
@@ -7,23 +9,32 @@ defineProps({
7
9
  disabled: { type: Boolean, required: false }
8
10
  });
9
11
  const model = defineModel({ type: [String, null], ...{ default: null } });
12
+ const embedConfig = useEmbedConfig();
10
13
  const providerIcons = {
11
14
  Anthropic: TelaChatIconsAnthropic,
12
15
  OpenAI: TelaChatIconsOpenai,
13
16
  Google: TelaChatIconsGemini
14
17
  };
15
- const options = chatModelOptions.map((option) => ({
16
- value: option.value,
17
- label: option.label,
18
- description: option.description,
19
- group: option.provider,
20
- icon: providerIcons[option.provider],
21
- cost: option.cost,
22
- maxInputTokens: option.maxInputTokens,
23
- maxOutputTokens: option.maxOutputTokens,
24
- isMultiModal: option.isMultiModal,
25
- tabs: [...option.tabs]
26
- }));
18
+ const options = computed(() => {
19
+ const availableModels = resolveAvailableChatModels(embedConfig?.availableModels.value);
20
+ return availableModels.map((model2) => {
21
+ const option = chatModelOptions.find((candidate) => candidate.value === model2);
22
+ if (!option)
23
+ throw new Error(`${model2} is missing from the chat model catalog`);
24
+ return {
25
+ value: option.value,
26
+ label: option.label,
27
+ description: option.description,
28
+ group: option.provider,
29
+ icon: providerIcons[option.provider],
30
+ cost: option.cost,
31
+ maxInputTokens: option.maxInputTokens,
32
+ maxOutputTokens: option.maxOutputTokens,
33
+ isMultiModal: option.isMultiModal,
34
+ tabs: [...option.tabs]
35
+ };
36
+ });
37
+ });
27
38
  const tabLabels = {
28
39
  all: "Todos",
29
40
  advanced: "Avan\xE7ados",
@@ -9,9 +9,9 @@ type __VLS_Slots = {} & {
9
9
  default?: (props: typeof __VLS_1) => any;
10
10
  };
11
11
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
12
+ flush: boolean;
12
13
  limit: "input" | "output" | "none";
13
14
  tone: "mono" | "prose" | "error";
14
- flush: boolean;
15
15
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
16
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
17
  declare const _default: typeof __VLS_export;
@@ -9,9 +9,9 @@ type __VLS_Slots = {} & {
9
9
  default?: (props: typeof __VLS_1) => any;
10
10
  };
11
11
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
12
+ flush: boolean;
12
13
  limit: "input" | "output" | "none";
13
14
  tone: "mono" | "prose" | "error";
14
- flush: boolean;
15
15
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
16
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
17
  declare const _default: typeof __VLS_export;
@@ -40,7 +40,7 @@ export declare function useChat(options?: {
40
40
  }>, queuedSend?: QueuedSend) => Promise<Message | null>;
41
41
  flushOutboundQueue: (wakeSessionId?: string) => Promise<Message | null>;
42
42
  failOutboundQueue: (message: string) => boolean;
43
- retryMessage: (messageId: string, wakeSessionId?: string) => Promise<boolean>;
43
+ retryMessage: (messageId: string, prepare?: () => Promise<string | undefined>) => Promise<boolean>;
44
44
  cancelConversation: () => Promise<boolean>;
45
45
  startPolling: () => void;
46
46
  stopPolling: () => void;
@@ -713,19 +713,24 @@ export function useChat(options = {}) {
713
713
  return false;
714
714
  }
715
715
  };
716
- const retryMessage = async (messageId, wakeSessionId) => {
716
+ const retryMessage = async (messageId, prepare) => {
717
717
  if (!currentConversation.value)
718
718
  return false;
719
+ const conversationId = currentConversation.value.id;
719
720
  error.value = null;
720
- const retry = beginAssistantMessageRetry(messages.value, messageId);
721
- if (!retry)
722
- return false;
723
- messages.value = retry.messages;
724
- streamingMessageId.value = messageId;
725
- directStream.beginMessage();
721
+ let retry = null;
726
722
  try {
723
+ const wakeSessionId = prepare ? await prepare() : void 0;
724
+ if (currentConversation.value?.id !== conversationId)
725
+ return false;
726
+ retry = beginAssistantMessageRetry(messages.value, messageId);
727
+ if (!retry)
728
+ return false;
729
+ messages.value = retry.messages;
730
+ streamingMessageId.value = messageId;
731
+ directStream.beginMessage();
727
732
  await $fetch(
728
- chatApi.path(`/conversations/${currentConversation.value.id}/messages/${messageId}/retry`),
733
+ chatApi.path(`/conversations/${conversationId}/messages/${messageId}/retry`),
729
734
  chatApi.withChatHeaders({
730
735
  method: "POST",
731
736
  body: wakeSessionId ? { wakeSessionId } : {}
@@ -734,9 +739,11 @@ export function useChat(options = {}) {
734
739
  startPolling();
735
740
  return true;
736
741
  } catch (err) {
737
- messages.value = restoreAssistantMessageAfterRetryFailure(messages.value, retry.originalMessage);
738
- streamingMessageId.value = null;
739
- directStream.disconnect();
742
+ if (retry) {
743
+ messages.value = restoreAssistantMessageAfterRetryFailure(messages.value, retry.originalMessage);
744
+ streamingMessageId.value = null;
745
+ directStream.disconnect();
746
+ }
740
747
  const errorMessage = getChatApiErrorCode(err) === "workspace_agent_not_ready" ? WORKSPACE_AGENT_NOT_READY_TEXT : err instanceof Error ? err.message : "Erro ao reenviar mensagem";
741
748
  error.value = errorMessage;
742
749
  Sentry.captureException(err);
@@ -0,0 +1,6 @@
1
+ import type { ChatModel } from '../types/schemas/chat/models.js';
2
+ export type AvailableChatModels = readonly [ChatModel, ...ChatModel[]];
3
+ export declare const MODEL_UPDATE_FAILED_MESSAGE = "N\u00E3o foi poss\u00EDvel atualizar o modelo da conversa";
4
+ export declare function resolveAvailableChatModels(availableModels?: readonly ChatModel[]): readonly ChatModel[];
5
+ export declare function resolveChatModelSelection(selectedModel: string | null, availableModels?: readonly ChatModel[]): string | null;
6
+ export declare function ensureConversationUsesSelectedModel(conversationModel: string | null, selectedModel: string | null, updateModel: (model: string | null) => Promise<boolean>): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { chatModelIds, isValidChatModel } from "../types/schemas/chat/models.js";
2
+ export const MODEL_UPDATE_FAILED_MESSAGE = "N\xE3o foi poss\xEDvel atualizar o modelo da conversa";
3
+ export function resolveAvailableChatModels(availableModels) {
4
+ if (availableModels === void 0)
5
+ return chatModelIds;
6
+ if (availableModels.length === 0)
7
+ throw new Error("availableModels must contain at least one model");
8
+ const uniqueModels = [];
9
+ for (const model of availableModels) {
10
+ if (!isValidChatModel(model))
11
+ throw new Error(`${model} is not a supported chat model`);
12
+ if (!uniqueModels.includes(model))
13
+ uniqueModels.push(model);
14
+ }
15
+ return uniqueModels;
16
+ }
17
+ export function resolveChatModelSelection(selectedModel, availableModels) {
18
+ if (availableModels === void 0)
19
+ return selectedModel;
20
+ const resolvedModels = resolveAvailableChatModels(availableModels);
21
+ return selectedModel && resolvedModels.includes(selectedModel) ? selectedModel : resolvedModels[0];
22
+ }
23
+ export async function ensureConversationUsesSelectedModel(conversationModel, selectedModel, updateModel) {
24
+ if (conversationModel === selectedModel)
25
+ return;
26
+ if (!await updateModel(selectedModel))
27
+ throw new Error(MODEL_UPDATE_FAILED_MESSAGE);
28
+ }
@@ -1,9 +1,10 @@
1
1
  export type { ChatCitationsConfig, CitationMeta, CitationRef, } from '../citations/types.js';
2
2
  export type { ChatFeatureConfig } from '../embed/feature-config.js';
3
- export type { ChatActor, ChatEmbedSharedProps, ChatEmbedVariant, ChatEmbedVariantProps, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps, } from '../embed/types.js';
3
+ export type { AvailableChatModels, ChatActor, ChatEmbedSharedProps, ChatEmbedVariant, ChatEmbedVariantProps, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps, } from '../embed/types.js';
4
4
  export type { ChatActionPayload } from '../messages/composables/chat-action.js';
5
5
  export type { MessageFeedbackConfig, MessageFeedbackPayload, MessageFeedbackRating, MessageFeedbackSubmitHandler, MessageFeedbackSubmitResult, } from '../messages/composables/chat-feedback.js';
6
6
  export { ChatMessageStatus } from '../messages/composables/chat-message-terminal.js';
7
7
  export type { ChatMessageTerminalPayload } from '../messages/composables/chat-message-terminal.js';
8
8
  export type { MessageOverviewResponse } from './schemas/chat/messages.js';
9
+ export type { ConversationCreatorFilter } from './schemas/chat/primitives.js';
9
10
  export type { TelaAgentExecutionInput } from './schemas/integrations/tela-agent-api.js';
@@ -216,6 +216,7 @@ export declare const createConversationRequestSchema: z.ZodObject<{
216
216
  "claude-opus-5": "claude-opus-5";
217
217
  "claude-opus-4-8": "claude-opus-4-8";
218
218
  "claude-sonnet-5": "claude-sonnet-5";
219
+ "claude-sonnet-4-6": "claude-sonnet-4-6";
219
220
  "claude-haiku-4-5": "claude-haiku-4-5";
220
221
  }>>>;
221
222
  agentInputs: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -253,6 +254,7 @@ export declare const updateConversationRequestSchema: z.ZodObject<{
253
254
  "claude-opus-5": "claude-opus-5";
254
255
  "claude-opus-4-8": "claude-opus-4-8";
255
256
  "claude-sonnet-5": "claude-sonnet-5";
257
+ "claude-sonnet-4-6": "claude-sonnet-4-6";
256
258
  "claude-haiku-4-5": "claude-haiku-4-5";
257
259
  }>>>;
258
260
  }, z.core.$strict>;
@@ -1,9 +1,10 @@
1
1
  import { z } from 'zod';
2
- export declare const chatModelIds: readonly ["claude-opus-5", "claude-opus-4-8", "claude-sonnet-5", "claude-haiku-4-5"];
2
+ export declare const chatModelIds: readonly ["claude-opus-5", "claude-opus-4-8", "claude-sonnet-5", "claude-sonnet-4-6", "claude-haiku-4-5"];
3
3
  export declare const chatModelSchema: z.ZodEnum<{
4
4
  "claude-opus-5": "claude-opus-5";
5
5
  "claude-opus-4-8": "claude-opus-4-8";
6
6
  "claude-sonnet-5": "claude-sonnet-5";
7
+ "claude-sonnet-4-6": "claude-sonnet-4-6";
7
8
  "claude-haiku-4-5": "claude-haiku-4-5";
8
9
  }>;
9
10
  export type ChatModel = z.infer<typeof chatModelSchema>;
@@ -3,6 +3,7 @@ export const chatModelIds = [
3
3
  'claude-opus-5',
4
4
  'claude-opus-4-8',
5
5
  'claude-sonnet-5',
6
+ 'claude-sonnet-4-6',
6
7
  'claude-haiku-4-5',
7
8
  ];
8
9
  export const chatModelSchema = z.enum(chatModelIds);
@@ -49,6 +49,16 @@ export declare const chatModelOptions: readonly [{
49
49
  readonly maxOutputTokens: 64000;
50
50
  readonly isMultiModal: true;
51
51
  readonly tabs: readonly ["all", "advanced", "multimodal"];
52
+ }, {
53
+ readonly value: "claude-sonnet-4-6";
54
+ readonly label: "Claude 4.6 Sonnet";
55
+ readonly description: "Agente rápido para tarefas avançadas";
56
+ readonly provider: "Anthropic";
57
+ readonly cost: 4;
58
+ readonly maxInputTokens: 1000000;
59
+ readonly maxOutputTokens: 64000;
60
+ readonly isMultiModal: true;
61
+ readonly tabs: readonly ["all", "advanced", "multimodal"];
52
62
  }, {
53
63
  readonly value: "claude-haiku-4-5";
54
64
  readonly label: "Claude 4.5 Haiku";
@@ -9,6 +9,7 @@ export const chatModelOptions = [
9
9
  { value: 'claude-opus-5', label: 'Claude Opus 5', description: 'Agente de ponta para trabalho complexo', provider: 'Anthropic', cost: 5, maxInputTokens: 1_000_000, maxOutputTokens: 128_000, isMultiModal: true, tabs: ['all', 'advanced', 'multimodal'] },
10
10
  { value: 'claude-opus-4-8', label: 'Claude 4.8 Opus', description: 'Agente de ponta para tarefas complexas', provider: 'Anthropic', cost: 4, maxInputTokens: 1_000_000, maxOutputTokens: 128_000, isMultiModal: true, tabs: ['all', 'advanced', 'multimodal'] },
11
11
  { value: 'claude-sonnet-5', label: 'Claude Sonnet 5', description: 'Agente rápido para tarefas avançadas', provider: 'Anthropic', cost: 4, maxInputTokens: 1_000_000, maxOutputTokens: 64_000, isMultiModal: true, tabs: ['all', 'advanced', 'multimodal'] },
12
+ { value: 'claude-sonnet-4-6', label: 'Claude 4.6 Sonnet', description: 'Agente rápido para tarefas avançadas', provider: 'Anthropic', cost: 4, maxInputTokens: 1_000_000, maxOutputTokens: 64_000, isMultiModal: true, tabs: ['all', 'advanced', 'multimodal'] },
12
13
  { value: 'claude-haiku-4-5', label: 'Claude 4.5 Haiku', description: 'Agente rápido para tarefas simples', provider: 'Anthropic', cost: 3, maxInputTokens: 200_000, maxOutputTokens: 64_000, isMultiModal: true, tabs: ['all', 'cheap', 'multimodal'] },
13
14
  ];
14
15
  export const topbarTabs = ['chat', 'files', 'usage'];
@@ -278,6 +278,7 @@ export declare const telaAgentWakeRequestSchema: z.ZodObject<{
278
278
  "claude-opus-5": "claude-opus-5";
279
279
  "claude-opus-4-8": "claude-opus-4-8";
280
280
  "claude-sonnet-5": "claude-sonnet-5";
281
+ "claude-sonnet-4-6": "claude-sonnet-4-6";
281
282
  "claude-haiku-4-5": "claude-haiku-4-5";
282
283
  }>>;
283
284
  }, z.core.$strip>;
package/dist/types.d.mts CHANGED
@@ -6,7 +6,7 @@ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<
6
6
 
7
7
  export { ChatMessageStatus } from '../dist/runtime/messages/composables/chat-message-terminal.js'
8
8
 
9
- export { type ChatActionPayload, type ChatActor, type ChatEmbedSharedProps, type ChatEmbedVariant, type ChatEmbedVariantProps, type ChatFeatureConfig, type ChatMessageTerminalPayload, type ChatSidebarConfig, type ChatSuggestion, type DefaultChatEmbedProps, type MeistrariChatEmbedProps, type MessageFeedbackConfig, type MessageFeedbackPayload, type MessageFeedbackRating, type MessageFeedbackSubmitHandler, type MessageFeedbackSubmitResult, type MessageOverviewResponse, type TelaAgentChatEmbedProps, type TelaAgentExecutionInput } from '../dist/runtime/types/embed.js'
9
+ export { type AvailableChatModels, type ChatActionPayload, type ChatActor, type ChatEmbedSharedProps, type ChatEmbedVariant, type ChatEmbedVariantProps, type ChatFeatureConfig, type ChatMessageTerminalPayload, type ChatSidebarConfig, type ChatSuggestion, type DefaultChatEmbedProps, type MeistrariChatEmbedProps, type MessageFeedbackConfig, type MessageFeedbackPayload, type MessageFeedbackRating, type MessageFeedbackSubmitHandler, type MessageFeedbackSubmitResult, type MessageOverviewResponse, type TelaAgentChatEmbedProps, type TelaAgentExecutionInput } from '../dist/runtime/types/embed.js'
10
10
 
11
11
  export { default } from './module.mjs'
12
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
- "version": "3.14.2-rc.1",
3
+ "version": "3.15.0-rc.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {