Files
neuron/packages/opencode/src/provider/hooks.ts
T
will.anderson cfca4cec19 feat(opencode): cut plugin system and remote behavior feeds; add SessionContext assembly and Runner
- delete plugin machinery (loader, install, meta, hooks) and all trigger sites
- fold first-party provider auth into static registry (provider/hooks.ts)
- remove remote instruction URL fetch, skills remote puller, TUI plugin host
- add session/context.ts: single provenance-tagged context assembly point
- add session/runner.ts: admit/context/stream/tools loop with compaction policy
- relocate audit artifacts to audit/ (FORK-AUDIT, instruction docs as evidence)
2026-08-22 16:13:29 -05:00

75 lines
2.7 KiB
TypeScript

import type { Hooks, PluginInput } from "@opencode-ai/plugin"
import { createOpencodeClient } from "@opencode-ai/sdk"
import { InstallationChannel } from "@opencode-ai/core/installation/version"
import { Effect } from "effect"
import { ServerAuth } from "@/server/auth"
import { InstanceState } from "@/effect/instance-state"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { CodexAuthPlugin } from "@/plugin/openai/codex"
import { gitlabAuthPlugin as GitlabAuthPlugin } from "opencode-gitlab-auth"
import { PoeAuthPlugin } from "opencode-poe-auth"
import { DigitalOceanAuthPlugin } from "@/plugin/digitalocean"
import { XaiAuthPlugin } from "@/plugin/xai"
import { CerebrasPlugin } from "@/plugin/cerebras"
// Static first-party auth providers. There is no plugin loader: this list IS
// the extension surface for provider authentication. Nothing user-configurable
// participates.
export async function authProviderHooks(input: {
directory: string
project: PluginInput["project"]
worktree: string
experimentalWebSockets: boolean
}): Promise<Hooks[]> {
const { Server } = await import("@/server/server")
const serverUrl = Server.url
const client = createOpencodeClient({
baseUrl: serverUrl?.toString() ?? "http://localhost:4096",
directory: input.directory,
headers: ServerAuth.headers(),
...(serverUrl ? {} : { fetch: async (...args) => Server.Default().app.fetch(...args) }),
})
const pluginInput: PluginInput = {
client,
project: input.project,
worktree: input.worktree,
directory: input.directory,
serverUrl: serverUrl ?? new URL("http://localhost:4096"),
// @ts-expect-error
$: typeof Bun === "undefined" ? undefined : Bun.$,
}
// Pre-release builds default WebSockets on; releases require explicit opt-in.
const experimentalWebSockets =
input.experimentalWebSockets || ["local", "dev", "beta"].includes(InstallationChannel)
const results = await Promise.allSettled([
CodexAuthPlugin(pluginInput, { experimentalWebSockets }),
GitlabAuthPlugin(pluginInput),
PoeAuthPlugin(pluginInput),
DigitalOceanAuthPlugin(pluginInput),
XaiAuthPlugin(pluginInput),
CerebrasPlugin(pluginInput),
])
return results.flatMap((result) => (result.status === "fulfilled" ? [result.value] : []))
}
// Effect-context variant for call sites already inside the instance runtime.
export const hooks = Effect.gen(function* () {
const ctx = yield* InstanceState.context
const flags = yield* RuntimeFlags.Service
return yield* Effect.promise(() =>
authProviderHooks({
directory: ctx.directory,
project: ctx.project,
worktree: ctx.worktree,
experimentalWebSockets: flags.experimentalWebSockets,
}),
)
})
export * as AuthProviders from "./hooks"