@meistrari/chat-nuxt 3.7.0 → 3.9.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 (50) hide show
  1. package/README.md +26 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +4 -3
  4. package/dist/runtime/citations/citation-links.d.ts +32 -0
  5. package/dist/runtime/citations/citation-links.js +56 -0
  6. package/dist/runtime/citations/components/chat-citation.d.vue.ts +9 -0
  7. package/dist/runtime/citations/components/chat-citation.vue +186 -0
  8. package/dist/runtime/citations/components/chat-citation.vue.d.ts +9 -0
  9. package/dist/runtime/citations/components/citation-document-panel.d.vue.ts +3 -0
  10. package/dist/runtime/citations/components/citation-document-panel.vue +241 -0
  11. package/dist/runtime/citations/components/citation-document-panel.vue.d.ts +3 -0
  12. package/dist/runtime/citations/components/citation-highlight.d.vue.ts +19 -0
  13. package/dist/runtime/citations/components/citation-highlight.vue +16 -0
  14. package/dist/runtime/citations/components/citation-highlight.vue.d.ts +19 -0
  15. package/dist/runtime/citations/composables/citation-panel.d.ts +8 -0
  16. package/dist/runtime/citations/composables/citation-panel.js +17 -0
  17. package/dist/runtime/citations/composables/citations.d.ts +17 -0
  18. package/dist/runtime/citations/composables/citations.js +44 -0
  19. package/dist/runtime/citations/document-highlight.d.ts +14 -0
  20. package/dist/runtime/citations/document-highlight.js +43 -0
  21. package/dist/runtime/citations/types.d.ts +57 -0
  22. package/dist/runtime/citations/types.js +0 -0
  23. package/dist/runtime/conversations/components/chat-conversation-list.vue +2 -2
  24. package/dist/runtime/embed/components/chat-embed-inner.vue +15 -0
  25. package/dist/runtime/embed/components/chat-embed.vue +2 -0
  26. package/dist/runtime/embed/components/configuration/chat-configuration-knowledge-sources-tab.d.vue.ts +2 -2
  27. package/dist/runtime/embed/components/configuration/chat-configuration-knowledge-sources-tab.vue.d.ts +2 -2
  28. package/dist/runtime/embed/components/meistrari-chat-embed.vue +3 -0
  29. package/dist/runtime/embed/components/mobile/chat-mobile-drawer.vue +2 -2
  30. package/dist/runtime/embed/components/mobile/chat-mobile-shell.d.vue.ts +2 -2
  31. package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue.d.ts +2 -2
  32. package/dist/runtime/embed/composables/embed-config.d.ts +3 -0
  33. package/dist/runtime/embed/composables/embed-config.js +9 -0
  34. package/dist/runtime/embed/types.d.ts +12 -1
  35. package/dist/runtime/files/components/chat-vault-link.vue +13 -0
  36. package/dist/runtime/files/content-detection.d.ts +9 -1
  37. package/dist/runtime/files/content-detection.js +29 -8
  38. package/dist/runtime/messages/components/chat-message-bubble.vue +7 -3
  39. package/dist/runtime/messages/components/reasoning/chat-reasoning-message.vue +22 -266
  40. package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.vue +2 -3
  41. package/dist/runtime/messages/tool-registry.d.ts +15 -0
  42. package/dist/runtime/messages/tool-registry.js +138 -0
  43. package/dist/runtime/types/citations.d.ts +1 -0
  44. package/dist/runtime/types/citations.js +0 -0
  45. package/dist/runtime/types/embed.d.ts +1 -0
  46. package/package.json +1 -1
  47. package/dist/runtime/messages/composables/tool-formatting.d.ts +0 -5
  48. package/dist/runtime/messages/composables/tool-formatting.js +0 -61
  49. package/dist/runtime/shared/composables/verb-conjugation.d.ts +0 -7
  50. package/dist/runtime/shared/composables/verb-conjugation.js +0 -269
@@ -98,9 +98,9 @@ const contentSegments = computed(() => {
98
98
  const content = displayContent.value;
99
99
  if (!content)
100
100
  return [];
101
- return parseContentWithFiles(content);
101
+ return parseContentWithFiles(content, { detectCitations: Boolean(embedConfig?.citations.value) });
102
102
  });
103
- const hasDetectedFiles = computed(() => contentSegments.value.some((s) => s.type === "file"));
103
+ const hasDetectedFiles = computed(() => contentSegments.value.some((s) => s.type !== "text"));
104
104
  </script>
105
105
 
106
106
  <template>
@@ -258,13 +258,17 @@ const hasDetectedFiles = computed(() => contentSegments.value.some((s) => s.type
258
258
  />
259
259
  </ClientOnly>
260
260
  <ChatFilePreview
261
- v-else
261
+ v-else-if="segment.type === 'file'"
262
262
  :file="segment.file"
263
263
  inline-block
264
264
  align-middle
265
265
  w-full
266
266
  my-4px
267
267
  />
268
+ <ChatCitation
269
+ v-else
270
+ :citation="segment.citation"
271
+ />
268
272
  </template>
269
273
  </div>
270
274
  <ClientOnly v-else>
@@ -1,6 +1,5 @@
1
1
  <script setup>
2
- import { useVerbConjugation } from "../../../shared/composables/verb-conjugation";
3
- import { useWorkspaceSettings } from "../../../workspace/composables/workspace-settings";
2
+ import { resolveToolDisplay, resolveToolTitle } from "../../tool-registry";
4
3
  import ChatBashWidget from "../widgets/chat-bash-widget.vue";
5
4
  import ChatDocSdkWidget from "../widgets/chat-doc-sdk-widget.vue";
6
5
  import ChatGenericToolWidget from "../widgets/chat-generic-tool-widget.vue";
@@ -21,75 +20,21 @@ const props = defineProps({
21
20
  isPreviewMode: { type: Boolean, required: false },
22
21
  completed: { type: Boolean, required: false }
23
22
  });
24
- const { conjugateText, resolveReadFileStepTitle } = useVerbConjugation();
25
- const { settings: workspaceSettings } = useWorkspaceSettings();
26
- const canvasToolNames = computed(() => {
27
- const names = /* @__PURE__ */ new Set();
28
- if (workspaceSettings.value?.canvasTools) {
29
- for (const t of workspaceSettings.value.canvasTools)
30
- names.add(t.name);
31
- }
32
- return names;
33
- });
34
- const isTelaSkill = computed(() => {
35
- if (typeof props.step === "string")
36
- return false;
37
- return props.step.toolUse.name === "Skill";
38
- });
39
- const isDocSdk = computed(() => {
40
- if (typeof props.step === "string")
41
- return false;
42
- if (props.step.toolUse.name !== "Skill")
43
- return false;
44
- const skill = props.step.toolUse.input?.skill;
45
- return typeof skill === "string" && skill.toLowerCase() === "doc-sdk";
46
- });
47
- const isWorkstationQuery = computed(() => {
48
- if (typeof props.step === "string")
49
- return false;
50
- if (props.step.toolUse.name !== "Skill")
51
- return false;
52
- const skill = props.step.toolUse.input?.skill;
53
- return typeof skill === "string" && skill.toLowerCase() === "workstation-query";
54
- });
55
- const isWebSearch = computed(() => {
56
- if (typeof props.step === "string")
57
- return false;
58
- return props.step.toolUse.name === "WebSearch";
59
- });
60
- const isBash = computed(() => {
61
- if (typeof props.step === "string")
62
- return false;
63
- return props.step.toolUse.name === "Bash";
64
- });
65
- const isBashWorkstationQuery = computed(() => {
66
- if (typeof props.step === "string")
67
- return false;
68
- if (props.step.toolUse.name !== "Bash")
69
- return false;
70
- const command = props.step.toolUse.input?.command;
71
- return typeof command === "string" && command.includes("workstation-query");
72
- });
73
- const isWrite = computed(() => {
74
- if (typeof props.step === "string")
75
- return false;
76
- return props.step.toolUse.name === "Write";
77
- });
78
- const isRead = computed(() => {
79
- if (typeof props.step === "string")
80
- return false;
81
- return props.step.toolUse.name === "Read";
82
- });
83
- const isGrep = computed(() => {
23
+ const TOOL_WIDGETS = {
24
+ "web-search": ChatWebSearchWidget,
25
+ "doc-sdk": ChatDocSdkWidget,
26
+ "workstation-query": ChatWorkstationQueryWidget,
27
+ "tela-skill": ChatTelaSkillWidget,
28
+ "bash": ChatBashWidget,
29
+ "write": ChatWriteWidget,
30
+ "read": ChatReadWidget,
31
+ "grep": ChatGrepWidget,
32
+ "generic": ChatGenericToolWidget
33
+ };
34
+ const toolDisplay = computed(() => {
84
35
  if (typeof props.step === "string")
85
- return false;
86
- return props.step.toolUse.name === "Grep";
87
- });
88
- const searchQuery = computed(() => {
89
- if (typeof props.step === "string")
90
- return "";
91
- const query = props.step.toolUse.input?.query;
92
- return typeof query === "string" ? query : "";
36
+ return null;
37
+ return resolveToolDisplay(props.step.toolUse);
93
38
  });
94
39
  const stepWasExecuted = computed(() => {
95
40
  if (typeof props.step === "string") {
@@ -97,55 +42,7 @@ const stepWasExecuted = computed(() => {
97
42
  }
98
43
  return props.step.toolResult !== void 0 && !props.isActive;
99
44
  });
100
- const stepIcon = computed(() => {
101
- if (typeof props.step === "string") {
102
- return "i-ph-brain";
103
- }
104
- const name = props.step.toolUse.name.toLowerCase();
105
- if (name === "websearch") {
106
- return "i-ph-globe";
107
- }
108
- if (name === "skill") {
109
- if (isDocSdk.value)
110
- return "i-ph-file-text";
111
- if (isWorkstationQuery.value)
112
- return "i-ph-database";
113
- return "i-ph-puzzle-piece";
114
- }
115
- if (name.includes("search") || name.includes("grep") || name.includes("find")) {
116
- return "i-ph-magnifying-glass";
117
- }
118
- if (name === "write") {
119
- return "i-ph-file-plus";
120
- }
121
- if (name === "read") {
122
- return "i-ph-file-magnifying-glass";
123
- }
124
- if (name.includes("file") || name.includes("dir")) {
125
- return "i-ph-file-code";
126
- }
127
- if (name === "bash" || name.includes("terminal") || name.includes("cmd")) {
128
- if (isBashWorkstationQuery.value)
129
- return "i-ph-database";
130
- return "i-ph-terminal-window";
131
- }
132
- if (name.includes("browser")) {
133
- return "i-ph-browser";
134
- }
135
- if (name.includes("figma")) {
136
- return "i-ph-figma-logo";
137
- }
138
- if (name.includes("todo")) {
139
- return "i-ph-list-checks";
140
- }
141
- return "i-ph-wrench";
142
- });
143
- const telaSkillName = computed(() => {
144
- if (typeof props.step === "string")
145
- return "";
146
- const skill = props.step.toolUse.input?.skill;
147
- return typeof skill === "string" ? skill : "Canvas";
148
- });
45
+ const stepIcon = computed(() => toolDisplay.value?.icon ?? "i-ph-brain");
149
46
  const stepTitle = computed(() => {
150
47
  if (typeof props.step === "string") {
151
48
  if (stepWasExecuted.value) {
@@ -153,68 +50,7 @@ const stepTitle = computed(() => {
153
50
  }
154
51
  return "Pensando...";
155
52
  }
156
- const name = props.step.toolUse.name;
157
- let title = "";
158
- if (name === "WebSearch") {
159
- const query = searchQuery.value;
160
- const verb = stepWasExecuted.value ? "Buscou" : "Buscando";
161
- title = query.length > 40 ? `${verb}: ${query.slice(0, 40)}...` : `${verb}: ${query}`;
162
- } else if (name === "Skill") {
163
- const verb = stepWasExecuted.value ? "Executou" : "Executando";
164
- if (isDocSdk.value) {
165
- title = stepWasExecuted.value ? "Processou documento" : "Processando documento";
166
- } else if (isWorkstationQuery.value) {
167
- title = stepWasExecuted.value ? "Consultou dados do workstation" : "Consultando dados do workstation";
168
- } else {
169
- const skillLabel = canvasToolNames.value.has(telaSkillName.value) ? "canvas" : "skill";
170
- title = `${verb} ${skillLabel}: ${telaSkillName.value}`;
171
- }
172
- } else if (name === "Bash") {
173
- if (isBashWorkstationQuery.value) {
174
- return "Consultando dados do workstation";
175
- }
176
- const desc = props.step.toolUse.input?.description;
177
- if (typeof desc === "string" && desc.length > 0) {
178
- const truncatedDesc = desc.length > 50 ? `${desc.slice(0, 50)}...` : desc;
179
- title = conjugateText(truncatedDesc, stepWasExecuted.value);
180
- } else {
181
- const verb = stepWasExecuted.value ? "Executou" : "Executando";
182
- title = `${verb} comando no terminal`;
183
- }
184
- } else if (name === "Write") {
185
- const filePath = props.step.toolUse.input?.file_path;
186
- const verb = stepWasExecuted.value ? "Criou" : "Criando";
187
- if (typeof filePath === "string") {
188
- const fileName = filePath.split("/").pop() || "arquivo";
189
- title = `${verb}: ${fileName.length > 40 ? `${fileName.slice(0, 40)}...` : fileName}`;
190
- } else {
191
- title = `${verb} arquivo`;
192
- }
193
- } else if (name === "Read") {
194
- const filePath = props.step.toolUse.input?.file_path;
195
- const verb = stepWasExecuted.value ? "Leu" : "Lendo";
196
- if (typeof filePath === "string") {
197
- const fileName = filePath.split("/").pop() || "arquivo";
198
- const readTitle = resolveReadFileStepTitle(fileName, stepWasExecuted.value);
199
- if (readTitle)
200
- return readTitle;
201
- title = `${verb}: ${fileName.length > 40 ? `${fileName.slice(0, 40)}...` : fileName}`;
202
- } else {
203
- title = `${verb} arquivo`;
204
- }
205
- } else if (name === "Grep") {
206
- const pattern = props.step.toolUse.input?.pattern;
207
- const verb = stepWasExecuted.value ? "Buscou" : "Buscando";
208
- if (typeof pattern === "string") {
209
- title = `${verb}: ${pattern.length > 35 ? `${pattern.slice(0, 35)}...` : pattern}`;
210
- } else {
211
- title = `${verb} no c\xF3digo`;
212
- }
213
- } else {
214
- const verb = stepWasExecuted.value ? "Executou" : "Executando";
215
- title = `${verb} ferramenta: ${name}`;
216
- }
217
- return title;
53
+ return resolveToolTitle(props.step.toolUse, stepWasExecuted.value);
218
54
  });
219
55
  const isTitleSameAsContent = computed(() => {
220
56
  if (typeof props.step !== "string") {
@@ -251,94 +87,14 @@ const isTitleSameAsContent = computed(() => {
251
87
  />
252
88
  </div>
253
89
 
254
- <!-- Web Search Widget -->
255
- <div v-else-if="step.type === 'tool_group' && isWebSearch">
256
- <ChatWebSearchWidget
257
- :tool-use="step.toolUse"
258
- :tool-result="step.toolResult"
259
- :is-active="isActive"
260
- />
261
- </div>
262
-
263
- <!-- Doc SDK Widget -->
264
- <div v-else-if="step.type === 'tool_group' && isDocSdk">
265
- <ChatDocSdkWidget
266
- :tool-use="step.toolUse"
267
- :tool-result="step.toolResult"
268
- :is-active="isActive"
269
- />
270
- </div>
271
-
272
- <!-- Workstation Query Widget -->
273
- <div v-else-if="step.type === 'tool_group' && isWorkstationQuery">
274
- <ChatWorkstationQueryWidget
275
- :tool-use="step.toolUse"
276
- :tool-result="step.toolResult"
277
- :is-active="isActive"
278
- />
279
- </div>
280
-
281
- <!-- Special Tela Skill Widget -->
282
- <div v-else-if="step.type === 'tool_group' && isTelaSkill">
283
- <ChatTelaSkillWidget
284
- :tool-use="step.toolUse"
285
- :tool-result="step.toolResult"
286
- :is-active="isActive"
287
- />
288
- </div>
289
-
290
- <!-- Bash Workstation Query Widget -->
291
- <div v-else-if="step.type === 'tool_group' && isBashWorkstationQuery">
292
- <ChatWorkstationQueryWidget
293
- :tool-use="step.toolUse"
294
- :tool-result="step.toolResult"
295
- :is-active="isActive"
296
- :is-bash-execution="true"
297
- />
298
- </div>
299
-
300
- <!-- Bash/Terminal Widget -->
301
- <div v-else-if="step.type === 'tool_group' && isBash">
302
- <ChatBashWidget
303
- :tool-use="step.toolUse"
304
- :tool-result="step.toolResult"
305
- :is-active="isActive"
306
- />
307
- </div>
308
-
309
- <!-- Write/File Widget -->
310
- <div v-else-if="step.type === 'tool_group' && isWrite">
311
- <ChatWriteWidget
312
- :tool-use="step.toolUse"
313
- :tool-result="step.toolResult"
314
- :is-active="isActive"
315
- />
316
- </div>
317
-
318
- <!-- Read/File Widget -->
319
- <div v-else-if="step.type === 'tool_group' && isRead">
320
- <ChatReadWidget
321
- :tool-use="step.toolUse"
322
- :tool-result="step.toolResult"
323
- :is-active="isActive"
324
- />
325
- </div>
326
-
327
- <!-- Grep/Search Widget -->
328
- <div v-else-if="step.type === 'tool_group' && isGrep">
329
- <ChatGrepWidget
330
- :tool-use="step.toolUse"
331
- :tool-result="step.toolResult"
332
- :is-active="isActive"
333
- />
334
- </div>
335
-
336
- <!-- Generic tool display -->
337
- <div v-else-if="step.type === 'tool_group'">
338
- <ChatGenericToolWidget
90
+ <!-- Tool widget resolved by the registry -->
91
+ <div v-else-if="step.type === 'tool_group' && toolDisplay">
92
+ <component
93
+ :is="TOOL_WIDGETS[toolDisplay.widgetId]"
339
94
  :tool-use="step.toolUse"
340
95
  :tool-result="step.toolResult"
341
96
  :is-active="isActive"
97
+ v-bind="toolDisplay.widgetProps"
342
98
  />
343
99
  </div>
344
100
  </div>
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { useToolFormatting } from "../../composables/tool-formatting";
2
+ import { resolveToolTitle } from "../../tool-registry";
3
3
  import ChatReasoningSteps from "./chat-reasoning-steps.vue";
4
4
  const props = defineProps({
5
5
  reasoningData: { type: Array, required: true },
@@ -22,7 +22,6 @@ const elapsedTime = ref(0);
22
22
  let dotInterval;
23
23
  let timerInterval;
24
24
  const storageKey = computed(() => `reasoning-timer-${new Date(props.createdAt).getTime()}`);
25
- const { getDisplayName } = useToolFormatting();
26
25
  const showGradient = computed(() => !props.completed && !isExpanded.value);
27
26
  const groupedReasoning = computed(() => {
28
27
  if (!props.reasoningData || !Array.isArray(props.reasoningData))
@@ -39,7 +38,7 @@ const currentStepName = computed(() => {
39
38
  return null;
40
39
  const step = lastStep.value;
41
40
  if (step && typeof step !== "string" && step.type === "tool_group") {
42
- return getDisplayName(step.toolUse.name);
41
+ return resolveToolTitle(step.toolUse, false);
43
42
  }
44
43
  if (step && typeof step === "string") {
45
44
  const truncated = step.length > TEXT_TRUNCATE_LENGTH ? `${step.slice(0, TEXT_TRUNCATE_LENGTH)}...` : step;
@@ -0,0 +1,15 @@
1
+ import type { ToolUse } from './reasoning.js';
2
+ export type ToolWidgetId = 'web-search' | 'doc-sdk' | 'workstation-query' | 'tela-skill' | 'bash' | 'write' | 'read' | 'grep' | 'generic';
3
+ export interface ToolLabels {
4
+ active: string;
5
+ executed: string;
6
+ }
7
+ export interface ToolDisplay {
8
+ icon: string;
9
+ widgetId: ToolWidgetId;
10
+ labels?: ToolLabels;
11
+ widgetProps?: Record<string, unknown>;
12
+ }
13
+ export declare const TOOL_ICON_SAFELIST: string[];
14
+ export declare function resolveToolDisplay(toolUse: ToolUse): ToolDisplay;
15
+ export declare function resolveToolTitle(toolUse: ToolUse, wasExecuted: boolean): string;
@@ -0,0 +1,138 @@
1
+ const TOOL_REGISTRY = {
2
+ "WebSearch": {
3
+ icon: "i-ph-globe",
4
+ widgetId: "web-search",
5
+ labels: { active: "Pesquisando na web", executed: "Pesquisou na web" }
6
+ },
7
+ "WebFetch": {
8
+ icon: "i-ph-globe",
9
+ widgetId: "generic",
10
+ labels: { active: "Pesquisando na web", executed: "Pesquisou na web" }
11
+ },
12
+ "Skill:doc-sdk": {
13
+ icon: "i-ph-file-text",
14
+ widgetId: "doc-sdk",
15
+ labels: { active: "Processando documento", executed: "Processou documento" }
16
+ },
17
+ "Skill:workstation-query": {
18
+ icon: "i-ph-database",
19
+ widgetId: "workstation-query",
20
+ labels: { active: "Consultando dados do workstation", executed: "Consultou dados do workstation" }
21
+ },
22
+ "Skill": {
23
+ icon: "i-ph-puzzle-piece",
24
+ widgetId: "tela-skill",
25
+ labels: { active: "Executando skill", executed: "Executou skill" }
26
+ },
27
+ "Bash:workstation-query": {
28
+ icon: "i-ph-database",
29
+ widgetId: "workstation-query",
30
+ widgetProps: { isBashExecution: true },
31
+ labels: { active: "Consultando dados do workstation", executed: "Consultou dados do workstation" }
32
+ },
33
+ "Bash": {
34
+ icon: "i-ph-terminal-window",
35
+ widgetId: "bash",
36
+ labels: { active: "Executando comando", executed: "Executou comando" }
37
+ },
38
+ "Write": {
39
+ icon: "i-ph-file-plus",
40
+ widgetId: "write",
41
+ labels: { active: "Escrevendo arquivo", executed: "Escreveu arquivo" }
42
+ },
43
+ "Read": {
44
+ icon: "i-ph-file-magnifying-glass",
45
+ widgetId: "read",
46
+ labels: { active: "Lendo arquivo", executed: "Leu arquivo" }
47
+ },
48
+ "Edit": {
49
+ icon: "i-ph-pencil-simple",
50
+ widgetId: "generic",
51
+ labels: { active: "Editando arquivo", executed: "Editou arquivo" }
52
+ },
53
+ "Grep": {
54
+ icon: "i-ph-magnifying-glass",
55
+ widgetId: "grep",
56
+ labels: { active: "Buscando no c\xF3digo", executed: "Buscou no c\xF3digo" }
57
+ },
58
+ "Glob": {
59
+ icon: "i-ph-files",
60
+ widgetId: "generic",
61
+ labels: { active: "Buscando arquivos", executed: "Buscou arquivos" }
62
+ },
63
+ "TodoWrite": {
64
+ icon: "i-ph-list-checks",
65
+ widgetId: "generic",
66
+ labels: { active: "Atualizando tarefas", executed: "Atualizou tarefas" }
67
+ },
68
+ "Task": {
69
+ icon: "i-ph-robot",
70
+ widgetId: "generic",
71
+ labels: { active: "Executando tarefa", executed: "Executou tarefa" }
72
+ },
73
+ "Agent": {
74
+ icon: "i-ph-robot",
75
+ widgetId: "generic",
76
+ labels: { active: "Executando agente", executed: "Executou agente" }
77
+ }
78
+ };
79
+ function toolQualifier(toolUse) {
80
+ if (toolUse.name === "Skill") {
81
+ const skill = toolUse.input?.skill;
82
+ return typeof skill === "string" ? skill.toLowerCase() : null;
83
+ }
84
+ if (toolUse.name === "Bash") {
85
+ const command = toolUse.input?.command;
86
+ return typeof command === "string" && command.includes("workstation-query") ? "workstation-query" : null;
87
+ }
88
+ return null;
89
+ }
90
+ function fallbackToolIcon(name) {
91
+ const lowered = name.toLowerCase();
92
+ if (lowered === "websearch")
93
+ return "i-ph-globe";
94
+ if (lowered === "skill")
95
+ return "i-ph-puzzle-piece";
96
+ if (lowered.includes("search") || lowered.includes("grep") || lowered.includes("find"))
97
+ return "i-ph-magnifying-glass";
98
+ if (lowered === "write")
99
+ return "i-ph-file-plus";
100
+ if (lowered === "read")
101
+ return "i-ph-file-magnifying-glass";
102
+ if (lowered.includes("file") || lowered.includes("dir"))
103
+ return "i-ph-file-code";
104
+ if (lowered === "bash" || lowered.includes("terminal") || lowered.includes("cmd"))
105
+ return "i-ph-terminal-window";
106
+ if (lowered.includes("browser"))
107
+ return "i-ph-browser";
108
+ if (lowered.includes("figma"))
109
+ return "i-ph-figma-logo";
110
+ if (lowered.includes("todo"))
111
+ return "i-ph-list-checks";
112
+ return "i-ph-wrench";
113
+ }
114
+ export const TOOL_ICON_SAFELIST = [.../* @__PURE__ */ new Set([
115
+ ...Object.values(TOOL_REGISTRY).map((entry) => entry.icon),
116
+ "i-ph-file-code",
117
+ "i-ph-browser",
118
+ "i-ph-figma-logo",
119
+ "i-ph-wrench"
120
+ ])];
121
+ export function resolveToolDisplay(toolUse) {
122
+ const qualifier = toolQualifier(toolUse);
123
+ if (qualifier) {
124
+ const qualified = TOOL_REGISTRY[`${toolUse.name}:${qualifier}`];
125
+ if (qualified)
126
+ return qualified;
127
+ }
128
+ const entry = TOOL_REGISTRY[toolUse.name];
129
+ if (entry)
130
+ return entry;
131
+ return { icon: fallbackToolIcon(toolUse.name), widgetId: "generic" };
132
+ }
133
+ export function resolveToolTitle(toolUse, wasExecuted) {
134
+ const { labels } = resolveToolDisplay(toolUse);
135
+ if (!labels)
136
+ return toolUse.name;
137
+ return wasExecuted ? labels.executed : labels.active;
138
+ }
@@ -0,0 +1 @@
1
+ export type { ChatCitationsConfig, CitationDocument, CitationLocator, CitationMeta, CitationOccurrence, CitationRef, CitationStatus, } from '../citations/types.js';
File without changes
@@ -1,3 +1,4 @@
1
+ export type { ChatCitationsConfig, CitationMeta, CitationRef, } from '../citations/types.js';
1
2
  export type { ChatFeatureConfig } from '../embed/feature-config.js';
2
3
  export type { ChatActor, ChatEmbedSharedProps, ChatSidebarConfig, DefaultChatEmbedProps, MeistrariChatEmbedProps, TelaAgentChatEmbedProps, } from '../embed/types.js';
3
4
  export type { ChatActionPayload } from '../messages/composables/chat-action.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
- "version": "3.7.0",
3
+ "version": "3.9.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,5 +0,0 @@
1
- export declare function useToolFormatting(): {
2
- formatToolName: (name: string) => string;
3
- getDisplayName: (toolName: string) => string;
4
- toolDisplayNames: Record<string, string>;
5
- };
@@ -1,61 +0,0 @@
1
- const toolDisplayNames = {
2
- WebSearch: "Pesquisando na web",
3
- Skill: "Executando skill",
4
- Bash: "Executando comando",
5
- Write: "Escrevendo arquivo",
6
- Read: "Lendo arquivo",
7
- Grep: "Buscando no c\xF3digo",
8
- Glob: "Buscando arquivos",
9
- Edit: "Editando arquivo",
10
- Task: "Executando tarefa",
11
- TodoWrite: "Atualizando tarefas",
12
- Search: "Buscando",
13
- CodebaseSearch: "Buscando no c\xF3digo",
14
- FileSearch: "Buscando arquivos"
15
- };
16
- const translations = {
17
- Search: "Busca",
18
- Read: "Leitura",
19
- Write: "Escrita",
20
- Edit: "Edi\xE7\xE3o",
21
- File: "Arquivo",
22
- Directory: "Diret\xF3rio",
23
- Code: "C\xF3digo",
24
- Codebase: "C\xF3digo",
25
- Web: "Web",
26
- Bash: "Terminal",
27
- Execute: "Execu\xE7\xE3o",
28
- Run: "Execu\xE7\xE3o",
29
- Task: "Tarefa",
30
- Todo: "Tarefa",
31
- Glob: "Busca",
32
- Grep: "Busca",
33
- Skill: "Skill"
34
- };
35
- const translationRegexes = Object.entries(translations).map(([en, pt]) => ({
36
- regex: new RegExp(`\\b${en}\\b`, "gi"),
37
- replacement: pt
38
- }));
39
- const toolNameCache = /* @__PURE__ */ new Map();
40
- export function useToolFormatting() {
41
- function formatToolName(name) {
42
- if (toolNameCache.has(name)) {
43
- return toolNameCache.get(name);
44
- }
45
- let formatted = name.replace(/_/g, " ");
46
- translationRegexes.forEach(({ regex, replacement }) => {
47
- formatted = formatted.replace(regex, replacement);
48
- });
49
- formatted = formatted.replace(/\b\w/g, (c) => c.toUpperCase());
50
- toolNameCache.set(name, formatted);
51
- return formatted;
52
- }
53
- function getDisplayName(toolName) {
54
- return toolDisplayNames[toolName] || formatToolName(toolName);
55
- }
56
- return {
57
- formatToolName,
58
- getDisplayName,
59
- toolDisplayNames
60
- };
61
- }
@@ -1,7 +0,0 @@
1
- export declare function useVerbConjugation(): {
2
- conjugateText: (text: string, wasExecuted: boolean) => string;
3
- isEnglish: (text: string) => boolean;
4
- translateEnglishText: (text: string, toPast: boolean) => string;
5
- conjugatePortugueseVerb: (text: string) => string;
6
- resolveReadFileStepTitle: (fileName: string, wasExecuted: boolean) => string | null;
7
- };