@meistrari/chat-nuxt 1.1.3 → 1.2.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 (68) hide show
  1. package/README.md +70 -4
  2. package/dist/module.d.mts +5 -0
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +74 -27
  5. package/dist/runtime/components/chat/conversation-list.d.vue.ts +1 -0
  6. package/dist/runtime/components/chat/conversation-list.vue +22 -2
  7. package/dist/runtime/components/chat/conversation-list.vue.d.ts +1 -0
  8. package/dist/runtime/components/chat/message-list.d.vue.ts +1 -0
  9. package/dist/runtime/components/chat/message-list.vue +23 -2
  10. package/dist/runtime/components/chat/message-list.vue.d.ts +1 -0
  11. package/dist/runtime/composables/useChat.d.ts +2 -1
  12. package/dist/runtime/composables/useChat.js +32 -3
  13. package/dist/runtime/composables/useChatApi.js +2 -1
  14. package/dist/runtime/composables/useConversations.d.ts +6 -3
  15. package/dist/runtime/composables/useConversations.js +114 -12
  16. package/dist/runtime/composables/useEmbedConfig.d.ts +11 -6
  17. package/dist/runtime/composables/useEmbedConfig.js +35 -7
  18. package/dist/runtime/composables/useIDB.js +4 -0
  19. package/dist/runtime/composables/usePdf.d.ts +840 -1
  20. package/dist/runtime/composables/usePdf.js +21 -3
  21. package/dist/runtime/composables/useWorkspaceContextFiles.d.ts +3 -3
  22. package/dist/runtime/composables/useWorkspaceContextFiles.js +19 -10
  23. package/dist/runtime/composables/useWorkspaceExternalSkills.d.ts +1 -1
  24. package/dist/runtime/composables/useWorkspaceExternalSkills.js +5 -6
  25. package/dist/runtime/composables/useWorkspacePersonalization.d.ts +1 -1
  26. package/dist/runtime/composables/useWorkspacePersonalization.js +4 -5
  27. package/dist/runtime/composables/useWorkspaceSettings.js +11 -12
  28. package/dist/runtime/embed/components/ChatConfigurationModal.d.vue.ts +25 -0
  29. package/dist/runtime/embed/components/ChatConfigurationModal.vue +373 -0
  30. package/dist/runtime/embed/components/ChatConfigurationModal.vue.d.ts +25 -0
  31. package/dist/runtime/embed/components/ChatEmbed.vue +12 -1
  32. package/dist/runtime/embed/components/ChatEmbedInner.vue +35 -19
  33. package/dist/runtime/embed/components/configuration/ChatConfigurationContextFilesTab.d.vue.ts +22 -0
  34. package/dist/runtime/embed/components/configuration/ChatConfigurationContextFilesTab.vue +133 -0
  35. package/dist/runtime/embed/components/configuration/ChatConfigurationContextFilesTab.vue.d.ts +22 -0
  36. package/dist/runtime/embed/components/configuration/ChatConfigurationCredentialsTab.d.vue.ts +10 -0
  37. package/dist/runtime/embed/components/configuration/ChatConfigurationCredentialsTab.vue +220 -0
  38. package/dist/runtime/embed/components/configuration/ChatConfigurationCredentialsTab.vue.d.ts +10 -0
  39. package/dist/runtime/embed/components/configuration/ChatConfigurationExternalSkillsTab.d.vue.ts +32 -0
  40. package/dist/runtime/embed/components/configuration/ChatConfigurationExternalSkillsTab.vue +222 -0
  41. package/dist/runtime/embed/components/configuration/ChatConfigurationExternalSkillsTab.vue.d.ts +32 -0
  42. package/dist/runtime/embed/components/configuration/ChatConfigurationKnowledgeSourcesTab.d.vue.ts +18 -0
  43. package/dist/runtime/embed/components/configuration/ChatConfigurationKnowledgeSourcesTab.vue +142 -0
  44. package/dist/runtime/embed/components/configuration/ChatConfigurationKnowledgeSourcesTab.vue.d.ts +18 -0
  45. package/dist/runtime/embed/components/configuration/ChatConfigurationPersonalizationTab.d.vue.ts +10 -0
  46. package/dist/runtime/embed/components/configuration/ChatConfigurationPersonalizationTab.vue +37 -0
  47. package/dist/runtime/embed/components/configuration/ChatConfigurationPersonalizationTab.vue.d.ts +10 -0
  48. package/dist/runtime/embed/components/configuration/ChatConfigurationTelaToolsTab.d.vue.ts +20 -0
  49. package/dist/runtime/embed/components/configuration/ChatConfigurationTelaToolsTab.vue +146 -0
  50. package/dist/runtime/embed/components/configuration/ChatConfigurationTelaToolsTab.vue.d.ts +20 -0
  51. package/dist/runtime/server/api/conversations/[id]/duplicate.post.js +45 -12
  52. package/dist/runtime/types/chat.d.ts +2 -1
  53. package/dist/runtime/types/workspace-settings.d.ts +3 -0
  54. package/dist/runtime/types/workspace-settings.js +0 -0
  55. package/dist/runtime/utils/conversation-list-skeleton.d.ts +31 -0
  56. package/dist/runtime/utils/conversation-list-skeleton.js +12 -0
  57. package/dist/runtime/utils/file.js +42 -42
  58. package/dist/types.d.mts +2 -0
  59. package/package.json +23 -27
  60. package/dist/runtime/composables/PageNavigation.d.ts +0 -13
  61. package/dist/runtime/composables/PageNavigation.js +0 -18
  62. /package/dist/runtime/components/{pdf-preview.d.vue.ts → pdf-preview.client.d.vue.ts} +0 -0
  63. /package/dist/runtime/components/{pdf-preview.vue → pdf-preview.client.vue} +0 -0
  64. /package/dist/runtime/components/{pdf-preview.vue.d.ts → pdf-preview.client.vue.d.ts} +0 -0
  65. /package/dist/runtime/components/{pdf-viewer.d.vue.ts → pdf-viewer.client.d.vue.ts} +0 -0
  66. /package/dist/runtime/components/{pdf-viewer.vue → pdf-viewer.client.vue} +0 -0
  67. /package/dist/runtime/components/{pdf-viewer.vue.d.ts → pdf-viewer.client.vue.d.ts} +0 -0
  68. /package/dist/runtime/public/{github.svg → assets/github.svg} +0 -0
@@ -1,11 +1,39 @@
1
1
  import * as Sentry from "@sentry/nuxt";
2
+ function sortConversationsByUpdatedAt(conversations) {
3
+ return [...conversations].sort(
4
+ (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
5
+ );
6
+ }
7
+ export function mergeFetchedConversations(fetchedConversations, localConversations, deletedConversationIds = [], locallyMutatedConversationIds = []) {
8
+ const deletedIds = new Set(deletedConversationIds);
9
+ const locallyMutatedIds = new Set(locallyMutatedConversationIds);
10
+ const mergedById = /* @__PURE__ */ new Map();
11
+ for (const conversation of fetchedConversations) {
12
+ if (!deletedIds.has(conversation.id)) {
13
+ mergedById.set(conversation.id, conversation);
14
+ }
15
+ }
16
+ for (const conversation of localConversations) {
17
+ if (!deletedIds.has(conversation.id)) {
18
+ if (!mergedById.has(conversation.id) || locallyMutatedIds.has(conversation.id)) {
19
+ mergedById.set(conversation.id, conversation);
20
+ }
21
+ }
22
+ }
23
+ return sortConversationsByUpdatedAt([...mergedById.values()]);
24
+ }
2
25
  export function useConversations() {
3
26
  const chatApi = useChatApi();
4
27
  const embedConfig = useEmbedConfig();
28
+ const { activeOrganization } = useTelaApplicationAuth();
5
29
  const conversationBuckets = useState("conversations", () => ({}));
6
30
  const loadingBuckets = useState("conversations-loading", () => ({}));
7
31
  const errorBuckets = useState("conversations-error", () => ({}));
8
- const workspaceScope = computed(() => embedConfig?.workspaceId.value.trim() || "default");
32
+ const fetchedBuckets = useState("conversations-fetched", () => ({}));
33
+ const mutationVersionBuckets = useState("conversations-mutation-version", () => ({}));
34
+ const deletedIdBuckets = useState("conversations-deleted-ids", () => ({}));
35
+ const mutatedIdBuckets = useState("conversations-mutated-ids", () => ({}));
36
+ const workspaceScope = computed(() => embedConfig?.workspaceId.value.trim() || activeOrganization.value?.id?.trim() || "default");
9
37
  const conversations = computed({
10
38
  get: () => conversationBuckets.value[workspaceScope.value] ?? [],
11
39
  set: (value) => {
@@ -15,6 +43,33 @@ export function useConversations() {
15
43
  };
16
44
  }
17
45
  });
46
+ const mutationVersion = computed({
47
+ get: () => mutationVersionBuckets.value[workspaceScope.value] ?? 0,
48
+ set: (value) => {
49
+ mutationVersionBuckets.value = {
50
+ ...mutationVersionBuckets.value,
51
+ [workspaceScope.value]: value
52
+ };
53
+ }
54
+ });
55
+ const deletedConversationIds = computed({
56
+ get: () => deletedIdBuckets.value[workspaceScope.value] ?? [],
57
+ set: (value) => {
58
+ deletedIdBuckets.value = {
59
+ ...deletedIdBuckets.value,
60
+ [workspaceScope.value]: value
61
+ };
62
+ }
63
+ });
64
+ const mutatedConversationIds = computed({
65
+ get: () => mutatedIdBuckets.value[workspaceScope.value] ?? [],
66
+ set: (value) => {
67
+ mutatedIdBuckets.value = {
68
+ ...mutatedIdBuckets.value,
69
+ [workspaceScope.value]: value
70
+ };
71
+ }
72
+ });
18
73
  const loading = computed({
19
74
  get: () => loadingBuckets.value[workspaceScope.value] ?? false,
20
75
  set: (value) => {
@@ -33,20 +88,69 @@ export function useConversations() {
33
88
  };
34
89
  }
35
90
  });
91
+ const hasFetched = computed({
92
+ get: () => fetchedBuckets.value[workspaceScope.value] ?? false,
93
+ set: (value) => {
94
+ fetchedBuckets.value = {
95
+ ...fetchedBuckets.value,
96
+ [workspaceScope.value]: value
97
+ };
98
+ }
99
+ });
100
+ function markMutated(id) {
101
+ mutationVersion.value = mutationVersion.value + 1;
102
+ if (id) {
103
+ mutatedConversationIds.value = [.../* @__PURE__ */ new Set([...mutatedConversationIds.value, id])];
104
+ }
105
+ }
106
+ function commitConversations(nextConversations, mutatedId) {
107
+ conversations.value = sortConversationsByUpdatedAt(nextConversations);
108
+ markMutated(mutatedId);
109
+ }
110
+ function addDeletedConversationId(id) {
111
+ deletedConversationIds.value = [.../* @__PURE__ */ new Set([...deletedConversationIds.value, id])];
112
+ markMutated();
113
+ }
114
+ function removeDeletedConversationId(id) {
115
+ deletedConversationIds.value = deletedConversationIds.value.filter((deletedId) => deletedId !== id);
116
+ markMutated();
117
+ }
118
+ function pruneDeletedConversationIds(serverConversations) {
119
+ const returnedIds = new Set(serverConversations.map((conversation) => conversation.id));
120
+ deletedConversationIds.value = deletedConversationIds.value.filter((id) => returnedIds.has(id));
121
+ }
36
122
  function cloneAppliedSettingsSnapshot(snapshot) {
37
123
  if (!snapshot)
38
124
  return null;
39
125
  return JSON.parse(JSON.stringify(snapshot));
40
126
  }
41
- const fetchConversations = async () => {
127
+ const fetchConversations = async (options = {}) => {
128
+ if (loading.value || hasFetched.value && !options.force) {
129
+ return;
130
+ }
42
131
  loading.value = true;
43
132
  error.value = null;
133
+ const mutationVersionAtStart = mutationVersion.value;
44
134
  try {
45
135
  const data = await $fetch(
46
136
  chatApi.path("/conversations"),
47
137
  chatApi.withChatHeaders()
48
138
  );
49
- conversations.value = data;
139
+ const visibleData = data.filter((conversation) => !deletedConversationIds.value.includes(conversation.id));
140
+ if (mutationVersion.value === mutationVersionAtStart) {
141
+ conversations.value = sortConversationsByUpdatedAt(visibleData);
142
+ mutatedConversationIds.value = [];
143
+ } else {
144
+ conversations.value = mergeFetchedConversations(
145
+ visibleData,
146
+ conversations.value,
147
+ deletedConversationIds.value,
148
+ mutatedConversationIds.value
149
+ );
150
+ mutatedConversationIds.value = [];
151
+ }
152
+ pruneDeletedConversationIds(data);
153
+ hasFetched.value = true;
50
154
  } catch (err) {
51
155
  const message = err instanceof Error ? err.message : "Erro ao carregar conversas";
52
156
  error.value = message;
@@ -65,7 +169,7 @@ export function useConversations() {
65
169
  body: options?.model ? { model: options.model } : void 0
66
170
  })
67
171
  );
68
- conversations.value = [conversation, ...conversations.value];
172
+ commitConversations([conversation, ...conversations.value], conversation.id);
69
173
  return conversation;
70
174
  } catch (err) {
71
175
  const message = err instanceof Error ? err.message : "Erro ao criar conversa";
@@ -77,7 +181,8 @@ export function useConversations() {
77
181
  error.value = null;
78
182
  const statusToast = useStatusToast();
79
183
  const deletedConversation = conversations.value.find((c) => c.id === id);
80
- conversations.value = conversations.value.filter((c) => c.id !== id);
184
+ addDeletedConversationId(id);
185
+ commitConversations(conversations.value.filter((c) => c.id !== id), id);
81
186
  try {
82
187
  await $fetch(
83
188
  chatApi.path(`/conversations/${id}`),
@@ -91,10 +196,9 @@ export function useConversations() {
91
196
  });
92
197
  return true;
93
198
  } catch (err) {
199
+ removeDeletedConversationId(id);
94
200
  if (deletedConversation) {
95
- conversations.value = [...conversations.value, deletedConversation].sort(
96
- (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
97
- );
201
+ commitConversations([...conversations.value, deletedConversation], deletedConversation.id);
98
202
  }
99
203
  const message = err instanceof Error ? err.message : "Erro ao deletar conversa";
100
204
  error.value = message;
@@ -122,9 +226,7 @@ export function useConversations() {
122
226
  createdAt: updated.createdAt,
123
227
  updatedAt: updated.updatedAt
124
228
  };
125
- conversations.value = nextConversations.sort(
126
- (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
127
- );
229
+ commitConversations(nextConversations, updated.id);
128
230
  }
129
231
  };
130
232
  const renameConversation = async (id, title) => {
@@ -161,7 +263,7 @@ export function useConversations() {
161
263
  method: "POST"
162
264
  })
163
265
  );
164
- conversations.value = [duplicated, ...conversations.value];
266
+ commitConversations([duplicated, ...conversations.value], duplicated.id);
165
267
  statusToast.update({
166
268
  text: "Conversa duplicada",
167
269
  icon: "i-ph-check"
@@ -1,13 +1,18 @@
1
- import type { DeepReadonly, Ref } from 'vue';
1
+ import type { DeepReadonly, MaybeRefOrGetter, Ref } from 'vue';
2
2
  import type { WorkspaceSettings } from './useWorkspaceSettings.js';
3
3
  export type EmbedConfig = {
4
4
  workspaceId: Ref<string>;
5
5
  workspaceSettings: Ref<DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null | undefined>;
6
6
  hideSidebar: Ref<boolean>;
7
7
  };
8
- export declare function provideEmbedConfig(props: {
9
- workspaceId: string;
10
- workspaceSettings?: DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null;
11
- hideSidebar?: boolean;
12
- }): void;
8
+ type EmbedConfigInput = {
9
+ workspaceId: MaybeRefOrGetter<string>;
10
+ workspaceSettings?: MaybeRefOrGetter<DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null | undefined>;
11
+ hideSidebar?: MaybeRefOrGetter<boolean | undefined>;
12
+ };
13
+ type ProvideEmbedConfigOptions = {
14
+ syncGlobal?: boolean;
15
+ };
16
+ export declare function provideEmbedConfig(input: EmbedConfigInput, options?: ProvideEmbedConfigOptions): void;
13
17
  export declare function useEmbedConfig(): EmbedConfig | null;
18
+ export {};
@@ -1,11 +1,39 @@
1
1
  const EMBED_CONFIG_KEY = "embed-config";
2
- export function provideEmbedConfig(props) {
3
- provide(EMBED_CONFIG_KEY, {
4
- workspaceId: computed(() => props.workspaceId),
5
- workspaceSettings: toRef(props, "workspaceSettings"),
6
- hideSidebar: computed(() => props.hideSidebar ?? true)
7
- });
2
+ function useGlobalEmbedConfigState() {
3
+ return {
4
+ provided: useState("chat-embed-config-provided", () => false),
5
+ workspaceId: useState("chat-embed-config-workspace-id", () => ""),
6
+ workspaceSettings: useState("chat-embed-config-workspace-settings", () => void 0),
7
+ hideSidebar: useState("chat-embed-config-hide-sidebar", () => void 0)
8
+ };
9
+ }
10
+ export function provideEmbedConfig(input, options = {}) {
11
+ const config = {
12
+ workspaceId: computed(() => toValue(input.workspaceId)),
13
+ workspaceSettings: computed(() => toValue(input.workspaceSettings)),
14
+ hideSidebar: computed(() => toValue(input.hideSidebar) ?? true)
15
+ };
16
+ const globalConfig = useGlobalEmbedConfigState();
17
+ if (options.syncGlobal ?? true) {
18
+ watchEffect(() => {
19
+ globalConfig.provided.value = true;
20
+ globalConfig.workspaceId.value = config.workspaceId.value;
21
+ globalConfig.workspaceSettings.value = config.workspaceSettings.value;
22
+ globalConfig.hideSidebar.value = config.hideSidebar.value;
23
+ });
24
+ }
25
+ provide(EMBED_CONFIG_KEY, config);
8
26
  }
9
27
  export function useEmbedConfig() {
10
- return inject(EMBED_CONFIG_KEY, null);
28
+ const injectedConfig = inject(EMBED_CONFIG_KEY, null);
29
+ if (injectedConfig)
30
+ return injectedConfig;
31
+ const globalConfig = useGlobalEmbedConfigState();
32
+ if (!globalConfig.provided.value)
33
+ return null;
34
+ return {
35
+ workspaceId: computed(() => globalConfig.workspaceId.value),
36
+ workspaceSettings: computed(() => globalConfig.workspaceSettings.value),
37
+ hideSidebar: computed(() => globalConfig.hideSidebar.value ?? true)
38
+ };
11
39
  }
@@ -2,6 +2,8 @@ export function useIDB(options) {
2
2
  const { dbName = "tela", storeName, version } = options;
3
3
  let dbInstance = null;
4
4
  async function setup() {
5
+ if (!import.meta.client)
6
+ return null;
5
7
  if (dbInstance)
6
8
  return dbInstance;
7
9
  return new Promise((resolve, reject) => {
@@ -36,6 +38,8 @@ export function useIDB(options) {
36
38
  }
37
39
  async function withStore(mode, callback) {
38
40
  const db = await setup();
41
+ if (!db)
42
+ return null;
39
43
  return new Promise((resolve, reject) => {
40
44
  const transaction = db.transaction(storeName, mode);
41
45
  const store = transaction.objectStore(storeName);