From 9e50e1a613a4fc52e2d7b7f799eaf24d2acf5696 Mon Sep 17 00:00:00 2001 From: Tobias Garcia Date: Thu, 21 May 2026 14:49:35 +0900 Subject: [PATCH 1/7] feat: add base slash command autocomplete logic --- .../ui/SlashCommandAutocomplete.module.css | 5 ++ .../ui/SlashCommandAutocomplete.tsx | 49 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.module.css create mode 100644 app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.tsx diff --git a/app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.module.css b/app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.module.css new file mode 100644 index 00000000..f81fe5d5 --- /dev/null +++ b/app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.module.css @@ -0,0 +1,5 @@ +.autocomplete { + list-style: none; + padding: 0; + margin: 0; +} \ No newline at end of file diff --git a/app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.tsx b/app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.tsx new file mode 100644 index 00000000..cfbbd49a --- /dev/null +++ b/app/ui_layer/browser/frontend/src/components/ui/SlashCommandAutocomplete.tsx @@ -0,0 +1,49 @@ +import React, { useEffect, useState, createContext, useContext } from 'react' +import { useSettingsWebSocket } from '@/pages/Settings/useSettingsWebSocket'; +import styles from './SlashCommandAutocomplete.module.css'; + +interface SkillConfig { + name: string + description: string + enabled: boolean + user_invocable: boolean + action_sets: string[] + source: string +} + +interface SlashCommandProps { + input: string; +} + +export function SlashCommandAutocomplete({ input }: SlashCommandProps) { + const [skills, setSkills] = useState(['']); + const [query, setQuery] = useState(''); + + const { send, onMessage, isConnected } = useSettingsWebSocket() + useEffect(() => { + if (!isConnected) return; + + const cleanup = onMessage('skill_list', (data: unknown) => { + const d = data as { success: boolean; skills?: SkillConfig[]; total?: number; enabled?: number; error?: string } + if (d.success && d.skills) { + const userInvocable = d.skills.filter(s => s.enabled) + console.log('[SlashCommandAutocomplete] user-invocable skills:', userInvocable) + setSkills(userInvocable.map(s => s.name)) + } + }) + + send('skill_list') + return cleanup + }, [isConnected, send, onMessage]) + + console.log(skills) + if (input && input[0] === '/') return ( +
+
    + {skills.filter(item => item.includes(input.slice(1))).map((item, index) => ( +
  • /{item}
  • + ))} +
+
+ ); +} \ No newline at end of file From 02547555a95ebc19acb57526752488866cdc8f8c Mon Sep 17 00:00:00 2001 From: Tobias Garcia Date: Thu, 21 May 2026 16:32:29 +0900 Subject: [PATCH 2/7] feat: add core logic and ui for slash command autocomplete --- .../src/components/Chat/Chat.module.css | 1 + .../frontend/src/components/Chat/Chat.tsx | 9 ++- .../ui/SlashCommandAutocomplete.module.css | 61 ++++++++++++++++++- .../ui/SlashCommandAutocomplete.tsx | 6 +- .../frontend/src/components/ui/index.ts | 2 + 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/app/ui_layer/browser/frontend/src/components/Chat/Chat.module.css b/app/ui_layer/browser/frontend/src/components/Chat/Chat.module.css index 09c04973..913f5ed6 100644 --- a/app/ui_layer/browser/frontend/src/components/Chat/Chat.module.css +++ b/app/ui_layer/browser/frontend/src/components/Chat/Chat.module.css @@ -185,6 +185,7 @@ min-width: 0; border-radius: var(--radius-md); transition: outline var(--transition-fast), background var(--transition-fast); + position: relative; } .inputWrapperDragOver { diff --git a/app/ui_layer/browser/frontend/src/components/Chat/Chat.tsx b/app/ui_layer/browser/frontend/src/components/Chat/Chat.tsx index 14ea658d..b53835be 100644 --- a/app/ui_layer/browser/frontend/src/components/Chat/Chat.tsx +++ b/app/ui_layer/browser/frontend/src/components/Chat/Chat.tsx @@ -4,7 +4,7 @@ import { Send, Paperclip, X, Loader2, File, AlertCircle, Reply, Mic, MicOff, Che import { useVirtualizer } from '@tanstack/react-virtual' import { useWebSocket } from '../../contexts/WebSocketContext' import { useToast } from '../../contexts/ToastContext' -import { Button, IconButton, StatusIndicator } from '../ui' +import { Button, IconButton, SlashCommandAutocomplete, StatusIndicator } from '../ui' import { useDerivedAgentStatus } from '../../hooks' import { ChatMessageItem } from '../../pages/Chat/ChatMessage' import styles from './Chat.module.css' @@ -625,13 +625,13 @@ export function Chat({ livingUIId, placeholder, emptyMessage }: ChatProps) { )} - + {/* Status bar */}
{status.message}
- + {/* Input area */}
@@ -727,7 +727,7 @@ export function Chat({ livingUIId, placeholder, emptyMessage }: ChatProps) { ))}
)} - +