diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 5f0bcdc24b..669462772d 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -31,9 +31,9 @@ import { type Usage, } from "@agentclientprotocol/sdk" -import { Log } from "../util/log" +import { Log } from "../util" import { pathToFileURL } from "url" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" import { Hash } from "@opencode-ai/shared/util/hash" import { ACPSessionManager } from "./session" import type { ACPConfig } from "./types" diff --git a/packages/opencode/src/acp/session.ts b/packages/opencode/src/acp/session.ts index b96ebc1c89..523b037374 100644 --- a/packages/opencode/src/acp/session.ts +++ b/packages/opencode/src/acp/session.ts @@ -1,6 +1,6 @@ import { RequestError, type McpServer } from "@agentclientprotocol/sdk" import type { ACPSessionState } from "./types" -import { Log } from "@/util/log" +import { Log } from "@/util" import type { OpencodeClient } from "@opencode-ai/sdk/v2" const log = Log.create({ service: "acp-session-manager" }) diff --git a/packages/opencode/src/bus/bus.ts b/packages/opencode/src/bus/bus.ts index 12d7f246cd..beac809925 100644 --- a/packages/opencode/src/bus/bus.ts +++ b/packages/opencode/src/bus/bus.ts @@ -1,7 +1,7 @@ import z from "zod" import { Effect, Exit, Layer, PubSub, Scope, Context, Stream } from "effect" import { EffectBridge } from "@/effect" -import { Log } from "../util/log" +import { Log } from "../util" import { BusEvent } from "./bus-event" import { GlobalBus } from "./global" import { InstanceState } from "@/effect" diff --git a/packages/opencode/src/cli/cmd/acp.ts b/packages/opencode/src/cli/cmd/acp.ts index 2fb9038b0f..8141adc4f7 100644 --- a/packages/opencode/src/cli/cmd/acp.ts +++ b/packages/opencode/src/cli/cmd/acp.ts @@ -1,4 +1,4 @@ -import { Log } from "@/util/log" +import { Log } from "@/util" import { bootstrap } from "../bootstrap" import { cmd } from "./cmd" import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk" diff --git a/packages/opencode/src/cli/cmd/agent.ts b/packages/opencode/src/cli/cmd/agent.ts index 0e93946a23..fd559935fc 100644 --- a/packages/opencode/src/cli/cmd/agent.ts +++ b/packages/opencode/src/cli/cmd/agent.ts @@ -7,7 +7,7 @@ import { Agent } from "../../agent/agent" import { Provider } from "../../provider" import path from "path" import fs from "fs/promises" -import { Filesystem } from "../../util/filesystem" +import { Filesystem } from "../../util" import matter from "gray-matter" import { Instance } from "../../project/instance" import { EOL } from "os" diff --git a/packages/opencode/src/cli/cmd/debug/lsp.ts b/packages/opencode/src/cli/cmd/debug/lsp.ts index 18f67b3917..185cab9c75 100644 --- a/packages/opencode/src/cli/cmd/debug/lsp.ts +++ b/packages/opencode/src/cli/cmd/debug/lsp.ts @@ -3,7 +3,7 @@ import { AppRuntime } from "../../../effect/app-runtime" import { Effect } from "effect" import { bootstrap } from "../../bootstrap" import { cmd } from "../cmd" -import { Log } from "../../../util/log" +import { Log } from "../../../util" import { EOL } from "os" export const LSPCommand = cmd({ diff --git a/packages/opencode/src/cli/cmd/debug/scrap.ts b/packages/opencode/src/cli/cmd/debug/scrap.ts index f4b96e883a..464b165d72 100644 --- a/packages/opencode/src/cli/cmd/debug/scrap.ts +++ b/packages/opencode/src/cli/cmd/debug/scrap.ts @@ -1,6 +1,6 @@ import { EOL } from "os" import { Project } from "../../../project/project" -import { Log } from "../../../util/log" +import { Log } from "../../../util" import { cmd } from "../cmd" export const ScrapCommand = cmd({ diff --git a/packages/opencode/src/cli/cmd/github.ts b/packages/opencode/src/cli/cmd/github.ts index 46d091642f..d7863c5486 100644 --- a/packages/opencode/src/cli/cmd/github.ts +++ b/packages/opencode/src/cli/cmd/github.ts @@ -1,6 +1,6 @@ import path from "path" import { exec } from "child_process" -import { Filesystem } from "../../util/filesystem" +import { Filesystem } from "../../util" import * as prompts from "@clack/prompts" import { map, pipe, sortBy, values } from "remeda" import { Octokit } from "@octokit/rest" @@ -32,7 +32,7 @@ import { SessionPrompt } from "@/session/prompt" import { AppRuntime } from "@/effect/app-runtime" import { Git } from "@/git" import { setTimeout as sleep } from "node:timers/promises" -import { Process } from "@/util/process" +import { Process } from "@/util" import { Effect } from "effect" type GitHubAuthor = { diff --git a/packages/opencode/src/cli/cmd/import.ts b/packages/opencode/src/cli/cmd/import.ts index 1232f07422..bb8a1f63f3 100644 --- a/packages/opencode/src/cli/cmd/import.ts +++ b/packages/opencode/src/cli/cmd/import.ts @@ -9,7 +9,7 @@ import { SessionTable, MessageTable, PartTable } from "../../session/session.sql import { Instance } from "../../project/instance" import { ShareNext } from "../../share/share-next" import { EOL } from "os" -import { Filesystem } from "../../util/filesystem" +import { Filesystem } from "../../util" import { AppRuntime } from "@/effect/app-runtime" /** Discriminated union returned by the ShareNext API (GET /api/shares/:id/data) */ diff --git a/packages/opencode/src/cli/cmd/mcp.ts b/packages/opencode/src/cli/cmd/mcp.ts index b9e4b04219..06c03d9f49 100644 --- a/packages/opencode/src/cli/cmd/mcp.ts +++ b/packages/opencode/src/cli/cmd/mcp.ts @@ -13,7 +13,7 @@ import { Installation } from "../../installation" import path from "path" import { Global } from "../../global" import { modify, applyEdits } from "jsonc-parser" -import { Filesystem } from "../../util/filesystem" +import { Filesystem } from "../../util" import { Bus } from "../../bus" import { AppRuntime } from "../../effect/app-runtime" import { Effect } from "effect" diff --git a/packages/opencode/src/cli/cmd/plug.ts b/packages/opencode/src/cli/cmd/plug.ts index 692c556b24..42d06ff47f 100644 --- a/packages/opencode/src/cli/cmd/plug.ts +++ b/packages/opencode/src/cli/cmd/plug.ts @@ -7,8 +7,8 @@ import { installPlugin, patchPluginConfig, readPluginManifest } from "../../plug import { resolvePluginTarget } from "../../plugin/shared" import { Instance } from "../../project/instance" import { errorMessage } from "../../util/error" -import { Filesystem } from "../../util/filesystem" -import { Process } from "../../util/process" +import { Filesystem } from "../../util" +import { Process } from "../../util" import { UI } from "../ui" import { cmd } from "./cmd" diff --git a/packages/opencode/src/cli/cmd/pr.ts b/packages/opencode/src/cli/cmd/pr.ts index f392bab4c8..6141ef90a8 100644 --- a/packages/opencode/src/cli/cmd/pr.ts +++ b/packages/opencode/src/cli/cmd/pr.ts @@ -3,7 +3,7 @@ import { cmd } from "./cmd" import { AppRuntime } from "@/effect/app-runtime" import { Git } from "@/git" import { Instance } from "@/project/instance" -import { Process } from "@/util/process" +import { Process } from "@/util" export const PrCommand = cmd({ command: "pr ", diff --git a/packages/opencode/src/cli/cmd/providers.ts b/packages/opencode/src/cli/cmd/providers.ts index 5b7f5a1a0d..47a5c37e85 100644 --- a/packages/opencode/src/cli/cmd/providers.ts +++ b/packages/opencode/src/cli/cmd/providers.ts @@ -12,7 +12,7 @@ import { Global } from "../../global" import { Plugin } from "../../plugin" import { Instance } from "../../project/instance" import type { Hooks } from "@opencode-ai/plugin" -import { Process } from "../../util/process" +import { Process } from "../../util" import { text } from "node:stream/consumers" import { Effect } from "effect" diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index e94ba5d119..da72372370 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -6,7 +6,7 @@ import { cmd } from "./cmd" import { Flag } from "../../flag/flag" import { bootstrap } from "../bootstrap" import { EOL } from "os" -import { Filesystem } from "../../util/filesystem" +import { Filesystem } from "../../util" import { createOpencodeClient, type OpencodeClient, type ToolPart } from "@opencode-ai/sdk/v2" import { Server } from "../../server/server" import { Provider } from "../../provider" @@ -25,7 +25,7 @@ import { TaskTool } from "../../tool/task" import { SkillTool } from "../../tool/skill" import { BashTool } from "../../tool/bash" import { TodoWriteTool } from "../../tool/todo" -import { Locale } from "../../util/locale" +import { Locale } from "../../util" import { AppRuntime } from "@/effect/app-runtime" type ToolProps = { diff --git a/packages/opencode/src/cli/cmd/session.ts b/packages/opencode/src/cli/cmd/session.ts index 6f79e726fa..8537a74d45 100644 --- a/packages/opencode/src/cli/cmd/session.ts +++ b/packages/opencode/src/cli/cmd/session.ts @@ -4,10 +4,10 @@ import { Session } from "../../session" import { SessionID } from "../../session/schema" import { bootstrap } from "../bootstrap" import { UI } from "../ui" -import { Locale } from "../../util/locale" +import { Locale } from "../../util" import { Flag } from "../../flag/flag" -import { Filesystem } from "../../util/filesystem" -import { Process } from "../../util/process" +import { Filesystem } from "../../util" +import { Process } from "../../util" import { EOL } from "os" import path from "path" import { which } from "../../util/which" diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-mcp.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-mcp.tsx index 173c5ff60c..e3e80c0fda 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-mcp.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-mcp.tsx @@ -4,7 +4,7 @@ import { useSync } from "@tui/context/sync" import { map, pipe, entries, sortBy } from "remeda" import { DialogSelect, type DialogSelectRef, type DialogSelectOption } from "@tui/ui/dialog-select" import { useTheme } from "../context/theme" -import { Keybind } from "@/util/keybind" +import { Keybind } from "@/util" import { TextAttributes } from "@opentui/core" import { useSDK } from "@tui/context/sdk" diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 9ecb21e82a..a42755bee7 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -3,14 +3,14 @@ import { DialogSelect } from "@tui/ui/dialog-select" import { useRoute } from "@tui/context/route" import { useSync } from "@tui/context/sync" import { createMemo, createResource, createSignal, onMount } from "solid-js" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" 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 { DialogSessionRename } from "./dialog-session-rename" -import { Keybind } from "@/util/keybind" +import { Keybind } from "@/util" import { createDebouncedSignal } from "../util/signal" import { useToast } from "../ui/toast" import { DialogWorkspaceCreate, openWorkspaceSession } from "./dialog-workspace-create" diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-stash.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-stash.tsx index e8664f6289..8a6e69145d 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-stash.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-stash.tsx @@ -1,7 +1,7 @@ import { useDialog } from "@tui/ui/dialog" import { DialogSelect } from "@tui/ui/dialog-select" import { createMemo, createSignal } from "solid-js" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import { useTheme } from "../context/theme" import { useKeybind } from "../context/keybind" import { usePromptStash, type StashEntry } from "./prompt/stash" diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 7ca73310bc..305d076223 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -12,7 +12,7 @@ import { useTheme, selectedForeground } from "@tui/context/theme" import { SplitBorder } from "@tui/component/border" import { useCommandDialog } from "@tui/component/dialog-command" import { useTerminalDimensions } from "@opentui/solid" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import type { PromptInfo } from "./history" import { useFrecency } from "./frecency" diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/frecency.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/frecency.tsx index 3ea8826ef8..929f3a07da 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/frecency.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/frecency.tsx @@ -1,6 +1,6 @@ import path from "path" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { onMount } from "solid-js" import { createStore } from "solid-js/store" import { createSimpleContext } from "../../context/helper" diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx index d49dd5c7b6..03db74de94 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx @@ -1,6 +1,6 @@ import path from "path" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { onMount } from "solid-js" import { createStore, produce, unwrap } from "solid-js/store" import { createSimpleContext } from "../../context/helper" diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index 87440d0e24..c361e48c9e 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -3,7 +3,7 @@ import { createEffect, createMemo, onMount, createSignal, onCleanup, on, Show, S import "opentui-spinner/solid" import path from "path" import { fileURLToPath } from "url" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { useLocal } from "@tui/context/local" import { useTheme } from "@tui/context/theme" import { EmptyBorder, SplitBorder } from "@tui/component/border" @@ -27,7 +27,7 @@ import { Clipboard } from "../../util/clipboard" import type { AssistantMessage, FilePart, UserMessage } from "@opencode-ai/sdk/v2" import { TuiEvent } from "../../event" import { iife } from "@/util/iife" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import { formatDuration } from "@/util/format" import { createColors, createFrames } from "../../ui/spinner.ts" import { useDialog } from "@tui/ui/dialog" diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/stash.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/stash.tsx index ef3eb329a9..84ba62338a 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/stash.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/stash.tsx @@ -1,6 +1,6 @@ import path from "path" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { onMount } from "solid-js" import { createStore, produce, unwrap } from "solid-js/store" import { createSimpleContext } from "../../context/helper" diff --git a/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts b/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts index 36ab03de54..eb7b622c6f 100644 --- a/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts +++ b/packages/opencode/src/cli/cmd/tui/component/textarea-keybindings.ts @@ -1,7 +1,7 @@ import { createMemo } from "solid-js" import type { KeyBinding } from "@opentui/core" import { useKeybind } from "../context/keybind" -import { Keybind } from "@/util/keybind" +import { Keybind } from "@/util" const TEXTAREA_ACTIONS = [ "submit", diff --git a/packages/opencode/src/cli/cmd/tui/context/keybind.tsx b/packages/opencode/src/cli/cmd/tui/context/keybind.tsx index 8d3fe487d1..9c883aa205 100644 --- a/packages/opencode/src/cli/cmd/tui/context/keybind.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/keybind.tsx @@ -1,5 +1,5 @@ import { createMemo } from "solid-js" -import { Keybind } from "@/util/keybind" +import { Keybind } from "@/util" import { pipe, mapValues } from "remeda" import type { TuiConfig } from "@/config/tui" import type { ParsedKey, Renderable } from "@opentui/core" diff --git a/packages/opencode/src/cli/cmd/tui/context/kv.tsx b/packages/opencode/src/cli/cmd/tui/context/kv.tsx index 7a52156f88..dc0b96c62a 100644 --- a/packages/opencode/src/cli/cmd/tui/context/kv.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/kv.tsx @@ -1,5 +1,5 @@ import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { createSignal, type Setter } from "solid-js" import { createStore } from "solid-js/store" import { createSimpleContext } from "./helper" diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index 29f95141c9..612f2b7177 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -12,7 +12,7 @@ import { Provider } from "@/provider" import { useArgs } from "./args" import { useSDK } from "./sdk" import { RGBA } from "@opentui/core" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ name: "Local", diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index cab162f8f0..a0a59199bb 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -28,7 +28,7 @@ import type { Snapshot } from "@/snapshot" import { useExit } from "./exit" import { useArgs } from "./args" import { batch, createEffect, on } from "solid-js" -import { Log } from "@/util/log" +import { Log } from "@/util" import { ConsoleState, emptyConsoleState, type ConsoleState as ConsoleStateType } from "@/config/console-state" export const { use: useSync, provider: SyncProvider } = createSimpleContext({ diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx index 0c0658e743..179dc93700 100644 --- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx @@ -40,7 +40,7 @@ import { useKV } from "./kv" import { useRenderer } from "@opentui/solid" import { createStore, produce } from "solid-js/store" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { useTuiConfig } from "./tui-config" import { isRecord } from "@/util/record" import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui" diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/system/plugins.tsx b/packages/opencode/src/cli/cmd/tui/feature-plugins/system/plugins.tsx index f2fd25ffb6..f391eb24a7 100644 --- a/packages/opencode/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/system/plugins.tsx @@ -1,4 +1,4 @@ -import { Keybind } from "@/util/keybind" +import { Keybind } from "@/util" import type { TuiPlugin, TuiPluginApi, TuiPluginModule, TuiPluginStatus } from "@opencode-ai/plugin/tui" import { useKeyboard, useTerminalDimensions } from "@opentui/solid" import { fileURLToPath } from "url" diff --git a/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts b/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts index bd7eac7713..dd873b753a 100644 --- a/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts +++ b/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts @@ -15,7 +15,7 @@ import { fileURLToPath } from "url" import { Config } from "@/config" import { TuiConfig } from "@/config/tui" -import { Log } from "@/util/log" +import { Log } from "@/util" import { errorData, errorMessage } from "@/util/error" import { isRecord } from "@/util/record" import { Instance } from "@/project/instance" @@ -32,8 +32,8 @@ import { PluginMeta } from "@/plugin/meta" import { installPlugin as installModulePlugin, patchPluginConfig, readPluginManifest } from "@/plugin/install" import { hasTheme, upsertTheme } from "../context/theme" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" -import { Process } from "@/util/process" +import { Filesystem } from "@/util" +import { Process } from "@/util" import { Flock } from "@opencode-ai/shared/util/flock" import { Flag } from "@/flag/flag" import { INTERNAL_TUI_PLUGINS, type InternalTuiPlugin } from "./internal" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx index 742d51be22..0ce33a59a9 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx @@ -2,7 +2,7 @@ import { createMemo, onMount } from "solid-js" import { useSync } from "@tui/context/sync" import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select" import type { TextPart } from "@opencode-ai/sdk/v2" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import { useSDK } from "@tui/context/sdk" import { useRoute } from "@tui/context/route" import { useDialog } from "../../ui/dialog" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx index 87248a6a8b..c0052f25fb 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx @@ -2,7 +2,7 @@ import { createMemo, onMount } from "solid-js" import { useSync } from "@tui/context/sync" import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select" import type { TextPart } from "@opencode-ai/sdk/v2" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import { DialogMessage } from "./dialog-message" import { useDialog } from "../../ui/dialog" import type { PromptInfo } from "../../component/prompt/history" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 9f0dfa6038..58b5d6626c 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -33,7 +33,7 @@ import type { ReasoningPart, } from "@opencode-ai/sdk/v2" import { useLocal } from "@tui/context/local" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import type { Tool } from "@/tool/tool" import type { ReadTool } from "@/tool/read" import type { WriteTool } from "@/tool/write" @@ -73,7 +73,7 @@ import { Editor } from "../../util/editor" import stripAnsi from "strip-ansi" import { usePromptRef } from "../../context/prompt" import { useExit } from "../../context/exit" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { Global } from "@/global" import { PermissionPrompt } from "./permission" import { QuestionPrompt } from "./question" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx index ad824fe48f..3554ab44ca 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx @@ -11,8 +11,8 @@ import { useSync } from "../../context/sync" import { useTextareaKeybindings } from "../../component/textarea-keybindings" import path from "path" import { LANGUAGE_EXTENSIONS } from "@/lsp/language" -import { Keybind } from "@/util/keybind" -import { Locale } from "@/util/locale" +import { Keybind } from "@/util" +import { Locale } from "@/util" import { Global } from "@/global" import { useDialog } from "../../ui/dialog" import { getScrollAcceleration } from "../../util/scroll" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx index c857937d4a..5569599607 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/subagent-footer.tsx @@ -6,7 +6,7 @@ import { SplitBorder } from "@tui/component/border" import type { AssistantMessage } from "@opencode-ai/sdk/v2" import { useCommandDialog } from "@tui/component/dialog-command" import { useKeybind } from "../../context/keybind" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import { useTerminalDimensions } from "@opentui/solid" export function SubagentFooter() { diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index 972e67d103..3aaa5a54f8 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -1,15 +1,15 @@ import { cmd } from "@/cli/cmd/cmd" import { tui } from "./app" -import { Rpc } from "@/util/rpc" +import { Rpc } from "@/util" import { type rpc } from "./worker" import path from "path" import { fileURLToPath } from "url" import { UI } from "@/cli/ui" -import { Log } from "@/util/log" +import { Log } from "@/util" import { errorMessage } from "@/util/error" import { withTimeout } from "@/util/timeout" import { withNetworkOptions, resolveNetworkOptions } from "@/cli/network" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import type { GlobalEvent } from "@opencode-ai/sdk/v2" import type { EventSource } from "./context/sdk" import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32" diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx index 48adddaedc..526f3a61b5 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-confirm.tsx @@ -4,7 +4,7 @@ import { useDialog, type DialogContext } from "./dialog" import { createStore } from "solid-js/store" import { For } from "solid-js" import { useKeyboard } from "@opentui/solid" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" export type DialogConfirmProps = { title: string diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index b6c937f411..dda9a5a8ed 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -8,8 +8,8 @@ import * as fuzzysort from "fuzzysort" import { isDeepEqual } from "remeda" import { useDialog, type DialogContext } from "@tui/ui/dialog" import { useKeybind } from "@tui/context/keybind" -import { Keybind } from "@/util/keybind" -import { Locale } from "@/util/locale" +import { Keybind } from "@/util" +import { Locale } from "@/util" import { getScrollAcceleration } from "../util/scroll" import { useTuiConfig } from "../context/tui-config" diff --git a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts index 87c0a63abc..a67eb04f69 100644 --- a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts +++ b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts @@ -4,8 +4,8 @@ import { lazy } from "../../../../util/lazy.js" import { tmpdir } from "os" import path from "path" import fs from "fs/promises" -import { Filesystem } from "../../../../util/filesystem" -import { Process } from "../../../../util/process" +import { Filesystem } from "../../../../util" +import { Process } from "../../../../util" import { which } from "../../../../util/which" /** diff --git a/packages/opencode/src/cli/cmd/tui/util/editor.ts b/packages/opencode/src/cli/cmd/tui/util/editor.ts index 9eaae99fce..540cf6f497 100644 --- a/packages/opencode/src/cli/cmd/tui/util/editor.ts +++ b/packages/opencode/src/cli/cmd/tui/util/editor.ts @@ -3,8 +3,8 @@ import { rm } from "node:fs/promises" import { tmpdir } from "node:os" import { join } from "node:path" import { CliRenderer } from "@opentui/core" -import { Filesystem } from "@/util/filesystem" -import { Process } from "@/util/process" +import { Filesystem } from "@/util" +import { Process } from "@/util" export namespace Editor { export async function open(opts: { value: string; renderer: CliRenderer }): Promise { diff --git a/packages/opencode/src/cli/cmd/tui/util/sound.ts b/packages/opencode/src/cli/cmd/tui/util/sound.ts index d3a8db8b4f..1be35eecbf 100644 --- a/packages/opencode/src/cli/cmd/tui/util/sound.ts +++ b/packages/opencode/src/cli/cmd/tui/util/sound.ts @@ -2,7 +2,7 @@ import { Player } from "cli-sound" import { mkdirSync } from "node:fs" import { tmpdir } from "node:os" import { basename, join } from "node:path" -import { Process } from "@/util/process" +import { Process } from "@/util" import { which } from "@/util/which" import pulseA from "../asset/pulse-a.wav" with { type: "file" } import pulseB from "../asset/pulse-b.wav" with { type: "file" } diff --git a/packages/opencode/src/cli/cmd/tui/util/transcript.ts b/packages/opencode/src/cli/cmd/tui/util/transcript.ts index a89559c953..8fa0bc426e 100644 --- a/packages/opencode/src/cli/cmd/tui/util/transcript.ts +++ b/packages/opencode/src/cli/cmd/tui/util/transcript.ts @@ -1,5 +1,5 @@ import type { AssistantMessage, Part, Provider, UserMessage } from "@opencode-ai/sdk/v2" -import { Locale } from "@/util/locale" +import { Locale } from "@/util" import * as Model from "./model" export type TranscriptOptions = { diff --git a/packages/opencode/src/cli/cmd/tui/worker.ts b/packages/opencode/src/cli/cmd/tui/worker.ts index da9e3985b5..393a407eb0 100644 --- a/packages/opencode/src/cli/cmd/tui/worker.ts +++ b/packages/opencode/src/cli/cmd/tui/worker.ts @@ -1,9 +1,9 @@ import { Installation } from "@/installation" import { Server } from "@/server/server" -import { Log } from "@/util/log" +import { Log } from "@/util" import { Instance } from "@/project/instance" import { InstanceBootstrap } from "@/project/bootstrap" -import { Rpc } from "@/util/rpc" +import { Rpc } from "@/util" import { upgrade } from "@/cli/upgrade" import { Config } from "@/config" import { GlobalBus } from "@/bus/global" diff --git a/packages/opencode/src/cli/cmd/uninstall.ts b/packages/opencode/src/cli/cmd/uninstall.ts index 31830f0859..c0517d491d 100644 --- a/packages/opencode/src/cli/cmd/uninstall.ts +++ b/packages/opencode/src/cli/cmd/uninstall.ts @@ -7,8 +7,8 @@ import { Global } from "../../global" import fs from "fs/promises" import path from "path" import os from "os" -import { Filesystem } from "../../util/filesystem" -import { Process } from "../../util/process" +import { Filesystem } from "../../util" +import { Process } from "../../util" interface UninstallArgs { keepConfig: boolean diff --git a/packages/opencode/src/cli/heap.ts b/packages/opencode/src/cli/heap.ts index bb5a3d0937..cf1cffa800 100644 --- a/packages/opencode/src/cli/heap.ts +++ b/packages/opencode/src/cli/heap.ts @@ -2,7 +2,7 @@ import path from "path" import { writeHeapSnapshot } from "node:v8" import { Flag } from "@/flag/flag" import { Global } from "@/global" -import { Log } from "@/util/log" +import { Log } from "@/util" const log = Log.create({ service: "heap" }) const MINUTE = 60_000 diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 7eeacf1ffc..ee1c755ebc 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1,8 +1,8 @@ -import { Log } from "../util/log" +import { Log } from "../util" import path from "path" import { pathToFileURL } from "url" import os from "os" -import { Process } from "../util/process" +import { Process } from "../util" import z from "zod" import { mergeDeep, pipe, unique } from "remeda" import { Global } from "../global" diff --git a/packages/opencode/src/config/markdown.ts b/packages/opencode/src/config/markdown.ts index 2f1483dca3..8b5392be5e 100644 --- a/packages/opencode/src/config/markdown.ts +++ b/packages/opencode/src/config/markdown.ts @@ -1,7 +1,7 @@ import { NamedError } from "@opencode-ai/shared/util/error" import matter from "gray-matter" import { z } from "zod" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" export namespace ConfigMarkdown { export const FILE_REGEX = /(? diff --git a/packages/opencode/src/effect/run-service.ts b/packages/opencode/src/effect/run-service.ts index 3de82e0d11..9553e7a3aa 100644 --- a/packages/opencode/src/effect/run-service.ts +++ b/packages/opencode/src/effect/run-service.ts @@ -1,7 +1,7 @@ import { Effect, Layer, ManagedRuntime } from "effect" import * as Context from "effect/Context" import { Instance } from "@/project/instance" -import { LocalContext } from "@/util/local-context" +import { LocalContext } from "@/util" import { InstanceRef, WorkspaceRef } from "./instance-ref" import { Observability } from "./observability" import { WorkspaceContext } from "@/control-plane/workspace-context" diff --git a/packages/opencode/src/file/file.ts b/packages/opencode/src/file/file.ts index 35f2a8740a..2269065913 100644 --- a/packages/opencode/src/file/file.ts +++ b/packages/opencode/src/file/file.ts @@ -12,7 +12,7 @@ import path from "path" import z from "zod" import { Global } from "../global" import { Instance } from "../project/instance" -import { Log } from "../util/log" +import { Log } from "../util" import { Protected } from "./protected" import { Ripgrep } from "./ripgrep" diff --git a/packages/opencode/src/file/ripgrep.ts b/packages/opencode/src/file/ripgrep.ts index fee9cf4430..9a78c5b7fb 100644 --- a/packages/opencode/src/file/ripgrep.ts +++ b/packages/opencode/src/file/ripgrep.ts @@ -5,8 +5,8 @@ import z from "zod" import { Cause, Context, Effect, Layer, Queue, Stream } from "effect" import { ripgrep } from "ripgrep" -import { Filesystem } from "@/util/filesystem" -import { Log } from "@/util/log" +import { Filesystem } from "@/util" +import { Log } from "@/util" export namespace Ripgrep { const log = Log.create({ service: "ripgrep" }) diff --git a/packages/opencode/src/file/time.ts b/packages/opencode/src/file/time.ts index 86b6b4116b..327eadbef5 100644 --- a/packages/opencode/src/file/time.ts +++ b/packages/opencode/src/file/time.ts @@ -3,7 +3,7 @@ import { InstanceState } from "@/effect" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Flag } from "@/flag/flag" import type { SessionID } from "@/session/schema" -import { Log } from "../util/log" +import { Log } from "../util" export namespace FileTime { const log = Log.create({ service: "file.time" }) diff --git a/packages/opencode/src/file/watcher.ts b/packages/opencode/src/file/watcher.ts index ab5942547d..f11cf88a65 100644 --- a/packages/opencode/src/file/watcher.ts +++ b/packages/opencode/src/file/watcher.ts @@ -15,7 +15,7 @@ import { lazy } from "@/util/lazy" import { Config } from "../config" import { FileIgnore } from "./ignore" import { Protected } from "./protected" -import { Log } from "../util/log" +import { Log } from "../util" declare const OPENCODE_LIBC: string | undefined diff --git a/packages/opencode/src/format/format.ts b/packages/opencode/src/format/format.ts index 2ce922495e..40855636f9 100644 --- a/packages/opencode/src/format/format.ts +++ b/packages/opencode/src/format/format.ts @@ -6,7 +6,7 @@ import path from "path" import { mergeDeep } from "remeda" import z from "zod" import { Config } from "../config" -import { Log } from "../util/log" +import { Log } from "../util" import * as Formatter from "./formatter" const log = Log.create({ service: "format" }) diff --git a/packages/opencode/src/format/formatter.ts b/packages/opencode/src/format/formatter.ts index 6c17310ff8..36249db7db 100644 --- a/packages/opencode/src/format/formatter.ts +++ b/packages/opencode/src/format/formatter.ts @@ -1,7 +1,7 @@ import { Npm } from "../npm" import { Instance } from "../project/instance" -import { Filesystem } from "../util/filesystem" -import { Process } from "../util/process" +import { Filesystem } from "../util" +import { Process } from "../util" import { which } from "../util/which" import { Flag } from "@/flag/flag" diff --git a/packages/opencode/src/global/global.ts b/packages/opencode/src/global/global.ts index 1bbb5968c9..3633e0855a 100644 --- a/packages/opencode/src/global/global.ts +++ b/packages/opencode/src/global/global.ts @@ -2,7 +2,7 @@ import fs from "fs/promises" import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir" import path from "path" import os from "os" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" import { Flock } from "@opencode-ai/shared/util/flock" const app = "opencode" diff --git a/packages/opencode/src/ide/ide.ts b/packages/opencode/src/ide/ide.ts index cbced9c3d8..65e80d7f28 100644 --- a/packages/opencode/src/ide/ide.ts +++ b/packages/opencode/src/ide/ide.ts @@ -1,8 +1,8 @@ import { BusEvent } from "@/bus/bus-event" import z from "zod" import { NamedError } from "@opencode-ai/shared/util/error" -import { Log } from "../util/log" -import { Process } from "@/util/process" +import { Log } from "../util" +import { Process } from "@/util" const SUPPORTED_IDES = [ { name: "Windsurf" as const, cmd: "windsurf" }, diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 641411461d..ab3ccb712a 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -2,7 +2,7 @@ import yargs from "yargs" import { hideBin } from "yargs/helpers" import { RunCommand } from "./cli/cmd/run" import { GenerateCommand } from "./cli/cmd/generate" -import { Log } from "./util/log" +import { Log } from "./util" import { ConsoleCommand } from "./cli/cmd/account" import { ProvidersCommand } from "./cli/cmd/providers" import { AgentCommand } from "./cli/cmd/agent" @@ -14,7 +14,7 @@ import { Installation } from "./installation" import { NamedError } from "@opencode-ai/shared/util/error" import { FormatError } from "./cli/error" import { ServeCommand } from "./cli/cmd/serve" -import { Filesystem } from "./util/filesystem" +import { Filesystem } from "./util" import { DebugCommand } from "./cli/cmd/debug" import { StatsCommand } from "./cli/cmd/stats" import { McpCommand } from "./cli/cmd/mcp" diff --git a/packages/opencode/src/installation/installation.ts b/packages/opencode/src/installation/installation.ts index 898af9269c..dcaa0cd723 100644 --- a/packages/opencode/src/installation/installation.ts +++ b/packages/opencode/src/installation/installation.ts @@ -7,7 +7,7 @@ import path from "path" import z from "zod" import { BusEvent } from "@/bus/bus-event" import { Flag } from "../flag/flag" -import { Log } from "../util/log" +import { Log } from "../util" import { CHANNEL as channel, VERSION as version } from "./meta" import semver from "semver" diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts index fe5a9ab182..50051b3901 100644 --- a/packages/opencode/src/lsp/client.ts +++ b/packages/opencode/src/lsp/client.ts @@ -4,15 +4,15 @@ import path from "path" import { pathToFileURL, fileURLToPath } from "url" import { createMessageConnection, StreamMessageReader, StreamMessageWriter } from "vscode-jsonrpc/node" import type { Diagnostic as VSCodeDiagnostic } from "vscode-languageserver-types" -import { Log } from "../util/log" -import { Process } from "../util/process" +import { Log } from "../util" +import { Process } from "../util" import { LANGUAGE_EXTENSIONS } from "./language" import z from "zod" import type { LSPServer } from "./server" import { NamedError } from "@opencode-ai/shared/util/error" import { withTimeout } from "../util/timeout" import { Instance } from "../project/instance" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" const DIAGNOSTICS_DEBOUNCE_MS = 150 diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts index f567868f68..a55ac18402 100644 --- a/packages/opencode/src/lsp/index.ts +++ b/packages/opencode/src/lsp/index.ts @@ -1,6 +1,6 @@ import { BusEvent } from "@/bus/bus-event" import { Bus } from "@/bus" -import { Log } from "../util/log" +import { Log } from "../util" import { LSPClient } from "./client" import path from "path" import { pathToFileURL, fileURLToPath } from "url" @@ -9,7 +9,7 @@ import z from "zod" import { Config } from "../config" import { Instance } from "../project/instance" import { Flag } from "@/flag/flag" -import { Process } from "../util/process" +import { Process } from "../util" import { spawn as lspspawn } from "./launch" import { Effect, Layer, Context } from "effect" import { InstanceState } from "@/effect" diff --git a/packages/opencode/src/lsp/launch.ts b/packages/opencode/src/lsp/launch.ts index 51a7c209b4..fb84666b01 100644 --- a/packages/opencode/src/lsp/launch.ts +++ b/packages/opencode/src/lsp/launch.ts @@ -1,5 +1,5 @@ import type { ChildProcessWithoutNullStreams } from "child_process" -import { Process } from "../util/process" +import { Process } from "../util" type Child = Process.Child & ChildProcessWithoutNullStreams diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts index 769880ef03..8110e86082 100644 --- a/packages/opencode/src/lsp/server.ts +++ b/packages/opencode/src/lsp/server.ts @@ -2,14 +2,14 @@ import type { ChildProcessWithoutNullStreams } from "child_process" import path from "path" import os from "os" import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" import { text } from "node:stream/consumers" import fs from "fs/promises" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" import { Instance } from "../project/instance" import { Flag } from "../flag/flag" import { Archive } from "../util" -import { Process } from "../util/process" +import { Process } from "../util" import { which } from "../util/which" import { Module } from "@opencode-ai/shared/util/module" import { spawn } from "./launch" diff --git a/packages/opencode/src/mcp/mcp.ts b/packages/opencode/src/mcp/mcp.ts index f5179b224d..8a57bcff73 100644 --- a/packages/opencode/src/mcp/mcp.ts +++ b/packages/opencode/src/mcp/mcp.ts @@ -10,7 +10,7 @@ import { ToolListChangedNotificationSchema, } from "@modelcontextprotocol/sdk/types.js" import { Config } from "../config" -import { Log } from "../util/log" +import { Log } from "../util" import { NamedError } from "@opencode-ai/shared/util/error" import z from "zod/v4" import { Instance } from "../project/instance" diff --git a/packages/opencode/src/mcp/oauth-callback.ts b/packages/opencode/src/mcp/oauth-callback.ts index 6babccd779..3e6169517f 100644 --- a/packages/opencode/src/mcp/oauth-callback.ts +++ b/packages/opencode/src/mcp/oauth-callback.ts @@ -1,6 +1,6 @@ import { createConnection } from "net" import { createServer } from "http" -import { Log } from "../util/log" +import { Log } from "../util" import { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_PATH, parseRedirectUri } from "./oauth-provider" const log = Log.create({ service: "mcp.oauth-callback" }) diff --git a/packages/opencode/src/mcp/oauth-provider.ts b/packages/opencode/src/mcp/oauth-provider.ts index 4fdc192df7..fe09e14a58 100644 --- a/packages/opencode/src/mcp/oauth-provider.ts +++ b/packages/opencode/src/mcp/oauth-provider.ts @@ -7,7 +7,7 @@ import type { } from "@modelcontextprotocol/sdk/shared/auth.js" import { Effect } from "effect" import { McpAuth } from "./auth" -import { Log } from "../util/log" +import { Log } from "../util" const log = Log.create({ service: "mcp.oauth" }) diff --git a/packages/opencode/src/node.ts b/packages/opencode/src/node.ts index 6f020576d9..a30783fb21 100644 --- a/packages/opencode/src/node.ts +++ b/packages/opencode/src/node.ts @@ -1,6 +1,6 @@ export { Config } from "./config" export { Server } from "./server/server" export { bootstrap } from "./cli/bootstrap" -export { Log } from "./util/log" +export { Log } from "./util" export { Database } from "./storage/db" export { JsonMigration } from "./storage/json-migration" diff --git a/packages/opencode/src/npm/npm.ts b/packages/opencode/src/npm/npm.ts index f905130719..7f17446057 100644 --- a/packages/opencode/src/npm/npm.ts +++ b/packages/opencode/src/npm/npm.ts @@ -2,10 +2,10 @@ import semver from "semver" import z from "zod" import { NamedError } from "@opencode-ai/shared/util/error" import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" import path from "path" import { readdir, rm } from "fs/promises" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { Flock } from "@opencode-ai/shared/util/flock" import { Arborist } from "@npmcli/arborist" diff --git a/packages/opencode/src/patch/patch.ts b/packages/opencode/src/patch/patch.ts index 749efd911c..1dc99b4da9 100644 --- a/packages/opencode/src/patch/patch.ts +++ b/packages/opencode/src/patch/patch.ts @@ -2,7 +2,7 @@ import z from "zod" import * as path from "path" import * as fs from "fs/promises" import { readFileSync } from "fs" -import { Log } from "../util/log" +import { Log } from "../util" const log = Log.create({ service: "patch" }) diff --git a/packages/opencode/src/permission/evaluate.ts b/packages/opencode/src/permission/evaluate.ts index 2b0604f4ba..bcc4e58118 100644 --- a/packages/opencode/src/permission/evaluate.ts +++ b/packages/opencode/src/permission/evaluate.ts @@ -1,4 +1,4 @@ -import { Wildcard } from "@/util/wildcard" +import { Wildcard } from "@/util" type Rule = { permission: string diff --git a/packages/opencode/src/permission/permission.ts b/packages/opencode/src/permission/permission.ts index e2dead8fe2..a8463510c4 100644 --- a/packages/opencode/src/permission/permission.ts +++ b/packages/opencode/src/permission/permission.ts @@ -7,9 +7,9 @@ import { MessageID, SessionID } from "@/session/schema" import { PermissionTable } from "@/session/session.sql" import { Database, eq } from "@/storage/db" import { zod } from "@/util/effect-zod" -import { Log } from "@/util/log" +import { Log } from "@/util" import { withStatics } from "@/util/schema" -import { Wildcard } from "@/util/wildcard" +import { Wildcard } from "@/util" import { Deferred, Effect, Layer, Schema, Context } from "effect" import os from "os" import { evaluate as evalRule } from "./evaluate" diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts index ea356d55d2..e0f1afa63f 100644 --- a/packages/opencode/src/plugin/codex.ts +++ b/packages/opencode/src/plugin/codex.ts @@ -1,5 +1,5 @@ import type { Hooks, PluginInput } from "@opencode-ai/plugin" -import { Log } from "../util/log" +import { Log } from "../util" import { Installation } from "../installation" import { OAUTH_DUMMY_KEY } from "../auth" import os from "os" diff --git a/packages/opencode/src/plugin/github-copilot/copilot.ts b/packages/opencode/src/plugin/github-copilot/copilot.ts index e12d182e4f..eeea219241 100644 --- a/packages/opencode/src/plugin/github-copilot/copilot.ts +++ b/packages/opencode/src/plugin/github-copilot/copilot.ts @@ -2,7 +2,7 @@ import type { Hooks, PluginInput } from "@opencode-ai/plugin" import type { Model } from "@opencode-ai/sdk/v2" import { Installation } from "@/installation" import { iife } from "@/util/iife" -import { Log } from "../../util/log" +import { Log } from "../../util" import { setTimeout as sleep } from "node:timers/promises" import { CopilotModels } from "./models" import { MessageV2 } from "@/session/message-v2" diff --git a/packages/opencode/src/plugin/install.ts b/packages/opencode/src/plugin/install.ts index 8dd8212965..0a6256d6f2 100644 --- a/packages/opencode/src/plugin/install.ts +++ b/packages/opencode/src/plugin/install.ts @@ -9,7 +9,7 @@ import { import { ConfigPaths } from "@/config/paths" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { Flock } from "@opencode-ai/shared/util/flock" import { isRecord } from "@/util/record" diff --git a/packages/opencode/src/plugin/meta.ts b/packages/opencode/src/plugin/meta.ts index 3f02f543ef..89955d1dfb 100644 --- a/packages/opencode/src/plugin/meta.ts +++ b/packages/opencode/src/plugin/meta.ts @@ -3,7 +3,7 @@ import { fileURLToPath } from "url" import { Flag } from "@/flag/flag" import { Global } from "@/global" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { Flock } from "@opencode-ai/shared/util/flock" import { parsePluginSpecifier, pluginSource } from "./shared" diff --git a/packages/opencode/src/plugin/plugin.ts b/packages/opencode/src/plugin/plugin.ts index 23c807ebe7..ec1cf1e313 100644 --- a/packages/opencode/src/plugin/plugin.ts +++ b/packages/opencode/src/plugin/plugin.ts @@ -7,7 +7,7 @@ import type { } from "@opencode-ai/plugin" import { Config } from "../config" import { Bus } from "../bus" -import { Log } from "../util/log" +import { Log } from "../util" import { createOpencodeClient } from "@opencode-ai/sdk" import { Flag } from "../flag/flag" import { CodexAuthPlugin } from "./codex" diff --git a/packages/opencode/src/plugin/shared.ts b/packages/opencode/src/plugin/shared.ts index 54cc32af5b..11f36c41ae 100644 --- a/packages/opencode/src/plugin/shared.ts +++ b/packages/opencode/src/plugin/shared.ts @@ -3,7 +3,7 @@ import { fileURLToPath, pathToFileURL } from "url" import npa from "npm-package-arg" import semver from "semver" import { Npm } from "../npm" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { isRecord } from "@/util/record" // Old npm package names for plugins that are now built-in diff --git a/packages/opencode/src/project/bootstrap.ts b/packages/opencode/src/project/bootstrap.ts index a1f2a8cb02..f00d8ffd9b 100644 --- a/packages/opencode/src/project/bootstrap.ts +++ b/packages/opencode/src/project/bootstrap.ts @@ -8,7 +8,7 @@ import { Vcs } from "./vcs" import { Bus } from "../bus" import { Command } from "../command" import { Instance } from "./instance" -import { Log } from "@/util/log" +import { Log } from "@/util" import { FileWatcher } from "@/file/watcher" import { ShareNext } from "@/share/share-next" import * as Effect from "effect/Effect" diff --git a/packages/opencode/src/project/instance.ts b/packages/opencode/src/project/instance.ts index 2a20ecac97..a8a5218751 100644 --- a/packages/opencode/src/project/instance.ts +++ b/packages/opencode/src/project/instance.ts @@ -3,8 +3,8 @@ import { disposeInstance } from "@/effect/instance-registry" import { makeRuntime } from "@/effect/run-service" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { iife } from "@/util/iife" -import { Log } from "@/util/log" -import { LocalContext } from "../util/local-context" +import { Log } from "@/util" +import { LocalContext } from "../util" import { Project } from "./project" import { WorkspaceContext } from "@/control-plane/workspace-context" diff --git a/packages/opencode/src/project/project.ts b/packages/opencode/src/project/project.ts index d20bf42494..9c4ed58ce8 100644 --- a/packages/opencode/src/project/project.ts +++ b/packages/opencode/src/project/project.ts @@ -2,7 +2,7 @@ import z from "zod" import { and, Database, eq } from "../storage/db" import { ProjectTable } from "./project.sql" import { SessionTable } from "../session/session.sql" -import { Log } from "../util/log" +import { Log } from "../util" import { Flag } from "@/flag/flag" import { BusEvent } from "@/bus/bus-event" import { GlobalBus } from "@/bus/global" diff --git a/packages/opencode/src/project/vcs.ts b/packages/opencode/src/project/vcs.ts index 187c616602..cb0b46adcb 100644 --- a/packages/opencode/src/project/vcs.ts +++ b/packages/opencode/src/project/vcs.ts @@ -7,7 +7,7 @@ import { InstanceState } from "@/effect" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { FileWatcher } from "@/file/watcher" import { Git } from "@/git" -import { Log } from "@/util/log" +import { Log } from "@/util" import { Instance } from "./instance" import z from "zod" diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts index 55f137aa0b..59d629a379 100644 --- a/packages/opencode/src/provider/models.ts +++ b/packages/opencode/src/provider/models.ts @@ -1,11 +1,11 @@ import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" import path from "path" import z from "zod" import { Installation } from "../installation" import { Flag } from "../flag/flag" import { lazy } from "@/util/lazy" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" import { Flock } from "@opencode-ai/shared/util/flock" import { Hash } from "@opencode-ai/shared/util/hash" diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index ef6cbd61e7..432dbab34a 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -4,7 +4,7 @@ import fuzzysort from "fuzzysort" import { Config } from "../config" import { mapValues, mergeDeep, omit, pickBy, sortBy } from "remeda" import { NoSuchModelError, type Provider as SDK } from "ai" -import { Log } from "../util/log" +import { Log } from "../util" import { Npm } from "../npm" import { Hash } from "@opencode-ai/shared/util/hash" import { Plugin } from "../plugin" diff --git a/packages/opencode/src/pty/service.ts b/packages/opencode/src/pty/service.ts index ff52095b4f..a4ebd0696b 100644 --- a/packages/opencode/src/pty/service.ts +++ b/packages/opencode/src/pty/service.ts @@ -4,7 +4,7 @@ import { InstanceState } from "@/effect" import { Instance } from "@/project/instance" import type { Proc } from "#pty" import z from "zod" -import { Log } from "../util/log" +import { Log } from "../util" import { lazy } from "@opencode-ai/shared/util/lazy" import { Shell } from "@/shell/shell" import { Plugin } from "@/plugin" diff --git a/packages/opencode/src/question/index.ts b/packages/opencode/src/question/index.ts index 8d023c18bf..627d04564d 100644 --- a/packages/opencode/src/question/index.ts +++ b/packages/opencode/src/question/index.ts @@ -4,7 +4,7 @@ import { BusEvent } from "@/bus/bus-event" import { InstanceState } from "@/effect" import { SessionID, MessageID } from "@/session/schema" import { zod } from "@/util/effect-zod" -import { Log } from "@/util/log" +import { Log } from "@/util" import { withStatics } from "@/util/schema" import { QuestionID } from "./schema" diff --git a/packages/opencode/src/server/control/index.ts b/packages/opencode/src/server/control/index.ts index cf8949c954..737f958d6b 100644 --- a/packages/opencode/src/server/control/index.ts +++ b/packages/opencode/src/server/control/index.ts @@ -1,6 +1,6 @@ import { Auth } from "@/auth" import { AppRuntime } from "@/effect/app-runtime" -import { Log } from "@/util/log" +import { Log } from "@/util" import { Effect } from "effect" import { ProviderID } from "@/provider/schema" import { Hono } from "hono" diff --git a/packages/opencode/src/server/fence.ts b/packages/opencode/src/server/fence.ts index b6dbde0081..87771745c8 100644 --- a/packages/opencode/src/server/fence.ts +++ b/packages/opencode/src/server/fence.ts @@ -3,7 +3,7 @@ import { Database, inArray } from "@/storage/db" import { EventSequenceTable } from "@/sync/event.sql" import { Workspace } from "@/control-plane/workspace" import type { WorkspaceID } from "@/control-plane/schema" -import { Log } from "@/util/log" +import { Log } from "@/util" const HEADER = "x-opencode-sync" type State = Record diff --git a/packages/opencode/src/server/instance/event.ts b/packages/opencode/src/server/instance/event.ts index f13ed035e0..103d3d7cfb 100644 --- a/packages/opencode/src/server/instance/event.ts +++ b/packages/opencode/src/server/instance/event.ts @@ -2,7 +2,7 @@ import z from "zod" import { Hono } from "hono" import { describeRoute, resolver } from "hono-openapi" import { streamSSE } from "hono/streaming" -import { Log } from "@/util/log" +import { Log } from "@/util" import { BusEvent } from "@/bus/bus-event" import { Bus } from "@/bus" import { AsyncQueue } from "../../util/queue" diff --git a/packages/opencode/src/server/instance/global.ts b/packages/opencode/src/server/instance/global.ts index b69f35a649..ac73bb64d8 100644 --- a/packages/opencode/src/server/instance/global.ts +++ b/packages/opencode/src/server/instance/global.ts @@ -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 { Log } from "../../util/log" +import { Log } from "../../util" import { lazy } from "../../util/lazy" import { Config } from "../../config" import { errors } from "../error" diff --git a/packages/opencode/src/server/instance/httpapi/server.ts b/packages/opencode/src/server/instance/httpapi/server.ts index 9ecefe2915..62ffb5940d 100644 --- a/packages/opencode/src/server/instance/httpapi/server.ts +++ b/packages/opencode/src/server/instance/httpapi/server.ts @@ -9,7 +9,7 @@ import { Flag } from "@/flag/flag" import { InstanceBootstrap } from "@/project/bootstrap" import { Instance } from "@/project/instance" import { lazy } from "@/util/lazy" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { PermissionApi, permissionHandlers } from "./permission" import { ProviderApi, providerHandlers } from "./provider" import { QuestionApi, questionHandlers } from "./question" diff --git a/packages/opencode/src/server/instance/middleware.ts b/packages/opencode/src/server/instance/middleware.ts index 5fd1fc25e8..7b66072c23 100644 --- a/packages/opencode/src/server/instance/middleware.ts +++ b/packages/opencode/src/server/instance/middleware.ts @@ -11,7 +11,7 @@ import { Session } from "@/session" import { SessionID } from "@/session/schema" import { WorkspaceContext } from "@/control-plane/workspace-context" import { AppRuntime } from "@/effect/app-runtime" -import { Log } from "@/util/log" +import { Log } from "@/util" import { AppFileSystem } from "@opencode-ai/shared/filesystem" type Rule = { method?: string; path: string; exact?: boolean; action: "local" | "forward" } diff --git a/packages/opencode/src/server/instance/session.ts b/packages/opencode/src/server/instance/session.ts index c606af8544..1b2755fb8a 100644 --- a/packages/opencode/src/server/instance/session.ts +++ b/packages/opencode/src/server/instance/session.ts @@ -18,7 +18,7 @@ import { AppRuntime } from "../../effect/app-runtime" import { Agent } from "../../agent/agent" import { Snapshot } from "@/snapshot" import { Command } from "../../command" -import { Log } from "../../util/log" +import { Log } from "../../util" import { Permission } from "@/permission" import { PermissionID } from "@/permission/schema" import { ModelID, ProviderID } from "@/provider/schema" diff --git a/packages/opencode/src/server/instance/sync.ts b/packages/opencode/src/server/instance/sync.ts index c22969130a..2513e519ee 100644 --- a/packages/opencode/src/server/instance/sync.ts +++ b/packages/opencode/src/server/instance/sync.ts @@ -5,7 +5,7 @@ import { SyncEvent } from "@/sync" import { Database, asc, and, not, or, lte, eq } from "@/storage/db" import { EventTable } from "@/sync/event.sql" import { lazy } from "@/util/lazy" -import { Log } from "@/util/log" +import { Log } from "@/util" import { errors } from "../error" const ReplayEvent = z.object({ diff --git a/packages/opencode/src/server/instance/workspace.ts b/packages/opencode/src/server/instance/workspace.ts index a4ff4eda8d..59369ef8e7 100644 --- a/packages/opencode/src/server/instance/workspace.ts +++ b/packages/opencode/src/server/instance/workspace.ts @@ -6,7 +6,7 @@ import { Workspace } from "../../control-plane/workspace" import { Instance } from "../../project/instance" import { errors } from "../error" import { lazy } from "../../util/lazy" -import { Log } from "@/util/log" +import { Log } from "@/util" import { errorData } from "@/util/error" const log = Log.create({ service: "server.workspace" }) diff --git a/packages/opencode/src/server/mdns.ts b/packages/opencode/src/server/mdns.ts index 778afa26ac..2011771a20 100644 --- a/packages/opencode/src/server/mdns.ts +++ b/packages/opencode/src/server/mdns.ts @@ -1,4 +1,4 @@ -import { Log } from "@/util/log" +import { Log } from "@/util" import { Bonjour } from "bonjour-service" const log = Log.create({ service: "mdns" }) diff --git a/packages/opencode/src/server/middleware.ts b/packages/opencode/src/server/middleware.ts index 880c432c7c..e0958196a5 100644 --- a/packages/opencode/src/server/middleware.ts +++ b/packages/opencode/src/server/middleware.ts @@ -5,7 +5,7 @@ import { Session } from "../session" import type { ContentfulStatusCode } from "hono/utils/http-status" import type { ErrorHandler, MiddlewareHandler } from "hono" import { HTTPException } from "hono/http-exception" -import { Log } from "../util/log" +import { Log } from "../util" import { Flag } from "@/flag/flag" import { basicAuth } from "hono/basic-auth" import { cors } from "hono/cors" diff --git a/packages/opencode/src/server/proxy.ts b/packages/opencode/src/server/proxy.ts index 5effa5d05f..07edcc2bb2 100644 --- a/packages/opencode/src/server/proxy.ts +++ b/packages/opencode/src/server/proxy.ts @@ -1,6 +1,6 @@ import { Hono } from "hono" import type { UpgradeWebSocket } from "hono/ws" -import { Log } from "@/util/log" +import { Log } from "@/util" import * as Fence from "./fence" import type { WorkspaceID } from "@/control-plane/schema" import { Workspace } from "@/control-plane/workspace" diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index c6c37ee438..fc3b399f79 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -7,7 +7,7 @@ import { AuthMiddleware, CompressionMiddleware, CorsMiddleware, ErrorMiddleware, import { FenceMiddleware } from "./fence" import { InstanceRoutes } from "./instance" import { initProjectors } from "./projectors" -import { Log } from "@/util/log" +import { Log } from "@/util" import { Flag } from "@/flag/flag" import { ControlPlaneRoutes } from "./control" import { UIRoutes } from "./ui" diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index 3d39a60555..72b9963215 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -5,8 +5,8 @@ import { SessionID, MessageID, PartID } from "./schema" import { Provider } from "../provider" import { MessageV2 } from "./message-v2" import z from "zod" -import { Token } from "../util/token" -import { Log } from "../util/log" +import { Token } from "../util" +import { Log } from "../util" import { SessionProcessor } from "./processor" import { Agent } from "@/agent/agent" import { Plugin } from "@/plugin" diff --git a/packages/opencode/src/session/instruction.ts b/packages/opencode/src/session/instruction.ts index 076c81ec75..cd2050adf5 100644 --- a/packages/opencode/src/session/instruction.ts +++ b/packages/opencode/src/session/instruction.ts @@ -9,7 +9,7 @@ import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { withTransientReadRetry } from "@/util/effect-http-client" import { Global } from "../global" import { Instance } from "../project/instance" -import { Log } from "../util/log" +import { Log } from "../util" import type { MessageV2 } from "./message-v2" import type { MessageID } from "./schema" diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index bde36d2638..8f93bd5e15 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -1,5 +1,5 @@ import { Provider } from "@/provider" -import { Log } from "@/util/log" +import { Log } from "@/util" import { Context, Effect, Layer, Record } from "effect" import * as Stream from "effect/Stream" import { streamText, wrapLanguageModel, type ModelMessage, type Tool, tool, jsonSchema } from "ai" @@ -16,7 +16,7 @@ import { Flag } from "@/flag/flag" import { Permission } from "@/permission" import { PermissionID } from "@/permission/schema" import { Bus } from "@/bus" -import { Wildcard } from "@/util/wildcard" +import { Wildcard } from "@/util" import { SessionID } from "@/session/schema" import { Auth } from "@/auth" import { Installation } from "@/installation" diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 1ae70c3c6e..72b27403bd 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -18,7 +18,7 @@ import { SessionSummary } from "./summary" import type { Provider } from "@/provider" import { Question } from "@/question" import { errorMessage } from "@/util/error" -import { Log } from "@/util/log" +import { Log } from "@/util" import { isRecord } from "@/util/record" export namespace SessionProcessor { diff --git a/packages/opencode/src/session/projectors.ts b/packages/opencode/src/session/projectors.ts index bc083105c2..1e092b07e0 100644 --- a/packages/opencode/src/session/projectors.ts +++ b/packages/opencode/src/session/projectors.ts @@ -3,7 +3,7 @@ import { SyncEvent } from "@/sync" import { Session } from "." import { MessageV2 } from "./message-v2" import { SessionTable, MessageTable, PartTable } from "./session.sql" -import { Log } from "../util/log" +import { Log } from "../util" const log = Log.create({ service: "session.projector" }) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index f04ea8cdeb..a072633aa7 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -3,7 +3,7 @@ import os from "os" import z from "zod" import { SessionID, MessageID, PartID } from "./schema" import { MessageV2 } from "./message-v2" -import { Log } from "../util/log" +import { Log } from "../util" import { SessionRevert } from "./revert" import { Session } from "." import { Agent } from "../agent/agent" @@ -42,7 +42,7 @@ import { Shell } from "@/shell/shell" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Truncate } from "@/tool/truncate" import { decodeDataUrl } from "@/util/data-url" -import { Process } from "@/util/process" +import { Process } from "@/util" import { Cause, Effect, Exit, Layer, Option, Scope, Context } from "effect" import { EffectLogger } from "@/effect/logger" import { InstanceState } from "@/effect" diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index 7a7f847ad1..383fe08e87 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -4,7 +4,7 @@ import { Bus } from "../bus" import { Snapshot } from "../snapshot" import { Storage } from "@/storage/storage" import { SyncEvent } from "../sync" -import { Log } from "../util/log" +import { Log } from "../util" import { Session } from "." import { MessageV2 } from "./message-v2" import { SessionID, MessageID, PartID } from "./schema" diff --git a/packages/opencode/src/session/session.ts b/packages/opencode/src/session/session.ts index 0b82d8b99f..a4bf446a1a 100644 --- a/packages/opencode/src/session/session.ts +++ b/packages/opencode/src/session/session.ts @@ -14,7 +14,7 @@ import type { SQL } from "../storage/db" import { PartTable, SessionTable } from "./session.sql" import { ProjectTable } from "../project/project.sql" import { Storage } from "@/storage/storage" -import { Log } from "../util/log" +import { Log } from "../util" import { updateSchema } from "../util/update-schema" import { MessageV2 } from "./message-v2" import { Instance } from "../project/instance" diff --git a/packages/opencode/src/share/share-next.ts b/packages/opencode/src/share/share-next.ts index 9b345ac8ef..bcb1fcc962 100644 --- a/packages/opencode/src/share/share-next.ts +++ b/packages/opencode/src/share/share-next.ts @@ -11,7 +11,7 @@ import { MessageV2 } from "@/session/message-v2" import type { SessionID } from "@/session/schema" import { Database, eq } from "@/storage/db" import { Config } from "@/config" -import { Log } from "@/util/log" +import { Log } from "@/util" import { SessionShareTable } from "./share.sql" export namespace ShareNext { diff --git a/packages/opencode/src/shell/shell.ts b/packages/opencode/src/shell/shell.ts index 0044dda89c..056a794dc8 100644 --- a/packages/opencode/src/shell/shell.ts +++ b/packages/opencode/src/shell/shell.ts @@ -1,6 +1,6 @@ import { Flag } from "@/flag/flag" import { lazy } from "@/util/lazy" -import { Filesystem } from "@/util/filesystem" +import { Filesystem } from "@/util" import { which } from "@/util/which" import path from "path" import { spawn, type ChildProcess } from "child_process" diff --git a/packages/opencode/src/skill/discovery.ts b/packages/opencode/src/skill/discovery.ts index 0323f250f6..eff64ed2bb 100644 --- a/packages/opencode/src/skill/discovery.ts +++ b/packages/opencode/src/skill/discovery.ts @@ -4,7 +4,7 @@ import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } fr import { withTransientReadRetry } from "@/util/effect-http-client" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" export namespace Discovery { const skillConcurrency = 4 diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts index 3122115cd3..ef9f661cb5 100644 --- a/packages/opencode/src/skill/skill.ts +++ b/packages/opencode/src/skill/skill.ts @@ -14,7 +14,7 @@ import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Config } from "../config" import { ConfigMarkdown } from "../config/markdown" import { Glob } from "@opencode-ai/shared/util/glob" -import { Log } from "../util/log" +import { Log } from "../util" import { Discovery } from "./discovery" const log = Log.create({ service: "skill" }) diff --git a/packages/opencode/src/snapshot/snapshot.ts b/packages/opencode/src/snapshot/snapshot.ts index 7aa3a4debf..8d8118131e 100644 --- a/packages/opencode/src/snapshot/snapshot.ts +++ b/packages/opencode/src/snapshot/snapshot.ts @@ -9,7 +9,7 @@ import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { Hash } from "@opencode-ai/shared/util/hash" import { Config } from "../config" import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" export const Patch = z.object({ hash: z.string(), diff --git a/packages/opencode/src/storage/db.ts b/packages/opencode/src/storage/db.ts index 247cb347cb..ee53182f36 100644 --- a/packages/opencode/src/storage/db.ts +++ b/packages/opencode/src/storage/db.ts @@ -2,10 +2,10 @@ import { type SQLiteBunDatabase } from "drizzle-orm/bun-sqlite" import { migrate } from "drizzle-orm/bun-sqlite/migrator" import { type SQLiteTransaction } from "drizzle-orm/sqlite-core" export * from "drizzle-orm" -import { LocalContext } from "../util/local-context" +import { LocalContext } from "../util" import { lazy } from "../util/lazy" import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" import { NamedError } from "@opencode-ai/shared/util/error" import z from "zod" import path from "path" diff --git a/packages/opencode/src/storage/json-migration.ts b/packages/opencode/src/storage/json-migration.ts index c13a005ca6..4bf75f5a1c 100644 --- a/packages/opencode/src/storage/json-migration.ts +++ b/packages/opencode/src/storage/json-migration.ts @@ -1,13 +1,13 @@ import type { SQLiteBunDatabase } from "drizzle-orm/bun-sqlite" import type { NodeSQLiteDatabase } from "drizzle-orm/node-sqlite" import { Global } from "../global" -import { Log } from "../util/log" +import { Log } from "../util" import { ProjectTable } from "../project/project.sql" import { SessionTable, MessageTable, PartTable, TodoTable, PermissionTable } from "../session/session.sql" import { SessionShareTable } from "../share/share.sql" import path from "path" import { existsSync } from "fs" -import { Filesystem } from "../util/filesystem" +import { Filesystem } from "../util" import { Glob } from "@opencode-ai/shared/util/glob" export namespace JsonMigration { diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts index 359c750ced..f4793c6204 100644 --- a/packages/opencode/src/storage/storage.ts +++ b/packages/opencode/src/storage/storage.ts @@ -1,4 +1,4 @@ -import { Log } from "../util/log" +import { Log } from "../util" import path from "path" import { Global } from "../global" import { NamedError } from "@opencode-ai/shared/util/error" diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index 0ab1301305..1edd754143 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -4,7 +4,7 @@ import { createWriteStream } from "node:fs" import { Tool } from "./tool" import path from "path" import DESCRIPTION from "./bash.txt" -import { Log } from "../util/log" +import { Log } from "../util" import { Instance } from "../project/instance" import { lazy } from "@/util/lazy" import { Language, type Node } from "web-tree-sitter" diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index 6171e4366e..80115884d9 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -22,7 +22,7 @@ import { ProviderID, type ModelID } from "../provider/schema" import { WebSearchTool } from "./websearch" import { CodeSearchTool } from "./codesearch" import { Flag } from "@/flag/flag" -import { Log } from "@/util/log" +import { Log } from "@/util" import { LspTool } from "./lsp" import { Truncate } from "./truncate" import { ApplyPatchTool } from "./apply_patch" diff --git a/packages/opencode/src/tool/truncate.ts b/packages/opencode/src/tool/truncate.ts index d607e22f28..d2aa944a85 100644 --- a/packages/opencode/src/tool/truncate.ts +++ b/packages/opencode/src/tool/truncate.ts @@ -5,7 +5,7 @@ import type { Agent } from "../agent/agent" import { AppFileSystem } from "@opencode-ai/shared/filesystem" import { evaluate } from "@/permission/evaluate" import { Identifier } from "../id/id" -import { Log } from "../util/log" +import { Log } from "../util" import { ToolID } from "./schema" import { TRUNCATION_DIR } from "./truncation-dir" diff --git a/packages/opencode/src/util/archive.ts b/packages/opencode/src/util/archive.ts index cf25636841..21d014c6a8 100644 --- a/packages/opencode/src/util/archive.ts +++ b/packages/opencode/src/util/archive.ts @@ -1,5 +1,5 @@ import path from "path" -import { Process } from "./process" +import { Process } from "." export async function extractZip(zipPath: string, destDir: string) { if (process.platform === "win32") { diff --git a/packages/opencode/src/util/color.ts b/packages/opencode/src/util/color.ts index b96deaec47..43408295fa 100644 --- a/packages/opencode/src/util/color.ts +++ b/packages/opencode/src/util/color.ts @@ -1,19 +1,17 @@ -export namespace Color { - export function isValidHex(hex?: string): hex is string { - if (!hex) return false - return /^#[0-9a-fA-F]{6}$/.test(hex) - } - - export function hexToRgb(hex: string): { r: number; g: number; b: number } { - const r = parseInt(hex.slice(1, 3), 16) - const g = parseInt(hex.slice(3, 5), 16) - const b = parseInt(hex.slice(5, 7), 16) - return { r, g, b } - } - - export function hexToAnsiBold(hex?: string): string | undefined { - if (!isValidHex(hex)) return undefined - const { r, g, b } = hexToRgb(hex) - return `\x1b[38;2;${r};${g};${b}m\x1b[1m` - } +export function isValidHex(hex?: string): hex is string { + if (!hex) return false + return /^#[0-9a-fA-F]{6}$/.test(hex) +} + +export function hexToRgb(hex: string): { r: number; g: number; b: number } { + const r = parseInt(hex.slice(1, 3), 16) + const g = parseInt(hex.slice(3, 5), 16) + const b = parseInt(hex.slice(5, 7), 16) + return { r, g, b } +} + +export function hexToAnsiBold(hex?: string): string | undefined { + if (!isValidHex(hex)) return undefined + const { r, g, b } = hexToRgb(hex) + return `\x1b[38;2;${r};${g};${b}m\x1b[1m` } diff --git a/packages/opencode/src/util/filesystem.ts b/packages/opencode/src/util/filesystem.ts index b4aef05456..c3f59d3297 100644 --- a/packages/opencode/src/util/filesystem.ts +++ b/packages/opencode/src/util/filesystem.ts @@ -7,239 +7,237 @@ import { Readable } from "stream" import { pipeline } from "stream/promises" import { Glob } from "@opencode-ai/shared/util/glob" -export namespace Filesystem { - // Fast sync version for metadata checks - export async function exists(p: string): Promise { - return existsSync(p) - } +// Fast sync version for metadata checks +export async function exists(p: string): Promise { + return existsSync(p) +} - export async function isDir(p: string): Promise { - try { - return statSync(p).isDirectory() - } catch { - return false +export async function isDir(p: string): Promise { + try { + return statSync(p).isDirectory() + } catch { + return false + } +} + +export function stat(p: string): ReturnType | undefined { + return statSync(p, { throwIfNoEntry: false }) ?? undefined +} + +export async function statAsync(p: string): Promise | undefined> { + return statFile(p).catch((e) => { + if (isEnoent(e)) return undefined + throw e + }) +} + +export async function size(p: string): Promise { + const s = stat(p)?.size ?? 0 + return typeof s === "bigint" ? Number(s) : s +} + +export async function readText(p: string): Promise { + return readFile(p, "utf-8") +} + +export async function readJson(p: string): Promise { + return JSON.parse(await readFile(p, "utf-8")) +} + +export async function readBytes(p: string): Promise { + return readFile(p) +} + +export async function readArrayBuffer(p: string): Promise { + const buf = await readFile(p) + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer +} + +function isEnoent(e: unknown): e is { code: "ENOENT" } { + return typeof e === "object" && e !== null && "code" in e && (e as { code: string }).code === "ENOENT" +} + +export async function write(p: string, content: string | Buffer | Uint8Array, mode?: number): Promise { + try { + if (mode) { + await writeFile(p, content, { mode }) + } else { + await writeFile(p, content) } - } - - export function stat(p: string): ReturnType | undefined { - return statSync(p, { throwIfNoEntry: false }) ?? undefined - } - - export async function statAsync(p: string): Promise | undefined> { - return statFile(p).catch((e) => { - if (isEnoent(e)) return undefined - throw e - }) - } - - export async function size(p: string): Promise { - const s = stat(p)?.size ?? 0 - return typeof s === "bigint" ? Number(s) : s - } - - export async function readText(p: string): Promise { - return readFile(p, "utf-8") - } - - export async function readJson(p: string): Promise { - return JSON.parse(await readFile(p, "utf-8")) - } - - export async function readBytes(p: string): Promise { - return readFile(p) - } - - export async function readArrayBuffer(p: string): Promise { - const buf = await readFile(p) - return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer - } - - function isEnoent(e: unknown): e is { code: "ENOENT" } { - return typeof e === "object" && e !== null && "code" in e && (e as { code: string }).code === "ENOENT" - } - - export async function write(p: string, content: string | Buffer | Uint8Array, mode?: number): Promise { - try { + } catch (e) { + if (isEnoent(e)) { + await mkdir(dirname(p), { recursive: true }) if (mode) { await writeFile(p, content, { mode }) } else { await writeFile(p, content) } - } catch (e) { - if (isEnoent(e)) { - await mkdir(dirname(p), { recursive: true }) - if (mode) { - await writeFile(p, content, { mode }) - } else { - await writeFile(p, content) - } - return - } - throw e + return } - } - - export async function writeJson(p: string, data: unknown, mode?: number): Promise { - return write(p, JSON.stringify(data, null, 2), mode) - } - - export async function writeStream( - p: string, - stream: ReadableStream | Readable, - mode?: number, - ): Promise { - const dir = dirname(p) - if (!existsSync(dir)) { - await mkdir(dir, { recursive: true }) - } - - const nodeStream = stream instanceof ReadableStream ? Readable.fromWeb(stream as any) : stream - const writeStream = createWriteStream(p) - await pipeline(nodeStream, writeStream) - - if (mode) { - await chmod(p, mode) - } - } - - export function mimeType(p: string): string { - return lookup(p) || "application/octet-stream" - } - - /** - * On Windows, normalize a path to its canonical casing using the filesystem. - * This is needed because Windows paths are case-insensitive but LSP servers - * may return paths with different casing than what we send them. - */ - export function normalizePath(p: string): string { - if (process.platform !== "win32") return p - const resolved = win32.normalize(win32.resolve(windowsPath(p))) - try { - return realpathSync.native(resolved) - } catch { - return resolved - } - } - - export function normalizePathPattern(p: string): string { - if (process.platform !== "win32") return p - if (p === "*") return p - const match = p.match(/^(.*)[\\/]\*$/) - if (!match) return normalizePath(p) - const dir = /^[A-Za-z]:$/.test(match[1]) ? match[1] + "\\" : match[1] - return join(normalizePath(dir), "*") - } - - // We cannot rely on path.resolve() here because git.exe may come from Git Bash, Cygwin, or MSYS2, so we need to translate these paths at the boundary. - // Also resolves symlinks so that callers using the result as a cache key - // always get the same canonical path for a given physical directory. - export function resolve(p: string): string { - const resolved = pathResolve(windowsPath(p)) - try { - return normalizePath(realpathSync(resolved)) - } catch (e) { - if (isEnoent(e)) return normalizePath(resolved) - throw e - } - } - - export function windowsPath(p: string): string { - if (process.platform !== "win32") return p - return ( - p - .replace(/^\/([a-zA-Z]):(?:[\\/]|$)/, (_, drive) => `${drive.toUpperCase()}:/`) - // Git Bash for Windows paths are typically //... - .replace(/^\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`) - // Cygwin git paths are typically /cygdrive//... - .replace(/^\/cygdrive\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`) - // WSL paths are typically /mnt//... - .replace(/^\/mnt\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`) - ) - } - export function overlaps(a: string, b: string) { - const relA = relative(a, b) - const relB = relative(b, a) - return !relA || !relA.startsWith("..") || !relB || !relB.startsWith("..") - } - - export function contains(parent: string, child: string) { - return !relative(parent, child).startsWith("..") - } - - export async function findUp( - target: string, - start: string, - stop?: string, - options?: { rootFirst?: boolean }, - ): Promise - export async function findUp( - target: string[], - start: string, - stop?: string, - options?: { rootFirst?: boolean }, - ): Promise - export async function findUp( - target: string | string[], - start: string, - stop?: string, - options?: { rootFirst?: boolean }, - ) { - const dirs = [start] - let current = start - while (true) { - if (stop === current) break - const parent = dirname(current) - if (parent === current) break - dirs.push(parent) - current = parent - } - - const targets = Array.isArray(target) ? target : [target] - const result = [] - for (const dir of options?.rootFirst ? dirs.toReversed() : dirs) { - for (const item of targets) { - const search = join(dir, item) - if (await exists(search)) result.push(search) - } - } - return result - } - - export async function* up(options: { targets: string[]; start: string; stop?: string }) { - const { targets, start, stop } = options - let current = start - while (true) { - for (const target of targets) { - const search = join(current, target) - if (await exists(search)) yield search - } - if (stop === current) break - const parent = dirname(current) - if (parent === current) break - current = parent - } - } - - export async function globUp(pattern: string, start: string, stop?: string) { - let current = start - const result = [] - while (true) { - try { - const matches = await Glob.scan(pattern, { - cwd: current, - absolute: true, - include: "file", - dot: true, - }) - result.push(...matches) - } catch { - // Skip invalid glob patterns - } - if (stop === current) break - const parent = dirname(current) - if (parent === current) break - current = parent - } - return result + throw e } } + +export async function writeJson(p: string, data: unknown, mode?: number): Promise { + return write(p, JSON.stringify(data, null, 2), mode) +} + +export async function writeStream( + p: string, + stream: ReadableStream | Readable, + mode?: number, +): Promise { + const dir = dirname(p) + if (!existsSync(dir)) { + await mkdir(dir, { recursive: true }) + } + + const nodeStream = stream instanceof ReadableStream ? Readable.fromWeb(stream as any) : stream + const writeStream = createWriteStream(p) + await pipeline(nodeStream, writeStream) + + if (mode) { + await chmod(p, mode) + } +} + +export function mimeType(p: string): string { + return lookup(p) || "application/octet-stream" +} + +/** + * On Windows, normalize a path to its canonical casing using the filesystem. + * This is needed because Windows paths are case-insensitive but LSP servers + * may return paths with different casing than what we send them. + */ +export function normalizePath(p: string): string { + if (process.platform !== "win32") return p + const resolved = win32.normalize(win32.resolve(windowsPath(p))) + try { + return realpathSync.native(resolved) + } catch { + return resolved + } +} + +export function normalizePathPattern(p: string): string { + if (process.platform !== "win32") return p + if (p === "*") return p + const match = p.match(/^(.*)[\\/]\*$/) + if (!match) return normalizePath(p) + const dir = /^[A-Za-z]:$/.test(match[1]) ? match[1] + "\\" : match[1] + return join(normalizePath(dir), "*") +} + +// We cannot rely on path.resolve() here because git.exe may come from Git Bash, Cygwin, or MSYS2, so we need to translate these paths at the boundary. +// Also resolves symlinks so that callers using the result as a cache key +// always get the same canonical path for a given physical directory. +export function resolve(p: string): string { + const resolved = pathResolve(windowsPath(p)) + try { + return normalizePath(realpathSync(resolved)) + } catch (e) { + if (isEnoent(e)) return normalizePath(resolved) + throw e + } +} + +export function windowsPath(p: string): string { + if (process.platform !== "win32") return p + return ( + p + .replace(/^\/([a-zA-Z]):(?:[\\/]|$)/, (_, drive) => `${drive.toUpperCase()}:/`) + // Git Bash for Windows paths are typically //... + .replace(/^\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`) + // Cygwin git paths are typically /cygdrive//... + .replace(/^\/cygdrive\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`) + // WSL paths are typically /mnt//... + .replace(/^\/mnt\/([a-zA-Z])(?:\/|$)/, (_, drive) => `${drive.toUpperCase()}:/`) + ) +} +export function overlaps(a: string, b: string) { + const relA = relative(a, b) + const relB = relative(b, a) + return !relA || !relA.startsWith("..") || !relB || !relB.startsWith("..") +} + +export function contains(parent: string, child: string) { + return !relative(parent, child).startsWith("..") +} + +export async function findUp( + target: string, + start: string, + stop?: string, + options?: { rootFirst?: boolean }, +): Promise +export async function findUp( + target: string[], + start: string, + stop?: string, + options?: { rootFirst?: boolean }, +): Promise +export async function findUp( + target: string | string[], + start: string, + stop?: string, + options?: { rootFirst?: boolean }, +) { + const dirs = [start] + let current = start + while (true) { + if (stop === current) break + const parent = dirname(current) + if (parent === current) break + dirs.push(parent) + current = parent + } + + const targets = Array.isArray(target) ? target : [target] + const result = [] + for (const dir of options?.rootFirst ? dirs.toReversed() : dirs) { + for (const item of targets) { + const search = join(dir, item) + if (await exists(search)) result.push(search) + } + } + return result +} + +export async function* up(options: { targets: string[]; start: string; stop?: string }) { + const { targets, start, stop } = options + let current = start + while (true) { + for (const target of targets) { + const search = join(current, target) + if (await exists(search)) yield search + } + if (stop === current) break + const parent = dirname(current) + if (parent === current) break + current = parent + } +} + +export async function globUp(pattern: string, start: string, stop?: string) { + let current = start + const result = [] + while (true) { + try { + const matches = await Glob.scan(pattern, { + cwd: current, + absolute: true, + include: "file", + dot: true, + }) + result.push(...matches) + } catch { + // Skip invalid glob patterns + } + if (stop === current) break + const parent = dirname(current) + if (parent === current) break + current = parent + } + return result +} diff --git a/packages/opencode/src/util/index.ts b/packages/opencode/src/util/index.ts index 157bb8e521..f051ad9649 100644 --- a/packages/opencode/src/util/index.ts +++ b/packages/opencode/src/util/index.ts @@ -1 +1,12 @@ export * as Archive from "./archive" +export * as Color from "./color" +export * as Filesystem from "./filesystem" +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 Process from "./process" +export * as Rpc from "./rpc" +export * as Token from "./token" +export * as Wildcard from "./wildcard" diff --git a/packages/opencode/src/util/keybind.ts b/packages/opencode/src/util/keybind.ts index 83c7945ae1..10a68c4b2a 100644 --- a/packages/opencode/src/util/keybind.ts +++ b/packages/opencode/src/util/keybind.ts @@ -1,103 +1,101 @@ import { isDeepEqual } from "remeda" import type { ParsedKey } from "@opentui/core" -export namespace Keybind { - /** - * Keybind info derived from OpenTUI's ParsedKey with our custom `leader` field. - * This ensures type compatibility and catches missing fields at compile time. - */ - export type Info = Pick & { - leader: boolean // our custom field - } +/** + * Keybind info derived from OpenTUI's ParsedKey with our custom `leader` field. + * This ensures type compatibility and catches missing fields at compile time. + */ +export type Info = Pick & { + leader: boolean // our custom field +} - export function match(a: Info | undefined, b: Info): boolean { - if (!a) return false - const normalizedA = { ...a, super: a.super ?? false } - const normalizedB = { ...b, super: b.super ?? false } - return isDeepEqual(normalizedA, normalizedB) - } +export function match(a: Info | undefined, b: Info): boolean { + if (!a) return false + const normalizedA = { ...a, super: a.super ?? false } + const normalizedB = { ...b, super: b.super ?? false } + return isDeepEqual(normalizedA, normalizedB) +} - /** - * Convert OpenTUI's ParsedKey to our Keybind.Info format. - * This helper ensures all required fields are present and avoids manual object creation. - */ - export function fromParsedKey(key: ParsedKey, leader = false): Info { - return { - name: key.name === " " ? "space" : key.name, - ctrl: key.ctrl, - meta: key.meta, - shift: key.shift, - super: key.super ?? false, - leader, - } - } - - export function toString(info: Info | undefined): string { - if (!info) return "" - const parts: string[] = [] - - if (info.ctrl) parts.push("ctrl") - if (info.meta) parts.push("alt") - if (info.super) parts.push("super") - if (info.shift) parts.push("shift") - if (info.name) { - if (info.name === "delete") parts.push("del") - else parts.push(info.name) - } - - let result = parts.join("+") - - if (info.leader) { - result = result ? ` ${result}` : `` - } - - return result - } - - export function parse(key: string): Info[] { - if (key === "none") return [] - - return key.split(",").map((combo) => { - // Handle syntax by replacing with leader+ - const normalized = combo.replace(//g, "leader+") - const parts = normalized.toLowerCase().split("+") - const info: Info = { - ctrl: false, - meta: false, - shift: false, - leader: false, - name: "", - } - - for (const part of parts) { - switch (part) { - case "ctrl": - info.ctrl = true - break - case "alt": - case "meta": - case "option": - info.meta = true - break - case "super": - info.super = true - break - case "shift": - info.shift = true - break - case "leader": - info.leader = true - break - case "esc": - info.name = "escape" - break - default: - info.name = part - break - } - } - - return info - }) +/** + * Convert OpenTUI's ParsedKey to our Keybind.Info format. + * This helper ensures all required fields are present and avoids manual object creation. + */ +export function fromParsedKey(key: ParsedKey, leader = false): Info { + return { + name: key.name === " " ? "space" : key.name, + ctrl: key.ctrl, + meta: key.meta, + shift: key.shift, + super: key.super ?? false, + leader, } } + +export function toString(info: Info | undefined): string { + if (!info) return "" + const parts: string[] = [] + + if (info.ctrl) parts.push("ctrl") + if (info.meta) parts.push("alt") + if (info.super) parts.push("super") + if (info.shift) parts.push("shift") + if (info.name) { + if (info.name === "delete") parts.push("del") + else parts.push(info.name) + } + + let result = parts.join("+") + + if (info.leader) { + result = result ? ` ${result}` : `` + } + + return result +} + +export function parse(key: string): Info[] { + if (key === "none") return [] + + return key.split(",").map((combo) => { + // Handle syntax by replacing with leader+ + const normalized = combo.replace(//g, "leader+") + const parts = normalized.toLowerCase().split("+") + const info: Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "", + } + + for (const part of parts) { + switch (part) { + case "ctrl": + info.ctrl = true + break + case "alt": + case "meta": + case "option": + info.meta = true + break + case "super": + info.super = true + break + case "shift": + info.shift = true + break + case "leader": + info.leader = true + break + case "esc": + info.name = "escape" + break + default: + info.name = part + break + } + } + + return info + }) +} diff --git a/packages/opencode/src/util/local-context.ts b/packages/opencode/src/util/local-context.ts index 26f88ab09e..c1aef946f4 100644 --- a/packages/opencode/src/util/local-context.ts +++ b/packages/opencode/src/util/local-context.ts @@ -1,25 +1,23 @@ import { AsyncLocalStorage } from "async_hooks" -export namespace LocalContext { - export class NotFound extends Error { - constructor(public override readonly name: string) { - super(`No context found for ${name}`) - } - } - - export function create(name: string) { - const storage = new AsyncLocalStorage() - return { - use() { - const result = storage.getStore() - if (!result) { - throw new NotFound(name) - } - return result - }, - provide(value: T, fn: () => R) { - return storage.run(value, fn) - }, - } +export class NotFound extends Error { + constructor(public override readonly name: string) { + super(`No context found for ${name}`) + } +} + +export function create(name: string) { + const storage = new AsyncLocalStorage() + return { + use() { + const result = storage.getStore() + if (!result) { + throw new NotFound(name) + } + return result + }, + provide(value: T, fn: () => R) { + return storage.run(value, fn) + }, } } diff --git a/packages/opencode/src/util/locale.ts b/packages/opencode/src/util/locale.ts index 653da09a0b..202e856b2e 100644 --- a/packages/opencode/src/util/locale.ts +++ b/packages/opencode/src/util/locale.ts @@ -1,81 +1,79 @@ -export namespace Locale { - export function titlecase(str: string) { - return str.replace(/\b\w/g, (c) => c.toUpperCase()) - } +export function titlecase(str: string) { + return str.replace(/\b\w/g, (c) => c.toUpperCase()) +} - export function time(input: number): string { - const date = new Date(input) - return date.toLocaleTimeString(undefined, { timeStyle: "short" }) - } +export function time(input: number): string { + const date = new Date(input) + return date.toLocaleTimeString(undefined, { timeStyle: "short" }) +} - export function datetime(input: number): string { - const date = new Date(input) - const localTime = time(input) - const localDate = date.toLocaleDateString() - return `${localTime} · ${localDate}` - } +export function datetime(input: number): string { + const date = new Date(input) + const localTime = time(input) + const localDate = date.toLocaleDateString() + return `${localTime} · ${localDate}` +} - export function todayTimeOrDateTime(input: number): string { - const date = new Date(input) - const now = new Date() - const isToday = - date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate() +export function todayTimeOrDateTime(input: number): string { + const date = new Date(input) + const now = new Date() + const isToday = + date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate() - if (isToday) { - return time(input) - } else { - return datetime(input) - } - } - - export function number(num: number): string { - if (num >= 1000000) { - return (num / 1000000).toFixed(1) + "M" - } else if (num >= 1000) { - return (num / 1000).toFixed(1) + "K" - } - return num.toString() - } - - export function duration(input: number) { - if (input < 1000) { - return `${input}ms` - } - if (input < 60000) { - return `${(input / 1000).toFixed(1)}s` - } - if (input < 3600000) { - const minutes = Math.floor(input / 60000) - const seconds = Math.floor((input % 60000) / 1000) - return `${minutes}m ${seconds}s` - } - if (input < 86400000) { - const hours = Math.floor(input / 3600000) - const minutes = Math.floor((input % 3600000) / 60000) - return `${hours}h ${minutes}m` - } - const hours = Math.floor(input / 3600000) - const days = Math.floor((input % 3600000) / 86400000) - return `${days}d ${hours}h` - } - - export function truncate(str: string, len: number): string { - if (str.length <= len) return str - return str.slice(0, len - 1) + "…" - } - - export function truncateMiddle(str: string, maxLength: number = 35): string { - if (str.length <= maxLength) return str - - const ellipsis = "…" - const keepStart = Math.ceil((maxLength - ellipsis.length) / 2) - const keepEnd = Math.floor((maxLength - ellipsis.length) / 2) - - return str.slice(0, keepStart) + ellipsis + str.slice(-keepEnd) - } - - export function pluralize(count: number, singular: string, plural: string): string { - const template = count === 1 ? singular : plural - return template.replace("{}", count.toString()) + if (isToday) { + return time(input) + } else { + return datetime(input) } } + +export function number(num: number): string { + if (num >= 1000000) { + return (num / 1000000).toFixed(1) + "M" + } else if (num >= 1000) { + return (num / 1000).toFixed(1) + "K" + } + return num.toString() +} + +export function duration(input: number) { + if (input < 1000) { + return `${input}ms` + } + if (input < 60000) { + return `${(input / 1000).toFixed(1)}s` + } + if (input < 3600000) { + const minutes = Math.floor(input / 60000) + const seconds = Math.floor((input % 60000) / 1000) + return `${minutes}m ${seconds}s` + } + if (input < 86400000) { + const hours = Math.floor(input / 3600000) + const minutes = Math.floor((input % 3600000) / 60000) + return `${hours}h ${minutes}m` + } + const hours = Math.floor(input / 3600000) + const days = Math.floor((input % 3600000) / 86400000) + return `${days}d ${hours}h` +} + +export function truncate(str: string, len: number): string { + if (str.length <= len) return str + return str.slice(0, len - 1) + "…" +} + +export function truncateMiddle(str: string, maxLength: number = 35): string { + if (str.length <= maxLength) return str + + const ellipsis = "…" + const keepStart = Math.ceil((maxLength - ellipsis.length) / 2) + const keepEnd = Math.floor((maxLength - ellipsis.length) / 2) + + return str.slice(0, keepStart) + ellipsis + str.slice(-keepEnd) +} + +export function pluralize(count: number, singular: string, plural: string): string { + const template = count === 1 ? singular : plural + return template.replace("{}", count.toString()) +} diff --git a/packages/opencode/src/util/lock.ts b/packages/opencode/src/util/lock.ts index 3aea64394f..3f8e609378 100644 --- a/packages/opencode/src/util/lock.ts +++ b/packages/opencode/src/util/lock.ts @@ -1,54 +1,62 @@ -export namespace Lock { - const locks = new Map< - string, - { - readers: number - writer: boolean - waitingReaders: (() => void)[] - waitingWriters: (() => void)[] - } - >() +const locks = new Map< + string, + { + readers: number + writer: boolean + waitingReaders: (() => void)[] + waitingWriters: (() => void)[] + } +>() - function get(key: string) { - if (!locks.has(key)) { - locks.set(key, { - readers: 0, - writer: false, - waitingReaders: [], - waitingWriters: [], +function get(key: string) { + if (!locks.has(key)) { + locks.set(key, { + readers: 0, + writer: false, + waitingReaders: [], + waitingWriters: [], + }) + } + return locks.get(key)! +} + +function process(key: string) { + const lock = locks.get(key) + if (!lock || lock.writer || lock.readers > 0) return + + // Prioritize writers to prevent starvation + if (lock.waitingWriters.length > 0) { + const nextWriter = lock.waitingWriters.shift()! + nextWriter() + return + } + + // Wake up all waiting readers + while (lock.waitingReaders.length > 0) { + const nextReader = lock.waitingReaders.shift()! + nextReader() + } + + // Clean up empty locks + if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) { + locks.delete(key) + } +} + +export async function read(key: string): Promise { + const lock = get(key) + + return new Promise((resolve) => { + if (!lock.writer && lock.waitingWriters.length === 0) { + lock.readers++ + resolve({ + [Symbol.dispose]: () => { + lock.readers-- + process(key) + }, }) - } - return locks.get(key)! - } - - function process(key: string) { - const lock = locks.get(key) - if (!lock || lock.writer || lock.readers > 0) return - - // Prioritize writers to prevent starvation - if (lock.waitingWriters.length > 0) { - const nextWriter = lock.waitingWriters.shift()! - nextWriter() - return - } - - // Wake up all waiting readers - while (lock.waitingReaders.length > 0) { - const nextReader = lock.waitingReaders.shift()! - nextReader() - } - - // Clean up empty locks - if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) { - locks.delete(key) - } - } - - export async function read(key: string): Promise { - const lock = get(key) - - return new Promise((resolve) => { - if (!lock.writer && lock.waitingWriters.length === 0) { + } else { + lock.waitingReaders.push(() => { lock.readers++ resolve({ [Symbol.dispose]: () => { @@ -56,25 +64,25 @@ export namespace Lock { process(key) }, }) - } else { - lock.waitingReaders.push(() => { - lock.readers++ - resolve({ - [Symbol.dispose]: () => { - lock.readers-- - process(key) - }, - }) - }) - } - }) - } + }) + } + }) +} - export async function write(key: string): Promise { - const lock = get(key) +export async function write(key: string): Promise { + const lock = get(key) - return new Promise((resolve) => { - if (!lock.writer && lock.readers === 0) { + return new Promise((resolve) => { + if (!lock.writer && lock.readers === 0) { + lock.writer = true + resolve({ + [Symbol.dispose]: () => { + lock.writer = false + process(key) + }, + }) + } else { + lock.waitingWriters.push(() => { lock.writer = true resolve({ [Symbol.dispose]: () => { @@ -82,17 +90,7 @@ export namespace Lock { process(key) }, }) - } else { - lock.waitingWriters.push(() => { - lock.writer = true - resolve({ - [Symbol.dispose]: () => { - lock.writer = false - process(key) - }, - }) - }) - } - }) - } + }) + } + }) } diff --git a/packages/opencode/src/util/log.ts b/packages/opencode/src/util/log.ts index 7812632768..6be9816a87 100644 --- a/packages/opencode/src/util/log.ts +++ b/packages/opencode/src/util/log.ts @@ -5,183 +5,181 @@ import { Global } from "../global" import z from "zod" import { Glob } from "@opencode-ai/shared/util/glob" -export namespace Log { - export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" }) - export type Level = z.infer +export const Level = z.enum(["DEBUG", "INFO", "WARN", "ERROR"]).meta({ ref: "LogLevel", description: "Log level" }) +export type Level = z.infer - const levelPriority: Record = { - DEBUG: 0, - INFO: 1, - WARN: 2, - ERROR: 3, - } - const keep = 10 +const levelPriority: Record = { + DEBUG: 0, + INFO: 1, + WARN: 2, + ERROR: 3, +} +const keep = 10 - let level: Level = "INFO" +let level: Level = "INFO" - function shouldLog(input: Level): boolean { - return levelPriority[input] >= levelPriority[level] - } +function shouldLog(input: Level): boolean { + return levelPriority[input] >= levelPriority[level] +} - export type Logger = { - debug(message?: any, extra?: Record): void - info(message?: any, extra?: Record): void - error(message?: any, extra?: Record): void - warn(message?: any, extra?: Record): void - tag(key: string, value: string): Logger - clone(): Logger - time( - message: string, - extra?: Record, - ): { - stop(): void - [Symbol.dispose](): void - } - } - - const loggers = new Map() - - 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 - 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) { - 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) { - 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) { - if (shouldLog("DEBUG")) { - write("DEBUG " + build(message, extra)) - } - }, - info(message?: any, extra?: Record) { - if (shouldLog("INFO")) { - write("INFO " + build(message, extra)) - } - }, - error(message?: any, extra?: Record) { - if (shouldLog("ERROR")) { - write("ERROR " + build(message, extra)) - } - }, - warn(message?: any, extra?: Record) { - if (shouldLog("WARN")) { - write("WARN " + build(message, extra)) - } - }, - tag(key: string, value: string) { - if (tags) tags[key] = value - return result - }, - clone() { - return Log.create({ ...tags }) - }, - time(message: string, extra?: Record) { - 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 +export type Logger = { + debug(message?: any, extra?: Record): void + info(message?: any, extra?: Record): void + error(message?: any, extra?: Record): void + warn(message?: any, extra?: Record): void + tag(key: string, value: string): Logger + clone(): Logger + time( + message: string, + extra?: Record, + ): { + stop(): void + [Symbol.dispose](): void } } + +const loggers = new Map() + +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 + 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) { + 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) { + 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) { + if (shouldLog("DEBUG")) { + write("DEBUG " + build(message, extra)) + } + }, + info(message?: any, extra?: Record) { + if (shouldLog("INFO")) { + write("INFO " + build(message, extra)) + } + }, + error(message?: any, extra?: Record) { + if (shouldLog("ERROR")) { + write("ERROR " + build(message, extra)) + } + }, + warn(message?: any, extra?: Record) { + 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) { + 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 +} diff --git a/packages/opencode/src/util/process.ts b/packages/opencode/src/util/process.ts index e45ceb4710..96c35e5d6a 100644 --- a/packages/opencode/src/util/process.ts +++ b/packages/opencode/src/util/process.ts @@ -3,174 +3,172 @@ import launch from "cross-spawn" import { buffer } from "node:stream/consumers" import { errorMessage } from "./error" -export namespace Process { - export type Stdio = "inherit" | "pipe" | "ignore" - export type Shell = boolean | string +export type Stdio = "inherit" | "pipe" | "ignore" +export type Shell = boolean | string - export interface Options { - cwd?: string - env?: NodeJS.ProcessEnv | null - stdin?: Stdio - stdout?: Stdio - stderr?: Stdio - shell?: Shell - abort?: AbortSignal - kill?: NodeJS.Signals | number - timeout?: number - } +export interface Options { + cwd?: string + env?: NodeJS.ProcessEnv | null + stdin?: Stdio + stdout?: Stdio + stderr?: Stdio + shell?: Shell + abort?: AbortSignal + kill?: NodeJS.Signals | number + timeout?: number +} - export interface RunOptions extends Omit { - nothrow?: boolean - } +export interface RunOptions extends Omit { + nothrow?: boolean +} - export interface Result { - code: number - stdout: Buffer - stderr: Buffer - } +export interface Result { + code: number + stdout: Buffer + stderr: Buffer +} - export interface TextResult extends Result { - text: string - } +export interface TextResult extends Result { + text: string +} - export class RunFailedError extends Error { - readonly cmd: string[] - readonly code: number - readonly stdout: Buffer - readonly stderr: Buffer +export class RunFailedError extends Error { + readonly cmd: string[] + readonly code: number + readonly stdout: Buffer + readonly stderr: Buffer - constructor(cmd: string[], code: number, stdout: Buffer, stderr: Buffer) { - const text = stderr.toString().trim() - super( - text - ? `Command failed with code ${code}: ${cmd.join(" ")}\n${text}` - : `Command failed with code ${code}: ${cmd.join(" ")}`, - ) - this.name = "ProcessRunFailedError" - this.cmd = [...cmd] - this.code = code - this.stdout = stdout - this.stderr = stderr - } - } - - export type Child = ChildProcess & { exited: Promise } - - export function spawn(cmd: string[], opts: Options = {}): Child { - if (cmd.length === 0) throw new Error("Command is required") - opts.abort?.throwIfAborted() - - const proc = launch(cmd[0], cmd.slice(1), { - cwd: opts.cwd, - shell: opts.shell, - env: opts.env === null ? {} : opts.env ? { ...process.env, ...opts.env } : undefined, - stdio: [opts.stdin ?? "ignore", opts.stdout ?? "ignore", opts.stderr ?? "ignore"], - windowsHide: process.platform === "win32", - }) - - let closed = false - let timer: ReturnType | undefined - - const abort = () => { - if (closed) return - if (proc.exitCode !== null || proc.signalCode !== null) return - closed = true - - proc.kill(opts.kill ?? "SIGTERM") - - const ms = opts.timeout ?? 5_000 - if (ms <= 0) return - timer = setTimeout(() => proc.kill("SIGKILL"), ms) - } - - const exited = new Promise((resolve, reject) => { - const done = () => { - opts.abort?.removeEventListener("abort", abort) - if (timer) clearTimeout(timer) - } - - proc.once("exit", (code, signal) => { - done() - resolve(code ?? (signal ? 1 : 0)) - }) - - proc.once("error", (error) => { - done() - reject(error) - }) - }) - void exited.catch(() => undefined) - - if (opts.abort) { - opts.abort.addEventListener("abort", abort, { once: true }) - if (opts.abort.aborted) abort() - } - - const child = proc as Child - child.exited = exited - return child - } - - export async function run(cmd: string[], opts: RunOptions = {}): Promise { - const proc = spawn(cmd, { - cwd: opts.cwd, - env: opts.env, - stdin: opts.stdin, - shell: opts.shell, - abort: opts.abort, - kill: opts.kill, - timeout: opts.timeout, - stdout: "pipe", - stderr: "pipe", - }) - - if (!proc.stdout || !proc.stderr) throw new Error("Process output not available") - - const out = await Promise.all([proc.exited, buffer(proc.stdout), buffer(proc.stderr)]) - .then(([code, stdout, stderr]) => ({ - code, - stdout, - stderr, - })) - .catch((err: unknown) => { - if (!opts.nothrow) throw err - return { - code: 1, - stdout: Buffer.alloc(0), - stderr: Buffer.from(errorMessage(err)), - } - }) - if (out.code === 0 || opts.nothrow) return out - throw new RunFailedError(cmd, out.code, out.stdout, out.stderr) - } - - // Duplicated in `packages/sdk/js/src/process.ts` because the SDK cannot import - // `opencode` without creating a cycle. Keep both copies in sync. - export async function stop(proc: ChildProcess) { - if (proc.exitCode !== null || proc.signalCode !== null) return - - if (process.platform !== "win32" || !proc.pid) { - proc.kill() - return - } - - const out = await run(["taskkill", "/pid", String(proc.pid), "/T", "/F"], { - nothrow: true, - }) - - if (out.code === 0) return - proc.kill() - } - - export async function text(cmd: string[], opts: RunOptions = {}): Promise { - const out = await run(cmd, opts) - return { - ...out, - text: out.stdout.toString(), - } - } - - export async function lines(cmd: string[], opts: RunOptions = {}): Promise { - return (await text(cmd, opts)).text.split(/\r?\n/).filter(Boolean) + constructor(cmd: string[], code: number, stdout: Buffer, stderr: Buffer) { + const text = stderr.toString().trim() + super( + text + ? `Command failed with code ${code}: ${cmd.join(" ")}\n${text}` + : `Command failed with code ${code}: ${cmd.join(" ")}`, + ) + this.name = "ProcessRunFailedError" + this.cmd = [...cmd] + this.code = code + this.stdout = stdout + this.stderr = stderr } } + +export type Child = ChildProcess & { exited: Promise } + +export function spawn(cmd: string[], opts: Options = {}): Child { + if (cmd.length === 0) throw new Error("Command is required") + opts.abort?.throwIfAborted() + + const proc = launch(cmd[0], cmd.slice(1), { + cwd: opts.cwd, + shell: opts.shell, + env: opts.env === null ? {} : opts.env ? { ...process.env, ...opts.env } : undefined, + stdio: [opts.stdin ?? "ignore", opts.stdout ?? "ignore", opts.stderr ?? "ignore"], + windowsHide: process.platform === "win32", + }) + + let closed = false + let timer: ReturnType | undefined + + const abort = () => { + if (closed) return + if (proc.exitCode !== null || proc.signalCode !== null) return + closed = true + + proc.kill(opts.kill ?? "SIGTERM") + + const ms = opts.timeout ?? 5_000 + if (ms <= 0) return + timer = setTimeout(() => proc.kill("SIGKILL"), ms) + } + + const exited = new Promise((resolve, reject) => { + const done = () => { + opts.abort?.removeEventListener("abort", abort) + if (timer) clearTimeout(timer) + } + + proc.once("exit", (code, signal) => { + done() + resolve(code ?? (signal ? 1 : 0)) + }) + + proc.once("error", (error) => { + done() + reject(error) + }) + }) + void exited.catch(() => undefined) + + if (opts.abort) { + opts.abort.addEventListener("abort", abort, { once: true }) + if (opts.abort.aborted) abort() + } + + const child = proc as Child + child.exited = exited + return child +} + +export async function run(cmd: string[], opts: RunOptions = {}): Promise { + const proc = spawn(cmd, { + cwd: opts.cwd, + env: opts.env, + stdin: opts.stdin, + shell: opts.shell, + abort: opts.abort, + kill: opts.kill, + timeout: opts.timeout, + stdout: "pipe", + stderr: "pipe", + }) + + if (!proc.stdout || !proc.stderr) throw new Error("Process output not available") + + const out = await Promise.all([proc.exited, buffer(proc.stdout), buffer(proc.stderr)]) + .then(([code, stdout, stderr]) => ({ + code, + stdout, + stderr, + })) + .catch((err: unknown) => { + if (!opts.nothrow) throw err + return { + code: 1, + stdout: Buffer.alloc(0), + stderr: Buffer.from(errorMessage(err)), + } + }) + if (out.code === 0 || opts.nothrow) return out + throw new RunFailedError(cmd, out.code, out.stdout, out.stderr) +} + +// Duplicated in `packages/sdk/js/src/process.ts` because the SDK cannot import +// `opencode` without creating a cycle. Keep both copies in sync. +export async function stop(proc: ChildProcess) { + if (proc.exitCode !== null || proc.signalCode !== null) return + + if (process.platform !== "win32" || !proc.pid) { + proc.kill() + return + } + + const out = await run(["taskkill", "/pid", String(proc.pid), "/T", "/F"], { + nothrow: true, + }) + + if (out.code === 0) return + proc.kill() +} + +export async function text(cmd: string[], opts: RunOptions = {}): Promise { + const out = await run(cmd, opts) + return { + ...out, + text: out.stdout.toString(), + } +} + +export async function lines(cmd: string[], opts: RunOptions = {}): Promise { + return (await text(cmd, opts)).text.split(/\r?\n/).filter(Boolean) +} diff --git a/packages/opencode/src/util/rpc.ts b/packages/opencode/src/util/rpc.ts index ebd8be40e4..98f3a09d46 100644 --- a/packages/opencode/src/util/rpc.ts +++ b/packages/opencode/src/util/rpc.ts @@ -1,66 +1,64 @@ -export namespace Rpc { - type Definition = { - [method: string]: (input: any) => any - } +type Definition = { + [method: string]: (input: any) => any +} - export function listen(rpc: Definition) { - onmessage = async (evt) => { - const parsed = JSON.parse(evt.data) - if (parsed.type === "rpc.request") { - const result = await rpc[parsed.method](parsed.input) - postMessage(JSON.stringify({ type: "rpc.result", result, id: parsed.id })) - } - } - } - - export function emit(event: string, data: unknown) { - postMessage(JSON.stringify({ type: "rpc.event", event, data })) - } - - export function client(target: { - postMessage: (data: string) => void | null - onmessage: ((this: Worker, ev: MessageEvent) => any) | null - }) { - const pending = new Map void>() - const listeners = new Map void>>() - let id = 0 - target.onmessage = async (evt) => { - const parsed = JSON.parse(evt.data) - if (parsed.type === "rpc.result") { - const resolve = pending.get(parsed.id) - if (resolve) { - resolve(parsed.result) - pending.delete(parsed.id) - } - } - if (parsed.type === "rpc.event") { - const handlers = listeners.get(parsed.event) - if (handlers) { - for (const handler of handlers) { - handler(parsed.data) - } - } - } - } - return { - call(method: Method, input: Parameters[0]): Promise> { - const requestId = id++ - return new Promise((resolve) => { - pending.set(requestId, resolve) - target.postMessage(JSON.stringify({ type: "rpc.request", method, input, id: requestId })) - }) - }, - on(event: string, handler: (data: Data) => void) { - let handlers = listeners.get(event) - if (!handlers) { - handlers = new Set() - listeners.set(event, handlers) - } - handlers.add(handler) - return () => { - handlers!.delete(handler) - } - }, +export function listen(rpc: Definition) { + onmessage = async (evt) => { + const parsed = JSON.parse(evt.data) + if (parsed.type === "rpc.request") { + const result = await rpc[parsed.method](parsed.input) + postMessage(JSON.stringify({ type: "rpc.result", result, id: parsed.id })) } } } + +export function emit(event: string, data: unknown) { + postMessage(JSON.stringify({ type: "rpc.event", event, data })) +} + +export function client(target: { + postMessage: (data: string) => void | null + onmessage: ((this: Worker, ev: MessageEvent) => any) | null +}) { + const pending = new Map void>() + const listeners = new Map void>>() + let id = 0 + target.onmessage = async (evt) => { + const parsed = JSON.parse(evt.data) + if (parsed.type === "rpc.result") { + const resolve = pending.get(parsed.id) + if (resolve) { + resolve(parsed.result) + pending.delete(parsed.id) + } + } + if (parsed.type === "rpc.event") { + const handlers = listeners.get(parsed.event) + if (handlers) { + for (const handler of handlers) { + handler(parsed.data) + } + } + } + } + return { + call(method: Method, input: Parameters[0]): Promise> { + const requestId = id++ + return new Promise((resolve) => { + pending.set(requestId, resolve) + target.postMessage(JSON.stringify({ type: "rpc.request", method, input, id: requestId })) + }) + }, + on(event: string, handler: (data: Data) => void) { + let handlers = listeners.get(event) + if (!handlers) { + handlers = new Set() + listeners.set(event, handlers) + } + handlers.add(handler) + return () => { + handlers!.delete(handler) + } + }, + } +} diff --git a/packages/opencode/src/util/token.ts b/packages/opencode/src/util/token.ts index cee5adc377..52951c4cf2 100644 --- a/packages/opencode/src/util/token.ts +++ b/packages/opencode/src/util/token.ts @@ -1,7 +1,5 @@ -export namespace Token { - const CHARS_PER_TOKEN = 4 +const CHARS_PER_TOKEN = 4 - export function estimate(input: string) { - return Math.max(0, Math.round((input || "").length / CHARS_PER_TOKEN)) - } +export function estimate(input: string) { + return Math.max(0, Math.round((input || "").length / CHARS_PER_TOKEN)) } diff --git a/packages/opencode/src/util/wildcard.ts b/packages/opencode/src/util/wildcard.ts index f54b6c85fd..0efb94e915 100644 --- a/packages/opencode/src/util/wildcard.ts +++ b/packages/opencode/src/util/wildcard.ts @@ -1,59 +1,57 @@ import { sortBy, pipe } from "remeda" -export namespace Wildcard { - export function match(str: string, pattern: string) { - if (str) str = str.replaceAll("\\", "/") - if (pattern) pattern = pattern.replaceAll("\\", "/") - let escaped = pattern - .replace(/[.+^${}()|[\]\\]/g, "\\$&") // escape special regex chars - .replace(/\*/g, ".*") // * becomes .* - .replace(/\?/g, ".") // ? becomes . +export function match(str: string, pattern: string) { + if (str) str = str.replaceAll("\\", "/") + if (pattern) pattern = pattern.replaceAll("\\", "/") + let escaped = pattern + .replace(/[.+^${}()|[\]\\]/g, "\\$&") // escape special regex chars + .replace(/\*/g, ".*") // * becomes .* + .replace(/\?/g, ".") // ? becomes . - // If pattern ends with " *" (space + wildcard), make the trailing part optional - // This allows "ls *" to match both "ls" and "ls -la" - if (escaped.endsWith(" .*")) { - escaped = escaped.slice(0, -3) + "( .*)?" - } - - const flags = process.platform === "win32" ? "si" : "s" - return new RegExp("^" + escaped + "$", flags).test(str) + // If pattern ends with " *" (space + wildcard), make the trailing part optional + // This allows "ls *" to match both "ls" and "ls -la" + if (escaped.endsWith(" .*")) { + escaped = escaped.slice(0, -3) + "( .*)?" } - export function all(input: string, patterns: Record) { - const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"])) - let result = undefined - for (const [pattern, value] of sorted) { - if (match(input, pattern)) { - result = value - continue - } - } - return result - } - - export function allStructured(input: { head: string; tail: string[] }, patterns: Record) { - const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"])) - let result = undefined - for (const [pattern, value] of sorted) { - const parts = pattern.split(/\s+/) - if (!match(input.head, parts[0])) continue - if (parts.length === 1 || matchSequence(input.tail, parts.slice(1))) { - result = value - continue - } - } - return result - } - - function matchSequence(items: string[], patterns: string[]): boolean { - if (patterns.length === 0) return true - const [pattern, ...rest] = patterns - if (pattern === "*") return matchSequence(items, rest) - for (let i = 0; i < items.length; i++) { - if (match(items[i], pattern) && matchSequence(items.slice(i + 1), rest)) { - return true - } - } - return false - } + const flags = process.platform === "win32" ? "si" : "s" + return new RegExp("^" + escaped + "$", flags).test(str) +} + +export function all(input: string, patterns: Record) { + const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"])) + let result = undefined + for (const [pattern, value] of sorted) { + if (match(input, pattern)) { + result = value + continue + } + } + return result +} + +export function allStructured(input: { head: string; tail: string[] }, patterns: Record) { + const sorted = pipe(patterns, Object.entries, sortBy([([key]) => key.length, "asc"], [([key]) => key, "asc"])) + let result = undefined + for (const [pattern, value] of sorted) { + const parts = pattern.split(/\s+/) + if (!match(input.head, parts[0])) continue + if (parts.length === 1 || matchSequence(input.tail, parts.slice(1))) { + result = value + continue + } + } + return result +} + +function matchSequence(items: string[], patterns: string[]): boolean { + if (patterns.length === 0) return true + const [pattern, ...rest] = patterns + if (pattern === "*") return matchSequence(items, rest) + for (let i = 0; i < items.length; i++) { + if (match(items[i], pattern) && matchSequence(items.slice(i + 1), rest)) { + return true + } + } + return false } diff --git a/packages/opencode/src/worktree/worktree.ts b/packages/opencode/src/worktree/worktree.ts index fab9ce57fa..86ef95f0e6 100644 --- a/packages/opencode/src/worktree/worktree.ts +++ b/packages/opencode/src/worktree/worktree.ts @@ -7,7 +7,7 @@ import { Project } from "../project/project" import { Database, eq } from "../storage/db" import { ProjectTable } from "../project/project.sql" import type { ProjectID } from "../project/schema" -import { Log } from "../util/log" +import { Log } from "../util" import { Slug } from "@opencode-ai/shared/util/slug" import { errorMessage } from "../util/error" import { BusEvent } from "@/bus/bus-event" diff --git a/packages/opencode/test/cli/tui/plugin-loader.test.ts b/packages/opencode/test/cli/tui/plugin-loader.test.ts index 119517b10c..8446570cc3 100644 --- a/packages/opencode/test/cli/tui/plugin-loader.test.ts +++ b/packages/opencode/test/cli/tui/plugin-loader.test.ts @@ -6,7 +6,7 @@ import { tmpdir } from "../../fixture/fixture" import { createTuiPluginApi } from "../../fixture/tui-plugin" import { Global } from "../../../src/global" import { TuiConfig } from "../../../src/config/tui" -import { Filesystem } from "../../../src/util/filesystem" +import { Filesystem } from "../../../src/util" const { allThemes, addTheme } = await import("../../../src/cli/cmd/tui/context/theme") const { TuiPluginRuntime } = await import("../../../src/cli/cmd/tui/plugin/runtime") diff --git a/packages/opencode/test/cli/tui/thread.test.ts b/packages/opencode/test/cli/tui/thread.test.ts index 176c2575a3..1c5c7e65e4 100644 --- a/packages/opencode/test/cli/tui/thread.test.ts +++ b/packages/opencode/test/cli/tui/thread.test.ts @@ -3,7 +3,7 @@ import fs from "fs/promises" import path from "path" import { tmpdir } from "../../fixture/fixture" import * as App from "../../../src/cli/cmd/tui/app" -import { Rpc } from "../../../src/util/rpc" +import { Rpc } from "../../../src/util" import { UI } from "../../../src/cli/ui" import * as Timeout from "../../../src/util/timeout" import * as Network from "../../../src/cli/network" diff --git a/packages/opencode/test/config/agent-color.test.ts b/packages/opencode/test/config/agent-color.test.ts index d77782354c..bfa948619b 100644 --- a/packages/opencode/test/config/agent-color.test.ts +++ b/packages/opencode/test/config/agent-color.test.ts @@ -5,7 +5,7 @@ import { provideInstance, tmpdir } from "../fixture/fixture" import { Instance } from "../../src/project/instance" import { Config } from "../../src/config" import { Agent as AgentSvc } from "../../src/agent/agent" -import { Color } from "../../src/util/color" +import { Color } from "../../src/util" import { AppRuntime } from "../../src/effect/app-runtime" const load = () => AppRuntime.runPromise(Config.Service.use((svc) => svc.get())) diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts index 8cf410c3d2..bc9fe5b015 100644 --- a/packages/opencode/test/config/config.test.ts +++ b/packages/opencode/test/config/config.test.ts @@ -23,7 +23,7 @@ import fs from "fs/promises" import { pathToFileURL } from "url" import { Global } from "../../src/global" import { ProjectID } from "../../src/project/schema" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import * as Network from "../../src/util/network" import { Npm } from "../../src/npm" diff --git a/packages/opencode/test/config/tui.test.ts b/packages/opencode/test/config/tui.test.ts index 4767e94b01..c80905cd1d 100644 --- a/packages/opencode/test/config/tui.test.ts +++ b/packages/opencode/test/config/tui.test.ts @@ -6,7 +6,7 @@ import { Instance } from "../../src/project/instance" import { Config } from "../../src/config" import { TuiConfig } from "../../src/config/tui" import { Global } from "../../src/global" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { AppRuntime } from "../../src/effect/app-runtime" const managedConfigDir = process.env.OPENCODE_TEST_MANAGED_CONFIG_DIR! diff --git a/packages/opencode/test/file/index.test.ts b/packages/opencode/test/file/index.test.ts index 877e2ae0a3..28fd2c8384 100644 --- a/packages/opencode/test/file/index.test.ts +++ b/packages/opencode/test/file/index.test.ts @@ -5,7 +5,7 @@ import path from "path" import fs from "fs/promises" import { File } from "../../src/file" import { Instance } from "../../src/project/instance" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { provideInstance, tmpdir } from "../fixture/fixture" afterEach(async () => { diff --git a/packages/opencode/test/file/path-traversal.test.ts b/packages/opencode/test/file/path-traversal.test.ts index 1f2e45a6ad..1190053949 100644 --- a/packages/opencode/test/file/path-traversal.test.ts +++ b/packages/opencode/test/file/path-traversal.test.ts @@ -2,7 +2,7 @@ import { test, expect, describe } from "bun:test" import { Effect } from "effect" import path from "path" import fs from "fs/promises" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { File } from "../../src/file" import { Instance } from "../../src/project/instance" import { provideInstance, tmpdir } from "../fixture/fixture" diff --git a/packages/opencode/test/file/time.test.ts b/packages/opencode/test/file/time.test.ts index 7f65d05ead..cb6390df87 100644 --- a/packages/opencode/test/file/time.test.ts +++ b/packages/opencode/test/file/time.test.ts @@ -6,7 +6,7 @@ import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner" import { FileTime } from "../../src/file/time" import { Instance } from "../../src/project/instance" import { SessionID } from "../../src/session/schema" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { provideInstance, provideTmpdirInstance, tmpdirScoped } from "../fixture/fixture" import { testEffect } from "../lib/effect" diff --git a/packages/opencode/test/fixture/plug-worker.ts b/packages/opencode/test/fixture/plug-worker.ts index e4b80c5dc5..c9afcd39f9 100644 --- a/packages/opencode/test/fixture/plug-worker.ts +++ b/packages/opencode/test/fixture/plug-worker.ts @@ -1,7 +1,7 @@ import path from "path" import { createPlugTask, type PlugCtx, type PlugDeps } from "../../src/cli/cmd/plug" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" type Msg = { dir: string diff --git a/packages/opencode/test/keybind.test.ts b/packages/opencode/test/keybind.test.ts index 4ca1f1697e..1e900a6020 100644 --- a/packages/opencode/test/keybind.test.ts +++ b/packages/opencode/test/keybind.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from "bun:test" -import { Keybind } from "../src/util/keybind" +import { Keybind } from "../src/util" describe("Keybind.toString", () => { test("should convert simple key to string", () => { diff --git a/packages/opencode/test/lsp/client.test.ts b/packages/opencode/test/lsp/client.test.ts index c2ba3ac5b0..414d11f8e7 100644 --- a/packages/opencode/test/lsp/client.test.ts +++ b/packages/opencode/test/lsp/client.test.ts @@ -3,7 +3,7 @@ import path from "path" import { LSPClient } from "../../src/lsp/client" import { LSPServer } from "../../src/lsp/server" import { Instance } from "../../src/project/instance" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" // Minimal fake LSP server that speaks JSON-RPC over stdio function spawnFakeServer() { diff --git a/packages/opencode/test/plugin/install-concurrency.test.ts b/packages/opencode/test/plugin/install-concurrency.test.ts index cf3e8692e1..06ec2fc996 100644 --- a/packages/opencode/test/plugin/install-concurrency.test.ts +++ b/packages/opencode/test/plugin/install-concurrency.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from "bun:test" import fs from "fs/promises" import path from "path" -import { Process } from "../../src/util/process" -import { Filesystem } from "../../src/util/filesystem" +import { Process } from "../../src/util" +import { Filesystem } from "../../src/util" import { tmpdir } from "../fixture/fixture" const root = path.join(import.meta.dir, "../..") diff --git a/packages/opencode/test/plugin/install.test.ts b/packages/opencode/test/plugin/install.test.ts index 5ce21c4cf4..f125f188a7 100644 --- a/packages/opencode/test/plugin/install.test.ts +++ b/packages/opencode/test/plugin/install.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test" import fs from "fs/promises" import path from "path" import { parse as parseJsonc } from "jsonc-parser" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { createPlugTask, type PlugCtx, type PlugDeps } from "../../src/cli/cmd/plug" import { tmpdir } from "../fixture/fixture" diff --git a/packages/opencode/test/plugin/loader-shared.test.ts b/packages/opencode/test/plugin/loader-shared.test.ts index 4265e83c55..5072c1e748 100644 --- a/packages/opencode/test/plugin/loader-shared.test.ts +++ b/packages/opencode/test/plugin/loader-shared.test.ts @@ -4,7 +4,7 @@ import fs from "fs/promises" import path from "path" import { pathToFileURL } from "url" import { tmpdir } from "../fixture/fixture" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" const disableDefault = process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS = "1" diff --git a/packages/opencode/test/plugin/meta.test.ts b/packages/opencode/test/plugin/meta.test.ts index 0571740667..3e2d4c6177 100644 --- a/packages/opencode/test/plugin/meta.test.ts +++ b/packages/opencode/test/plugin/meta.test.ts @@ -4,8 +4,8 @@ import path from "path" import { pathToFileURL } from "url" import { tmpdir } from "../fixture/fixture" -import { Process } from "../../src/util/process" -import { Filesystem } from "../../src/util/filesystem" +import { Process } from "../../src/util" +import { Filesystem } from "../../src/util" const { PluginMeta } = await import("../../src/plugin/meta") const root = path.join(import.meta.dir, "../..") diff --git a/packages/opencode/test/preload.ts b/packages/opencode/test/preload.ts index 0ddc797faf..ba5df4f1ea 100644 --- a/packages/opencode/test/preload.ts +++ b/packages/opencode/test/preload.ts @@ -78,7 +78,7 @@ delete process.env["OPENCODE_SERVER_USERNAME"] process.env["OPENCODE_DB"] = ":memory:" // Now safe to import from src/ -const { Log } = await import("../src/util/log") +const { Log } = await import("../src/util") const { initProjectors } = await import("../src/server/projectors") Log.init({ diff --git a/packages/opencode/test/project/migrate-global.test.ts b/packages/opencode/test/project/migrate-global.test.ts index d4313c12f1..d645fb25b8 100644 --- a/packages/opencode/test/project/migrate-global.test.ts +++ b/packages/opencode/test/project/migrate-global.test.ts @@ -5,7 +5,7 @@ import { SessionTable } from "../../src/session/session.sql" import { ProjectTable } from "../../src/project/project.sql" import { ProjectID } from "../../src/project/schema" import { SessionID } from "../../src/session/schema" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { $ } from "bun" import { tmpdir } from "../fixture/fixture" import { Effect } from "effect" diff --git a/packages/opencode/test/project/project.test.ts b/packages/opencode/test/project/project.test.ts index ba253a9205..a579a2335d 100644 --- a/packages/opencode/test/project/project.test.ts +++ b/packages/opencode/test/project/project.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test" import { Project } from "../../src/project/project" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { $ } from "bun" import path from "path" import { tmpdir } from "../fixture/fixture" diff --git a/packages/opencode/test/provider/amazon-bedrock.test.ts b/packages/opencode/test/provider/amazon-bedrock.test.ts index 6809e4d17e..03f83601dd 100644 --- a/packages/opencode/test/provider/amazon-bedrock.test.ts +++ b/packages/opencode/test/provider/amazon-bedrock.test.ts @@ -8,7 +8,7 @@ import { Instance } from "../../src/project/instance" import { Provider } from "../../src/provider" import { Env } from "../../src/env" import { Global } from "../../src/global" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { Effect } from "effect" import { AppRuntime } from "../../src/effect/app-runtime" import { makeRuntime } from "../../src/effect/run-service" diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index a6a93e8091..300a5b9031 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/packages/opencode/test/provider/provider.test.ts @@ -9,7 +9,7 @@ import { Plugin } from "../../src/plugin/index" import { ModelsDev } from "../../src/provider/models" import { Provider } from "../../src/provider" import { ProviderID, ModelID } from "../../src/provider/schema" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { Env } from "../../src/env" import { Effect } from "effect" import { AppRuntime } from "../../src/effect/app-runtime" diff --git a/packages/opencode/test/server/global-session-list.test.ts b/packages/opencode/test/server/global-session-list.test.ts index a1e374b4f7..c029fd9336 100644 --- a/packages/opencode/test/server/global-session-list.test.ts +++ b/packages/opencode/test/server/global-session-list.test.ts @@ -4,7 +4,7 @@ import z from "zod" import { Instance } from "../../src/project/instance" import { Project } from "../../src/project/project" import { Session as SessionNs } from "../../src/session" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { tmpdir } from "../fixture/fixture" Log.init({ print: false }) diff --git a/packages/opencode/test/server/project-init-git.test.ts b/packages/opencode/test/server/project-init-git.test.ts index 406b3d6d89..c3ee18e73a 100644 --- a/packages/opencode/test/server/project-init-git.test.ts +++ b/packages/opencode/test/server/project-init-git.test.ts @@ -5,8 +5,8 @@ import { GlobalBus } from "../../src/bus/global" import { Snapshot } from "../../src/snapshot" import { Instance } from "../../src/project/instance" import { Server } from "../../src/server/server" -import { Filesystem } from "../../src/util/filesystem" -import { Log } from "../../src/util/log" +import { Filesystem } from "../../src/util" +import { Log } from "../../src/util" import { resetDatabase } from "../fixture/db" import { provideInstance, tmpdir } from "../fixture/fixture" diff --git a/packages/opencode/test/server/session-actions.test.ts b/packages/opencode/test/server/session-actions.test.ts index 301691ae2f..3209ebff35 100644 --- a/packages/opencode/test/server/session-actions.test.ts +++ b/packages/opencode/test/server/session-actions.test.ts @@ -4,7 +4,7 @@ import { Instance } from "../../src/project/instance" import { Server } from "../../src/server/server" import { Session as SessionNs } from "../../src/session" import type { SessionID } from "../../src/session/schema" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { tmpdir } from "../fixture/fixture" Log.init({ print: false }) diff --git a/packages/opencode/test/server/session-list.test.ts b/packages/opencode/test/server/session-list.test.ts index 75adb7f9f3..9af60b9bdd 100644 --- a/packages/opencode/test/server/session-list.test.ts +++ b/packages/opencode/test/server/session-list.test.ts @@ -2,7 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test" import { Effect } from "effect" import { Instance } from "../../src/project/instance" import { Session as SessionNs } from "../../src/session" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { tmpdir } from "../fixture/fixture" Log.init({ print: false }) diff --git a/packages/opencode/test/server/session-messages.test.ts b/packages/opencode/test/server/session-messages.test.ts index 24ee6a1b43..d558d4324f 100644 --- a/packages/opencode/test/server/session-messages.test.ts +++ b/packages/opencode/test/server/session-messages.test.ts @@ -5,7 +5,7 @@ import { Server } from "../../src/server/server" import { Session as SessionNs } from "../../src/session" import { MessageV2 } from "../../src/session/message-v2" import { MessageID, PartID, type SessionID } from "../../src/session/schema" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { tmpdir } from "../fixture/fixture" Log.init({ print: false }) diff --git a/packages/opencode/test/server/session-select.test.ts b/packages/opencode/test/server/session-select.test.ts index 12552538da..c53448dfd4 100644 --- a/packages/opencode/test/server/session-select.test.ts +++ b/packages/opencode/test/server/session-select.test.ts @@ -2,7 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test" import { Effect } from "effect" import { Session as SessionNs } from "../../src/session" import type { SessionID } from "../../src/session/schema" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { Instance } from "../../src/project/instance" import { Server } from "../../src/server/server" import { tmpdir } from "../fixture/fixture" diff --git a/packages/opencode/test/session/compaction.test.ts b/packages/opencode/test/session/compaction.test.ts index 7711d31931..ee01932210 100644 --- a/packages/opencode/test/session/compaction.test.ts +++ b/packages/opencode/test/session/compaction.test.ts @@ -8,9 +8,9 @@ import { Config } from "../../src/config" import { Agent } from "../../src/agent/agent" import { LLM } from "../../src/session/llm" import { SessionCompaction } from "../../src/session/compaction" -import { Token } from "../../src/util/token" +import { Token } from "../../src/util" import { Instance } from "../../src/project/instance" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { Permission } from "../../src/permission" import { Plugin } from "../../src/plugin" import { provideTmpdirInstance, tmpdir } from "../fixture/fixture" diff --git a/packages/opencode/test/session/llm.test.ts b/packages/opencode/test/session/llm.test.ts index f25ecc356a..d1d53f605b 100644 --- a/packages/opencode/test/session/llm.test.ts +++ b/packages/opencode/test/session/llm.test.ts @@ -10,7 +10,7 @@ import { Provider } from "../../src/provider" import { ProviderTransform } from "../../src/provider/transform" import { ModelsDev } from "../../src/provider/models" import { ProviderID, ModelID } from "../../src/provider/schema" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { tmpdir } from "../fixture/fixture" import type { Agent } from "../../src/agent/agent" import { MessageV2 } from "../../src/session/message-v2" diff --git a/packages/opencode/test/session/messages-pagination.test.ts b/packages/opencode/test/session/messages-pagination.test.ts index f728bd3646..804076dd48 100644 --- a/packages/opencode/test/session/messages-pagination.test.ts +++ b/packages/opencode/test/session/messages-pagination.test.ts @@ -6,7 +6,7 @@ import { Session as SessionNs } from "../../src/session" import { MessageV2 } from "../../src/session/message-v2" import { MessageID, PartID, type SessionID } from "../../src/session/schema" import { ModelID, ProviderID } from "../../src/provider/schema" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" const root = path.join(__dirname, "../..") Log.init({ print: false }) diff --git a/packages/opencode/test/session/processor-effect.test.ts b/packages/opencode/test/session/processor-effect.test.ts index 982399d6d1..87ff40c707 100644 --- a/packages/opencode/test/session/processor-effect.test.ts +++ b/packages/opencode/test/session/processor-effect.test.ts @@ -18,7 +18,7 @@ import { MessageID, PartID, SessionID } from "../../src/session/schema" import { SessionStatus } from "../../src/session/status" import { SessionSummary } from "../../src/session/summary" import { Snapshot } from "../../src/snapshot" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner" import { provideTmpdirServer } from "../fixture/fixture" import { testEffect } from "../lib/effect" diff --git a/packages/opencode/test/session/prompt-effect.test.ts b/packages/opencode/test/session/prompt-effect.test.ts index 5ff8bf3424..0a750352a7 100644 --- a/packages/opencode/test/session/prompt-effect.test.ts +++ b/packages/opencode/test/session/prompt-effect.test.ts @@ -36,7 +36,7 @@ import { Shell } from "../../src/shell/shell" import { Snapshot } from "../../src/snapshot" import { ToolRegistry } from "../../src/tool/registry" import { Truncate } from "../../src/tool/truncate" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner" import { Ripgrep } from "../../src/file/ripgrep" import { Format } from "../../src/format" diff --git a/packages/opencode/test/session/prompt.test.ts b/packages/opencode/test/session/prompt.test.ts index 4f5b19bca0..acf305f3f9 100644 --- a/packages/opencode/test/session/prompt.test.ts +++ b/packages/opencode/test/session/prompt.test.ts @@ -8,7 +8,7 @@ import { ModelID, ProviderID } from "../../src/provider/schema" import { Session } from "../../src/session" import { MessageV2 } from "../../src/session/message-v2" import { SessionPrompt } from "../../src/session/prompt" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { tmpdir } from "../fixture/fixture" Log.init({ print: false }) diff --git a/packages/opencode/test/session/revert-compact.test.ts b/packages/opencode/test/session/revert-compact.test.ts index 679f6166ff..211fcde9a8 100644 --- a/packages/opencode/test/session/revert-compact.test.ts +++ b/packages/opencode/test/session/revert-compact.test.ts @@ -7,7 +7,7 @@ import { ModelID, ProviderID } from "../../src/provider/schema" import { SessionRevert } from "../../src/session/revert" import { MessageV2 } from "../../src/session/message-v2" import { Snapshot } from "../../src/snapshot" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { MessageID, PartID, SessionID } from "../../src/session/schema" import * as CrossSpawnSpawner from "../../src/effect/cross-spawn-spawner" import { provideTmpdirInstance } from "../fixture/fixture" diff --git a/packages/opencode/test/session/session.test.ts b/packages/opencode/test/session/session.test.ts index 15132a2701..9c4686cba6 100644 --- a/packages/opencode/test/session/session.test.ts +++ b/packages/opencode/test/session/session.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test" import path from "path" import { Session as SessionNs } from "../../src/session" import { Bus } from "../../src/bus" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { Instance } from "../../src/project/instance" import { MessageV2 } from "../../src/session/message-v2" import { MessageID, PartID, type SessionID } from "../../src/session/schema" diff --git a/packages/opencode/test/session/snapshot-tool-race.test.ts b/packages/opencode/test/session/snapshot-tool-race.test.ts index 3681b14f7a..cb7fe4568e 100644 --- a/packages/opencode/test/session/snapshot-tool-race.test.ts +++ b/packages/opencode/test/session/snapshot-tool-race.test.ts @@ -22,7 +22,7 @@ import { SessionPrompt } from "../../src/session/prompt" import { SessionRevert } from "../../src/session/revert" import { SessionSummary } from "../../src/session/summary" import { MessageV2 } from "../../src/session/message-v2" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { provideTmpdirServer } from "../fixture/fixture" import { testEffect } from "../lib/effect" import { TestLLMServer } from "../lib/llm-server" diff --git a/packages/opencode/test/session/structured-output-integration.test.ts b/packages/opencode/test/session/structured-output-integration.test.ts index 64266de47a..346705bf22 100644 --- a/packages/opencode/test/session/structured-output-integration.test.ts +++ b/packages/opencode/test/session/structured-output-integration.test.ts @@ -3,7 +3,7 @@ import path from "path" import { Effect, Layer } from "effect" import { Session } from "../../src/session" import { SessionPrompt } from "../../src/session/prompt" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { Instance } from "../../src/project/instance" import { MessageV2 } from "../../src/session/message-v2" diff --git a/packages/opencode/test/shell/shell.test.ts b/packages/opencode/test/shell/shell.test.ts index 760d6dc05a..6d7a77d72d 100644 --- a/packages/opencode/test/shell/shell.test.ts +++ b/packages/opencode/test/shell/shell.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test" import path from "path" import { Shell } from "../../src/shell/shell" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" const withShell = async (shell: string | undefined, fn: () => void | Promise) => { const prev = process.env.SHELL diff --git a/packages/opencode/test/skill/discovery.test.ts b/packages/opencode/test/skill/discovery.test.ts index de356ef154..175500862d 100644 --- a/packages/opencode/test/skill/discovery.test.ts +++ b/packages/opencode/test/skill/discovery.test.ts @@ -2,7 +2,7 @@ import { describe, test, expect, beforeAll, afterAll } from "bun:test" import { Effect } from "effect" import { Discovery } from "../../src/skill/discovery" import { Global } from "../../src/global" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { rm } from "fs/promises" import path from "path" diff --git a/packages/opencode/test/snapshot/snapshot.test.ts b/packages/opencode/test/snapshot/snapshot.test.ts index 0c480a97c2..3330b497c3 100644 --- a/packages/opencode/test/snapshot/snapshot.test.ts +++ b/packages/opencode/test/snapshot/snapshot.test.ts @@ -5,7 +5,7 @@ import path from "path" import { Effect } from "effect" import { Snapshot } from "../../src/snapshot" import { Instance } from "../../src/project/instance" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { provideInstance, tmpdir } from "../fixture/fixture" // Git always outputs /-separated paths internally. Snapshot.patch() joins them diff --git a/packages/opencode/test/tool/bash.test.ts b/packages/opencode/test/tool/bash.test.ts index 19135ba98b..6a3eac15e0 100644 --- a/packages/opencode/test/tool/bash.test.ts +++ b/packages/opencode/test/tool/bash.test.ts @@ -5,7 +5,7 @@ import path from "path" import { Shell } from "../../src/shell/shell" import { BashTool } from "../../src/tool/bash" import { Instance } from "../../src/project/instance" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { tmpdir } from "../fixture/fixture" import type { Permission } from "../../src/permission" import { Agent } from "../../src/agent/agent" diff --git a/packages/opencode/test/tool/external-directory.test.ts b/packages/opencode/test/tool/external-directory.test.ts index 727ab74f18..ee8cb53963 100644 --- a/packages/opencode/test/tool/external-directory.test.ts +++ b/packages/opencode/test/tool/external-directory.test.ts @@ -4,7 +4,7 @@ import { Effect } from "effect" import type { Tool } from "../../src/tool/tool" import { Instance } from "../../src/project/instance" import { assertExternalDirectory } from "../../src/tool/external-directory" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { tmpdir } from "../fixture/fixture" import type { Permission } from "../../src/permission" import { SessionID, MessageID } from "../../src/session/schema" diff --git a/packages/opencode/test/tool/read.test.ts b/packages/opencode/test/tool/read.test.ts index f14ec33105..fa65068f86 100644 --- a/packages/opencode/test/tool/read.test.ts +++ b/packages/opencode/test/tool/read.test.ts @@ -13,7 +13,7 @@ import { Instruction } from "../../src/session/instruction" import { ReadTool } from "../../src/tool/read" import { Truncate } from "../../src/tool/truncate" import { Tool } from "../../src/tool/tool" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { provideInstance, tmpdirScoped } from "../fixture/fixture" import { testEffect } from "../lib/effect" diff --git a/packages/opencode/test/tool/truncation.test.ts b/packages/opencode/test/tool/truncation.test.ts index c9ef0d82a3..d0873046d6 100644 --- a/packages/opencode/test/tool/truncation.test.ts +++ b/packages/opencode/test/tool/truncation.test.ts @@ -3,8 +3,8 @@ import { NodeFileSystem } from "@effect/platform-node" import { Effect, FileSystem, Layer } from "effect" import { Truncate } from "../../src/tool/truncate" import { Identifier } from "../../src/id/id" -import { Process } from "../../src/util/process" -import { Filesystem } from "../../src/util/filesystem" +import { Process } from "../../src/util" +import { Filesystem } from "../../src/util" import path from "path" import { testEffect } from "../lib/effect" import { writeFileStringScoped } from "../lib/filesystem" diff --git a/packages/opencode/test/util/filesystem.test.ts b/packages/opencode/test/util/filesystem.test.ts index 3abcf011bc..1f3a66b950 100644 --- a/packages/opencode/test/util/filesystem.test.ts +++ b/packages/opencode/test/util/filesystem.test.ts @@ -1,7 +1,7 @@ import { describe, test, expect } from "bun:test" import path from "path" import fs from "fs/promises" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { tmpdir } from "../fixture/fixture" describe("filesystem", () => { diff --git a/packages/opencode/test/util/lock.test.ts b/packages/opencode/test/util/lock.test.ts index b877311e39..d51b936484 100644 --- a/packages/opencode/test/util/lock.test.ts +++ b/packages/opencode/test/util/lock.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test" -import { Lock } from "../../src/util/lock" +import { Lock } from "../../src/util" function tick() { return new Promise((r) => queueMicrotask(r)) diff --git a/packages/opencode/test/util/log.test.ts b/packages/opencode/test/util/log.test.ts index 33e64fcd01..336b16a17b 100644 --- a/packages/opencode/test/util/log.test.ts +++ b/packages/opencode/test/util/log.test.ts @@ -2,7 +2,7 @@ import { afterEach, expect, test } from "bun:test" import fs from "fs/promises" import path from "path" import { Global } from "../../src/global" -import { Log } from "../../src/util/log" +import { Log } from "../../src/util" import { tmpdir } from "../fixture/fixture" const log = Global.Path.log diff --git a/packages/opencode/test/util/module.test.ts b/packages/opencode/test/util/module.test.ts index 6f8539bfb7..6725149c74 100644 --- a/packages/opencode/test/util/module.test.ts +++ b/packages/opencode/test/util/module.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test" import path from "path" import { Module } from "@opencode-ai/shared/util/module" -import { Filesystem } from "../../src/util/filesystem" +import { Filesystem } from "../../src/util" import { tmpdir } from "../fixture/fixture" describe("util.module", () => { diff --git a/packages/opencode/test/util/process.test.ts b/packages/opencode/test/util/process.test.ts index 1d08cba6b7..5442025700 100644 --- a/packages/opencode/test/util/process.test.ts +++ b/packages/opencode/test/util/process.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test" import fs from "fs/promises" import path from "path" -import { Process } from "../../src/util/process" +import { Process } from "../../src/util" import { tmpdir } from "../fixture/fixture" function node(script: string) { diff --git a/packages/opencode/test/util/wildcard.test.ts b/packages/opencode/test/util/wildcard.test.ts index 56e753d12a..7c9b1e4ac1 100644 --- a/packages/opencode/test/util/wildcard.test.ts +++ b/packages/opencode/test/util/wildcard.test.ts @@ -1,5 +1,5 @@ import { test, expect } from "bun:test" -import { Wildcard } from "../../src/util/wildcard" +import { Wildcard } from "../../src/util" test("match handles glob tokens", () => { expect(Wildcard.match("file1.txt", "file?.txt")).toBe(true)