Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/components/views/AllMcpsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface Props {
tools: AiTool[]
onBack: () => void
onSelectMcp: (mcp: McpServer) => void
onAddMcp?: () => void
}

interface McpVariant extends McpServer {
Expand Down Expand Up @@ -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])
Expand All @@ -65,8 +66,21 @@ export default function AllMcpsView({ tools, onSelectMcp }: Props) {

return (
<div className="flex flex-col h-full bg-[var(--c-bg)]">
<div className="flex items-center justify-end px-4 py-2 border-b border-[var(--c-border)] flex-shrink-0">
<div className="flex items-center justify-between px-4 py-2 border-b border-[var(--c-border)] flex-shrink-0">
<span className="text-[12px] text-[var(--c-text-3)]">{countLabel}</span>
{onAddMcp && (
<button
onClick={onAddMcp}
className="flex items-center gap-1 px-2 py-1 rounded-md bg-violet-500/10 text-violet-400 hover:bg-violet-500/20 transition-colors text-[12px] font-medium"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"
className="w-3 h-3">
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
</svg>
Add MCP
</button>
)}
</div>

<div className="px-3 py-2 border-b border-[var(--c-border)] flex-shrink-0">
Expand Down
18 changes: 16 additions & 2 deletions src/components/views/AllSkillsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface Props {
tools: AiTool[]
onBack: () => void
onSelectSkill: (skill: Skill) => void
onAddSkill?: () => void
}

interface SkillVariant extends Skill {
Expand Down Expand Up @@ -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])
Expand All @@ -68,8 +69,21 @@ export default function AllSkillsView({ tools, onSelectSkill }: Props) {

return (
<div className="flex flex-col h-full bg-[var(--c-bg)]">
<div className="flex items-center justify-end px-4 py-2 border-b border-[var(--c-border)] flex-shrink-0">
<div className="flex items-center justify-between px-4 py-2 border-b border-[var(--c-border)] flex-shrink-0">
<span className="text-[12px] text-[var(--c-text-3)]">{countLabel}</span>
{onAddSkill && (
<button
onClick={onAddSkill}
className="flex items-center gap-1 px-2 py-1 rounded-md bg-indigo-500/10 text-indigo-400 hover:bg-indigo-500/20 transition-colors text-[12px] font-medium"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"
className="w-3 h-3">
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
</svg>
Add skill
</button>
)}
</div>

<div className="px-3 py-2 border-b border-[var(--c-border)] flex-shrink-0">
Expand Down
12 changes: 8 additions & 4 deletions src/components/views/ViewManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export default function ViewManager({
selectMcp,
openSkillsPage,
openMcpsPage,
openAddSkill,
openAddMcp,
goTo,
escape,
query,
Expand Down Expand Up @@ -59,7 +61,7 @@ export default function ViewManager({
return (
<AddSkillView
installedTools={installedTools}
onBack={() => goTo('llms-list')}
onBack={() => escape()}
onCreated={handleFetchTools}
/>
)
Expand All @@ -68,7 +70,7 @@ export default function ViewManager({
return (
<AddMcpView
installedTools={installedTools}
onBack={() => goTo('llms-list')}
onBack={() => escape()}
onAdded={handleFetchTools}
/>
)
Expand All @@ -88,7 +90,7 @@ export default function ViewManager({
tool={selectedTool}
onBack={() => escape()}
onSelectSkill={skill => selectSkill(skill, 'skills-list')}
onAddSkill={() => goTo('add-skill')}
onAddSkill={openAddSkill}
/>
)
}
Expand All @@ -98,7 +100,7 @@ export default function ViewManager({
tool={selectedTool}
onBack={() => escape()}
onSelectMcp={mcp => selectMcp(mcp, 'mcps-list')}
onAddMcp={() => goTo('add-mcp')}
onAddMcp={openAddMcp}
/>
)
}
Expand All @@ -108,6 +110,7 @@ export default function ViewManager({
tools={tools}
onBack={() => escape()}
onSelectSkill={skill => selectSkill(skill, 'all-skills-list')}
onAddSkill={openAddSkill}
/>
)
}
Expand All @@ -117,6 +120,7 @@ export default function ViewManager({
tools={tools}
onBack={() => escape()}
onSelectMcp={mcp => selectMcp(mcp, 'all-mcps-list')}
onAddMcp={openAddMcp}
/>
)
}
Expand Down
11 changes: 10 additions & 1 deletion src/useViewRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 })
Expand All @@ -96,6 +103,8 @@ export function useViewRouter(): UseViewRouterResult {
selectMcp,
openSkillsPage,
openMcpsPage,
openAddSkill,
openAddMcp,
goTo,
escape,
refreshSelected,
Expand Down
18 changes: 16 additions & 2 deletions src/viewRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export interface RouterState {
mcpBackView: View
allSkillsBackView: View
allMcpsBackView: View
addSkillBackView: View
addMcpBackView: View
}

export type RouterAction =
Expand All @@ -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 =
Expand All @@ -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 }
Expand All @@ -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' }
Expand All @@ -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',
}
}

Expand Down Expand Up @@ -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 }

Expand Down
Loading