mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-15 13:14:35 +00:00
feat: hooks
This commit is contained in:
78
packages/app/src/components/dialog-select-prompt.tsx
Normal file
78
packages/app/src/components/dialog-select-prompt.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import { useQuery } from "@tanstack/solid-query"
|
||||
import { Component, createMemo, Show } from "solid-js"
|
||||
import { useSDK } from "@/context/sdk"
|
||||
import { useDialog } from "@opencode-ai/ui/context/dialog"
|
||||
import { Dialog } from "@opencode-ai/ui/dialog"
|
||||
import { List } from "@opencode-ai/ui/list"
|
||||
import { useLanguage } from "@/context/language"
|
||||
import { useLocal } from "@/context/local"
|
||||
import { usePrompt, type Prompt } from "@/context/prompt"
|
||||
import type { AppPromptsResponse } from "@opencode-ai/sdk/v2"
|
||||
|
||||
export const DialogSelectPrompt: Component = () => {
|
||||
const sdk = useSDK()
|
||||
const dialog = useDialog()
|
||||
const language = useLanguage()
|
||||
const local = useLocal()
|
||||
const prompt = usePrompt()
|
||||
|
||||
const promptsQuery = useQuery(() => ({
|
||||
queryKey: ["prompts"],
|
||||
queryFn: async () => {
|
||||
const result = await sdk.client.app.prompts()
|
||||
return result.data as AppPromptsResponse
|
||||
},
|
||||
}))
|
||||
|
||||
const currentAgent = createMemo(() => local.agent.current())
|
||||
const tfAgentId = createMemo(() => currentAgent()?.options?.tf_agent_id as string | undefined)
|
||||
|
||||
const prompts = createMemo(() => {
|
||||
const all = promptsQuery.data ?? []
|
||||
const agentId = tfAgentId()
|
||||
if (!agentId) return []
|
||||
return all.filter((p) => p.available_to_agents?.includes(agentId))
|
||||
})
|
||||
|
||||
const applyPrompt = (p: { interpolation_string: string }) => {
|
||||
const text = p.interpolation_string
|
||||
const parts: Prompt = [{ type: "text", content: text, start: 0, end: text.length }]
|
||||
prompt.set(parts, text.length)
|
||||
dialog.close()
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
title={language.t("dialog.prompt.title")}
|
||||
description={language.t("dialog.prompt.description", {
|
||||
agent: currentAgent()?.name ?? "",
|
||||
})}
|
||||
>
|
||||
<Show
|
||||
when={!promptsQuery.isLoading}
|
||||
fallback={<div class="p-4 text-center">{language.t("common.loading.ellipsis")}</div>}
|
||||
>
|
||||
<List
|
||||
search={{ placeholder: language.t("common.search.placeholder"), autofocus: true }}
|
||||
emptyMessage={language.t("dialog.prompt.empty")}
|
||||
key={(x) => x?.id ?? ""}
|
||||
items={prompts}
|
||||
filterKeys={["label", "description"]}
|
||||
sortBy={(a, b) => a.label.localeCompare(b.label)}
|
||||
onSelect={(x) => {
|
||||
if (x) applyPrompt(x)
|
||||
}}
|
||||
>
|
||||
{(i) => (
|
||||
<div class="w-full flex flex-col gap-0.5 min-w-0">
|
||||
<span class="truncate text-13-medium">{i.label}</span>
|
||||
<Show when={i.description}>
|
||||
<span class="text-11-regular text-text-weaker truncate">{i.description}</span>
|
||||
</Show>
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
</Show>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -69,6 +69,8 @@ export const dict = {
|
||||
"command.agent.cycle.description": "Switch to the next agent",
|
||||
"command.agent.cycle.reverse": "Cycle agent backwards",
|
||||
"command.agent.cycle.reverse.description": "Switch to the previous agent",
|
||||
"command.prompts.select": "Select prompt",
|
||||
"command.prompts.select.description": "Select a ToothFairyAI prompt for the current agent",
|
||||
"command.model.variant.cycle": "Cycle thinking effort",
|
||||
"command.model.variant.cycle.description": "Switch to the next effort level",
|
||||
"command.prompt.mode.shell": "Shell",
|
||||
@@ -296,6 +298,10 @@ export const dict = {
|
||||
"dialog.mcp.description": "{{enabled}} of {{total}} enabled",
|
||||
"dialog.mcp.empty": "No MCPs configured",
|
||||
|
||||
"dialog.prompt.title": "Select prompt",
|
||||
"dialog.prompt.description": "Prompts for {{agent}}",
|
||||
"dialog.prompt.empty": "No prompts available for this agent",
|
||||
|
||||
"dialog.lsp.empty": "LSPs auto-detected from file types",
|
||||
"dialog.plugins.empty": "Plugins configured in opencode.json",
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import { useTerminal } from "@/context/terminal"
|
||||
import { DialogSelectFile } from "@/components/dialog-select-file"
|
||||
import { DialogSelectModel } from "@/components/dialog-select-model"
|
||||
import { DialogSelectMcp } from "@/components/dialog-select-mcp"
|
||||
import { DialogSelectPrompt } from "@/components/dialog-select-prompt"
|
||||
import { DialogFork } from "@/components/dialog-fork"
|
||||
import { showToast } from "@opencode-ai/ui/toast"
|
||||
import { findLast } from "@opencode-ai/util/array"
|
||||
@@ -376,6 +377,13 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||
keybind: "shift+mod+.",
|
||||
onSelect: () => local.agent.move(-1),
|
||||
}),
|
||||
agentCommand({
|
||||
id: "prompts.select",
|
||||
title: language.t("command.prompts.select"),
|
||||
description: language.t("command.prompts.select.description"),
|
||||
slash: "prompts",
|
||||
onSelect: () => dialog.show(() => <DialogSelectPrompt />),
|
||||
}),
|
||||
modelCommand({
|
||||
id: "model.variant.cycle",
|
||||
title: language.t("command.model.variant.cycle"),
|
||||
|
||||
Reference in New Issue
Block a user