Stabilize product data export flow
This commit is contained in:
+61
-7
@@ -1474,7 +1474,7 @@ def _data_agent_confirm_generation_plan_tool(arguments: dict[str, Any], context:
|
||||
|
||||
|
||||
def _normalize_dataset_draft_tool(arguments: dict[str, Any], _context: ToolExecutionContext) -> str:
|
||||
draft_text = _require_string(arguments, 'draft_text')
|
||||
draft_text = _draft_text_from_arguments(arguments, _context)
|
||||
batch_id = arguments.get('batch_id', 'aabbccdd')
|
||||
if not isinstance(batch_id, str) or not batch_id.strip():
|
||||
raise ToolExecutionError('batch_id must be a non-empty string')
|
||||
@@ -1508,10 +1508,8 @@ def _normalize_dataset_draft_tool(arguments: dict[str, Any], _context: ToolExecu
|
||||
|
||||
|
||||
def _validate_dataset_records_tool(arguments: dict[str, Any], _context: ToolExecutionContext) -> str:
|
||||
if 'records' not in arguments:
|
||||
raise ToolExecutionError('records is required')
|
||||
try:
|
||||
records = records_from_tool_argument(arguments['records'])
|
||||
records = _records_from_arguments(arguments, _context)
|
||||
payload = validate_dataset_records(records)
|
||||
except (DataRecordError, json.JSONDecodeError) as exc:
|
||||
raise ToolExecutionError(str(exc)) from exc
|
||||
@@ -1519,8 +1517,6 @@ def _validate_dataset_records_tool(arguments: dict[str, Any], _context: ToolExec
|
||||
|
||||
|
||||
def _export_dataset_records_tool(arguments: dict[str, Any], context: ToolExecutionContext) -> str:
|
||||
if 'records' not in arguments:
|
||||
raise ToolExecutionError('records is required')
|
||||
output_format = arguments.get('output_format', 'jsonl')
|
||||
if not isinstance(output_format, str):
|
||||
raise ToolExecutionError('output_format must be a string')
|
||||
@@ -1530,8 +1526,11 @@ def _export_dataset_records_tool(arguments: dict[str, Any], context: ToolExecuti
|
||||
overwrite = arguments.get('overwrite', True)
|
||||
if not isinstance(overwrite, bool):
|
||||
raise ToolExecutionError('overwrite must be a boolean')
|
||||
export_table = arguments.get('export_table', True)
|
||||
if not isinstance(export_table, bool):
|
||||
raise ToolExecutionError('export_table must be a boolean')
|
||||
try:
|
||||
records = records_from_tool_argument(arguments['records'])
|
||||
records = _records_from_arguments(arguments, context)
|
||||
canonical_filename = 'records.json' if output_format == 'json' else 'records.jsonl'
|
||||
payload = export_dataset_records(
|
||||
records,
|
||||
@@ -1544,12 +1543,67 @@ def _export_dataset_records_tool(arguments: dict[str, Any], context: ToolExecuti
|
||||
output_format=output_format,
|
||||
require_validation_ok=require_validation_ok,
|
||||
overwrite=overwrite,
|
||||
export_table=export_table,
|
||||
)
|
||||
except (DataRecordError, json.JSONDecodeError) as exc:
|
||||
raise ToolExecutionError(str(exc)) from exc
|
||||
return json.dumps(payload, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def _draft_text_from_arguments(arguments: dict[str, Any], context: ToolExecutionContext) -> str:
|
||||
draft_text = arguments.get('draft_text')
|
||||
draft_path = arguments.get('draft_path')
|
||||
has_text = isinstance(draft_text, str) and bool(draft_text.strip())
|
||||
has_path = isinstance(draft_path, str) and bool(draft_path.strip())
|
||||
if has_text and has_path:
|
||||
raise ToolExecutionError('provide only one of draft_text or draft_path')
|
||||
if has_text:
|
||||
return draft_text
|
||||
if not has_path:
|
||||
raise ToolExecutionError('draft_text or draft_path is required')
|
||||
path = _resolve_path(draft_path, context, allow_missing=False, allow_outside_root=True)
|
||||
if not path.is_file():
|
||||
raise ToolExecutionError(f'draft_path is not a file: {path}')
|
||||
return path.read_text(encoding='utf-8', errors='replace')
|
||||
|
||||
|
||||
def _records_from_arguments(arguments: dict[str, Any], context: ToolExecutionContext) -> list[dict[str, Any]]:
|
||||
has_records = 'records' in arguments and arguments.get('records') is not None
|
||||
records_path = arguments.get('records_path')
|
||||
has_path = isinstance(records_path, str) and bool(records_path.strip())
|
||||
if has_records and has_path:
|
||||
raise ToolExecutionError('provide only one of records or records_path')
|
||||
if has_records:
|
||||
return records_from_tool_argument(arguments['records'])
|
||||
if not has_path:
|
||||
raise ToolExecutionError('records or records_path is required')
|
||||
path = _resolve_path(records_path, context, allow_missing=False, allow_outside_root=True)
|
||||
if not path.is_file():
|
||||
raise ToolExecutionError(f'records_path is not a file: {path}')
|
||||
return _records_from_file(path)
|
||||
|
||||
|
||||
def _records_from_file(path: Path) -> list[dict[str, Any]]:
|
||||
text = path.read_text(encoding='utf-8', errors='replace').strip()
|
||||
if not text:
|
||||
raise DataRecordError('records_path is empty')
|
||||
if path.suffix == '.jsonl':
|
||||
records: list[dict[str, Any]] = []
|
||||
for line_number, line in enumerate(text.splitlines(), start=1):
|
||||
stripped = line.strip()
|
||||
if not stripped:
|
||||
continue
|
||||
item = json.loads(stripped)
|
||||
if not isinstance(item, dict):
|
||||
raise DataRecordError(f'records_path line {line_number} must decode to an object')
|
||||
records.append(item)
|
||||
return records_from_tool_argument(records)
|
||||
payload = json.loads(text)
|
||||
if isinstance(payload, dict) and isinstance(payload.get('records'), list):
|
||||
payload = payload['records']
|
||||
return records_from_tool_argument(payload)
|
||||
|
||||
|
||||
def _data_agent_output_path(
|
||||
output_path: str,
|
||||
context: ToolExecutionContext,
|
||||
|
||||
Reference in New Issue
Block a user