@meistrari/chat-nuxt 3.8.0 → 3.9.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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +14 -5
- package/dist/runtime/citations/components/citation-document-panel.vue +40 -16
- package/dist/runtime/citations/components/citation-highlight.d.vue.ts +19 -0
- package/dist/runtime/citations/components/citation-highlight.vue +16 -0
- package/dist/runtime/citations/components/citation-highlight.vue.d.ts +19 -0
- package/dist/runtime/citations/document-highlight.d.ts +1 -0
- package/dist/runtime/citations/document-highlight.js +8 -0
- package/dist/runtime/embed/components/configuration/chat-configuration-knowledge-sources-tab.d.vue.ts +2 -2
- package/dist/runtime/embed/components/configuration/chat-configuration-knowledge-sources-tab.vue.d.ts +2 -2
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.d.vue.ts +2 -2
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue.d.ts +2 -2
- package/dist/runtime/messages/components/reasoning/chat-reasoning-message.vue +22 -266
- package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.vue +2 -3
- package/dist/runtime/messages/tool-registry.d.ts +15 -0
- package/dist/runtime/messages/tool-registry.js +138 -0
- package/package.json +1 -1
- package/dist/runtime/messages/composables/tool-formatting.d.ts +0 -5
- package/dist/runtime/messages/composables/tool-formatting.js +0 -61
- package/dist/runtime/shared/composables/verb-conjugation.d.ts +0 -7
- package/dist/runtime/shared/composables/verb-conjugation.js +0 -269
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, mkdirSync, symlinkSync } from 'node:fs';
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
4
|
import { defineNuxtModule, createResolver, addTemplate, addTypeTemplate, addPlugin, addImportsDir, addComponent, addComponentsDir } from 'nuxt/kit';
|
|
5
|
+
import { TOOL_ICON_SAFELIST } from '../dist/runtime/messages/tool-registry.js';
|
|
5
6
|
export { ChatMessageStatus } from '../dist/runtime/messages/composables/chat-message-terminal.js';
|
|
6
7
|
|
|
7
8
|
const localRequire = createRequire(import.meta.url);
|
|
@@ -253,15 +254,18 @@ function ensureIconifyPackages(consumerRoot) {
|
|
|
253
254
|
}
|
|
254
255
|
}
|
|
255
256
|
}
|
|
257
|
+
function pushIconSafelist(safelist) {
|
|
258
|
+
for (const icon of [...DYNAMIC_ICON_SAFELIST, ...TOOL_ICON_SAFELIST]) {
|
|
259
|
+
if (!safelist.includes(icon)) {
|
|
260
|
+
safelist.push(icon);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
256
264
|
function ensureDynamicIconSafelist(nuxtOptions) {
|
|
257
265
|
const options = nuxtOptions;
|
|
258
266
|
const unocssOptions = options.unocss ||= {};
|
|
259
267
|
const currentSafelist = Array.isArray(unocssOptions.safelist) ? unocssOptions.safelist : unocssOptions.safelist ? [unocssOptions.safelist] : [];
|
|
260
|
-
|
|
261
|
-
if (!currentSafelist.includes(icon)) {
|
|
262
|
-
currentSafelist.push(icon);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
268
|
+
pushIconSafelist(currentSafelist);
|
|
265
269
|
unocssOptions.safelist = currentSafelist;
|
|
266
270
|
}
|
|
267
271
|
function validateRuntimeConfig(runtimeConfig, mode) {
|
|
@@ -308,6 +312,11 @@ const module$1 = defineNuxtModule({
|
|
|
308
312
|
}
|
|
309
313
|
ensureIconifyPackages(nuxt.options.rootDir);
|
|
310
314
|
ensureDynamicIconSafelist(nuxt.options);
|
|
315
|
+
const unocssHookNuxt = nuxt;
|
|
316
|
+
unocssHookNuxt.hook("unocss:config", (config) => {
|
|
317
|
+
const safelist = Array.isArray(config.safelist) ? config.safelist : config.safelist = [];
|
|
318
|
+
pushIconSafelist(safelist);
|
|
319
|
+
});
|
|
311
320
|
const resolver = createResolver(import.meta.url);
|
|
312
321
|
const builtRuntimeDir = resolver.resolve("./runtime");
|
|
313
322
|
const sourceRuntimeDir = resolver.resolve("../src/runtime");
|
|
@@ -2,10 +2,22 @@
|
|
|
2
2
|
import { useMagicKeys } from "@vueuse/core";
|
|
3
3
|
import { useEmbedConfig } from "../../embed/composables/embed-config";
|
|
4
4
|
import { useCitationPanel } from "../composables/citation-panel";
|
|
5
|
-
import { locateTermClientSide, splitContentByOccurrences } from "../document-highlight";
|
|
5
|
+
import { escapeCitationMarkup, locateTermClientSide, splitContentByOccurrences } from "../document-highlight";
|
|
6
|
+
import CitationHighlight from "./citation-highlight.vue";
|
|
6
7
|
const { isOpen, active, closeCitationDocument } = useCitationPanel();
|
|
7
8
|
const embedConfig = useEmbedConfig();
|
|
8
9
|
const config = computed(() => embedConfig?.citations.value);
|
|
10
|
+
const citationHighlightTag = "citation_highlight";
|
|
11
|
+
const markdownComponents = computed(() => ({
|
|
12
|
+
...embedConfig?.customComponents.value ?? {},
|
|
13
|
+
[citationHighlightTag]: CitationHighlight
|
|
14
|
+
}));
|
|
15
|
+
const markdownHtmlTags = computed(() => [
|
|
16
|
+
.../* @__PURE__ */ new Set([
|
|
17
|
+
...embedConfig?.customHtmlTags.value ?? [],
|
|
18
|
+
citationHighlightTag
|
|
19
|
+
])
|
|
20
|
+
]);
|
|
9
21
|
const isLoading = ref(false);
|
|
10
22
|
const loadFailed = ref(false);
|
|
11
23
|
const documentData = ref(null);
|
|
@@ -76,6 +88,13 @@ const targetOccurrence = computed(() => {
|
|
|
76
88
|
const wanted = active.value?.citation.locator?.occurrence ?? 1;
|
|
77
89
|
return Math.min(wanted, totalOccurrences.value);
|
|
78
90
|
});
|
|
91
|
+
const highlightedContent = computed(() => highlightSegments.value.map((segment) => {
|
|
92
|
+
if (segment.occurrence === void 0)
|
|
93
|
+
return escapeCitationMarkup(segment.text, citationHighlightTag, "document");
|
|
94
|
+
const target = segment.occurrence === targetOccurrence.value ? ' target="true"' : "";
|
|
95
|
+
const content = escapeCitationMarkup(segment.text, citationHighlightTag, "highlight");
|
|
96
|
+
return `<${citationHighlightTag} occurrence="${segment.occurrence}"${target}>${content}</${citationHighlightTag}>`;
|
|
97
|
+
}).join(""));
|
|
79
98
|
const termNotFound = computed(() => Boolean(
|
|
80
99
|
!isLoading.value && documentData.value && active.value?.citation.locator?.term && totalOccurrences.value === 0
|
|
81
100
|
));
|
|
@@ -191,22 +210,27 @@ const safeSourceUrl = computed(() => {
|
|
|
191
210
|
<div
|
|
192
211
|
v-else-if="documentData"
|
|
193
212
|
ref="contentEl"
|
|
194
|
-
flex-1 overflow-y-auto
|
|
195
|
-
|
|
213
|
+
flex-1 min-h-0 overflow-y-auto
|
|
214
|
+
bg-muted p-16px
|
|
196
215
|
>
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
216
|
+
<div
|
|
217
|
+
min-h-full bg-white
|
|
218
|
+
b=".5px border-subtle"
|
|
219
|
+
rounded-12px p-24px
|
|
220
|
+
>
|
|
221
|
+
<ClientOnly>
|
|
222
|
+
<AppMarkdownRender
|
|
223
|
+
:content="highlightedContent"
|
|
224
|
+
:custom-components="markdownComponents"
|
|
225
|
+
:custom-html-tags="markdownHtmlTags"
|
|
226
|
+
:batch-rendering="false"
|
|
227
|
+
:max-live-nodes="0"
|
|
228
|
+
:render-code-blocks-as-pre="true"
|
|
229
|
+
:typewriter="false"
|
|
230
|
+
text-neutral-800
|
|
231
|
+
/>
|
|
232
|
+
</ClientOnly>
|
|
233
|
+
</div>
|
|
210
234
|
</div>
|
|
211
235
|
</div>
|
|
212
236
|
</Transition>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CustomMarkdownNode } from '../../rendering/markdown/custom-components.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
node: CustomMarkdownNode;
|
|
4
|
+
occurrence: string;
|
|
5
|
+
target?: boolean | string;
|
|
6
|
+
};
|
|
7
|
+
declare var __VLS_1: {};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
default?: (props: typeof __VLS_1) => any;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
15
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
16
|
+
new (): {
|
|
17
|
+
$slots: S;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
node: { type: Object, required: true },
|
|
4
|
+
occurrence: { type: String, required: true },
|
|
5
|
+
target: { type: [Boolean, String], required: false }
|
|
6
|
+
});
|
|
7
|
+
const isTarget = computed(() => props.target === true || props.target === "true");
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<mark
|
|
12
|
+
:data-occurrence="occurrence"
|
|
13
|
+
rounded-2px
|
|
14
|
+
:class="isTarget ? 'bg-amber-300' : 'bg-amber-100'"
|
|
15
|
+
><slot /></mark>
|
|
16
|
+
</template>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CustomMarkdownNode } from '../../rendering/markdown/custom-components.js';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
node: CustomMarkdownNode;
|
|
4
|
+
occurrence: string;
|
|
5
|
+
target?: boolean | string;
|
|
6
|
+
};
|
|
7
|
+
declare var __VLS_1: {};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
default?: (props: typeof __VLS_1) => any;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
15
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
16
|
+
new (): {
|
|
17
|
+
$slots: S;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -4,6 +4,7 @@ export type HighlightSegment = {
|
|
|
4
4
|
/** 1-based occurrence number when this segment is a highlighted match. */
|
|
5
5
|
occurrence?: number;
|
|
6
6
|
};
|
|
7
|
+
export declare function escapeCitationMarkup(text: string, tagName: string, context: 'document' | 'highlight'): string;
|
|
7
8
|
/**
|
|
8
9
|
* Fallback when the host provides no `locate` callback. Plain case-insensitive matching:
|
|
9
10
|
* accent variants won't match, which degrades to "term not found" rather than breaking.
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export function escapeCitationMarkup(text, tagName, context) {
|
|
2
|
+
if (context === "highlight") {
|
|
3
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
4
|
+
}
|
|
5
|
+
const escapedTagName = tagName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6
|
+
const citationTag = new RegExp(`<\\/?${escapedTagName}(?=[\\s>])`, "gi");
|
|
7
|
+
return text.replace(citationTag, (match) => `<${match.slice(1)}`);
|
|
8
|
+
}
|
|
1
9
|
export function locateTermClientSide(content, term) {
|
|
2
10
|
const needle = term.toLowerCase();
|
|
3
11
|
if (!needle)
|
|
@@ -8,11 +8,11 @@ type __VLS_Props = {
|
|
|
8
8
|
getProjectNameForWorkstation: (w: TelaWorkstation) => string;
|
|
9
9
|
};
|
|
10
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
11
|
-
"update:searchQuery": (value: string) => any;
|
|
12
11
|
toggle: (sourceId: string) => any;
|
|
12
|
+
"update:searchQuery": (value: string) => any;
|
|
13
13
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
-
"onUpdate:searchQuery"?: ((value: string) => any) | undefined;
|
|
15
14
|
onToggle?: ((sourceId: string) => any) | undefined;
|
|
15
|
+
"onUpdate:searchQuery"?: ((value: string) => any) | undefined;
|
|
16
16
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
17
|
declare const _default: typeof __VLS_export;
|
|
18
18
|
export default _default;
|
|
@@ -8,11 +8,11 @@ type __VLS_Props = {
|
|
|
8
8
|
getProjectNameForWorkstation: (w: TelaWorkstation) => string;
|
|
9
9
|
};
|
|
10
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
11
|
-
"update:searchQuery": (value: string) => any;
|
|
12
11
|
toggle: (sourceId: string) => any;
|
|
12
|
+
"update:searchQuery": (value: string) => any;
|
|
13
13
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
-
"onUpdate:searchQuery"?: ((value: string) => any) | undefined;
|
|
15
14
|
onToggle?: ((sourceId: string) => any) | undefined;
|
|
15
|
+
"onUpdate:searchQuery"?: ((value: string) => any) | undefined;
|
|
16
16
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
17
|
declare const _default: typeof __VLS_export;
|
|
18
18
|
export default _default;
|
|
@@ -63,8 +63,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
63
63
|
copyLink: () => any;
|
|
64
64
|
selectConversation: (id: string) => any;
|
|
65
65
|
cancel: () => any;
|
|
66
|
-
settings: () => any;
|
|
67
66
|
send: (content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any;
|
|
67
|
+
settings: () => any;
|
|
68
68
|
debug: () => any;
|
|
69
69
|
tabChange: (tab: TopbarTab) => any;
|
|
70
70
|
newConversation: (groupId?: string | null | undefined) => any;
|
|
@@ -84,8 +84,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
84
84
|
onCopyLink?: (() => any) | undefined;
|
|
85
85
|
onSelectConversation?: ((id: string) => any) | undefined;
|
|
86
86
|
onCancel?: (() => any) | undefined;
|
|
87
|
-
onSettings?: (() => any) | undefined;
|
|
88
87
|
onSend?: ((content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any) | undefined;
|
|
88
|
+
onSettings?: (() => any) | undefined;
|
|
89
89
|
"onUpdate:selectedModel"?: ((value: string | null) => any) | undefined;
|
|
90
90
|
onDebug?: (() => any) | undefined;
|
|
91
91
|
onTabChange?: ((tab: TopbarTab) => any) | undefined;
|
|
@@ -63,8 +63,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
63
63
|
copyLink: () => any;
|
|
64
64
|
selectConversation: (id: string) => any;
|
|
65
65
|
cancel: () => any;
|
|
66
|
-
settings: () => any;
|
|
67
66
|
send: (content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any;
|
|
67
|
+
settings: () => any;
|
|
68
68
|
debug: () => any;
|
|
69
69
|
tabChange: (tab: TopbarTab) => any;
|
|
70
70
|
newConversation: (groupId?: string | null | undefined) => any;
|
|
@@ -84,8 +84,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
84
84
|
onCopyLink?: (() => any) | undefined;
|
|
85
85
|
onSelectConversation?: ((id: string) => any) | undefined;
|
|
86
86
|
onCancel?: (() => any) | undefined;
|
|
87
|
-
onSettings?: (() => any) | undefined;
|
|
88
87
|
onSend?: ((content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any) | undefined;
|
|
88
|
+
onSettings?: (() => any) | undefined;
|
|
89
89
|
"onUpdate:selectedModel"?: ((value: string | null) => any) | undefined;
|
|
90
90
|
onDebug?: (() => any) | undefined;
|
|
91
91
|
onTabChange?: ((tab: TopbarTab) => any) | undefined;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
86
|
-
return props.step.toolUse
|
|
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
|
-
|
|
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
|
-
<!--
|
|
255
|
-
<div v-else-if="step.type === 'tool_group' &&
|
|
256
|
-
<
|
|
257
|
-
:
|
|
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 {
|
|
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
|
|
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
|
+
}
|
package/package.json
CHANGED
|
@@ -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
|
-
};
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
const pt = {
|
|
2
|
-
buscar: { infinitive: "buscar", gerund: "Buscando", past: "Buscou" },
|
|
3
|
-
listar: { infinitive: "listar", gerund: "Listando", past: "Listou" },
|
|
4
|
-
encontrar: { infinitive: "encontrar", gerund: "Encontrando", past: "Encontrou" },
|
|
5
|
-
ler: { infinitive: "ler", gerund: "Lendo", past: "Leu" },
|
|
6
|
-
escrever: { infinitive: "escrever", gerund: "Escrevendo", past: "Escreveu" },
|
|
7
|
-
criar: { infinitive: "criar", gerund: "Criando", past: "Criou" },
|
|
8
|
-
deletar: { infinitive: "deletar", gerund: "Deletando", past: "Deletou" },
|
|
9
|
-
remover: { infinitive: "remover", gerund: "Removendo", past: "Removeu" },
|
|
10
|
-
copiar: { infinitive: "copiar", gerund: "Copiando", past: "Copiou" },
|
|
11
|
-
mover: { infinitive: "mover", gerund: "Movendo", past: "Moveu" },
|
|
12
|
-
executar: { infinitive: "executar", gerund: "Executando", past: "Executou" },
|
|
13
|
-
verificar: { infinitive: "verificar", gerund: "Verificando", past: "Verificou" },
|
|
14
|
-
instalar: { infinitive: "instalar", gerund: "Instalando", past: "Instalou" },
|
|
15
|
-
atualizar: { infinitive: "atualizar", gerund: "Atualizando", past: "Atualizou" },
|
|
16
|
-
construir: { infinitive: "construir", gerund: "Construindo", past: "Construiu" },
|
|
17
|
-
compilar: { infinitive: "compilar", gerund: "Compilando", past: "Compilou" },
|
|
18
|
-
testar: { infinitive: "testar", gerund: "Testando", past: "Testou" },
|
|
19
|
-
iniciar: { infinitive: "iniciar", gerund: "Iniciando", past: "Iniciou" },
|
|
20
|
-
parar: { infinitive: "parar", gerund: "Parando", past: "Parou" },
|
|
21
|
-
reiniciar: { infinitive: "reiniciar", gerund: "Reiniciando", past: "Reiniciou" },
|
|
22
|
-
carregar: { infinitive: "carregar", gerund: "Carregando", past: "Carregou" },
|
|
23
|
-
salvar: { infinitive: "salvar", gerund: "Salvando", past: "Salvou" },
|
|
24
|
-
baixar: { infinitive: "baixar", gerund: "Baixando", past: "Baixou" },
|
|
25
|
-
enviar: { infinitive: "enviar", gerund: "Enviando", past: "Enviou" },
|
|
26
|
-
analisar: { infinitive: "analisar", gerund: "Analisando", past: "Analisou" },
|
|
27
|
-
processar: { infinitive: "processar", gerund: "Processando", past: "Processou" },
|
|
28
|
-
obter: { infinitive: "obter", gerund: "Obtendo", past: "Obteve" },
|
|
29
|
-
definir: { infinitive: "definir", gerund: "Definindo", past: "Definiu" },
|
|
30
|
-
abrir: { infinitive: "abrir", gerund: "Abrindo", past: "Abriu" },
|
|
31
|
-
fechar: { infinitive: "fechar", gerund: "Fechando", past: "Fechou" },
|
|
32
|
-
escanear: { infinitive: "escanear", gerund: "Escaneando", past: "Escaneou" },
|
|
33
|
-
monitorar: { infinitive: "monitorar", gerund: "Monitorando", past: "Monitorou" },
|
|
34
|
-
aguardar: { infinitive: "aguardar", gerund: "Aguardando", past: "Aguardou" },
|
|
35
|
-
procurar: { infinitive: "procurar", gerund: "Procurando", past: "Procurou" },
|
|
36
|
-
explorar: { infinitive: "explorar", gerund: "Explorando", past: "Explorou" },
|
|
37
|
-
modificar: { infinitive: "modificar", gerund: "Modificando", past: "Modificou" },
|
|
38
|
-
alterar: { infinitive: "alterar", gerund: "Alterando", past: "Alterou" },
|
|
39
|
-
adicionar: { infinitive: "adicionar", gerund: "Adicionando", past: "Adicionou" },
|
|
40
|
-
renomear: { infinitive: "renomear", gerund: "Renomeando", past: "Renomeou" },
|
|
41
|
-
configurar: { infinitive: "configurar", gerund: "Configurando", past: "Configurou" },
|
|
42
|
-
preparar: { infinitive: "preparar", gerund: "Preparando", past: "Preparou" },
|
|
43
|
-
exibir: { infinitive: "exibir", gerund: "Exibindo", past: "Exibiu" },
|
|
44
|
-
limpar: { infinitive: "limpar", gerund: "Limpando", past: "Limpou" },
|
|
45
|
-
filtrar: { infinitive: "filtrar", gerund: "Filtrando", past: "Filtrou" },
|
|
46
|
-
ordenar: { infinitive: "ordenar", gerund: "Ordenando", past: "Ordenou" },
|
|
47
|
-
contar: { infinitive: "contar", gerund: "Contando", past: "Contou" },
|
|
48
|
-
comparar: { infinitive: "comparar", gerund: "Comparando", past: "Comparou" },
|
|
49
|
-
extrair: { infinitive: "extrair", gerund: "Extraindo", past: "Extraiu" },
|
|
50
|
-
comprimir: { infinitive: "comprimir", gerund: "Comprimindo", past: "Comprimiu" },
|
|
51
|
-
descomprimir: { infinitive: "descomprimir", gerund: "Descomprimindo", past: "Descomprimiu" },
|
|
52
|
-
consultar: { infinitive: "consultar", gerund: "Consultando", past: "Consultou" },
|
|
53
|
-
navegar: { infinitive: "navegar", gerund: "Navegando", past: "Navegou" },
|
|
54
|
-
trocar: { infinitive: "trocar", gerund: "Trocando", past: "Trocou" },
|
|
55
|
-
gerenciar: { infinitive: "gerenciar", gerund: "Gerenciando", past: "Gerenciou" },
|
|
56
|
-
apagar: { infinitive: "apagar", gerund: "Apagando", past: "Apagou" },
|
|
57
|
-
rodar: { infinitive: "rodar", gerund: "Rodando", past: "Rodou" },
|
|
58
|
-
subir: { infinitive: "subir", gerund: "Subindo", past: "Subiu" },
|
|
59
|
-
fazer: { infinitive: "fazer", gerund: "Fazendo", past: "Fez" }
|
|
60
|
-
};
|
|
61
|
-
function verb(key) {
|
|
62
|
-
return pt[key];
|
|
63
|
-
}
|
|
64
|
-
const englishToPortuguese = {
|
|
65
|
-
search: verb("buscar"),
|
|
66
|
-
searching: verb("buscar"),
|
|
67
|
-
list: verb("listar"),
|
|
68
|
-
listing: verb("listar"),
|
|
69
|
-
find: verb("encontrar"),
|
|
70
|
-
finding: verb("encontrar"),
|
|
71
|
-
read: verb("ler"),
|
|
72
|
-
reading: verb("ler"),
|
|
73
|
-
write: verb("escrever"),
|
|
74
|
-
writing: verb("escrever"),
|
|
75
|
-
create: verb("criar"),
|
|
76
|
-
creating: verb("criar"),
|
|
77
|
-
delete: verb("deletar"),
|
|
78
|
-
deleting: verb("deletar"),
|
|
79
|
-
remove: verb("remover"),
|
|
80
|
-
removing: verb("remover"),
|
|
81
|
-
copy: verb("copiar"),
|
|
82
|
-
copying: verb("copiar"),
|
|
83
|
-
move: verb("mover"),
|
|
84
|
-
moving: verb("mover"),
|
|
85
|
-
execute: verb("executar"),
|
|
86
|
-
executing: verb("executar"),
|
|
87
|
-
run: verb("executar"),
|
|
88
|
-
running: verb("executar"),
|
|
89
|
-
check: verb("verificar"),
|
|
90
|
-
checking: verb("verificar"),
|
|
91
|
-
verify: verb("verificar"),
|
|
92
|
-
verifying: verb("verificar"),
|
|
93
|
-
install: verb("instalar"),
|
|
94
|
-
installing: verb("instalar"),
|
|
95
|
-
update: verb("atualizar"),
|
|
96
|
-
updating: verb("atualizar"),
|
|
97
|
-
build: verb("construir"),
|
|
98
|
-
building: verb("construir"),
|
|
99
|
-
compile: verb("compilar"),
|
|
100
|
-
compiling: verb("compilar"),
|
|
101
|
-
test: verb("testar"),
|
|
102
|
-
testing: verb("testar"),
|
|
103
|
-
start: verb("iniciar"),
|
|
104
|
-
starting: verb("iniciar"),
|
|
105
|
-
stop: verb("parar"),
|
|
106
|
-
stopping: verb("parar"),
|
|
107
|
-
restart: verb("reiniciar"),
|
|
108
|
-
restarting: verb("reiniciar"),
|
|
109
|
-
load: verb("carregar"),
|
|
110
|
-
loading: verb("carregar"),
|
|
111
|
-
save: verb("salvar"),
|
|
112
|
-
saving: verb("salvar"),
|
|
113
|
-
download: verb("baixar"),
|
|
114
|
-
downloading: verb("baixar"),
|
|
115
|
-
upload: verb("enviar"),
|
|
116
|
-
uploading: verb("enviar"),
|
|
117
|
-
analyze: verb("analisar"),
|
|
118
|
-
analyzing: verb("analisar"),
|
|
119
|
-
process: verb("processar"),
|
|
120
|
-
processing: verb("processar"),
|
|
121
|
-
parse: verb("processar"),
|
|
122
|
-
parsing: verb("processar"),
|
|
123
|
-
fetch: verb("buscar"),
|
|
124
|
-
fetching: verb("buscar"),
|
|
125
|
-
get: verb("obter"),
|
|
126
|
-
getting: verb("obter"),
|
|
127
|
-
set: verb("definir"),
|
|
128
|
-
setting: verb("definir"),
|
|
129
|
-
open: verb("abrir"),
|
|
130
|
-
opening: verb("abrir"),
|
|
131
|
-
close: verb("fechar"),
|
|
132
|
-
closing: verb("fechar"),
|
|
133
|
-
scan: verb("escanear"),
|
|
134
|
-
scanning: verb("escanear"),
|
|
135
|
-
monitor: verb("monitorar"),
|
|
136
|
-
monitoring: verb("monitorar"),
|
|
137
|
-
wait: verb("aguardar"),
|
|
138
|
-
waiting: verb("aguardar"),
|
|
139
|
-
look: verb("procurar"),
|
|
140
|
-
looking: verb("procurar"),
|
|
141
|
-
navigate: verb("navegar"),
|
|
142
|
-
navigating: verb("navegar"),
|
|
143
|
-
explore: verb("explorar"),
|
|
144
|
-
exploring: verb("explorar"),
|
|
145
|
-
modify: verb("modificar"),
|
|
146
|
-
modifying: verb("modificar"),
|
|
147
|
-
change: verb("alterar"),
|
|
148
|
-
changing: verb("alterar"),
|
|
149
|
-
add: verb("adicionar"),
|
|
150
|
-
adding: verb("adicionar"),
|
|
151
|
-
rename: verb("renomear"),
|
|
152
|
-
renaming: verb("renomear"),
|
|
153
|
-
configure: verb("configurar"),
|
|
154
|
-
configuring: verb("configurar"),
|
|
155
|
-
prepare: verb("preparar"),
|
|
156
|
-
preparing: verb("preparar"),
|
|
157
|
-
display: verb("exibir"),
|
|
158
|
-
displaying: verb("exibir"),
|
|
159
|
-
show: verb("exibir"),
|
|
160
|
-
showing: verb("exibir"),
|
|
161
|
-
clean: verb("limpar"),
|
|
162
|
-
cleaning: verb("limpar"),
|
|
163
|
-
clear: verb("limpar"),
|
|
164
|
-
clearing: verb("limpar"),
|
|
165
|
-
match: verb("encontrar"),
|
|
166
|
-
matching: verb("encontrar"),
|
|
167
|
-
filter: verb("filtrar"),
|
|
168
|
-
filtering: verb("filtrar"),
|
|
169
|
-
sort: verb("ordenar"),
|
|
170
|
-
sorting: verb("ordenar"),
|
|
171
|
-
count: verb("contar"),
|
|
172
|
-
counting: verb("contar"),
|
|
173
|
-
compare: verb("comparar"),
|
|
174
|
-
comparing: verb("comparar"),
|
|
175
|
-
extract: verb("extrair"),
|
|
176
|
-
extracting: verb("extrair"),
|
|
177
|
-
compress: verb("comprimir"),
|
|
178
|
-
compressing: verb("comprimir"),
|
|
179
|
-
decompress: verb("descomprimir"),
|
|
180
|
-
decompressing: verb("descomprimir")
|
|
181
|
-
};
|
|
182
|
-
const ptValues = Object.values(pt);
|
|
183
|
-
const gerundToPast = new Map(
|
|
184
|
-
ptValues.map((v) => [v.gerund, v.past])
|
|
185
|
-
);
|
|
186
|
-
const infinitiveToPast = new Map(
|
|
187
|
-
ptValues.map((v) => [v.infinitive, v.past])
|
|
188
|
-
);
|
|
189
|
-
const readFileStepLabels = {
|
|
190
|
-
"instructions.md": "instru\xE7\xF5es",
|
|
191
|
-
"output-format.json": "estrutura de sa\xEDda esperada",
|
|
192
|
-
"input-list.json": "lista de arquivos de entrada",
|
|
193
|
-
"result.json": "resultado"
|
|
194
|
-
};
|
|
195
|
-
export function useVerbConjugation() {
|
|
196
|
-
function isEnglish(text) {
|
|
197
|
-
const firstWord = text.trim().split(/\s+/)[0]?.toLowerCase() || "";
|
|
198
|
-
if (firstWord in englishToPortuguese) {
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
const englishPatterns = [
|
|
202
|
-
/^(search|list|find|read|write|create|delete|remove|copy|move|execute|run|check|verify)/i,
|
|
203
|
-
/\s(for|in|from|to|with|at|of|the|a|an)\s/i,
|
|
204
|
-
/files?|director(y|ies)|input|output|data/i
|
|
205
|
-
];
|
|
206
|
-
return englishPatterns.some((pattern) => pattern.test(text));
|
|
207
|
-
}
|
|
208
|
-
function translateEnglishText(text, toPast) {
|
|
209
|
-
const words = text.trim().split(/\s+/);
|
|
210
|
-
const firstWord = words[0]?.toLowerCase();
|
|
211
|
-
if (!firstWord) {
|
|
212
|
-
return text;
|
|
213
|
-
}
|
|
214
|
-
if (firstWord in englishToPortuguese) {
|
|
215
|
-
const verb2 = englishToPortuguese[firstWord];
|
|
216
|
-
if (!verb2) {
|
|
217
|
-
return text;
|
|
218
|
-
}
|
|
219
|
-
const restOfSentence = words.slice(1).join(" ");
|
|
220
|
-
const translatedRest = restOfSentence.replace(/\bfor\b/gi, "por").replace(/\bin\b/gi, "em").replace(/\bfrom\b/gi, "de").replace(/\bto\b/gi, "para").replace(/\bwith\b/gi, "com").replace(/\bfiles?\b/gi, "arquivos").replace(/\bdirector(y|ies)\b/gi, (_match, suffix) => suffix === "ies" ? "diret\xF3rios" : "diret\xF3rio").replace(/\binput\b/gi, "entrada").replace(/\boutput\b/gi, "sa\xEDda").replace(/\bdata\b/gi, "dados");
|
|
221
|
-
const conjugatedVerb = toPast ? verb2.past : verb2.gerund;
|
|
222
|
-
return translatedRest ? `${conjugatedVerb} ${translatedRest}` : conjugatedVerb;
|
|
223
|
-
}
|
|
224
|
-
return text;
|
|
225
|
-
}
|
|
226
|
-
function conjugatePortugueseVerb(text) {
|
|
227
|
-
for (const [gerund, past] of gerundToPast) {
|
|
228
|
-
if (text.startsWith(gerund)) {
|
|
229
|
-
return text.replace(gerund, past);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
for (const [infinitive, past] of infinitiveToPast) {
|
|
233
|
-
const regex = new RegExp(`^${infinitive}(\\s|$)`, "i");
|
|
234
|
-
if (regex.test(text)) {
|
|
235
|
-
return text.replace(regex, `${past}$1`);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
let result = text;
|
|
239
|
-
result = result.replace(/^(\w)(\w*)ando(\s|$)/i, (_, first, rest, space) => `${first.toUpperCase()}${rest}ou${space}`);
|
|
240
|
-
result = result.replace(/^(\w)(\w*)endo(\s|$)/i, (_, first, rest, space) => `${first.toUpperCase()}${rest}eu${space}`);
|
|
241
|
-
result = result.replace(/^(\w)(\w*)indo(\s|$)/i, (_, first, rest, space) => `${first.toUpperCase()}${rest}iu${space}`);
|
|
242
|
-
result = result.replace(/^(\w)(\w*)ar(\s|$)/i, (_, first, rest, space) => `${first.toUpperCase()}${rest}ou${space}`);
|
|
243
|
-
result = result.replace(/^(\w)(\w*)er(\s|$)/i, (_, first, rest, space) => `${first.toUpperCase()}${rest}eu${space}`);
|
|
244
|
-
result = result.replace(/^(\w)(\w*)ir(\s|$)/i, (_, first, rest, space) => `${first.toUpperCase()}${rest}iu${space}`);
|
|
245
|
-
return result;
|
|
246
|
-
}
|
|
247
|
-
function conjugateText(text, wasExecuted) {
|
|
248
|
-
if (!wasExecuted) {
|
|
249
|
-
return text;
|
|
250
|
-
}
|
|
251
|
-
if (isEnglish(text)) {
|
|
252
|
-
return translateEnglishText(text, true);
|
|
253
|
-
}
|
|
254
|
-
return conjugatePortugueseVerb(text);
|
|
255
|
-
}
|
|
256
|
-
function resolveReadFileStepTitle(fileName, wasExecuted) {
|
|
257
|
-
const label = readFileStepLabels[fileName];
|
|
258
|
-
if (!label)
|
|
259
|
-
return null;
|
|
260
|
-
return conjugateText(`Lendo ${label}`, wasExecuted);
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
conjugateText,
|
|
264
|
-
isEnglish,
|
|
265
|
-
translateEnglishText,
|
|
266
|
-
conjugatePortugueseVerb,
|
|
267
|
-
resolveReadFileStepTitle
|
|
268
|
-
};
|
|
269
|
-
}
|