diff --git a/src/components/views/AllMcpsView.tsx b/src/components/views/AllMcpsView.tsx index 26448cd..d944a4a 100644 --- a/src/components/views/AllMcpsView.tsx +++ b/src/components/views/AllMcpsView.tsx @@ -9,6 +9,7 @@ interface Props { tools: AiTool[] onBack: () => void onSelectMcp: (mcp: McpServer) => void + onAddMcp?: () => void } interface McpVariant extends McpServer { @@ -41,7 +42,7 @@ function buildMcpGroups(tools: AiTool[]): McpGroup[] { return groups.sort((a, b) => a.name.localeCompare(b.name)) } -export default function AllMcpsView({ tools, onSelectMcp }: Props) { +export default function AllMcpsView({ tools, onSelectMcp, onAddMcp }: Props) { const [query, setQuery] = useState('') const { installedTools, selectedTools, toggleTool, allSelected } = useProviderFilter(tools) const groups = useMemo(() => buildMcpGroups(tools), [tools]) @@ -65,8 +66,21 @@ export default function AllMcpsView({ tools, onSelectMcp }: Props) { return (
-
+
{countLabel} + {onAddMcp && ( + + )}
diff --git a/src/components/views/AllSkillsView.tsx b/src/components/views/AllSkillsView.tsx index ceae73e..ba49240 100644 --- a/src/components/views/AllSkillsView.tsx +++ b/src/components/views/AllSkillsView.tsx @@ -9,6 +9,7 @@ interface Props { tools: AiTool[] onBack: () => void onSelectSkill: (skill: Skill) => void + onAddSkill?: () => void } interface SkillVariant extends Skill { @@ -41,7 +42,7 @@ function buildGroups(tools: AiTool[]): SkillGroup[] { return groups.sort((a, b) => a.name.localeCompare(b.name)) } -export default function AllSkillsView({ tools, onSelectSkill }: Props) { +export default function AllSkillsView({ tools, onSelectSkill, onAddSkill }: Props) { const [query, setQuery] = useState('') const { installedTools, selectedTools, toggleTool, allSelected } = useProviderFilter(tools) const groups = useMemo(() => buildGroups(tools), [tools]) @@ -68,8 +69,21 @@ export default function AllSkillsView({ tools, onSelectSkill }: Props) { return (
-
+
{countLabel} + {onAddSkill && ( + + )}
diff --git a/src/components/views/ViewManager.tsx b/src/components/views/ViewManager.tsx index 659f1cd..1c330ed 100644 --- a/src/components/views/ViewManager.tsx +++ b/src/components/views/ViewManager.tsx @@ -27,6 +27,8 @@ export default function ViewManager({ selectMcp, openSkillsPage, openMcpsPage, + openAddSkill, + openAddMcp, goTo, escape, query, @@ -59,7 +61,7 @@ export default function ViewManager({ return ( goTo('llms-list')} + onBack={() => escape()} onCreated={handleFetchTools} /> ) @@ -68,7 +70,7 @@ export default function ViewManager({ return ( goTo('llms-list')} + onBack={() => escape()} onAdded={handleFetchTools} /> ) @@ -88,7 +90,7 @@ export default function ViewManager({ tool={selectedTool} onBack={() => escape()} onSelectSkill={skill => selectSkill(skill, 'skills-list')} - onAddSkill={() => goTo('add-skill')} + onAddSkill={openAddSkill} /> ) } @@ -98,7 +100,7 @@ export default function ViewManager({ tool={selectedTool} onBack={() => escape()} onSelectMcp={mcp => selectMcp(mcp, 'mcps-list')} - onAddMcp={() => goTo('add-mcp')} + onAddMcp={openAddMcp} /> ) } @@ -108,6 +110,7 @@ export default function ViewManager({ tools={tools} onBack={() => escape()} onSelectSkill={skill => selectSkill(skill, 'all-skills-list')} + onAddSkill={openAddSkill} /> ) } @@ -117,6 +120,7 @@ export default function ViewManager({ tools={tools} onBack={() => escape()} onSelectMcp={mcp => selectMcp(mcp, 'all-mcps-list')} + onAddMcp={openAddMcp} /> ) } diff --git a/src/useViewRouter.ts b/src/useViewRouter.ts index d11b436..3cf36a5 100644 --- a/src/useViewRouter.ts +++ b/src/useViewRouter.ts @@ -22,6 +22,8 @@ export interface UseViewRouterResult extends RouterState { selectMcp: (mcp: McpServer, fromView?: View) => void openSkillsPage: () => void openMcpsPage: () => void + openAddSkill: () => void + openAddMcp: () => void goTo: (view: View) => void escape: () => void refreshSelected: (tools: AiTool[]) => void @@ -71,16 +73,21 @@ export function useViewRouter(): UseViewRouterResult { const openMcpsPage = useCallback(() => dispatch({ type: 'OPEN_MCPS_PAGE', fromView: state.view }), [state.view]) + const openAddSkill = useCallback(() => dispatch({ type: 'OPEN_ADD_SKILL', fromView: state.view }), [state.view]) + + const openAddMcp = useCallback(() => dispatch({ type: 'OPEN_ADD_MCP', fromView: state.view }), [state.view]) + const goTo = useCallback((view: View) => dispatch({ type: 'GO_TO', view }), []) const escape = useCallback(() => { const result = escapeTransition( state.view, state.skillBackView, state.mcpBackView, state.selectedTool, state.allSkillsBackView, state.allMcpsBackView, + state.addSkillBackView, state.addMcpBackView, ) if (result.type === 'navigate') dispatch({ type: 'GO_TO', view: result.to }) else invoke('hide_window').catch(() => {}) - }, [state.view, state.skillBackView, state.mcpBackView, state.selectedTool, state.allSkillsBackView, state.allMcpsBackView]) + }, [state.view, state.skillBackView, state.mcpBackView, state.selectedTool, state.allSkillsBackView, state.allMcpsBackView, state.addSkillBackView, state.addMcpBackView]) const refreshSelected = useCallback((tools: AiTool[]) => { dispatch({ type: 'REFRESH_SELECTED', tools }) @@ -96,6 +103,8 @@ export function useViewRouter(): UseViewRouterResult { selectMcp, openSkillsPage, openMcpsPage, + openAddSkill, + openAddMcp, goTo, escape, refreshSelected, diff --git a/src/viewRouter.ts b/src/viewRouter.ts index e46e93a..fb32d94 100644 --- a/src/viewRouter.ts +++ b/src/viewRouter.ts @@ -53,6 +53,8 @@ export interface RouterState { mcpBackView: View allSkillsBackView: View allMcpsBackView: View + addSkillBackView: View + addMcpBackView: View } export type RouterAction = @@ -66,6 +68,8 @@ export type RouterAction = | { type: 'OPEN_SKILLS_PAGE'; fromView: View } | { type: 'OPEN_MCPS_PAGE'; fromView: View } | { type: 'GO_TO'; view: View } + | { type: 'OPEN_ADD_SKILL'; fromView: View } + | { type: 'OPEN_ADD_MCP'; fromView: View } | { type: 'REFRESH_SELECTED'; tools: AiTool[] } export type EscapeResult = @@ -79,6 +83,8 @@ export function escapeTransition( selectedTool: AiTool | null, allSkillsBackView: View, allMcpsBackView: View, + addSkillBackView: View = 'all-skills-list', + addMcpBackView: View = 'all-mcps-list', ): EscapeResult { if (view === 'skill-detail') return { type: 'navigate', to: skillBackView } if (view === 'mcp-detail') return { type: 'navigate', to: mcpBackView } @@ -88,8 +94,8 @@ export function escapeTransition( if (view === 'skills-list') return { type: 'navigate', to: 'tool-detail' } if (view === 'mcps-list') return { type: 'navigate', to: 'tool-detail' } if (view === 'tool-detail') return { type: 'navigate', to: 'llms-list' } - if (view === 'add-skill') return { type: 'navigate', to: 'llms-list' } - if (view === 'add-mcp') return { type: 'navigate', to: 'llms-list' } + if (view === 'add-skill') return { type: 'navigate', to: addSkillBackView } + if (view === 'add-mcp') return { type: 'navigate', to: addMcpBackView } if (view === 'llms-list') return { type: 'navigate', to: 'main' } if (view === 'settings' || view === 'notifications' || view === 'logs') return { type: 'navigate', to: 'main' } @@ -107,6 +113,8 @@ export function initialRouterState(hash = ''): RouterState { mcpBackView: 'tool-detail', allSkillsBackView: 'tool-detail', allMcpsBackView: 'tool-detail', + addSkillBackView: 'all-skills-list', + addMcpBackView: 'all-mcps-list', } } @@ -139,6 +147,12 @@ export function routerReducer(state: RouterState, action: RouterAction): RouterS case 'OPEN_MCPS_PAGE': return { ...state, view: 'all-mcps-list', allMcpsBackView: action.fromView } + case 'OPEN_ADD_SKILL': + return { ...state, view: 'add-skill', addSkillBackView: action.fromView } + + case 'OPEN_ADD_MCP': + return { ...state, view: 'add-mcp', addMcpBackView: action.fromView } + case 'GO_TO': return { ...state, view: action.view }