| 132 | const appendMessage = (message: SessionMessage.Message) => insertMessage(db, event, message) |
| 133 | const adapter: SessionMessageUpdater.Adapter = { |
| 134 | getCurrentAssistant() { |
| 135 | return Effect.gen(function* () { |
| 136 | // A newer turn supersedes stale incomplete rows; never resume an older assistant projection. |
| 137 | const row = yield* db |
| 138 | .select() |
| 139 | .from(SessionMessageTable) |
| 140 | .where( |
| 141 | and(eq(SessionMessageTable.session_id, event.data.sessionID), eq(SessionMessageTable.type, "assistant")), |
| 142 | ) |
| 143 | .orderBy(desc(SessionMessageTable.seq)) |
| 144 | .limit(1) |
| 145 | .get() |
| 146 | .pipe(Effect.orDie) |
| 147 | if (!row) return |
| 148 | const message = decodeRow(row) |
| 149 | return message.type === "assistant" && !message.time.completed ? message : undefined |
| 150 | }) |
| 151 | }, |
| 152 | getAssistant(messageID) { |
| 153 | return Effect.gen(function* () { |
| 154 | const row = yield* db |