Merge pull request #308 from ggozad/feat/rlm-monty-update

RLM monty update.
This commit is contained in:
Yiorgis Gozadinos 2026-03-13 11:23:39 +02:00 committed by GitHub
commit b09b45e8fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 2805 additions and 4690 deletions

View file

@ -1,6 +1,10 @@
# Changelog
## [Unreleased]
### Changed
- **RLM sandbox**: Bumped pydantic-monty to 0.0.8. Removed `regex_*` external functions — the sandbox now has native `re` and `math` modules via `import`. Also adds `filter()` and `getattr()` builtins.
## [0.33.3] - 2026-03-12
### Added

View file

@ -64,15 +64,14 @@ The agent's code runs in a sandboxed Python interpreter ([pydantic-monty](https:
| `get_chunk(chunk_id)` | Get a chunk with metadata (headings, page numbers, labels) for citations |
| `get_docling_document(document_id)` | Get the full DoclingDocument structure as a dict (texts, tables, pictures, pages) |
| `llm(prompt)` | Call an LLM for classification, summarization, or extraction |
| `regex_findall(pattern, text)`, `regex_sub(pattern, repl, text)`, `regex_search(pattern, text)`, `regex_split(pattern, text)` | Regular expression matching via Python's `re` module |
When documents are pre-loaded via the `documents` parameter, they are injected as a `documents` variable accessible in the sandbox code.
### Python Features
The interpreter supports a subset of Python: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, try/except, and the `json` module.
The interpreter supports a subset of Python: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `filter()`, `getattr()`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements. For pattern matching, the agent can use the `regex_*` functions, string methods, or the `llm()` function.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements. For pattern matching, the agent can use `import re`, string methods, or the `llm()` function.
### Security
@ -80,7 +79,7 @@ Code executes in an isolated interpreter with:
- **No filesystem access**: Code cannot read or write files
- **No network access**: Code cannot make HTTP requests or open sockets
- **No imports**: Only the `json` module is available
- **No imports**: Only `json`, `re`, and `math` modules are available
- **Execution timeout**: Configurable limit (default 60s)
- **Output truncation**: Large outputs are truncated to prevent memory issues

View file

@ -34,18 +34,6 @@ Use `list_documents()` or search results to get document IDs first.
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -63,11 +51,11 @@ Check if it exists with: `try: documents ... except NameError: ...`
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -93,10 +81,11 @@ print(f"Total: {count}")
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\\$([\\d,]+)', r['content'])
amounts = re.findall(r'\\$([\\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:

View file

@ -1,5 +1,4 @@
import json
import re
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Literal
@ -128,26 +127,6 @@ class Sandbox:
result = await agent.run(prompt)
return result.output
async def regex_findall(pattern: str, text: str) -> list[str]:
return re.findall(pattern, text)
async def regex_sub(pattern: str, repl: str, text: str) -> str:
return re.sub(pattern, repl, text)
async def regex_search(pattern: str, text: str) -> dict[str, Any] | None:
m = re.search(pattern, text)
if m is None:
return None
return {
"group": m.group(),
"groups": list(m.groups()),
"start": m.start(),
"end": m.end(),
}
async def regex_split(pattern: str, text: str) -> list[str]:
return re.split(pattern, text)
return {
"search": search,
"list_documents": list_documents,
@ -155,10 +134,6 @@ class Sandbox:
"get_chunk": get_chunk,
"get_docling_document": get_docling_document,
"llm": llm,
"regex_findall": regex_findall,
"regex_sub": regex_sub,
"regex_search": regex_search,
"regex_split": regex_split,
}
async def execute(self, code: str) -> SandboxResult:
@ -185,7 +160,6 @@ class Sandbox:
monty = pydantic_monty.Monty(
code,
inputs=input_names,
external_functions=list(external_fns.keys()),
)
except (
pydantic_monty.MontySyntaxError,

View file

@ -31,7 +31,7 @@ dependencies = [
"pathspec>=1.0.4",
"pydantic>=2.12.5",
"pydantic-ai-slim[openai,fastmcp,logfire,ag-ui]>=1.66.0",
"pydantic-monty>=0.0.7",
"pydantic-monty>=0.0.8",
"python-dotenv>=1.2.2",
"pyyaml>=6.0.3",
"rich>=14.3.3",

View file

@ -381,70 +381,6 @@ class TestSandboxDoclingDocument:
assert "True" in result.stdout
class TestSandboxRegex:
"""Test regex external functions."""
@pytest.mark.asyncio
async def test_regex_findall(self, sandbox):
"""regex_findall extracts all matches."""
result = await sandbox.execute(
r"matches = await regex_findall(r'\d+', 'abc 123 def 456')"
"\nprint(matches)"
)
assert result.success
assert "['123', '456']" in result.stdout
@pytest.mark.asyncio
async def test_regex_sub(self, sandbox):
"""regex_sub replaces matches."""
result = await sandbox.execute(
r"out = await regex_sub(r'\d+', 'X', 'abc 123 def 456')"
"\nprint(out)"
)
assert result.success
assert "abc X def X" in result.stdout
@pytest.mark.asyncio
async def test_regex_search_match(self, sandbox):
"""regex_search returns match dict when pattern matches."""
result = await sandbox.execute(
r"m = await regex_search(r'(\d+)', 'abc 123')"
"\nprint(m['group'])"
"\nprint(m['start'])"
"\nprint(m['end'])"
)
assert result.success
assert "123" in result.stdout
assert "4" in result.stdout
assert "7" in result.stdout
@pytest.mark.asyncio
async def test_regex_search_no_match(self, sandbox):
"""regex_search returns None when pattern doesn't match."""
result = await sandbox.execute(
r"m = await regex_search(r'\d+', 'abc')"
"\nprint(m is None)"
)
assert result.success
assert "True" in result.stdout
@pytest.mark.asyncio
async def test_regex_split(self, sandbox):
"""regex_split splits on pattern."""
result = await sandbox.execute(
"out = await regex_split(',', 'a,b,,c')\nprint(out)"
)
assert result.success
assert "['a', 'b', '', 'c']" in result.stdout
@pytest.mark.asyncio
async def test_regex_invalid_pattern(self, sandbox):
"""Invalid regex pattern surfaces as an error."""
result = await sandbox.execute("await regex_findall('[invalid', 'text')")
assert not result.success
assert result.stderr != ""
class TestSandboxLLM:
"""Test llm() external function."""

View file

@ -128,7 +128,7 @@ interactions:
connection:
- keep-alive
content-length:
- '7737'
- '7274'
content-type:
- application/json
host:
@ -173,18 +173,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -202,11 +190,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -232,10 +220,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -296,6 +285,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -325,7 +315,7 @@ interactions:
response:
headers:
content-length:
- '690'
- '699'
content-type:
- application/json
parsed_body:
@ -334,25 +324,26 @@ interactions:
index: 0
message:
content: ''
reasoning: Need revenue from quarterly reports. Search for "quarterly report revenue".
reasoning: Need to search for quarterly reports revenue.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor
r in results[:5]:\n print(r[''document_title''], r[''score''], r[''content''][:200])"}'
arguments: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly
report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''],
r[''score''])\n"}'
name: execute_code
id: call_no1egdsi
id: call_exbbulxp
index: 0
type: function
created: 1772626955
id: chatcmpl-2
created: 1773329130
id: chatcmpl-407
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 85
prompt_tokens: 1688
total_tokens: 1773
prompt_tokens: 1594
total_tokens: 1679
status:
code: 200
message: OK
@ -405,7 +396,7 @@ interactions:
connection:
- keep-alive
content-length:
- '8682'
- '8148'
content-type:
- application/json
host:
@ -450,18 +441,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -479,11 +458,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -509,10 +488,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -552,21 +532,20 @@ interactions:
- content: What is the total revenue across all quarterly reports?
role: user
- content: null
reasoning: Need revenue from quarterly reports. Search for "quarterly report revenue".
reasoning: Need to search for quarterly reports revenue.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor
r in results[:5]:\n print(r[''document_title''], r[''score''], r[''content''][:200])"}'
arguments: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly
report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n"}'
name: execute_code
id: call_no1egdsi
id: call_exbbulxp
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''],
r[''score''], r[''content''][:200])","stdout":"3\nQ1 Report 0.03226645663380623 Sales report Q1: Revenue was $100,000.\nQ2
Report 0.03226645663380623 Sales report Q2: Revenue was $150,000.\nQ3 Report 0.032258063554763794 Sales report Q3:
Revenue was $200,000.\n","stderr":"","success":true}'
- content: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly report
revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n","stdout":"3\nQ1
Report 0.03226645663380623\nQ2 Report 0.03226645663380623\nQ3 Report 0.032258063554763794\n","stderr":"","success":true}'
role: tool
tool_call_id: call_no1egdsi
tool_call_id: call_exbbulxp
model: gpt-oss
reasoning_effort: low
response_format:
@ -589,6 +568,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -618,7 +598,7 @@ interactions:
response:
headers:
content-length:
- '689'
- '680'
content-type:
- application/json
parsed_body:
@ -627,25 +607,25 @@ interactions:
index: 0
message:
content: ''
reasoning: Three reports with revenue numbers. Sum = 450k. Need citation chunks. Retrieve chunks.
reasoning: We need revenue numbers. Let's fetch chunks.
role: assistant
tool_calls:
- function:
arguments: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())"}'
arguments: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n"}'
name: execute_code
id: call_sg5vtxpb
id: call_2hd3mgon
index: 0
type: function
created: 1772626957
id: chatcmpl-37
created: 1773329146
id: chatcmpl-173
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 85
prompt_tokens: 1922
total_tokens: 2007
prompt_tokens: 1798
total_tokens: 1883
status:
code: 200
message: OK
@ -658,7 +638,7 @@ interactions:
connection:
- keep-alive
content-length:
- '9437'
- '8925'
content-type:
- application/json
host:
@ -703,18 +683,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -732,11 +700,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -762,10 +730,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -805,35 +774,34 @@ interactions:
- content: What is the total revenue across all quarterly reports?
role: user
- content: null
reasoning: Need revenue from quarterly reports. Search for "quarterly report revenue".
reasoning: Need to search for quarterly reports revenue.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor
r in results[:5]:\n print(r[''document_title''], r[''score''], r[''content''][:200])"}'
arguments: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly
report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n"}'
name: execute_code
id: call_no1egdsi
id: call_exbbulxp
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''],
r[''score''], r[''content''][:200])","stdout":"3\nQ1 Report 0.03226645663380623 Sales report Q1: Revenue was $100,000.\nQ2
Report 0.03226645663380623 Sales report Q2: Revenue was $150,000.\nQ3 Report 0.032258063554763794 Sales report Q3:
Revenue was $200,000.\n","stderr":"","success":true}'
- content: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly report
revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n","stdout":"3\nQ1
Report 0.03226645663380623\nQ2 Report 0.03226645663380623\nQ3 Report 0.032258063554763794\n","stderr":"","success":true}'
role: tool
tool_call_id: call_no1egdsi
tool_call_id: call_exbbulxp
- content: null
reasoning: Three reports with revenue numbers. Sum = 450k. Need citation chunks. Retrieve chunks.
reasoning: We need revenue numbers. Let's fetch chunks.
role: assistant
tool_calls:
- function:
arguments: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())"}'
arguments: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n"}'
name: execute_code
id: call_sg5vtxpb
id: call_2hd3mgon
type: function
- content: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
- content: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
role: tool
tool_call_id: call_sg5vtxpb
tool_call_id: call_2hd3mgon
model: gpt-oss
reasoning_effort: low
response_format:
@ -856,6 +824,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -885,7 +854,7 @@ interactions:
response:
headers:
content-length:
- '737'
- '713'
content-type:
- application/json
parsed_body:
@ -894,25 +863,25 @@ interactions:
index: 0
message:
content: ''
reasoning: Need to keep results variable. Use same scope. Let's re-run with storing results.
reasoning: Need to re-run search inside same code.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())"}'
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n"}'
name: execute_code
id: call_h6pfbenb
id: call_10n40kz9
index: 0
type: function
created: 1772626960
id: chatcmpl-20
created: 1773329159
id: chatcmpl-749
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 98
prompt_tokens: 2084
total_tokens: 2182
completion_tokens: 93
prompt_tokens: 1970
total_tokens: 2063
status:
code: 200
message: OK
@ -965,7 +934,7 @@ interactions:
connection:
- keep-alive
content-length:
- '10405'
- '9885'
content-type:
- application/json
host:
@ -1010,18 +979,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -1039,11 +996,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -1069,10 +1026,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -1112,51 +1070,50 @@ interactions:
- content: What is the total revenue across all quarterly reports?
role: user
- content: null
reasoning: Need revenue from quarterly reports. Search for "quarterly report revenue".
reasoning: Need to search for quarterly reports revenue.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor
r in results[:5]:\n print(r[''document_title''], r[''score''], r[''content''][:200])"}'
arguments: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly
report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n"}'
name: execute_code
id: call_no1egdsi
id: call_exbbulxp
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''],
r[''score''], r[''content''][:200])","stdout":"3\nQ1 Report 0.03226645663380623 Sales report Q1: Revenue was $100,000.\nQ2
Report 0.03226645663380623 Sales report Q2: Revenue was $150,000.\nQ3 Report 0.032258063554763794 Sales report Q3:
Revenue was $200,000.\n","stderr":"","success":true}'
- content: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly report
revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n","stdout":"3\nQ1
Report 0.03226645663380623\nQ2 Report 0.03226645663380623\nQ3 Report 0.032258063554763794\n","stderr":"","success":true}'
role: tool
tool_call_id: call_no1egdsi
tool_call_id: call_exbbulxp
- content: null
reasoning: Three reports with revenue numbers. Sum = 450k. Need citation chunks. Retrieve chunks.
reasoning: We need revenue numbers. Let's fetch chunks.
role: assistant
tool_calls:
- function:
arguments: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())"}'
arguments: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n"}'
name: execute_code
id: call_sg5vtxpb
id: call_2hd3mgon
type: function
- content: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
- content: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
role: tool
tool_call_id: call_sg5vtxpb
tool_call_id: call_2hd3mgon
- content: null
reasoning: Need to keep results variable. Use same scope. Let's re-run with storing results.
reasoning: Need to re-run search inside same code.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())"}'
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n"}'
name: execute_code
id: call_h6pfbenb
id: call_10n40kz9
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())","stdout":"Q1
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n","stdout":"Q1
Report Sales report Q1: Revenue was $100,000.\nQ2 Report Sales report Q2: Revenue was $150,000.\nQ3 Report Sales
report Q3: Revenue was $200,000.\n","stderr":"","success":true}'
role: tool
tool_call_id: call_h6pfbenb
tool_call_id: call_10n40kz9
model: gpt-oss
reasoning_effort: low
response_format:
@ -1179,6 +1136,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -1208,7 +1166,7 @@ interactions:
response:
headers:
content-length:
- '614'
- '643'
content-type:
- application/json
parsed_body:
@ -1216,25 +1174,26 @@ interactions:
- finish_reason: tool_calls
index: 0
message:
content: Now compute sum.
content: ''
reasoning: Sum revenues.
role: assistant
tool_calls:
- function:
arguments: '{"code":"total = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for
n in nums:\n total += int(n.replace('','', ''''))\nprint(total)"}'
arguments: '{"code":"total=0\nfor c in chunks:\n import re\n m=re.search(r''\\$([\\d,]+)'', c[''content''])\n if
m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n"}'
name: execute_code
id: call_rlqh271l
id: call_51jmnwfv
index: 0
type: function
created: 1772626962
id: chatcmpl-924
created: 1773329170
id: chatcmpl-461
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 83
prompt_tokens: 2312
total_tokens: 2395
completion_tokens: 88
prompt_tokens: 2196
total_tokens: 2284
status:
code: 200
message: OK
@ -1247,7 +1206,7 @@ interactions:
connection:
- keep-alive
content-length:
- '11090'
- '10618'
content-type:
- application/json
host:
@ -1292,18 +1251,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -1321,11 +1268,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -1351,10 +1298,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -1394,65 +1342,65 @@ interactions:
- content: What is the total revenue across all quarterly reports?
role: user
- content: null
reasoning: Need revenue from quarterly reports. Search for "quarterly report revenue".
reasoning: Need to search for quarterly reports revenue.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor
r in results[:5]:\n print(r[''document_title''], r[''score''], r[''content''][:200])"}'
arguments: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly
report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n"}'
name: execute_code
id: call_no1egdsi
id: call_exbbulxp
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''],
r[''score''], r[''content''][:200])","stdout":"3\nQ1 Report 0.03226645663380623 Sales report Q1: Revenue was $100,000.\nQ2
Report 0.03226645663380623 Sales report Q2: Revenue was $150,000.\nQ3 Report 0.032258063554763794 Sales report Q3:
Revenue was $200,000.\n","stderr":"","success":true}'
- content: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly report
revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n","stdout":"3\nQ1
Report 0.03226645663380623\nQ2 Report 0.03226645663380623\nQ3 Report 0.032258063554763794\n","stderr":"","success":true}'
role: tool
tool_call_id: call_no1egdsi
tool_call_id: call_exbbulxp
- content: null
reasoning: Three reports with revenue numbers. Sum = 450k. Need citation chunks. Retrieve chunks.
reasoning: We need revenue numbers. Let's fetch chunks.
role: assistant
tool_calls:
- function:
arguments: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())"}'
arguments: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n"}'
name: execute_code
id: call_sg5vtxpb
id: call_2hd3mgon
type: function
- content: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
- content: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
role: tool
tool_call_id: call_sg5vtxpb
tool_call_id: call_2hd3mgon
- content: null
reasoning: Need to keep results variable. Use same scope. Let's re-run with storing results.
reasoning: Need to re-run search inside same code.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())"}'
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n"}'
name: execute_code
id: call_h6pfbenb
id: call_10n40kz9
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())","stdout":"Q1
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n","stdout":"Q1
Report Sales report Q1: Revenue was $100,000.\nQ2 Report Sales report Q2: Revenue was $150,000.\nQ3 Report Sales
report Q3: Revenue was $200,000.\n","stderr":"","success":true}'
role: tool
tool_call_id: call_h6pfbenb
- content: Now compute sum.
tool_call_id: call_10n40kz9
- content: null
reasoning: Sum revenues.
role: assistant
tool_calls:
- function:
arguments: '{"code":"total = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for
n in nums:\n total += int(n.replace('','', ''''))\nprint(total)"}'
arguments: '{"code":"total=0\nfor c in chunks:\n import re\n m=re.search(r''\\$([\\d,]+)'', c[''content''])\n if
m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n"}'
name: execute_code
id: call_rlqh271l
id: call_51jmnwfv
type: function
- content: '{"code":"total = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for
n in nums:\n total += int(n.replace('','', ''''))\nprint(total)","stdout":"","stderr":"NameError: name ''chunks''
is not defined","success":false}'
- content: '{"code":"total=0\nfor c in chunks:\n import re\n m=re.search(r''\\$([\\d,]+)'', c[''content''])\n if
m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n","stdout":"","stderr":"NameError:
name ''chunks'' is not defined","success":false}'
role: tool
tool_call_id: call_rlqh271l
tool_call_id: call_51jmnwfv
model: gpt-oss
reasoning_effort: low
response_format:
@ -1475,6 +1423,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -1504,7 +1453,7 @@ interactions:
response:
headers:
content-length:
- '819'
- '848'
content-type:
- application/json
parsed_body:
@ -1513,27 +1462,26 @@ interactions:
index: 0
message:
content: ''
reasoning: Variable scope lost. Let's combine.
reasoning: Need to keep chunks variable. Let's combine.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n\ntotal = 0\nfor c in chunks:\n nums = await
regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for n in nums:\n total += int(n.replace('','',
''''))\nprint(total)"}'
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n\ntotal=0\nimport re\nfor c in chunks:\n m=re.search(r''\\$([\\d,]+)'',
c[''content''])\n if m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n"}'
name: execute_code
id: call_kbsx3dxm
id: call_axsiusi8
index: 0
type: function
created: 1772626965
id: chatcmpl-319
created: 1773329179
id: chatcmpl-56
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 132
prompt_tokens: 2483
total_tokens: 2615
completion_tokens: 140
prompt_tokens: 2380
total_tokens: 2520
status:
code: 200
message: OK
@ -1586,7 +1534,7 @@ interactions:
connection:
- keep-alive
content-length:
- '12120'
- '11699'
content-type:
- application/json
host:
@ -1631,18 +1579,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -1660,11 +1596,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -1690,10 +1626,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -1733,81 +1670,81 @@ interactions:
- content: What is the total revenue across all quarterly reports?
role: user
- content: null
reasoning: Need revenue from quarterly reports. Search for "quarterly report revenue".
reasoning: Need to search for quarterly reports revenue.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor
r in results[:5]:\n print(r[''document_title''], r[''score''], r[''content''][:200])"}'
arguments: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly
report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n"}'
name: execute_code
id: call_no1egdsi
id: call_exbbulxp
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''],
r[''score''], r[''content''][:200])","stdout":"3\nQ1 Report 0.03226645663380623 Sales report Q1: Revenue was $100,000.\nQ2
Report 0.03226645663380623 Sales report Q2: Revenue was $150,000.\nQ3 Report 0.032258063554763794 Sales report Q3:
Revenue was $200,000.\n","stderr":"","success":true}'
- content: '{"code":"import re\n# search for revenue in quarterly reports\nresults = await search(\"quarterly report
revenue\", limit=20)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''])\n","stdout":"3\nQ1
Report 0.03226645663380623\nQ2 Report 0.03226645663380623\nQ3 Report 0.032258063554763794\n","stderr":"","success":true}'
role: tool
tool_call_id: call_no1egdsi
tool_call_id: call_exbbulxp
- content: null
reasoning: Three reports with revenue numbers. Sum = 450k. Need citation chunks. Retrieve chunks.
reasoning: We need revenue numbers. Let's fetch chunks.
role: assistant
tool_calls:
- function:
arguments: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())"}'
arguments: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n"}'
name: execute_code
id: call_sg5vtxpb
id: call_2hd3mgon
type: function
- content: '{"code":"chunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''].strip())","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
- content: '{"code":"# get chunks for each result\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''],
chunk[''content''][:200])\n","stdout":"","stderr":"NameError: name ''results'' is not defined","success":false}'
role: tool
tool_call_id: call_sg5vtxpb
tool_call_id: call_2hd3mgon
- content: null
reasoning: Need to keep results variable. Use same scope. Let's re-run with storing results.
reasoning: Need to re-run search inside same code.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())"}'
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n"}'
name: execute_code
id: call_h6pfbenb
id: call_10n40kz9
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n print(c[''document_title''], c[''content''].strip())","stdout":"Q1
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n print(chunk[''document_title''], chunk[''content''][:200])\n","stdout":"Q1
Report Sales report Q1: Revenue was $100,000.\nQ2 Report Sales report Q2: Revenue was $150,000.\nQ3 Report Sales
report Q3: Revenue was $200,000.\n","stderr":"","success":true}'
role: tool
tool_call_id: call_h6pfbenb
- content: Now compute sum.
role: assistant
tool_calls:
- function:
arguments: '{"code":"total = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for
n in nums:\n total += int(n.replace('','', ''''))\nprint(total)"}'
name: execute_code
id: call_rlqh271l
type: function
- content: '{"code":"total = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for
n in nums:\n total += int(n.replace('','', ''''))\nprint(total)","stdout":"","stderr":"NameError: name ''chunks''
is not defined","success":false}'
role: tool
tool_call_id: call_rlqh271l
tool_call_id: call_10n40kz9
- content: null
reasoning: Variable scope lost. Let's combine.
reasoning: Sum revenues.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n\ntotal = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'',
c[''content''])\n for n in nums:\n total += int(n.replace('','', ''''))\nprint(total)"}'
arguments: '{"code":"total=0\nfor c in chunks:\n import re\n m=re.search(r''\\$([\\d,]+)'', c[''content''])\n if
m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n"}'
name: execute_code
id: call_kbsx3dxm
id: call_51jmnwfv
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c
= await get_chunk(r[''chunk_id''])\n chunks.append(c)\n\ntotal = 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'',
c[''content''])\n for n in nums:\n total += int(n.replace('','', ''''))\nprint(total)","stdout":"450000\n","stderr":"","success":true}'
- content: '{"code":"total=0\nfor c in chunks:\n import re\n m=re.search(r''\\$([\\d,]+)'', c[''content''])\n if
m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n","stdout":"","stderr":"NameError:
name ''chunks'' is not defined","success":false}'
role: tool
tool_call_id: call_kbsx3dxm
tool_call_id: call_51jmnwfv
- content: null
reasoning: Need to keep chunks variable. Let's combine.
role: assistant
tool_calls:
- function:
arguments: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n\ntotal=0\nimport re\nfor c in chunks:\n m=re.search(r''\\$([\\d,]+)'',
c[''content''])\n if m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n"}'
name: execute_code
id: call_axsiusi8
type: function
- content: '{"code":"results = await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk
= await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n\ntotal=0\nimport re\nfor c in chunks:\n m=re.search(r''\\$([\\d,]+)'',
c[''content''])\n if m:\n val=int(m.group(1).replace('','',''''))\n total+=val\nprint(total)\n","stdout":"450000\n","stderr":"","success":true}'
role: tool
tool_call_id: call_axsiusi8
model: gpt-oss
reasoning_effort: low
response_format:
@ -1830,6 +1767,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -1859,7 +1797,7 @@ interactions:
response:
headers:
content-length:
- '880'
- '980'
content-type:
- application/json
parsed_body:
@ -1867,21 +1805,22 @@ interactions:
- finish_reason: stop
index: 0
message:
content: '{"answer":"The total revenue across all quarterly reports is $450,000. This figure comes from three reports:\n-
Q1 Report: $100,000\n- Q2 Report: $150,000\n- Q3 Report: $200,000\nSumming these gives the stated total.\n", "program":"results
= await search(\"quarterly report revenue\", limit=20)\nchunks = []\nfor r in results:\n c = await get_chunk(r[''chunk_id''])\n chunks.append(c)\n\ntotal
= 0\nfor c in chunks:\n nums = await regex_findall(r''\\$([\\d,]+)'', c[''content''])\n for n in nums:\n total
+= int(n.replace('','', ''''))\nprint(total)"}'
content: '{"answer":"The total revenue reported across all quarterly reports is $450,000. This figure is the sum
of $100,000 from Q1, $150,000 from Q2, and $200,000 from Q3, as extracted from the respective quarterly report
documents.","program":"import re\n# Search for quarterly report revenue chunks\nresults = await search(\"quarterly
report revenue\", limit=20)\nchunks = []\nfor r in results:\n chunk = await get_chunk(r[''chunk_id''])\n chunks.append(chunk)\n#
Sum revenue amounts\ntotal = 0\nfor c in chunks:\n m = re.search(r\"\\$([\\d,]+)\", c[''content''])\n if
m:\n val = int(m.group(1).replace('','', ''''))\n total += val\nprint(total)"}'
role: assistant
created: 1772626970
id: chatcmpl-772
created: 1773329189
id: chatcmpl-169
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 178
prompt_tokens: 2744
total_tokens: 2922
completion_tokens: 186
prompt_tokens: 2655
total_tokens: 2841
status:
code: 200
message: OK

View file

@ -128,7 +128,7 @@ interactions:
connection:
- keep-alive
content-length:
- '7721'
- '7258'
content-type:
- application/json
host:
@ -173,18 +173,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -202,11 +190,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -232,10 +220,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -296,6 +285,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -325,7 +315,7 @@ interactions:
response:
headers:
content-length:
- '522'
- '525'
content-type:
- application/json
parsed_body:
@ -338,20 +328,20 @@ interactions:
role: assistant
tool_calls:
- function:
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))"}'
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\n"}'
name: execute_code
id: call_cthflnpr
id: call_04viywlj
index: 0
type: function
created: 1772626945
id: chatcmpl-979
created: 1773329125
id: chatcmpl-653
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 45
prompt_tokens: 1686
total_tokens: 1731
completion_tokens: 47
prompt_tokens: 1592
total_tokens: 1639
status:
code: 200
message: OK
@ -364,7 +354,7 @@ interactions:
connection:
- keep-alive
content-length:
- '8163'
- '7706'
content-type:
- application/json
host:
@ -409,18 +399,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -438,11 +416,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -468,10 +446,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -515,13 +494,13 @@ interactions:
role: assistant
tool_calls:
- function:
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))"}'
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\n"}'
name: execute_code
id: call_cthflnpr
id: call_04viywlj
type: function
- content: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))","stdout":"3\n","stderr":"","success":true}'
- content: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\n","stdout":"3\n","stderr":"","success":true}'
role: tool
tool_call_id: call_cthflnpr
tool_call_id: call_04viywlj
model: gpt-oss
reasoning_effort: low
response_format:
@ -544,6 +523,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -573,7 +553,7 @@ interactions:
response:
headers:
content-length:
- '459'
- '416'
content-type:
- application/json
parsed_body:
@ -581,18 +561,17 @@ interactions:
- finish_reason: stop
index: 0
message:
content: '{"answer":"There are 3 documents in the database.","program":"docs = await list_documents(limit=1000)\nprint(f''There
are {len(docs)} documents in the database.'')" }'
content: '{"answer":"There are 3 documents in the database.","program":"docs = await list_documents(limit=1000)\nprint(len(docs))"}'
role: assistant
created: 1772626947
id: chatcmpl-490
created: 1773329134
id: chatcmpl-151
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 49
prompt_tokens: 1773
total_tokens: 1822
completion_tokens: 38
prompt_tokens: 1683
total_tokens: 1721
status:
code: 200
message: OK

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -128,7 +128,7 @@ interactions:
connection:
- keep-alive
content-length:
- '7715'
- '7252'
content-type:
- application/json
host:
@ -173,18 +173,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -202,11 +190,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -232,10 +220,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -296,6 +285,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -325,7 +315,7 @@ interactions:
response:
headers:
content-length:
- '522'
- '576'
content-type:
- application/json
parsed_body:
@ -334,24 +324,25 @@ interactions:
index: 0
message:
content: ''
reasoning: Need to list documents.
reasoning: We need to list documents.
role: assistant
tool_calls:
- function:
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\n"}'
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\nfor d in docs:\n print(d[''id''],
d.get(''title''))"}'
name: execute_code
id: call_jsd3hga7
id: call_nap68rkx
index: 0
type: function
created: 1772626976
id: chatcmpl-987
created: 1773329124
id: chatcmpl-461
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 46
prompt_tokens: 1684
total_tokens: 1730
completion_tokens: 64
prompt_tokens: 1590
total_tokens: 1654
status:
code: 200
message: OK
@ -364,7 +355,7 @@ interactions:
connection:
- keep-alive
content-length:
- '8160'
- '7846'
content-type:
- application/json
host:
@ -409,18 +400,6 @@ interactions:
- `pictures`: list of figures/images with metadata
- `pages`: page dimensions and metadata
### await regex_findall(pattern, text) -> list[str]
Find all non-overlapping matches of a regular expression pattern in text.
### await regex_sub(pattern, repl, text) -> str
Replace all occurrences of a regular expression pattern with a replacement string.
### await regex_search(pattern, text) -> dict | None
Search for the first match of a pattern. Returns a dict with keys: group, groups, start, end — or None if no match.
### await regex_split(pattern, text) -> list[str]
Split text by a regular expression pattern.
### await llm(prompt) -> str
Call an LLM directly with the given prompt. Returns the response as a string.
Use this for classification, summarization, extraction, or any task where you
@ -438,11 +417,11 @@ interactions:
## Available Python Features
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `sorted()`/`.sort(key=...)`, try/except, and the `json` module.
The interpreter supports: variables, arithmetic, strings, f-strings, lists, dicts, tuples, sets, loops, conditionals, comprehensions, functions, async/await, `map()`, `filter()`, `getattr()`, `sorted()`/`.sort(key=...)`, try/except, and the `json`, `re`, `math` modules.
Not supported: imports (other than `json`), class definitions, generators/yield, match statements, decorators, `with` statements.
Not supported: most imports (only `json`, `re`, `math` are available), class definitions, generators/yield, match statements, decorators, `with` statements.
For pattern matching or text extraction, use the `regex_*` functions, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
For pattern matching or text extraction, use `import re`, string methods (`str.split`, `str.find`, `str.startswith`, `in` operator), or the `llm()` function.
## Strategy Guide
@ -468,10 +447,11 @@ interactions:
### Extracting data with regex
```python
import re
numbers = []
results = await search("financial data", limit=20)
for r in results:
amounts = await regex_findall(r'\$([\d,]+)', r['content'])
amounts = re.findall(r'\$([\d,]+)', r['content'])
for a in amounts:
numbers.append(int(a.replace(',', '')))
if numbers:
@ -511,17 +491,19 @@ interactions:
- content: How many documents are available?
role: user
- content: null
reasoning: Need to list documents.
reasoning: We need to list documents.
role: assistant
tool_calls:
- function:
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\n"}'
arguments: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\nfor d in docs:\n print(d[''id''],
d.get(''title''))"}'
name: execute_code
id: call_jsd3hga7
id: call_nap68rkx
type: function
- content: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\n","stdout":"1\n","stderr":"","success":true}'
- content: '{"code":"docs = await list_documents(limit=1000)\nprint(len(docs))\nfor d in docs:\n print(d[''id''],
d.get(''title''))","stdout":"1\n7b1434a1-bbe5-4ae1-bb3e-5400eed94d72 Cats\n","stderr":"","success":true}'
role: tool
tool_call_id: call_jsd3hga7
tool_call_id: call_nap68rkx
model: gpt-oss
reasoning_effort: low
response_format:
@ -544,6 +526,7 @@ interactions:
strict: true
type: json_schema
stream: false
temperature: 0.0
tool_choice: auto
tools:
- function:
@ -573,7 +556,7 @@ interactions:
response:
headers:
content-length:
- '430'
- '484'
content-type:
- application/json
parsed_body:
@ -581,17 +564,18 @@ interactions:
- finish_reason: stop
index: 0
message:
content: '{"answer":"There is 1 document available in the knowledge base.","program":"docs = await list_documents(limit=1000)\nprint(len(docs))"}'
content: '{"answer":"There is 1 document available in the knowledge base.","program":"docs = await list_documents(limit=1000)\nprint(len(docs))\nfor
d in docs:\n print(d[''id''], d.get(''title''))"}'
role: assistant
created: 1772626977
id: chatcmpl-959
created: 1773329133
id: chatcmpl-985
model: gpt-oss
object: chat.completion
system_fingerprint: fp_ollama
usage:
completion_tokens: 37
prompt_tokens: 1774
total_tokens: 1811
completion_tokens: 59
prompt_tokens: 1741
total_tokens: 1800
status:
code: 200
message: OK

78
uv.lock
View file

@ -1529,7 +1529,7 @@ requires-dist = [
{ name = "pydantic-ai-slim", extras = ["openai", "fastmcp", "logfire", "ag-ui"], specifier = ">=1.66.0" },
{ name = "pydantic-ai-slim", extras = ["vertexai"], marker = "extra == 'vertexai'" },
{ name = "pydantic-ai-slim", extras = ["voyageai"], marker = "extra == 'voyageai'" },
{ name = "pydantic-monty", specifier = ">=0.0.7" },
{ name = "pydantic-monty", specifier = ">=0.0.8" },
{ name = "python-dotenv", specifier = ">=1.2.2" },
{ name = "pyyaml", specifier = ">=6.0.3" },
{ name = "rich", specifier = ">=14.3.3" },
@ -3790,46 +3790,46 @@ wheels = [
[[package]]
name = "pydantic-monty"
version = "0.0.7"
version = "0.0.8"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f5/e3/0d8b2b025628477c839f894e632f5197872b19df0a86b2ec30fac3b5960a/pydantic_monty-0.0.7.tar.gz", hash = "sha256:2189ea1d7aadab2f95374733d692f51d1206379a4fc7ce18ab46895512e88f92", size = 684705, upload-time = "2026-02-19T14:12:47.235Z" }
sdist = { url = "https://files.pythonhosted.org/packages/47/bf/e9794b562c207406d8fda0cf4fea810943a5e8a85fe69e5505046179df16/pydantic_monty-0.0.8.tar.gz", hash = "sha256:8135e781a184f971825c1d2eb6d621598103e900f6e0d34291ff0bf35df6142f", size = 802646, upload-time = "2026-03-10T14:46:51.353Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ce/7e/ca0884108c3237bb15bb2a1b3f24ddd957b9c750f1ed3211801497941999/pydantic_monty-0.0.7-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f35e18f284524d26d5f27084e2b93eb40139055bbf0cab6221a043eb5e9ce2dc", size = 6264252, upload-time = "2026-02-19T14:13:59.317Z" },
{ url = "https://files.pythonhosted.org/packages/5a/5b/31f70c7792a857bacbdce90b8aae4629c31a9fec35f0116d91a2fb53241b/pydantic_monty-0.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e5d8924c65bb1ced60785a156e28c73f7f79f164b4f090dc26312c3917ffff7", size = 6133285, upload-time = "2026-02-19T14:14:46.577Z" },
{ url = "https://files.pythonhosted.org/packages/42/56/c92216c0427e8a10a01fa98f29252f6fabd8ca80ca193e0fd30fe28e65c1/pydantic_monty-0.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6279a468469d5a3b80d94dd0ab6110cd291a1dfbb057fa7d6dbad1f499be855d", size = 6059856, upload-time = "2026-02-19T14:13:02.594Z" },
{ url = "https://files.pythonhosted.org/packages/b5/a7/bc3e67b12d8a9da65f2677d9a48bc1e055a1d853d48572ba4845a64075cf/pydantic_monty-0.0.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cb5feb69a5902d059db5dab269f90423b85a22163668422be47ccac8d7f7c44a", size = 6313780, upload-time = "2026-02-19T14:13:46.45Z" },
{ url = "https://files.pythonhosted.org/packages/c8/97/a9b856b17ee1e54892dafbb7ea29305520cae2dcd8aafe82a26a0edbc33c/pydantic_monty-0.0.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2f1913e9729aa6711092ecbfce764df199a4787fe3e23a7ed74c78bf846579e", size = 6856827, upload-time = "2026-02-19T14:13:40.836Z" },
{ url = "https://files.pythonhosted.org/packages/98/57/2d8184b9f5a0b2b3bb47fdad7061c6a182699824efe6de9d8dd19ee68c0a/pydantic_monty-0.0.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec528f9f4194e6298757ad99e25da47f06f49ae2bc176ee26f49da5eb1dd7849", size = 6870737, upload-time = "2026-02-19T14:13:53.602Z" },
{ url = "https://files.pythonhosted.org/packages/6b/b3/fe3d3eff82b41e517739841a492d7a48ea2daf8e7b822299b848b5d4c0aa/pydantic_monty-0.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75405b9186a9acfa49cd66aa339b5a2450d733a2d59fae20cc8be45e45204d5f", size = 6611843, upload-time = "2026-02-19T14:13:49.957Z" },
{ url = "https://files.pythonhosted.org/packages/ff/d2/fdd8fe135ea14e30b40adadc896dda6c805596688998c9bcdfd8d85a16cf/pydantic_monty-0.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1917e42fce4733f92f5f6ad64ae4d0e87abbf9fb284ef52589ac3e292e928bfe", size = 6692856, upload-time = "2026-02-19T14:13:00.635Z" },
{ url = "https://files.pythonhosted.org/packages/0d/a6/fdde6f8d76aa0cff4b53060b63d7f09dbb19da61a967cb4b3dfd972acf1c/pydantic_monty-0.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d72a5d4f3ee7f9d2630b0379e4cfb397e181eb0b16e8c49a03f80ba6471edb89", size = 6236587, upload-time = "2026-02-19T14:14:32.602Z" },
{ url = "https://files.pythonhosted.org/packages/1b/7e/0580bbc001a39252b2f7da4b7504ac10572e4ca0ec967aebc5a9d752b6f7/pydantic_monty-0.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20028220981516912f130986354ef6c926b98778146ca349560cb852e44d9ca6", size = 6672260, upload-time = "2026-02-19T14:13:26.527Z" },
{ url = "https://files.pythonhosted.org/packages/d8/53/578a7b781a5714db5c4b1989c6e876d30caa0adf8a5a4caad89abc306667/pydantic_monty-0.0.7-cp312-cp312-win32.whl", hash = "sha256:e28b1c3ed52892f8ac12ee0f2b535402dfe1cb1e5c18128f1cb69eb8b66c285a", size = 6131085, upload-time = "2026-02-19T14:14:13.296Z" },
{ url = "https://files.pythonhosted.org/packages/56/98/20bd45fcd472937b1b3438b7587e209e3cfd447c30d02f654b86b44adaad/pydantic_monty-0.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:031dfab63ff9d7acdc641852e0d822603038cef1c27c5060900b9fd51cc853d0", size = 6664431, upload-time = "2026-02-19T14:13:29.968Z" },
{ url = "https://files.pythonhosted.org/packages/ec/fe/d8cb6c30d9d7bcc7d3c8d2c349a227e2a83cd1fbe7182f4941896eb35443/pydantic_monty-0.0.7-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:55d36818f8e35872ed35e395b41df8acc460bcdbbfd471fe0c39e293a1d50db5", size = 6262596, upload-time = "2026-02-19T14:14:15.2Z" },
{ url = "https://files.pythonhosted.org/packages/81/7a/f6b4881ca9779bd87eb8d8c0823133b56c232cf09d765c07a7f91d641490/pydantic_monty-0.0.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:acb437458d93d54a9658656545fb6c9b396dbe66f68633b3c57bfd2f4aa1d400", size = 6133793, upload-time = "2026-02-19T14:14:06.498Z" },
{ url = "https://files.pythonhosted.org/packages/39/b9/dfcffd95ff233b8c98db9254242d9c10190989762016d18509aa04d43b1b/pydantic_monty-0.0.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b196345ffa1997041cb870ea693148feafe270575e2c2963532eedde0e84dedf", size = 6059400, upload-time = "2026-02-19T14:13:38.953Z" },
{ url = "https://files.pythonhosted.org/packages/6b/2e/d6ecef842024267ddf4128613342b8985a7444e74f3a4a312713c913a91a/pydantic_monty-0.0.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d471e3cfe77d62edaf43b7f0962b95270ee4243abea12cb8e8cf1ad972dc3612", size = 6312625, upload-time = "2026-02-19T14:13:36.901Z" },
{ url = "https://files.pythonhosted.org/packages/75/2e/e4a2a9fbc3640bcee15b80c2f8ba0f97bf989c58c01d6da187524f71d12b/pydantic_monty-0.0.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a67771afd385579bf3f894ce933fb9e467fba9a632ccf27246e271d448f6f5f", size = 6859902, upload-time = "2026-02-19T14:14:26.67Z" },
{ url = "https://files.pythonhosted.org/packages/d2/4a/7aaf5c793f52e3403892a2de1f5dd18ae38234d82111cc9b7d92443e5b0d/pydantic_monty-0.0.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf662e1bbee4ddd318d5b8bfa9233173045029be0f67f15f816955b246bb7ec0", size = 6870524, upload-time = "2026-02-19T14:13:28.208Z" },
{ url = "https://files.pythonhosted.org/packages/c3/a9/c16f078864a273460923f1371b769c2719e1ce1ad86bc9031e3ed7fb3eae/pydantic_monty-0.0.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0151ff59a8a0d9e29ddb448affa33943108121e6e324795646a2f5facaf1a5d8", size = 6611960, upload-time = "2026-02-19T14:14:38.812Z" },
{ url = "https://files.pythonhosted.org/packages/20/d3/b3ef3432558a8cc9551d8b80a028a0f51cd2a518275932e03359eac3dc39/pydantic_monty-0.0.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:45f17a65134d3a0031e1f54d143770699f6a0ce92a1e74f0ae4914e52370f058", size = 6691834, upload-time = "2026-02-19T14:13:34.661Z" },
{ url = "https://files.pythonhosted.org/packages/ef/56/1ab5d1cbc0edfb522f0c28c9f5a7fc74eea6355234f73833087524d034bf/pydantic_monty-0.0.7-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ede6e68cb8a1f7216e26b0b2fb6cd0eae7a92104be8a49d1042e9e428de9262b", size = 6235704, upload-time = "2026-02-19T14:13:48.276Z" },
{ url = "https://files.pythonhosted.org/packages/c4/d1/cdebae67b0543f696ed7daff8587dc8a458e6552b52d5877cb8e55be74b4/pydantic_monty-0.0.7-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:4b2fd51eea05a0cc37bb91f326efdb1acbcd4b8262dac1c55aeb208e51254978", size = 6671530, upload-time = "2026-02-19T14:12:56.96Z" },
{ url = "https://files.pythonhosted.org/packages/9f/53/c0dacaec260b71050fd6b31d09570f9d74bbb2a2e9586032694e92b9fa59/pydantic_monty-0.0.7-cp313-cp313-win32.whl", hash = "sha256:40f2092970c5899ac2a2784d712a4c7e194b33cd0133315254e4baf141cd6c93", size = 6130341, upload-time = "2026-02-19T14:14:09.701Z" },
{ url = "https://files.pythonhosted.org/packages/3e/05/31490a7a899d8bbb2e513630ea6f591ceb8a111c91fe7573a96c9f6b6327/pydantic_monty-0.0.7-cp313-cp313-win_amd64.whl", hash = "sha256:42cee2646415bb9bd7da428d169783203618a418f960c6f75c7a74d6946d6b31", size = 6664341, upload-time = "2026-02-19T14:14:19.008Z" },
{ url = "https://files.pythonhosted.org/packages/99/15/64aff358df0b822dd22f212fec501e3944edffe978a4ab05530ea641dc68/pydantic_monty-0.0.7-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c97b2e1dcd0126417892595c1da724a8c4348f7dcec26ba774117bd51bde46f8", size = 6266090, upload-time = "2026-02-19T14:13:12.364Z" },
{ url = "https://files.pythonhosted.org/packages/64/90/7b5a4292eb9993eb8be9d958b5a57764818eeda471e3e79be7da4e9b49ba/pydantic_monty-0.0.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6f40e6e133b309ba733874f5980ab6cf867ec8cea2a6a389a641819cd8dcb7cd", size = 6152219, upload-time = "2026-02-19T14:13:20.734Z" },
{ url = "https://files.pythonhosted.org/packages/43/e4/2740af0157eb3c6f10c16b0d8376b8c9cf0b910720fe90229885bccb4a91/pydantic_monty-0.0.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57f2a327b6aa7402a2b2c3ddb3964bd45f12597f8f950dd4c5905b843b353b73", size = 6060942, upload-time = "2026-02-19T14:12:45.601Z" },
{ url = "https://files.pythonhosted.org/packages/f6/26/1cf235c2cc8e219a94ed8b11151280ba89e8020a475b6280c89e62f7275f/pydantic_monty-0.0.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:771f1f158af0de2480ea2a8862e4c0c7f79e9a13cc3e17529002e1abfc077f95", size = 6315477, upload-time = "2026-02-19T14:14:11.314Z" },
{ url = "https://files.pythonhosted.org/packages/b8/41/0faca7b9d8868822b7177ae941f193f397479bb114d3a6396466167a3198/pydantic_monty-0.0.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a4182312ee8c26d8834e76375b2b5c766cb5d86d1dcf1515aa95e02704fcad83", size = 6862130, upload-time = "2026-02-19T14:13:22.375Z" },
{ url = "https://files.pythonhosted.org/packages/34/7b/0f2bd4105a285f50f17af721e83a76ebc1186a9f07a2a29d6d576490a232/pydantic_monty-0.0.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8751696fe66fb1bdd429d98fde3a7f4b7dce9cb45f22095e28b96b690a422a2c", size = 6872292, upload-time = "2026-02-19T14:14:08.078Z" },
{ url = "https://files.pythonhosted.org/packages/c9/18/4380820d62d348afb1355814ea674788e28db7a73108a486e0b8898987de/pydantic_monty-0.0.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b73cd1137bb4fd9bf95ed5f87e48d960f7d556c30eeafde6996f908abbf183", size = 6636567, upload-time = "2026-02-19T14:14:01.464Z" },
{ url = "https://files.pythonhosted.org/packages/3e/57/29e5f89a558a6409d514bb2790c72442ec65804cbf1df6a870bbc0038673/pydantic_monty-0.0.7-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1fa45a66757de5ea45c0809e15643bc2521959dbe2bc231694b22fa189decc9", size = 6693896, upload-time = "2026-02-19T14:14:34.128Z" },
{ url = "https://files.pythonhosted.org/packages/f6/26/5886d0f57ddb5ddf766ee2d0a4b3032267be9efd49a7c95c4d87a0b4b6a9/pydantic_monty-0.0.7-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ffe8122db9f0f64619a66f4cee2f577245ba59158b7d651a2eae08df691d34f9", size = 6236867, upload-time = "2026-02-19T14:14:20.704Z" },
{ url = "https://files.pythonhosted.org/packages/b5/72/1bb8741baf84f217d92291b862f8a8cb64d735fe4be20be2827fdf787593/pydantic_monty-0.0.7-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:2122a5b6df53843329af01f6671300747449608d9cdf88ae5f9cf9977794e7a2", size = 6673504, upload-time = "2026-02-19T14:14:24.517Z" },
{ url = "https://files.pythonhosted.org/packages/d1/14/a4ff2bfe46350ffde4b5edc1f293b252cff90063f1f4cece49affe5a6462/pydantic_monty-0.0.7-cp314-cp314-win32.whl", hash = "sha256:bfbea2eddb9eef186326a6dfb27d79f8de434d7a3979f36f03b04216234a0275", size = 6131872, upload-time = "2026-02-19T14:13:14.437Z" },
{ url = "https://files.pythonhosted.org/packages/60/1f/d873f280aae5cbd27021189843fbd5f77be4262a7654ef30445d984518ab/pydantic_monty-0.0.7-cp314-cp314-win_amd64.whl", hash = "sha256:1b750afceef78f5c5d3e3e3c32a8060b3a7e1b97e3a00ac2bede5bc5e87cde8f", size = 6687125, upload-time = "2026-02-19T14:13:04.317Z" },
{ url = "https://files.pythonhosted.org/packages/f4/4f/7d7c7531be850469bccfbbf3cfede9e95d92b1d8e7b245d9dc77a599d6e4/pydantic_monty-0.0.8-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:025b380c0ed728bdf88e3ed60d5977498d4bb9da61cd81d9cabdaecce16f5755", size = 6699454, upload-time = "2026-03-10T14:46:39.422Z" },
{ url = "https://files.pythonhosted.org/packages/c0/35/074daa5fd92e4a5c1e49c8fae06036e194139feef9a51b4db82d0fee7e54/pydantic_monty-0.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76846d77ebda3414beb8c9e5da9eaef722e06606dc0307613186d888e775dc51", size = 6743273, upload-time = "2026-03-10T14:46:16.184Z" },
{ url = "https://files.pythonhosted.org/packages/55/0d/e6cb1e9e1c2e51501d8f7848c18803780164948e338350ab94769690f207/pydantic_monty-0.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b58149d6a8998ffed80f626c10bf0de7e65964aae1dfad80db8ecb00968fb1a", size = 6503552, upload-time = "2026-03-10T14:45:26.083Z" },
{ url = "https://files.pythonhosted.org/packages/5f/a9/286f7eb6c95d7877f6f8b9bcbe26e2d988fa142cd77509e48e67302478bf/pydantic_monty-0.0.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b99bb030ff8e95b160c11702b9a6823705b7dcc1a49a2c1dccc43c2538bfe27", size = 6765377, upload-time = "2026-03-10T14:45:14.472Z" },
{ url = "https://files.pythonhosted.org/packages/74/76/85268f6305bc5b153be7c0860e69ce3b9ba916daa4a419f53d8a777e9a39/pydantic_monty-0.0.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b05b17fc2b8875e0efea047416fc0cd28a8018c040b25387454996b98540ccfc", size = 7324571, upload-time = "2026-03-10T14:45:48.786Z" },
{ url = "https://files.pythonhosted.org/packages/11/6a/2855c6149f6ba3138c7bfb009c07d528e2df12802e3216928b1289bbf233/pydantic_monty-0.0.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97fa5deef4d8cdcf60a4d8a4e7a34099deae1ad4b33acc1c33ac2e1cc348a1c2", size = 7533828, upload-time = "2026-03-10T14:46:55.386Z" },
{ url = "https://files.pythonhosted.org/packages/31/63/44b5bb5798323f7f735f5855a0d3f478d6852d9d1774427d77e31b5dbffb/pydantic_monty-0.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1aabd56af5db51c4af512142fe7ffc866b6a20dcd039a4aad5245ef42768f21", size = 7271978, upload-time = "2026-03-10T14:45:33.903Z" },
{ url = "https://files.pythonhosted.org/packages/4b/68/ce82eb571e45afbe3c0b9544fe3ebf93f841ec895fea0d39c9604a0a421f/pydantic_monty-0.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9782e58da29176a3fb0ce8ec808571d0be99c1e2ad167637225246e594e85f13", size = 7187140, upload-time = "2026-03-10T14:46:41.784Z" },
{ url = "https://files.pythonhosted.org/packages/5b/45/778bc260195ddb892f284c3cb8ab8cbcb0542e6a18f11b7e50a592b507ba/pydantic_monty-0.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ff7fb7ff3f4e830ef9b28a76e634219195b552c0dfed3471fb4910708db56221", size = 6677996, upload-time = "2026-03-10T14:46:03.163Z" },
{ url = "https://files.pythonhosted.org/packages/1e/02/8e8396b83d19ec70a09c24b0245177a595c2b7d6d092c6f6c7d3310b191c/pydantic_monty-0.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce7222d923676900827e3951e65f854d65f50b65ed8c7a84011d3472773d51bf", size = 7136513, upload-time = "2026-03-10T14:45:52.179Z" },
{ url = "https://files.pythonhosted.org/packages/fd/24/53d06af74b82043be9c4960c38bbc255eeb3de9f2a4d450f942912630bb3/pydantic_monty-0.0.8-cp312-cp312-win32.whl", hash = "sha256:4cb59e1e7b1a3d573247a871a87c88506ce9fb68bbd7648598e171cf2f04747e", size = 6582168, upload-time = "2026-03-10T14:45:58.197Z" },
{ url = "https://files.pythonhosted.org/packages/25/0f/55a16faf379139263ad852421734cb096390777d299ef7f185ec10404656/pydantic_monty-0.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:45bf11e3b795cc470a91cbd7cfeb9d96f7a60387e8da146a11bf952b4371aba7", size = 7335422, upload-time = "2026-03-10T14:45:28.301Z" },
{ url = "https://files.pythonhosted.org/packages/27/46/3268001a639052515d5a55ea2f1e087ae1e5f7aa9d7bc62c4808d731fff1/pydantic_monty-0.0.8-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f303f1d979213dcb365c69de3912daa70a32af019bb5ee86e086f584638974f2", size = 6698529, upload-time = "2026-03-10T14:45:39.712Z" },
{ url = "https://files.pythonhosted.org/packages/f4/22/28d6b7f8f7a1e0881c449310a6f2c8ee0cf85dc4434ae0f7e633dfcf5bcf/pydantic_monty-0.0.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8cc698da6f7f11743df7c48b959eea000e8e30511c7e1318b67543e25985062", size = 6743849, upload-time = "2026-03-10T14:46:48.023Z" },
{ url = "https://files.pythonhosted.org/packages/7b/ab/e3dfe057af472e4065297d69aea0cf30616d01366a29e02d0a2739f22b93/pydantic_monty-0.0.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f6da093164e99012b49b39ba1e64c166ccd126128d114f9e2c66df6fb695c4", size = 6503266, upload-time = "2026-03-10T14:46:19.594Z" },
{ url = "https://files.pythonhosted.org/packages/0a/82/d3e9aa9bd9ac69b3584216166a189e11370913ffcbd2a57a5cac6ce2d4ba/pydantic_monty-0.0.8-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f2432ef62140554f5970991b7df41e064824741a807515658f91283c75669086", size = 6765032, upload-time = "2026-03-10T14:45:20.571Z" },
{ url = "https://files.pythonhosted.org/packages/f8/9d/7ab11be8eff998bf9283c7bf444254cff5212f87fe3f2a9a2f7436cce6d7/pydantic_monty-0.0.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99951afb4d722212c2ce85c303b5e87d50756adaff46817ad0e60e95eb1e5141", size = 7324673, upload-time = "2026-03-10T14:45:37.957Z" },
{ url = "https://files.pythonhosted.org/packages/39/a0/7f026ece228cc990e58aa27f2ce5af26d042baaa0186cb451f3e04ff0abe/pydantic_monty-0.0.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bdef70921b408378f9bc38bce4952d3c176b3f7833aa782068b310390901c516", size = 7533774, upload-time = "2026-03-10T14:46:24.265Z" },
{ url = "https://files.pythonhosted.org/packages/07/e7/72f250ffd005520ad8cdffb387241a9dd92fc70bcbdd769720918bd34495/pydantic_monty-0.0.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00b5dee7bef619e7661f77bef765f483605bcd2a79c6b8bf5c910afa1c93fc40", size = 7272179, upload-time = "2026-03-10T14:45:08.085Z" },
{ url = "https://files.pythonhosted.org/packages/b8/7c/97c87c2a315ba4376bfb83197586365003005e01d6547df7f6d77b80d13f/pydantic_monty-0.0.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5f4c6f6fb2ebae0bc80520af71e1057055413ca96fd33f13f3c612a085e50fb8", size = 7186684, upload-time = "2026-03-10T14:46:49.833Z" },
{ url = "https://files.pythonhosted.org/packages/09/42/2eea55906fee8bef7c1024bf2d35e2c301b15b562934731bdae25db448cb/pydantic_monty-0.0.8-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3ab3c558a648942d4d31e7f668d60d2a2e129751a3e8e9dc27b1e6d635e9e627", size = 6677272, upload-time = "2026-03-10T14:45:54.037Z" },
{ url = "https://files.pythonhosted.org/packages/40/0a/066e53d4693b680e39080d3af4f234c1ff9976f7621b8a49dd2a41710431/pydantic_monty-0.0.8-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:782d686d217b537e6fa9047aa3444d67b3b7cc69bf6faf34078c992ceaeb1e9e", size = 7136493, upload-time = "2026-03-10T14:45:30.014Z" },
{ url = "https://files.pythonhosted.org/packages/81/c1/46dc300f87314aef883a57ae5a35ba45a463c09f64d3d9c9f0b620672734/pydantic_monty-0.0.8-cp313-cp313-win32.whl", hash = "sha256:ef0db454757cb92974890b11c7b0969d8c0d95944c821f6fc6cd23846d1d2aa4", size = 6581014, upload-time = "2026-03-10T14:46:07.886Z" },
{ url = "https://files.pythonhosted.org/packages/b0/2a/cf156df19a1612ca5ddcbd982645e54c5485e83215d9532cc9aff791f854/pydantic_monty-0.0.8-cp313-cp313-win_amd64.whl", hash = "sha256:dbf8c7cfaff2b345f8c1bfba98fdc282e790fef5c601f37c8d5355ccd45073de", size = 7335041, upload-time = "2026-03-10T14:46:21.371Z" },
{ url = "https://files.pythonhosted.org/packages/a5/69/5bedc7ad67fdd9e4f04007477f5c414b54c51d47c5dfdd7abad4c78663aa/pydantic_monty-0.0.8-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:47990770ed74af1e8e2160a7dd925aa1e4fd1bf4ae9658ffd1cdc32eb5c8c6e8", size = 6700454, upload-time = "2026-03-10T14:45:56.247Z" },
{ url = "https://files.pythonhosted.org/packages/bf/35/06aaa9c766a83e7e95219bfb6cb88bd0a87803f85eb3f596b82da0cb3009/pydantic_monty-0.0.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9534f6236b3ebdd09f0f7d71e508e68736733d24cdda2a6c0a758914261c75e5", size = 6760180, upload-time = "2026-03-10T14:45:22.982Z" },
{ url = "https://files.pythonhosted.org/packages/f3/b8/eaa4a4f0b3a1c343773317027bb5d1e11a1b0c1ad01d3f0921a7f547d346/pydantic_monty-0.0.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c4ffd8275d520628732d82e7410e5f1f69ef5af274d676f1f2f9221fd85a34", size = 6504414, upload-time = "2026-03-10T14:45:12.984Z" },
{ url = "https://files.pythonhosted.org/packages/9d/79/dbb0875ad2b565d7ef1981feda4438ab743130f4031107aaadc9212488dd/pydantic_monty-0.0.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:badaa22749fa7a22ee2cb88f6deb48fc191cb2f41237dd630593259ed9f30b67", size = 6766768, upload-time = "2026-03-10T14:46:29.12Z" },
{ url = "https://files.pythonhosted.org/packages/25/cb/bd6bef8fa2cfe807dd5ef36ab8ce6d094ecdad0050cf57dec4c8a438d413/pydantic_monty-0.0.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e39104684eda1ae3c290e3a4369bef9d00f9b637be8515802bc1523fecb5160d", size = 7326073, upload-time = "2026-03-10T14:45:50.679Z" },
{ url = "https://files.pythonhosted.org/packages/aa/44/b64b6e2857519d5fdc66f74998019e585e5c3bf2cf8deb7b77419d29db2a/pydantic_monty-0.0.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2e5b3b11b794f82504bb6929f4101f0db84933986aee9b46ce7561add152e9", size = 7535251, upload-time = "2026-03-10T14:46:04.645Z" },
{ url = "https://files.pythonhosted.org/packages/da/11/4e1524d94e33427990cffd74eaf94a023724c872f11d42ac90eebd74ccc0/pydantic_monty-0.0.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a94fc87b2a9b1b66a09f35b819b1c7e7da7702b21c923cdca21fa13129486b45", size = 7288739, upload-time = "2026-03-10T14:45:35.609Z" },
{ url = "https://files.pythonhosted.org/packages/2c/7d/7e667c72c9742a6725b04d21faf50e8f552a0e23da9ca1cbeba891961c9a/pydantic_monty-0.0.8-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:70b7479e7bd47d274fbd6278a625289e71b1a4aad400f40c7a4a89fe9a50952c", size = 7189195, upload-time = "2026-03-10T14:46:09.399Z" },
{ url = "https://files.pythonhosted.org/packages/7b/3f/3243277e2c6bf4c3e4684fbc78c316a8965dbbb012b573b38978d8628bfc/pydantic_monty-0.0.8-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:48b8c9cb9a96a5f28b03669771368a444c8b50c758b6a5bd0d148fa02db3f65b", size = 6679333, upload-time = "2026-03-10T14:45:24.494Z" },
{ url = "https://files.pythonhosted.org/packages/0c/51/88152b89f5288e9d3cd28e71f79a6567421e20d8f00b0514b7819a29a8bb/pydantic_monty-0.0.8-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:b005f10798a1b58a12b5643f69a7b54208bd4965d16ca2bd21d13fca4d1a4f67", size = 7137771, upload-time = "2026-03-10T14:46:33.043Z" },
{ url = "https://files.pythonhosted.org/packages/d8/38/baf5a66ed72b931de7ce92251822d6ffb752582389ff4f4c853742cee029/pydantic_monty-0.0.8-cp314-cp314-win32.whl", hash = "sha256:b143bba29c274e15424a097af6ae85a1e81e6c2fb7184ee7a93fbf10997dbbd3", size = 6584038, upload-time = "2026-03-10T14:46:34.53Z" },
{ url = "https://files.pythonhosted.org/packages/71/80/bfda690914fa15c68f8be9e824e62c4054118a9a72304735221446a89014/pydantic_monty-0.0.8-cp314-cp314-win_amd64.whl", hash = "sha256:f4bc9185bb5f37f3220a978889b4bc6f822a41ee4d5523c17eef4d869aca66e8", size = 7351170, upload-time = "2026-03-10T14:46:57.025Z" },
]
[[package]]