diff options
| author | Adam <[email protected]> | 2025-12-15 07:05:50 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2025-12-15 10:20:19 -0600 |
| commit | ff6864a7ca3772e6f2702d585c6bb64a40bd6cce (patch) | |
| tree | 9b4dfebee7db7d5dfd4098065d4fa4c99018d414 /packages/desktop/src/components | |
| parent | 5e37a902ce0ad209cedb0a85e997f1964064424a (diff) | |
| download | opencode-ff6864a7ca3772e6f2702d585c6bb64a40bd6cce.tar.gz opencode-ff6864a7ca3772e6f2702d585c6bb64a40bd6cce.zip | |
feat(desktop): custom commands
Diffstat (limited to 'packages/desktop/src/components')
| -rw-r--r-- | packages/desktop/src/components/prompt-input.tsx | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx index 51c4e24d2..87f91104c 100644 --- a/packages/desktop/src/components/prompt-input.tsx +++ b/packages/desktop/src/components/prompt-input.tsx @@ -61,6 +61,7 @@ interface SlashCommand { title: string description?: string keybind?: string + type: "builtin" | "custom" } export const PromptInput: Component<PromptInputProps> = (props) => { @@ -208,8 +209,8 @@ export const PromptInput: Component<PromptInputProps> = (props) => { }) // Get slash commands from registered commands (only those with explicit slash trigger) - const slashCommands = createMemo<SlashCommand[]>(() => - command.options + const slashCommands = createMemo<SlashCommand[]>(() => { + const builtin = command.options .filter((opt) => !opt.disabled && !opt.id.startsWith("suggested.") && opt.slash) .map((opt) => ({ id: opt.id, @@ -217,15 +218,46 @@ export const PromptInput: Component<PromptInputProps> = (props) => { title: opt.title, description: opt.description, keybind: opt.keybind, - })), - ) + type: "builtin" as const, + })) + + const custom = sync.data.command.map((cmd) => ({ + id: `custom.${cmd.name}`, + trigger: cmd.name, + title: cmd.name, + description: cmd.description, + type: "custom" as const, + })) + + return [...custom, ...builtin] + }) const handleSlashSelect = (cmd: SlashCommand | undefined) => { if (!cmd) return - // Since slash commands only trigger from start, just clear the input + setStore("popover", null) + + if (cmd.type === "custom") { + // For custom commands, insert the command text so user can add arguments + const text = `/${cmd.trigger} ` + editorRef.innerHTML = "" + editorRef.textContent = text + prompt.set([{ type: "text", content: text, start: 0, end: text.length }], text.length) + // Set cursor at end + requestAnimationFrame(() => { + editorRef.focus() + const range = document.createRange() + const sel = window.getSelection() + range.selectNodeContents(editorRef) + range.collapse(false) + sel?.removeAllRanges() + sel?.addRange(range) + }) + return + } + + // For built-in commands, clear input and execute immediately editorRef.innerHTML = "" prompt.set([{ type: "text", content: "", start: 0, end: 0 }], 0) - setStore("popover", null) command.trigger(cmd.id, "slash") } @@ -571,6 +603,23 @@ export const PromptInput: Component<PromptInputProps> = (props) => { editorRef.innerHTML = "" prompt.set([{ type: "text", content: "", start: 0, end: 0 }], 0) + // Check if this is a custom command + if (text.startsWith("/")) { + const [cmdName, ...args] = text.split(" ") + const commandName = cmdName.slice(1) // Remove leading "/" + const customCommand = sync.data.command.find((c) => c.name === commandName) + if (customCommand) { + sdk.client.session.command({ + sessionID: existing.id, + command: commandName, + arguments: args.join(" "), + agent: local.agent.current()!.name, + model: `${local.model.current()!.provider.id}/${local.model.current()!.id}`, + }) + return + } + } + sdk.client.session.prompt({ sessionID: existing.id, agent: local.agent.current()!.name, @@ -641,9 +690,16 @@ export const PromptInput: Component<PromptInputProps> = (props) => { <span class="text-14-regular text-text-weak truncate">{cmd.description}</span> </Show> </div> - <Show when={cmd.keybind}> - <span class="text-12-regular text-text-subtle shrink-0">{formatKeybind(cmd.keybind!)}</span> - </Show> + <div class="flex items-center gap-2 shrink-0"> + <Show when={cmd.type === "custom"}> + <span class="text-11-regular text-text-subtle px-1.5 py-0.5 bg-surface-base rounded"> + custom + </span> + </Show> + <Show when={cmd.keybind}> + <span class="text-12-regular text-text-subtle">{formatKeybind(cmd.keybind!)}</span> + </Show> + </div> </button> )} </For> |
