Avoid top-level composition in tool schemas
This commit is contained in:
@@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"records": {"type": "array"},
|
"records": {
|
||||||
"records_path": {"type": "string"},
|
"type": "array",
|
||||||
|
"description": "Canonical records. Provide exactly one of records or records_path."
|
||||||
|
},
|
||||||
|
"records_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to records JSON/JSONL. Provide exactly one of records or records_path."
|
||||||
|
},
|
||||||
"output_path": {"type": "string"},
|
"output_path": {"type": "string"},
|
||||||
"output_dir": {"type": "string"},
|
"output_dir": {"type": "string"},
|
||||||
"output_format": {
|
"output_format": {
|
||||||
@@ -13,9 +19,5 @@
|
|||||||
"require_validation_ok": {"type": "boolean", "default": true},
|
"require_validation_ok": {"type": "boolean", "default": true},
|
||||||
"overwrite": {"type": "boolean", "default": true},
|
"overwrite": {"type": "boolean", "default": true},
|
||||||
"export_table": {"type": "boolean", "default": true}
|
"export_table": {"type": "boolean", "default": true}
|
||||||
},
|
}
|
||||||
"anyOf": [
|
|
||||||
{"required": ["records"]},
|
|
||||||
{"required": ["records_path"]}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"records": {"type": "array"},
|
"records": {
|
||||||
"records_path": {"type": "string"},
|
"type": "array",
|
||||||
|
"description": "Canonical records. Provide exactly one of records or records_path."
|
||||||
|
},
|
||||||
|
"records_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to records JSON/JSONL. Provide exactly one of records or records_path."
|
||||||
|
},
|
||||||
"output_path": {"type": "string"},
|
"output_path": {"type": "string"},
|
||||||
"output_dir": {"type": "string"},
|
"output_dir": {"type": "string"},
|
||||||
"require_validation_ok": {"type": "boolean", "default": true},
|
"require_validation_ok": {"type": "boolean", "default": true},
|
||||||
"overwrite": {"type": "boolean", "default": true}
|
"overwrite": {"type": "boolean", "default": true}
|
||||||
},
|
}
|
||||||
"anyOf": [
|
|
||||||
{"required": ["records"]},
|
|
||||||
{"required": ["records_path"]}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"draft_text": {"type": "string"},
|
"draft_text": {
|
||||||
"draft_path": {"type": "string"},
|
"type": "string",
|
||||||
|
"description": "Dataset draft text. Provide exactly one of draft_text or draft_path."
|
||||||
|
},
|
||||||
|
"draft_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to UTF-8 dataset draft text. Provide exactly one of draft_text or draft_path."
|
||||||
|
},
|
||||||
"batch_id": {"type": "string", "default": "aabbccdd"},
|
"batch_id": {"type": "string", "default": "aabbccdd"},
|
||||||
"source_type": {
|
"source_type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -12,9 +18,5 @@
|
|||||||
"base_timestamp": {"type": "integer"},
|
"base_timestamp": {"type": "integer"},
|
||||||
"timestamp_step_ms": {"type": "integer", "minimum": 1, "default": 60000},
|
"timestamp_step_ms": {"type": "integer", "minimum": 1, "default": 60000},
|
||||||
"default_request_id": {"type": "string", "default": "aabbccdd"}
|
"default_request_id": {"type": "string", "default": "aabbccdd"}
|
||||||
},
|
}
|
||||||
"anyOf": [
|
|
||||||
{"required": ["draft_text"]},
|
|
||||||
{"required": ["draft_path"]}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"records": {"type": "array"},
|
"records": {
|
||||||
"records_path": {"type": "string"}
|
"type": "array",
|
||||||
},
|
"description": "Canonical records. Provide exactly one of records or records_path."
|
||||||
"anyOf": [
|
},
|
||||||
{"required": ["records"]},
|
"records_path": {
|
||||||
{"required": ["records_path"]}
|
"type": "string",
|
||||||
]
|
"description": "Path to records JSON/JSONL. Provide exactly one of records or records_path."
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -437,11 +437,11 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
|
|||||||
'properties': {
|
'properties': {
|
||||||
'draft_text': {
|
'draft_text': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'description': 'Dataset draft text in dataset draft text v1 format.',
|
'description': 'Dataset draft text in dataset draft text v1 format. Provide exactly one of draft_text or draft_path.',
|
||||||
},
|
},
|
||||||
'draft_path': {
|
'draft_path': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'description': 'Path to a UTF-8 dataset draft text file. Prefer this for large drafts.',
|
'description': 'Path to a UTF-8 dataset draft text file. Prefer this for large drafts. Provide exactly one of draft_text or draft_path.',
|
||||||
},
|
},
|
||||||
'batch_id': {
|
'batch_id': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
@@ -469,10 +469,6 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
|
|||||||
'description': 'Required for generated data; returned by data_agent_confirm_generation_plan.',
|
'description': 'Required for generated data; returned by data_agent_confirm_generation_plan.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'anyOf': [
|
|
||||||
{'required': ['draft_text']},
|
|
||||||
{'required': ['draft_path']},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
handler=resolve_handler(handlers, 'data_agent_normalize_dataset_draft', 'data-agent'),
|
handler=resolve_handler(handlers, 'data_agent_normalize_dataset_draft', 'data-agent'),
|
||||||
),
|
),
|
||||||
@@ -490,17 +486,13 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
|
|||||||
{'type': 'array'},
|
{'type': 'array'},
|
||||||
{'type': 'string'},
|
{'type': 'string'},
|
||||||
],
|
],
|
||||||
'description': 'Canonical records as an array, or a JSON string containing the array.',
|
'description': 'Canonical records as an array, or a JSON string containing the array. Provide exactly one of records or records_path.',
|
||||||
},
|
},
|
||||||
'records_path': {
|
'records_path': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'description': 'Path to records JSON/JSONL. Prefer this when records are large.',
|
'description': 'Path to records JSON/JSONL. Prefer this when records are large. Provide exactly one of records or records_path.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'anyOf': [
|
|
||||||
{'required': ['records']},
|
|
||||||
{'required': ['records_path']},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
handler=resolve_handler(handlers, 'data_agent_validate_dataset_records', 'data-agent'),
|
handler=resolve_handler(handlers, 'data_agent_validate_dataset_records', 'data-agent'),
|
||||||
),
|
),
|
||||||
@@ -519,11 +511,11 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
|
|||||||
{'type': 'array'},
|
{'type': 'array'},
|
||||||
{'type': 'string'},
|
{'type': 'string'},
|
||||||
],
|
],
|
||||||
'description': 'Canonical records as an array, or a JSON string containing the array.',
|
'description': 'Canonical records as an array, or a JSON string containing the array. Provide exactly one of records or records_path.',
|
||||||
},
|
},
|
||||||
'records_path': {
|
'records_path': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'description': 'Path to records JSON/JSONL. Prefer this when records are large.',
|
'description': 'Path to records JSON/JSONL. Prefer this when records are large. Provide exactly one of records or records_path.',
|
||||||
},
|
},
|
||||||
'output_path': {
|
'output_path': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
@@ -552,10 +544,6 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
'required': ['output_path'],
|
'required': ['output_path'],
|
||||||
'anyOf': [
|
|
||||||
{'required': ['records']},
|
|
||||||
{'required': ['records_path']},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
handler=resolve_handler(handlers, 'data_agent_export_dataset_records', 'data-agent'),
|
handler=resolve_handler(handlers, 'data_agent_export_dataset_records', 'data-agent'),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -647,6 +647,17 @@ target: Agent(tag='地图导航')
|
|||||||
self.assertEqual(export_payload['record_count'], 1)
|
self.assertEqual(export_payload['record_count'], 1)
|
||||||
self.assertTrue(table_exists)
|
self.assertTrue(table_exists)
|
||||||
|
|
||||||
|
def test_tool_schemas_avoid_top_level_composition_keywords(self) -> None:
|
||||||
|
# 部分 Bedrock/Anthropic 兼容后端不接受顶层 anyOf/oneOf/allOf。
|
||||||
|
blocked_keywords = {'anyOf', 'oneOf', 'allOf'}
|
||||||
|
violations = [
|
||||||
|
name
|
||||||
|
for name, tool in default_tool_registry().items()
|
||||||
|
if blocked_keywords.intersection(tool.parameters)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.assertEqual(violations, [])
|
||||||
|
|
||||||
def test_data_agent_tools_route_relative_outputs_to_session_output(self) -> None:
|
def test_data_agent_tools_route_relative_outputs_to_session_output(self) -> None:
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
root = Path(tmp_dir)
|
root = Path(tmp_dir)
|
||||||
|
|||||||
Reference in New Issue
Block a user