|
2 | 2 |
|
3 | 3 | ## Quick Orientation |
4 | 4 |
|
5 | | -dart_monty is a pure Dart package that exposes the Monty sandboxed Python |
6 | | -interpreter to Dart and Flutter applications. It wraps pydantic's `monty` |
7 | | -Rust crate via two execution paths: native (FFI to a shared library) and |
8 | | -web (JS interop to a WASM module running in a Web Worker). |
9 | | - |
10 | | -`MontyRuntime` is the recommended high-level API for stateful sessions with |
11 | | -extensions and OS-level interception. |
| 5 | +dart_monty is a pure Dart package for running sandboxed Python through |
| 6 | +`dart_monty_core`. `MontyRuntime` owns the high-level execution interface: |
| 7 | +stateful or fresh-session execution, host functions, extensions, OS handlers, |
| 8 | +and bridge events. |
12 | 9 |
|
13 | 10 | ## Architecture Diagrams |
14 | 11 |
|
15 | 12 | ### Diagram 1: High-Level Package Dependency |
16 | 13 |
|
17 | | -This diagram provides a simple, high-level overview of the main components and their dependencies, illustrating how the packages fit together. |
18 | | - |
19 | 14 | ```mermaid |
20 | 15 | graph TD |
21 | | - subgraph User Application |
22 | | - A[Dart/Flutter App] |
23 | | - end |
24 | | -
|
25 | | - subgraph dart_monty |
26 | | - B(MontyRuntime API) |
27 | | - end |
28 | | -
|
29 | | - subgraph dart_monty_core |
30 | | - C(Low-Level Engine) |
31 | | - end |
32 | | -
|
33 | | - subgraph Rust |
34 | | - D{Monty Crate} |
35 | | - end |
36 | | -
|
37 | | - A --> B |
38 | | - B --> C |
39 | | - C --> D |
| 16 | + A[Dart application] --> B[MontyRuntime] |
| 17 | + B --> C[dart_monty_core] |
| 18 | + C --> D[Monty pool and sessions] |
| 19 | + D --> E[Native worker or Web Worker] |
40 | 20 | ``` |
41 | 21 |
|
42 | | -### Diagram 2: API Layering & Abstraction |
43 | | - |
44 | | -This diagram illustrates the separation of concerns and how the APIs are layered, from the user-facing runtime down to the platform-specific backends. |
| 22 | +### Diagram 2: dart_monty Layers |
45 | 23 |
|
46 | 24 | ```mermaid |
47 | 25 | graph TD |
48 | | - subgraph dart_monty [High-Level API] |
49 | | - A(MontyRuntime) |
50 | | - B(ExtensionCoordinator) |
51 | | - C(PlatformBridge) |
52 | | - D(OsCallHandler) |
53 | | - end |
54 | | -
|
55 | | - subgraph dart_monty_core [Low-Level Engine] |
56 | | - E(MontyPlatform) |
57 | | - F(MontyRepl) |
58 | | - G[FFI Backend] |
59 | | - H[WASM Backend] |
60 | | - end |
61 | | -
|
62 | | - A --> B & C |
63 | | - B --> C |
64 | | - C --> D & E |
65 | | - E --> F |
66 | | - F --> G & H |
| 26 | + A[Runtime] --> B[Bridge] |
| 27 | + A --> C[Extension] |
| 28 | + B --> D[Host] |
| 29 | + C --> D |
| 30 | + C --> E[OS call] |
| 31 | + E --> F[Workspace] |
| 32 | + B --> G[Core pool and session] |
| 33 | + F --> G |
67 | 34 | ``` |
68 | 35 |
|
69 | | -### Diagram 3: Execution Flow for a Tool Call |
70 | | - |
71 | | -This diagram shows the sequence of events when a user calls `execute` and the Python code invokes a host function (a "tool"). |
| 36 | +### Diagram 3: Execution Flow for a Host Function |
72 | 37 |
|
73 | 38 | ```mermaid |
74 | 39 | sequenceDiagram |
75 | 40 | actor User |
76 | 41 | participant RT as MontyRuntime |
77 | | - participant PB as PlatformBridge |
78 | | - participant MR as MontyRepl (Core) |
79 | | - participant HF as Host Function (Dart) |
| 42 | + participant B as MontyBridge |
| 43 | + participant S as MontySession |
| 44 | + participant H as HostFunction |
80 | 45 |
|
81 | 46 | User->>RT: execute("my_tool()") |
82 | | - RT->>PB: execute("my_tool()") |
83 | | - PB->>MR: feedRun("my_tool()") |
84 | | - MR-->>PB: Yields (Pending Tool Call) |
85 | | - PB->>HF: Invoke handler for "my_tool" |
86 | | - HF-->>PB: Returns result |
87 | | - PB->>MR: resume(result) |
88 | | - MR-->>PB: Completes |
89 | | - PB-->>RT: ExecutionHandle completes |
90 | | - RT-->>User: Returns MontyResult |
| 47 | + RT->>B: execute |
| 48 | + B->>S: feedRun |
| 49 | + S-->>B: host-function request |
| 50 | + B->>H: invoke handler |
| 51 | + H-->>B: MontyValue |
| 52 | + B->>S: resume result |
| 53 | + S-->>B: MontyValue |
| 54 | + B-->>RT: BridgeRunFinished |
| 55 | + RT-->>User: ExecutionHandle.result |
91 | 56 | ``` |
92 | 57 |
|
93 | 58 | ## Internal Module Structure |
94 | 59 |
|
95 | 60 | ```text |
96 | | -dart_monty (high-level API package) |
| 61 | +dart_monty |
97 | 62 | │ |
98 | | - ├── lib/src/runtime/ (session management) |
99 | | - │ ├── MontyRuntime (high-level session facade) |
100 | | - │ └── ExecutionHandle (async execution control) |
101 | | - │ |
102 | | - ├── lib/src/bridge/ (tool-calling layer) |
103 | | - │ ├── PlatformBridge (tool schema + dispatch logic) |
104 | | - │ └── BridgeEvent (streamable execution events) |
105 | | - │ |
106 | | - ├── lib/src/extension/ (extension system) |
107 | | - │ ├── MontyExtension (abstract base) |
108 | | - │ └── ExtensionCoordinator (lifecycle and registration) |
109 | | - │ |
110 | | - └── lib/src/os_call/ (VFS and OS-level interception) |
111 | | - └── OsCallHandler (operation interception logic) |
112 | | -
|
113 | | -dart_monty_core (low-level core engine package) |
114 | | - │ |
115 | | - ├── lib/src/platform/ (abstract contract, pure Dart) |
116 | | - │ ├── MontyPlatform (abstract class) |
117 | | - │ ├── MontyCoreBindings (unified bindings contract) |
118 | | - │ └── MontyResult, MontyException, MontyStackFrame, ... |
119 | | - │ |
120 | | - ├── lib/src/repl/ (stateful Python REPL) |
121 | | - │ ├── MontyRepl (persistent Rust-backed REPL) |
122 | | - │ └── ReplPlatform (adapts MontyRepl to MontyPlatform) |
123 | | - │ |
124 | | - ├── lib/src/ffi/ (native FFI backend) |
125 | | - │ └── MontyFfi (FFI implementation) |
126 | | - │ |
127 | | - └── lib/src/wasm/ (web WASM backend) |
128 | | - └── MontyWasm (WASM implementation) |
| 63 | + ├── lib/src/runtime/ MontyRuntime and ExecutionHandle |
| 64 | + ├── lib/src/bridge/ MontyBridge and BridgeEvent streaming |
| 65 | + ├── lib/src/extension/ MontyExtension attachment and child policy |
| 66 | + ├── lib/src/extensions/ Built-in sandbox and event-loop extensions |
| 67 | + ├── lib/src/host/ Host functions, schemas, parameters, dispatch |
| 68 | + ├── lib/src/os_call/ OS handler composition |
| 69 | + └── lib/src/workspace/ Child workspace ownership and transfers |
| 70 | + │ |
| 71 | + ▼ |
| 72 | +dart_monty_core Monty pool, MontySession, values, OSAccess |
| 73 | + │ |
| 74 | + ▼ |
| 75 | +native worker or Web Worker |
129 | 76 | ``` |
130 | 77 |
|
131 | 78 | ## Platform Support Matrix |
132 | 79 |
|
133 | | -| Platform | Module | Status | Library | |
134 | | -|----------|--------|--------|---------| |
135 | | -| macOS | dart_monty_core (FFI) | Supported | `.dylib` | |
136 | | -| Linux | dart_monty_core (FFI) | Supported | `.so` | |
137 | | -| Web | dart_monty_core (WASM) | Supported | WASM via Worker | |
138 | | -| iOS | dart_monty_core (FFI) | Planned (M9) | `.a` static | |
139 | | -| Android | dart_monty_core (FFI) | Planned (M9) | `.so` via NDK | |
140 | | -| Windows | dart_monty_core (FFI) | Planned (M9) | `.dll` via MSVC | |
| 80 | +| Runtime layer | Responsibility | Public entry point | |
| 81 | +|---|---|---| |
| 82 | +| dart_monty | Runtime lifecycle and application capabilities | `MontyRuntime.start` | |
| 83 | +| dart_monty | Python-to-Dart calls and execution events | `MontyBridge`, `HostFunction` | |
| 84 | +| dart_monty | Child execution and workspace composition | `SandboxExtension`, `OSAccess` | |
| 85 | +| dart_monty_core | Pool, session, values, limits, and worker transport | `Monty`, `MontySession`, `ResourceLimits` | |
141 | 86 |
|
142 | 87 | ## Choosing the Right API |
143 | 88 |
|
144 | 89 | | Use case | API | Example | |
145 | | -|----------|-----|---------| |
146 | | -| Stateful session with tools | `MontyRuntime` | `final session = MontyRuntime(extensions: ...)` | |
147 | | -| Simple stateful evaluation | `MontyRepl` | `final repl = MontyRepl(); repl.feedRun('x=1')` | |
148 | | -| One-shot stateless evaluation | `Monty.exec()` | `await Monty.exec('2+2')` | |
| 90 | +|---|---|---| |
| 91 | +| Stateful Python execution with application capabilities | `MontyRuntime` | `final runtime = await MontyRuntime.start()` | |
| 92 | +| Direct core session feed | `Monty` and `MontySession` | `await Monty.withPool((pool) => pool.withSession((session) => session.feedRun('2 + 2')))` | |
| 93 | +| Python-callable Dart capability | `HostFunction` | `runtime.register(function)` | |
149 | 94 |
|
150 | 95 | ## Tool Calling & LLM Integration |
151 | 96 |
|
152 | | -The `MontyRuntime` and `PlatformBridge` serve two audiences simultaneously: |
153 | | - |
154 | | -1. **Python side** -- host functions are callable from sandboxed Python by |
155 | | - name (e.g., `search("query")`). |
156 | | -2. **LLM side** -- the same functions are advertised as tool schemas |
157 | | - (`HostFunctionSchema`) that LLMs use to generate Python code. |
| 97 | +`MontyRuntime` registers `HostFunction` values with its bridge. A function has |
| 98 | +a `HostFunctionSchema` for tool definitions and a handler that returns a |
| 99 | +`MontyValue` when Python calls the function. `runtime.schemas` exposes the |
| 100 | +registered schemas, and `runtime.events` exposes execution and host-call |
| 101 | +events. |
158 | 102 |
|
159 | | -This dual-audience pattern means you register a tool once and get both a |
160 | | -callable Python function and an LLM-compatible tool definition. |
| 103 | +`OsHandler` handles OS calls from Python. Extensions contribute handlers with |
| 104 | +`MontyExtension.osContribution`, or register one during attachment through |
| 105 | +`AttachContext.registerOs`. |
161 | 106 |
|
162 | | -For the `OsCallHandler` layer, see [OsCall / VFS Layer](../deep-dives/oscall-vfs.md). |
| 107 | +See [OsCall / VFS Layer](../deep-dives/oscall-vfs.md) for workspace and OS |
| 108 | +access policy. |
0 commit comments