From 1ef332bc28e6c3c03e85a2c566a3a10823b9af78 Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 17:08:48 +0500 Subject: [PATCH 1/8] feat(agents): add shortDescription and agent details modal (#4825) --- packages/opencode/src/agent/agent.ts | 5 +- packages/opencode/src/agent/generate.txt | 1 + packages/opencode/src/cli/cmd/agent.ts | 1 + .../tui/component/dialog-agent-details.tsx | 71 +++++++++++++++++++ .../cli/cmd/tui/component/dialog-agent.tsx | 41 ++++++++++- .../src/cli/cmd/tui/ui/dialog-select.tsx | 21 +++--- .../opencode/src/cli/cmd/tui/ui/dialog.tsx | 18 +++-- packages/opencode/src/config/config.ts | 4 ++ packages/sdk/js/src/gen/types.gen.ts | 5 ++ 9 files changed, 151 insertions(+), 16 deletions(-) create mode 100644 packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index b901b95c2fdb..24488a71413f 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -12,6 +12,7 @@ export namespace Agent { .object({ name: z.string(), description: z.string().optional(), + shortDescription: z.string().optional(), mode: z.enum(["subagent", "primary", "all"]), builtIn: z.boolean(), topP: z.number().optional(), @@ -182,7 +183,7 @@ export namespace Agent { tools: {}, builtIn: false, } - const { name, model, prompt, tools, description, temperature, top_p, mode, permission, color, ...extra } = value + const { name, model, prompt, tools, description, short_description, temperature, top_p, mode, permission, color, ...extra } = value item.options = { ...item.options, ...extra, @@ -199,6 +200,7 @@ export namespace Agent { ...item.tools, } if (description) item.description = description + if (short_description) item.shortDescription = short_description if (temperature != undefined) item.temperature = temperature if (top_p != undefined) item.topP = top_p if (mode) item.mode = mode @@ -244,6 +246,7 @@ export namespace Agent { model: model.language, schema: z.object({ identifier: z.string(), + shortSummary: z.string(), whenToUse: z.string(), systemPrompt: z.string(), }), diff --git a/packages/opencode/src/agent/generate.txt b/packages/opencode/src/agent/generate.txt index 774277b0fa8f..481c4c8a7a68 100644 --- a/packages/opencode/src/agent/generate.txt +++ b/packages/opencode/src/agent/generate.txt @@ -59,6 +59,7 @@ When a user describes what they want an agent to do, you will: Your output must be a valid JSON object with exactly these fields: { "identifier": "A unique, descriptive identifier using lowercase letters, numbers, and hyphens (e.g., 'code-reviewer', 'api-docs-writer', 'test-generator')", +"shortSummary": "A brief, human-readable summary of the agent's purpose (max 40 characters) for display in agent listings. Should be concise and descriptive, e.g., 'Reviews code for best practices and potential issues'", "whenToUse": "A precise, actionable description starting with 'Use this agent when...' that clearly defines the triggering conditions and use cases. Ensure you include examples as described above.", "systemPrompt": "The complete system prompt that will govern the agent's behavior, written in second person ('You are...', 'You will...') and structured for maximum clarity and effectiveness" } diff --git a/packages/opencode/src/cli/cmd/agent.ts b/packages/opencode/src/cli/cmd/agent.ts index a774c6d026be..1d4940e4ca7b 100644 --- a/packages/opencode/src/cli/cmd/agent.ts +++ b/packages/opencode/src/cli/cmd/agent.ts @@ -112,6 +112,7 @@ const AgentCreateCommand = cmd({ const frontmatter: any = { description: generated.whenToUse, + short_description: generated.shortSummary, mode: modeResult, } if (Object.keys(tools).length > 0) { diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx new file mode 100644 index 000000000000..90e9bde076a4 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx @@ -0,0 +1,71 @@ +import { createMemo, onMount } from "solid-js" +import { useLocal } from "@tui/context/local" +import { useDialog } from "@tui/ui/dialog" +import { useKeyboard, useTerminalDimensions } from "@opentui/solid" +import { useTheme } from "@tui/context/theme" +import { ScrollBoxRenderable, TextAttributes } from "@opentui/core" +import { DialogAgent } from "./dialog-agent" + +export function DialogAgentDetails(props: { agentName: string }) { + const local = useLocal() + const dialog = useDialog() + const { theme } = useTheme() + const dimensions = useTerminalDimensions() + + const agent = createMemo(() => local.agent.list().find((a) => a.name === props.agentName)) + const description = createMemo(() => agent()?.description ?? "No description available") + const maxHeight = createMemo(() => Math.floor(dimensions().height / 2) - 4) + + let scroll: ScrollBoxRenderable + + onMount(() => { + dialog.setSize("large") + }) + + useKeyboard((evt) => { + if (evt.name === "escape" || evt.name === "return") { + evt.preventDefault() + dialog.replace(() => ) + return + } + if (evt.name === "up" || (evt.ctrl && evt.name === "p")) { + scroll?.scrollBy(-1) + } + if (evt.name === "down" || (evt.ctrl && evt.name === "n")) { + scroll?.scrollBy(1) + } + if (evt.name === "pageup") { + scroll?.scrollBy(-10) + } + if (evt.name === "pagedown") { + scroll?.scrollBy(10) + } + }) + + return ( + + + + + {props.agentName} + + esc + + + (scroll = r)} + paddingLeft={4} + paddingRight={4} + paddingTop={1} + maxHeight={maxHeight()} + > + + {description()} + + + + Press esc or enter to go back + + + ) +} diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index 65aaeb22bf98..f57e08c2b803 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -1,18 +1,39 @@ -import { createMemo } from "solid-js" +import { createMemo, createSignal } from "solid-js" import { useLocal } from "@tui/context/local" import { DialogSelect } from "@tui/ui/dialog-select" import { useDialog } from "@tui/ui/dialog" +import { Keybind } from "@/util/keybind" +import { DialogAgentDetails } from "./dialog-agent-details" -export function DialogAgent() { +export function DialogAgent(props: { initialAgent?: string }) { const local = useLocal() const dialog = useDialog() + const [selectedAgentName, setSelectedAgentName] = createSignal(props.initialAgent ?? local.agent.current().name) + + const selectedAgentHasPrompt = createMemo(() => { + const agent = local.agent.list().find((a) => a.name === selectedAgentName()) + return agent && !agent.builtIn && !!agent.description + }) + const options = createMemo(() => local.agent.list().map((item) => { + let description: string | undefined + + if (item.builtIn) { + description = "native" + } else if (item.shortDescription) { + description = item.shortDescription + } else if (item.description) { + description = item.description + } + + description = description ? description.length > 35 ? description.slice(0, 32) + "..." : description : undefined + return { value: item.name, title: item.name, - description: item.builtIn ? "native" : item.description, + description } }), ) @@ -21,11 +42,25 @@ export function DialogAgent() { setSelectedAgentName(option.value)} onSelect={(option) => { local.agent.set(option.value) dialog.clear() }} + keybind={[ + { + keybind: Keybind.parse("ctrl+e")[0], + title: "show details", + get disabled() { + return !selectedAgentHasPrompt() + }, + onTrigger: (option) => { + dialog.replace(() => ) + }, + }, + ]} /> ) } diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index f6d79946c63b..160f4ea96ca2 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -26,6 +26,7 @@ export interface DialogSelectProps { onTrigger: (option: DialogSelectOption) => void }[] current?: T + defaultSelected?: T } export interface DialogSelectOption { @@ -53,10 +54,11 @@ export function DialogSelect(props: DialogSelectProps) { }) createEffect(() => { - if (props.current) { - const currentIndex = flat().findIndex((opt) => isDeepEqual(opt.value, props.current)) - if (currentIndex >= 0) { - setStore("selected", currentIndex) + const initialValue = props.defaultSelected ?? props.current + if (initialValue) { + const initialIndex = flat().findIndex((opt) => isDeepEqual(opt.value, initialValue)) + if (initialIndex >= 0) { + setStore("selected", initialIndex) } } }) @@ -101,10 +103,13 @@ export function DialogSelect(props: DialogSelectProps) { store.filter if (store.filter.length > 0) { setStore("selected", 0) - } else if (props.current) { - const currentIndex = flat().findIndex((opt) => isDeepEqual(opt.value, props.current)) - if (currentIndex >= 0) { - setStore("selected", currentIndex) + } else { + const initialValue = props.defaultSelected ?? props.current + if (initialValue) { + const initialIndex = flat().findIndex((opt) => isDeepEqual(opt.value, initialValue)) + if (initialIndex >= 0) { + setStore("selected", initialIndex) + } } } scroll.scrollTo(0) diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx index 9b773111c355..843232175d6d 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog.tsx @@ -57,7 +57,7 @@ function init() { }) useKeyboard((evt) => { - if (evt.name === "escape" && store.stack.length > 0) { + if (evt.name === "escape" && store.stack.length > 0 && !evt.defaultPrevented) { const current = store.stack.at(-1)! current.onClose?.() setStore("stack", store.stack.slice(0, -1)) @@ -70,8 +70,14 @@ function init() { let focus: Renderable | null function refocus() { setTimeout(() => { + // A new dialog was opened in the meantime (e.g., navigating between dialogs) + if (store.stack.length > 0) return + if (!focus) return - if (focus.isDestroyed) return + if (focus.isDestroyed) { + focus = null + return + } function find(item: Renderable) { for (const child of item.getChildren()) { if (child === focus) return true @@ -80,8 +86,12 @@ function init() { return false } const found = find(renderer.root) - if (!found) return + if (!found) { + focus = null + return + } focus.focus() + focus = null }, 1) } @@ -97,7 +107,7 @@ function init() { refocus() }, replace(input: any, onClose?: () => void) { - if (store.stack.length === 0) { + if (store.stack.length === 0 && (!focus || focus.isDestroyed)) { focus = renderer.currentFocusedRenderable } for (const item of store.stack) { diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 3ed487653d52..bd4e153aa0ff 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -369,6 +369,10 @@ export namespace Config { tools: z.record(z.string(), z.boolean()).optional(), disable: z.boolean().optional(), description: z.string().optional().describe("Description of when to use the agent"), + short_description: z + .string() + .optional() + .describe("Short description for display in agent listings (defaults to truncated description)"), mode: z.enum(["subagent", "primary", "all"]).optional(), color: z .string() diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index f8e1d34fb6e7..f48ae3463990 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -895,6 +895,10 @@ export type AgentConfig = { * Description of when to use the agent */ description?: string + /** + * Short description for display in agent listings (defaults to truncated description) + */ + short_description?: string mode?: "subagent" | "primary" | "all" /** * Hex color code for the agent (e.g., #FF5733) @@ -1452,6 +1456,7 @@ export type File = { export type Agent = { name: string description?: string + shortDescription?: string mode: "subagent" | "primary" | "all" builtIn: boolean topP?: number From 5403794acb94d20ab2c0973c378651bdc9ed036b Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 17:31:13 +0500 Subject: [PATCH 2/8] fix(agents): improve focus restoration and dynamic description truncation (#4825) - Rename initialAgent prop to focusedAgent for clarity - Add dynamic description truncation based on terminal width - Fix focus restoration when navigating between dialogs --- .../tui/component/dialog-agent-details.tsx | 2 +- .../cli/cmd/tui/component/dialog-agent.tsx | 26 ++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx index 90e9bde076a4..e97f287322b0 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx @@ -25,7 +25,7 @@ export function DialogAgentDetails(props: { agentName: string }) { useKeyboard((evt) => { if (evt.name === "escape" || evt.name === "return") { evt.preventDefault() - dialog.replace(() => ) + dialog.replace(() => ) return } if (evt.name === "up" || (evt.ctrl && evt.name === "p")) { diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index f57e08c2b803..1257cda747a2 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -2,20 +2,26 @@ import { createMemo, createSignal } from "solid-js" import { useLocal } from "@tui/context/local" import { DialogSelect } from "@tui/ui/dialog-select" import { useDialog } from "@tui/ui/dialog" +import { useTerminalDimensions } from "@opentui/solid" import { Keybind } from "@/util/keybind" +import { Locale } from "@/util/locale" import { DialogAgentDetails } from "./dialog-agent-details" -export function DialogAgent(props: { initialAgent?: string }) { +export function DialogAgent(props: { focusedAgent?: string }) { const local = useLocal() const dialog = useDialog() + const dimensions = useTerminalDimensions() - const [selectedAgentName, setSelectedAgentName] = createSignal(props.initialAgent ?? local.agent.current().name) + const [selectedAgentName, setSelectedAgentName] = createSignal(props.focusedAgent ?? local.agent.current().name) - const selectedAgentHasPrompt = createMemo(() => { + const selectedAgentHasDescription = createMemo(() => { const agent = local.agent.list().find((a) => a.name === selectedAgentName()) return agent && !agent.builtIn && !!agent.description }) + // Dialog width is min(60, terminalWidth - 2), minus ~10 for padding + const availableWidth = createMemo(() => Math.min(60, dimensions().width - 2) - 10) + const options = createMemo(() => local.agent.list().map((item) => { let description: string | undefined @@ -28,12 +34,18 @@ export function DialogAgent(props: { initialAgent?: string }) { description = item.description } - description = description ? description.length > 35 ? description.slice(0, 32) + "..." : description : undefined + // Truncate description based on available space after title + const maxDescLen = availableWidth() - item.name.length - 1 + if (description && maxDescLen > 3) { + description = Locale.truncate(description, maxDescLen) + } else if (description && maxDescLen <= 3) { + description = undefined + } return { value: item.name, title: item.name, - description + description, } }), ) @@ -42,7 +54,7 @@ export function DialogAgent(props: { initialAgent?: string }) { setSelectedAgentName(option.value)} onSelect={(option) => { @@ -54,7 +66,7 @@ export function DialogAgent(props: { initialAgent?: string }) { keybind: Keybind.parse("ctrl+e")[0], title: "show details", get disabled() { - return !selectedAgentHasPrompt() + return !selectedAgentHasDescription() }, onTrigger: (option) => { dialog.replace(() => ) From 891366b29966fc2898a9dbe65350be181c44a31b Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 17:49:45 +0500 Subject: [PATCH 3/8] fix(agents): improve agent details dialog layout (#4825) --- .../tui/component/dialog-agent-details.tsx | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx index e97f287322b0..24d852b610ce 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx @@ -13,8 +13,7 @@ export function DialogAgentDetails(props: { agentName: string }) { const dimensions = useTerminalDimensions() const agent = createMemo(() => local.agent.list().find((a) => a.name === props.agentName)) - const description = createMemo(() => agent()?.description ?? "No description available") - const maxHeight = createMemo(() => Math.floor(dimensions().height / 2) - 4) + const maxHeight = Math.floor(dimensions().height / 2) - 4 let scroll: ScrollBoxRenderable @@ -57,11 +56,20 @@ export function DialogAgentDetails(props: { agentName: string }) { paddingLeft={4} paddingRight={4} paddingTop={1} - maxHeight={maxHeight()} + maxHeight={maxHeight} > - - {description()} - + {agent()?.shortDescription && ( + + {agent()?.shortDescription} + + )} + {agent()?.description && ( + + + {agent()?.description} + + + )} Press esc or enter to go back From 10d082ab0f15bad159a8682373364d3eac3470e3 Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 17:50:41 +0500 Subject: [PATCH 4/8] docs(agents): update short_description field description (#4825) --- packages/opencode/src/config/config.ts | 2 +- packages/sdk/js/src/gen/types.gen.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index bd4e153aa0ff..e03b0e4ce961 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -372,7 +372,7 @@ export namespace Config { short_description: z .string() .optional() - .describe("Short description for display in agent listings (defaults to truncated description)"), + .describe("Short description for display in agent listings"), mode: z.enum(["subagent", "primary", "all"]).optional(), color: z .string() diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index f48ae3463990..3eaca962e30c 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -896,7 +896,7 @@ export type AgentConfig = { */ description?: string /** - * Short description for display in agent listings (defaults to truncated description) + * Short description for display in agent listings */ short_description?: string mode?: "subagent" | "primary" | "all" From 7c392294399f25e29f78b887baef81dd2a783ced Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 17:51:25 +0500 Subject: [PATCH 5/8] refactor(agents): rename focusedAgent prop to selectedAgent (#4825) --- .../src/cli/cmd/tui/component/dialog-agent-details.tsx | 2 +- .../opencode/src/cli/cmd/tui/component/dialog-agent.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx index 24d852b610ce..469c09c83f6a 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent-details.tsx @@ -24,7 +24,7 @@ export function DialogAgentDetails(props: { agentName: string }) { useKeyboard((evt) => { if (evt.name === "escape" || evt.name === "return") { evt.preventDefault() - dialog.replace(() => ) + dialog.replace(() => ) return } if (evt.name === "up" || (evt.ctrl && evt.name === "p")) { diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index 1257cda747a2..f58c690a2c5e 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -7,12 +7,12 @@ import { Keybind } from "@/util/keybind" import { Locale } from "@/util/locale" import { DialogAgentDetails } from "./dialog-agent-details" -export function DialogAgent(props: { focusedAgent?: string }) { +export function DialogAgent(props: { selectedAgent?: string }) { const local = useLocal() const dialog = useDialog() const dimensions = useTerminalDimensions() - const [selectedAgentName, setSelectedAgentName] = createSignal(props.focusedAgent ?? local.agent.current().name) + const [selectedAgentName, setSelectedAgentName] = createSignal(props.selectedAgent ?? local.agent.current().name) const selectedAgentHasDescription = createMemo(() => { const agent = local.agent.list().find((a) => a.name === selectedAgentName()) @@ -54,7 +54,7 @@ export function DialogAgent(props: { focusedAgent?: string }) { setSelectedAgentName(option.value)} onSelect={(option) => { From e7d5a9677a4e09d9121d50a806ad9ce6bbe8b21d Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 17:54:36 +0500 Subject: [PATCH 6/8] refactor(agents): rename maxDescLen to maxDescriptionLength (#4825) --- .../opencode/src/cli/cmd/tui/component/dialog-agent.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index f58c690a2c5e..d56a22d0eeff 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -35,10 +35,10 @@ export function DialogAgent(props: { selectedAgent?: string }) { } // Truncate description based on available space after title - const maxDescLen = availableWidth() - item.name.length - 1 - if (description && maxDescLen > 3) { - description = Locale.truncate(description, maxDescLen) - } else if (description && maxDescLen <= 3) { + const maxDescriptionLength = availableWidth() - item.name.length - 1 + if (description && maxDescriptionLength > 3) { + description = Locale.truncate(description, maxDescriptionLength) + } else if (description && maxDescriptionLength <= 3) { description = undefined } From fce8f10d59c36780df692e69a1689c61635e5118 Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 18:42:46 +0500 Subject: [PATCH 7/8] refactor(agents): rename shortSummary to shortDescription for consistency (#4825) --- packages/opencode/src/agent/agent.ts | 2 +- packages/opencode/src/agent/generate.txt | 2 +- packages/opencode/src/cli/cmd/agent.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 24488a71413f..1aa31e99e14d 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -246,7 +246,7 @@ export namespace Agent { model: model.language, schema: z.object({ identifier: z.string(), - shortSummary: z.string(), + shortDescription: z.string(), whenToUse: z.string(), systemPrompt: z.string(), }), diff --git a/packages/opencode/src/agent/generate.txt b/packages/opencode/src/agent/generate.txt index 481c4c8a7a68..b4f8ca2a77dd 100644 --- a/packages/opencode/src/agent/generate.txt +++ b/packages/opencode/src/agent/generate.txt @@ -59,7 +59,7 @@ When a user describes what they want an agent to do, you will: Your output must be a valid JSON object with exactly these fields: { "identifier": "A unique, descriptive identifier using lowercase letters, numbers, and hyphens (e.g., 'code-reviewer', 'api-docs-writer', 'test-generator')", -"shortSummary": "A brief, human-readable summary of the agent's purpose (max 40 characters) for display in agent listings. Should be concise and descriptive, e.g., 'Reviews code for best practices and potential issues'", +"shortDescription": "A brief, human-readable summary of the agent's purpose (max 40 characters) for display in agent listings. Should be concise and descriptive, e.g., 'Reviews code for best practices and potential issues'", "whenToUse": "A precise, actionable description starting with 'Use this agent when...' that clearly defines the triggering conditions and use cases. Ensure you include examples as described above.", "systemPrompt": "The complete system prompt that will govern the agent's behavior, written in second person ('You are...', 'You will...') and structured for maximum clarity and effectiveness" } diff --git a/packages/opencode/src/cli/cmd/agent.ts b/packages/opencode/src/cli/cmd/agent.ts index 1d4940e4ca7b..1169c7f6bc6c 100644 --- a/packages/opencode/src/cli/cmd/agent.ts +++ b/packages/opencode/src/cli/cmd/agent.ts @@ -112,7 +112,7 @@ const AgentCreateCommand = cmd({ const frontmatter: any = { description: generated.whenToUse, - short_description: generated.shortSummary, + short_description: generated.shortDescription, mode: modeResult, } if (Object.keys(tools).length > 0) { From ad11b9d25ecef47c4485dad4cb1de21d4b63b9a3 Mon Sep 17 00:00:00 2001 From: Nikita Snetkov Date: Fri, 5 Dec 2025 21:25:04 +0500 Subject: [PATCH 8/8] style: format agent.ts and config.ts (#4825) --- packages/opencode/src/agent/agent.ts | 15 ++++++++++++++- packages/opencode/src/config/config.ts | 5 +---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 1aa31e99e14d..f6b10d799a4a 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -183,7 +183,20 @@ export namespace Agent { tools: {}, builtIn: false, } - const { name, model, prompt, tools, description, short_description, temperature, top_p, mode, permission, color, ...extra } = value + const { + name, + model, + prompt, + tools, + description, + short_description, + temperature, + top_p, + mode, + permission, + color, + ...extra + } = value item.options = { ...item.options, ...extra, diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index e03b0e4ce961..537991f66e7a 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -369,10 +369,7 @@ export namespace Config { tools: z.record(z.string(), z.boolean()).optional(), disable: z.boolean().optional(), description: z.string().optional().describe("Description of when to use the agent"), - short_description: z - .string() - .optional() - .describe("Short description for display in agent listings"), + short_description: z.string().optional().describe("Short description for display in agent listings"), mode: z.enum(["subagent", "primary", "all"]).optional(), color: z .string()