summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/opencode/src/app/app.ts3
-rw-r--r--packages/opencode/src/cli/bootstrap.ts2
-rw-r--r--packages/opencode/src/cli/cmd/debug/index.ts11
-rw-r--r--packages/opencode/src/cli/cmd/serve.ts4
-rw-r--r--packages/opencode/src/file/watch.ts50
-rw-r--r--packages/opencode/src/session/message.ts5
6 files changed, 73 insertions, 2 deletions
diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts
index 95b17abb3..6467d252c 100644
--- a/packages/opencode/src/app/app.ts
+++ b/packages/opencode/src/app/app.ts
@@ -36,12 +36,15 @@ export namespace App {
services: Map<any, { state: any; shutdown?: (input: any) => Promise<void> }>
}>("app")
+ export const use = ctx.use
+
const APP_JSON = "app.json"
export type Input = {
cwd: string
}
+ export const provideExisting = ctx.provide
export async function provide<T>(
input: Input,
cb: (app: App.Info) => Promise<T>,
diff --git a/packages/opencode/src/cli/bootstrap.ts b/packages/opencode/src/cli/bootstrap.ts
index e2b96f23d..9ae274edb 100644
--- a/packages/opencode/src/cli/bootstrap.ts
+++ b/packages/opencode/src/cli/bootstrap.ts
@@ -1,5 +1,6 @@
import { App } from "../app/app"
import { ConfigHooks } from "../config/hooks"
+import { FileWatcher } from "../file/watch"
import { Format } from "../format"
import { LSP } from "../lsp"
import { Share } from "../share/share"
@@ -13,6 +14,7 @@ export async function bootstrap<T>(
Format.init()
ConfigHooks.init()
LSP.init()
+ FileWatcher.init()
return cb(app)
})
diff --git a/packages/opencode/src/cli/cmd/debug/index.ts b/packages/opencode/src/cli/cmd/debug/index.ts
index 5a765997f..e748183ed 100644
--- a/packages/opencode/src/cli/cmd/debug/index.ts
+++ b/packages/opencode/src/cli/cmd/debug/index.ts
@@ -1,3 +1,4 @@
+import { bootstrap } from "../../bootstrap"
import { cmd } from "../cmd"
import { FileCommand } from "./file"
import { LSPCommand } from "./lsp"
@@ -12,6 +13,16 @@ export const DebugCommand = cmd({
.command(RipgrepCommand)
.command(FileCommand)
.command(SnapshotCommand)
+ .command({
+ command: "wait",
+ async handler() {
+ await bootstrap({ cwd: process.cwd() }, async () => {
+ await new Promise((resolve) =>
+ setTimeout(resolve, 1_000 * 60 * 60 * 24),
+ )
+ })
+ },
+ })
.demandCommand(),
async handler() {},
})
diff --git a/packages/opencode/src/cli/cmd/serve.ts b/packages/opencode/src/cli/cmd/serve.ts
index ef09e7946..f3686f304 100644
--- a/packages/opencode/src/cli/cmd/serve.ts
+++ b/packages/opencode/src/cli/cmd/serve.ts
@@ -1,7 +1,7 @@
-import { App } from "../../app/app"
import { Provider } from "../../provider/provider"
import { Server } from "../../server/server"
import { Share } from "../../share/share"
+import { bootstrap } from "../bootstrap"
import { cmd } from "./cmd"
export const ServeCommand = cmd({
@@ -23,7 +23,7 @@ export const ServeCommand = cmd({
describe: "starts a headless opencode server",
handler: async (args) => {
const cwd = process.cwd()
- await App.provide({ cwd }, async () => {
+ await bootstrap({ cwd }, async () => {
const providers = await Provider.list()
if (Object.keys(providers).length === 0) {
return "needs_provider"
diff --git a/packages/opencode/src/file/watch.ts b/packages/opencode/src/file/watch.ts
new file mode 100644
index 000000000..2a702984e
--- /dev/null
+++ b/packages/opencode/src/file/watch.ts
@@ -0,0 +1,50 @@
+import { z } from "zod"
+import { Bus } from "../bus"
+import fs from "fs"
+import { App } from "../app/app"
+import { Log } from "../util/log"
+
+export namespace FileWatcher {
+ const log = Log.create({ service: "file.watcher" })
+
+ export const Event = {
+ Updated: Bus.event(
+ "file.watcher.updated",
+ z.object({
+ file: z.string(),
+ event: z.union([z.literal("rename"), z.literal("change")]),
+ }),
+ ),
+ }
+
+ export function init() {
+ App.state(
+ "file.watcher",
+ () => {
+ const app = App.use()
+ const watcher = fs.watch(
+ app.info.path.cwd,
+ { recursive: true },
+ (event, file) => {
+ log.info("change", { file, event })
+ if (!file) return
+ // for some reason async local storage is lost here
+ // https://github.com/oven-sh/bun/issues/20754
+ App.provideExisting(app, async () => {
+ Bus.publish(Event.Updated, {
+ file,
+ event,
+ })
+ })
+ },
+ )
+ return {
+ watcher,
+ }
+ },
+ async (state) => {
+ state.watcher.close()
+ },
+ )()
+ }
+}
diff --git a/packages/opencode/src/session/message.ts b/packages/opencode/src/session/message.ts
index 6d16497e4..b2171fa44 100644
--- a/packages/opencode/src/session/message.ts
+++ b/packages/opencode/src/session/message.ts
@@ -188,6 +188,11 @@ export namespace Message {
}),
})
.optional(),
+ user: z
+ .object({
+ snapshot: z.string().optional(),
+ })
+ .optional(),
})
.openapi({ ref: "MessageMetadata" }),
})