diff --git a/src/agent_tool_specs/data_agent.py b/src/agent_tool_specs/data_agent.py index 56b4377..d31c594 100644 --- a/src/agent_tool_specs/data_agent.py +++ b/src/agent_tool_specs/data_agent.py @@ -254,7 +254,7 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo 'paths': { 'type': 'array', 'items': {'type': 'string'}, - 'description': 'Workspace-relative parquet files or date directories. Use when dates is not enough.', + 'description': 'Parquet files or date directories. Relative paths resolve from workspace root; absolute paths are allowed for external online data.', }, 'max_files': {'type': 'integer', 'minimum': 1, 'maximum': 200}, 'max_rows_per_file': {'type': 'integer', 'minimum': 1, 'maximum': 100000}, @@ -280,7 +280,7 @@ def build_data_agent_tools(handlers: Mapping[str, ToolHandler]) -> list[AgentToo 'paths': { 'type': 'array', 'items': {'type': 'string'}, - 'description': 'Workspace-relative parquet files or date directories. Use when dates is not enough.', + 'description': 'Parquet files or date directories. Relative paths resolve from workspace root; absolute paths are allowed for external online data.', }, 'devices': {'type': 'array', 'items': {'type': 'string'}}, 'domains': {'type': 'array', 'items': {'type': 'string'}}, diff --git a/src/data_agent_router_sessions.py b/src/data_agent_router_sessions.py index e9b045e..45d6adf 100644 --- a/src/data_agent_router_sessions.py +++ b/src/data_agent_router_sessions.py @@ -278,10 +278,6 @@ def _resolve_parquet_files( files: list[Path] = [] for path in requested: resolved = path.resolve() - try: - resolved.relative_to(root_path) - except ValueError as exc: - raise DataAgentRouterSessionError(f'path escapes workspace root: {path}') from exc if not resolved.exists(): raise DataAgentRouterSessionError(f'path not found: {path}') if resolved.is_dir(): diff --git a/tests/test_data_agent_router_sessions.py b/tests/test_data_agent_router_sessions.py index a108f8d..655af90 100644 --- a/tests/test_data_agent_router_sessions.py +++ b/tests/test_data_agent_router_sessions.py @@ -123,6 +123,29 @@ class DataAgentRouterSessionTests(unittest.TestCase): self.assertEqual(candidate['matched_turn']['query'], '导航去公司') self.assertEqual(candidate['prev_turns'][0]['query'], '你好小爱') + @unittest.skipUnless(HAS_PYARROW, 'pyarrow is required for parquet tests') + def test_router_session_tools_allow_external_absolute_paths(self) -> None: + with tempfile.TemporaryDirectory() as workspace_dir, tempfile.TemporaryDirectory() as data_dir: + _write_router_parquet(Path(data_dir)) + external_partition = Path(data_dir) / 'router_session_parquet' / 'date=20260428' + + profile = profile_router_sessions( + workspace_dir, + paths=[str(external_partition)], + max_files=1, + ) + search = search_router_sessions( + workspace_dir, + paths=[str(external_partition)], + query_keywords=['导航'], + max_files=1, + max_candidates=5, + ) + + self.assertEqual(profile['sampled_row_count'], 2) + self.assertEqual(search['candidate_count'], 1) + self.assertEqual(search['candidates'][0]['matched_turn']['query'], '导航去公司') + @unittest.skipUnless(HAS_PYARROW, 'pyarrow is required for parquet tests') def test_router_session_tools_execute_against_registry(self) -> None: with tempfile.TemporaryDirectory() as tmp_dir: