@meistrari/chat-nuxt 1.4.0 → 1.5.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.
Files changed (90) hide show
  1. package/README.md +51 -16
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +24 -9
  4. package/dist/runtime/components/MeistrariChatEmbed.d.vue.ts +2 -18
  5. package/dist/runtime/components/MeistrariChatEmbed.vue +22 -4
  6. package/dist/runtime/components/MeistrariChatEmbed.vue.d.ts +2 -18
  7. package/dist/runtime/components/chat/message-input.d.vue.ts +30 -4
  8. package/dist/runtime/components/chat/message-input.vue +268 -24
  9. package/dist/runtime/components/chat/message-input.vue.d.ts +30 -4
  10. package/dist/runtime/composables/useChat.d.ts +3 -5
  11. package/dist/runtime/composables/useChat.js +18 -4
  12. package/dist/runtime/composables/useChatApi.js +4 -0
  13. package/dist/runtime/composables/useConversations.js +8 -2
  14. package/dist/runtime/composables/useEmbedConfig.d.ts +7 -1
  15. package/dist/runtime/composables/useEmbedConfig.js +8 -0
  16. package/dist/runtime/composables/useFeatureFlags.d.ts +1 -2
  17. package/dist/runtime/composables/useTelaAgentMetadata.d.ts +8 -0
  18. package/dist/runtime/composables/useTelaAgentMetadata.js +65 -0
  19. package/dist/runtime/composables/useWorkspaceSettings.d.ts +1 -19
  20. package/dist/runtime/composables/useWorkspaceSettings.js +24 -5
  21. package/dist/runtime/embed/components/ChatConfigurationModal.d.vue.ts +1 -1
  22. package/dist/runtime/embed/components/ChatConfigurationModal.vue.d.ts +1 -1
  23. package/dist/runtime/embed/components/ChatEmbed.d.vue.ts +3 -23
  24. package/dist/runtime/embed/components/ChatEmbed.vue +34 -9
  25. package/dist/runtime/embed/components/ChatEmbed.vue.d.ts +3 -23
  26. package/dist/runtime/embed/components/ChatEmbedInner.vue +50 -12
  27. package/dist/runtime/plugins/markstream.d.ts +1 -1
  28. package/dist/runtime/plugins/markstream.js +1 -1
  29. package/dist/runtime/server/api/chat/workspace/settings.patch.d.ts +2 -0
  30. package/dist/runtime/server/api/chat/workspace/settings.patch.js +8 -0
  31. package/dist/runtime/server/api/conversations/[id]/cancel.post.d.ts +1 -1
  32. package/dist/runtime/server/api/conversations/[id]/cancel.post.js +37 -17
  33. package/dist/runtime/server/api/conversations/[id]/clear.post.js +28 -13
  34. package/dist/runtime/server/api/conversations/[id]/duplicate.post.js +11 -13
  35. package/dist/runtime/server/api/conversations/[id]/files.get.js +5 -7
  36. package/dist/runtime/server/api/conversations/[id]/index.delete.js +13 -12
  37. package/dist/runtime/server/api/conversations/[id]/index.get.js +6 -13
  38. package/dist/runtime/server/api/conversations/[id]/index.patch.js +11 -10
  39. package/dist/runtime/server/api/conversations/[id]/messages/[messageId]/retry.post.js +46 -80
  40. package/dist/runtime/server/api/conversations/[id]/messages/index.get.d.ts +1 -14
  41. package/dist/runtime/server/api/conversations/[id]/messages/index.get.js +81 -187
  42. package/dist/runtime/server/api/conversations/[id]/messages/index.post.js +68 -86
  43. package/dist/runtime/server/api/conversations/[id]/usage.get.js +4 -8
  44. package/dist/runtime/server/api/conversations/generate-title.post.js +4 -3
  45. package/dist/runtime/server/api/conversations/index.get.js +5 -4
  46. package/dist/runtime/server/api/conversations/index.post.js +5 -4
  47. package/dist/runtime/server/api/tela/agents/[id].get.d.ts +6 -0
  48. package/dist/runtime/server/api/tela/agents/[id].get.js +25 -0
  49. package/dist/runtime/server/api/workspace/settings.patch.js +3 -82
  50. package/dist/runtime/server/db/schema/conversations.d.ts +17 -0
  51. package/dist/runtime/server/db/schema/conversations.js +3 -1
  52. package/dist/runtime/server/db/schema/workspace-settings.d.ts +1 -1
  53. package/dist/runtime/server/utils/chat-context.d.ts +5 -0
  54. package/dist/runtime/server/utils/chat-context.js +20 -0
  55. package/dist/runtime/server/utils/conversation-agent-turn.d.ts +39 -0
  56. package/dist/runtime/server/utils/conversation-agent-turn.js +170 -0
  57. package/dist/runtime/server/utils/conversation-message-files.d.ts +10 -0
  58. package/dist/runtime/server/utils/conversation-message-files.js +77 -0
  59. package/dist/runtime/server/utils/conversation-message-sync.d.ts +31 -0
  60. package/dist/runtime/server/utils/conversation-message-sync.js +132 -0
  61. package/dist/runtime/server/utils/conversation-scope.d.ts +2 -0
  62. package/dist/runtime/server/utils/conversation-scope.js +12 -0
  63. package/dist/runtime/server/utils/tela-agent-api.d.ts +29 -0
  64. package/dist/runtime/server/utils/tela-agent-api.js +107 -0
  65. package/dist/runtime/server/utils/tela-agent-session.d.ts +48 -0
  66. package/dist/runtime/server/utils/tela-agent-session.js +350 -0
  67. package/dist/runtime/server/utils/workspace-settings-update.d.ts +16 -0
  68. package/dist/runtime/server/utils/workspace-settings-update.js +84 -0
  69. package/dist/runtime/types/embed.d.ts +29 -0
  70. package/dist/runtime/types/embed.js +0 -0
  71. package/dist/runtime/types/tela-agent.d.ts +243 -0
  72. package/dist/runtime/types/tela-agent.js +98 -0
  73. package/dist/runtime/types/workspace-settings-data.d.ts +19 -0
  74. package/dist/runtime/types/workspace-settings-data.js +0 -0
  75. package/dist/runtime/types/workspace-settings.d.ts +1 -1
  76. package/dist/runtime/utils/agent-input-readiness.d.ts +14 -0
  77. package/dist/runtime/utils/agent-input-readiness.js +15 -0
  78. package/dist/runtime/utils/features.d.ts +9 -0
  79. package/dist/runtime/utils/features.js +5 -4
  80. package/dist/runtime/utils/file.js +46 -7
  81. package/dist/runtime/utils/markdown-nodes.d.ts +1 -0
  82. package/dist/runtime/utils/markdown-nodes.js +6 -0
  83. package/dist/runtime/utils/tela-chat.d.ts +6 -0
  84. package/dist/runtime/utils/tela-chat.js +12 -1
  85. package/drizzle/0014_faulty_lake.sql +2 -0
  86. package/drizzle/meta/0014_snapshot.json +732 -0
  87. package/drizzle/meta/_journal.json +7 -0
  88. package/package.json +1 -1
  89. package/dist/runtime/types/feature-flags.d.ts +0 -7
  90. package/dist/runtime/types/feature-flags.js +0 -6
@@ -0,0 +1,65 @@
1
+ import * as Sentry from "@sentry/nuxt";
2
+ export function useTelaAgentMetadata() {
3
+ const embedConfig = useEmbedConfig();
4
+ const agentId = computed(() => embedConfig?.telaAgentId.value?.trim() || null);
5
+ const metadataByAgentId = useState("chat-tela-agent-metadata", () => ({}));
6
+ const loadingByAgentId = useState("chat-tela-agent-metadata-loading", () => ({}));
7
+ const errorByAgentId = useState("chat-tela-agent-metadata-error", () => ({}));
8
+ const metadata = computed(() => {
9
+ const currentAgentId = agentId.value;
10
+ if (!currentAgentId)
11
+ return null;
12
+ return metadataByAgentId.value[currentAgentId] ?? null;
13
+ });
14
+ const loading = computed(() => {
15
+ const currentAgentId = agentId.value;
16
+ return currentAgentId ? loadingByAgentId.value[currentAgentId] === true : false;
17
+ });
18
+ const error = computed(() => {
19
+ const currentAgentId = agentId.value;
20
+ return currentAgentId ? errorByAgentId.value[currentAgentId] ?? null : null;
21
+ });
22
+ async function fetchAgentMetadata() {
23
+ const currentAgentId = agentId.value;
24
+ if (!currentAgentId)
25
+ return null;
26
+ if (metadataByAgentId.value[currentAgentId])
27
+ return metadataByAgentId.value[currentAgentId];
28
+ loadingByAgentId.value = {
29
+ ...loadingByAgentId.value,
30
+ [currentAgentId]: true
31
+ };
32
+ errorByAgentId.value = {
33
+ ...errorByAgentId.value,
34
+ [currentAgentId]: null
35
+ };
36
+ try {
37
+ const data = await $fetch(`/api/tela/agents/${encodeURIComponent(currentAgentId)}`);
38
+ metadataByAgentId.value = {
39
+ ...metadataByAgentId.value,
40
+ [currentAgentId]: data
41
+ };
42
+ return data;
43
+ } catch (err) {
44
+ const message = err instanceof Error ? err.message : "Erro ao carregar agente Tela";
45
+ errorByAgentId.value = {
46
+ ...errorByAgentId.value,
47
+ [currentAgentId]: message
48
+ };
49
+ Sentry.captureException(err);
50
+ return null;
51
+ } finally {
52
+ loadingByAgentId.value = {
53
+ ...loadingByAgentId.value,
54
+ [currentAgentId]: false
55
+ };
56
+ }
57
+ }
58
+ return {
59
+ agentId,
60
+ metadata,
61
+ loading,
62
+ error,
63
+ fetchAgentMetadata
64
+ };
65
+ }
@@ -1,22 +1,4 @@
1
- import type { ContextFile, ExternalSkill } from '../server/db/schema.js';
2
- import type { CanvasTool } from '../types/agent.js';
3
- import type { KnowledgeSource } from '../types/chat.js';
4
- export type WorkspaceSettings = {
5
- workspaceId: string;
6
- systemMessage: string | null;
7
- contextFiles: ContextFile[] | null;
8
- canvasTools: CanvasTool[] | null;
9
- knowledgeSources: KnowledgeSource[] | null;
10
- externalSkills: ExternalSkill[] | null;
11
- updatedAt: Date;
12
- };
13
- export type WorkspaceSettingsUpdate = {
14
- systemMessage?: string | null;
15
- contextFiles?: ContextFile[] | null;
16
- canvasTools?: CanvasTool[] | null;
17
- knowledgeSources?: KnowledgeSource[] | null;
18
- externalSkills?: ExternalSkill[] | null;
19
- };
1
+ import type { WorkspaceSettings, WorkspaceSettingsUpdate } from '../types/workspace-settings-data.js';
20
2
  export declare function useWorkspaceSettings(): {
21
3
  settings: any;
22
4
  loading: any;
@@ -1,4 +1,21 @@
1
1
  import * as Sentry from "@sentry/nuxt";
2
+ function isNullableArray(value) {
3
+ return value === null || Array.isArray(value);
4
+ }
5
+ function assertWorkspaceSettingsResponse(value) {
6
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
7
+ throw new Error("Invalid workspace settings response");
8
+ }
9
+ const settings = value;
10
+ const hasValidWorkspaceId = typeof settings.workspaceId === "string" && settings.workspaceId.length > 0;
11
+ const hasValidSystemMessage = settings.systemMessage === null || typeof settings.systemMessage === "string";
12
+ const hasValidUpdatedAt = settings.updatedAt instanceof Date || typeof settings.updatedAt === "string" && settings.updatedAt.length > 0;
13
+ const hasValidCollections = isNullableArray(settings.contextFiles) && isNullableArray(settings.canvasTools) && isNullableArray(settings.knowledgeSources) && isNullableArray(settings.externalSkills);
14
+ if (!hasValidWorkspaceId || !hasValidSystemMessage || !hasValidUpdatedAt || !hasValidCollections) {
15
+ throw new Error("Invalid workspace settings response");
16
+ }
17
+ return value;
18
+ }
2
19
  export function useWorkspaceSettings() {
3
20
  const chatApi = useChatApi();
4
21
  const embedConfig = useEmbedConfig();
@@ -65,12 +82,14 @@ export function useWorkspaceSettings() {
65
82
  if (hasWorkspaceSettingsOverride.value) {
66
83
  return settings.value;
67
84
  } else if (embedConfig !== null) {
68
- data = await $fetch(
69
- chatApi.path("/workspace/settings"),
70
- chatApi.withChatHeaders()
85
+ data = assertWorkspaceSettingsResponse(
86
+ await $fetch(
87
+ chatApi.path("/workspace/settings"),
88
+ chatApi.withChatHeaders()
89
+ )
71
90
  );
72
91
  } else {
73
- data = await $fetch("/api/workspace/settings");
92
+ data = assertWorkspaceSettingsResponse(await $fetch("/api/workspace/settings"));
74
93
  }
75
94
  if (import.meta.dev && embedConfig !== null && currentSettings) {
76
95
  const hydratedSettings = {
@@ -109,7 +128,7 @@ export function useWorkspaceSettings() {
109
128
  try {
110
129
  const path = embedConfig !== null ? chatApi.path("/workspace/settings") : "/api/workspace/settings";
111
130
  const options = embedConfig !== null ? chatApi.withChatHeaders({ method: "PATCH", body: updates }) : { method: "PATCH", body: updates };
112
- const data = await $fetch(path, options);
131
+ const data = assertWorkspaceSettingsResponse(await $fetch(path, options));
113
132
  settings.value = data;
114
133
  return data;
115
134
  } catch (e) {
@@ -1,5 +1,5 @@
1
1
  import type { DeepReadonly } from 'vue';
2
- import type { WorkspaceSettings, WorkspaceSettingsUpdate } from '../../composables/useWorkspaceSettings.js';
2
+ import type { WorkspaceSettings, WorkspaceSettingsUpdate } from '../../types/workspace-settings-data.js';
3
3
  export type ChatConfigurationTab = 'personalization' | 'context-files' | 'knowledge-sources' | 'tela-tools' | 'external-skills' | 'credentials';
4
4
  export type ChatConfigurationSavePayload = {
5
5
  updates: WorkspaceSettingsUpdate;
@@ -1,5 +1,5 @@
1
1
  import type { DeepReadonly } from 'vue';
2
- import type { WorkspaceSettings, WorkspaceSettingsUpdate } from '../../composables/useWorkspaceSettings.js';
2
+ import type { WorkspaceSettings, WorkspaceSettingsUpdate } from '../../types/workspace-settings-data.js';
3
3
  export type ChatConfigurationTab = 'personalization' | 'context-files' | 'knowledge-sources' | 'tela-tools' | 'external-skills' | 'credentials';
4
4
  export type ChatConfigurationSavePayload = {
5
5
  updates: WorkspaceSettingsUpdate;
@@ -1,30 +1,10 @@
1
- import type { Component, DeepReadonly } from 'vue';
2
1
  import { type ChatActionPayload } from '../../composables/useChatAction.js';
3
- import type { WorkspaceSettings } from '../../composables/useWorkspaceSettings.js';
4
- import type { ChatLoadingMessageMode } from '../../utils/chat-loading-messages.js';
5
- import type { ChatActor, ChatFeatureConfig } from '../../utils/tela-chat.js';
6
- type EmbedUser = ChatActor;
7
- type __VLS_Props = {
8
- workspaceSettings?: DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null;
9
- conversationId?: string | null;
10
- initialConversationId?: string | null;
11
- hideSidebar?: boolean;
12
- user?: EmbedUser | null;
13
- features?: Partial<ChatFeatureConfig>;
14
- loadingMessages?: readonly string[] | null;
15
- loadingMessagesMode?: ChatLoadingMessageMode | null;
16
- customComponents?: Record<string, Component>;
17
- customHtmlTags?: readonly string[];
18
- };
19
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
2
+ declare const __VLS_export: import("vue").DefineComponent<import("../../types/embed.js").DefaultChatEmbedProps | import("../../types/embed.js").TelaAgentChatEmbedProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
20
3
  "update:conversationId": (value: string | null) => any;
21
4
  action: (payload: ChatActionPayload) => any;
22
- }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
5
+ }, string, import("vue").PublicProps, Readonly<import("../../types/embed.js").DefaultChatEmbedProps | import("../../types/embed.js").TelaAgentChatEmbedProps> & Readonly<{
23
6
  "onUpdate:conversationId"?: ((value: string | null) => any) | undefined;
24
7
  onAction?: ((payload: ChatActionPayload) => any) | undefined;
25
- }>, {
26
- initialConversationId: string | null;
27
- hideSidebar: boolean;
28
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
29
9
  declare const _default: typeof __VLS_export;
30
10
  export default _default;
@@ -1,25 +1,32 @@
1
1
  <script setup>
2
2
  import { provideEmbedConfig, useEmbedConfig } from "../../composables/useEmbedConfig";
3
3
  import { provideChatAction } from "../../composables/useChatAction";
4
+ import { normalizeTelaAgentId } from "../../utils/tela-chat";
4
5
  import ChatEmbedInner from "./ChatEmbedInner.vue";
5
6
  const props = defineProps({
6
- workspaceSettings: { type: null, required: false },
7
7
  conversationId: { type: [String, null], required: false },
8
- initialConversationId: { type: [String, null], required: false, default: null },
9
- hideSidebar: { type: Boolean, required: false, default: true },
10
- user: { type: [Object, null], required: false },
11
- features: { type: Object, required: false },
8
+ initialConversationId: { type: [String, null], required: false },
9
+ hideSidebar: { type: Boolean, required: false },
12
10
  loadingMessages: { type: [Array, null], required: false },
13
11
  loadingMessagesMode: { type: [String, null], required: false },
14
12
  customComponents: { type: Object, required: false },
15
- customHtmlTags: { type: Array, required: false }
13
+ customHtmlTags: { type: Array, required: false },
14
+ telaAgentId: { type: null, required: false },
15
+ telaAgentInputs: { type: null, required: false },
16
+ workspaceSettings: { type: null, required: false },
17
+ user: { type: null, required: false },
18
+ features: { type: Object, required: false }
16
19
  });
17
20
  const emit = defineEmits(["update:conversationId", "action"]);
18
21
  const parentEmbedConfig = useEmbedConfig();
19
22
  const { activeOrganization } = useTelaApplicationAuth();
20
23
  const workspaceId = computed(() => activeOrganization.value?.id?.trim() ?? "");
24
+ const normalizedTelaAgentId = computed(() => normalizeTelaAgentId(props.telaAgentId));
25
+ const ignoredPropsWarningKey = ref(null);
21
26
  provideEmbedConfig({
22
27
  workspaceId,
28
+ telaAgentId: normalizedTelaAgentId,
29
+ telaAgentInputs: computed(() => props.telaAgentInputs),
23
30
  workspaceSettings: computed(() => props.workspaceSettings),
24
31
  hideSidebar: computed(() => props.hideSidebar),
25
32
  loadingMessages: computed(() => props.loadingMessages),
@@ -27,20 +34,38 @@ provideEmbedConfig({
27
34
  customComponents: computed(() => props.customComponents),
28
35
  customHtmlTags: computed(() => props.customHtmlTags)
29
36
  }, { syncGlobal: !parentEmbedConfig });
37
+ if (import.meta.dev) {
38
+ watchEffect(() => {
39
+ if (!normalizedTelaAgentId.value) {
40
+ ignoredPropsWarningKey.value = null;
41
+ return;
42
+ }
43
+ const ignoredProps = [
44
+ props.workspaceSettings !== void 0 ? "workspaceSettings" : null,
45
+ props.user !== void 0 ? "user" : null
46
+ ].filter((prop) => Boolean(prop));
47
+ const warningKey = ignoredProps.join(",");
48
+ if (ignoredProps.length === 0 || warningKey === ignoredPropsWarningKey.value)
49
+ return;
50
+ ignoredPropsWarningKey.value = warningKey;
51
+ console.warn(
52
+ `[chat-nuxt] telaAgentId is set, so ${ignoredProps.join(", ")} will be ignored.`
53
+ );
54
+ });
55
+ }
30
56
  provideChatAction((payload) => {
31
57
  emit("action", payload);
32
58
  });
33
59
  </script>
34
60
 
35
61
  <template>
36
- <!-- Force a clean state namespace when the workspace changes. -->
37
62
  <ChatEmbedInner
38
63
  v-if="workspaceId"
39
- :key="workspaceId"
64
+ :key="`${workspaceId}:${normalizedTelaAgentId ?? 'default-chat'}`"
40
65
  :conversation-id="conversationId"
41
66
  :initial-conversation-id="initialConversationId"
42
67
  :hide-sidebar="hideSidebar"
43
- :user="user"
68
+ :user="normalizedTelaAgentId ? null : user"
44
69
  :features="features"
45
70
  @update:conversation-id="$emit('update:conversationId', $event)"
46
71
  />
@@ -1,30 +1,10 @@
1
- import type { Component, DeepReadonly } from 'vue';
2
1
  import { type ChatActionPayload } from '../../composables/useChatAction.js';
3
- import type { WorkspaceSettings } from '../../composables/useWorkspaceSettings.js';
4
- import type { ChatLoadingMessageMode } from '../../utils/chat-loading-messages.js';
5
- import type { ChatActor, ChatFeatureConfig } from '../../utils/tela-chat.js';
6
- type EmbedUser = ChatActor;
7
- type __VLS_Props = {
8
- workspaceSettings?: DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null;
9
- conversationId?: string | null;
10
- initialConversationId?: string | null;
11
- hideSidebar?: boolean;
12
- user?: EmbedUser | null;
13
- features?: Partial<ChatFeatureConfig>;
14
- loadingMessages?: readonly string[] | null;
15
- loadingMessagesMode?: ChatLoadingMessageMode | null;
16
- customComponents?: Record<string, Component>;
17
- customHtmlTags?: readonly string[];
18
- };
19
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
2
+ declare const __VLS_export: import("vue").DefineComponent<import("../../types/embed.js").DefaultChatEmbedProps | import("../../types/embed.js").TelaAgentChatEmbedProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
20
3
  "update:conversationId": (value: string | null) => any;
21
4
  action: (payload: ChatActionPayload) => any;
22
- }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
5
+ }, string, import("vue").PublicProps, Readonly<import("../../types/embed.js").DefaultChatEmbedProps | import("../../types/embed.js").TelaAgentChatEmbedProps> & Readonly<{
23
6
  "onUpdate:conversationId"?: ((value: string | null) => any) | undefined;
24
7
  onAction?: ((payload: ChatActionPayload) => any) | undefined;
25
- }>, {
26
- initialConversationId: string | null;
27
- hideSidebar: boolean;
28
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
29
9
  declare const _default: typeof __VLS_export;
30
10
  export default _default;
@@ -21,18 +21,26 @@ const { getMember } = useWorkspaceMembers();
21
21
  const statusToast = useStatusToast();
22
22
  const { conversations, loading: conversationsLoading, fetchConversations, createConversation, deleteConversation, renameConversation, duplicateConversation, updateConversationInList } = useConversations();
23
23
  const { settings: workspaceSettingsState, fetchSettings } = useWorkspaceSettings();
24
- const effectiveWorkspaceSettings = computed(() => embedConfig?.workspaceSettings.value !== void 0 ? embedConfig.workspaceSettings.value : workspaceSettingsState.value);
24
+ const { metadata: telaAgentMetadata, loading: telaAgentMetadataLoading, fetchAgentMetadata } = useTelaAgentMetadata();
25
+ const isTelaAgentMode = computed(() => !!embedConfig?.telaAgentId.value);
26
+ const hasConfiguredTelaAgentInputs = computed(() => embedConfig?.telaAgentInputs?.value !== void 0 && embedConfig?.telaAgentInputs?.value !== null);
27
+ const shouldLoadTelaAgentMetadata = computed(() => isTelaAgentMode.value && !hasConfiguredTelaAgentInputs.value);
28
+ const telaAgentInputSchema = computed(
29
+ () => hasConfiguredTelaAgentInputs.value ? null : isTelaAgentMode.value ? telaAgentMetadata.value?.inputSchema ?? [] : null
30
+ );
31
+ const effectiveWorkspaceSettings = computed(() => {
32
+ if (isTelaAgentMode.value)
33
+ return void 0;
34
+ return embedConfig?.workspaceSettings.value !== void 0 ? embedConfig.workspaceSettings.value : workspaceSettingsState.value;
35
+ });
25
36
  const { closePanel: closeFilesPanel } = useConversationFilesPanel();
37
+ const { isOpen: isPreviewPanelOpen, panelWidth: previewPanelWidth, closePreview } = useFilePreviewPanel();
26
38
  const activeConversationId = ref(
27
39
  normalizeConversationId(props.conversationId) ?? normalizeConversationId(props.initialConversationId)
28
40
  );
29
41
  const loadingConversationId = ref(null);
30
42
  const isReady = ref(false);
31
- const moduleFeatures = useChatNuxtFeatures();
32
- const resolvedFeatures = computed(() => resolveChatFeatures({
33
- showUsageTab: moduleFeatures.usage ?? props.features?.showUsageTab,
34
- showDebugOption: props.features?.showDebugOption
35
- }));
43
+ const resolvedFeatures = computed(() => resolveChatFeatures(props.features));
36
44
  const dropZoneRef = ref(null);
37
45
  const activeTab = ref("chat");
38
46
  const messageInputRef = ref(null);
@@ -70,6 +78,8 @@ const conversationIdRef = computed(() => currentConversation.value?.id ?? null);
70
78
  const { total, files: conversationFiles } = useConversationFiles(conversationIdRef);
71
79
  const filesCount = computed(() => total.value);
72
80
  const hasMessages = computed(() => messages.value.length > 0);
81
+ const visibleTelaAgentInputSchema = computed(() => !hasMessages.value ? telaAgentInputSchema.value : null);
82
+ const visibleTelaAgentInputSchemaLoading = computed(() => !hasMessages.value && shouldLoadTelaAgentMetadata.value && telaAgentMetadataLoading.value);
73
83
  const visibleConversations = computed(
74
84
  () => conversations.value.filter((c) => c.title || c.id === activeConversationId.value)
75
85
  );
@@ -110,6 +120,7 @@ function resetConversation(shouldEmit = true) {
110
120
  clearConversation();
111
121
  activeTab.value = "chat";
112
122
  closeFilesPanel();
123
+ closePreview();
113
124
  if (shouldEmit) {
114
125
  updateConversationId(null);
115
126
  } else {
@@ -121,6 +132,9 @@ async function openConversation(nextConversationId) {
121
132
  if (!normalizedConversationId) {
122
133
  return;
123
134
  }
135
+ if (activeConversationId.value !== normalizedConversationId) {
136
+ closePreview();
137
+ }
124
138
  updateConversationId(normalizedConversationId);
125
139
  await ensureConversationLoaded(normalizedConversationId);
126
140
  }
@@ -141,11 +155,14 @@ watch(() => props.conversationId, async (nextConversationId) => {
141
155
  return;
142
156
  }
143
157
  syncConversationId(normalizedConversationId);
158
+ closePreview();
144
159
  await ensureConversationLoaded(normalizedConversationId);
145
160
  });
146
161
  onMounted(async () => {
147
162
  void fetchConversations();
148
- if (!effectiveWorkspaceSettings.value) {
163
+ if (shouldLoadTelaAgentMetadata.value) {
164
+ void fetchAgentMetadata();
165
+ } else if (!effectiveWorkspaceSettings.value) {
149
166
  void fetchSettings();
150
167
  }
151
168
  isReady.value = true;
@@ -227,12 +244,10 @@ const conversationCreator = computed(
227
244
  getMember
228
245
  })
229
246
  );
230
- async function handleSend(content, files, model) {
247
+ async function handleSend(content, files, model, agentInputs) {
231
248
  let createdConversationId = null;
232
249
  if (!activeConversationId.value || !currentConversation.value) {
233
- const conversation = await createConversation({
234
- model: model ?? selectedModel.value
235
- });
250
+ const conversation = await createConversation(isTelaAgentMode.value ? void 0 : { model: model ?? selectedModel.value });
236
251
  if (!conversation)
237
252
  return;
238
253
  setConversation(conversation);
@@ -240,7 +255,7 @@ async function handleSend(content, files, model) {
240
255
  }
241
256
  if (!currentConversation.value)
242
257
  return;
243
- const sendPromise = sendMessage(content, files.length > 0 ? files : void 0, model);
258
+ const sendPromise = sendMessage(content, files.length > 0 ? files : void 0, model, agentInputs);
244
259
  if (createdConversationId) {
245
260
  updateConversationId(createdConversationId);
246
261
  }
@@ -473,6 +488,11 @@ async function handleDelete() {
473
488
  <ChatMessageInput
474
489
  v-model:model="selectedModel"
475
490
  :disabled="true"
491
+ :allow-model-selection="!isTelaAgentMode"
492
+ :agent-input-schema="visibleTelaAgentInputSchema"
493
+ :agent-input-schema-loading="visibleTelaAgentInputSchemaLoading"
494
+ :show-model-selector="resolvedFeatures.showModelSelector"
495
+ :show-cancel-button="resolvedFeatures.showCancelButton"
476
496
  />
477
497
  </template>
478
498
 
@@ -500,6 +520,11 @@ async function handleDelete() {
500
520
  :messages="messages"
501
521
  :conversation-files="conversationFiles"
502
522
  :workspace-settings="effectiveWorkspaceSettings"
523
+ :allow-model-selection="!isTelaAgentMode"
524
+ :agent-input-schema="visibleTelaAgentInputSchema"
525
+ :agent-input-schema-loading="visibleTelaAgentInputSchemaLoading"
526
+ :show-model-selector="resolvedFeatures.showModelSelector"
527
+ :show-cancel-button="resolvedFeatures.showCancelButton"
503
528
  centered
504
529
  @send="handleSend"
505
530
  @cancel="cancelConversation"
@@ -523,6 +548,11 @@ async function handleDelete() {
523
548
  :messages="messages"
524
549
  :conversation-files="conversationFiles"
525
550
  :workspace-settings="effectiveWorkspaceSettings"
551
+ :allow-model-selection="!isTelaAgentMode"
552
+ :agent-input-schema="visibleTelaAgentInputSchema"
553
+ :agent-input-schema-loading="visibleTelaAgentInputSchemaLoading"
554
+ :show-model-selector="resolvedFeatures.showModelSelector"
555
+ :show-cancel-button="resolvedFeatures.showCancelButton"
526
556
  has-disclaimer
527
557
  @send="handleSend"
528
558
  @cancel="cancelConversation"
@@ -616,6 +646,14 @@ async function handleDelete() {
616
646
  </div>
617
647
  </TelaModal>
618
648
  </div>
649
+
650
+ <div
651
+ v-if="isPreviewPanelOpen"
652
+ h-full flex-shrink-0 pt-64px
653
+ :style="{ width: `${previewPanelWidth}px` }"
654
+ >
655
+ <FilePreviewPanel />
656
+ </div>
619
657
  </div>
620
658
  </template>
621
659
 
@@ -1,2 +1,2 @@
1
- declare const _default: any;
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
2
  export default _default;
@@ -1,4 +1,4 @@
1
- import { defineNuxtPlugin } from "#app";
1
+ import { defineNuxtPlugin } from "nuxt/app";
2
2
  import { setDefaultMathOptions } from "markstream-vue";
3
3
  export default defineNuxtPlugin(() => {
4
4
  setDefaultMathOptions({ strictDelimiters: true });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import { defineEventHandler, readBody } from "h3";
2
+ import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
3
+ import { persistWorkspaceSettingsUpdate } from "#chat-runtime/server/utils/workspace-settings-update";
4
+ export default defineEventHandler(async (event) => {
5
+ const context = resolveChatContext(event);
6
+ const body = await readBody(event);
7
+ return persistWorkspaceSettingsUpdate(context.workspaceId, context.user, body);
8
+ });
@@ -1,5 +1,5 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ previousStatus?: string | undefined;
2
3
  success: boolean;
3
- previousStatus: any;
4
4
  }>>;
5
5
  export default _default;
@@ -1,11 +1,13 @@
1
1
  import { createError, defineEventHandler, getRouterParam } from "h3";
2
2
  import { eq, and } from "drizzle-orm";
3
3
  import { useDb, schema } from "#chat-runtime/server/db";
4
- import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
5
6
  import { getAgentDataToken, cancelSession } from "#chat-runtime/server/utils/agent-api";
7
+ import { endTelaAgentSession } from "#chat-runtime/server/utils/tela-agent-api";
6
8
  import { logger } from "#chat-runtime/server/utils/logger";
7
9
  export default defineEventHandler(async (event) => {
8
- const context = resolveChatContext(event);
10
+ const context = resolveChatRuntimeContext(event);
9
11
  const db = useDb();
10
12
  const id = getRouterParam(event, "id");
11
13
  if (!id) {
@@ -14,12 +16,7 @@ export default defineEventHandler(async (event) => {
14
16
  statusMessage: "Conversation ID is required"
15
17
  });
16
18
  }
17
- const [conversation] = await db.select().from(schema.conversations).where(
18
- and(
19
- eq(schema.conversations.id, id),
20
- eq(schema.conversations.workspaceId, context.workspaceId)
21
- )
22
- );
19
+ const [conversation] = await db.select().from(schema.conversations).where(conversationScopeConditions(context, id));
23
20
  if (!conversation) {
24
21
  throw createError({
25
22
  statusCode: 404,
@@ -32,14 +29,34 @@ export default defineEventHandler(async (event) => {
32
29
  statusMessage: "No active session to cancel"
33
30
  });
34
31
  }
35
- const token = getAgentDataToken(event);
36
32
  logger.info({ conversationId: id, sessionId: conversation.threadSessionId }, "Session cancellation requested");
37
- const result = await cancelSession(token, conversation.threadSessionId);
38
- if (!result.success) {
39
- throw createError({
40
- statusCode: 500,
41
- statusMessage: result.error
42
- });
33
+ let previousStatus;
34
+ if (conversation.telaAgentId) {
35
+ try {
36
+ const result = await endTelaAgentSession(event, conversation.threadSessionId);
37
+ if (!result.success) {
38
+ logger.warn({
39
+ conversationId: id,
40
+ sessionId: conversation.threadSessionId,
41
+ error: result.error
42
+ }, "Tela agent session cancellation failed while cancelling conversation");
43
+ }
44
+ } catch (error) {
45
+ logger.warn({
46
+ conversationId: id,
47
+ sessionId: conversation.threadSessionId,
48
+ error
49
+ }, "Tela agent session cancellation threw while cancelling conversation");
50
+ }
51
+ } else {
52
+ const result = await cancelSession(getAgentDataToken(event), conversation.threadSessionId);
53
+ if (!result.success) {
54
+ throw createError({
55
+ statusCode: 500,
56
+ statusMessage: result.error
57
+ });
58
+ }
59
+ previousStatus = result.previousStatus;
43
60
  }
44
61
  await db.update(schema.messages).set({
45
62
  status: "completed",
@@ -51,9 +68,12 @@ export default defineEventHandler(async (event) => {
51
68
  eq(schema.messages.status, "pending")
52
69
  )
53
70
  );
54
- logger.info({ conversationId: id, previousStatus: result.previousStatus }, "Session cancelled");
71
+ logger.info({
72
+ conversationId: id,
73
+ ...previousStatus ? { previousStatus } : {}
74
+ }, "Session cancelled");
55
75
  return {
56
76
  success: true,
57
- previousStatus: result.previousStatus
77
+ ...previousStatus ? { previousStatus } : {}
58
78
  };
59
79
  });
@@ -1,11 +1,13 @@
1
1
  import { createError, defineEventHandler, getRouterParam } from "h3";
2
- import { eq, and } from "drizzle-orm";
2
+ import { eq } from "drizzle-orm";
3
3
  import { useDb, schema } from "#chat-runtime/server/db";
4
- import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
5
6
  import { getWorkspaceSettingsUpdatedAt, resolveWorkspaceSettings, serializeResolvedWorkspaceSettings } from "#chat-runtime/server/utils/chat-workspace-settings";
7
+ import { endTelaAgentSession } from "#chat-runtime/server/utils/tela-agent-api";
6
8
  import { logger } from "#chat-runtime/server/utils/logger";
7
9
  export default defineEventHandler(async (event) => {
8
- const context = resolveChatContext(event);
10
+ const context = resolveChatRuntimeContext(event);
9
11
  const db = useDb();
10
12
  const id = getRouterParam(event, "id");
11
13
  if (!id) {
@@ -14,26 +16,39 @@ export default defineEventHandler(async (event) => {
14
16
  statusMessage: "Conversation ID is required"
15
17
  });
16
18
  }
17
- const [conversation] = await db.select().from(schema.conversations).where(
18
- and(
19
- eq(schema.conversations.id, id),
20
- eq(schema.conversations.workspaceId, context.workspaceId)
21
- )
22
- ).limit(1);
19
+ const [conversation] = await db.select().from(schema.conversations).where(conversationScopeConditions(context, id)).limit(1);
23
20
  if (!conversation) {
24
21
  throw createError({
25
22
  statusCode: 404,
26
23
  statusMessage: "Conversation not found"
27
24
  });
28
25
  }
29
- const trustedSettings = await resolveWorkspaceSettings(event, context, db);
26
+ const trustedSettings = conversation.telaAgentId ? null : await resolveWorkspaceSettings(event, context, db);
27
+ if (conversation.telaAgentId && conversation.threadSessionId) {
28
+ try {
29
+ const result = await endTelaAgentSession(event, conversation.threadSessionId);
30
+ if (!result.success) {
31
+ logger.warn({
32
+ conversationId: id,
33
+ sessionId: conversation.threadSessionId,
34
+ error: result.error
35
+ }, "Tela agent session cleanup failed while clearing conversation");
36
+ }
37
+ } catch (error) {
38
+ logger.warn({
39
+ conversationId: id,
40
+ sessionId: conversation.threadSessionId,
41
+ error
42
+ }, "Tela agent session cleanup threw while clearing conversation");
43
+ }
44
+ }
30
45
  await db.delete(schema.messages).where(eq(schema.messages.conversationId, id));
31
46
  const [updated] = await db.update(schema.conversations).set({
32
47
  threadSessionId: null,
33
- appliedSettingsAt: getWorkspaceSettingsUpdatedAt(trustedSettings),
34
- appliedSettingsSnapshot: serializeResolvedWorkspaceSettings(trustedSettings),
48
+ appliedSettingsAt: trustedSettings ? getWorkspaceSettingsUpdatedAt(trustedSettings) : null,
49
+ appliedSettingsSnapshot: trustedSettings ? serializeResolvedWorkspaceSettings(trustedSettings) : null,
35
50
  updatedAt: /* @__PURE__ */ new Date()
36
- }).where(eq(schema.conversations.id, id)).returning();
51
+ }).where(conversationScopeConditions(context, id)).returning();
37
52
  logger.info({ conversationId: id, workspaceId: context.workspaceId }, "Conversation cleared");
38
53
  return updated;
39
54
  });