mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-10-22 01:53:33 +00:00
fix(client): friendly labels and correct arg parsing for native tools
Map skill, read_file, create_file, edit_file, set_memory, and delete_memory to localized display names so summaries stop showing raw tool ids, and give the memory tools the Brain icon the Memories panel already uses. read_file and skill rows parse the arg the backend schemas actually emit (path, with file_path as a legacy fallback; skillName) and fall back to a generic noun instead of rendering an empty name in their labels.
This commit is contained in:
parent
a498f0cc5f
commit
fa02825ead
6 changed files with 50 additions and 6 deletions
|
|
@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
|||
import { FileText } from 'lucide-react';
|
||||
import type { TAttachment, PartMetadata } from 'librechat-data-provider';
|
||||
import ProgressText from '~/components/Chat/Messages/Content/ProgressText';
|
||||
import { toolPanelSpacingClassName } from '../disclosure';
|
||||
import useToolCallState from './useToolCallState';
|
||||
import useLazyHighlight from './useLazyHighlight';
|
||||
import CodeWindowHeader from './CodeWindowHeader';
|
||||
|
|
@ -85,7 +86,10 @@ export default function ReadFileCall({
|
|||
onExpand?: () => void;
|
||||
}) {
|
||||
const localize = useLocalize();
|
||||
const filePath = useMemo(() => parseJsonField(args, 'file_path'), [args]);
|
||||
const filePath = useMemo(
|
||||
() => parseJsonField(args, 'path') || parseJsonField(args, 'file_path'),
|
||||
[args],
|
||||
);
|
||||
const intent = useToolCallIntent(args);
|
||||
const fileName = filePath.split('/').pop() || filePath;
|
||||
const lang = useMemo(() => langFromPath(filePath), [filePath]);
|
||||
|
|
@ -130,7 +134,12 @@ export default function ReadFileCall({
|
|||
<div style={expandStyle}>
|
||||
<div className="overflow-hidden" ref={expandRef}>
|
||||
{hasOutput && (
|
||||
<div className="my-2 overflow-hidden rounded-lg border border-border-light bg-surface-secondary">
|
||||
<div
|
||||
className={cn(
|
||||
toolPanelSpacingClassName,
|
||||
'overflow-hidden rounded-lg border border-border-light bg-surface-secondary',
|
||||
)}
|
||||
>
|
||||
<CodeWindowHeader language={fileName} code={output} />
|
||||
<pre className="max-h-[300px] overflow-auto bg-surface-chat p-4 font-mono text-xs dark:bg-surface-primary-alt">
|
||||
<code className={`hljs language-${lang} !whitespace-pre`}>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
|||
import { ScrollText } from 'lucide-react';
|
||||
import type { TAttachment, PartMetadata } from 'librechat-data-provider';
|
||||
import ProgressText from '~/components/Chat/Messages/Content/ProgressText';
|
||||
import { toolPanelSpacingClassName } from '../disclosure';
|
||||
import useToolCallState from './useToolCallState';
|
||||
import { AttachmentGroup } from './Attachment';
|
||||
import parseJsonField from './parseJsonField';
|
||||
|
|
@ -33,14 +34,15 @@ export default function SkillCall({
|
|||
onExpand?: () => void;
|
||||
}) {
|
||||
const localize = useLocalize();
|
||||
const skillName = useMemo(() => parseJsonField(args, 'skillName'), [args]);
|
||||
const parsedSkillName = useMemo(() => parseJsonField(args, 'skillName'), [args]);
|
||||
const skillName = parsedSkillName || localize('com_ui_skill').toLowerCase();
|
||||
const intent = useToolCallIntent(args);
|
||||
|
||||
const { showCode, toggleCode, expandStyle, expandRef, phase, hasOutput } = useToolCallState({
|
||||
initialProgress,
|
||||
isSubmitting,
|
||||
output,
|
||||
hasInput: !!skillName,
|
||||
hasInput: !!parsedSkillName,
|
||||
onExpand,
|
||||
runStepStatus,
|
||||
});
|
||||
|
|
@ -67,14 +69,19 @@ export default function SkillCall({
|
|||
aria-hidden="true"
|
||||
/>
|
||||
}
|
||||
hasInput={!!skillName || hasOutput}
|
||||
hasInput={!!parsedSkillName || hasOutput}
|
||||
isExpanded={showCode}
|
||||
/>
|
||||
</div>
|
||||
<div style={expandStyle}>
|
||||
<div className="overflow-hidden" ref={expandRef}>
|
||||
{hasOutput && (
|
||||
<div className="my-2 overflow-hidden rounded-lg border border-border-light bg-surface-secondary">
|
||||
<div
|
||||
className={cn(
|
||||
toolPanelSpacingClassName,
|
||||
'overflow-hidden rounded-lg border border-border-light bg-surface-secondary',
|
||||
)}
|
||||
>
|
||||
<div className="bg-surface-primary-alt p-4 text-xs dark:bg-transparent">
|
||||
<div className="mb-1.5 text-[10px] font-medium uppercase tracking-wide text-text-secondary">
|
||||
{localize('com_ui_output')}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
FileText,
|
||||
MessageCircleQuestion,
|
||||
ScrollText,
|
||||
Brain,
|
||||
Zap,
|
||||
Wrench,
|
||||
} from 'lucide-react';
|
||||
|
|
@ -30,6 +31,7 @@ export type ToolIconType =
|
|||
| 'read_file'
|
||||
| 'bash_tool'
|
||||
| 'ask_user_question'
|
||||
| 'memory'
|
||||
| 'action'
|
||||
| 'generic';
|
||||
|
||||
|
|
@ -44,6 +46,7 @@ const ICON_MAP: Record<ToolIconType, React.ComponentType<{ className?: string }>
|
|||
read_file: FileText,
|
||||
bash_tool: BashIcon,
|
||||
ask_user_question: MessageCircleQuestion,
|
||||
memory: Brain,
|
||||
action: Zap,
|
||||
generic: Wrench,
|
||||
};
|
||||
|
|
@ -82,6 +85,9 @@ export function getToolIconType(name: string): ToolIconType {
|
|||
if (name === 'ask_user_question') {
|
||||
return 'ask_user_question';
|
||||
}
|
||||
if (name === 'set_memory' || name === 'delete_memory') {
|
||||
return 'memory';
|
||||
}
|
||||
if (name.startsWith(Constants.LC_TRANSFER_TO_)) {
|
||||
return 'agent_handoff';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1621,8 +1621,10 @@
|
|||
"com_ui_more_options": "More options",
|
||||
"com_ui_my_prompts": "My Prompts",
|
||||
"com_ui_my_skills": "My Skills",
|
||||
"com_ui_n_actions_failed": "{{0}} failed",
|
||||
"com_ui_n_files": "{{0}} files",
|
||||
"com_ui_n_files_changed": "{{0}} files changed",
|
||||
"com_ui_n_searches": "{{0}} searches",
|
||||
"com_ui_name": "Name",
|
||||
"com_ui_name_sort": "Sort by Name",
|
||||
"com_ui_navigate_results": "Navigate results",
|
||||
|
|
@ -1689,6 +1691,7 @@
|
|||
"com_ui_omitted": "Omitted",
|
||||
"com_ui_on": "On",
|
||||
"com_ui_one_file_changed": "1 file changed",
|
||||
"com_ui_one_action_failed": "1 failed",
|
||||
"com_ui_open_archived_chat_new_tab_title": "{{title}} (opens in new tab)",
|
||||
"com_ui_open_artifact": "Open artifact",
|
||||
"com_ui_open_as_artifact": "Open as artifact",
|
||||
|
|
@ -1807,6 +1810,7 @@
|
|||
"com_ui_queued_turn_reconciliation_required": "Awaiting reconciliation",
|
||||
"com_ui_quote_selections": "{{0}} selections",
|
||||
"com_ui_quotes_queued": "Quotes added for your next message",
|
||||
"com_ui_ran_n_actions": "Ran {{0}} actions",
|
||||
"com_ui_ran_n_agents": "Ran {{0}} agents",
|
||||
"com_ui_read_aloud": "Read aloud",
|
||||
"com_ui_read_file": "Read {{0}}",
|
||||
|
|
@ -1893,6 +1897,7 @@
|
|||
"com_ui_run_code_error": "There was an error running the code",
|
||||
"com_ui_running": "Running...",
|
||||
"com_ui_running_command": "Running command",
|
||||
"com_ui_running_n_actions": "Running {{0}} actions",
|
||||
"com_ui_running_n_agents": "Running {{0}} agents",
|
||||
"com_ui_sandbox_starting": "Starting sandbox environment",
|
||||
"com_ui_save": "Save",
|
||||
|
|
@ -1981,7 +1986,9 @@
|
|||
"com_ui_search_skills": "Search skills...",
|
||||
"com_ui_search_table": "Search table",
|
||||
"com_ui_search_table_description": "Type to filter results",
|
||||
"com_ui_searched_web_and_files": "Searched web and files",
|
||||
"com_ui_searching_files": "Searching your files",
|
||||
"com_ui_searching_web_and_files": "Searching web and files",
|
||||
"com_ui_seconds": "seconds",
|
||||
"com_ui_secret_key": "Secret Key",
|
||||
"com_ui_select": "Select",
|
||||
|
|
@ -2393,9 +2400,14 @@
|
|||
"com_ui_tool_name_ask_user_question": "Question",
|
||||
"com_ui_tool_name_code": "Code",
|
||||
"com_ui_tool_name_code_analysis": "Code Analysis",
|
||||
"com_ui_tool_name_create_file": "Create File",
|
||||
"com_ui_tool_name_delete_memory": "Delete Memory",
|
||||
"com_ui_tool_name_edit_file": "Edit File",
|
||||
"com_ui_tool_name_file_search": "File Search",
|
||||
"com_ui_tool_name_image_edit": "Image Edit",
|
||||
"com_ui_tool_name_read_file": "Read File",
|
||||
"com_ui_tool_name_image_gen": "Image Generation",
|
||||
"com_ui_tool_name_set_memory": "Save Memory",
|
||||
"com_ui_tool_name_web_search": "Web Search",
|
||||
"com_ui_tool_response_placeholder": "Type a substitute result to return to the agent",
|
||||
"com_ui_tools": "Tools",
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ describe('getToolDisplayLabel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it.each(['set_memory', 'delete_memory'])('returns a friendly memory label for %s', (toolName) => {
|
||||
expect(getToolDisplayLabel(toolName, identityLocalize)).toBe(TOOL_FRIENDLY_NAME_KEYS[toolName]);
|
||||
});
|
||||
|
||||
it('returns the raw name for an unknown native tool', () => {
|
||||
expect(getToolDisplayLabel('custom_tool', identityLocalize)).toBe('custom_tool');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@ export const TOOL_FRIENDLY_NAME_KEYS: Record<string, TranslationKeys> = {
|
|||
code_interpreter: 'com_ui_tool_name_code_analysis',
|
||||
retrieval: 'com_ui_tool_name_file_search',
|
||||
ask_user_question: 'com_ui_tool_name_ask_user_question',
|
||||
create_file: 'com_ui_tool_name_create_file',
|
||||
set_memory: 'com_ui_tool_name_set_memory',
|
||||
edit_file: 'com_ui_tool_name_edit_file',
|
||||
delete_memory: 'com_ui_tool_name_delete_memory',
|
||||
skill: 'com_ui_skill',
|
||||
read_file: 'com_ui_tool_name_read_file',
|
||||
};
|
||||
|
||||
export interface ParsedToolName {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue