summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-12-09 13:55:39 -0500
committerDax Raad <[email protected]>2025-12-09 13:57:18 -0500
commitfb1b6c5e6bb93501b8a605e9080756c9f748b640 (patch)
treeef5d3daee9458bb76b582ef67ef9738d89be71a8
parentad0c4c5d89bc1be0dbc5782e493af66f5a34873b (diff)
downloadopencode-fb1b6c5e6bb93501b8a605e9080756c9f748b640.tar.gz
opencode-fb1b6c5e6bb93501b8a605e9080756c9f748b640.zip
add project.name/icon
-rw-r--r--packages/opencode/src/file/watcher.ts3
-rw-r--r--packages/opencode/src/project/project.ts28
-rw-r--r--packages/opencode/src/project/vcs.ts6
-rw-r--r--packages/opencode/src/server/project.ts31
-rw-r--r--packages/opencode/test/project/project.test.ts1
5 files changed, 52 insertions, 17 deletions
diff --git a/packages/opencode/src/file/watcher.ts b/packages/opencode/src/file/watcher.ts
index c9985acf3..da0ba444c 100644
--- a/packages/opencode/src/file/watcher.ts
+++ b/packages/opencode/src/file/watcher.ts
@@ -8,6 +8,7 @@ import { Config } from "../config/config"
import { createWrapper } from "@parcel/watcher/wrapper"
import { lazy } from "@/util/lazy"
import type ParcelWatcher from "@parcel/watcher"
+import { $ } from "bun"
declare const OPENCODE_LIBC: string | undefined
@@ -65,7 +66,7 @@ export namespace FileWatcher {
}),
)
- const vcsDir = Instance.project.vcsDir
+ const vcsDir = await $`git rev-parse --git-dir`.quiet().nothrow().cwd(Instance.worktree).text()
if (vcsDir && !cfgIgnores.includes(".git") && !cfgIgnores.includes(vcsDir)) {
subs.push(
await watcher().subscribe(vcsDir, subscribe, {
diff --git a/packages/opencode/src/project/project.ts b/packages/opencode/src/project/project.ts
index afd1436eb..f7e282083 100644
--- a/packages/opencode/src/project/project.ts
+++ b/packages/opencode/src/project/project.ts
@@ -7,6 +7,7 @@ import { Log } from "../util/log"
import { Flag } from "@/flag/flag"
import { Session } from "../session"
import { work } from "../util/queue"
+import { fn } from "@opencode-ai/util/fn"
export namespace Project {
const log = Log.create({ service: "project" })
@@ -14,8 +15,9 @@ export namespace Project {
.object({
id: z.string(),
worktree: z.string(),
- vcsDir: z.string().optional(),
vcs: z.literal("git").optional(),
+ name: z.string().optional(),
+ icon: z.string().optional(),
time: z.object({
created: z.number(),
updated: z.number().optional(),
@@ -46,7 +48,6 @@ export namespace Project {
return project
}
let worktree = path.dirname(git)
- const timer = log.time("git.rev-parse")
let id = await Bun.file(path.join(git, "opencode"))
.text()
.then((x) => x.trim())
@@ -67,19 +68,12 @@ export namespace Project {
id = roots[0]
if (id) Bun.file(path.join(git, "opencode")).write(id)
}
- timer.stop()
worktree = await $`git rev-parse --show-toplevel`
.quiet()
.nothrow()
.cwd(worktree)
.text()
.then((x) => path.resolve(worktree, x.trim()))
- const vcsDir = await $`git rev-parse --git-dir`
- .quiet()
- .nothrow()
- .cwd(worktree)
- .text()
- .then((x) => path.resolve(worktree, x.trim()))
const projectID = id || "global"
const existing = id ? await Storage.read<Info>(["project", id]).catch(() => undefined) : undefined
if (!existing && id) {
@@ -89,7 +83,6 @@ export namespace Project {
...existing,
id: projectID,
worktree,
- vcsDir,
vcs: "git",
time: {
created: Date.now(),
@@ -135,4 +128,19 @@ export namespace Project {
const keys = await Storage.list(["project"])
return await Promise.all(keys.map((x) => Storage.read<Info>(x)))
}
+
+ export const update = fn(
+ z.object({
+ projectID: z.string(),
+ name: z.string().optional(),
+ icon: z.string().optional(),
+ }),
+ async (input) => {
+ return await Storage.update<Info>(["project", input.projectID], (draft) => {
+ if (input.name !== undefined) draft.name = input.name
+ if (input.icon !== undefined) draft.icon = input.icon
+ draft.time.updated = Date.now()
+ })
+ },
+ )
}
diff --git a/packages/opencode/src/project/vcs.ts b/packages/opencode/src/project/vcs.ts
index a8d5e91b3..444e842ce 100644
--- a/packages/opencode/src/project/vcs.ts
+++ b/packages/opencode/src/project/vcs.ts
@@ -39,16 +39,14 @@ export namespace Vcs {
const state = Instance.state(
async () => {
- const vcsDir = Instance.project.vcsDir
- if (Instance.project.vcs !== "git" || !vcsDir) {
+ if (Instance.project.vcs !== "git") {
return { branch: async () => undefined, unsubscribe: undefined }
}
let current = await currentBranch()
log.info("initialized", { branch: current })
- const head = path.join(vcsDir, "HEAD")
const unsubscribe = Bus.subscribe(FileWatcher.Event.Updated, async (evt) => {
- if (evt.properties.file !== head) return
+ if (evt.properties.file.endsWith("HEAD")) return
const next = await currentBranch()
if (next !== current) {
log.info("branch changed", { from: current, to: next })
diff --git a/packages/opencode/src/server/project.ts b/packages/opencode/src/server/project.ts
index 9d5596595..5a45e68f0 100644
--- a/packages/opencode/src/server/project.ts
+++ b/packages/opencode/src/server/project.ts
@@ -1,8 +1,10 @@
import { Hono } from "hono"
-import { describeRoute } from "hono-openapi"
+import { describeRoute, validator } from "hono-openapi"
import { resolver } from "hono-openapi"
import { Instance } from "../project/instance"
import { Project } from "../project/project"
+import z from "zod"
+import { errors } from "./error"
export const ProjectRoute = new Hono()
.get(
@@ -48,3 +50,30 @@ export const ProjectRoute = new Hono()
return c.json(Instance.project)
},
)
+ .patch(
+ "/:projectID",
+ describeRoute({
+ summary: "Update project",
+ description: "Update project properties such as name and icon.",
+ operationId: "project.update",
+ responses: {
+ 200: {
+ description: "Updated project information",
+ content: {
+ "application/json": {
+ schema: resolver(Project.Info),
+ },
+ },
+ },
+ ...errors(400, 404),
+ },
+ }),
+ validator("param", z.object({ projectID: z.string() })),
+ validator("json", Project.update.schema.omit({ projectID: true })),
+ async (c) => {
+ const projectID = c.req.valid("param").projectID
+ const body = c.req.valid("json")
+ const project = await Project.update({ ...body, projectID })
+ return c.json(project)
+ },
+ )
diff --git a/packages/opencode/test/project/project.test.ts b/packages/opencode/test/project/project.test.ts
index 17b5c0fa5..da5af31b9 100644
--- a/packages/opencode/test/project/project.test.ts
+++ b/packages/opencode/test/project/project.test.ts
@@ -18,7 +18,6 @@ describe("Project.fromDirectory", () => {
expect(project.id).toBe("global")
expect(project.vcs).toBe("git")
expect(project.worktree).toBe(tmp.path)
- expect(project.vcsDir).toBe(path.join(tmp.path, ".git"))
const opencodeFile = path.join(tmp.path, ".git", "opencode")
const fileExists = await Bun.file(opencodeFile).exists()