v2 phase 1: foundation — types, DB layer, logging
Add the v2 data layer: typed interfaces, central DB with migration runner, per-entity CRUD, and agent-runner session DB operations. - src/log.ts: concise message-first logging API - src/types-v2.ts: AgentGroup, MessagingGroup, Session, MessageIn/Out - src/db/: connection (WAL), migration runner, 001-initial schema, CRUD for agent_groups, messaging_groups, sessions, pending_questions - container/agent-runner/src/db/: session DB connection, messages_in reads + status transitions, messages_out writes - 31 new tests, all 277 tests pass Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
85
src/db/sessions.ts
Normal file
85
src/db/sessions.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import type { PendingQuestion, Session } from '../types-v2.js';
|
||||
import { getDb } from './connection.js';
|
||||
|
||||
// ── Sessions ──
|
||||
|
||||
export function createSession(session: Session): void {
|
||||
getDb()
|
||||
.prepare(
|
||||
`INSERT INTO sessions (id, agent_group_id, messaging_group_id, thread_id, agent_provider, status, container_status, last_active, created_at)
|
||||
VALUES (@id, @agent_group_id, @messaging_group_id, @thread_id, @agent_provider, @status, @container_status, @last_active, @created_at)`,
|
||||
)
|
||||
.run(session);
|
||||
}
|
||||
|
||||
export function getSession(id: string): Session | undefined {
|
||||
return getDb().prepare('SELECT * FROM sessions WHERE id = ?').get(id) as Session | undefined;
|
||||
}
|
||||
|
||||
export function findSession(messagingGroupId: string, threadId: string | null): Session | undefined {
|
||||
if (threadId) {
|
||||
return getDb()
|
||||
.prepare('SELECT * FROM sessions WHERE messaging_group_id = ? AND thread_id = ? AND status = ?')
|
||||
.get(messagingGroupId, threadId, 'active') as Session | undefined;
|
||||
}
|
||||
return getDb()
|
||||
.prepare('SELECT * FROM sessions WHERE messaging_group_id = ? AND thread_id IS NULL AND status = ?')
|
||||
.get(messagingGroupId, 'active') as Session | undefined;
|
||||
}
|
||||
|
||||
export function getSessionsByAgentGroup(agentGroupId: string): Session[] {
|
||||
return getDb().prepare('SELECT * FROM sessions WHERE agent_group_id = ?').all(agentGroupId) as Session[];
|
||||
}
|
||||
|
||||
export function getActiveSessions(): Session[] {
|
||||
return getDb().prepare("SELECT * FROM sessions WHERE status = 'active'").all() as Session[];
|
||||
}
|
||||
|
||||
export function getRunningSessions(): Session[] {
|
||||
return getDb().prepare("SELECT * FROM sessions WHERE container_status IN ('running', 'idle')").all() as Session[];
|
||||
}
|
||||
|
||||
export function updateSession(
|
||||
id: string,
|
||||
updates: Partial<Pick<Session, 'status' | 'container_status' | 'last_active' | 'agent_provider'>>,
|
||||
): void {
|
||||
const fields: string[] = [];
|
||||
const values: Record<string, unknown> = { id };
|
||||
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
if (value !== undefined) {
|
||||
fields.push(`${key} = @${key}`);
|
||||
values[key] = value;
|
||||
}
|
||||
}
|
||||
if (fields.length === 0) return;
|
||||
|
||||
getDb()
|
||||
.prepare(`UPDATE sessions SET ${fields.join(', ')} WHERE id = @id`)
|
||||
.run(values);
|
||||
}
|
||||
|
||||
export function deleteSession(id: string): void {
|
||||
getDb().prepare('DELETE FROM sessions WHERE id = ?').run(id);
|
||||
}
|
||||
|
||||
// ── Pending Questions ──
|
||||
|
||||
export function createPendingQuestion(pq: PendingQuestion): void {
|
||||
getDb()
|
||||
.prepare(
|
||||
`INSERT INTO pending_questions (question_id, session_id, message_out_id, platform_id, channel_type, thread_id, created_at)
|
||||
VALUES (@question_id, @session_id, @message_out_id, @platform_id, @channel_type, @thread_id, @created_at)`,
|
||||
)
|
||||
.run(pq);
|
||||
}
|
||||
|
||||
export function getPendingQuestion(questionId: string): PendingQuestion | undefined {
|
||||
return getDb().prepare('SELECT * FROM pending_questions WHERE question_id = ?').get(questionId) as
|
||||
| PendingQuestion
|
||||
| undefined;
|
||||
}
|
||||
|
||||
export function deletePendingQuestion(questionId: string): void {
|
||||
getDb().prepare('DELETE FROM pending_questions WHERE question_id = ?').run(questionId);
|
||||
}
|
||||
Reference in New Issue
Block a user