codex-mobile-bridge 0.3.7

Remote bridge and service manager for codex-mobile.
Documentation
use rusqlite::{OptionalExtension, params};

use super::Storage;
use super::decode::decode_json_row;
use crate::bridge_protocol::PendingServerRequestRecord;

impl Storage {
    pub fn put_pending_request(&self, request: &PendingServerRequestRecord) -> anyhow::Result<()> {
        let conn = self.connect()?;
        conn.execute(
            "INSERT INTO pending_server_requests (
                 request_id, runtime_id, request_type, thread_id, turn_id, item_id, title,
                 reason, command, cwd, grant_root, tool_name, arguments, questions,
                 proposed_execpolicy_amendment, network_approval_context, schema,
                 available_decisions, raw_payload, created_at_ms, raw_json
             )
             VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21)
             ON CONFLICT(request_id) DO UPDATE SET
                 runtime_id = excluded.runtime_id,
                 request_type = excluded.request_type,
                 thread_id = excluded.thread_id,
                 turn_id = excluded.turn_id,
                 item_id = excluded.item_id,
                 title = excluded.title,
                 reason = excluded.reason,
                 command = excluded.command,
                 cwd = excluded.cwd,
                 grant_root = excluded.grant_root,
                 tool_name = excluded.tool_name,
                 arguments = excluded.arguments,
                 questions = excluded.questions,
                 proposed_execpolicy_amendment = excluded.proposed_execpolicy_amendment,
                 network_approval_context = excluded.network_approval_context,
                 schema = excluded.schema,
                 available_decisions = excluded.available_decisions,
                 raw_payload = excluded.raw_payload,
                 created_at_ms = excluded.created_at_ms,
                 raw_json = excluded.raw_json",
            params![
                request.request_id,
                request.runtime_id,
                request.request_type,
                request.thread_id,
                request.turn_id,
                request.item_id,
                request.title,
                request.reason,
                request.command,
                request.cwd,
                request.grant_root,
                request.tool_name,
                request.arguments.as_ref().map(serde_json::to_string).transpose()?,
                serde_json::to_string(&request.questions)?,
                request
                    .proposed_execpolicy_amendment
                    .as_ref()
                    .map(serde_json::to_string)
                    .transpose()?,
                request
                    .network_approval_context
                    .as_ref()
                    .map(serde_json::to_string)
                    .transpose()?,
                request.schema.as_ref().map(serde_json::to_string).transpose()?,
                serde_json::to_string(&request.available_decisions)?,
                serde_json::to_string(&request.raw_payload)?,
                request.created_at_ms,
                serde_json::to_string(request)?
            ],
        )?;
        Ok(())
    }

    pub fn get_pending_request(
        &self,
        request_id: &str,
    ) -> anyhow::Result<Option<PendingServerRequestRecord>> {
        let conn = self.connect()?;
        let record = conn
            .query_row(
                "SELECT raw_json FROM pending_server_requests WHERE request_id = ?1",
                params![request_id],
                |row| {
                    let raw: String = row.get(0)?;
                    decode_json_row(raw)
                },
            )
            .optional()?;
        Ok(record)
    }

    pub fn list_pending_requests(&self) -> anyhow::Result<Vec<PendingServerRequestRecord>> {
        let conn = self.connect()?;
        let mut stmt = conn.prepare(
            "SELECT raw_json
             FROM pending_server_requests
             ORDER BY created_at_ms ASC",
        )?;

        let rows = stmt.query_map([], |row| {
            let raw: String = row.get(0)?;
            decode_json_row(raw)
        })?;

        Ok(rows.collect::<rusqlite::Result<Vec<_>>>()?)
    }

    pub fn remove_pending_request(&self, request_id: &str) -> anyhow::Result<()> {
        let conn = self.connect()?;
        conn.execute(
            "DELETE FROM pending_server_requests WHERE request_id = ?1",
            params![request_id],
        )?;
        Ok(())
    }

    pub fn clear_pending_requests(&self) -> anyhow::Result<()> {
        let conn = self.connect()?;
        conn.execute("DELETE FROM pending_server_requests", [])?;
        Ok(())
    }
}