[Sync] opencode 2.x

This commit is contained in:
Coja
2026-09-17 21:25:54 +02:00
parent d8f6b30e2c
commit 4f5054ed0d
9 changed files with 161 additions and 163 deletions
@@ -0,0 +1,8 @@
// opencode v2 plugin "coja.verbose" — server half. Intentionally empty: all behaviour is in ./tui.ts.
// A local plugin is a DIRECTORY under ~/.config/opencode/plugins/ whose `server`/`index` and `tui`
// modules are resolved by name (packages/plugin/src/host.ts resolve()). No imports on purpose:
// `define()` is an identity helper, and a dependency-free module needs no node_modules.
export default {
id: "coja.verbose",
setup() {},
}
@@ -0,0 +1,62 @@
// opencode v2 TUI plugin: one key toggles the "verbose view".
//
// v2 dropped the v1 tool-details / timestamps / generic-output toggles. The session view now has two
// display toggles that matter: thinking blocks (session.thinking show|hide) and exploration grouping
// (session.grouping auto|none — "auto" folds read/glob/grep tool calls into one collapsed group).
// Verbose = thinking expanded AND tool calls shown individually. Both settings persist in the TUI config.
//
// State is read from the built-in commands' live titles (the only plugin-visible signal):
// session.toggle.thinking → "Collapse thinking" while expanded, else "Expand thinking"
// session.toggle.exploration_grouping → "Show tool calls individually" while grouped, else "Group related tool calls"
// then only the toggles that differ from the target are dispatched, so a mixed state converges.
//
// Auto-discovered from ~/.config/opencode/plugins/verbose/ (server.ts + this file). Key configurable
// via plugin options; default <leader>v. Also /verbose and a command-palette entry.
const THINKING = "session.toggle.thinking"
const GROUPING = "session.toggle.exploration_grouping"
type Command = { readonly id?: string; readonly title?: string }
type Context = {
readonly options?: Readonly<Record<string, unknown>>
readonly keymap: {
layer(input: () => { readonly commands?: readonly unknown[] }): void
dispatch(id: string, input?: string): void
commands(): readonly Command[]
}
readonly ui: { readonly toast: { show(o: { message: string; variant?: string; duration?: number }): void } }
}
export default {
id: "coja.verbose",
setup(context: Context) {
const key = typeof context.options?.key === "string" && context.options.key ? (context.options.key as string) : "<leader>v"
const title = (id: string) => context.keymap.commands().find((c) => c.id === id)?.title ?? ""
context.keymap.layer(() => ({
commands: [
{
id: "verbose.toggle",
title: "Toggle verbose view (expand thinking, ungroup tool calls)",
group: "Session",
bind: key,
palette: true,
slash: { name: "verbose" },
run() {
const thinkingTitle = title(THINKING)
const groupingTitle = title(GROUPING)
if (!thinkingTitle && !groupingTitle) {
context.ui.toast.show({ message: "Verbose view: open a session first", variant: "warning", duration: 2000 })
return
}
const thinkingVerbose = thinkingTitle.startsWith("Collapse")
const groupingVerbose = groupingTitle.startsWith("Group")
const on = !(thinkingVerbose && groupingVerbose)
if (thinkingTitle && thinkingVerbose !== on) context.keymap.dispatch(THINKING)
if (groupingTitle && groupingVerbose !== on) context.keymap.dispatch(GROUPING)
context.ui.toast.show({ message: on ? "Verbose view on" : "Verbose view off", variant: "info", duration: 1500 })
},
},
],
}))
},
}