diff --git a/packages/opencode/src/cli/cmd/debug/agent.ts b/packages/opencode/src/cli/cmd/debug/agent.ts index 831ca08b69..1a3f79396c 100644 --- a/packages/opencode/src/cli/cmd/debug/agent.ts +++ b/packages/opencode/src/cli/cmd/debug/agent.ts @@ -11,7 +11,6 @@ import { Permission } from "../../../permission" import { iife } from "../../../util/iife" import { effectCmd, fail } from "../../effect-cmd" import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" import type { InstanceContext } from "@/project/instance" export const AgentCommand = effectCmd({ @@ -35,8 +34,7 @@ export const AgentCommand = effectCmd({ handler: Effect.fn("Cli.debug.agent")(function* (args) { const ctx = yield* InstanceRef if (!ctx) return - const store = yield* InstanceStore.Service - return yield* run(args, ctx).pipe(Effect.ensuring(store.dispose(ctx))) + return yield* run(args, ctx) }), }) diff --git a/packages/opencode/src/cli/cmd/debug/config.ts b/packages/opencode/src/cli/cmd/debug/config.ts index 8102fcfb88..15bd1c1a92 100644 --- a/packages/opencode/src/cli/cmd/debug/config.ts +++ b/packages/opencode/src/cli/cmd/debug/config.ts @@ -2,20 +2,13 @@ import { EOL } from "os" import { Effect } from "effect" import { Config } from "@/config/config" import { effectCmd } from "../../effect-cmd" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" export const ConfigCommand = effectCmd({ command: "config", describe: "show resolved configuration", builder: (yargs) => yargs, handler: Effect.fn("Cli.debug.config")(function* () { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const config = yield* Config.Service.use((cfg) => cfg.get()) - process.stdout.write(JSON.stringify(config, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const config = yield* Config.Service.use((cfg) => cfg.get()) + process.stdout.write(JSON.stringify(config, null, 2) + EOL) }), }) diff --git a/packages/opencode/src/cli/cmd/debug/file.ts b/packages/opencode/src/cli/cmd/debug/file.ts index 1e2eb13bb7..d9bb252ea9 100644 --- a/packages/opencode/src/cli/cmd/debug/file.ts +++ b/packages/opencode/src/cli/cmd/debug/file.ts @@ -4,8 +4,6 @@ import { File } from "../../../file" import { Ripgrep } from "@/file/ripgrep" import { effectCmd } from "../../effect-cmd" import { cmd } from "../cmd" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" const FileSearchCommand = effectCmd({ command: "search ", @@ -17,13 +15,8 @@ const FileSearchCommand = effectCmd({ description: "Search query", }), handler: Effect.fn("Cli.debug.file.search")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const results = yield* File.Service.use((svc) => svc.search({ query: args.query })) - process.stdout.write(results.join(EOL) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const results = yield* File.Service.use((svc) => svc.search({ query: args.query })) + process.stdout.write(results.join(EOL) + EOL) }), }) @@ -37,13 +30,8 @@ const FileReadCommand = effectCmd({ description: "File path to read", }), handler: Effect.fn("Cli.debug.file.read")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const content = yield* File.Service.use((svc) => svc.read(args.path)) - process.stdout.write(JSON.stringify(content, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const content = yield* File.Service.use((svc) => svc.read(args.path)) + process.stdout.write(JSON.stringify(content, null, 2) + EOL) }), }) @@ -52,13 +40,8 @@ const FileStatusCommand = effectCmd({ describe: "show file status information", builder: (yargs) => yargs, handler: Effect.fn("Cli.debug.file.status")(function* () { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const status = yield* File.Service.use((svc) => svc.status()) - process.stdout.write(JSON.stringify(status, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const status = yield* File.Service.use((svc) => svc.status()) + process.stdout.write(JSON.stringify(status, null, 2) + EOL) }), }) @@ -72,13 +55,8 @@ const FileListCommand = effectCmd({ description: "File path to list", }), handler: Effect.fn("Cli.debug.file.list")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const files = yield* File.Service.use((svc) => svc.list(args.path)) - process.stdout.write(JSON.stringify(files, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const files = yield* File.Service.use((svc) => svc.list(args.path)) + process.stdout.write(JSON.stringify(files, null, 2) + EOL) }), }) @@ -92,13 +70,8 @@ const FileTreeCommand = effectCmd({ default: process.cwd(), }), handler: Effect.fn("Cli.debug.file.tree")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const tree = yield* Effect.orDie(Ripgrep.Service.use((svc) => svc.tree({ cwd: args.dir, limit: 200 }))) - console.log(JSON.stringify(tree, null, 2)) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const tree = yield* Effect.orDie(Ripgrep.Service.use((svc) => svc.tree({ cwd: args.dir, limit: 200 }))) + console.log(JSON.stringify(tree, null, 2)) }), }) diff --git a/packages/opencode/src/cli/cmd/debug/lsp.ts b/packages/opencode/src/cli/cmd/debug/lsp.ts index b822a98bc1..b40b423181 100644 --- a/packages/opencode/src/cli/cmd/debug/lsp.ts +++ b/packages/opencode/src/cli/cmd/debug/lsp.ts @@ -4,8 +4,6 @@ import { effectCmd } from "../../effect-cmd" import { cmd } from "../cmd" import * as Log from "@opencode-ai/core/util/log" import { EOL } from "os" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" export const LSPCommand = cmd({ command: "lsp", @@ -20,18 +18,13 @@ const DiagnosticsCommand = effectCmd({ describe: "get diagnostics for a file", builder: (yargs) => yargs.positional("file", { type: "string", demandOption: true }), handler: Effect.fn("Cli.debug.lsp.diagnostics")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const out = yield* LSP.Service.use((lsp) => - Effect.gen(function* () { - yield* lsp.touchFile(args.file, "full") - return yield* lsp.diagnostics() - }), - ) - process.stdout.write(JSON.stringify(out, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const out = yield* LSP.Service.use((lsp) => + Effect.gen(function* () { + yield* lsp.touchFile(args.file, "full") + return yield* lsp.diagnostics() + }), + ) + process.stdout.write(JSON.stringify(out, null, 2) + EOL) }), }) @@ -40,14 +33,9 @@ export const SymbolsCommand = effectCmd({ describe: "search workspace symbols", builder: (yargs) => yargs.positional("query", { type: "string", demandOption: true }), handler: Effect.fn("Cli.debug.lsp.symbols")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - using _ = Log.Default.time("symbols") - const results = yield* LSP.Service.use((lsp) => lsp.workspaceSymbol(args.query)) - process.stdout.write(JSON.stringify(results, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + using _ = Log.Default.time("symbols") + const results = yield* LSP.Service.use((lsp) => lsp.workspaceSymbol(args.query)) + process.stdout.write(JSON.stringify(results, null, 2) + EOL) }), }) @@ -56,13 +44,8 @@ export const DocumentSymbolsCommand = effectCmd({ describe: "get symbols from a document", builder: (yargs) => yargs.positional("uri", { type: "string", demandOption: true }), handler: Effect.fn("Cli.debug.lsp.documentSymbols")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - using _ = Log.Default.time("document-symbols") - const results = yield* LSP.Service.use((lsp) => lsp.documentSymbol(args.uri)) - process.stdout.write(JSON.stringify(results, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + using _ = Log.Default.time("document-symbols") + const results = yield* LSP.Service.use((lsp) => lsp.documentSymbol(args.uri)) + process.stdout.write(JSON.stringify(results, null, 2) + EOL) }), }) diff --git a/packages/opencode/src/cli/cmd/debug/ripgrep.ts b/packages/opencode/src/cli/cmd/debug/ripgrep.ts index f0be704485..ca95c1d559 100644 --- a/packages/opencode/src/cli/cmd/debug/ripgrep.ts +++ b/packages/opencode/src/cli/cmd/debug/ripgrep.ts @@ -4,7 +4,6 @@ import { Ripgrep } from "../../../file/ripgrep" import { effectCmd } from "../../effect-cmd" import { cmd } from "../cmd" import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" export const RipgrepCommand = cmd({ command: "rg", @@ -23,13 +22,10 @@ const TreeCommand = effectCmd({ handler: Effect.fn("Cli.debug.rg.tree")(function* (args) { const ctx = yield* InstanceRef if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const tree = yield* Effect.orDie( - Ripgrep.Service.use((svc) => svc.tree({ cwd: ctx.directory, limit: args.limit })), - ) - process.stdout.write(tree + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const tree = yield* Effect.orDie( + Ripgrep.Service.use((svc) => svc.tree({ cwd: ctx.directory, limit: args.limit })), + ) + process.stdout.write(tree + EOL) }), }) @@ -53,22 +49,19 @@ const FilesCommand = effectCmd({ handler: Effect.fn("Cli.debug.rg.files")(function* (args) { const ctx = yield* InstanceRef if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const rg = yield* Ripgrep.Service - const files = yield* rg - .files({ - cwd: ctx.directory, - glob: args.glob ? [args.glob] : undefined, - }) - .pipe( - Stream.take(args.limit ?? Infinity), - Stream.runCollect, - Effect.map((c) => [...c]), - Effect.orDie, - ) - process.stdout.write(files.join(EOL) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const rg = yield* Ripgrep.Service + const files = yield* rg + .files({ + cwd: ctx.directory, + glob: args.glob ? [args.glob] : undefined, + }) + .pipe( + Stream.take(args.limit ?? Infinity), + Stream.runCollect, + Effect.map((c) => [...c]), + Effect.orDie, + ) + process.stdout.write(files.join(EOL) + EOL) }), }) @@ -93,19 +86,16 @@ const SearchCommand = effectCmd({ handler: Effect.fn("Cli.debug.rg.search")(function* (args) { const ctx = yield* InstanceRef if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const results = yield* Effect.orDie( - Ripgrep.Service.use((svc) => - svc.search({ - cwd: ctx.directory, - pattern: args.pattern, - glob: args.glob as string[] | undefined, - limit: args.limit, - }), - ), - ) - process.stdout.write(JSON.stringify(results.items, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const results = yield* Effect.orDie( + Ripgrep.Service.use((svc) => + svc.search({ + cwd: ctx.directory, + pattern: args.pattern, + glob: args.glob as string[] | undefined, + limit: args.limit, + }), + ), + ) + process.stdout.write(JSON.stringify(results.items, null, 2) + EOL) }), }) diff --git a/packages/opencode/src/cli/cmd/debug/skill.ts b/packages/opencode/src/cli/cmd/debug/skill.ts index e23410a69b..3b120da3cb 100644 --- a/packages/opencode/src/cli/cmd/debug/skill.ts +++ b/packages/opencode/src/cli/cmd/debug/skill.ts @@ -2,21 +2,14 @@ import { EOL } from "os" import { Effect } from "effect" import { Skill } from "../../../skill" import { effectCmd } from "../../effect-cmd" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" export const SkillCommand = effectCmd({ command: "skill", describe: "list all available skills", builder: (yargs) => yargs, handler: Effect.fn("Cli.debug.skill")(function* () { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const skill = yield* Skill.Service - const skills = yield* skill.all() - process.stdout.write(JSON.stringify(skills, null, 2) + EOL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const skill = yield* Skill.Service + const skills = yield* skill.all() + process.stdout.write(JSON.stringify(skills, null, 2) + EOL) }), }) diff --git a/packages/opencode/src/cli/cmd/debug/snapshot.ts b/packages/opencode/src/cli/cmd/debug/snapshot.ts index 1675f175df..e37e63dc47 100644 --- a/packages/opencode/src/cli/cmd/debug/snapshot.ts +++ b/packages/opencode/src/cli/cmd/debug/snapshot.ts @@ -2,8 +2,6 @@ import { Effect } from "effect" import { Snapshot } from "../../../snapshot" import { effectCmd } from "../../effect-cmd" import { cmd } from "../cmd" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" export const SnapshotCommand = cmd({ command: "snapshot", @@ -16,13 +14,8 @@ const TrackCommand = effectCmd({ command: "track", describe: "track current snapshot state", handler: Effect.fn("Cli.debug.snapshot.track")(function* () { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const out = yield* Snapshot.Service.use((svc) => svc.track()) - console.log(out) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const out = yield* Snapshot.Service.use((svc) => svc.track()) + console.log(out) }), }) @@ -36,13 +29,8 @@ const PatchCommand = effectCmd({ demandOption: true, }), handler: Effect.fn("Cli.debug.snapshot.patch")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const out = yield* Snapshot.Service.use((svc) => svc.patch(args.hash)) - console.log(out) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const out = yield* Snapshot.Service.use((svc) => svc.patch(args.hash)) + console.log(out) }), }) @@ -56,12 +44,7 @@ const DiffCommand = effectCmd({ demandOption: true, }), handler: Effect.fn("Cli.debug.snapshot.diff")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const out = yield* Snapshot.Service.use((svc) => svc.diff(args.hash)) - console.log(out) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const out = yield* Snapshot.Service.use((svc) => svc.diff(args.hash)) + console.log(out) }), }) diff --git a/packages/opencode/src/cli/cmd/export.ts b/packages/opencode/src/cli/cmd/export.ts index 5ff282b543..bf73ce941e 100644 --- a/packages/opencode/src/cli/cmd/export.ts +++ b/packages/opencode/src/cli/cmd/export.ts @@ -6,8 +6,6 @@ import { UI } from "../ui" import * as prompts from "@clack/prompts" import { EOL } from "os" import { Effect } from "effect" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" function redact(kind: string, id: string, value: string) { return value.trim() ? `[redacted:${kind}:${id}]` : value @@ -234,10 +232,7 @@ export const ExportCommand = effectCmd({ type: "boolean", }), handler: Effect.fn("Cli.export")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* run(args).pipe(Effect.ensuring(store.dispose(ctx))) + return yield* run(args) }), }) diff --git a/packages/opencode/src/cli/cmd/import.ts b/packages/opencode/src/cli/cmd/import.ts index 8d19376662..419e81379b 100644 --- a/packages/opencode/src/cli/cmd/import.ts +++ b/packages/opencode/src/cli/cmd/import.ts @@ -5,7 +5,6 @@ import { CliError, effectCmd } from "../effect-cmd" import { Database } from "@/storage/db" import { SessionTable, MessageTable, PartTable } from "../../session/session.sql" import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" import { ShareNext } from "@/share/share-next" import { EOL } from "os" import { Filesystem } from "@/util/filesystem" @@ -88,13 +87,9 @@ export const ImportCommand = effectCmd({ demandOption: true, }), handler: Effect.fn("Cli.import")(function* (args) { - // effectCmd always provides InstanceRef via InstanceStore.Service.provide; this is an invariant. const ctx = yield* InstanceRef if (!ctx) return yield* Effect.die("InstanceRef not provided") - const store = yield* InstanceStore.Service - // Ensure store.dispose runs disposers and emits server.instance.disposed - // on every exit path: success, early return, typed failure, defect, interrupt. - return yield* runImport(args.file, ctx.project.id).pipe(Effect.ensuring(store.dispose(ctx))) + return yield* runImport(args.file, ctx.project.id) }), }) diff --git a/packages/opencode/src/cli/cmd/session.ts b/packages/opencode/src/cli/cmd/session.ts index dbf27ccc6c..08c0df929c 100644 --- a/packages/opencode/src/cli/cmd/session.ts +++ b/packages/opencode/src/cli/cmd/session.ts @@ -12,8 +12,6 @@ import { Process } from "@/util/process" import { EOL } from "os" import path from "path" import { which } from "../../util/which" -import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" function pagerCmd(): string[] { const lessOptions = ["-R", "-S"] @@ -59,17 +57,12 @@ export const SessionDeleteCommand = effectCmd({ demandOption: true, }), handler: Effect.fn("Cli.session.delete")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const svc = yield* Session.Service - const sessionID = SessionID.make(args.sessionID) - // Match legacy try/catch — Session.get surfaces NotFoundError as a defect. - yield* svc.get(sessionID).pipe(Effect.catchCause(() => fail(`Session not found: ${args.sessionID}`))) - yield* svc.remove(sessionID) - UI.println(UI.Style.TEXT_SUCCESS_BOLD + `Session ${args.sessionID} deleted` + UI.Style.TEXT_NORMAL) - }).pipe(Effect.ensuring(store.dispose(ctx))) + const svc = yield* Session.Service + const sessionID = SessionID.make(args.sessionID) + // Match legacy try/catch — Session.get surfaces NotFoundError as a defect. + yield* svc.get(sessionID).pipe(Effect.catchCause(() => fail(`Session not found: ${args.sessionID}`))) + yield* svc.remove(sessionID) + UI.println(UI.Style.TEXT_SUCCESS_BOLD + `Session ${args.sessionID} deleted` + UI.Style.TEXT_NORMAL) }), }) @@ -90,39 +83,34 @@ export const SessionListCommand = effectCmd({ default: "table", }), handler: Effect.fn("Cli.session.list")(function* (args) { - const ctx = yield* InstanceRef - if (!ctx) return - const store = yield* InstanceStore.Service - return yield* Effect.gen(function* () { - const sessions = yield* Session.Service.use((svc) => svc.list({ roots: true, limit: args.maxCount })) + const sessions = yield* Session.Service.use((svc) => svc.list({ roots: true, limit: args.maxCount })) - if (sessions.length === 0) return + if (sessions.length === 0) return - const output = args.format === "json" ? formatSessionJSON(sessions) : formatSessionTable(sessions) + const output = args.format === "json" ? formatSessionJSON(sessions) : formatSessionTable(sessions) - const shouldPaginate = process.stdout.isTTY && !args.maxCount && args.format === "table" + const shouldPaginate = process.stdout.isTTY && !args.maxCount && args.format === "table" - if (shouldPaginate) { - yield* Effect.promise(async () => { - const proc = Process.spawn(pagerCmd(), { - stdin: "pipe", - stdout: "inherit", - stderr: "inherit", - }) - - if (!proc.stdin) { - console.log(output) - return - } - - proc.stdin.write(output) - proc.stdin.end() - await proc.exited + if (shouldPaginate) { + yield* Effect.promise(async () => { + const proc = Process.spawn(pagerCmd(), { + stdin: "pipe", + stdout: "inherit", + stderr: "inherit", }) - } else { - console.log(output) - } - }).pipe(Effect.ensuring(store.dispose(ctx))) + + if (!proc.stdin) { + console.log(output) + return + } + + proc.stdin.write(output) + proc.stdin.end() + await proc.exited + }) + } else { + console.log(output) + } }), }) diff --git a/packages/opencode/src/cli/cmd/stats.ts b/packages/opencode/src/cli/cmd/stats.ts index 966eb5f662..8bf7b2345c 100644 --- a/packages/opencode/src/cli/cmd/stats.ts +++ b/packages/opencode/src/cli/cmd/stats.ts @@ -5,7 +5,6 @@ import { Database } from "@/storage/db" import { SessionTable } from "../../session/session.sql" import { Project } from "@/project/project" import { InstanceRef } from "@/effect/instance-ref" -import { InstanceStore } from "@/project/instance-store" import { AppRuntime } from "@/effect/app-runtime" interface SessionStats { @@ -70,8 +69,7 @@ export const StatsCommand = effectCmd({ handler: Effect.fn("Cli.stats")(function* (args) { const ctx = yield* InstanceRef if (!ctx) return - const store = yield* InstanceStore.Service - return yield* run(args, ctx.project).pipe(Effect.ensuring(store.dispose(ctx))) + return yield* run(args, ctx.project) }), })