summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2025-12-04 22:49:07 -0800
committerGitHub <[email protected]>2025-12-05 00:49:07 -0600
commitf950de95ba3744dad248f51aaaa893afb3a22f4e (patch)
treedda9037f0163bd468516748fc5eeb46fae3f6764
parenta4e5a72c36db16dd89f55de7ce97a7b383feee66 (diff)
downloadopencode-f950de95ba3744dad248f51aaaa893afb3a22f4e.tar.gz
opencode-f950de95ba3744dad248f51aaaa893afb3a22f4e.zip
fix: ensure projects that go from having no commits to having commits have sessions migrated (#5105)
Co-authored-by: GitHub Action <[email protected]>
-rw-r--r--.github/workflows/review.yml4
-rw-r--r--packages/opencode/src/project/project.ts31
-rw-r--r--packages/opencode/src/util/queue.ts13
3 files changed, 46 insertions, 2 deletions
diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml
index c190bb44a..08fcc388d 100644
--- a/.github/workflows/review.yml
+++ b/.github/workflows/review.yml
@@ -48,7 +48,7 @@ jobs:
OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }'
run: |
PR_BODY=$(jq -r .body pr_data.json)
- opencode run -m anthropic/claude-sonnet-4-5 "A new pull request has been created: '${{ steps.pr-details.outputs.title }}'
+ opencode run -m anthropic/claude-opus-4-5 "A new pull request has been created: '${{ steps.pr-details.outputs.title }}'
<pr-number>
${{ steps.pr-number.outputs.number }}
@@ -75,4 +75,4 @@ jobs:
-f 'body=[summary of issue]' -f 'commit_id=${{ steps.pr-details.outputs.sha }}' -f 'path=[path-to-file]' -F \"line=[line]\" -f 'side=RIGHT'
\`\`\`
- Only create comments for actual violations. If the code follows all guidelines, comment 'lgtm' AND NOTHING ELSE!!!!."
+ Only create comments for actual violations. If the code follows all guidelines, comment on the issue using gh cli: 'lgtm' AND NOTHING ELSE!!!!."
diff --git a/packages/opencode/src/project/project.ts b/packages/opencode/src/project/project.ts
index 0bf50e16c..b3b724005 100644
--- a/packages/opencode/src/project/project.ts
+++ b/packages/opencode/src/project/project.ts
@@ -5,6 +5,8 @@ import { $ } from "bun"
import { Storage } from "../storage/storage"
import { Log } from "../util/log"
import { Flag } from "@/flag/flag"
+import { Session } from "../session"
+import { work } from "../util/queue"
export namespace Project {
const log = Log.create({ service: "project" })
@@ -77,6 +79,10 @@ export namespace Project {
.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) {
+ await migrateFromGlobal(projectID, worktree)
+ }
const project: Info = {
id: projectID,
worktree,
@@ -90,6 +96,31 @@ export namespace Project {
return project
}
+ async function migrateFromGlobal(newProjectID: string, worktree: string) {
+ const globalProject = await Storage.read<Info>(["project", "global"]).catch(() => undefined)
+ if (!globalProject) return
+
+ const globalSessions = await Storage.list(["session", "global"]).catch(() => [])
+ if (globalSessions.length === 0) return
+
+ log.info("migrating sessions from global", { newProjectID, worktree, count: globalSessions.length })
+ const worktreePrefix = worktree.endsWith(path.sep) ? worktree : worktree + path.sep
+
+ await work(10, globalSessions, async (key) => {
+ const sessionID = key[key.length - 1]
+ const session = await Storage.read<Session.Info>(key).catch(() => undefined)
+ if (!session) return
+ if (session.directory && session.directory !== worktree && !session.directory.startsWith(worktreePrefix)) return
+
+ session.projectID = newProjectID
+ log.info("migrating session", { sessionID, from: "global", to: newProjectID })
+ await Storage.write(["session", newProjectID, sessionID], session)
+ await Storage.remove(key)
+ }).catch((error) => {
+ log.error("failed to migrate sessions from global to project", { error, projectId: newProjectID })
+ })
+ }
+
export async function setInitialized(projectID: string) {
await Storage.update<Info>(["project", projectID], (draft) => {
draft.time.initialized = Date.now()
diff --git a/packages/opencode/src/util/queue.ts b/packages/opencode/src/util/queue.ts
index 259d785ce..a1af53fe8 100644
--- a/packages/opencode/src/util/queue.ts
+++ b/packages/opencode/src/util/queue.ts
@@ -17,3 +17,16 @@ export class AsyncQueue<T> implements AsyncIterable<T> {
while (true) yield await this.next()
}
}
+
+export async function work<T>(concurrency: number, items: T[], fn: (item: T) => Promise<void>) {
+ const pending = [...items]
+ await Promise.all(
+ Array.from({ length: concurrency }, async () => {
+ while (true) {
+ const item = pending.pop()
+ if (item === undefined) return
+ await fn(item)
+ }
+ }),
+ )
+}