统一画布素材类型合同
补齐 Provider Prompt 的 icon-spec 类型 统一 Prompt、原生 schema 与执行校验的素材类型目录 增加权威集合、schema、执行校验和最终请求回归测试
This commit is contained in:
@@ -140,5 +140,5 @@ pub(crate) use tool_plan_protocol::{
|
||||
};
|
||||
pub(crate) use tool_policy_snapshot::{
|
||||
agent_runtime_executable_tools, agent_runtime_native_executable_tools,
|
||||
agent_runtime_tool_policy_snapshot_for_run_at,
|
||||
agent_runtime_tool_policy_snapshot_for_run_at, AGENT_RUNTIME_CANVAS_ASSET_KINDS,
|
||||
};
|
||||
|
||||
+6
-1
File diff suppressed because one or more lines are too long
+16
@@ -1,5 +1,21 @@
|
||||
use super::*;
|
||||
|
||||
pub(crate) const AGENT_RUNTIME_CANVAS_ASSET_KINDS: &[&str] =
|
||||
&["game-art", "icon-spec", "ui-prototype", "art-spritesheet"];
|
||||
|
||||
#[cfg(test)]
|
||||
mod canvas_asset_kind_contract_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn canvas_asset_kind_catalog_preserves_authoritative_contract() {
|
||||
assert_eq!(
|
||||
AGENT_RUNTIME_CANVAS_ASSET_KINDS,
|
||||
&["game-art", "icon-spec", "ui-prototype", "art-spritesheet"]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn agent_runtime_executable_tools() -> Vec<&'static str> {
|
||||
vec![
|
||||
GAME_CREATOR_USER_INPUT_REQUEST_TOOL,
|
||||
|
||||
@@ -14,6 +14,10 @@ pub(crate) const AGENT_RUNTIME_UI_PROTOTYPE_LEGACY_VALIDATION_PROFILE: &str = "u
|
||||
pub(crate) const AGENT_RUNTIME_UI_PROTOTYPE_VALIDATION_PROFILE: &str = "ui-prototype.v2";
|
||||
pub(crate) const AGENT_RUNTIME_ART_SPEC_PATH: &str = "assets/art-spec.png";
|
||||
|
||||
fn agent_runtime_canvas_asset_kind_is_supported(asset_kind: &str) -> bool {
|
||||
AGENT_RUNTIME_CANVAS_ASSET_KINDS.contains(&asset_kind)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub(in crate::agent) struct AgentRuntimeUiPrototypeChecks {
|
||||
@@ -652,10 +656,7 @@ pub(in crate::agent) async fn observe_agent_runtime_platform_art_asset_generatio
|
||||
detail: None,
|
||||
};
|
||||
}
|
||||
if !matches!(
|
||||
options.asset_kind.as_str(),
|
||||
"game-art" | "icon-spec" | "ui-prototype" | "art-spritesheet"
|
||||
) {
|
||||
if !agent_runtime_canvas_asset_kind_is_supported(&options.asset_kind) {
|
||||
return AgentRuntimeToolObservation {
|
||||
tool: "canvas.asset_generate".to_string(),
|
||||
status: "failed".to_string(),
|
||||
@@ -901,6 +902,14 @@ pub(crate) async fn observe_agent_runtime_platform_art_asset_generation_after_di
|
||||
mod platform_art_generation_observation_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn canvas_asset_kind_validation_accepts_shared_catalog() {
|
||||
for asset_kind in AGENT_RUNTIME_CANVAS_ASSET_KINDS {
|
||||
assert!(agent_runtime_canvas_asset_kind_is_supported(asset_kind));
|
||||
}
|
||||
assert!(!agent_runtime_canvas_asset_kind_is_supported("unsupported"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_external_generation_result_requires_runtime_reconciliation() {
|
||||
let root = tempfile::tempdir().expect("create observation status root");
|
||||
|
||||
@@ -12,7 +12,7 @@ use sha2::{Digest, Sha256};
|
||||
use crate::agent::{
|
||||
agent_runtime_native_executable_tools, AgentRuntimePlanUpdate, AgentRuntimeToolAction,
|
||||
AgentRuntimeToolPlan, AGENT_RUNTIME_BACKGROUND_TOOL_ACTION_LIMIT,
|
||||
AGENT_RUNTIME_PLAN_STEP_LIMIT,
|
||||
AGENT_RUNTIME_CANVAS_ASSET_KINDS, AGENT_RUNTIME_PLAN_STEP_LIMIT,
|
||||
};
|
||||
use crate::mcp::{GameCreatorMcpCatalog, GameCreatorMcpCatalogTool, GAME_CREATOR_MCP_CALL_TOOL};
|
||||
|
||||
@@ -1177,20 +1177,27 @@ fn runtime_tool_input_schema(tool: &str) -> Value {
|
||||
"question": { "type": ["string", "null"], "maxLength": 1000 }
|
||||
}
|
||||
}),
|
||||
"canvas.asset_generate" => json!({
|
||||
"type": "object",
|
||||
"required": ["prompt", "outputPath", "aspectRatio", "imageSize", "assetKind", "assetLabel", "replaceExisting"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"prompt": { "type": "string", "minLength": 1, "maxLength": 4000 },
|
||||
"outputPath": { "type": ["string", "null"], "maxLength": 240 },
|
||||
"aspectRatio": { "type": ["string", "null"], "enum": ["1:1", "2:3", "3:2", "9:16", "16:9", null] },
|
||||
"imageSize": { "type": ["string", "null"], "enum": ["0.5K", "1K", "2K", null] },
|
||||
"assetKind": { "type": ["string", "null"], "enum": ["game-art", "icon-spec", "ui-prototype", "art-spritesheet", null] },
|
||||
"assetLabel": { "type": ["string", "null"], "maxLength": 80 },
|
||||
"replaceExisting": { "type": "boolean" }
|
||||
}
|
||||
}),
|
||||
"canvas.asset_generate" => {
|
||||
let mut asset_kinds = AGENT_RUNTIME_CANVAS_ASSET_KINDS
|
||||
.iter()
|
||||
.map(|kind| Value::String((*kind).to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
asset_kinds.push(Value::Null);
|
||||
json!({
|
||||
"type": "object",
|
||||
"required": ["prompt", "outputPath", "aspectRatio", "imageSize", "assetKind", "assetLabel", "replaceExisting"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"prompt": { "type": "string", "minLength": 1, "maxLength": 4000 },
|
||||
"outputPath": { "type": ["string", "null"], "maxLength": 240 },
|
||||
"aspectRatio": { "type": ["string", "null"], "enum": ["1:1", "2:3", "3:2", "9:16", "16:9", null] },
|
||||
"imageSize": { "type": ["string", "null"], "enum": ["0.5K", "1K", "2K", null] },
|
||||
"assetKind": { "type": ["string", "null"], "enum": asset_kinds },
|
||||
"assetLabel": { "type": ["string", "null"], "maxLength": 80 },
|
||||
"replaceExisting": { "type": "boolean" }
|
||||
}
|
||||
})
|
||||
}
|
||||
"blackboard.write" => two_string_input_schema("title", "content"),
|
||||
"agent.message" => two_string_input_schema("agentId", "content"),
|
||||
"agent.delegate" => json!({
|
||||
@@ -1459,6 +1466,21 @@ mod tests {
|
||||
assert!(issues.is_empty(), "{}", issues.join("\n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canvas_asset_generate_schema_uses_shared_asset_kind_catalog() {
|
||||
let schema = runtime_tool_input_schema("canvas.asset_generate");
|
||||
let mut expected = AGENT_RUNTIME_CANVAS_ASSET_KINDS
|
||||
.iter()
|
||||
.map(|kind| Value::String((*kind).to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
expected.push(Value::Null);
|
||||
|
||||
assert_eq!(
|
||||
schema.pointer("/properties/assetKind/enum"),
|
||||
Some(&Value::Array(expected))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn action_function_parameters_rebases_local_schema_refs_after_wrapping() {
|
||||
let parameters = action_function_parameters(json!({
|
||||
|
||||
Reference in New Issue
Block a user