feat: add skill dialog for selecting and inserting skills (#11547)
This commit is contained in:
34
packages/opencode/src/cli/cmd/tui/component/dialog-skill.tsx
Normal file
34
packages/opencode/src/cli/cmd/tui/component/dialog-skill.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select"
|
||||||
|
import { createResource, createMemo } from "solid-js"
|
||||||
|
import { useDialog } from "@tui/ui/dialog"
|
||||||
|
import { useSDK } from "@tui/context/sdk"
|
||||||
|
|
||||||
|
export type DialogSkillProps = {
|
||||||
|
onSelect: (skill: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DialogSkill(props: DialogSkillProps) {
|
||||||
|
const dialog = useDialog()
|
||||||
|
const sdk = useSDK()
|
||||||
|
|
||||||
|
const [skills] = createResource(async () => {
|
||||||
|
const result = await sdk.client.app.skills()
|
||||||
|
return result.data ?? []
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = createMemo<DialogSelectOption<string>[]>(() => {
|
||||||
|
const list = skills() ?? []
|
||||||
|
return list.map((skill) => ({
|
||||||
|
title: skill.name,
|
||||||
|
description: skill.description,
|
||||||
|
value: skill.name,
|
||||||
|
category: "Skills",
|
||||||
|
onSelect: () => {
|
||||||
|
props.onSelect(skill.name)
|
||||||
|
dialog.clear()
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
return <DialogSelect title="Skills" placeholder="Search skills..." options={options()} />
|
||||||
|
}
|
||||||
@@ -345,7 +345,8 @@ export function Autocomplete(props: {
|
|||||||
const results: AutocompleteOption[] = [...command.slashes()]
|
const results: AutocompleteOption[] = [...command.slashes()]
|
||||||
|
|
||||||
for (const serverCommand of sync.data.command) {
|
for (const serverCommand of sync.data.command) {
|
||||||
const label = serverCommand.source === "mcp" ? ":mcp" : serverCommand.source === "skill" ? ":skill" : ""
|
if (serverCommand.source === "skill") continue
|
||||||
|
const label = serverCommand.source === "mcp" ? ":mcp" : ""
|
||||||
results.push({
|
results.push({
|
||||||
display: "/" + serverCommand.name + label,
|
display: "/" + serverCommand.name + label,
|
||||||
description: serverCommand.description,
|
description: serverCommand.description,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { DialogAlert } from "../../ui/dialog-alert"
|
|||||||
import { useToast } from "../../ui/toast"
|
import { useToast } from "../../ui/toast"
|
||||||
import { useKV } from "../../context/kv"
|
import { useKV } from "../../context/kv"
|
||||||
import { useTextareaKeybindings } from "../textarea-keybindings"
|
import { useTextareaKeybindings } from "../textarea-keybindings"
|
||||||
|
import { DialogSkill } from "../dialog-skill"
|
||||||
|
|
||||||
export type PromptProps = {
|
export type PromptProps = {
|
||||||
sessionID?: string
|
sessionID?: string
|
||||||
@@ -315,6 +316,28 @@ export function Prompt(props: PromptProps) {
|
|||||||
input.cursorOffset = Bun.stringWidth(content)
|
input.cursorOffset = Bun.stringWidth(content)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Skills",
|
||||||
|
value: "prompt.skills",
|
||||||
|
category: "Prompt",
|
||||||
|
slash: {
|
||||||
|
name: "skills",
|
||||||
|
},
|
||||||
|
onSelect: () => {
|
||||||
|
dialog.replace(() => (
|
||||||
|
<DialogSkill
|
||||||
|
onSelect={(skill) => {
|
||||||
|
input.setText(`/${skill} `)
|
||||||
|
setStore("prompt", {
|
||||||
|
input: `/${skill} `,
|
||||||
|
parts: [],
|
||||||
|
})
|
||||||
|
input.gotoBufferEnd()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user