systemprompt_evaluation/repository/
cases.rs1use sqlx::PgPool;
7use std::sync::Arc;
8use systemprompt_database::DbPool;
9use systemprompt_identifiers::{AiRequestId, EvalCaseId, UserId};
10
11use crate::error::Result;
12use crate::models::{EvalCase, NewCaseParams};
13
14#[derive(Debug, Clone)]
15pub struct EvalCaseRepository {
16 pool: Arc<PgPool>,
17}
18
19impl EvalCaseRepository {
20 pub fn new(db: &DbPool) -> Result<Self> {
21 Ok(Self {
22 pool: db.write_pool_arc()?,
23 })
24 }
25
26 pub async fn create(&self, params: &NewCaseParams) -> Result<EvalCaseId> {
27 let id = EvalCaseId::generate();
28 let prompt_body = serde_json::to_value(¶ms.prompt)?;
29 let canonical_messages = serde_json::to_value(¶ms.prompt.messages)?;
30 sqlx::query!(
31 r#"
32 INSERT INTO eval_cases (
33 id, name, prompt_body, source_ai_request_id, expectation,
34 tags, created_by, canonical_messages, system_prompt,
35 offered_tools, provider, model, prepared_body_sha256
36 )
37 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
38 "#,
39 id.as_str(),
40 params.name,
41 prompt_body,
42 params
43 .source_ai_request_id
44 .as_ref()
45 .map(AiRequestId::as_str),
46 params.expectation.as_deref(),
47 ¶ms.tags,
48 params.created_by.as_str(),
49 canonical_messages,
50 params.prompt.system_prompt.as_deref(),
51 params.prompt.offered_tools.as_ref(),
52 params.prompt.provider,
53 params.prompt.model,
54 params.prepared_body_sha256.as_deref()
55 )
56 .execute(self.pool.as_ref())
57 .await?;
58 Ok(id)
59 }
60
61 pub async fn list_enabled(&self) -> Result<Vec<EvalCase>> {
62 let rows = sqlx::query!(
63 r#"
64 SELECT id, name, prompt_body, source_ai_request_id, expectation,
65 tags, enabled, created_by, created_at, repair_hint,
66 canonical_messages, system_prompt, offered_tools,
67 provider, model, prepared_body_sha256
68 FROM eval_cases
69 WHERE enabled = TRUE
70 ORDER BY created_at DESC
71 "#
72 )
73 .fetch_all(self.pool.as_ref())
74 .await?;
75
76 Ok(rows
77 .into_iter()
78 .map(|row| EvalCase {
79 id: EvalCaseId::new(row.id),
80 name: row.name,
81 prompt_body: row.prompt_body,
82 source_ai_request_id: row.source_ai_request_id.map(AiRequestId::new),
83 expectation: row.expectation,
84 tags: row.tags,
85 enabled: row.enabled,
86 created_by: UserId::new(row.created_by),
87 created_at: row.created_at,
88 repair_hint: row.repair_hint,
89 canonical_messages: row.canonical_messages,
90 system_prompt: row.system_prompt,
91 offered_tools: row.offered_tools,
92 provider: row.provider,
93 model: row.model,
94 prepared_body_sha256: row.prepared_body_sha256,
95 })
96 .collect())
97 }
98
99 pub async fn set_enabled(&self, id: &EvalCaseId, enabled: bool) -> Result<()> {
100 sqlx::query!(
101 "UPDATE eval_cases SET enabled = $2 WHERE id = $1",
102 id.as_str(),
103 enabled
104 )
105 .execute(self.pool.as_ref())
106 .await?;
107 Ok(())
108 }
109
110 pub async fn set_repair_hint(&self, id: &EvalCaseId, repair_hint: &str) -> Result<()> {
111 sqlx::query!(
112 "UPDATE eval_cases SET repair_hint = $2 WHERE id = $1",
113 id.as_str(),
114 repair_hint
115 )
116 .execute(self.pool.as_ref())
117 .await?;
118 Ok(())
119 }
120}