Skip to main content

objectiveai_cli/db/
agent_continuations.rs

1//! Latest-continuation registry keyed by `agent_instance_hierarchy`.
2//!
3//! Single function: [`upsert`]. Called by the chunk-yielder loops
4//! (`agents spawn`'s `run_multi_pass` and `functions execute`'s
5//! `runner::run`) before each chunk yield. The row holds whichever
6//! continuation was most recently observed for that AIH; the
7//! `ON CONFLICT DO UPDATE` clause keeps it idempotent against
8//! repeated upserts and overwrites stale rows from prior runs.
9//!
10//! No read API today — this is write-only scaffolding for future
11//! consumers (resume-from-continuation flows, etc.).
12
13use super::{Error, Pool};
14
15fn now_seconds() -> i64 {
16    use std::time::{SystemTime, UNIX_EPOCH};
17    SystemTime::now()
18        .duration_since(UNIX_EPOCH)
19        .map(|d| d.as_secs() as i64)
20        .unwrap_or(0)
21}
22
23/// Insert-or-replace the continuation for an AIH. Matches the
24/// `INSERT … ON CONFLICT … DO UPDATE` idiom used by `tags::apply`.
25pub async fn upsert(
26    pool: &Pool,
27    agent_instance_hierarchy: &str,
28    continuation: &str,
29) -> Result<(), Error> {
30    sqlx::query(
31        "INSERT INTO objectiveai.agent_continuations \
32             (agent_instance_hierarchy, continuation, updated_at) \
33         VALUES ($1, $2, $3) \
34         ON CONFLICT (agent_instance_hierarchy) DO UPDATE SET \
35             continuation = EXCLUDED.continuation, \
36             updated_at   = EXCLUDED.updated_at",
37    )
38    .bind(agent_instance_hierarchy)
39    .bind(continuation)
40    .bind(now_seconds())
41    .execute(&**pool)
42    .await?;
43    Ok(())
44}