core: consolidate shared infrastructure into core package

Moves effect logging, observability, runtime utilities, flags, installation
version info, and process utilities from opencode to core package. This
enables better code sharing across packages and establishes core as the
single source of truth for foundational utilities.

All internal imports updated to use @opencode-ai/core paths for consistency.
This commit is contained in:
Dax Raad
2026-04-25 13:30:37 -04:00
parent a9740b9133
commit 1a734adb4d
90 changed files with 140 additions and 119 deletions
+5
View File
@@ -197,8 +197,13 @@
"opencode": "./bin/opencode",
},
"dependencies": {
"@effect/opentelemetry": "catalog:",
"@effect/platform-node": "catalog:",
"@npmcli/arborist": "catalog:",
"@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",
"effect": "catalog:",
"glob": "13.0.5",
"mime-types": "3.0.2",
+5
View File
@@ -23,8 +23,13 @@
"@types/npmcli__arborist": "6.3.3"
},
"dependencies": {
"@effect/opentelemetry": "catalog:",
"@effect/platform-node": "catalog:",
"@npmcli/arborist": "catalog:",
"@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",
"effect": "catalog:",
"glob": "13.0.5",
"mime-types": "3.0.2",
@@ -1,5 +1,5 @@
import { Cause, Effect, Logger, References } from "effect"
import { Log } from "@/util"
import * as Log from "../util/log"
type Fields = Record<string, unknown>
@@ -2,9 +2,9 @@ import { Effect, Layer, Logger } from "effect"
import { FetchHttpClient } from "effect/unstable/http"
import { OtlpLogger, OtlpSerialization } from "effect/unstable/observability"
import * as EffectLogger from "./logger"
import { Flag } from "@/flag/flag"
import { InstallationChannel, InstallationVersion } from "@/installation/version"
import { ensureProcessMetadata } from "@/util/opencode-process"
import { Flag } from "../flag/flag"
import { InstallationChannel, InstallationVersion } from "../installation/version"
import { ensureProcessMetadata } from "../util/opencode-process"
const base = Flag.OTEL_EXPORTER_OTLP_ENDPOINT
export const enabled = !!base
@@ -76,7 +76,7 @@ const traces = async () => {
// register(), so the global @opentelemetry/api context manager stays
// as the no-op default. Non-Effect code (like the AI SDK) that calls
// tracer.startActiveSpan() relies on context.active() to find the
// parent span without a real context manager every span starts a
// parent span - without a real context manager every span starts a
// new trace. Registering AsyncLocalStorageContextManager fixes this.
const { AsyncLocalStorageContextManager } = await import("@opentelemetry/context-async-hooks")
const { context } = await import("@opentelemetry/api")
@@ -1,11 +1,13 @@
import { Observability } from "./observability"
import { Layer, type Context, ManagedRuntime, type Effect } from "effect"
import { memoMap } from "./memo-map"
import { Observability } from "./observability"
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
const getRuntime = () =>
(rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer) as Layer.Layer<I, E>, { memoMap }))
(rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer) as Layer.Layer<I, E>, {
memoMap,
}))
return {
runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(service.use(fn)),
+25 -16
View File
@@ -3,6 +3,24 @@ import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir"
import os from "os"
import { Context, Effect, Layer } from "effect"
const app = "opencode"
const data = path.join(xdgData!, app)
const cache = path.join(xdgCache!, app)
const config = path.join(xdgConfig!, app)
const state = path.join(xdgState!, app)
export const Path = {
get home() {
return process.env.OPENCODE_TEST_HOME ?? os.homedir()
},
data,
bin: path.join(cache, "bin"),
log: path.join(data, "log"),
cache,
config,
state,
}
export namespace Global {
export class Service extends Context.Service<Service, Interface>()("@opencode/Global") {}
@@ -19,23 +37,14 @@ export namespace Global {
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const app = "opencode"
const home = process.env.OPENCODE_TEST_HOME ?? os.homedir()
const data = path.join(xdgData!, app)
const cache = path.join(xdgCache!, app)
const cfg = path.join(xdgConfig!, app)
const state = path.join(xdgState!, app)
const bin = path.join(cache, "bin")
const log = path.join(data, "log")
return Service.of({
home,
data,
cache,
config: cfg,
state,
bin,
log,
home: Path.home,
data: Path.data,
cache: Path.cache,
config: Path.config,
state: Path.state,
bin: Path.bin,
log: Path.log,
})
}),
)
@@ -1,9 +1,9 @@
import path from "path"
import fs from "fs/promises"
import { createWriteStream } from "fs"
import { Global } from "../global"
import * as Global from "../global"
import z from "zod"
import { Glob } from "@opencode-ai/core/util/glob"
import { Glob } from "./glob"
export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" })
export type Level = z.infer<typeof Level>
@@ -1,5 +1,5 @@
import { afterEach, describe, expect, test } from "bun:test"
import { resource } from "../../src/effect/observability"
import { resource } from "@opencode-ai/core/effect/observability"
const otelResourceAttributes = process.env.OTEL_RESOURCE_ATTRIBUTES
const opencodeClient = process.env.OPENCODE_CLIENT
+1 -1
View File
@@ -50,7 +50,7 @@ import { Result, Schema } from "effect"
import { LoadAPIKeyError } from "ai"
import type { AssistantMessage, Event, OpencodeClient, SessionMessageResponse, ToolPart } from "@opencode-ai/sdk/v2"
import { applyPatch } from "diff"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
type ModeOption = { id: string; name: string; description?: string }
type ModelOption = { modelId: string; name: string }
+1 -1
View File
@@ -11,7 +11,7 @@ import { Config } from "../../config"
import { ConfigMCP } from "../../config/mcp"
import { Instance } from "../../project/instance"
import { Installation } from "../../installation"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import path from "path"
import { Global } from "../../global"
import { modify, applyEdits } from "jsonc-parser"
+1 -1
View File
@@ -3,7 +3,7 @@ import path from "path"
import { pathToFileURL } from "url"
import { UI } from "../ui"
import { cmd } from "./cmd"
import { Flag } from "../../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { bootstrap } from "../bootstrap"
import { EOL } from "os"
import { Filesystem } from "../../util"
+1 -1
View File
@@ -1,7 +1,7 @@
import { Server } from "../../server/server"
import { cmd } from "./cmd"
import { withNetworkOptions, resolveNetworkOptions } from "../network"
import { Flag } from "../../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
export const ServeCommand = cmd({
command: "serve",
+1 -1
View File
@@ -5,7 +5,7 @@ import { SessionID } from "../../session/schema"
import { bootstrap } from "../bootstrap"
import { UI } from "../ui"
import { Locale } from "../../util"
import { Flag } from "../../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Filesystem } from "../../util"
import { Process } from "../../util"
import { EOL } from "os"
+1 -1
View File
@@ -16,7 +16,7 @@ import {
on,
} from "solid-js"
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import semver from "semver"
import { DialogProvider, useDialog } from "@tui/ui/dialog"
import { DialogProvider as DialogProviderList } from "@tui/component/dialog-provider"
@@ -8,7 +8,7 @@ import { useProject } from "@tui/context/project"
import { useKeybind } from "../context/keybind"
import { useTheme } from "../context/theme"
import { useSDK } from "../context/sdk"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { DialogSessionRename } from "./dialog-session-rename"
import { Keybind } from "@/util"
import { createDebouncedSignal } from "../util/signal"
@@ -7,7 +7,7 @@ import { useProject } from "@tui/context/project"
import { createMemo, createSignal, onMount } from "solid-js"
import { setTimeout as sleep } from "node:timers/promises"
import { errorData, errorMessage } from "@/util/error"
import * as Log from "@/util/log"
import * as Log from "@opencode-ai/core/util/log"
import { useSDK } from "../context/sdk"
import { useToast } from "../ui/toast"
@@ -2,7 +2,7 @@ import { TextAttributes } from "@opentui/core"
import { useKeyboard, useRenderer, useTerminalDimensions } from "@opentui/solid"
import * as Clipboard from "@tui/util/clipboard"
import { createSignal } from "solid-js"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { win32FlushInputBuffer } from "../win32"
import { getScrollAcceleration } from "../util/scroll"
@@ -3,7 +3,7 @@ import { type ParseError as JsoncParseError, applyEdits, modify, parse as parseJ
import { unique } from "remeda"
import z from "zod"
import { TuiInfo, TuiOptions } from "./tui-schema"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Global } from "@/global"
import { Filesystem, Log } from "@/util"
import * as ConfigPaths from "@/config/paths"
@@ -7,15 +7,15 @@ import { ConfigParse } from "@/config/parse"
import * as ConfigPaths from "@/config/paths"
import { migrateTuiConfig } from "./tui-migrate"
import { TuiInfo } from "./tui-schema"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { isRecord } from "@/util/record"
import { Global } from "@/global"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { CurrentWorkingDirectory } from "./cwd"
import { ConfigPlugin } from "@/config/plugin"
import { ConfigKeybinds } from "@/config/keybinds"
import { InstallationLocal, InstallationVersion } from "@/installation/version"
import { makeRuntime } from "@/effect/runtime"
import { InstallationLocal, InstallationVersion } from "@opencode-ai/core/installation/version"
import { makeRuntime } from "@opencode-ai/core/effect/runtime"
import { Filesystem, Log } from "@/util"
import { ConfigVariable } from "@/config/variable"
import { Npm } from "@/npm"
@@ -2,7 +2,7 @@ import { createOpencodeClient } from "@opencode-ai/sdk/v2"
import type { GlobalEvent } from "@opencode-ai/sdk/v2"
import { createSimpleContext } from "./helper"
import { createGlobalEmitter } from "@solid-primitives/event-bus"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { batch, onCleanup, onMount } from "solid-js"
export type EventSource = {
+1 -1
View File
@@ -1,6 +1,6 @@
import { Layer } from "effect"
import { TuiConfig } from "./config/tui"
import { Npm } from "@/npm"
import { Observability } from "@/effect/observability"
import { Observability } from "@opencode-ai/core/effect/observability"
export const CliLayer = Observability.layer.pipe(Layer.merge(TuiConfig.layer), Layer.provide(Npm.defaultLayer))
@@ -18,7 +18,7 @@ import { DialogSelect, type DialogSelectOption as SelectOption } from "../ui/dia
import { Prompt } from "../component/prompt"
import { Slot as HostSlot } from "./slots"
import type { useToast } from "../ui/toast"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
type RouteEntry = {
key: symbol
@@ -33,7 +33,7 @@ import { Global } from "@/global"
import { Filesystem } from "@/util"
import { Process } from "@/util"
import { Flock } from "@opencode-ai/core/util/flock"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { INTERNAL_TUI_PLUGINS, type InternalTuiPlugin } from "./internal"
import { setupSlots, Slot as View } from "./slots"
import type { HostPluginApi, HostSlots } from "./slots"
@@ -64,7 +64,7 @@ import { DialogForkFromTimeline } from "./dialog-fork-from-timeline"
import { DialogSessionRename } from "../../component/dialog-session-rename"
import { Sidebar } from "./sidebar"
import { SubagentFooter } from "./subagent-footer.tsx"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { LANGUAGE_EXTENSIONS } from "@/lsp/language"
import parsers from "../../../../../../parsers-config.ts"
import * as Clipboard from "../../util/clipboard"
@@ -3,7 +3,7 @@ import { useSync } from "@tui/context/sync"
import { createMemo, Show } from "solid-js"
import { useTheme } from "../../context/theme"
import { useTuiConfig } from "../../context/tui-config"
import { InstallationChannel, InstallationVersion } from "@/installation/version"
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
import { TuiPluginRuntime } from "../../plugin"
import { getScrollAcceleration } from "../../util/scroll"
+1 -1
View File
@@ -15,7 +15,7 @@ import type { EventSource } from "./context/sdk"
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"
import { writeHeapSnapshot } from "v8"
import { TuiConfig } from "./config/tui"
import { OPENCODE_PROCESS_ROLE, OPENCODE_RUN_ID, ensureRunID, sanitizedProcessEnv } from "@/util/opencode-process"
import { OPENCODE_PROCESS_ROLE, OPENCODE_RUN_ID, ensureRunID, sanitizedProcessEnv } from "@opencode-ai/core/util/opencode-process"
import { validateSession } from "./validate-session"
declare global {
@@ -4,7 +4,7 @@ import { useTheme } from "@tui/context/theme"
import { MouseButton, Renderable, RGBA } from "@opentui/core"
import { createStore } from "solid-js/store"
import { useToast } from "./toast"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import * as Selection from "@tui/util/selection"
export function Dialog(
+2 -2
View File
@@ -7,11 +7,11 @@ import { Rpc } from "@/util"
import { upgrade } from "@/cli/upgrade"
import { Config } from "@/config"
import { GlobalBus } from "@/bus/global"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { writeHeapSnapshot } from "node:v8"
import { Heap } from "@/cli/heap"
import { AppRuntime } from "@/effect/app-runtime"
import { ensureProcessMetadata } from "@/util/opencode-process"
import { ensureProcessMetadata } from "@opencode-ai/core/util/opencode-process"
ensureProcessMetadata("worker")
+1 -1
View File
@@ -3,7 +3,7 @@ import { UI } from "../ui"
import * as prompts from "@clack/prompts"
import { AppRuntime } from "@/effect/app-runtime"
import { Installation } from "../../installation"
import { InstallationVersion } from "../../installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
export const UpgradeCommand = {
command: "upgrade [target]",
+1 -1
View File
@@ -2,7 +2,7 @@ import { Server } from "../../server/server"
import { UI } from "../ui"
import { cmd } from "./cmd"
import { withNetworkOptions, resolveNetworkOptions } from "../network"
import { Flag } from "../../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import open from "open"
import { networkInterfaces } from "os"
+1 -1
View File
@@ -1,6 +1,6 @@
import path from "path"
import { writeHeapSnapshot } from "node:v8"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Global } from "@/global"
import { Log } from "@/util"
+2 -2
View File
@@ -1,9 +1,9 @@
import { Bus } from "@/bus"
import { Config } from "@/config"
import { AppRuntime } from "@/effect/app-runtime"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Installation } from "@/installation"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
export async function upgrade() {
const config = await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.getGlobal()))
+2 -2
View File
@@ -7,12 +7,12 @@ import { mergeDeep, pipe } from "remeda"
import { Global } from "../global"
import fsNode from "fs/promises"
import { NamedError } from "@opencode-ai/core/util/error"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Auth } from "../auth"
import { Env } from "../env"
import { applyEdits, modify } from "jsonc-parser"
import { Instance, type InstanceContext } from "../project/instance"
import { InstallationLocal, InstallationVersion } from "@/installation/version"
import { InstallationLocal, InstallationVersion } from "@opencode-ai/core/installation/version"
import { existsSync } from "fs"
import { GlobalBus } from "@/bus/global"
import { Event } from "../server/event"
+1 -1
View File
@@ -2,7 +2,7 @@ export * as ConfigPaths from "./paths"
import path from "path"
import { Filesystem } from "@/util"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Global } from "@/global"
import { unique } from "remeda"
import { JsonError } from "./error"
@@ -8,7 +8,7 @@ import { GlobalBus } from "@/bus/global"
import { Auth } from "@/auth"
import { SyncEvent } from "@/sync"
import { EventSequenceTable, EventTable } from "@/sync/event.sql"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Log } from "@/util"
import { Filesystem } from "@/util"
import { ProjectID } from "@/project/schema"
+2 -2
View File
@@ -1,6 +1,6 @@
import { Layer, ManagedRuntime } from "effect"
import { attach } from "./run-service"
import * as Observability from "./observability"
import * as Observability from "@opencode-ai/core/effect/observability"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { Bus } from "@/bus"
@@ -47,7 +47,7 @@ import { Installation } from "@/installation"
import { ShareNext } from "@/share"
import { SessionShare } from "@/share"
import { Npm } from "@/npm"
import { memoMap } from "./memo-map"
import { memoMap } from "@opencode-ai/core/effect/memo-map"
export const AppLayer = Layer.mergeAll(
Npm.defaultLayer,
@@ -10,8 +10,8 @@ import { Vcs } from "@/project"
import { Snapshot } from "@/snapshot"
import { Bus } from "@/bus"
import { Config } from "@/config"
import * as Observability from "./observability"
import { memoMap } from "./memo-map"
import * as Observability from "@opencode-ai/core/effect/observability"
import { memoMap } from "@opencode-ai/core/effect/memo-map"
export const BootstrapLayer = Layer.mergeAll(
Config.defaultLayer,
+2 -2
View File
@@ -1,5 +1,5 @@
export * as InstanceState from "./instance-state"
export * as EffectBridge from "./bridge"
export * as Runner from "./runner"
export * as Observability from "./observability"
export * as EffectLogger from "./logger"
export * as Observability from "@opencode-ai/core/effect/observability"
export * as EffectLogger from "@opencode-ai/core/effect/logger"
@@ -1,5 +1,5 @@
import { Effect, Fiber, ScopedCache, Scope, Context } from "effect"
import * as EffectLogger from "./logger"
import * as EffectLogger from "@opencode-ai/core/effect/logger"
import { Instance, type InstanceContext } from "@/project/instance"
import { LocalContext } from "@/util"
import { InstanceRef, WorkspaceRef } from "./instance-ref"
+2 -2
View File
@@ -3,10 +3,10 @@ import * as Context from "effect/Context"
import { Instance } from "@/project/instance"
import { LocalContext } from "@/util"
import { InstanceRef, WorkspaceRef } from "./instance-ref"
import * as Observability from "./observability"
import * as Observability from "@opencode-ai/core/effect/observability"
import { WorkspaceContext } from "@/control-plane/workspace-context"
import type { InstanceContext } from "@/project/instance"
import { memoMap } from "./memo-map"
import { memoMap } from "@opencode-ai/core/effect/memo-map"
type Refs = {
instance?: InstanceContext
+1 -1
View File
@@ -9,7 +9,7 @@ import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner
import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
import { Global } from "@/global"
import { Log } from "@/util"
import { sanitizedProcessEnv } from "@/util/opencode-process"
import { sanitizedProcessEnv } from "@opencode-ai/core/util/opencode-process"
import { which } from "@/util/which"
import { zod } from "@/util/effect-zod"
import { withStatics } from "@/util/schema"
+1 -1
View File
@@ -8,7 +8,7 @@ import z from "zod"
import { Bus } from "@/bus"
import { BusEvent } from "@/bus/bus-event"
import { InstanceState } from "@/effect"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Git } from "@/git"
import { Instance } from "@/project/instance"
import { lazy } from "@/util/lazy"
+1 -1
View File
@@ -3,7 +3,7 @@ import type { InstanceContext } from "../project/instance"
import { Filesystem } from "../util"
import { Process } from "../util"
import { which } from "../util/which"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
export interface Context extends Pick<InstanceContext, "directory" | "worktree"> {}
+2 -2
View File
@@ -11,7 +11,7 @@ import { UninstallCommand } from "./cli/cmd/uninstall"
import { ModelsCommand } from "./cli/cmd/models"
import { UI } from "./cli/ui"
import { Installation } from "./installation"
import { InstallationVersion } from "./installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { NamedError } from "@opencode-ai/core/util/error"
import { FormatError } from "./cli/error"
import { ServeCommand } from "./cli/cmd/serve"
@@ -38,7 +38,7 @@ import { errorMessage } from "./util/error"
import { PluginCommand } from "./cli/cmd/plug"
import { Heap } from "./cli/heap"
import { drizzle } from "drizzle-orm/bun-sqlite"
import { ensureProcessMetadata } from "./util/opencode-process"
import { ensureProcessMetadata } from "@opencode-ai/core/util/opencode-process"
const processMetadata = ensureProcessMetadata("main")
+2 -2
View File
@@ -6,11 +6,11 @@ import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import path from "path"
import z from "zod"
import { BusEvent } from "@/bus/bus-event"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Log } from "../util"
import semver from "semver"
import { InstallationChannel, InstallationVersion } from "./version"
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
const log = Log.create({ service: "installation" })
+1 -1
View File
@@ -7,7 +7,7 @@ import { pathToFileURL, fileURLToPath } from "url"
import * as LSPServer from "./server"
import z from "zod"
import { Config } from "../config"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Process } from "../util"
import { spawn as lspspawn } from "./launch"
import { Effect, Layer, Context, Schema } from "effect"
+1 -1
View File
@@ -7,7 +7,7 @@ import { text } from "node:stream/consumers"
import fs from "fs/promises"
import { Filesystem } from "../util"
import type { InstanceContext } from "../project/instance"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Archive } from "../util"
import { Process } from "../util"
import { which } from "../util/which"
+1 -1
View File
@@ -15,7 +15,7 @@ import { Log } from "../util"
import { NamedError } from "@opencode-ai/core/util/error"
import z from "zod/v4"
import { Installation } from "../installation"
import { InstallationVersion } from "../installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { withTimeout } from "@/util/timeout"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { McpOAuthProvider } from "./oauth-provider"
+1 -1
View File
@@ -11,10 +11,10 @@ import { NodeFileSystem } from "@effect/platform-node"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { Global } from "@opencode-ai/core/global"
import { EffectFlock } from "@opencode-ai/core/util/effect-flock"
import { makeRuntime } from "@opencode-ai/core/effect/runtime"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import * as CrossSpawnSpawner from "../effect/cross-spawn-spawner"
import { makeRuntime } from "../effect/runtime"
export class InstallFailedError extends Schema.TaggedErrorClass<InstallFailedError>()("NpmInstallFailedError", {
add: Schema.Array(Schema.String).pipe(Schema.optional),
+1 -1
View File
@@ -1,7 +1,7 @@
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
import { Log } from "../util"
import { Installation } from "../installation"
import { InstallationVersion } from "../installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { OAUTH_DUMMY_KEY } from "../auth"
import os from "os"
import { setTimeout as sleep } from "node:timers/promises"
@@ -1,6 +1,6 @@
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
import type { Model } from "@opencode-ai/sdk/v2"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { iife } from "@/util/iife"
import { Log } from "../../util"
import { setTimeout as sleep } from "node:timers/promises"
+1 -1
View File
@@ -9,7 +9,7 @@ import { Config } from "../config"
import { Bus } from "../bus"
import { Log } from "../util"
import { createOpencodeClient } from "@opencode-ai/sdk"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { CodexAuthPlugin } from "./codex"
import { Session } from "../session"
import { NamedError } from "@opencode-ai/core/util/error"
+1 -1
View File
@@ -9,7 +9,7 @@ import {
type PluginSource,
} from "./shared"
import { ConfigPlugin } from "@/config/plugin"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
export namespace PluginLoader {
// A normalized plugin declaration derived from config before any filesystem or npm work happens.
+1 -1
View File
@@ -1,7 +1,7 @@
import path from "path"
import { fileURLToPath } from "url"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Global } from "@/global"
import { Filesystem } from "@/util"
import { Flock } from "@opencode-ai/core/util/flock"
+1 -1
View File
@@ -3,7 +3,7 @@ import { and, Database, eq } from "../storage"
import { ProjectTable } from "./project.sql"
import { SessionTable } from "../session/session.sql"
import { Log } from "../util"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { BusEvent } from "@/bus/bus-event"
import { GlobalBus } from "@/bus/global"
import { which } from "../util/which"
+1 -1
View File
@@ -3,7 +3,7 @@ import { Log } from "../util"
import path from "path"
import { Schema } from "effect"
import { Installation } from "../installation"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { lazy } from "@/util/lazy"
import { Filesystem } from "../util"
import { Flock } from "@opencode-ai/core/util/flock"
+2 -2
View File
@@ -11,8 +11,8 @@ import { type LanguageModelV3 } from "@ai-sdk/provider"
import * as ModelsDev from "./models"
import { Auth } from "../auth"
import { Env } from "../env"
import { InstallationVersion } from "../installation/version"
import { Flag } from "../flag/flag"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { Flag } from "@opencode-ai/core/flag/flag"
import { zod } from "@/util/effect-zod"
import { namedSchemaError } from "@/util/named-schema-error"
import { iife } from "@/util/iife"
+1 -1
View File
@@ -5,7 +5,7 @@ import type { JSONSchema } from "zod/v4/core"
import type * as Provider from "./provider"
import type * as ModelsDev from "./models"
import { iife } from "@/util/iife"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
type Modality = NonNullable<ModelsDev.Model["modalities"]>["input"][number]
+1 -1
View File
@@ -6,7 +6,7 @@ import type { ContentfulStatusCode } from "hono/utils/http-status"
import type { ErrorHandler, MiddlewareHandler } from "hono"
import { HTTPException } from "hono/http-exception"
import { Log } from "../util"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { basicAuth } from "hono/basic-auth"
import { cors } from "hono/cors"
import { compress } from "hono/compress"
@@ -10,7 +10,7 @@ import { AppRuntime } from "@/effect/app-runtime"
import { AsyncQueue } from "@/util/queue"
import { Instance } from "../../project/instance"
import { Installation } from "@/installation"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { Log } from "../../util"
import { lazy } from "../../util/lazy"
import { Config } from "../../config"
@@ -1,6 +1,6 @@
import { Effect, Encoding, Layer, Redacted, Schema } from "effect"
import { HttpApiMiddleware, HttpApiSecurity } from "effect/unstable/httpapi"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
class Unauthorized extends Schema.TaggedErrorClass<Unauthorized>()(
"Unauthorized",
@@ -18,7 +18,7 @@ import { ProjectApi, projectHandlers } from "./project"
import { ProviderApi, providerHandlers } from "./provider"
import { QuestionApi, questionHandlers } from "./question"
import { WorkspaceApi, workspaceHandlers } from "./workspace"
import { memoMap } from "@/effect/memo-map"
import { memoMap } from "@opencode-ai/core/effect/memo-map"
const Query = Schema.Struct({
directory: Schema.optional(Schema.String),
@@ -14,7 +14,7 @@ import { LSP } from "@/lsp"
import { Command } from "@/command"
import { QuestionRoutes } from "./question"
import { PermissionRoutes } from "./permission"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { ExperimentalHttpApiServer } from "./httpapi/server"
import { FilePaths } from "./httpapi/file"
import { InstancePaths } from "./httpapi/instance"
+1 -1
View File
@@ -1,4 +1,4 @@
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Hono } from "hono"
import { proxy } from "hono/proxy"
import { getMimeType } from "hono/utils/mime"
+1 -1
View File
@@ -3,7 +3,7 @@ import { Hono } from "hono"
import { adapter } from "#hono"
import { lazy } from "@/util/lazy"
import { Log } from "@/util"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { WorkspaceID } from "@/control-plane/schema"
import { MDNS } from "./mdns"
import { AuthMiddleware, CompressionMiddleware, CorsMiddleware, ErrorMiddleware, LoggerMiddleware } from "./middleware"
+1 -1
View File
@@ -4,7 +4,7 @@ import { getAdaptor } from "@/control-plane/adaptors"
import { WorkspaceID } from "@/control-plane/schema"
import { WorkspaceContext } from "@/control-plane/workspace-context"
import { Workspace } from "@/control-plane/workspace"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { InstanceBootstrap } from "@/project/bootstrap"
import { Instance } from "@/project/instance"
import { Session } from "@/session"
+1 -1
View File
@@ -4,7 +4,7 @@ import { Effect, Layer, Context } from "effect"
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http"
import { Config } from "@/config"
import { InstanceState } from "@/effect"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { withTransientReadRetry } from "@/util/effect-http-client"
import { Global } from "../global"
+2 -2
View File
@@ -12,7 +12,7 @@ import type { Agent } from "@/agent/agent"
import type { MessageV2 } from "./message-v2"
import { Plugin } from "@/plugin"
import { SystemPrompt } from "./system"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Permission } from "@/permission"
import { PermissionID } from "@/permission/schema"
import { Bus } from "@/bus"
@@ -20,7 +20,7 @@ import { Wildcard } from "@/util"
import { SessionID } from "@/session/schema"
import { Auth } from "@/auth"
import { Installation } from "@/installation"
import { InstallationVersion } from "@/installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { EffectBridge } from "@/effect"
import * as Option from "effect/Option"
import * as OtelTracer from "@effect/opentelemetry/Tracer"
+1 -1
View File
@@ -24,7 +24,7 @@ import MAX_STEPS from "../session/prompt/max-steps.txt"
import { ToolRegistry } from "../tool"
import { MCP } from "../mcp"
import { LSP } from "../lsp"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { ulid } from "ulid"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import * as CrossSpawnSpawner from "@/effect/cross-spawn-spawner"
+2 -2
View File
@@ -5,8 +5,8 @@ import { Bus } from "@/bus"
import { Decimal } from "decimal.js"
import z from "zod"
import { type ProviderMetadata, type LanguageModelUsage } from "ai"
import { Flag } from "../flag/flag"
import { InstallationVersion } from "../installation/version"
import { Flag } from "@opencode-ai/core/flag/flag"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { Database, NotFoundError, eq, and, gte, isNull, desc, like, inArray, lt } from "../storage"
import { SyncEvent } from "../sync"
+1 -1
View File
@@ -3,7 +3,7 @@ import { SessionID } from "@/session/schema"
import { SyncEvent } from "@/sync"
import { Effect, Layer, Scope, Context } from "effect"
import { Config } from "../config"
import { Flag } from "../flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import * as ShareNext from "./share-next"
export interface Interface {
+1 -1
View File
@@ -1,4 +1,4 @@
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { lazy } from "@/util/lazy"
import { Filesystem } from "@/util"
import { which } from "@/util/which"
+1 -1
View File
@@ -7,7 +7,7 @@ import { NamedError } from "@opencode-ai/core/util/error"
import type { Agent } from "@/agent/agent"
import { Bus } from "@/bus"
import { InstanceState } from "@/effect"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Global } from "@/global"
import { Permission } from "@/permission"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
+2 -2
View File
@@ -10,8 +10,8 @@ import { NamedError } from "@opencode-ai/core/util/error"
import z from "zod"
import path from "path"
import { readFileSync, readdirSync, existsSync } from "fs"
import { Flag } from "../flag/flag"
import { InstallationChannel } from "../installation/version"
import { Flag } from "@opencode-ai/core/flag/flag"
import { InstallationChannel } from "@opencode-ai/core/installation/version"
import { InstanceState } from "@/effect"
import { iife } from "@/util/iife"
import { init } from "#db"
+1 -1
View File
@@ -7,7 +7,7 @@ import { Instance } from "@/project/instance"
import { EventSequenceTable, EventTable } from "./event.sql"
import { WorkspaceContext } from "@/control-plane/workspace-context"
import { EventID } from "./schema"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Schema as EffectSchema } from "effect"
import { zodObject } from "@/util/effect-zod"
import type { DeepMutable } from "@/util/schema"
+1 -1
View File
@@ -1,6 +1,6 @@
import yargs from "yargs"
import { TuiThreadCommand } from "./cli/cmd/tui/thread"
import { InstallationVersion } from "./installation/version"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { hideBin } from "yargs/helpers"
import { Log } from "./node"
+1 -1
View File
@@ -11,7 +11,7 @@ import { Language, type Node } from "web-tree-sitter"
import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { fileURLToPath } from "url"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Shell } from "@/shell/shell"
import { BashArity } from "@/permission/arity"
+1 -1
View File
@@ -23,7 +23,7 @@ import { Provider } from "../provider"
import { ProviderID, type ModelID } from "../provider/schema"
import { WebSearchTool } from "./websearch"
import { CodeSearchTool } from "./codesearch"
import { Flag } from "@/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Log } from "@/util"
import { LspTool } from "./lsp"
import * as Truncate from "./truncate"
+1 -1
View File
@@ -5,7 +5,7 @@ export * as Keybind from "./keybind"
export * as LocalContext from "./local-context"
export * as Locale from "./locale"
export * as Lock from "./lock"
export * as Log from "./log"
export * as Log from "@opencode-ai/core/util/log"
export * as Process from "./process"
export * as Rpc from "./rpc"
export * as Token from "./token"
@@ -3,7 +3,7 @@ import { Effect, Layer, Stream } from "effect"
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
import { Installation } from "../../src/installation"
import { InstallationChannel } from "../../src/installation/version"
import { InstallationChannel } from "@opencode-ai/core/installation/version"
const encoder = new TextEncoder()
@@ -7,7 +7,7 @@ import { tmpdir } from "../fixture/fixture"
const disableDefault = process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS
process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS = "1"
const { Flag } = await import("../../src/flag/flag")
const { Flag } = await import("@opencode-ai/core/flag/flag")
const { Plugin } = await import("../../src/plugin/index")
const { Workspace } = await import("../../src/control-plane/workspace")
const { Instance } = await import("../../src/project/instance")
@@ -1,6 +1,6 @@
import { afterEach, describe, expect, test } from "bun:test"
import type { UpgradeWebSocket } from "hono/ws"
import { Flag } from "../../src/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Instance } from "../../src/project/instance"
import { InstanceRoutes } from "../../src/server/routes/instance"
import { FilePaths } from "../../src/server/routes/instance/httpapi/file"
@@ -1,7 +1,7 @@
import { afterEach, describe, expect, test } from "bun:test"
import type { UpgradeWebSocket } from "hono/ws"
import path from "path"
import { Flag } from "../../src/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Instance } from "../../src/project/instance"
import { InstanceRoutes } from "../../src/server/routes/instance"
import { InstancePaths } from "../../src/server/routes/instance/httpapi/instance"
+1 -1
View File
@@ -1,7 +1,7 @@
import { describe, expect, test } from "bun:test"
import path from "path"
import { Global } from "../../src/global"
import { InstallationChannel } from "../../src/installation/version"
import { InstallationChannel } from "@opencode-ai/core/installation/version"
import { Database } from "../../src/storage"
describe("Database.Path", () => {
+1 -1
View File
@@ -7,7 +7,7 @@ import { SyncEvent } from "../../src/sync"
import { Database } from "../../src/storage"
import { EventTable } from "../../src/sync/event.sql"
import { Identifier } from "../../src/id/id"
import { Flag } from "../../src/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { initProjectors } from "../../src/server/projectors"
const original = Flag.OPENCODE_EXPERIMENTAL_WORKSPACES
@@ -6,7 +6,7 @@ import { registerAdaptor } from "../../src/control-plane/adaptors"
import type { WorkspaceAdaptor } from "../../src/control-plane/types"
import { Workspace } from "../../src/control-plane/workspace"
import { AppRuntime } from "../../src/effect/app-runtime"
import { Flag } from "../../src/flag/flag"
import { Flag } from "@opencode-ai/core/flag/flag"
import { ModelID, ProviderID } from "../../src/provider/schema"
import { Instance } from "../../src/project/instance"
import { Session as SessionNs } from "../../src/session"