From 0c361bb2a496ad783ec5f2bc2c51bd81208ff5cd Mon Sep 17 00:00:00 2001 From: Mark IJbema Date: Thu, 12 Feb 2026 10:02:41 +0100 Subject: [PATCH] feat(settings): implement Agent Behaviour tab with per-agent config and subtabs --- .../components/settings/AgentBehaviourTab.tsx | 620 +++++++++++++++++- 1 file changed, 600 insertions(+), 20 deletions(-) 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 3d51b1dd3..61eb6e79a 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/AgentBehaviourTab.tsx @@ -1,5 +1,8 @@ -import { Component, createSignal, For } from "solid-js" +import { Component, createSignal, createMemo, For, Show } from "solid-js" +import { useConfig } from "../../context/config" +import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" +import type { AgentConfig } from "../../types/messages" type SubtabId = "modes" | "mcpServers" | "rules" | "workflows" | "skills" @@ -16,38 +19,615 @@ const subtabs: SubtabConfig[] = [ { id: "skills", labelKey: "settings.agentBehaviour.subtab.skills" }, ] +const selectStyle = { + padding: "4px 8px", + "border-radius": "4px", + border: "1px solid var(--vscode-dropdown-border, var(--vscode-panel-border))", + background: "var(--vscode-dropdown-background)", + color: "var(--vscode-dropdown-foreground)", + "font-size": "12px", + "font-family": "var(--vscode-font-family)", + cursor: "pointer", + outline: "none", + "min-width": "120px", +} + +const inputStyle = { + padding: "4px 8px", + "border-radius": "4px", + border: "1px solid var(--vscode-input-border, var(--vscode-panel-border))", + background: "var(--vscode-input-background)", + color: "var(--vscode-input-foreground)", + "font-size": "12px", + "font-family": "var(--vscode-font-family)", + outline: "none", +} + +interface SettingRowProps { + label: string + description: string + last?: boolean + children: any +} + +const SettingRow: Component = (props) => ( +
+
+
{props.label}
+
+ {props.description} +
+
+ {props.children} +
+) + +const Placeholder: Component<{ text: string }> = (props) => ( +
+

+ Not yet implemented. {props.text} +

+
+) + const AgentBehaviourTab: Component = () => { const language = useLanguage() + const { config, updateConfig } = useConfig() + const session = useSession() const [activeSubtab, setActiveSubtab] = createSignal("modes") + const [selectedAgent, setSelectedAgent] = createSignal("") + const [newSkillPath, setNewSkillPath] = createSignal("") + const [newSkillUrl, setNewSkillUrl] = createSignal("") - const renderSubtabContent = () => { - return ( -
-

{ + const names = session.agents().map((a) => a.name) + // Also include any agents from config that might not be in the agent list + const configAgents = Object.keys(config().agent ?? {}) + for (const name of configAgents) { + if (!names.includes(name)) { + names.push(name) + } + } + return names.sort() + }) + + const currentAgentConfig = createMemo(() => { + const name = selectedAgent() + if (!name) { + return {} + } + return config().agent?.[name] ?? {} + }) + + const updateAgentConfig = (name: string, partial: Partial) => { + const existing = config().agent ?? {} + const current = existing[name] ?? {} + updateConfig({ + agent: { + ...existing, + [name]: { ...current, ...partial }, + }, + }) + } + + const skillPaths = () => config().skills?.paths ?? [] + const skillUrls = () => config().skills?.urls ?? [] + + const addSkillPath = () => { + const value = newSkillPath().trim() + if (!value) { + return + } + const current = [...skillPaths()] + if (!current.includes(value)) { + current.push(value) + updateConfig({ skills: { ...config().skills, paths: current } }) + } + setNewSkillPath("") + } + + const removeSkillPath = (index: number) => { + const current = [...skillPaths()] + current.splice(index, 1) + updateConfig({ skills: { ...config().skills, paths: current } }) + } + + const addSkillUrl = () => { + const value = newSkillUrl().trim() + if (!value) { + return + } + const current = [...skillUrls()] + if (!current.includes(value)) { + current.push(value) + updateConfig({ skills: { ...config().skills, urls: current } }) + } + setNewSkillUrl("") + } + + const removeSkillUrl = (index: number) => { + const current = [...skillUrls()] + current.splice(index, 1) + updateConfig({ skills: { ...config().skills, urls: current } }) + } + + const renderModesSubtab = () => ( +

+ {/* Agent selector */} +
+ +
+ + +
- This section is not implemented yet. It will - contain configuration options for {activeSubtab()}. During reimplementation, use this space to validate - layout, spacing, scrolling behavior, and navigation state before wiring up real controls. -

+ {/* Model override */} + + + updateAgentConfig(selectedAgent(), { + model: e.currentTarget.value.trim() || undefined, + }) + } + onKeyDown={(e) => { + if (e.key === "Enter") { + e.currentTarget.blur() + } + }} + /> + + + {/* System prompt */} + +