diff --git a/CHANGELOG.md b/CHANGELOG.md index e75d8907..f40fd167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog ## [Unreleased] +### Added + +- Analysis sandbox supports `open()` and `with` blocks for reading document files, including `.read()`, `.readline()`, and `.readlines()`. + ### Changed - Require `pydantic-ai-slim>=2.18,<3`. diff --git a/haiku_rag_slim/haiku/rag/capabilities/instructions/analysis.md b/haiku_rag_slim/haiku/rag/capabilities/instructions/analysis.md index 92cbf702..fb4b00a8 100644 --- a/haiku_rag_slim/haiku/rag/capabilities/instructions/analysis.md +++ b/haiku_rag_slim/haiku/rag/capabilities/instructions/analysis.md @@ -17,7 +17,7 @@ Inside the code, these functions are available (use `await`): - `await list_documents()` → list of dicts with keys: id, title, uri, created_at Available modules: `json`, `re`, `math`, `pathlib` -Not supported: class definitions, generators/yield, match statements, decorators, `with` statements +Not supported: class definitions, generators/yield, match statements, decorators, `collections` ### analysis_search Search the knowledge base directly (outside code execution). Each result has a `Type:` (paragraph, table, code, list_item, picture). When the Type is `picture`, the corresponding figure may also be attached to the tool response as an image alongside the text — use it directly to answer questions about figures, diagrams, charts, screenshots. @@ -48,7 +48,7 @@ All documents are mounted as a virtual filesystem at `/documents/`: `{document_id}` is an internal identifier, not the user-facing `uri` (filename, URL, etc.). When you only know a document by its URI or title, use `await list_documents()` to enumerate ids and match against `uri` / `title` — that's a single call to the host. Iterating `/documents/` and reading every `metadata.json` works too but is much slower on portal-scale corpora. ### Reading files -Always use `Path.read_text()` — do NOT use `open()` or `with` statements (they are not supported). +Read with `Path.read_text()` or `open()` (including `with` blocks); file objects support `.read()`, `.readline()`, and `.readlines()`. File objects are NOT iterable — do not write `for line in f`; use `.readlines()` or `text.split(chr(10))` for line-wise processing. Files are read-only; writing raises `PermissionError`. ```python from pathlib import Path @@ -112,6 +112,6 @@ You MUST call `analysis_cite` with at least one chunk ID before producing your f - Use `print()` to output results — the output is your only feedback - When you write code, execute it — don't describe what code would do. But not every question needs code; simple lookups are best answered by `analysis_search → analysis_cite`. - Use `await` for all async functions inside `analysis_execute_code` (`search`, `list_documents`) -- Use `Path.read_text()` to read files — do NOT use `open()`, `with` statements, or `collections` module +- Read files with `Path.read_text()` or `open()`/`with`; file objects are not iterable (no `for line in f`) and the `collections` module is unavailable - Do NOT include chunk IDs or UUIDs in your answer text — your answer should read naturally. Use the `analysis_cite` tool separately to register citations. `cite{...}` markdown-style inline references do nothing; only an actual `analysis_cite` tool call registers a citation. - **Before you write your final answer, invoke the `analysis_cite` tool with the supporting chunk_ids.** This is the last tool call before answering whenever your answer draws on retrieved evidence. diff --git a/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_read.yaml b/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_read.yaml new file mode 100644 index 00000000..67dccd0c --- /dev/null +++ b/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_read.yaml @@ -0,0 +1,42 @@ +interactions: +- request: + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + content-length: + - '99' + content-type: + - application/json + host: + - localhost:11434 + method: POST + parsed_body: + encoding_format: base64 + input: + - Content about foxes and dogs. + model: qwen3-embedding:4b + uri: http://localhost:11434/v1/embeddings + response: + headers: + content-type: + - application/json + transfer-encoding: + - chunked + parsed_body: + data: + - embedding: 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 + index: 0 + object: embedding + model: qwen3-embedding:4b + object: list + usage: + prompt_tokens: 8 + total_tokens: 8 + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_readlines.yaml b/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_readlines.yaml new file mode 100644 index 00000000..634000ab --- /dev/null +++ b/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_readlines.yaml @@ -0,0 +1,42 @@ +interactions: +- request: + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + content-length: + - '114' + content-type: + - application/json + host: + - localhost:11434 + method: POST + parsed_body: + encoding_format: base64 + input: + - The quick brown fox jumps over the lazy dog. + model: qwen3-embedding:4b + uri: http://localhost:11434/v1/embeddings + response: + headers: + content-type: + - application/json + transfer-encoding: + - chunked + parsed_body: + data: + - embedding: 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 + index: 0 + object: embedding + model: qwen3-embedding:4b + object: list + usage: + prompt_tokens: 11 + total_tokens: 11 + status: + code: 200 + message: OK +version: 1 diff --git a/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_write_denied.yaml b/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_write_denied.yaml new file mode 100644 index 00000000..67dccd0c --- /dev/null +++ b/tests/cassettes/test_sandbox/TestSandboxVFS.test_open_write_denied.yaml @@ -0,0 +1,42 @@ +interactions: +- request: + headers: + accept: + - application/json + accept-encoding: + - gzip, deflate, zstd + connection: + - keep-alive + content-length: + - '99' + content-type: + - application/json + host: + - localhost:11434 + method: POST + parsed_body: + encoding_format: base64 + input: + - Content about foxes and dogs. + model: qwen3-embedding:4b + uri: http://localhost:11434/v1/embeddings + response: + headers: + content-type: + - application/json + transfer-encoding: + - chunked + parsed_body: + data: + - embedding: 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 + index: 0 + object: embedding + model: qwen3-embedding:4b + object: list + usage: + prompt_tokens: 8 + total_tokens: 8 + status: + code: 200 + message: OK +version: 1 diff --git a/tests/sandbox/test_sandbox.py b/tests/sandbox/test_sandbox.py index 7f65ce43..27c4fa5c 100644 --- a/tests/sandbox/test_sandbox.py +++ b/tests/sandbox/test_sandbox.py @@ -383,6 +383,77 @@ class TestSandboxVFS: assert result.success assert result.stdout.count("True") == 6 + @pytest.mark.asyncio + @pytest.mark.vcr() + async def test_open_read(self, temp_db_path): + """open() and a with-block read document files through the VFS.""" + config = AppConfig() + async with HaikuRAG(temp_db_path, create=True) as client: + doc = await client.create_document( + content="Content about foxes and dogs.", + uri="test://doc", + title="Fox Document", + ) + + context = AnalysisContext() + sb = Sandbox(db_path=temp_db_path, config=config, context=context) + result = await sb.execute( + f"with open('/documents/{doc.id}/content.txt') as f:\n" + " data = f.read()\n" + "print('foxes' in data.lower())" + ) + assert result.success + assert "True" in result.stdout + + @pytest.mark.asyncio + @pytest.mark.vcr() + async def test_open_readlines(self, temp_db_path): + """readlines() splits a newline-delimited VFS file into lines.""" + config = AppConfig() + async with HaikuRAG(temp_db_path, create=True) as client: + doc = await client.create_document( + content="The quick brown fox jumps over the lazy dog.", + uri="test://animals", + title="Animals", + ) + + context = AnalysisContext() + sb = Sandbox(db_path=temp_db_path, config=config, context=context) + result = await sb.execute( + f"lines = open('/documents/{doc.id}/items.jsonl').readlines()\n" + "print(len(lines) > 0)\n" + "import json\n" + "print('self_ref' in json.loads(lines[0]))" + ) + assert result.success + assert result.stdout.count("True") == 2 + + @pytest.mark.asyncio + @pytest.mark.vcr() + async def test_open_write_denied(self, temp_db_path): + """Opening a document file for writing raises PermissionError.""" + config = AppConfig() + async with HaikuRAG(temp_db_path, create=True) as client: + doc = await client.create_document( + content="Content about foxes and dogs.", + uri="test://doc", + title="Fox Document", + ) + + context = AnalysisContext() + sb = Sandbox(db_path=temp_db_path, config=config, context=context) + result = await sb.execute( + "try:\n" + f" with open('/documents/{doc.id}/content.txt', 'w') as f:\n" + " f.write('nope')\n" + " print('WROTE')\n" + "except PermissionError:\n" + " print('DENIED')" + ) + assert result.success + assert "DENIED" in result.stdout + assert "WROTE" not in result.stdout + @pytest.mark.asyncio @pytest.mark.vcr() async def test_context_filter_limits_vfs(self, temp_db_path):