mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
refactor: move skills state to session context with refreshSkills/removeSkill
Move discoveredSkills signal from AgentBehaviourTab into the session context so any component can access session.skills(), session.refreshSkills(), and session.removeSkill(location). removeSkill optimistically removes the skill from the UI signal before sending the message to the extension, so the screen updates immediately.
This commit is contained in:
@@ -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<SubtabId>("agents")
|
||||
const [selectedAgent, setSelectedAgent] = createSignal<string>("")
|
||||
const [newSkillPath, setNewSkillPath] = createSignal("")
|
||||
const [newSkillUrl, setNewSkillUrl] = createSignal("")
|
||||
const [newInstruction, setNewInstruction] = createSignal("")
|
||||
const [discoveredSkills, setDiscoveredSkills] = createSignal<SkillInfo[]>([])
|
||||
|
||||
// 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(() => (
|
||||
<Dialog title={language.t("settings.agentBehaviour.removeSkill.title")} fit>
|
||||
@@ -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")}
|
||||
</h4>
|
||||
<Show
|
||||
when={discoveredSkills().length > 0}
|
||||
when={session.skills().length > 0}
|
||||
fallback={
|
||||
<Card style={{ "margin-bottom": "16px" }}>
|
||||
<div data-slot="settings-row-label-subtitle">{language.t("settings.agentBehaviour.noSkillsFound")}</div>
|
||||
@@ -438,7 +422,7 @@ const AgentBehaviourTab: Component = () => {
|
||||
}
|
||||
>
|
||||
<Card style={{ "margin-bottom": "16px" }}>
|
||||
<For each={discoveredSkills()}>
|
||||
<For each={session.skills()}>
|
||||
{(skill, index) => (
|
||||
<div
|
||||
style={{
|
||||
@@ -446,8 +430,7 @@ const AgentBehaviourTab: Component = () => {
|
||||
"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",
|
||||
}}
|
||||
>
|
||||
<div style={{ flex: 1, "min-width": 0 }}>
|
||||
|
||||
@@ -36,6 +36,7 @@ import type {
|
||||
ModelSelection,
|
||||
ContextUsage,
|
||||
AgentInfo,
|
||||
SkillInfo,
|
||||
ExtensionMessage,
|
||||
FileAttachment,
|
||||
SendMessageFailedMessage,
|
||||
@@ -114,6 +115,11 @@ interface SessionContextValue {
|
||||
totalCost: Accessor<number>
|
||||
contextUsage: Accessor<ContextUsage | undefined>
|
||||
|
||||
// Skills loaded from the CLI backend
|
||||
skills: Accessor<SkillInfo[]>
|
||||
refreshSkills: () => void
|
||||
removeSkill: (location: string) => void
|
||||
|
||||
// Agent/mode selection (per-session)
|
||||
agents: Accessor<AgentInfo[]>
|
||||
selectedAgent: Accessor<string>
|
||||
@@ -204,6 +210,9 @@ export const SessionProvider: ParentComponent = (props) => {
|
||||
const [agents, setAgents] = createSignal<AgentInfo[]>([])
|
||||
const [defaultAgent, setDefaultAgent] = createSignal("code")
|
||||
|
||||
// Skills loaded from the CLI backend
|
||||
const [skills, setSkills] = createSignal<SkillInfo[]>([])
|
||||
|
||||
// Pending agent selection for before a session exists
|
||||
const [pendingAgentSelection, setPendingAgentSelection] = createSignal<string | null>(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(),
|
||||
|
||||
Reference in New Issue
Block a user