mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-30 09:03:33 +00:00
feat(tui): discover project plugins
This commit is contained in:
parent
a2885d1662
commit
068c32df39
4 changed files with 61 additions and 1 deletions
16
.opencode/plugins/tui/discovery-smoke.ts
Normal file
16
.opencode/plugins/tui/discovery-smoke.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import type { Context } from "../../../packages/plugin/src/tui/context"
|
||||
|
||||
export default {
|
||||
id: "test.tui-discovery-smoke",
|
||||
setup(context: Context) {
|
||||
const timer = setTimeout(() => {
|
||||
context.ui.toast.show({
|
||||
title: "TUI plugin discovery works",
|
||||
message: "Loaded .opencode/plugins/tui/discovery-smoke.ts",
|
||||
variant: "success",
|
||||
duration: 30_000,
|
||||
})
|
||||
}, 1_000)
|
||||
return () => clearTimeout(timer)
|
||||
},
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ import { useToast } from "../ui/toast"
|
|||
import { useAttention } from "../context/attention"
|
||||
import { abbreviateHome } from "../util/path-format"
|
||||
import { builtins } from "./builtins"
|
||||
import { discoverTuiPlugins } from "./discovery"
|
||||
|
||||
export interface PackageResolver {
|
||||
readonly resolve: (spec: string) => Promise<string | undefined>
|
||||
|
|
@ -353,7 +354,7 @@ export function PluginProvider(props: ParentProps<{ packages: PackageResolver }>
|
|||
.filter(([, registration]) => registration.active)
|
||||
.map(([id]) => deactivate(id)),
|
||||
)
|
||||
const entries = config.data.plugins ?? []
|
||||
const entries = [...(await discoverTuiPlugins(paths.cwd)), ...(config.data.plugins ?? [])]
|
||||
batch(() => {
|
||||
setStore("registrations", reconcileStore({}))
|
||||
setStore("states", [])
|
||||
|
|
|
|||
16
packages/tui/src/plugin/discovery.ts
Normal file
16
packages/tui/src/plugin/discovery.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { readdir } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
|
||||
const extensions = new Set([".cjs", ".cts", ".js", ".jsx", ".mjs", ".mts", ".ts", ".tsx"])
|
||||
|
||||
export async function discoverTuiPlugins(cwd: string) {
|
||||
const directory = path.join(cwd, ".opencode", "plugins", "tui")
|
||||
const entries = await readdir(directory, { withFileTypes: true }).catch((error: unknown) => {
|
||||
if (error && typeof error === "object" && Reflect.get(error, "code") === "ENOENT") return []
|
||||
return Promise.reject(error)
|
||||
})
|
||||
return entries
|
||||
.filter((entry) => (entry.isFile() || entry.isSymbolicLink()) && extensions.has(path.extname(entry.name)))
|
||||
.map((entry) => path.join(directory, entry.name))
|
||||
.sort()
|
||||
}
|
||||
27
packages/tui/test/plugin-discovery.test.ts
Normal file
27
packages/tui/test/plugin-discovery.test.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { mkdir, writeFile } from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
import { expect, test } from "bun:test"
|
||||
import { discoverTuiPlugins } from "../src/plugin/discovery"
|
||||
import { tmpdir } from "./fixture/fixture"
|
||||
|
||||
test("discovers project TUI plugin files in stable order", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
const directory = path.join(tmp.path, ".opencode", "plugins", "tui")
|
||||
await mkdir(path.join(directory, "nested"), { recursive: true })
|
||||
await Promise.all([
|
||||
writeFile(path.join(directory, "second.tsx"), "export default {}"),
|
||||
writeFile(path.join(directory, "first.js"), "export default {}"),
|
||||
writeFile(path.join(directory, "ignored.json"), "{}"),
|
||||
writeFile(path.join(directory, "nested", "ignored.ts"), "export default {}"),
|
||||
])
|
||||
|
||||
expect(await discoverTuiPlugins(tmp.path)).toEqual([
|
||||
path.join(directory, "first.js"),
|
||||
path.join(directory, "second.tsx"),
|
||||
])
|
||||
})
|
||||
|
||||
test("returns no project TUI plugins when the directory is absent", async () => {
|
||||
await using tmp = await tmpdir()
|
||||
expect(await discoverTuiPlugins(tmp.path)).toEqual([])
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue