Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand All @@ -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!!!!."
2 changes: 2 additions & 0 deletions .opencode/command/rmslop.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ description: Remove AI code slop
Check the diff against dev, and remove all AI generated slop introduced in this branch.

This includes:

- Extra comments that a human wouldn't add or is inconsistent with the rest of the file
- Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths)
- Casts to any to get around type issues
- Any other style that is inconsistent with the file
- Unnecessary emoji usage

Report at the end with only a 1-3 sentence summary of what you changed
31 changes: 31 additions & 0 deletions packages/opencode/src/project/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" })
Expand Down Expand Up @@ -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,
Expand All @@ -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()
Expand Down
13 changes: 13 additions & 0 deletions packages/opencode/src/util/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}),
)
}