fix: add FromRow derive macros for agent repo structs

This commit is contained in:
2026-09-15 00:06:37 +09:00
parent a8ef9ad3cb
commit 379aa5ce4d
2 changed files with 83 additions and 23 deletions
+6 -6
View File
@@ -1,10 +1,10 @@
use anyhow::Result; use anyhow::Result;
use sqlx::PgPool; use sqlx::{PgPool, FromRow};
use uuid::Uuid; use uuid::Uuid;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct AgentPrompt { pub struct AgentPrompt {
pub id: Uuid, pub id: Uuid,
pub project_id: String, pub project_id: String,
@@ -22,7 +22,7 @@ pub struct AgentPrompt {
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct AgentSkill { pub struct AgentSkill {
pub id: Uuid, pub id: Uuid,
pub project_id: String, pub project_id: String,
@@ -39,7 +39,7 @@ pub struct AgentSkill {
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct AgentDecision { pub struct AgentDecision {
pub id: Uuid, pub id: Uuid,
pub project_id: String, pub project_id: String,
@@ -59,7 +59,7 @@ pub struct AgentDecision {
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct RolePromptMapping { pub struct RolePromptMapping {
pub id: Uuid, pub id: Uuid,
pub project_id: String, pub project_id: String,
@@ -71,7 +71,7 @@ pub struct RolePromptMapping {
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct AgentMetrics { pub struct AgentMetrics {
pub id: Uuid, pub id: Uuid,
pub project_id: String, pub project_id: String,
+77 -17
View File
@@ -233,15 +233,33 @@ Output JSON with:
// Validate error schema is consistent // Validate error schema is consistent
let error_schema = &api_spec["components"]["schemas"]["Error"]; let error_schema = &api_spec["components"]["schemas"]["Error"];
assert!(error_schema["required"].as_array().unwrap().contains(&Value::String("code".to_string()))); assert!(error_schema["required"]
assert!(error_schema["required"].as_array().unwrap().contains(&Value::String("message".to_string()))); .as_array()
.unwrap()
.contains(&Value::String("code".to_string())));
assert!(error_schema["required"]
.as_array()
.unwrap()
.contains(&Value::String("message".to_string())));
// Validate naming consistency (snake_case) // Validate naming consistency (snake_case)
assert!(api_spec["paths"]["/memory/agents/{project_id}/prompts"]["post"]["operationId"].as_str().unwrap().contains("createPrompt")); assert!(
assert!(api_spec["paths"]["/memory/agents/{project_id}/roles/{role_name}/prompts"]["get"]["operationId"].as_str().unwrap().contains("getRolePrompts")); api_spec["paths"]["/memory/agents/{project_id}/prompts"]["post"]["operationId"]
.as_str()
.unwrap()
.contains("createPrompt")
);
assert!(
api_spec["paths"]["/memory/agents/{project_id}/roles/{role_name}/prompts"]["get"]
["operationId"]
.as_str()
.unwrap()
.contains("getRolePrompts")
);
// Validate backward compatibility: all fields are optional except required ones // Validate backward compatibility: all fields are optional except required ones
let create_prompt_schema = &api_spec["paths"]["/memory/agents/{project_id}/prompts"]["post"]["requestBody"]["content"]["application/json"]["schema"]; let create_prompt_schema = &api_spec["paths"]["/memory/agents/{project_id}/prompts"]
["post"]["requestBody"]["content"]["application/json"]["schema"];
assert_eq!( assert_eq!(
create_prompt_schema["required"].as_array().unwrap(), create_prompt_schema["required"].as_array().unwrap(),
&vec![ &vec![
@@ -329,8 +347,16 @@ Output JSON with:
}); });
assert_eq!(rate_limited_response["status"], 429); assert_eq!(rate_limited_response["status"], 429);
assert_eq!(rate_limited_response["error"]["code"], "rate_limit_exceeded"); assert_eq!(
assert!(rate_limited_response["headers"]["Retry-After"].as_i64().unwrap() > 0); rate_limited_response["error"]["code"],
"rate_limit_exceeded"
);
assert!(
rate_limited_response["headers"]["Retry-After"]
.as_i64()
.unwrap()
> 0
);
println!("✓ Rate limiting communication validated"); println!("✓ Rate limiting communication validated");
} }
@@ -396,8 +422,13 @@ Output JSON with:
}); });
assert_eq!(deprecation_plan["lifecycle"]["runway_days"], 365); assert_eq!(deprecation_plan["lifecycle"]["runway_days"], 365);
assert!(deprecation_plan["signals"]["deprecation_header"].as_str().unwrap().contains("Deprecation")); assert!(deprecation_plan["signals"]["deprecation_header"]
assert!(deprecation_plan["monitoring"]["track_usage_by_consumer"].as_bool().unwrap()); .as_str()
.unwrap()
.contains("Deprecation"));
assert!(deprecation_plan["monitoring"]["track_usage_by_consumer"]
.as_bool()
.unwrap());
println!("✓ Deprecation lifecycle validated"); println!("✓ Deprecation lifecycle validated");
} }
@@ -481,11 +512,30 @@ Output JSON with:
// Validate all requirements // Validate all requirements
assert!(role_requirements["requirements"]["contract_first"]["openapi_spec"] == "required"); assert!(role_requirements["requirements"]["contract_first"]["openapi_spec"] == "required");
assert!(role_requirements["requirements"]["backward_compatibility"]["no_silent_breaking_changes"].as_bool().unwrap()); assert!(role_requirements["requirements"]["backward_compatibility"]
assert!(role_requirements["requirements"]["error_handling"]["consistent_structure"].as_bool().unwrap()); ["no_silent_breaking_changes"]
assert!(role_requirements["requirements"]["rate_limiting"]["communicated_headers"].as_bool().unwrap()); .as_bool()
assert!(role_requirements["requirements"]["sdk_and_docs"]["generated_from_spec"].as_bool().unwrap()); .unwrap());
assert!(role_requirements["requirements"]["idempotency"]["write_operations_idempotent"].as_bool().unwrap()); assert!(
role_requirements["requirements"]["error_handling"]["consistent_structure"]
.as_bool()
.unwrap()
);
assert!(
role_requirements["requirements"]["rate_limiting"]["communicated_headers"]
.as_bool()
.unwrap()
);
assert!(
role_requirements["requirements"]["sdk_and_docs"]["generated_from_spec"]
.as_bool()
.unwrap()
);
assert!(
role_requirements["requirements"]["idempotency"]["write_operations_idempotent"]
.as_bool()
.unwrap()
);
println!("✓ API Platform Engineer role requirements validated"); println!("✓ API Platform Engineer role requirements validated");
} }
@@ -495,7 +545,11 @@ Output JSON with:
// Agent prompts aligned with API Platform Engineer role // Agent prompts aligned with API Platform Engineer role
let agent_prompts = vec![ let agent_prompts = vec![
("contract-review", CONTRACT_FIRST_PROMPT, "extraction"), ("contract-review", CONTRACT_FIRST_PROMPT, "extraction"),
("compatibility-check", BACKWARD_COMPATIBILITY_PROMPT, "reasoning"), (
"compatibility-check",
BACKWARD_COMPATIBILITY_PROMPT,
"reasoning",
),
("sdk-generation", SDK_GENERATION_PROMPT, "generation"), ("sdk-generation", SDK_GENERATION_PROMPT, "generation"),
]; ];
@@ -508,7 +562,10 @@ Output JSON with:
}); });
assert!(!prompt["template"].as_str().unwrap().is_empty()); assert!(!prompt["template"].as_str().unwrap().is_empty());
assert!(prompt["template"].as_str().unwrap().contains("{{") || prompt["template"].as_str().unwrap().contains("output")); assert!(
prompt["template"].as_str().unwrap().contains("{{")
|| prompt["template"].as_str().unwrap().contains("output")
);
} }
println!("✓ Agent prompts for API Platform Engineer validated"); println!("✓ Agent prompts for API Platform Engineer validated");
@@ -541,7 +598,10 @@ Output JSON with:
assert_eq!(engineer_prompts.len(), 3); assert_eq!(engineer_prompts.len(), 3);
// Prompts ordered by priority // Prompts ordered by priority
assert!(engineer_prompts[0]["priority"].as_i64().unwrap() < engineer_prompts[1]["priority"].as_i64().unwrap()); assert!(
engineer_prompts[0]["priority"].as_i64().unwrap()
< engineer_prompts[1]["priority"].as_i64().unwrap()
);
println!("✓ Role-to-prompt mapping consistency validated"); println!("✓ Role-to-prompt mapping consistency validated");
} }