| 56 | } |
| 57 | |
| 58 | export function writeWorkspaceStateRecordSync( |
| 59 | state: AgentSpaceState, |
| 60 | workspaceId = DEFAULT_WORKSPACE_ID, |
| 61 | options?: WorkspaceStateWriteOptions, |
| 62 | ): AgentSpaceState { |
| 63 | const db = getDatabase(); |
| 64 | const now = new Date().toISOString(); |
| 65 | const existing = db |
| 66 | .prepare("SELECT id, state_version FROM workspace_snapshot WHERE id = ?") |
| 67 | .get(workspaceId) as { id: string; state_version: number } | undefined; |
| 68 | const expectedVersion = options?.expectedVersion ?? readWorkspaceStateVersion(state); |
| 69 | |
| 70 | if (!existing) { |
| 71 | db.prepare( |
| 72 | `INSERT INTO workspace_snapshot ( |
| 73 | id, |
| 74 | organization_name, |
| 75 | pending_handoffs, |
| 76 | state_json, |
| 77 | state_version, |
| 78 | created_at, |
| 79 | updated_at |
| 80 | ) VALUES (?, ?, ?, ?, 1, ?, ?)`, |
| 81 | ).run( |
| 82 | workspaceId, |
| 83 | state.organizationName, |
| 84 | state.pendingHandoffs, |
| 85 | JSON.stringify(state), |
| 86 | now, |
| 87 | now, |
| 88 | ); |
| 89 | return attachWorkspaceStateVersion(state, 1); |
| 90 | } |
| 91 | |
| 92 | if (!options?.skipVersionCheck && typeof expectedVersion === "number") { |
| 93 | const result = db.prepare( |
| 94 | `UPDATE workspace_snapshot |
| 95 | SET organization_name = ?, |
| 96 | pending_handoffs = ?, |
| 97 | state_json = ?, |
| 98 | state_version = state_version + 1, |
| 99 | updated_at = ? |
| 100 | WHERE id = ? AND state_version = ?`, |
| 101 | ).run( |
| 102 | state.organizationName, |
| 103 | state.pendingHandoffs, |
| 104 | JSON.stringify(state), |
| 105 | now, |
| 106 | workspaceId, |
| 107 | expectedVersion, |
| 108 | ); |
| 109 | |
| 110 | if (result.changes === 0) { |
| 111 | const currentVersion = readWorkspaceStateCurrentVersionSync(workspaceId) ?? existing.state_version; |
| 112 | throw new WorkspaceStateConflictError({ |
| 113 | workspaceId, |
| 114 | expectedVersion, |
| 115 | currentVersion, |