1use super::rows::*;
2use super::*;
3
4impl Store {
5 pub fn upsert_session(&self, s: &SessionRecord) -> Result<()> {
6 self.conn.execute(
7 "INSERT INTO sessions (
8 id, agent, model, workspace, started_at_ms, ended_at_ms, status, trace_path,
9 start_commit, end_commit, branch, dirty_start, dirty_end, repo_binding_source,
10 prompt_fingerprint, parent_session_id, agent_version, os, arch,
11 repo_file_count, repo_total_loc
12 )
13 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15,
14 ?16, ?17, ?18, ?19, ?20, ?21)
15 ON CONFLICT(id) DO UPDATE SET
16 agent=excluded.agent, model=excluded.model, workspace=excluded.workspace,
17 started_at_ms=excluded.started_at_ms, ended_at_ms=excluded.ended_at_ms,
18 status=excluded.status, trace_path=excluded.trace_path,
19 start_commit=excluded.start_commit, end_commit=excluded.end_commit,
20 branch=excluded.branch, dirty_start=excluded.dirty_start,
21 dirty_end=excluded.dirty_end, repo_binding_source=excluded.repo_binding_source,
22 prompt_fingerprint=excluded.prompt_fingerprint,
23 parent_session_id=excluded.parent_session_id,
24 agent_version=excluded.agent_version, os=excluded.os, arch=excluded.arch,
25 repo_file_count=excluded.repo_file_count, repo_total_loc=excluded.repo_total_loc",
26 params![
27 s.id,
28 s.agent,
29 s.model,
30 s.workspace,
31 s.started_at_ms as i64,
32 s.ended_at_ms.map(|v| v as i64),
33 format!("{:?}", s.status),
34 s.trace_path,
35 s.start_commit,
36 s.end_commit,
37 s.branch,
38 s.dirty_start.map(bool_to_i64),
39 s.dirty_end.map(bool_to_i64),
40 s.repo_binding_source.clone().unwrap_or_default(),
41 s.prompt_fingerprint.as_deref(),
42 s.parent_session_id.as_deref(),
43 s.agent_version.as_deref(),
44 s.os.as_deref(),
45 s.arch.as_deref(),
46 s.repo_file_count.map(|v| v as i64),
47 s.repo_total_loc.map(|v| v as i64),
48 ],
49 )?;
50 self.conn.execute(
51 "INSERT INTO session_repo_binding (
52 session_id, start_commit, end_commit, branch, dirty_start, dirty_end, repo_binding_source
53 ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
54 ON CONFLICT(session_id) DO UPDATE SET
55 start_commit=excluded.start_commit,
56 end_commit=excluded.end_commit,
57 branch=excluded.branch,
58 dirty_start=excluded.dirty_start,
59 dirty_end=excluded.dirty_end,
60 repo_binding_source=excluded.repo_binding_source",
61 params![
62 s.id,
63 s.start_commit,
64 s.end_commit,
65 s.branch,
66 s.dirty_start.map(bool_to_i64),
67 s.dirty_end.map(bool_to_i64),
68 s.repo_binding_source.clone().unwrap_or_default(),
69 ],
70 )?;
71 Ok(())
72 }
73
74 pub fn ensure_session_stub(
77 &self,
78 id: &str,
79 agent: &str,
80 workspace: &str,
81 started_at_ms: u64,
82 ) -> Result<()> {
83 self.conn.execute(
84 "INSERT OR IGNORE INTO sessions (
85 id, agent, model, workspace, started_at_ms, ended_at_ms, status, trace_path,
86 start_commit, end_commit, branch, dirty_start, dirty_end, repo_binding_source,
87 prompt_fingerprint, parent_session_id, agent_version, os, arch, repo_file_count, repo_total_loc
88 ) VALUES (?1, ?2, NULL, ?3, ?4, NULL, 'Running', '', NULL, NULL, NULL, NULL, NULL, '',
89 NULL, NULL, NULL, NULL, NULL, NULL, NULL)",
90 params![id, agent, workspace, started_at_ms as i64],
91 )?;
92 Ok(())
93 }
94
95 pub fn enrich_session_identity(
96 &self,
97 id: &str,
98 agent: Option<&str>,
99 model: Option<&str>,
100 trace_path: Option<&str>,
101 ) -> Result<()> {
102 self.conn.execute(
103 "UPDATE sessions SET agent = COALESCE(?2, agent), model = COALESCE(?3, model),
104 trace_path = CASE WHEN COALESCE(?4, '') = '' THEN trace_path ELSE ?4 END WHERE id = ?1",
105 params![id, agent, model, trace_path],
106 )?;
107 Ok(())
108 }
109
110 pub fn update_session_status(&self, id: &str, status: SessionStatus) -> Result<()> {
112 self.conn.execute(
113 "UPDATE sessions SET status = ?1 WHERE id = ?2",
114 params![format!("{:?}", status), id],
115 )?;
116 Ok(())
117 }
118}