#![allow(dead_code, unused_imports)] use std::collections::BTreeMap; use crank_core::{ AgentId, AgentOperationBinding, AgentStatus, AgentVersion, ApiKeyHeaderAuthConfig, AuthConfig, AuthKind, AuthProfile, ConfigExport, ExecutionConfig, ExportMode, GeneratedDraft, GeneratedDraftStatus, HttpMethod, InvocationLog, MembershipRole, OperationId, OperationSecurityLevel, OperationStatus, PlatformApiKey, PlatformApiKeyId, PlatformApiKeyScope, PlatformApiKeyStatus, Protocol, RestTarget, RetryPolicy, Samples, SecretId, Target, ToolDescription, ToolExample, User, UserId, UserSessionId, WizardState, Workspace, WorkspaceId, }; use crank_mapping::{MappingRule, MappingSet}; use crank_schema::{Schema, SchemaKind}; use serde_json::json; use sqlx::{Executor, PgPool, postgres::PgPoolOptions}; use time::{OffsetDateTime, format_description::well_known::Rfc3339}; use crank_registry::{ CreateAgentRequest, CreateInvocationLogRequest, CreatePlatformApiKeyRequest, CreateVersionRequest, CreateWorkspaceRequest, CreateYamlImportJobRequest, DescriptorKind, DescriptorMetadata, OperationSampleMetadata, PlatformApiKeyRecord, PostgresRegistry, PublishAgentRequest, PublishRequest, RegistryError, RegistryOperation, SampleKind, SaveAuthProfileRequest, SaveDescriptorMetadataRequest, SaveSampleMetadataRequest, WorkspaceRecord, YamlImportJobCompletion, YamlImportJobId, YamlImportJobStatus, }; fn test_workspace_id() -> WorkspaceId { WorkspaceId::new("ws_default") } fn timestamp(value: &str) -> OffsetDateTime { OffsetDateTime::parse(value, &Rfc3339).unwrap() } pub(super) fn test_operation(id: &str, version: u32, status: OperationStatus) -> RegistryOperation { RegistryOperation { id: OperationId::new(id), name: format!("{id}_tool"), display_name: format!("Display {id}"), category: "general".to_owned(), protocol: Protocol::Rest, security_level: OperationSecurityLevel::Standard, status, version, target: Target::Rest(RestTarget { base_url: "https://api.example.com".to_owned(), method: HttpMethod::Post, path_template: "/v1/leads".to_owned(), static_headers: BTreeMap::from([("X-Static".to_owned(), "true".to_owned())]), }), input_schema: Schema { kind: SchemaKind::Object, description: Some("input".to_owned()), required: true, nullable: false, default_value: None, fields: BTreeMap::from([( "email".to_owned(), Schema { kind: SchemaKind::String, description: None, required: true, nullable: false, default_value: None, fields: BTreeMap::new(), items: None, enum_values: Vec::new(), variants: Vec::new(), }, )]), items: None, enum_values: Vec::new(), variants: Vec::new(), }, output_schema: Schema { kind: SchemaKind::Object, description: Some("output".to_owned()), required: true, nullable: false, default_value: None, fields: BTreeMap::from([( "id".to_owned(), Schema { kind: SchemaKind::String, description: None, required: true, nullable: false, default_value: None, fields: BTreeMap::new(), items: None, enum_values: Vec::new(), variants: Vec::new(), }, )]), items: None, enum_values: Vec::new(), variants: Vec::new(), }, input_mapping: MappingSet { rules: vec![MappingRule { source: "$.mcp.email".to_owned(), target: "$.request.body.email".to_owned(), required: true, default_value: None, transform: None, condition: None, notes: None, }], }, output_mapping: MappingSet { rules: vec![MappingRule { source: "$.response.body.id".to_owned(), target: "$.output.id".to_owned(), required: true, default_value: None, transform: None, condition: None, notes: None, }], }, execution_config: ExecutionConfig { timeout_ms: 10_000, retry_policy: Some(RetryPolicy { max_attempts: 3 }), auth_profile_ref: Some("auth_crank".into()), headers: BTreeMap::from([("X-Request-Id".to_owned(), "static".to_owned())]), ..ExecutionConfig::default() }, tool_description: ToolDescription { title: "Create lead".to_owned(), description: "Creates CRM lead".to_owned(), tags: vec!["crm".to_owned()], examples: vec![ToolExample { input: json!({ "email": "a@example.com" }), }], }, samples: Some(Samples { input_json_sample_ref: Some("sample_input".into()), output_json_sample_ref: Some("sample_output".into()), }), generated_draft: Some(GeneratedDraft { status: GeneratedDraftStatus::Available, source_types: vec!["input_json".to_owned(), "output_json".to_owned()], generated_at: Some("2026-03-25T11:59:00Z".to_owned()), input_schema_generated: true, output_schema_generated: true, input_mapping_generated: true, output_mapping_generated: true, warnings: Vec::new(), }), config_export: Some(ConfigExport { format_version: "v1".to_owned(), export_mode: ExportMode::Portable, }), wizard_state: Some(WizardState { input_sample: Some(json!({ "email": format!("lead-{version}@example.com") })), output_sample: Some(json!({ "id": format!("lead_{version}") })), test_input: Some(json!({ "email": format!("test-v{version}@example.com") })), }), created_at: timestamp("2026-03-25T11:58:00Z"), updated_at: timestamp(&format!("2026-03-25T12:{version:02}:00Z")), published_at: None, } } pub(super) fn test_agent(id: &str, status: AgentStatus) -> crank_core::Agent { crank_core::Agent { id: AgentId::new(id), workspace_id: test_workspace_id(), slug: format!("{id}_slug"), display_name: format!("Display {id}"), description: format!("Description {id}"), status, current_draft_version: 1, latest_published_version: None, created_at: timestamp("2026-03-25T11:58:00Z"), updated_at: timestamp("2026-03-25T12:00:00Z"), published_at: None, } } pub(super) fn test_agent_version( agent_id: &AgentId, version: u32, status: AgentStatus, ) -> AgentVersion { AgentVersion { agent_id: agent_id.clone(), version, status, instructions: json!({ "system": "triage tickets", "guardrails": ["don't mutate state"] }), tool_selection_policy: json!({ "mode": "allow_list", "max_tools": 8 }), created_at: timestamp("2026-03-25T12:00:00Z"), } } pub(super) fn test_invocation_log( id: &str, operation_id: &OperationId, agent_id: Option, status: crank_core::InvocationStatus, duration_ms: u64, created_at: &str, ) -> InvocationLog { InvocationLog { id: crank_core::InvocationLogId::new(id), workspace_id: test_workspace_id(), agent_id, operation_id: operation_id.clone(), source: crank_core::InvocationSource::AgentToolCall, level: crank_core::InvocationLevel::Info, status, tool_name: "create_lead".to_owned(), message: "invocation".to_owned(), request_id: Some(format!("req_{id}")), status_code: Some(200), duration_ms, error_kind: None, request_preview: json!({"input":"value"}), response_preview: json!({"ok":true}), created_at: timestamp(created_at), } } pub(super) struct TestDatabase { admin_pool: PgPool, database_url: String, schema: String, } impl TestDatabase { pub(super) async fn new() -> Self { let database_url = crank_test_support::postgres_database_url().await.to_owned(); let admin_pool = PgPoolOptions::new() .max_connections(1) .connect(&database_url) .await .unwrap(); let schema = crank_test_support::unique_schema_name("test_registry"); admin_pool .execute(sqlx::query(&format!("create schema {schema}"))) .await .unwrap(); Self { admin_pool, database_url, schema, } } pub(super) async fn registry(&self) -> PostgresRegistry { PostgresRegistry::connect(&format!( "{}?options=-csearch_path%3D{}", self.database_url, self.schema )) .await .unwrap() } pub(super) async fn cleanup(&self) { self.admin_pool .execute(sqlx::query(&format!( "drop schema if exists {} cascade", self.schema ))) .await .unwrap(); } }