diff --git a/packages/opencode/script/check-migrations.ts b/packages/opencode/script/check-migrations.ts deleted file mode 100644 index f5eaf79323..0000000000 --- a/packages/opencode/script/check-migrations.ts +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bun - -import { $ } from "bun" - -// drizzle-kit check compares schema to migrations, exits non-zero if drift -const result = await $`bun drizzle-kit check`.quiet().nothrow() - -if (result.exitCode !== 0) { - console.error("Schema has changes not captured in migrations!") - console.error("Run: bun drizzle-kit generate") - console.error("") - console.error(result.stderr.toString()) - process.exit(1) -} - -console.log("Migrations are up to date") diff --git a/packages/opencode/script/time.ts b/packages/opencode/script/time.ts deleted file mode 100755 index 0db795ed0a..0000000000 --- a/packages/opencode/script/time.ts +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bun - -import path from "path" -const toDynamicallyImport = path.join(process.cwd(), process.argv[2]) -await import(toDynamicallyImport) -console.log(performance.now()) diff --git a/packages/opencode/script/trace-imports.ts b/packages/opencode/script/trace-imports.ts deleted file mode 100755 index 3aad338515..0000000000 --- a/packages/opencode/script/trace-imports.ts +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env bun -import * as path from "path" -import * as ts from "typescript" - -const BASE_DIR = "/home/thdxr/dev/projects/anomalyco/opencode/packages/opencode" - -// Get entry file from command line arg or use default -const ENTRY_FILE = process.argv[2] || "src/cli/cmd/tui/plugin/index.ts" - -const visited = new Set() - -function resolveImport(importPath: string, fromFile: string): string | null { - if (importPath.startsWith("@/")) { - return path.join(BASE_DIR, "src", importPath.slice(2)) - } - - if (importPath.startsWith("./") || importPath.startsWith("../")) { - const dir = path.dirname(fromFile) - return path.resolve(dir, importPath) - } - - return null -} - -function isInternalImport(importPath: string): boolean { - return importPath.startsWith("@/") || importPath.startsWith("./") || importPath.startsWith("../") -} - -async function tryExtensions(filePath: string): Promise { - const extensions = [".ts", ".tsx", ".js", ".jsx"] - - try { - const file = Bun.file(filePath) - const stat = await file.stat() - - if (stat?.isDirectory()) { - for (const ext of extensions) { - const indexPath = path.join(filePath, "index" + ext) - const indexFile = Bun.file(indexPath) - if (await indexFile.exists()) return indexPath - } - return null - } - - // It's a file - return filePath - } catch { - // Path doesn't exist, try adding extensions - for (const ext of extensions) { - const withExt = filePath + ext - const extFile = Bun.file(withExt) - if (await extFile.exists()) return withExt - } - return null - } -} - -function extractImports(sourceFile: ts.SourceFile): string[] { - const imports: string[] = [] - - function visit(node: ts.Node) { - // import x from "path" or import { x } from "path" - if (ts.isImportDeclaration(node)) { - // Skip type-only imports - if (node.importClause?.isTypeOnly) return - - const moduleSpec = node.moduleSpecifier - if (ts.isStringLiteral(moduleSpec)) { - imports.push(moduleSpec.text) - } - } - - // export { x } from "path" - if (ts.isExportDeclaration(node) && node.moduleSpecifier) { - if (ts.isStringLiteral(node.moduleSpecifier)) { - imports.push(node.moduleSpecifier.text) - } - } - - // Dynamic import: import("path") - if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) { - const arg = node.arguments[0] - if (arg && ts.isStringLiteral(arg)) { - imports.push(arg.text) - } - } - - ts.forEachChild(node, visit) - } - - visit(sourceFile) - return imports -} - -async function traceFile(filePath: string, depth = 0): Promise { - const normalizedPath = path.relative(BASE_DIR, filePath) - - if (visited.has(filePath)) { - return - } - - // Only trace TypeScript/JavaScript files - if (!filePath.match(/\.(ts|tsx|js|jsx)$/)) { - return - } - - visited.add(filePath) - console.log("\t".repeat(depth) + normalizedPath) - - let content: string - try { - content = await Bun.file(filePath).text() - } catch { - return - } - - const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true) - - const imports = extractImports(sourceFile) - const internalImports = imports.filter(isInternalImport) - const externalImports = imports.filter((imp) => !isInternalImport(imp)) - - // Print external imports - for (const imp of externalImports) { - console.log("\t".repeat(depth + 1) + `[ext] ${imp}`) - } - - for (const imp of internalImports) { - const resolved = resolveImport(imp, filePath) - if (!resolved) continue - - const actualPath = await tryExtensions(resolved) - if (!actualPath) continue - - await traceFile(actualPath, depth + 1) - } -} - -async function main() { - const entryPath = path.join(BASE_DIR, ENTRY_FILE) - - // Check if file exists - const file = Bun.file(entryPath) - if (!(await file.exists())) { - console.error(`File not found: ${ENTRY_FILE}`) - console.error(`Resolved to: ${entryPath}`) - process.exit(1) - } - - await traceFile(entryPath) -} - -main().catch(console.error) diff --git a/packages/opencode/specs/v2/api.ts b/packages/opencode/specs/v2/api.ts deleted file mode 100644 index b8b5d6abce..0000000000 --- a/packages/opencode/specs/v2/api.ts +++ /dev/null @@ -1,67 +0,0 @@ -// @ts-nocheck - -import { OpenCode } from "@opencode-ai/core" -import { ReadTool } from "@opencode-ai/core/tools" - -const opencode = OpenCode.make({}) - -opencode.tool.add(ReadTool) - -opencode.tool.add({ - name: "bash", - schema: { - type: "object", - properties: { - command: { - type: "string", - description: "The command to run.", - }, - }, - required: ["command"], - }, - execute(input, ctx) {}, -}) - -opencode.auth.add({ - provider: "openai", - type: "api", - value: process.env.OPENAI_API_KEY, -}) - -opencode.agent.add({ - name: "build", - permissions: [], - model: { - id: "gpt-5-5", - provider: "openai", - variant: "xhigh", - }, -}) - -const sessionID = await opencode.session.create({ - agent: "build", -}) - -opencode.subscribe((event) => { - console.log(event) -}) - -await opencode.session.prompt({ - sessionID, - text: "hey what is up", -}) - -await opencode.session.prompt({ - sessionID, - text: "what is up with this", - files: [ - { - mime: "image/png", - uri: "data:image/png;base64,xxxx", - }, - ], -}) - -await opencode.session.wait() - -console.log(await opencode.session.messages(sessionID)) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx deleted file mode 100644 index 1d58401ebc..0000000000 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { createMemo, createResource } from "solid-js" -import { DialogSelect } from "@tui/ui/dialog-select" -import { useDialog } from "@tui/ui/dialog" -import { useProject } from "@tui/context/project" -import { useSDK } from "@tui/context/sdk" -import { createStore } from "solid-js/store" - -export function DialogTag(props: { onSelect?: (value: string) => void }) { - const sdk = useSDK() - const dialog = useDialog() - const project = useProject() - - const [store] = createStore({ - filter: "", - }) - - const [files] = createResource( - () => [store.filter], - async () => { - const result = await sdk.client.find.files({ - query: store.filter, - workspace: project.workspace.current(), - }) - if (result.error) return [] - const sliced = (result.data ?? []).slice(0, 5) - return sliced - }, - ) - - const options = createMemo(() => - (files() ?? []).map((file) => ({ - value: file, - title: file, - })), - ) - - return ( - { - props.onSelect?.(option.value) - dialog.clear() - }} - /> - ) -} diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx deleted file mode 100644 index c5ef70ef06..0000000000 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { DialogSelect } from "@tui/ui/dialog-select" -import { useRoute } from "@tui/context/route" - -export function DialogSubagent(props: { sessionID: string }) { - const route = useRoute() - - return ( - { - route.navigate({ - type: "session", - sessionID: props.sessionID, - }) - dialog.clear() - }, - }, - ]} - /> - ) -} diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx deleted file mode 100644 index c3a96254e9..0000000000 --- a/packages/opencode/src/cli/cmd/tui/routes/session/footer.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { createMemo, Match, onCleanup, onMount, Show, Switch } from "solid-js" -import { useTheme } from "../../context/theme" -import { useSync } from "../../context/sync" -import { useDirectory } from "../../context/directory" -import { useConnected } from "../../component/use-connected" -import { createStore } from "solid-js/store" -import { useRoute } from "../../context/route" - -export function Footer() { - const { theme } = useTheme() - const sync = useSync() - const route = useRoute() - const mcp = createMemo(() => Object.values(sync.data.mcp).filter((x) => x.status === "connected").length) - const mcpError = createMemo(() => Object.values(sync.data.mcp).some((x) => x.status === "failed")) - const lsp = createMemo(() => Object.keys(sync.data.lsp)) - const permissions = createMemo(() => { - if (route.data.type !== "session") return [] - return sync.data.permission[route.data.sessionID] ?? [] - }) - const directory = useDirectory() - const connected = useConnected() - - const [store, setStore] = createStore({ - welcome: false, - }) - - onMount(() => { - // Track all timeouts to ensure proper cleanup - const timeouts: ReturnType[] = [] - - function tick() { - if (connected()) return - if (!store.welcome) { - setStore("welcome", true) - timeouts.push(setTimeout(() => tick(), 5000)) - return - } - - if (store.welcome) { - setStore("welcome", false) - timeouts.push(setTimeout(() => tick(), 10_000)) - return - } - } - timeouts.push(setTimeout(() => tick(), 10_000)) - - onCleanup(() => { - timeouts.forEach(clearTimeout) - }) - }) - - return ( - - {directory()} - - - - - Get started /connect - - - - 0}> - - {permissions().length} Permission - {permissions().length > 1 ? "s" : ""} - - - - 0 ? theme.success : theme.textMuted }}>• {lsp().length} LSP - - - - - - - - - - - - {mcp()} MCP - - - /status - - - - - ) -} diff --git a/packages/opencode/test/fixture/flock-worker.ts b/packages/opencode/test/fixture/flock-worker.ts deleted file mode 100644 index 0b9c314c08..0000000000 --- a/packages/opencode/test/fixture/flock-worker.ts +++ /dev/null @@ -1,72 +0,0 @@ -import fs from "fs/promises" -import { Flock } from "@opencode-ai/core/util/flock" - -type Msg = { - key: string - dir: string - staleMs?: number - timeoutMs?: number - baseDelayMs?: number - maxDelayMs?: number - holdMs?: number - ready?: string - active?: string - done?: string -} - -function sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms) - }) -} - -function input() { - const raw = process.argv[2] - if (!raw) { - throw new Error("Missing flock worker input") - } - - return JSON.parse(raw) as Msg -} - -async function job(input: Msg) { - if (input.ready) { - await fs.writeFile(input.ready, String(process.pid)) - } - - if (input.active) { - await fs.writeFile(input.active, String(process.pid), { flag: "wx" }) - } - - try { - if (input.holdMs && input.holdMs > 0) { - await sleep(input.holdMs) - } - - if (input.done) { - await fs.appendFile(input.done, "1\n") - } - } finally { - if (input.active) { - await fs.rm(input.active, { force: true }) - } - } -} - -async function main() { - const msg = input() - - await Flock.withLock(msg.key, () => job(msg), { - dir: msg.dir, - staleMs: msg.staleMs, - timeoutMs: msg.timeoutMs, - baseDelayMs: msg.baseDelayMs, - maxDelayMs: msg.maxDelayMs, - }) -} - -await main().catch((err) => { - const text = err instanceof Error ? (err.stack ?? err.message) : String(err) - process.stderr.write(text) - process.exit(1) -})