refactor: extract shared util package

This commit is contained in:
Dax Raad
2026-07-19 20:39:55 -04:00
parent 68cdfeffeb
commit 6ce2519cab
520 changed files with 1043 additions and 1047 deletions
+42 -18
View File
@@ -126,14 +126,15 @@
"dependencies": {
"@effect/platform-node": "catalog:",
"@opencode-ai/client": "workspace:*",
"@opencode-ai/core": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/server": "workspace:*",
"@opencode-ai/tui": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@opentui/core": "catalog:",
"@opentui/solid": "catalog:",
"@parcel/watcher": "2.5.1",
"@silvia-odwyer/photon-node": "0.3.4",
"effect": "catalog:",
"immer": "11.1.4",
"jsonc-parser": "3.3.1",
@@ -358,51 +359,38 @@
"@ai-sdk/vercel": "2.0.39",
"@ai-sdk/xai": "3.0.102",
"@aws-sdk/credential-providers": "3.1057.0",
"@effect/opentelemetry": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@ff-labs/fff-bun": "0.9.4",
"@lydell/node-pty": "catalog:",
"@modelcontextprotocol/sdk": "1.29.0",
"@npmcli/arborist": "9.4.0",
"@npmcli/config": "10.8.1",
"@opencode-ai/ai": "workspace:*",
"@opencode-ai/codemode": "workspace:*",
"@opencode-ai/effect-drizzle-sqlite": "workspace:*",
"@opencode-ai/effect-sqlite-node": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@openrouter/ai-sdk-provider": "2.9.0",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "2.6.1",
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
"@opentelemetry/sdk-trace-base": "2.6.1",
"@parcel/watcher": "2.5.1",
"@silvia-odwyer/photon-node": "0.3.4",
"ai-gateway-provider": "3.1.2",
"bun-pty": "0.4.8",
"cross-spawn": "catalog:",
"diff": "catalog:",
"drizzle-orm": "catalog:",
"effect": "catalog:",
"fuzzysort": "3.1.0",
"gitlab-ai-provider": "6.11.1",
"glob": "13.0.5",
"google-auth-library": "10.5.0",
"gray-matter": "4.0.3",
"htmlparser2": "8.0.2",
"ignore": "7.0.5",
"immer": "11.1.4",
"jsonc-parser": "3.3.1",
"mime-types": "3.0.2",
"minimatch": "10.2.5",
"npm-package-arg": "13.0.2",
"resolve.exports": "catalog:",
"semver": "^7.6.3",
"turndown": "7.2.0",
"venice-ai-sdk-provider": "2.1.1",
"which": "6.0.1",
"xdg-basedir": "5.1.0",
"zod": "catalog:",
},
"devDependencies": {
@@ -417,10 +405,7 @@
"@parcel/watcher-win32-x64": "2.5.1",
"@tsconfig/bun": "catalog:",
"@types/bun": "catalog:",
"@types/cross-spawn": "catalog:",
"@types/node": "catalog:",
"@types/npm-package-arg": "6.1.4",
"@types/npmcli__arborist": "6.3.3",
"@types/semver": "catalog:",
"@types/turndown": "5.0.5",
"@types/which": "3.0.4",
@@ -708,6 +693,7 @@
"@opencode-ai/core": "workspace:*",
"@opencode-ai/http-recorder": "workspace:*",
"@opencode-ai/script": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@standard-schema/spec": "1.0.0",
"@tsconfig/bun": "catalog:",
"@types/babel__core": "7.20.5",
@@ -805,6 +791,7 @@
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/server": "workspace:*",
"@opencode-ai/util": "workspace:*",
"effect": "catalog:",
},
"devDependencies": {
@@ -838,6 +825,7 @@
"@opencode-ai/core": "workspace:*",
"@opencode-ai/protocol": "workspace:*",
"@opencode-ai/simulation": "workspace:*",
"@opencode-ai/util": "workspace:*",
"drizzle-orm": "catalog:",
"effect": "catalog:",
},
@@ -903,6 +891,7 @@
"@opencode-ai/ai": "workspace:*",
"@opencode-ai/core": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@opentui/core": "catalog:",
"effect": "catalog:",
},
@@ -1029,6 +1018,7 @@
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/simulation": "workspace:*",
"@opencode-ai/ui": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@opentui/core": "catalog:",
"@opentui/keymap": "catalog:",
"@opentui/solid": "catalog:",
@@ -1103,6 +1093,38 @@
"solid-js": "^1.9.0",
},
},
"packages/util": {
"name": "@opencode-ai/util",
"version": "1.18.3",
"dependencies": {
"@effect/opentelemetry": "catalog:",
"@effect/platform-node": "catalog:",
"@npmcli/arborist": "catalog:",
"@npmcli/config": "10.8.1",
"@opencode-ai/ai": "workspace:*",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "2.6.1",
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
"@opentelemetry/sdk-trace-base": "2.6.1",
"cross-spawn": "catalog:",
"effect": "catalog:",
"glob": "13.0.5",
"mime-types": "3.0.2",
"minimatch": "10.2.5",
"npm-package-arg": "13.0.2",
"resolve.exports": "catalog:",
"xdg-basedir": "5.1.0",
},
"devDependencies": {
"@tsconfig/bun": "catalog:",
"@types/bun": "catalog:",
"@types/cross-spawn": "catalog:",
"@types/node": "catalog:",
"@types/npm-package-arg": "6.1.4",
"@types/npmcli__arborist": "6.3.3",
"@typescript/native-preview": "catalog:",
},
},
"packages/web": {
"name": "@opencode-ai/web",
"version": "1.18.3",
@@ -2268,6 +2290,8 @@
"@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"],
"@opencode-ai/util": ["@opencode-ai/util@workspace:packages/util"],
"@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"],
"@opencode-ai/www": ["@opencode-ai/www@workspace:packages/www"],
+1 -1
View File
@@ -15,7 +15,7 @@
"dev:www": "bun run --cwd packages/www dev",
"dev:storybook": "bun --cwd packages/storybook storybook",
"lint": "oxlint",
"lint:effect-patterns": "ast-grep scan -c script/ast-grep/sgconfig.yml packages/core/src packages/server/src packages/protocol/src packages/cli/src",
"lint:effect-patterns": "ast-grep scan -c script/ast-grep/sgconfig.yml packages/util/src packages/core/src packages/server/src packages/protocol/src packages/cli/src",
"test:lint-rules": "ast-grep test -c script/ast-grep/sgconfig.yml",
"typecheck": "bun turbo typecheck --concurrency=3",
"typecheck:profile": "bun script/profile-typecheck.ts",
+2 -1
View File
@@ -25,14 +25,15 @@
"dependencies": {
"@effect/platform-node": "catalog:",
"@opencode-ai/client": "workspace:*",
"@opencode-ai/core": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/server": "workspace:*",
"@opencode-ai/tui": "workspace:*",
"@opencode-ai/util": "workspace:*",
"@opentui/core": "catalog:",
"@opentui/solid": "catalog:",
"@parcel/watcher": "2.5.1",
"@silvia-odwyer/photon-node": "0.3.4",
"effect": "catalog:",
"immer": "11.1.4",
"jsonc-parser": "3.3.1",
+1 -2
View File
@@ -1,6 +1,5 @@
import { createHash } from "node:crypto"
import { copyFile, mkdir, readdir, readFile, stat } from "node:fs/promises"
import { createRequire } from "node:module"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { getNodeAssets } from "@opentui/core/node-assets"
@@ -40,7 +39,7 @@ export async function collectNodeAssets(target: NodeTarget) {
{ key: target.parcelWatcherAsset, source: fileURLToPath(import.meta.resolve(target.parcelWatcherPackage)) },
{
key: photonWasmAsset,
source: createRequire(path.resolve(dir, "../core/package.json")).resolve(photonWasmAsset),
source: fileURLToPath(import.meta.resolve(photonWasmAsset)),
},
...attentionSoundAssets.map((key) => ({
key,
@@ -1,7 +1,7 @@
import { Cause, Effect, Exit, Option } from "effect"
import { Service } from "@opencode-ai/client/effect/service"
import { OpenCode, type OpenCodeClient } from "@opencode-ai/client/promise"
import { AppProcess } from "@opencode-ai/core/process"
import { AppProcess } from "@opencode-ai/util/process"
import { Commands } from "../../commands"
import { Runtime } from "../../../framework/runtime"
import { ServiceConfig } from "../../../services/service-config"
@@ -1,5 +1,5 @@
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { Global } from "@opencode-ai/core/global"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Global } from "@opencode-ai/util/global"
import { run } from "@opencode-ai/tui"
import { Commands } from "../commands"
import { Runtime } from "../../framework/runtime"
@@ -8,7 +8,7 @@ import { Context, Effect, FileSystem, Option } from "effect"
import { ServerConnection } from "../../services/server-connection"
import { Updater } from "../../services/updater"
import { UpdatePreflight } from "../../services/update-preflight"
import { Npm } from "@opencode-ai/core/npm"
import { Npm } from "@opencode-ai/util/npm"
export default Runtime.handler(Commands, (input) =>
Effect.gen(function* () {
@@ -3,7 +3,7 @@ import path from "node:path"
import { readFile, stat, writeFile } from "node:fs/promises"
import { Effect, Option } from "effect"
import { applyEdits, modify } from "jsonc-parser"
import { Global } from "@opencode-ai/core/global"
import { Global } from "@opencode-ai/util/global"
import { Commands } from "../../commands"
import { Runtime } from "../../../framework/runtime"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as Config from "./config"
import { Global } from "@opencode-ai/core/global"
import { Global } from "@opencode-ai/util/global"
import { Context, Effect, FileSystem, Layer, Option, Schema, Semaphore } from "effect"
import { produce, type Draft } from "immer"
import { applyEdits, modify, parse, type ParseError } from "jsonc-parser"
+2 -2
View File
@@ -1,10 +1,10 @@
import { Effect, FileSystem, Scope } from "effect"
import { Command } from "effect/unstable/cli"
import { Spec } from "./spec"
import { Global } from "@opencode-ai/core/global"
import { Global } from "@opencode-ai/util/global"
import { Updater } from "../services/updater"
import { Config } from "../config"
import { Npm } from "@opencode-ai/core/npm"
import { Npm } from "@opencode-ai/util/npm"
export type Input<Value> =
Value extends Spec.Node<infer _Name, infer Command, infer _Commands>
+6 -6
View File
@@ -4,14 +4,14 @@ import { NodeRuntime, NodeServices } from "@effect/platform-node"
import { Effect } from "effect"
import { Commands } from "./commands/commands"
import { Runtime } from "./framework/runtime"
import { Observability } from "@opencode-ai/core/observability"
import { Observability } from "@opencode-ai/util/observability"
import { Updater } from "./services/updater"
import { InstallationChannel, InstallationVersion, InstallationLocal } from "@opencode-ai/core/installation/version"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { Global } from "@opencode-ai/core/global"
import { AppProcess } from "@opencode-ai/core/process"
import { InstallationChannel, InstallationVersion, InstallationLocal } from "@opencode-ai/util/installation/version"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Global } from "@opencode-ai/util/global"
import { AppProcess } from "@opencode-ai/util/process"
import { Config } from "./config"
import { Npm } from "@opencode-ai/core/npm"
import { Npm } from "@opencode-ai/util/npm"
const Handlers = Runtime.handlers(Commands, {
$: () => import("./commands/handlers/default"),
+2 -2
View File
@@ -1,6 +1,6 @@
import type { MiniFrontendInput } from "@opencode-ai/tui/mini"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Global } from "@opencode-ai/core/global"
import { Flag } from "@opencode-ai/util/flag"
import { Global } from "@opencode-ai/util/global"
import fs from "node:fs"
import { mkdir, readFile, writeFile } from "node:fs/promises"
import path from "node:path"
+1 -1
View File
@@ -1,6 +1,6 @@
import { Service, type Endpoint } from "@opencode-ai/client/effect/service"
import { OpenCode, type OpenCodeClient, type SessionMessageAssistantTool } from "@opencode-ai/client/promise"
import { FSUtil } from "@opencode-ai/core/fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { open } from "node:fs/promises"
import path from "node:path"
import { readStdin } from "../util/io"
+4 -4
View File
@@ -2,10 +2,10 @@ export * as ServerProcess from "./server-process"
import { NodeServices } from "@effect/platform-node"
import { Service, type DiscoverOptions, type Info } from "@opencode-ai/client/effect/service"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { Global } from "@opencode-ai/core/global"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { AppProcess } from "@opencode-ai/core/process"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Global } from "@opencode-ai/util/global"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { AppProcess } from "@opencode-ai/util/process"
import { randomBytes, randomUUID } from "node:crypto"
import path from "node:path"
import { Effect, FileSystem, Logger, Option, Redacted, Schedule, Schema } from "effect"
@@ -1,6 +1,6 @@
import { Service, type Endpoint, type EnsureOptions } from "@opencode-ai/client/effect/service"
import { ClientError, isUnauthorizedError, OpenCode } from "@opencode-ai/client/promise"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Effect, Redacted } from "effect"
import { Env } from "../env"
import { ServiceConfig } from "./service-config"
+3 -3
View File
@@ -1,6 +1,6 @@
import { Global } from "@opencode-ai/core/global"
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
import { Hash } from "@opencode-ai/core/util/hash"
import { Global } from "@opencode-ai/util/global"
import { InstallationChannel, InstallationVersion } from "@opencode-ai/util/installation/version"
import { Hash } from "@opencode-ai/util/hash"
import { Service } from "@opencode-ai/client/effect/service"
import { Effect, FileSystem, Option, Schema } from "effect"
import { randomBytes } from "crypto"
+2 -2
View File
@@ -1,6 +1,6 @@
import { Service, type Endpoint } from "@opencode-ai/client/effect/service"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { CrossSpawnSpawner } from "@opencode-ai/util/cross-spawn-spawner"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Deferred, Effect, Schema, Stream } from "effect"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import { randomBytes } from "node:crypto"
@@ -3,7 +3,7 @@
// version-mismatched background service before the TUI attaches.
import { createCliRenderer, RGBA, TextAttributes, type CliRenderer, type ThemeMode } from "@opentui/core"
import { render, useTerminalDimensions } from "@opentui/solid"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { registerOpencodeSpinner } from "@opencode-ai/tui/component/register-spinner"
import { SPINNER_FRAMES } from "@opencode-ai/tui/component/spinner"
import { go } from "@opencode-ai/tui/logo"
+4 -4
View File
@@ -1,11 +1,11 @@
import { Global } from "@opencode-ai/core/global"
import { Flag } from "@opencode-ai/core/flag/flag"
import { AppProcess } from "@opencode-ai/core/process"
import { Global } from "@opencode-ai/util/global"
import { Flag } from "@opencode-ai/util/flag"
import { AppProcess } from "@opencode-ai/util/process"
import {
InstallationChannel,
InstallationLocal,
InstallationVersion,
} from "@opencode-ai/core/installation/version"
} from "@opencode-ai/util/installation/version"
import { Context, Duration, Effect, FileSystem, Layer } from "effect"
import { ChildProcess } from "effect/unstable/process"
import { parse, type ParseError } from "jsonc-parser"
+1 -1
View File
@@ -1,5 +1,5 @@
import { NodeFileSystem } from "@effect/platform-node"
import { Global } from "@opencode-ai/core/global"
import { Global } from "@opencode-ai/util/global"
import { Effect } from "effect"
import { expect, test } from "bun:test"
import path from "path"
@@ -5,6 +5,16 @@ import path from "node:path"
const root = path.resolve(import.meta.dir, "../../..")
describe("CLI frontend import boundaries", () => {
test("does not import Core directly", async () => {
const glob = new Bun.Glob("{src,test}/**/*.{ts,tsx}")
const imports: string[] = []
for await (const file of glob.scan({ cwd: path.join(root, "packages/cli") })) {
const source = await Bun.file(path.join(root, "packages/cli", file)).text()
if (/["']@opencode-ai\/core(?:\/[^"']*)?["']/.test(source)) imports.push(file)
}
expect(imports).toEqual([])
})
test("exposes only the intentional package entrypoints", async () => {
const run = await import("@opencode-ai/cli/run")
const mini = await import("@opencode-ai/tui/mini")
+1 -1
View File
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test"
import { ClientError, OpenCode } from "@opencode-ai/client/promise"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import path from "node:path"
import { createMiniConnection, mergeInput as mergeInteractiveInput, resolveMiniTarget } from "../src/mini"
import { mergeInput as mergeNonInteractiveInput, parseRunModel } from "../src/run/run"
+2 -2
View File
@@ -1,6 +1,6 @@
import { NodeFileSystem } from "@effect/platform-node"
import { Global } from "@opencode-ai/core/global"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { Global } from "@opencode-ai/util/global"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { expect, test } from "bun:test"
import { Effect, FileSystem, Scope } from "effect"
import fs from "node:fs/promises"
+3 -85
View File
@@ -1,18 +1,9 @@
import { NodeFileSystem } from "@effect/platform-node"
import { Service, type Info } from "@opencode-ai/client/effect/service"
import { Database } from "@opencode-ai/core/database/database"
import { EventV2 } from "@opencode-ai/core/event"
import { EventTable } from "@opencode-ai/core/event/sql"
import { Global } from "@opencode-ai/core/global"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { Project } from "@opencode-ai/core/project"
import { ProjectTable } from "@opencode-ai/core/project/sql"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { SessionV2 } from "@opencode-ai/core/session"
import { SessionEvent } from "@opencode-ai/core/session/event"
import { SessionTable } from "@opencode-ai/core/session/sql"
import { Global } from "@opencode-ai/util/global"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { expect, test } from "bun:test"
import { Effect, Schedule, Schema } from "effect"
import { Effect, Schema } from "effect"
import fs from "node:fs/promises"
import os from "node:os"
import path from "node:path"
@@ -204,31 +195,6 @@ test("concurrent service processes elect one server", async () => {
XDG_DATA_HOME: path.join(root, "data"),
XDG_STATE_HOME: path.join(root, "state"),
}
const sessionID = SessionV2.ID.make("ses_service_recovery")
await withDatabase(
database,
Effect.gen(function* () {
const { db } = yield* Database.Service
yield* db
.insert(ProjectTable)
.values({ id: Project.ID.global, worktree: AbsolutePath.make(root), sandboxes: [] })
.run()
.pipe(Effect.orDie)
yield* db
.insert(SessionTable)
.values({
id: sessionID,
project_id: Project.ID.global,
slug: "recovery",
directory: root,
title: "recovery",
version: "test",
time_suspended: Date.now(),
})
.run()
.pipe(Effect.orDie)
}),
)
const command = [process.execPath, path.join(import.meta.dir, "../src/index.ts"), "serve", "--service"]
const registration = path.join(root, "state", "opencode", "service-local.json")
const port = await availablePort()
@@ -281,20 +247,6 @@ test("concurrent service processes elect one server", async () => {
contender.kill("SIGTERM")
await contender.exited
}
expect(
await withDatabase(
database,
Effect.gen(function* () {
const { db } = yield* Database.Service
return yield* db
.select({ timeSuspended: SessionTable.time_suspended })
.from(SessionTable)
.get()
.pipe(Effect.orDie)
}),
),
).toEqual({ timeSuspended: null })
expect(await waitForExecutionStart(database, sessionID)).toBe(1)
await Effect.runPromise(Service.stop({ file: registration }).pipe(Effect.provide(NodeFileSystem.layer)))
await winner?.exited
expect(await Bun.file(registration).exists()).toBe(false)
@@ -529,40 +481,6 @@ test("a failed service stays registered and owns the selected port until stopped
}
}, 30_000)
function withDatabase<A, E>(file: string, effect: Effect.Effect<A, E, Database.Service>) {
return Effect.runPromise(effect.pipe(Effect.provide(Database.layerFromPath(file)), Effect.scoped))
}
function waitForExecutionStart(file: string, sessionID: SessionV2.ID) {
return withDatabase(
file,
Effect.gen(function* () {
const { db } = yield* Database.Service
return yield* db
.select({ id: EventTable.id, sessionID: EventTable.aggregate_id, type: EventTable.type })
.from(EventTable)
.all()
.pipe(
Effect.orDie,
Effect.map((rows) =>
rows.filter(
(row) =>
row.sessionID === sessionID &&
row.type ===
EventV2.versionedType(
SessionEvent.Execution.Started.type,
SessionEvent.Execution.Started.durable.version,
),
),
),
Effect.filterOrFail((rows) => rows.length > 0),
Effect.map((rows) => rows.length),
Effect.retry(Schedule.max([Schedule.spaced("50 millis"), Schedule.recurs(200)])),
)
}),
)
}
async function waitForInfo(file: string, accept: (info: Info) => boolean = () => true) {
for (let attempt = 0; attempt < 400; attempt++) {
const value = await Bun.file(file)
+4 -21
View File
@@ -16,7 +16,6 @@
"opencode": "./bin/opencode"
},
"exports": {
"./effect/layer-node": "./src/effect/layer-node.ts",
"./effect/app-node": "./src/effect/app-node.ts",
"./session/runner": "./src/session/runner/index.ts",
"./instructions": "./src/instructions/index.ts",
@@ -44,9 +43,9 @@
"default": "./src/image/photon-wasm.bun.ts"
},
"#runtime-import": {
"bun": "./src/runtime/import.bun.ts",
"node": "./src/runtime/import.node.ts",
"default": "./src/runtime/import.bun.ts"
"bun": "@opencode-ai/util/runtime/import.bun",
"node": "@opencode-ai/util/runtime/import.node",
"default": "@opencode-ai/util/runtime/import.bun"
},
"#process-lock-ffi": {
"bun": "./src/util/process-lock-ffi.bun.ts",
@@ -57,10 +56,7 @@
"devDependencies": {
"@tsconfig/bun": "catalog:",
"@types/bun": "catalog:",
"@types/cross-spawn": "catalog:",
"@types/node": "catalog:",
"@types/npm-package-arg": "6.1.4",
"@types/npmcli__arborist": "6.3.3",
"@types/semver": "catalog:",
"@types/turndown": "5.0.5",
"@types/which": "3.0.4",
@@ -97,51 +93,38 @@
"@ai-sdk/vercel": "2.0.39",
"@ai-sdk/xai": "3.0.102",
"@aws-sdk/credential-providers": "3.1057.0",
"@effect/opentelemetry": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@lydell/node-pty": "catalog:",
"@modelcontextprotocol/sdk": "1.29.0",
"@ff-labs/fff-bun": "0.9.4",
"@npmcli/arborist": "9.4.0",
"@npmcli/config": "10.8.1",
"@opencode-ai/codemode": "workspace:*",
"@opencode-ai/effect-drizzle-sqlite": "workspace:*",
"@opencode-ai/effect-sqlite-node": "workspace:*",
"@opencode-ai/ai": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
"@opentelemetry/api": "1.9.0",
"@opentelemetry/context-async-hooks": "2.6.1",
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
"@opentelemetry/sdk-trace-base": "2.6.1",
"@opencode-ai/util": "workspace:*",
"@parcel/watcher": "2.5.1",
"@silvia-odwyer/photon-node": "0.3.4",
"@openrouter/ai-sdk-provider": "2.9.0",
"ai-gateway-provider": "3.1.2",
"bun-pty": "0.4.8",
"cross-spawn": "catalog:",
"diff": "catalog:",
"drizzle-orm": "catalog:",
"effect": "catalog:",
"fuzzysort": "3.1.0",
"gitlab-ai-provider": "6.11.1",
"glob": "13.0.5",
"google-auth-library": "10.5.0",
"gray-matter": "4.0.3",
"htmlparser2": "8.0.2",
"immer": "11.1.4",
"ignore": "7.0.5",
"jsonc-parser": "3.3.1",
"mime-types": "3.0.2",
"minimatch": "10.2.5",
"npm-package-arg": "13.0.2",
"resolve.exports": "catalog:",
"semver": "^7.6.3",
"turndown": "7.2.0",
"venice-ai-sdk-provider": "2.1.1",
"which": "6.0.1",
"xdg-basedir": "5.1.0",
"zod": "catalog:"
},
"overrides": {
+1 -1
View File
@@ -1,6 +1,6 @@
export * as AgentV2 from "./agent"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Array, Context, Effect, Layer, Types } from "effect"
import { Agent } from "@opencode-ai/schema/agent"
import { EventV2 } from "./event"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as AISDK from "./aisdk"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import type {
JSONSchema7,
JSONValue,
+1 -1
View File
@@ -1,6 +1,6 @@
export * as Catalog from "./catalog"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Array, Context, Effect, Layer, Option, Order, pipe } from "effect"
import { Catalog } from "@opencode-ai/schema/catalog"
import { ModelV2 } from "./model"
+2 -2
View File
@@ -1,12 +1,12 @@
export * as CommandV2 from "./command"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Schema, Types } from "effect"
import { Command } from "@opencode-ai/schema/command"
import { State } from "./state"
import { MCP } from "./mcp/index"
import { EventV2 } from "./event"
import { AppProcess } from "./process"
import { AppProcess } from "@opencode-ai/util/process"
import { ChildProcess } from "effect/unstable/process"
import { Config } from "./config"
import { Location } from "./location"
+3 -3
View File
@@ -1,6 +1,6 @@
export * as Config from "./config"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import path from "path"
import { isDeepStrictEqual } from "node:util"
import { type ParseError, parse } from "jsonc-parser"
@@ -11,8 +11,8 @@ import { Integration } from "@opencode-ai/schema/integration"
import { Credential } from "./credential"
import { EventV2 } from "./event"
import { Watcher } from "./filesystem/watcher"
import { FSUtil } from "./fs-util"
import { Global } from "./global"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Global } from "@opencode-ai/util/global"
import { Location } from "./location"
import { AbsolutePath } from "./schema"
import { ConfigAgent } from "./config/agent"
+2 -2
View File
@@ -7,10 +7,10 @@ import { AgentV2 } from "../../agent"
import { Config } from "../../config"
import { ConfigAgent } from "../agent"
import { ConfigMarkdown } from "../markdown"
import { FSUtil } from "../../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { ConfigAgentV1 } from "../../v1/config/agent"
import { ConfigMigrateV1 } from "../../v1/config/migrate"
import { Global } from "../../global"
import { Global } from "@opencode-ai/util/global"
import { PermissionV2 } from "../../permission"
import type { LocationMutation } from "../../location-mutation"
import type { ReadTool } from "../../tool/read"
+1 -1
View File
@@ -5,7 +5,7 @@ import path from "path"
import { Effect, Option, Schema, Stream } from "effect"
import { CommandV2 } from "../../command"
import { Config } from "../../config"
import { FSUtil } from "../../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { ConfigCommand } from "../command"
import { ConfigMarkdown } from "../markdown"
+1 -1
View File
@@ -7,7 +7,7 @@ import { Config } from "../../config"
import { ConfigReference } from "../reference"
import { Reference } from "../../reference"
import { AbsolutePath } from "../../schema"
import { Global } from "../../global"
import { Global } from "@opencode-ai/util/global"
import { Location } from "../../location"
export const Plugin = define({
+1 -1
View File
@@ -6,7 +6,7 @@ import { Effect, Stream } from "effect"
import { Config } from "../../config"
import { AbsolutePath } from "../../schema"
import { SkillV2 } from "../../skill"
import { Global } from "../../global"
import { Global } from "@opencode-ai/util/global"
import { Location } from "../../location"
export const Plugin = define({
+1 -1
View File
@@ -3,7 +3,7 @@ export * as ConfigVariable from "./variable"
import os from "os"
import path from "path"
import { Effect } from "effect"
import { FSUtil } from "../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { InvalidError } from "../v1/config/error"
type ParseSource =
@@ -1,10 +1,10 @@
export * as MoveSession from "./move-session"
import { Context, DateTime, Effect, Layer, Schema } from "effect"
import { makeGlobalNode } from "../effect/app-node"
import { FSUtil } from "../fs-util"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Git } from "../git"
import { Global } from "../global"
import { Global } from "@opencode-ai/util/global"
import { ProjectV2 } from "../project"
import { SessionV2 } from "../session"
import { SessionExecution } from "../session/execution"
+1 -1
View File
@@ -5,7 +5,7 @@ import { Context, Effect, Layer, Schema } from "effect"
import { Credential } from "@opencode-ai/schema/credential"
import { Integration } from "@opencode-ai/schema/integration"
import { Database } from "./database/database"
import { makeGlobalNode } from "./effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { CredentialTable } from "./credential/sql"
export const ID = Credential.ID
+4 -4
View File
@@ -3,12 +3,12 @@ export * as Database from "./database"
import { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
import { layer } from "#sqlite"
import { Context, Effect, Layer } from "effect"
import { Global } from "../global"
import { Flag } from "../flag/flag"
import { Global } from "@opencode-ai/util/global"
import { Flag } from "@opencode-ai/util/flag"
import { isAbsolute, join } from "path"
import { DatabaseMigration } from "./migration"
import { InstallationChannel } from "../installation/version"
import { makeGlobalNode } from "../effect/app-node"
import { InstallationChannel } from "@opencode-ai/util/installation/version"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
const makeDatabase = EffectDrizzleSqlite.makeWithDefaults()
type DatabaseShape = Effect.Success<typeof makeDatabase>
+2 -2
View File
@@ -1,7 +1,7 @@
import { buildLocationServiceMap } from "../location-services"
import { LocationServiceMap } from "../location-service-map"
import { LayerNode } from "./layer-node"
import { makeGlobalNode } from "./app-node"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
export function build<A, E>(root: LayerNode.Node<A, E, any>, replacements: LayerNode.Replacements = []) {
let allReplacements = replacements
+1 -1
View File
@@ -1,7 +1,7 @@
export * as EventLogger from "./event-logger"
import { Effect, Layer } from "effect"
import { makeGlobalNode } from "./effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { EventV2 } from "./event"
const Types = new Set([
+1 -1
View File
@@ -8,7 +8,7 @@ import { and, asc, eq, gt, inArray, lte, sql } from "drizzle-orm"
import { Database } from "./database/database"
import { EventSequenceTable, EventTable } from "./event/sql"
import { Location } from "./location"
import { makeGlobalNode } from "./effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { isDeepStrictEqual } from "node:util"
import { Durable } from "@opencode-ai/schema/durable-event-manifest"
+2 -2
View File
@@ -1,10 +1,10 @@
export * as FileMutation from "./file-mutation"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Schema } from "effect"
import { dirname } from "path"
import { KeyedMutex } from "./effect/keyed-mutex"
import { FSUtil } from "./fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
export interface Target {
readonly canonical: string
+2 -2
View File
@@ -1,9 +1,9 @@
export * as FileSystem from "./filesystem"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import path from "path"
import { Context, Effect, Layer, Schema } from "effect"
import { FSUtil } from "./fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Location } from "./location"
import { PositiveInt, RelativePath } from "./schema"
import { FileSystemSearch } from "./filesystem/search"
+1 -1
View File
@@ -1,4 +1,4 @@
import { Glob } from "../util/glob"
import { Glob } from "@opencode-ai/util/glob"
const FOLDERS = new Set([
"node_modules",
@@ -1,13 +1,13 @@
export * as LocationWatcher from "./location-watcher"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Stream } from "effect"
import { FileSystem } from "@opencode-ai/schema/filesystem"
import os from "os"
import path from "path"
import { Config } from "../config"
import { EventV2 } from "../event"
import { FSUtil } from "../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Git } from "../git"
import { Location } from "../location"
import { Watcher } from "./watcher"
+3 -3
View File
@@ -1,16 +1,16 @@
export * as FileSystemSearch from "./search"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import path from "path"
import { Context, Effect, Layer, Scope } from "effect"
import { Fff } from "#fff"
import fuzzysort from "fuzzysort"
import { FileSystem } from "../filesystem"
import { FSUtil } from "../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Location } from "../location"
import { Ripgrep } from "../ripgrep"
import { RelativePath } from "../schema"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/util/flag"
export interface Interface {
readonly find: (input: FileSystem.FindInput) => Effect.Effect<FileSystem.Entry[]>
+2 -2
View File
@@ -4,10 +4,10 @@ export * as Watcher from "./watcher"
import { createWrapper } from "@parcel/watcher/wrapper"
import type ParcelWatcher from "@parcel/watcher"
import { FileSystem } from "@opencode-ai/schema/filesystem"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { Cause, Context, Effect, Layer, PubSub, Scope, Stream } from "effect"
import { KeyedMutex } from "../effect/keyed-mutex"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/util/flag"
import { lazy } from "../util/lazy"
import { watch as watchFileSystem } from "node:fs"
import path from "path"
+1 -1
View File
@@ -2,7 +2,7 @@ export * as Form from "./form"
import { Form } from "@opencode-ai/schema/form"
import { Cache, Context, Deferred, Duration, Effect, Exit, Layer, Option, Schema } from "effect"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { EventV2 } from "./event"
const RETENTION = Duration.minutes(10)
+2 -2
View File
@@ -3,8 +3,8 @@ export * as Generate from "./generate"
import { LLM, LLMClient, LLMError } from "@opencode-ai/ai"
import { Context, Effect, Layer, Schema } from "effect"
import { Catalog } from "./catalog"
import { makeLocationNode } from "./effect/app-node"
import { llmClient } from "./effect/app-node-platform"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { llmClient } from "@opencode-ai/util/effect/app-node-platform"
import { Integration } from "./integration"
import { ModelV2 } from "./model"
import { SessionRunnerModel } from "./session/runner/model"
+3 -3
View File
@@ -5,9 +5,9 @@ import { randomUUID } from "crypto"
import { Context, Effect, Layer, Schema, Stream } from "effect"
import { ChildProcess } from "effect/unstable/process"
import { AbsolutePath, RelativePath } from "./schema"
import { FSUtil } from "./fs-util"
import { AppProcess } from "./process"
import { makeGlobalNode } from "./effect/app-node"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { AppProcess } from "@opencode-ai/util/process"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { File } from "./file"
import { KeyedMutex } from "./effect/keyed-mutex"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as Image from "./image"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Schema } from "effect"
import { Config } from "./config"
import { FileSystem } from "./filesystem"
+4 -4
View File
@@ -2,13 +2,13 @@ export * as InstructionDiscovery from "./instruction-discovery"
import { Array, Context, Effect, Layer, Schema } from "effect"
import { isAbsolute, join, relative, sep } from "path"
import { FSUtil } from "./fs-util"
import { Flag } from "./flag/flag"
import { Global } from "./global"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Flag } from "@opencode-ai/util/flag"
import { Global } from "@opencode-ai/util/global"
import { Location } from "./location"
import { AbsolutePath } from "./schema"
import { Instructions } from "./instructions/index"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
class File extends Schema.Class<File>("InstructionDiscovery.File")({
path: AbsolutePath,
+1 -1
View File
@@ -1,6 +1,6 @@
export * as InstructionBuiltIns from "./builtins"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, DateTime, Effect, Layer, Schema } from "effect"
import { Location } from "../location"
import { SessionSchema } from "../session/schema"
+2 -2
View File
@@ -1,6 +1,6 @@
export * as Integration from "./integration"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import {
Cause,
Clock,
@@ -22,7 +22,7 @@ import { Credential } from "./credential"
import { State } from "./state"
import { EventV2 } from "./event"
import { IntegrationConnection } from "./integration/connection"
import { AppProcess } from "./process"
import { AppProcess } from "@opencode-ai/util/process"
import { ChildProcess } from "effect/unstable/process"
export const ID = Integration.ID
+1 -1
View File
@@ -1,7 +1,7 @@
export * as Job from "./job"
import { Cause, Clock, Context, Deferred, Effect, Exit, Layer, Scope, SynchronizedRef } from "effect"
import { makeGlobalNode } from "./effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { Identifier } from "./id/id"
import { SessionSchema } from "./session/schema"
+1 -1
View File
@@ -3,7 +3,7 @@ export * as KV from "./kv"
import { eq } from "drizzle-orm"
import { Context, Effect, Layer, Schema } from "effect"
import { Database } from "./database/database"
import { makeGlobalNode } from "./effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { KVTable } from "./kv/sql"
export type Value = Schema.Json
+2 -2
View File
@@ -1,9 +1,9 @@
export * as LocationMutation from "./location-mutation"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import path from "path"
import { Context, Effect, Layer, Schema } from "effect"
import { FSUtil } from "./fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Location } from "./location"
import { Project } from "./project"
import { AbsolutePath } from "./schema"
+2 -2
View File
@@ -1,6 +1,6 @@
import { Context, Effect, Layer, LayerMap } from "effect"
import { LayerNode } from "./effect/layer-node"
import { Node } from "./effect/app-node"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Node } from "@opencode-ai/util/effect/app-node"
import { Location } from "./location"
import type { LocationError, LocationServices } from "./location-services"
+2 -2
View File
@@ -4,8 +4,8 @@ import { AISDK } from "./aisdk"
import { Catalog } from "./catalog"
import { CommandV2 } from "./command"
import { Config } from "./config"
import { LayerNode } from "./effect/layer-node"
import { Node } from "./effect/app-node"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Node } from "@opencode-ai/util/effect/app-node"
import { EventV2 } from "./event"
import { FileMutation } from "./file-mutation"
import { FileSystem } from "./filesystem"
+2 -2
View File
@@ -1,8 +1,8 @@
import { Context, Effect, Layer } from "effect"
import { Info, Ref, response } from "@opencode-ai/schema/location"
import { Project } from "./project"
import { LayerNode } from "./effect/layer-node"
import { makeLocationNode, tags } from "./effect/app-node"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { makeLocationNode, tags } from "@opencode-ai/util/effect/app-node"
export * as Location from "./location"
+1 -1
View File
@@ -29,7 +29,7 @@ import {
} from "@modelcontextprotocol/sdk/types.js"
import { Cause, Effect, Exit, Schema } from "effect"
import { ConfigMCP } from "../config/mcp"
import { InstallationVersion } from "../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
const DEFAULT_STARTUP_TIMEOUT = 30_000
const DEFAULT_CATALOG_TIMEOUT = 30_000
+2 -2
View File
@@ -5,7 +5,7 @@ import { McpEvent } from "@opencode-ai/schema/mcp-event"
import { Command } from "@opencode-ai/schema/command"
import { createHash } from "node:crypto"
import { Cause, Context, Deferred, Effect, Exit, FiberSet, Layer, Schema, Scope, Stream } from "effect"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Config } from "../config"
import { ConfigMCP } from "../config/mcp"
import { Credential } from "../credential"
@@ -15,7 +15,7 @@ import { Integration } from "../integration"
import { IntegrationConnection } from "../integration/connection"
import { KeyedMutex } from "../effect/keyed-mutex"
import { Location } from "../location"
import { waitForAbort } from "../process"
import { waitForAbort } from "@opencode-ai/util/process"
import { State } from "../state"
import { MCPClient } from "./client"
import { MCPOAuth } from "./oauth"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as McpInstructions from "./instructions"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Schema } from "effect"
import { AgentV2 } from "../agent"
import { PermissionV2 } from "../permission"
+8 -8
View File
@@ -3,15 +3,15 @@ import { Context, Duration, Effect, Layer, Option, Schedule, Schema } from "effe
import { HttpClient, HttpClientRequest } from "effect/unstable/http"
import { ModelsDev } from "@opencode-ai/schema/models-dev"
import { Money } from "@opencode-ai/schema/money"
import { Global } from "./global"
import { Flag } from "./flag/flag"
import { Flock } from "./util/flock"
import { Hash } from "./util/hash"
import { FSUtil } from "./fs-util"
import { InstallationChannel, InstallationVersion } from "./installation/version"
import { Global } from "@opencode-ai/util/global"
import { Flag } from "@opencode-ai/util/flag"
import { Flock } from "@opencode-ai/util/flock"
import { Hash } from "@opencode-ai/util/hash"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { InstallationChannel, InstallationVersion } from "@opencode-ai/util/installation/version"
import { EventV2 } from "./event"
import { makeGlobalNode } from "./effect/app-node"
import { httpClient } from "./effect/app-node-platform"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { httpClient } from "@opencode-ai/util/effect/app-node-platform"
import { ModelV2 } from "./model"
import { ProviderV2 } from "./provider"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as PermissionV2 from "./permission"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Deferred, Effect, Layer, Schema } from "effect"
import { Permission } from "@opencode-ai/schema/permission"
import { EventV2 } from "./event"
+1 -1
View File
@@ -3,7 +3,7 @@ export * as PermissionSaved from "./saved"
import { eq } from "drizzle-orm"
import { Context, Effect, Layer, Schema } from "effect"
import { Database } from "../database/database"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { ProjectV2 } from "../project"
import { PermissionTable } from "./sql"
import { PermissionSaved } from "@opencode-ai/schema/permission-saved"
+1 -1
View File
@@ -2,7 +2,7 @@ export * as PluginV2 from "./plugin"
import type { Plugin } from "@opencode-ai/plugin/v2/effect/plugin"
import { Event, ID, type Info } from "@opencode-ai/schema/plugin"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Exit, Layer, Scope, Semaphore } from "effect"
import { AgentV2 } from "./agent"
import { AISDK } from "./aisdk"
+1 -1
View File
@@ -4,7 +4,7 @@ import path from "path"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { Effect } from "effect"
import { AgentV2 } from "../agent"
import { Global } from "../global"
import { Global } from "@opencode-ai/util/global"
import { Location } from "../location"
import { PermissionV2 } from "../permission"
+1 -1
View File
@@ -4,7 +4,7 @@ import type { AISDKHooks } from "@opencode-ai/plugin/v2/effect/aisdk"
import type { SessionHooks } from "@opencode-ai/plugin/v2/effect/session"
import type { ToolHooks } from "@opencode-ai/plugin/v2/effect/tool"
import { Context, Effect, Layer, Scope } from "effect"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { State } from "../state"
export interface Domains {
+3 -3
View File
@@ -17,14 +17,14 @@ import { EventV2 } from "../event"
import { FileMutation } from "../file-mutation"
import { Form } from "../form"
import { FileSystem } from "../filesystem"
import { FSUtil } from "../fs-util"
import { Global } from "../global"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Global } from "@opencode-ai/util/global"
import { Image } from "../image"
import { Integration } from "../integration"
import { Location } from "../location"
import { LocationMutation } from "../location-mutation"
import { ModelsDev } from "../models-dev"
import { Npm } from "../npm"
import { Npm } from "@opencode-ai/util/npm"
import { PermissionV2 } from "../permission"
import { Reference } from "../reference"
import { Ripgrep } from "../ripgrep"
@@ -1,7 +1,7 @@
export * as LayerMapExample from "./layer-map.example"
import { Context, Effect, Layer, LayerMap } from "effect"
import { Npm } from "../npm"
import { Npm } from "@opencode-ai/util/npm"
/**
* Tutorial: split global services from context-specific services.
@@ -1,5 +1,5 @@
import os from "os"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Effect, Option, Schema } from "effect"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
@@ -1,5 +1,5 @@
import os from "os"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Effect } from "effect"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { ProviderV2 } from "../../provider"
+1 -1
View File
@@ -1,7 +1,7 @@
import { Effect } from "effect"
import { pathToFileURL } from "url"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { Npm } from "../../npm"
import { Npm } from "@opencode-ai/util/npm"
import { importModule } from "#runtime-import"
export const DynamicProviderPlugin = define({
@@ -4,7 +4,7 @@ import { Catalog } from "../../catalog"
import { Credential } from "../../credential"
import { EventV2 } from "../../event"
import { CopilotModels } from "../../github-copilot/models"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Integration } from "../../integration"
import { ModelV2 } from "../../model"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
+1 -1
View File
@@ -1,5 +1,5 @@
import os from "os"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Effect } from "effect"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { ProviderV2 } from "../../provider"
+1 -1
View File
@@ -4,7 +4,7 @@ import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { Deferred, Effect, Option, Schema, Semaphore, Stream } from "effect"
import { Credential } from "../../credential"
import { EventV2 } from "../../event"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Integration } from "../../integration"
import { ModelV2 } from "../../model"
import { OauthCallbackPage } from "../../oauth/page"
@@ -1,7 +1,7 @@
import { Effect } from "effect"
import { pathToFileURL } from "url"
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { Npm } from "../../npm"
import { Npm } from "@opencode-ai/util/npm"
import { ProviderV2 } from "../../provider"
import { importModule } from "#runtime-import"
+1 -1
View File
@@ -3,7 +3,7 @@ import type { IntegrationOAuthMethodRegistration } from "@opencode-ai/plugin/v2/
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { Clock, Deferred, Effect, Option, Schema } from "effect"
import { Credential } from "../../credential"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Integration } from "../../integration"
import { OauthCallbackPage } from "../../oauth/page"
import { ProviderV2 } from "../../provider"
+1 -1
View File
@@ -2,7 +2,7 @@ export * as PluginRuntime from "./runtime"
import { Context, Effect, Layer } from "effect"
import { AgentV2 } from "../agent"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { Job } from "../job"
import { Location } from "../location"
import { LocationServiceMap } from "../location-service-map"
+1 -1
View File
@@ -2,7 +2,7 @@ export * as SdkPlugins from "./sdk"
import type { Plugin } from "@opencode-ai/plugin/v2/effect/plugin"
import { Context, Effect, Layer } from "effect"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { EventV2 } from "../event"
import type { PluginV2 } from "../plugin"
+2 -2
View File
@@ -6,10 +6,10 @@ import { define } from "@opencode-ai/plugin/v2/effect/plugin"
import { Effect } from "effect"
import { AbsolutePath } from "../schema"
import { SkillV2 } from "../skill"
import { InstallationChannel, InstallationVersion } from "../installation/version"
import { InstallationChannel, InstallationVersion } from "@opencode-ai/util/installation/version"
import { Config } from "../config"
import { Location } from "../location"
import { FSUtil } from "../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import os from "os"
import path from "path"
import { fileURLToPath } from "url"
+5 -5
View File
@@ -10,20 +10,20 @@ import { Catalog } from "../catalog"
import { CommandV2 } from "../command"
import { Config } from "../config"
import { ConfigPlugin } from "../config/plugin"
import { makeLocationNode } from "../effect/app-node"
import { httpClient } from "../effect/app-node-platform"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { httpClient } from "@opencode-ai/util/effect/app-node-platform"
import { EventV2 } from "../event"
import { FileMutation } from "../file-mutation"
import { FileSystem } from "../filesystem"
import { Form } from "../form"
import { FSUtil } from "../fs-util"
import { Global } from "../global"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Global } from "@opencode-ai/util/global"
import { Image } from "../image"
import { Integration } from "../integration"
import { Location } from "../location"
import { LocationMutation } from "../location-mutation"
import { ModelsDev } from "../models-dev"
import { Npm } from "../npm"
import { Npm } from "@opencode-ai/util/npm"
import { PermissionV2 } from "../permission"
import { PluginV2 } from "../plugin"
import { PluginPromise } from "../plugin/promise"
+4 -4
View File
@@ -7,11 +7,11 @@ import { asc, desc } from "drizzle-orm"
import path from "path"
import { AbsolutePath } from "./schema"
import { Database } from "./database/database"
import { FSUtil } from "./fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Git } from "./git"
import { AppProcess } from "./process"
import { makeGlobalNode } from "./effect/app-node"
import { Hash } from "./util/hash"
import { AppProcess } from "@opencode-ai/util/process"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { Hash } from "@opencode-ai/util/hash"
import { ProjectDirectories } from "./project/directories"
import { ProjectSchema } from "./project/schema"
import { ProjectTable } from "./project/sql"
+2 -2
View File
@@ -3,9 +3,9 @@ export * as ProjectCopy from "./copy"
import { Context, Effect, Layer, Schema } from "effect"
import path from "path"
import { AbsolutePath } from "../schema"
import { FSUtil } from "../fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Git } from "../git"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Project } from "../project"
import { ProjectDirectories } from "./directories"
import { makeGitWorktreeStrategy } from "./copy-strategies"
+1 -1
View File
@@ -3,7 +3,7 @@ export * as ProjectDirectories from "./directories"
import { and, asc, desc, eq, isNotNull, isNull, ne, or } from "drizzle-orm"
import { Context, Effect, Layer, Schema } from "effect"
import { Database } from "../database/database"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { AbsolutePath } from "../schema"
import { ProjectSchema } from "./schema"
import { ProjectDirectoryTable } from "./sql"
+1 -1
View File
@@ -3,7 +3,7 @@ export * as ProviderV2 from "./provider"
import { Effect, Schema } from "effect"
import { Provider } from "@opencode-ai/schema/provider"
import type { ProviderPackageDefinition } from "@opencode-ai/ai"
import { Npm } from "./npm"
import { Npm } from "@opencode-ai/util/npm"
import type { DeepMutable } from "./schema"
import { importModule, resolveModule } from "#runtime-import"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as Pty from "./pty"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import type { Disp, Proc } from "#pty"
import { Context, Effect, Layer, Schema, Types } from "effect"
import { Pty } from "@opencode-ai/schema/pty"
+1 -1
View File
@@ -4,7 +4,7 @@ import { WorkspaceV2 } from "../workspace"
import { PtyTicket } from "@opencode-ai/schema/pty-ticket"
import { PtyID } from "./schema"
import { Cache, Context, Duration, Effect, Layer } from "effect"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
const DEFAULT_TTL = Duration.seconds(60)
const CAPACITY = 10_000
+1 -1
View File
@@ -1,6 +1,6 @@
export * as QuestionV2 from "./question"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Deferred, Effect, Layer, Schema } from "effect"
import { Question } from "@opencode-ai/schema/question"
import { EventV2 } from "./event"
+2 -2
View File
@@ -1,9 +1,9 @@
export * as Reference from "./reference"
import { makeLocationNode } from "./effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Scope, Types } from "effect"
import { Reference } from "@opencode-ai/schema/reference"
import { Global } from "./global"
import { Global } from "@opencode-ai/util/global"
import { EventV2 } from "./event"
import { Repository } from "./repository"
import { RepositoryCache } from "./repository-cache"
+1 -1
View File
@@ -1,6 +1,6 @@
export * as ReferenceInstructions from "./instructions"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Context, Effect, Layer, Schema } from "effect"
import { Reference } from "../reference"
import { Instructions } from "../instructions/index"
+4 -4
View File
@@ -1,12 +1,12 @@
import path from "path"
import { Context, Effect, Layer, Schema } from "effect"
import { FSUtil } from "./fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Git } from "./git"
import { Global } from "./global"
import { Global } from "@opencode-ai/util/global"
import { Repository } from "./repository"
import { AbsolutePath } from "./schema"
import { makeGlobalNode } from "./effect/app-node"
import { EffectFlock } from "./util/effect-flock"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { EffectFlock } from "@opencode-ai/util/effect-flock"
export type Result = {
readonly repository: string
+2 -2
View File
@@ -3,8 +3,8 @@ export * as Ripgrep from "./ripgrep"
import { Context, Effect, Fiber, Layer, Schema, Stream } from "effect"
import { ChildProcess } from "effect/unstable/process"
import { Entry, Match } from "@opencode-ai/schema/filesystem"
import { makeGlobalNode } from "./effect/app-node"
import { AppProcess, collectStream, waitForAbort } from "./process"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { AppProcess, collectStream, waitForAbort } from "@opencode-ai/util/process"
import { NonNegativeInt, PositiveInt, RelativePath } from "./schema"
import { RipgrepBinary } from "./ripgrep/binary"
+5 -5
View File
@@ -3,11 +3,11 @@ import { Context, Effect, Layer, Stream } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http"
import { ChildProcess } from "effect/unstable/process"
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
import { CrossSpawnSpawner } from "../cross-spawn-spawner"
import { makeGlobalNode } from "../effect/app-node"
import { httpClient } from "../effect/app-node-platform"
import { FSUtil } from "../fs-util"
import { Global } from "../global"
import { CrossSpawnSpawner } from "@opencode-ai/util/cross-spawn-spawner"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { httpClient } from "@opencode-ai/util/effect/app-node-platform"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Global } from "@opencode-ai/util/global"
import { which } from "../util/which"
export namespace RipgrepBinary {
+4 -4
View File
@@ -20,7 +20,7 @@ import { AbsolutePath, PositiveInt, RelativePath } from "./schema"
import { AgentV2 } from "./agent"
import { SessionV1 } from "./v1/session"
import { Money } from "@opencode-ai/schema/money"
import { InstallationVersion } from "./installation/version"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { Slug } from "./util/slug"
import { ProjectTable } from "./project/sql"
import path from "path"
@@ -29,7 +29,7 @@ import { SessionRunner } from "./session/runner/index"
import { SessionStore } from "./session/store"
import { SessionExecution } from "./session/execution"
import { MessageDecodeError, NotFoundError } from "./session/error"
import { makeGlobalNode } from "./effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { LocationServiceMap } from "./location-service-map"
import { SessionEvent } from "./session/event"
import { SessionPending } from "./session/pending"
@@ -37,7 +37,7 @@ import { SessionGenerate } from "./session/generate"
import { Snapshot } from "./snapshot"
import { SessionRevert } from "./session/revert"
import { Session } from "@opencode-ai/schema/session"
import { FSUtil } from "./fs-util"
import { FSUtil } from "@opencode-ai/util/fs-util"
import { Image } from "./image"
import { Mime } from "./mime"
import type { EventLog } from "@opencode-ai/schema/event-log"
@@ -45,7 +45,7 @@ import { SkillV2 } from "./skill"
import { Job } from "./job"
import { CommandV2 } from "./command"
import { Shell } from "./shell"
import { Global } from "./global"
import { Global } from "@opencode-ai/util/global"
import { Shell as ShellSchema } from "@opencode-ai/schema/shell"
import { KeyedMutex } from "./effect/keyed-mutex"
import { fileURLToPath } from "url"
+2 -2
View File
@@ -5,8 +5,8 @@ import { SessionError } from "@opencode-ai/schema/session-error"
import { Context, Effect, Layer, Stream } from "effect"
import { Config } from "../config"
import { EventV2 } from "../event"
import { makeLocationNode } from "../effect/app-node"
import { llmClient } from "../effect/app-node-platform"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { llmClient } from "@opencode-ai/util/effect/app-node-platform"
import { SessionEvent } from "./event"
import type { SessionMessage } from "./message"
import { SessionModelHeaders } from "./model-headers"
+1 -1
View File
@@ -3,7 +3,7 @@ export * as SessionContext from "./context"
import { Context, Effect, Layer } from "effect"
import { AgentV2 } from "../agent"
import { Database } from "../database/database"
import { makeLocationNode } from "../effect/app-node"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { InstructionDiscovery } from "../instruction-discovery"
import { Instructions } from "../instructions/index"
import { InstructionBuiltIns } from "../instructions/builtins"
+1 -1
View File
@@ -3,7 +3,7 @@ export * as SessionExecution from "./execution"
import { Cause, Context, Effect, Exit, Layer } from "effect"
import { EventV2 } from "../event"
import { LocationServiceMap } from "../location-service-map"
import { makeGlobalNode } from "../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { SessionEvent } from "./event"
import { SessionRunCoordinator } from "./run-coordinator"
import { SessionRunner } from "./runner/index"
@@ -1,7 +1,7 @@
export * as SessionRestart from "./restart"
import { Context, Effect, Layer } from "effect"
import { makeGlobalNode } from "../../effect/app-node"
import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
import { SessionExecution } from "../execution"
import { SessionStore } from "../store"
+2 -2
View File
@@ -3,8 +3,8 @@ export * as SessionGenerateNode from "./generate-node"
import { LLM, LLMClient, Message, SystemPart } from "@opencode-ai/ai"
import { Effect, Layer } from "effect"
import { Database } from "../database/database"
import { makeLocationNode } from "../effect/app-node"
import { llmClient } from "../effect/app-node-platform"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { llmClient } from "@opencode-ai/util/effect/app-node-platform"
import { PluginHooks } from "../plugin/hooks"
import { SessionContext } from "./context"
import { SessionGenerate } from "./generate"

Some files were not shown because too many files have changed in this diff Show More