diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx index 3b0d278b92e..1d4236d87a1 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -1,4 +1,4 @@ -import { Component, createSignal, createMemo, createEffect, For, Show, onCleanup } from "solid-js" +import { Component, createSignal, createMemo, createEffect, For, Show } from "solid-js" import { Select } from "@kilocode/kilo-ui/select" import { TextField } from "@kilocode/kilo-ui/text-field" import { Card } from "@kilocode/kilo-ui/card" @@ -10,8 +10,7 @@ import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { useConfig } from "../../context/config" import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" -import { useVSCode } from "../../context/vscode" -import type { AgentConfig, SkillInfo, ExtensionMessage } from "../../types/messages" +import type { AgentConfig, SkillInfo } from "../../types/messages" type SubtabId = "agents" | "mcpServers" | "rules" | "workflows" | "skills" @@ -54,31 +53,20 @@ const AgentBehaviourTab: Component = () => { const language = useLanguage() const { config, updateConfig } = useConfig() const session = useSession() - const vscode = useVSCode() const dialog = useDialog() const [activeSubtab, setActiveSubtab] = createSignal("agents") const [selectedAgent, setSelectedAgent] = createSignal("") const [newSkillPath, setNewSkillPath] = createSignal("") const [newSkillUrl, setNewSkillUrl] = createSignal("") const [newInstruction, setNewInstruction] = createSignal("") - const [discoveredSkills, setDiscoveredSkills] = createSignal([]) - - // Subscribe to skillsLoaded messages from the extension - const unsub = vscode.onMessage((message: ExtensionMessage) => { - if (message.type === "skillsLoaded") { - setDiscoveredSkills(message.skills) - } - }) // Fetch skills whenever the skills subtab becomes active createEffect(() => { if (activeSubtab() === "skills") { - vscode.postMessage({ type: "requestSkills" }) + session.refreshSkills() } }) - onCleanup(() => unsub()) - const agentNames = createMemo(() => { const names = session.agents().map((a) => a.name) // Also include any agents from config that might not be in the agent list @@ -182,10 +170,6 @@ const AgentBehaviourTab: Component = () => { updateConfig({ skills: { ...config().skills, urls: current } }) } - const removeSkill = (skill: SkillInfo) => { - vscode.postMessage({ type: "removeSkill", location: skill.location }) - } - const confirmRemoveSkill = (skill: SkillInfo) => { dialog.show(() => ( @@ -199,7 +183,7 @@ const AgentBehaviourTab: Component = () => { variant="primary" size="large" onClick={() => { - removeSkill(skill) + session.removeSkill(skill.location) dialog.close() }} > @@ -430,7 +414,7 @@ const AgentBehaviourTab: Component = () => { {language.t("settings.agentBehaviour.discoveredSkills")} 0} + when={session.skills().length > 0} fallback={
{language.t("settings.agentBehaviour.noSkillsFound")}
@@ -438,7 +422,7 @@ const AgentBehaviourTab: Component = () => { } > - + {(skill, index) => (
{ "align-items": "center", "justify-content": "space-between", padding: "8px 0", - "border-bottom": - index() < discoveredSkills().length - 1 ? "1px solid var(--border-weak-base)" : "none", + "border-bottom": index() < session.skills().length - 1 ? "1px solid var(--border-weak-base)" : "none", }} >
diff --git a/packages/kilo-vscode/webview-ui/src/context/session.tsx b/packages/kilo-vscode/webview-ui/src/context/session.tsx index 24219c433a8..9bec4955fd9 100644 --- a/packages/kilo-vscode/webview-ui/src/context/session.tsx +++ b/packages/kilo-vscode/webview-ui/src/context/session.tsx @@ -36,6 +36,7 @@ import type { ModelSelection, ContextUsage, AgentInfo, + SkillInfo, ExtensionMessage, FileAttachment, SendMessageFailedMessage, @@ -114,6 +115,11 @@ interface SessionContextValue { totalCost: Accessor contextUsage: Accessor + // Skills loaded from the CLI backend + skills: Accessor + refreshSkills: () => void + removeSkill: (location: string) => void + // Agent/mode selection (per-session) agents: Accessor selectedAgent: Accessor @@ -204,6 +210,9 @@ export const SessionProvider: ParentComponent = (props) => { const [agents, setAgents] = createSignal([]) const [defaultAgent, setDefaultAgent] = createSignal("code") + // Skills loaded from the CLI backend + const [skills, setSkills] = createSignal([]) + // Pending agent selection for before a session exists const [pendingAgentSelection, setPendingAgentSelection] = createSignal(null) @@ -341,8 +350,25 @@ export const SessionProvider: ParentComponent = (props) => { vscode.postMessage({ type: "requestAgents" }) }, agentRetryMs) + // Skills loaded from the CLI backend + const unsubSkills = vscode.onMessage((message: ExtensionMessage) => { + if (message.type === "skillsLoaded") { + setSkills(message.skills) + } + }) + + const refreshSkills = () => { + vscode.postMessage({ type: "requestSkills" }) + } + + const removeSkill = (location: string) => { + setSkills((prev) => prev.filter((s) => s.location !== location)) + vscode.postMessage({ type: "removeSkill", location }) + } + onCleanup(() => { unsubAgents() + unsubSkills() clearInterval(agentRetryTimer) }) @@ -1285,6 +1311,9 @@ export const SessionProvider: ParentComponent = (props) => { totalCost, contextUsage, agents, + skills, + refreshSkills, + removeSkill, selectedAgent: selectedAgentName, selectAgent, getSessionAgent: (sessionID: string) => store.agentSelections[sessionID] ?? defaultAgent(),