summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2026-02-14 20:35:43 -0500
committerDax Raad <[email protected]>2026-02-14 20:37:17 -0500
commit2bab5e8c39f4ed70dbfe6d971728d8d899b88e4f (patch)
treeee11d5cd1a8c9144ffb97dee81046effe0ad654a /packages
parent85b5f5b705e8f7852184a4ef147bdc826639d224 (diff)
downloadopencode-2bab5e8c39f4ed70dbfe6d971728d8d899b88e4f.tar.gz
opencode-2bab5e8c39f4ed70dbfe6d971728d8d899b88e4f.zip
fix: derive all IDs from file paths during json migration
Earlier migrations moved data to new directories without updating JSON fields. Now consistently derives all IDs from file paths: - Projects: id from filename - Sessions: id from filename, projectID from parent directory - Messages: id from filename, sessionID from parent directory - Parts: id from filename, messageID from parent directory This ensures migrated data matches the actual file layout regardless of stale values in JSON content.
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/storage/json-migration.ts41
1 files changed, 16 insertions, 25 deletions
diff --git a/packages/opencode/src/storage/json-migration.ts b/packages/opencode/src/storage/json-migration.ts
index 89d561188..e0684ce3c 100644
--- a/packages/opencode/src/storage/json-migration.ts
+++ b/packages/opencode/src/storage/json-migration.ts
@@ -152,6 +152,7 @@ export namespace JsonMigration {
sqlite.exec("BEGIN TRANSACTION")
// Migrate projects first (no FK deps)
+ // Derive all IDs from file paths, not JSON content
const projectIds = new Set<string>()
const projectValues = [] as any[]
for (let i = 0; i < projectFiles.length; i += batchSize) {
@@ -161,13 +162,10 @@ export namespace JsonMigration {
for (let j = 0; j < batch.length; j++) {
const data = batch[j]
if (!data) continue
- if (!data?.id) {
- errs.push(`project missing id: ${projectFiles[i + j]}`)
- continue
- }
- projectIds.add(data.id)
+ const id = path.basename(projectFiles[i + j], ".json")
+ projectIds.add(id)
projectValues.push({
- id: data.id,
+ id,
worktree: data.worktree ?? "/",
vcs: data.vcs,
name: data.name ?? undefined,
@@ -186,6 +184,9 @@ export namespace JsonMigration {
log.info("migrated projects", { count: stats.projects, duration: Math.round(performance.now() - start) })
// Migrate sessions (depends on projects)
+ // Derive all IDs from directory/file paths, not JSON content, since earlier
+ // migrations may have moved sessions to new directories without updating the JSON
+ const sessionProjects = sessionFiles.map((file) => path.basename(path.dirname(file)))
const sessionIds = new Set<string>()
const sessionValues = [] as any[]
for (let i = 0; i < sessionFiles.length; i += batchSize) {
@@ -195,18 +196,16 @@ export namespace JsonMigration {
for (let j = 0; j < batch.length; j++) {
const data = batch[j]
if (!data) continue
- if (!data?.id || !data?.projectID) {
- errs.push(`session missing id or projectID: ${sessionFiles[i + j]}`)
- continue
- }
- if (!projectIds.has(data.projectID)) {
+ const id = path.basename(sessionFiles[i + j], ".json")
+ const projectID = sessionProjects[i + j]
+ if (!projectIds.has(projectID)) {
orphans.sessions++
continue
}
- sessionIds.add(data.id)
+ sessionIds.add(id)
sessionValues.push({
- id: data.id,
- project_id: data.projectID,
+ id,
+ project_id: projectID,
parent_id: data.parentID ?? null,
slug: data.slug ?? "",
directory: data.directory ?? "",
@@ -253,11 +252,7 @@ export namespace JsonMigration {
const data = batch[j]
if (!data) continue
const file = allMessageFiles[i + j]
- const id = data.id ?? path.basename(file, ".json")
- if (!id) {
- errs.push(`message missing id: ${file}`)
- continue
- }
+ const id = path.basename(file, ".json")
const sessionID = allMessageSessions[i + j]
messageSessions.set(id, sessionID)
const rest = data
@@ -287,12 +282,8 @@ export namespace JsonMigration {
const data = batch[j]
if (!data) continue
const file = partFiles[i + j]
- const id = data.id ?? path.basename(file, ".json")
- const messageID = data.messageID ?? path.basename(path.dirname(file))
- if (!id || !messageID) {
- errs.push(`part missing id/messageID/sessionID: ${file}`)
- continue
- }
+ const id = path.basename(file, ".json")
+ const messageID = path.basename(path.dirname(file))
const sessionID = messageSessions.get(messageID)
if (!sessionID) {
errs.push(`part missing message session: ${file}`)