Add schema quality checks
Deploy / deploy (push) Successful in 1m36s
CI / Rust Checks (push) Successful in 5m43s
CI / UI Checks (push) Successful in 5s
CI / Deployment Manifests (push) Successful in 2s
CI / Frontend E2E (push) Successful in 4m36s

This commit is contained in:
github-ops
2026-06-20 19:59:55 +00:00
parent 2719c5f7bf
commit d79ec95028
4 changed files with 242 additions and 10 deletions
+44 -7
View File
@@ -12,8 +12,8 @@ use crank_core::{
NoopAuditSink, OperationId, OperationSecurityLevel, OperationStatus, OwnerOnlyPolicyEngine,
PlatformApiKey, PlatformApiKeyId, PlatformApiKeyScope, PlatformApiKeyStatus, PolicyEngine,
ProductEdition, Protocol, ResponseCachePolicy, SampleId, Samples, Secret, SecretId, SecretKind,
SecretStatus, Target, UsagePeriod, UserId, UserSessionId, WizardState, Workspace, WorkspaceId,
WorkspaceStatus,
SecretStatus, Target, ToolQualitySchemaKind, ToolQualitySchemaNode, UsagePeriod, UserId,
UserSessionId, WizardState, Workspace, WorkspaceId, WorkspaceStatus,
};
use crank_mapping::{JsonPathRoot, MappingSet, infer_mapping_from_samples};
use crank_registry::{
@@ -32,7 +32,7 @@ use crank_runtime::{
PreparedRequest, ResolvedAuth, RuntimeError, RuntimeExecutor, RuntimeOperation,
RuntimeRequestContext, SecretCrypto,
};
use crank_schema::Schema;
use crank_schema::{Schema, SchemaKind};
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use sha2::{Digest, Sha256};
@@ -1452,10 +1452,15 @@ impl AdminService {
self.validate_operation_payload(&payload)?;
self.ensure_workspace_exists(workspace_id).await?;
Ok(crank_core::analyze_tool_identity_quality(
&payload.name,
&payload.tool_description,
))
let mut findings =
crank_core::analyze_tool_identity_quality(&payload.name, &payload.tool_description)
.findings;
let input_schema = tool_quality_schema_node(&payload.input_schema);
findings.extend(
crank_core::analyze_tool_schema_quality("input_schema", &input_schema).findings,
);
Ok(crank_core::ToolQualityReport::new(findings))
}
#[instrument(skip(self, payload), fields(operation_id = %operation_id.as_str(), protocol = ?payload.operation.protocol))]
@@ -3795,6 +3800,38 @@ fn validate_response_cache_policy(
Ok(())
}
fn tool_quality_schema_node(schema: &Schema) -> ToolQualitySchemaNode {
ToolQualitySchemaNode {
kind: tool_quality_schema_kind(&schema.kind),
description: schema.description.clone(),
fields: schema
.fields
.iter()
.map(|(name, field)| (name.clone(), tool_quality_schema_node(field)))
.collect(),
items: schema
.items
.as_deref()
.map(tool_quality_schema_node)
.map(Box::new),
enum_values: schema.enum_values.clone(),
}
}
fn tool_quality_schema_kind(kind: &SchemaKind) -> ToolQualitySchemaKind {
match kind {
SchemaKind::Object => ToolQualitySchemaKind::Object,
SchemaKind::Array => ToolQualitySchemaKind::Array,
SchemaKind::String => ToolQualitySchemaKind::String,
SchemaKind::Integer => ToolQualitySchemaKind::Integer,
SchemaKind::Number => ToolQualitySchemaKind::Number,
SchemaKind::Boolean => ToolQualitySchemaKind::Boolean,
SchemaKind::Enum => ToolQualitySchemaKind::Enum,
SchemaKind::Null => ToolQualitySchemaKind::Null,
SchemaKind::Oneof => ToolQualitySchemaKind::Oneof,
}
}
#[cfg(test)]
#[allow(clippy::items_after_test_module)]
mod tests {