summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-06-01 14:40:44 -0400
committerDax Raad <[email protected]>2025-06-01 14:40:44 -0400
commit526a8ea19a64c131fb0b7924f38860984244b0cc (patch)
tree87cd4bb085bc4b5c2e39fe47a57af38bb2742b1e
parent4be9f7ab9c019d01acdf097071782c55089c0f4f (diff)
downloadopencode-526a8ea19a64c131fb0b7924f38860984244b0cc.tar.gz
opencode-526a8ea19a64c131fb0b7924f38860984244b0cc.zip
Refactor application path handling and data storage architecture
Replace simple directory-based path system with git-aware data management that uses global data directories and proper workspace detection. 🤖 Generated with opencode Co-Authored-By: opencode <[email protected]>
-rw-r--r--packages/opencode/src/app/app.ts33
-rw-r--r--packages/opencode/src/app/path.ts11
-rw-r--r--packages/opencode/src/config/config.ts2
-rw-r--r--packages/opencode/src/global/index.ts4
-rw-r--r--packages/opencode/src/id/id.ts1
-rw-r--r--packages/opencode/src/index.ts7
-rw-r--r--packages/opencode/src/lsp/client.ts4
-rw-r--r--packages/opencode/src/session/session.ts2
-rw-r--r--packages/opencode/src/storage/storage.ts4
-rw-r--r--packages/opencode/src/tool/glob.ts2
-rw-r--r--packages/opencode/src/tool/grep.ts2
-rw-r--r--packages/opencode/src/tool/ls.ts2
-rw-r--r--packages/opencode/src/tool/lsp-diagnostics.ts2
-rw-r--r--packages/opencode/src/tool/lsp-hover.ts2
-rw-r--r--packages/opencode/src/util/filesystem.ts18
-rw-r--r--packages/opencode/src/util/log.ts6
-rw-r--r--packages/opencode/sst-env.d.ts9
17 files changed, 69 insertions, 42 deletions
diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts
index 188726961..eae0d03b4 100644
--- a/packages/opencode/src/app/app.ts
+++ b/packages/opencode/src/app/app.ts
@@ -1,7 +1,9 @@
import fs from "fs/promises"
-import { AppPath } from "./path"
import { Log } from "../util/log"
import { Context } from "../util/context"
+import { Filesystem } from "../util/filesystem"
+import { Global } from "../global"
+import path from "path"
export namespace App {
const log = Log.create({ service: "app" })
@@ -10,12 +12,13 @@ export namespace App {
const ctx = Context.create<Info>("app")
- async function create(input: { directory: string }) {
- const dataDir = AppPath.data(input.directory)
- await fs.mkdir(dataDir, { recursive: true })
- await Log.file(input.directory)
+ async function create(input: { cwd: string; version: string }) {
+ let root = await Filesystem.findUp(".git", input.cwd).then((x) =>
+ x ? path.dirname(x) : input.cwd,
+ )
- log.info("created", { path: dataDir })
+ const data = path.join(Global.data(), root)
+ await Bun.write(path.join(data, "version"), input.version)
const services = new Map<
any,
@@ -25,14 +28,16 @@ export namespace App {
}
>()
- const result = {
- get services() {
- return services
- },
- get root() {
- return input.directory
+ await Log.file(path.join(data, "log"))
+
+ const result = Object.freeze({
+ services,
+ path: {
+ data,
+ root,
+ cwd: input.cwd,
},
- }
+ })
return result
}
@@ -61,7 +66,7 @@ export namespace App {
}
export async function provide<T extends (app: Info) => any>(
- input: { directory: string },
+ input: { cwd: string; version: string },
cb: T,
) {
const app = await create(input)
diff --git a/packages/opencode/src/app/path.ts b/packages/opencode/src/app/path.ts
deleted file mode 100644
index 4a5f4a858..000000000
--- a/packages/opencode/src/app/path.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import path from "path"
-
-export namespace AppPath {
- export function data(input: string) {
- return path.join(input, ".opencode")
- }
-
- export function storage(input: string) {
- return path.join(data(input), "storage")
- }
-}
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 88952d57b..8726b5a3d 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -8,7 +8,7 @@ export namespace Config {
const log = Log.create({ service: "config" })
export const state = App.state("config", async (app) => {
- const result = await load(app.root)
+ const result = await load(app.path.root)
return result
})
diff --git a/packages/opencode/src/global/index.ts b/packages/opencode/src/global/index.ts
index 4d766b4f8..e8afe4df3 100644
--- a/packages/opencode/src/global/index.ts
+++ b/packages/opencode/src/global/index.ts
@@ -17,4 +17,8 @@ export namespace Global {
export function cache() {
return paths.cache
}
+
+ export function data() {
+ return paths.data
+ }
}
diff --git a/packages/opencode/src/id/id.ts b/packages/opencode/src/id/id.ts
index b59848343..5544ff6f1 100644
--- a/packages/opencode/src/id/id.ts
+++ b/packages/opencode/src/id/id.ts
@@ -5,6 +5,7 @@ export namespace Identifier {
const prefixes = {
session: "ses",
message: "msg",
+ user: "usr",
} as const
export function schema(prefix: keyof typeof prefixes) {
diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts
index e311a3044..80bf4e00d 100644
--- a/packages/opencode/src/index.ts
+++ b/packages/opencode/src/index.ts
@@ -16,9 +16,10 @@ declare global {
}
const cli = cac("opencode")
+const version = typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev"
cli.command("", "Start the opencode in interactive mode").action(async () => {
- await App.provide({ directory: process.cwd() }, async () => {
+ await App.provide({ cwd: process.cwd(), version }, async () => {
await Share.init()
const server = Server.listen()
@@ -66,14 +67,14 @@ cli
.command("run [...message]", "Run a chat message")
.option("--session <id>", "Session ID")
.action(async (message: string[], options) => {
- await App.provide({ directory: process.cwd() }, async () => {
+ await App.provide({ cwd: process.cwd(), version }, async () => {
await Share.init()
const session = options.session
? await Session.get(options.session)
: await Session.create()
console.log("Session:", session.id)
- Bus.subscribe(Message.Event.Updated, async (message) => {
+ Bus.subscribe(Message.Event.Updated, async () => {
console.log("Thinking...")
})
diff --git a/packages/opencode/src/lsp/client.ts b/packages/opencode/src/lsp/client.ts
index 52e3ca32e..3f94bea6d 100644
--- a/packages/opencode/src/lsp/client.ts
+++ b/packages/opencode/src/lsp/client.ts
@@ -36,7 +36,7 @@ export namespace LSPClient {
const [command, ...args] = input.cmd
const server = spawn(command, args, {
stdio: ["pipe", "pipe", "pipe"],
- cwd: app.root,
+ cwd: app.path.cwd,
})
const connection = createMessageConnection(
@@ -64,7 +64,7 @@ export namespace LSPClient {
workspaceFolders: [
{
name: "workspace",
- uri: "file://" + app.root,
+ uri: "file://" + app.path.cwd,
},
],
tsserver: {
diff --git a/packages/opencode/src/session/session.ts b/packages/opencode/src/session/session.ts
index 008c84248..65e9c4515 100644
--- a/packages/opencode/src/session/session.ts
+++ b/packages/opencode/src/session/session.ts
@@ -220,7 +220,7 @@ export namespace Session {
tool: {},
},
}
- const contextFile = Bun.file(path.join(app.root, "CONTEXT.md"))
+ const contextFile = Bun.file(path.join(app.path.root, "CONTEXT.md"))
if (await contextFile.exists()) {
const context = await contextFile.text()
system.parts.push({
diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts
index 3680a9e2d..4addf5846 100644
--- a/packages/opencode/src/storage/storage.ts
+++ b/packages/opencode/src/storage/storage.ts
@@ -3,8 +3,8 @@ import { LocalStorageAdapter } from "@flystorage/local-fs"
import fs from "fs/promises"
import { Log } from "../util/log"
import { App } from "../app/app"
-import { AppPath } from "../app/path"
import { Bus } from "../bus"
+import path from "path"
import z from "zod"
export namespace Storage {
@@ -19,7 +19,7 @@ export namespace Storage {
const state = App.state("storage", async () => {
const app = await App.use()
- const storageDir = AppPath.storage(app.root)
+ const storageDir = path.join(app.path.data, "storage")
await fs.mkdir(storageDir, { recursive: true })
const storage = new FileStorage(new LocalStorageAdapter(storageDir))
log.info("created", { path: storageDir })
diff --git a/packages/opencode/src/tool/glob.ts b/packages/opencode/src/tool/glob.ts
index f505a6389..31b60a263 100644
--- a/packages/opencode/src/tool/glob.ts
+++ b/packages/opencode/src/tool/glob.ts
@@ -51,7 +51,7 @@ export const GlobTool = Tool.define({
}),
async execute(params) {
const app = await App.use()
- const search = params.path || app.root
+ const search = params.path || app.path.cwd
const limit = 100
const glob = new Bun.Glob(params.pattern)
const files = []
diff --git a/packages/opencode/src/tool/grep.ts b/packages/opencode/src/tool/grep.ts
index d1712e147..32a40bce9 100644
--- a/packages/opencode/src/tool/grep.ts
+++ b/packages/opencode/src/tool/grep.ts
@@ -287,7 +287,7 @@ export const GrepTool = Tool.define({
}
const app = await App.use()
- const searchPath = params.path || app.root
+ const searchPath = params.path || app.path.cwd
// If literalText is true, escape the pattern
const searchPattern = params.literalText
diff --git a/packages/opencode/src/tool/ls.ts b/packages/opencode/src/tool/ls.ts
index 7e97eb655..821f7e5e9 100644
--- a/packages/opencode/src/tool/ls.ts
+++ b/packages/opencode/src/tool/ls.ts
@@ -26,7 +26,7 @@ export const ListTool = Tool.define({
}),
async execute(params) {
const app = await App.use()
- const searchPath = path.resolve(app.root, params.path || ".")
+ const searchPath = path.resolve(app.path.cwd, params.path || ".")
const glob = new Bun.Glob("**/*")
const files = []
diff --git a/packages/opencode/src/tool/lsp-diagnostics.ts b/packages/opencode/src/tool/lsp-diagnostics.ts
index f9bde717a..d10542310 100644
--- a/packages/opencode/src/tool/lsp-diagnostics.ts
+++ b/packages/opencode/src/tool/lsp-diagnostics.ts
@@ -37,7 +37,7 @@ TIPS:
const app = await App.use()
const normalized = path.isAbsolute(args.path)
? args.path
- : path.join(app.root, args.path)
+ : path.join(app.path.cwd, args.path)
await LSP.file(normalized)
const diagnostics = await LSP.diagnostics()
const file = diagnostics[normalized]
diff --git a/packages/opencode/src/tool/lsp-hover.ts b/packages/opencode/src/tool/lsp-hover.ts
index e5bf02305..5ca654a5e 100644
--- a/packages/opencode/src/tool/lsp-hover.ts
+++ b/packages/opencode/src/tool/lsp-hover.ts
@@ -21,7 +21,7 @@ export const LspHoverTool = Tool.define({
const app = await App.use()
const file = path.isAbsolute(args.file)
? args.file
- : path.join(app.root, args.file)
+ : path.join(app.path.cwd, args.file)
await LSP.file(file)
const result = await LSP.hover({
...args,
diff --git a/packages/opencode/src/util/filesystem.ts b/packages/opencode/src/util/filesystem.ts
new file mode 100644
index 000000000..b85fbd72a
--- /dev/null
+++ b/packages/opencode/src/util/filesystem.ts
@@ -0,0 +1,18 @@
+import { exists } from "fs/promises"
+import { dirname, join } from "path"
+
+export namespace Filesystem {
+ export async function findUp(target: string, start: string) {
+ let currentDir = start
+ while (true) {
+ const targetPath = join(currentDir, target)
+ if (await exists(targetPath)) return targetPath
+ const parentDir = dirname(currentDir)
+ if (parentDir === currentDir) {
+ return
+ }
+ currentDir = parentDir
+ }
+ }
+}
+
diff --git a/packages/opencode/src/util/log.ts b/packages/opencode/src/util/log.ts
index 003ebb77a..dd97846c1 100644
--- a/packages/opencode/src/util/log.ts
+++ b/packages/opencode/src/util/log.ts
@@ -1,5 +1,4 @@
import path from "path"
-import { AppPath } from "../app/path"
import fs from "fs/promises"
export namespace Log {
const write = {
@@ -12,8 +11,9 @@ export namespace Log {
}
export async function file(directory: string) {
- const outPath = path.join(AppPath.data(directory), "opencode.out.log")
- const errPath = path.join(AppPath.data(directory), "opencode.err.log")
+ await fs.mkdir(directory, { recursive: true })
+ const outPath = path.join(directory, "opencode.out.log")
+ const errPath = path.join(directory, "opencode.err.log")
await fs.truncate(outPath).catch(() => {})
await fs.truncate(errPath).catch(() => {})
const out = Bun.file(outPath)
diff --git a/packages/opencode/sst-env.d.ts b/packages/opencode/sst-env.d.ts
new file mode 100644
index 000000000..b6a7e9066
--- /dev/null
+++ b/packages/opencode/sst-env.d.ts
@@ -0,0 +1,9 @@
+/* This file is auto-generated by SST. Do not edit. */
+/* tslint:disable */
+/* eslint-disable */
+/* deno-fmt-ignore-file */
+
+/// <reference path="../../sst-env.d.ts" />
+
+import "sst"
+export {} \ No newline at end of file