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:
parent
a9740b9133
commit
1a734adb4d
90 changed files with 140 additions and 119 deletions
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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]",
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
import { Cause, Effect, Logger, References } from "effect"
|
||||
import { Log } from "@/util"
|
||||
|
||||
type Fields = Record<string, unknown>
|
||||
|
||||
const normalizeKey = (key: string) => (key === "sessionID" ? "session.id" : key)
|
||||
|
||||
export interface Handle {
|
||||
readonly debug: (msg?: unknown, extra?: Fields) => Effect.Effect<void>
|
||||
readonly info: (msg?: unknown, extra?: Fields) => Effect.Effect<void>
|
||||
readonly warn: (msg?: unknown, extra?: Fields) => Effect.Effect<void>
|
||||
readonly error: (msg?: unknown, extra?: Fields) => Effect.Effect<void>
|
||||
readonly with: (extra: Fields) => Handle
|
||||
}
|
||||
|
||||
const clean = (input?: Fields): Fields =>
|
||||
Object.fromEntries(
|
||||
Object.entries(input ?? {})
|
||||
.filter((entry) => entry[1] !== undefined && entry[1] !== null)
|
||||
.map(([key, value]) => [normalizeKey(key), value]),
|
||||
)
|
||||
|
||||
const text = (input: unknown): string => {
|
||||
// oxlint-disable-next-line no-base-to-string
|
||||
if (Array.isArray(input)) return input.map((item) => String(item)).join(" ")
|
||||
// oxlint-disable-next-line no-base-to-string
|
||||
return input === undefined ? "" : String(input)
|
||||
}
|
||||
|
||||
const call = (run: (msg?: unknown) => Effect.Effect<void>, base: Fields, msg?: unknown, extra?: Fields) => {
|
||||
const ann = clean({ ...base, ...extra })
|
||||
const fx = run(msg)
|
||||
return Object.keys(ann).length ? Effect.annotateLogs(fx, ann) : fx
|
||||
}
|
||||
|
||||
export const logger = Logger.make((opts) => {
|
||||
const extra = clean(opts.fiber.getRef(References.CurrentLogAnnotations))
|
||||
const now = opts.date.getTime()
|
||||
for (const [key, start] of opts.fiber.getRef(References.CurrentLogSpans)) {
|
||||
extra[`logSpan.${key}`] = `${now - start}ms`
|
||||
}
|
||||
if (opts.cause.reasons.length > 0) {
|
||||
extra.cause = Cause.pretty(opts.cause)
|
||||
}
|
||||
|
||||
const svc = typeof extra.service === "string" ? extra.service : undefined
|
||||
if (svc) delete extra.service
|
||||
const log = svc ? Log.create({ service: svc }) : Log.Default
|
||||
const msg = text(opts.message)
|
||||
|
||||
switch (opts.logLevel) {
|
||||
case "Trace":
|
||||
case "Debug":
|
||||
return log.debug(msg, extra)
|
||||
case "Warn":
|
||||
return log.warn(msg, extra)
|
||||
case "Error":
|
||||
case "Fatal":
|
||||
return log.error(msg, extra)
|
||||
default:
|
||||
return log.info(msg, extra)
|
||||
}
|
||||
})
|
||||
|
||||
export const layer = Logger.layer([logger], { mergeWithExisting: false })
|
||||
|
||||
export const create = (base: Fields = {}): Handle => ({
|
||||
debug: (msg, extra) => call((item) => Effect.logDebug(item), base, msg, extra),
|
||||
info: (msg, extra) => call((item) => Effect.logInfo(item), base, msg, extra),
|
||||
warn: (msg, extra) => call((item) => Effect.logWarning(item), base, msg, extra),
|
||||
error: (msg, extra) => call((item) => Effect.logError(item), base, msg, extra),
|
||||
with: (extra) => create({ ...base, ...extra }),
|
||||
})
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { Layer } from "effect"
|
||||
|
||||
export const memoMap = Layer.makeMemoMapUnsafe()
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
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"
|
||||
|
||||
const base = Flag.OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
export const enabled = !!base
|
||||
const processID = crypto.randomUUID()
|
||||
|
||||
const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
|
||||
? Flag.OTEL_EXPORTER_OTLP_HEADERS.split(",").reduce(
|
||||
(acc, x) => {
|
||||
const [key, ...value] = x.split("=")
|
||||
acc[key] = value.join("=")
|
||||
return acc
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
)
|
||||
: undefined
|
||||
|
||||
export function resource(): { serviceName: string; serviceVersion: string; attributes: Record<string, string> } {
|
||||
const processMetadata = ensureProcessMetadata("main")
|
||||
const attributes: Record<string, string> = (() => {
|
||||
const value = process.env.OTEL_RESOURCE_ATTRIBUTES
|
||||
if (!value) return {}
|
||||
try {
|
||||
return Object.fromEntries(
|
||||
value.split(",").map((entry) => {
|
||||
const index = entry.indexOf("=")
|
||||
if (index < 1) throw new Error("Invalid OTEL_RESOURCE_ATTRIBUTES entry")
|
||||
return [decodeURIComponent(entry.slice(0, index)), decodeURIComponent(entry.slice(index + 1))]
|
||||
}),
|
||||
)
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
})()
|
||||
|
||||
return {
|
||||
serviceName: "opencode",
|
||||
serviceVersion: InstallationVersion,
|
||||
attributes: {
|
||||
...attributes,
|
||||
"deployment.environment.name": InstallationChannel,
|
||||
"opencode.client": Flag.OPENCODE_CLIENT,
|
||||
"opencode.process_role": processMetadata.processRole,
|
||||
"opencode.run_id": processMetadata.runID,
|
||||
"service.instance.id": processID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function logs() {
|
||||
return Logger.layer(
|
||||
[
|
||||
EffectLogger.logger,
|
||||
OtlpLogger.make({
|
||||
url: `${base}/v1/logs`,
|
||||
resource: resource(),
|
||||
headers,
|
||||
}),
|
||||
],
|
||||
{ mergeWithExisting: false },
|
||||
).pipe(Layer.provide(OtlpSerialization.layerJson), Layer.provide(FetchHttpClient.layer))
|
||||
}
|
||||
|
||||
const traces = async () => {
|
||||
const NodeSdk = await import("@effect/opentelemetry/NodeSdk")
|
||||
const OTLP = await import("@opentelemetry/exporter-trace-otlp-http")
|
||||
const SdkBase = await import("@opentelemetry/sdk-trace-base")
|
||||
|
||||
// @effect/opentelemetry creates a NodeTracerProvider but never calls
|
||||
// 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
|
||||
// new trace. Registering AsyncLocalStorageContextManager fixes this.
|
||||
const { AsyncLocalStorageContextManager } = await import("@opentelemetry/context-async-hooks")
|
||||
const { context } = await import("@opentelemetry/api")
|
||||
const mgr = new AsyncLocalStorageContextManager()
|
||||
mgr.enable()
|
||||
context.setGlobalContextManager(mgr)
|
||||
|
||||
return NodeSdk.layer(() => ({
|
||||
resource: resource(),
|
||||
spanProcessor: new SdkBase.BatchSpanProcessor(
|
||||
new OTLP.OTLPTraceExporter({
|
||||
url: `${base}/v1/traces`,
|
||||
headers,
|
||||
}),
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
export const layer = !base
|
||||
? EffectLogger.layer
|
||||
: Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
const trace = yield* Effect.promise(traces)
|
||||
return Layer.mergeAll(trace, logs())
|
||||
}),
|
||||
)
|
||||
|
||||
export const Observability = { enabled, layer }
|
||||
|
|
@ -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,19 +0,0 @@
|
|||
import { Observability } from "./observability"
|
||||
import { Layer, type Context, ManagedRuntime, type Effect } from "effect"
|
||||
import { memoMap } from "./memo-map"
|
||||
|
||||
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 }))
|
||||
|
||||
return {
|
||||
runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(service.use(fn)),
|
||||
runPromiseExit: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>, options?: Effect.RunOptions) =>
|
||||
getRuntime().runPromiseExit(service.use(fn), options),
|
||||
runPromise: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>, options?: Effect.RunOptions) =>
|
||||
getRuntime().runPromise(service.use(fn), options),
|
||||
runFork: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runFork(service.use(fn)),
|
||||
runCallback: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runCallback(service.use(fn)),
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,107 +0,0 @@
|
|||
import { Config } from "effect"
|
||||
|
||||
function truthy(key: string) {
|
||||
const value = process.env[key]?.toLowerCase()
|
||||
return value === "true" || value === "1"
|
||||
}
|
||||
|
||||
function falsy(key: string) {
|
||||
const value = process.env[key]?.toLowerCase()
|
||||
return value === "false" || value === "0"
|
||||
}
|
||||
|
||||
function number(key: string) {
|
||||
const value = process.env[key]
|
||||
if (!value) return undefined
|
||||
const parsed = Number(value)
|
||||
return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined
|
||||
}
|
||||
|
||||
const OPENCODE_EXPERIMENTAL = truthy("OPENCODE_EXPERIMENTAL")
|
||||
const OPENCODE_DISABLE_CLAUDE_CODE = truthy("OPENCODE_DISABLE_CLAUDE_CODE")
|
||||
const OPENCODE_DISABLE_CLAUDE_CODE_SKILLS =
|
||||
OPENCODE_DISABLE_CLAUDE_CODE || truthy("OPENCODE_DISABLE_CLAUDE_CODE_SKILLS")
|
||||
const copy = process.env["OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT"]
|
||||
|
||||
export const Flag = {
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: process.env["OTEL_EXPORTER_OTLP_ENDPOINT"],
|
||||
OTEL_EXPORTER_OTLP_HEADERS: process.env["OTEL_EXPORTER_OTLP_HEADERS"],
|
||||
|
||||
OPENCODE_AUTO_SHARE: truthy("OPENCODE_AUTO_SHARE"),
|
||||
OPENCODE_AUTO_HEAP_SNAPSHOT: truthy("OPENCODE_AUTO_HEAP_SNAPSHOT"),
|
||||
OPENCODE_GIT_BASH_PATH: process.env["OPENCODE_GIT_BASH_PATH"],
|
||||
OPENCODE_CONFIG: process.env["OPENCODE_CONFIG"],
|
||||
OPENCODE_CONFIG_CONTENT: process.env["OPENCODE_CONFIG_CONTENT"],
|
||||
OPENCODE_DISABLE_AUTOUPDATE: truthy("OPENCODE_DISABLE_AUTOUPDATE"),
|
||||
OPENCODE_ALWAYS_NOTIFY_UPDATE: truthy("OPENCODE_ALWAYS_NOTIFY_UPDATE"),
|
||||
OPENCODE_DISABLE_PRUNE: truthy("OPENCODE_DISABLE_PRUNE"),
|
||||
OPENCODE_DISABLE_TERMINAL_TITLE: truthy("OPENCODE_DISABLE_TERMINAL_TITLE"),
|
||||
OPENCODE_SHOW_TTFD: truthy("OPENCODE_SHOW_TTFD"),
|
||||
OPENCODE_PERMISSION: process.env["OPENCODE_PERMISSION"],
|
||||
OPENCODE_DISABLE_DEFAULT_PLUGINS: truthy("OPENCODE_DISABLE_DEFAULT_PLUGINS"),
|
||||
OPENCODE_DISABLE_LSP_DOWNLOAD: truthy("OPENCODE_DISABLE_LSP_DOWNLOAD"),
|
||||
OPENCODE_ENABLE_EXPERIMENTAL_MODELS: truthy("OPENCODE_ENABLE_EXPERIMENTAL_MODELS"),
|
||||
OPENCODE_DISABLE_AUTOCOMPACT: truthy("OPENCODE_DISABLE_AUTOCOMPACT"),
|
||||
OPENCODE_DISABLE_MODELS_FETCH: truthy("OPENCODE_DISABLE_MODELS_FETCH"),
|
||||
OPENCODE_DISABLE_MOUSE: truthy("OPENCODE_DISABLE_MOUSE"),
|
||||
OPENCODE_DISABLE_CLAUDE_CODE,
|
||||
OPENCODE_DISABLE_CLAUDE_CODE_PROMPT: OPENCODE_DISABLE_CLAUDE_CODE || truthy("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"),
|
||||
OPENCODE_DISABLE_CLAUDE_CODE_SKILLS,
|
||||
OPENCODE_DISABLE_EXTERNAL_SKILLS: OPENCODE_DISABLE_CLAUDE_CODE_SKILLS || truthy("OPENCODE_DISABLE_EXTERNAL_SKILLS"),
|
||||
OPENCODE_FAKE_VCS: process.env["OPENCODE_FAKE_VCS"],
|
||||
OPENCODE_SERVER_PASSWORD: process.env["OPENCODE_SERVER_PASSWORD"],
|
||||
OPENCODE_SERVER_USERNAME: process.env["OPENCODE_SERVER_USERNAME"],
|
||||
OPENCODE_ENABLE_QUESTION_TOOL: truthy("OPENCODE_ENABLE_QUESTION_TOOL"),
|
||||
|
||||
// Experimental
|
||||
OPENCODE_EXPERIMENTAL,
|
||||
OPENCODE_EXPERIMENTAL_FILEWATCHER: Config.boolean("OPENCODE_EXPERIMENTAL_FILEWATCHER").pipe(
|
||||
Config.withDefault(false),
|
||||
),
|
||||
OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: Config.boolean("OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER").pipe(
|
||||
Config.withDefault(false),
|
||||
),
|
||||
OPENCODE_EXPERIMENTAL_ICON_DISCOVERY: OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY"),
|
||||
OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT:
|
||||
copy === undefined ? process.platform === "win32" : truthy("OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT"),
|
||||
OPENCODE_ENABLE_EXA: truthy("OPENCODE_ENABLE_EXA") || OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_EXA"),
|
||||
OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS: number("OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS"),
|
||||
OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX: number("OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX"),
|
||||
OPENCODE_EXPERIMENTAL_OXFMT: OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_OXFMT"),
|
||||
OPENCODE_EXPERIMENTAL_LSP_TY: truthy("OPENCODE_EXPERIMENTAL_LSP_TY"),
|
||||
OPENCODE_EXPERIMENTAL_LSP_TOOL: OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_LSP_TOOL"),
|
||||
OPENCODE_EXPERIMENTAL_PLAN_MODE: OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_PLAN_MODE"),
|
||||
OPENCODE_EXPERIMENTAL_MARKDOWN: !falsy("OPENCODE_EXPERIMENTAL_MARKDOWN"),
|
||||
OPENCODE_MODELS_URL: process.env["OPENCODE_MODELS_URL"],
|
||||
OPENCODE_MODELS_PATH: process.env["OPENCODE_MODELS_PATH"],
|
||||
OPENCODE_DISABLE_EMBEDDED_WEB_UI: truthy("OPENCODE_DISABLE_EMBEDDED_WEB_UI"),
|
||||
OPENCODE_DB: process.env["OPENCODE_DB"],
|
||||
OPENCODE_DISABLE_CHANNEL_DB: truthy("OPENCODE_DISABLE_CHANNEL_DB"),
|
||||
OPENCODE_SKIP_MIGRATIONS: truthy("OPENCODE_SKIP_MIGRATIONS"),
|
||||
OPENCODE_STRICT_CONFIG_DEPS: truthy("OPENCODE_STRICT_CONFIG_DEPS"),
|
||||
|
||||
OPENCODE_WORKSPACE_ID: process.env["OPENCODE_WORKSPACE_ID"],
|
||||
OPENCODE_EXPERIMENTAL_HTTPAPI: truthy("OPENCODE_EXPERIMENTAL_HTTPAPI"),
|
||||
OPENCODE_EXPERIMENTAL_WORKSPACES: OPENCODE_EXPERIMENTAL || truthy("OPENCODE_EXPERIMENTAL_WORKSPACES"),
|
||||
|
||||
// Evaluated at access time (not module load) because tests, the CLI, and
|
||||
// external tooling set these env vars at runtime.
|
||||
get OPENCODE_DISABLE_PROJECT_CONFIG() {
|
||||
return truthy("OPENCODE_DISABLE_PROJECT_CONFIG")
|
||||
},
|
||||
get OPENCODE_TUI_CONFIG() {
|
||||
return process.env["OPENCODE_TUI_CONFIG"]
|
||||
},
|
||||
get OPENCODE_CONFIG_DIR() {
|
||||
return process.env["OPENCODE_CONFIG_DIR"]
|
||||
},
|
||||
get OPENCODE_PURE() {
|
||||
return truthy("OPENCODE_PURE")
|
||||
},
|
||||
get OPENCODE_PLUGIN_META_FILE() {
|
||||
return process.env["OPENCODE_PLUGIN_META_FILE"]
|
||||
},
|
||||
get OPENCODE_CLIENT() {
|
||||
return process.env["OPENCODE_CLIENT"] ?? "cli"
|
||||
},
|
||||
}
|
||||
|
|
@ -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"> {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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,8 +0,0 @@
|
|||
declare global {
|
||||
const OPENCODE_VERSION: string
|
||||
const OPENCODE_CHANNEL: string
|
||||
}
|
||||
|
||||
export const InstallationVersion = typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "local"
|
||||
export const InstallationChannel = typeof OPENCODE_CHANNEL === "string" ? OPENCODE_CHANNEL : "local"
|
||||
export const InstallationLocal = InstallationChannel === "local"
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1,185 +0,0 @@
|
|||
import path from "path"
|
||||
import fs from "fs/promises"
|
||||
import { createWriteStream } from "fs"
|
||||
import { Global } from "../global"
|
||||
import z from "zod"
|
||||
import { Glob } from "@opencode-ai/core/util/glob"
|
||||
|
||||
export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" })
|
||||
export type Level = z.infer<typeof Level>
|
||||
|
||||
const levelPriority: Record<Level, number> = {
|
||||
DEBUG: 0,
|
||||
INFO: 1,
|
||||
WARN: 2,
|
||||
ERROR: 3,
|
||||
}
|
||||
const keep = 10
|
||||
|
||||
let level: Level = "INFO"
|
||||
|
||||
function shouldLog(input: Level): boolean {
|
||||
return levelPriority[input] >= levelPriority[level]
|
||||
}
|
||||
|
||||
export type Logger = {
|
||||
debug(message?: any, extra?: Record<string, any>): void
|
||||
info(message?: any, extra?: Record<string, any>): void
|
||||
error(message?: any, extra?: Record<string, any>): void
|
||||
warn(message?: any, extra?: Record<string, any>): void
|
||||
tag(key: string, value: string): Logger
|
||||
clone(): Logger
|
||||
time(
|
||||
message: string,
|
||||
extra?: Record<string, any>,
|
||||
): {
|
||||
stop(): void
|
||||
[Symbol.dispose](): void
|
||||
}
|
||||
}
|
||||
|
||||
const loggers = new Map<string, Logger>()
|
||||
|
||||
export const Default = create({ service: "default" })
|
||||
|
||||
export interface Options {
|
||||
print: boolean
|
||||
dev?: boolean
|
||||
level?: Level
|
||||
}
|
||||
|
||||
let logpath = ""
|
||||
export function file() {
|
||||
return logpath
|
||||
}
|
||||
let write = (msg: any) => {
|
||||
process.stderr.write(msg)
|
||||
return msg.length
|
||||
}
|
||||
|
||||
export async function init(options: Options) {
|
||||
if (options.level) level = options.level
|
||||
void cleanup(Global.Path.log)
|
||||
if (options.print) return
|
||||
logpath = path.join(
|
||||
Global.Path.log,
|
||||
options.dev ? "dev.log" : new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log",
|
||||
)
|
||||
await fs.truncate(logpath).catch(() => {})
|
||||
const stream = createWriteStream(logpath, { flags: "a" })
|
||||
write = async (msg: any) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
stream.write(msg, (err) => {
|
||||
if (err) reject(err)
|
||||
else resolve(msg.length)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanup(dir: string) {
|
||||
const files = (
|
||||
await Glob.scan("????-??-??T??????.log", {
|
||||
cwd: dir,
|
||||
absolute: false,
|
||||
include: "file",
|
||||
}).catch(() => [])
|
||||
)
|
||||
.filter((file) => path.basename(file) === file)
|
||||
.sort()
|
||||
if (files.length <= keep) return
|
||||
|
||||
const doomed = files.slice(0, -keep)
|
||||
await Promise.all(doomed.map((file) => fs.unlink(path.join(dir, file)).catch(() => {})))
|
||||
}
|
||||
|
||||
function formatError(error: Error, depth = 0): string {
|
||||
const result = error.message
|
||||
return error.cause instanceof Error && depth < 10
|
||||
? result + " Caused by: " + formatError(error.cause, depth + 1)
|
||||
: result
|
||||
}
|
||||
|
||||
let last = Date.now()
|
||||
export function create(tags?: Record<string, any>) {
|
||||
tags = tags || {}
|
||||
|
||||
const service = tags["service"]
|
||||
if (service && typeof service === "string") {
|
||||
const cached = loggers.get(service)
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
}
|
||||
|
||||
function build(message: any, extra?: Record<string, any>) {
|
||||
const prefix = Object.entries({
|
||||
...tags,
|
||||
...extra,
|
||||
})
|
||||
.filter(([_, value]) => value !== undefined && value !== null)
|
||||
.map(([key, value]) => {
|
||||
const prefix = `${key}=`
|
||||
if (value instanceof Error) return prefix + formatError(value)
|
||||
if (typeof value === "object") return prefix + JSON.stringify(value)
|
||||
return prefix + value
|
||||
})
|
||||
.join(" ")
|
||||
const next = new Date()
|
||||
const diff = next.getTime() - last
|
||||
last = next.getTime()
|
||||
return [next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message].filter(Boolean).join(" ") + "\n"
|
||||
}
|
||||
const result: Logger = {
|
||||
debug(message?: any, extra?: Record<string, any>) {
|
||||
if (shouldLog("DEBUG")) {
|
||||
write("DEBUG " + build(message, extra))
|
||||
}
|
||||
},
|
||||
info(message?: any, extra?: Record<string, any>) {
|
||||
if (shouldLog("INFO")) {
|
||||
write("INFO " + build(message, extra))
|
||||
}
|
||||
},
|
||||
error(message?: any, extra?: Record<string, any>) {
|
||||
if (shouldLog("ERROR")) {
|
||||
write("ERROR " + build(message, extra))
|
||||
}
|
||||
},
|
||||
warn(message?: any, extra?: Record<string, any>) {
|
||||
if (shouldLog("WARN")) {
|
||||
write("WARN " + build(message, extra))
|
||||
}
|
||||
},
|
||||
tag(key: string, value: string) {
|
||||
if (tags) tags[key] = value
|
||||
return result
|
||||
},
|
||||
clone() {
|
||||
return create({ ...tags })
|
||||
},
|
||||
time(message: string, extra?: Record<string, any>) {
|
||||
const now = Date.now()
|
||||
result.info(message, { status: "started", ...extra })
|
||||
function stop() {
|
||||
result.info(message, {
|
||||
status: "completed",
|
||||
duration: Date.now() - now,
|
||||
...extra,
|
||||
})
|
||||
}
|
||||
return {
|
||||
stop,
|
||||
[Symbol.dispose]() {
|
||||
stop()
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if (service && typeof service === "string") {
|
||||
loggers.set(service, result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
export const OPENCODE_RUN_ID = "OPENCODE_RUN_ID"
|
||||
export const OPENCODE_PROCESS_ROLE = "OPENCODE_PROCESS_ROLE"
|
||||
|
||||
export function ensureRunID() {
|
||||
return (process.env[OPENCODE_RUN_ID] ??= crypto.randomUUID())
|
||||
}
|
||||
|
||||
export function ensureProcessRole(fallback: "main" | "worker") {
|
||||
return (process.env[OPENCODE_PROCESS_ROLE] ??= fallback)
|
||||
}
|
||||
|
||||
export function ensureProcessMetadata(fallback: "main" | "worker") {
|
||||
return {
|
||||
runID: ensureRunID(),
|
||||
processRole: ensureProcessRole(fallback),
|
||||
}
|
||||
}
|
||||
|
||||
export function sanitizedProcessEnv(overrides?: Record<string, string>) {
|
||||
const env = Object.fromEntries(
|
||||
Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] !== undefined),
|
||||
)
|
||||
return overrides ? Object.assign(env, overrides) : env
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { resource } from "../../src/effect/observability"
|
||||
|
||||
const otelResourceAttributes = process.env.OTEL_RESOURCE_ATTRIBUTES
|
||||
const opencodeClient = process.env.OPENCODE_CLIENT
|
||||
|
||||
afterEach(() => {
|
||||
if (otelResourceAttributes === undefined) delete process.env.OTEL_RESOURCE_ATTRIBUTES
|
||||
else process.env.OTEL_RESOURCE_ATTRIBUTES = otelResourceAttributes
|
||||
|
||||
if (opencodeClient === undefined) delete process.env.OPENCODE_CLIENT
|
||||
else process.env.OPENCODE_CLIENT = opencodeClient
|
||||
})
|
||||
|
||||
describe("resource", () => {
|
||||
test("parses and decodes OTEL resource attributes", () => {
|
||||
process.env.OTEL_RESOURCE_ATTRIBUTES =
|
||||
"service.namespace=anomalyco,team=platform%2Cobservability,label=hello%3Dworld,key%2Fname=value%20here"
|
||||
|
||||
expect(resource().attributes).toMatchObject({
|
||||
"service.namespace": "anomalyco",
|
||||
team: "platform,observability",
|
||||
label: "hello=world",
|
||||
"key/name": "value here",
|
||||
})
|
||||
})
|
||||
|
||||
test("drops OTEL resource attributes when any entry is invalid", () => {
|
||||
process.env.OTEL_RESOURCE_ATTRIBUTES = "service.namespace=anomalyco,broken"
|
||||
|
||||
expect(resource().attributes["service.namespace"]).toBeUndefined()
|
||||
expect(resource().attributes["opencode.client"]).toBeDefined()
|
||||
})
|
||||
|
||||
test("keeps built-in attributes when env values conflict", () => {
|
||||
process.env.OPENCODE_CLIENT = "cli"
|
||||
process.env.OTEL_RESOURCE_ATTRIBUTES =
|
||||
"opencode.client=web,service.instance.id=override,service.namespace=anomalyco"
|
||||
|
||||
expect(resource().attributes).toMatchObject({
|
||||
"opencode.client": "cli",
|
||||
"service.namespace": "anomalyco",
|
||||
})
|
||||
expect(resource().attributes["service.instance.id"]).not.toBe("override")
|
||||
})
|
||||
})
|
||||
|
|
@ -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,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", () => {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue