@meistrari/chat-nuxt 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "1.2.0",
4
+ "version": "1.2.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -220,10 +220,12 @@ const module$1 = defineNuxtModule({
220
220
  }
221
221
  ensureIconifyPackages(nuxt.options.rootDir);
222
222
  const resolver = createResolver(import.meta.url);
223
- const runtimeDir = resolver.resolve("./runtime");
223
+ const builtRuntimeDir = resolver.resolve("./runtime");
224
+ const sourceRuntimeDir = resolver.resolve("../src/runtime");
225
+ const runtimeDir = nuxt.options.dev && existsSync(sourceRuntimeDir) ? sourceRuntimeDir : builtRuntimeDir;
224
226
  const workspaceSettingsResolverEntry = resolveWorkspaceSettingsResolverEntry(
225
227
  nuxt.options.srcDir,
226
- resolver.resolve("./runtime/internal/workspace-settings-resolver.stub")
228
+ join(runtimeDir, "internal/workspace-settings-resolver.stub")
227
229
  );
228
230
  const telaBuildPath = resolveTelaBuildLayer();
229
231
  const runtimeAliases = resolveRuntimeAliases(telaBuildPath);
@@ -258,18 +260,18 @@ const module$1 = defineNuxtModule({
258
260
  rc.public = rc.public || {};
259
261
  rc.public.agentApiUrl = rc.public.agentApiUrl || process.env.AGENT_API_URL || "";
260
262
  validateRuntimeConfig(rc, options.validateConfig ?? false);
261
- addImportsDir(resolver.resolve("./runtime/composables"));
262
- addImportsDir(resolver.resolve("./runtime/utils"));
263
+ addImportsDir(join(runtimeDir, "composables"));
264
+ addImportsDir(join(runtimeDir, "utils"));
263
265
  addComponent({
264
266
  name: "MeistrariChatEmbed",
265
- filePath: resolver.resolve("./runtime/components/MeistrariChatEmbed.vue"),
267
+ filePath: join(runtimeDir, "components/MeistrariChatEmbed.vue"),
266
268
  priority: 1e3
267
269
  });
268
270
  addComponentsDir({
269
- path: resolver.resolve("./runtime/components")
271
+ path: join(runtimeDir, "components")
270
272
  });
271
273
  addComponentsDir({
272
- path: resolver.resolve("./runtime/embed/components"),
274
+ path: join(runtimeDir, "embed/components"),
273
275
  pathPrefix: false
274
276
  });
275
277
  nuxt.hook("vite:extendConfig", (config, { isServer }) => {
@@ -310,8 +312,9 @@ export default globalThis.ELK;
310
312
  }
311
313
  });
312
314
  });
313
- const serverDir = resolver.resolve("./runtime/server");
314
- const publicFilesDir = resolver.resolve("./runtime/public/files");
315
+ const serverDir = join(runtimeDir, "server");
316
+ const publicAssetsDir = join(runtimeDir, "public/assets");
317
+ const publicFilesDir = join(runtimeDir, "public/files");
315
318
  nuxt.hook("nitro:config", (nitroConfig) => {
316
319
  nitroConfig.scanDirs = nitroConfig.scanDirs || [];
317
320
  nitroConfig.scanDirs.push(serverDir);
@@ -321,6 +324,11 @@ export default globalThis.ELK;
321
324
  "#chat-workspace-settings-resolver": workspaceSettingsResolverEntry
322
325
  };
323
326
  nitroConfig.publicAssets = nitroConfig.publicAssets || [];
327
+ nitroConfig.publicAssets.push({
328
+ dir: publicAssetsDir,
329
+ baseURL: "/chat-assets",
330
+ maxAge: 60 * 60 * 24 * 7
331
+ });
324
332
  nitroConfig.publicAssets.push({
325
333
  dir: publicFilesDir,
326
334
  baseURL: "/chat-files",
@@ -1,6 +1,6 @@
1
1
  import * as Sentry from "@sentry/nuxt";
2
2
  import { exportConversationToMarkdown } from "../utils/export-conversation.js";
3
- import { addFilesToConversation } from "./useConversationFiles.js";
3
+ import { useConversationFileActions } from "./useConversationFiles.js";
4
4
  function getStepKey(step) {
5
5
  if (typeof step === "string") {
6
6
  return `text:${step.slice(0, 100)}`;
@@ -146,6 +146,7 @@ export function useChat() {
146
146
  const chatApi = useChatApi();
147
147
  const embedConfig = useEmbedConfig();
148
148
  const { user: authUser, activeOrganization } = useTelaApplicationAuth();
149
+ const { addFilesToConversation } = useConversationFileActions();
149
150
  const chatScope = computed(() => embedConfig?.workspaceId.value.trim() || activeOrganization.value?.id?.trim() || "default");
150
151
  const currentConversationBuckets = useState("chat-current-conversation", () => ({}));
151
152
  const messageBuckets = useState("chat-messages", () => ({}));
@@ -1,5 +1,8 @@
1
1
  import type { MessageFile, MessageRole } from '../types/chat.js';
2
2
  export declare function addFilesToConversation(conversationId: string, newFiles: MessageFile[], messageId: string, messageRole: MessageRole): void;
3
+ export declare function useConversationFileActions(): {
4
+ addFilesToConversation: (conversationId: string, newFiles: MessageFile[], messageId: string, messageRole: MessageRole) => void;
5
+ };
3
6
  export declare function useConversationFiles(conversationId: Ref<string | null | undefined>): {
4
7
  files: any;
5
8
  total: any;
@@ -1,9 +1,13 @@
1
1
  import { generateFileId } from "../utils/file.js";
2
- const sharedFiles = useState("conversationFiles", () => ({}));
3
- const sharedLoading = useState("conversationFilesLoading", () => ({}));
4
- const sharedError = useState("conversationFilesError", () => ({}));
5
- export function addFilesToConversation(conversationId, newFiles, messageId, messageRole) {
6
- const current = sharedFiles.value[conversationId] ?? [];
2
+ function useConversationFilesState() {
3
+ return {
4
+ files: useState("conversationFiles", () => ({})),
5
+ loading: useState("conversationFilesLoading", () => ({})),
6
+ error: useState("conversationFilesError", () => ({}))
7
+ };
8
+ }
9
+ function addFilesToConversationState(state, conversationId, newFiles, messageId, messageRole) {
10
+ const current = state.files.value[conversationId] ?? [];
7
11
  const filesToAdd = newFiles.filter((f) => !current.some((existing) => existing.url === f.url)).map((f) => ({
8
12
  id: generateFileId(f.url),
9
13
  url: f.url,
@@ -16,26 +20,36 @@ export function addFilesToConversation(conversationId, newFiles, messageId, mess
16
20
  size: f.size
17
21
  }));
18
22
  if (filesToAdd.length > 0) {
19
- sharedFiles.value = {
20
- ...sharedFiles.value,
23
+ state.files.value = {
24
+ ...state.files.value,
21
25
  [conversationId]: [...filesToAdd, ...current]
22
26
  };
23
27
  }
24
28
  }
29
+ export function addFilesToConversation(conversationId, newFiles, messageId, messageRole) {
30
+ addFilesToConversationState(useConversationFilesState(), conversationId, newFiles, messageId, messageRole);
31
+ }
32
+ export function useConversationFileActions() {
33
+ const state = useConversationFilesState();
34
+ return {
35
+ addFilesToConversation: (conversationId, newFiles, messageId, messageRole) => addFilesToConversationState(state, conversationId, newFiles, messageId, messageRole)
36
+ };
37
+ }
25
38
  export function useConversationFiles(conversationId) {
26
39
  const chatApi = useChatApi();
40
+ const state = useConversationFilesState();
27
41
  const files = computed(() => {
28
42
  const id = conversationId.value;
29
- return id ? sharedFiles.value[id] ?? [] : [];
43
+ return id ? state.files.value[id] ?? [] : [];
30
44
  });
31
45
  const total = computed(() => files.value.length);
32
46
  const loading = computed(() => {
33
47
  const id = conversationId.value;
34
- return id ? sharedLoading.value[id] ?? false : false;
48
+ return id ? state.loading.value[id] ?? false : false;
35
49
  });
36
50
  const error = computed(() => {
37
51
  const id = conversationId.value;
38
- return id ? sharedError.value[id] ?? null : null;
52
+ return id ? state.error.value[id] ?? null : null;
39
53
  });
40
54
  let currentFetchId = 0;
41
55
  async function fetchFiles() {
@@ -43,27 +57,27 @@ export function useConversationFiles(conversationId) {
43
57
  if (!id)
44
58
  return;
45
59
  const fetchId = ++currentFetchId;
46
- sharedLoading.value = { ...sharedLoading.value, [id]: true };
47
- sharedError.value = { ...sharedError.value, [id]: null };
60
+ state.loading.value = { ...state.loading.value, [id]: true };
61
+ state.error.value = { ...state.error.value, [id]: null };
48
62
  try {
49
63
  const response = await $fetch(
50
64
  chatApi.path(`/conversations/${id}/files`),
51
65
  chatApi.withChatHeaders()
52
66
  );
53
67
  if (fetchId === currentFetchId) {
54
- sharedFiles.value = { ...sharedFiles.value, [id]: response.files };
68
+ state.files.value = { ...state.files.value, [id]: response.files };
55
69
  }
56
70
  } catch (err) {
57
71
  if (fetchId === currentFetchId) {
58
- sharedError.value = {
59
- ...sharedError.value,
72
+ state.error.value = {
73
+ ...state.error.value,
60
74
  [id]: err instanceof Error ? err.message : "Falha ao buscar arquivos"
61
75
  };
62
- sharedFiles.value = { ...sharedFiles.value, [id]: [] };
76
+ state.files.value = { ...state.files.value, [id]: [] };
63
77
  }
64
78
  } finally {
65
79
  if (fetchId === currentFetchId) {
66
- sharedLoading.value = { ...sharedLoading.value, [id]: false };
80
+ state.loading.value = { ...state.loading.value, [id]: false };
67
81
  }
68
82
  }
69
83
  }
@@ -5,7 +5,9 @@ export declare function useConversations(): {
5
5
  conversations: any;
6
6
  loading: any;
7
7
  error: any;
8
- fetchConversations: () => Promise<void>;
8
+ fetchConversations: (options?: {
9
+ force?: boolean;
10
+ }) => Promise<void>;
9
11
  createConversation: (options?: {
10
12
  model?: ModelOption | null;
11
13
  }) => Promise<Conversation | null>;
@@ -29,6 +29,7 @@ export function useConversations() {
29
29
  const conversationBuckets = useState("conversations", () => ({}));
30
30
  const loadingBuckets = useState("conversations-loading", () => ({}));
31
31
  const errorBuckets = useState("conversations-error", () => ({}));
32
+ const fetchedBuckets = useState("conversations-fetched", () => ({}));
32
33
  const mutationVersionBuckets = useState("conversations-mutation-version", () => ({}));
33
34
  const deletedIdBuckets = useState("conversations-deleted-ids", () => ({}));
34
35
  const mutatedIdBuckets = useState("conversations-mutated-ids", () => ({}));
@@ -87,6 +88,15 @@ export function useConversations() {
87
88
  };
88
89
  }
89
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
+ });
90
100
  function markMutated(id) {
91
101
  mutationVersion.value = mutationVersion.value + 1;
92
102
  if (id) {
@@ -114,7 +124,10 @@ export function useConversations() {
114
124
  return null;
115
125
  return JSON.parse(JSON.stringify(snapshot));
116
126
  }
117
- const fetchConversations = async () => {
127
+ const fetchConversations = async (options = {}) => {
128
+ if (loading.value || hasFetched.value && !options.force) {
129
+ return;
130
+ }
118
131
  loading.value = true;
119
132
  error.value = null;
120
133
  const mutationVersionAtStart = mutationVersion.value;
@@ -137,6 +150,7 @@ export function useConversations() {
137
150
  mutatedConversationIds.value = [];
138
151
  }
139
152
  pruneDeletedConversationIds(data);
153
+ hasFetched.value = true;
140
154
  } catch (err) {
141
155
  const message = err instanceof Error ? err.message : "Erro ao carregar conversas";
142
156
  error.value = message;
@@ -1,5 +1,5 @@
1
- const knowledgeSources = useState("knowledgeSources", () => []);
2
1
  export function useKnowledgeSources() {
2
+ const knowledgeSources = useState("knowledgeSources", () => []);
3
3
  function setKnowledgeSources(sources) {
4
4
  knowledgeSources.value = sources ?? [];
5
5
  }
@@ -1,11 +1,16 @@
1
- const mediaCache = useIDB({
2
- storeName: "vault-media-cache",
3
- version: 2
4
- });
1
+ let mediaCache = null;
2
+ function getMediaCache() {
3
+ mediaCache ??= useIDB({
4
+ storeName: "vault-media-cache",
5
+ version: 2
6
+ });
7
+ return mediaCache;
8
+ }
5
9
  export function useMediaCache() {
10
+ const mediaCache2 = getMediaCache();
6
11
  async function getCached(cacheKey) {
7
12
  try {
8
- const cachedData = await mediaCache.get(cacheKey);
13
+ const cachedData = await mediaCache2.get(cacheKey);
9
14
  if (cachedData)
10
15
  return cachedData;
11
16
  return null;
@@ -15,13 +20,13 @@ export function useMediaCache() {
15
20
  }
16
21
  async function setCache(cacheKey, base64) {
17
22
  try {
18
- await mediaCache.set(cacheKey, base64);
23
+ await mediaCache2.set(cacheKey, base64);
19
24
  } catch {
20
25
  }
21
26
  }
22
27
  async function removeFromCache(cacheKey) {
23
28
  try {
24
- await mediaCache.remove(cacheKey);
29
+ await mediaCache2.remove(cacheKey);
25
30
  } catch {
26
31
  }
27
32
  }
@@ -48,15 +48,11 @@ export function useWorkspaceSettings() {
48
48
  });
49
49
  }
50
50
  function openModal(tab) {
51
- if (embedConfig !== null)
52
- return;
53
51
  if (tab)
54
52
  initialTab.value = tab;
55
53
  isModalOpen.value = true;
56
54
  }
57
55
  function closeModal() {
58
- if (embedConfig !== null)
59
- return;
60
56
  isModalOpen.value = false;
61
57
  initialTab.value = null;
62
58
  }
@@ -140,14 +140,15 @@ watch(() => props.conversationId, async (nextConversationId) => {
140
140
  await ensureConversationLoaded(normalizedConversationId);
141
141
  });
142
142
  onMounted(async () => {
143
- const pendingTasks = [fetchConversations()];
143
+ void fetchConversations();
144
144
  if (!effectiveWorkspaceSettings.value) {
145
- pendingTasks.push(fetchSettings());
145
+ void fetchSettings();
146
146
  }
147
- await Promise.allSettled(pendingTasks);
148
147
  isReady.value = true;
149
148
  if (activeConversationId.value) {
150
149
  await ensureConversationLoaded(activeConversationId.value);
150
+ } else {
151
+ resetConversation(false);
151
152
  }
152
153
  });
153
154
  const MAX_DISMISSED_CHAT_IDS = 100;
@@ -12,7 +12,7 @@ defineProps({
12
12
  gitHubButtonText: { type: String, required: true }
13
13
  });
14
14
  const emit = defineEmits(["update:searchQuery", "update:skillModalOpen", "update:skillRefInput", "removeSkill", "closeSkillModal", "handleAddSkillAndClose", "connectGitHub"]);
15
- const githubIconUrl = "/github.svg";
15
+ const githubIconUrl = "/chat-assets/github.svg";
16
16
  </script>
17
17
 
18
18
  <template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {