1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright 2026 Thomas Santerre and Moderately AI Inc.
//
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Sandboxed Python AST interpreter with host tool injection and resource limits.
//!
//! Evaluates [`rustpython_parser`] ASTs — not an embedded CPython. There is no
//! filesystem, network, or process access unless the host registers tools that
//! provide them.
//!
//! # Quick start
//!
//! ```no_run
//! use std::collections::HashMap;
//!
//! use interpretthis::{
//! Interpreter, InterpreterConfig, InterpreterDeps, KwargsExt, ToolDefinition, Tools, Value,
//! };
//!
//! # async fn demo() {
//! let tools = Tools::new().with(
//! "double",
//! ToolDefinition::from_fn(|kwargs| async move {
//! let n = kwargs.require_int("n")?;
//! Ok(Value::Int(n * 2))
//! }),
//! );
//! let interp = Interpreter::new(
//! InterpreterDeps { tools },
//! InterpreterConfig::default(),
//! );
//! let resp = interp
//! .execute(
//! "result = double(n=x)\nprint(result)",
//! &Tools::new(),
//! HashMap::from([("x".to_string(), Value::Int(42))]),
//! )
//! .await;
//! assert!(resp.is_ok());
//! # }
//! ```
//!
//! Registered tools on [`InterpreterDeps`] and the per-call `tools` argument are
//! merged; on a name clash the per-call tool wins.
//!
//! # Contracts worth knowing
//!
//! - **Tool errors** surface as [`InterpreterError::Tool`]. Uncaught, they fail
//! the host `execute` call; inside user Python they become a generic
//! `Exception` and **can** be caught by bare `except` / `except Exception`.
//! - **State export** ([`Interpreter::export_state`]) is a **versioned byte
//! blob** (4-byte little-endian `STATE_FORMAT_VERSION` + JSON body).
//! Mismatched versions fail with [`InterpreterError::StateFormatSuperseded`].
//! Lazy tool proxies are omitted. Signing is a host concern.
//! - **Language surface** is intentional, not accidental. Divergences and the
//! stdlib allowlist live in the repo’s `CONFORMANCE.md`; the security boundary
//! is described in `THREAT_MODEL.md`.
//! - **Integers** use a hybrid representation: values that fit in `i64` stay
//! compact; larger results promote automatically (CPython-like arbitrary
//! precision). Extremely large powers/shifts are resource-capped.
//! - **ExceptionGroup** / `except*` (PEP 654 leaf split) are available; nested
//! group APIs are still incomplete — see CONFORMANCE.
//! - **async/await** is not supported; host code should await around
//! [`Interpreter::execute`] instead.
pub
pub
pub
pub
pub
pub
// --- Public re-exports: core types ---
pub use InterpreterConfig;
pub use InterpreterError;
pub use ;
// Wire-format version for state checkpoints (export/import).
pub use STATE_FORMAT_VERSION;
// --- Public re-exports: tool system ---
pub use ;
// Host-facing value surface. Deeper interpreter shapes (`ClassValue`,
// `FunctionDef`, `MatchValue`, …) remain available under `interpretthis::value`
// for advanced hosts but are intentionally not re-exported at the crate root.
pub use ;