aether-lang-runtime 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,457 @@
1
+ Metadata-Version: 2.5
2
+ Name: aether-lang-runtime
3
+ Version: 0.1.0
4
+ Summary: AI-Safe Execution Infrastructure: structured, sandboxed, reversible AI code modification
5
+ License: MIT
6
+ Keywords: agents,ai,execution,patch,safe,sandbox
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Security
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: jsonschema>=4.22
18
+ Requires-Dist: libcst>=1.1.0
19
+ Requires-Dist: pathspec>=0.12
20
+ Requires-Dist: zstandard>=0.23; sys_platform != 'win32'
21
+ Provides-Extra: dev
22
+ Requires-Dist: mypy>=1.10; extra == 'dev'
23
+ Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
24
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
25
+ Requires-Dist: pytest>=8.0; extra == 'dev'
26
+ Requires-Dist: ruff>=0.5; extra == 'dev'
27
+ Provides-Extra: wasm
28
+ Requires-Dist: wasmtime>=23.0; extra == 'wasm'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # AI-Safe Execution Infrastructure
32
+
33
+ > **A structured, sandboxed, and reversible execution layer for AI-driven code modification.**
34
+
35
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
37
+ [![Tests](https://img.shields.io/badge/tests-94%20passed-brightgreen.svg)](#testing)
38
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](#requirements)
39
+
40
+ ---
41
+
42
+ ## The Problem
43
+
44
+ When AI agents generate code and apply it directly to a codebase, several fundamental failure modes emerge:
45
+
46
+ | Failure | Impact |
47
+ |:--------|:-------|
48
+ | **Syntax errors** | File is broken, app crashes |
49
+ | **Semantic errors** | Logic is wrong, tests fail silently |
50
+ | **Uncontrolled execution** | Changes applied directly against live state |
51
+ | **No rollback path** | Recovery requires manual `git reset` or worse |
52
+ | **Ambiguous intent** | Agent emits free-form diffs, no structured contract |
53
+
54
+ `aether-lang-runtime` reframes the problem: instead of agents generating raw source code, they emit **structured patch instructions** — a typed JSON contract — that the runtime validates, sandboxes, and commits or rolls back automatically.
55
+
56
+ ---
57
+
58
+ ## Architecture
59
+
60
+ ```
61
+ ┌─────────────────────────────────────────────────────────────────┐
62
+ │ AI Agent │
63
+ │ (LLM, Copilot, AutoGPT, etc.) │
64
+ └────────────────────────┬────────────────────────────────────────┘
65
+ │ Structured Patch (JSON)
66
+
67
+ ┌─────────────────────────────────────────────────────────────────┐
68
+ │ Validation Layer │
69
+ │ │
70
+ │ Gate 1 ──── JSON Schema (Draft 2020-12) │
71
+ │ • Action type enforcement │
72
+ │ • UUID patch_id required │
73
+ │ • Payload size ceiling (64 KB) │
74
+ │ • Timeout bounds [100ms – 30s] │
75
+ │ │
76
+ │ Gate 2 ──── Allow-list & Security Rules │
77
+ │ • (action, operation) allow-list │
78
+ │ • No absolute paths / path traversal │
79
+ │ • No os.system / subprocess / eval in payload │
80
+ │ • run_script requires explicit trust elevation │
81
+ └────────────────────────┬────────────────────────────────────────┘
82
+ │ Valid patch only
83
+
84
+ ┌─────────────────────────────────────────────────────────────────┐
85
+ │ Snapshot System │
86
+ │ │
87
+ │ • Captures project state → .tar.gz archive │
88
+ │ • .gitignore + .ai_runtimeignore aware │
89
+ │ • Always skips: node_modules / venv / __pycache__ / .git │
90
+ │ • SQLite WAL index (concurrent-reader safe) │
91
+ │ • Cross-platform write lock (fcntl / msvcrt) │
92
+ │ • Atomic rename: no partial archives ever on disk │
93
+ └────────────────────────┬────────────────────────────────────────┘
94
+
95
+
96
+ ┌─────────────────────────────────────────────────────────────────┐
97
+ │ Sandbox Execution │
98
+ │ │
99
+ │ Tier 1 ── Cranelift JIT (zero-syscall, v1.2+) │
100
+ │ Tier 2 ── Wasmtime/WASM (hardware boundary, v1.1+) │
101
+ │ Tier 3 ── Subprocess (OS process isolation, v1.0 ✅) │
102
+ │ • Windows: Win32 Job Objects (memory limit) │
103
+ │ • Linux: resource.setrlimit (RLIMIT_AS + CPU) │
104
+ │ • Timeout enforced via communicate(timeout=) │
105
+ │ • CREATE_NEW_PROCESS_GROUP (Windows signal safety) │
106
+ │ • setsid() + preexec_fn (Unix process group) │
107
+ └────────────────────────┬────────────────────────────────────────┘
108
+
109
+ ┌──────────┴──────────┐
110
+ │ │
111
+ Success Failure
112
+ │ │
113
+ ▼ ▼
114
+ ┌──────────┐ ┌──────────────┐
115
+ │ Commit │ │ Rollback │
116
+ │ snapshot │ │ from archive │
117
+ └──────────┘ └──────────────┘
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Project Layout
123
+
124
+ ```
125
+ aether-lang/
126
+ ├── sdk/
127
+ │ └── python/
128
+ │ ├── ai_runtime/
129
+ │ │ ├── __init__.py # Public API: PatchEngine, Sandbox, etc.
130
+ │ │ ├── _types.py # Shared dataclasses (ExecutionResult, SnapshotHandle)
131
+ │ │ ├── patch_engine.py # PatchEngine — validate() + apply() orchestrator
132
+ │ │ ├── sandbox.py # Sandbox — tier-dispatching execution environment
133
+ │ │ ├── sandbox_t3.py # T3 subprocess backend (Windows + Unix)
134
+ │ │ ├── sandbox_runner.py # Worker script run inside child process
135
+ │ │ ├── validation/
136
+ │ │ │ ├── patch_schema.json # JSON Schema Draft 2020-12 contract
137
+ │ │ │ ├── schema.py # Gate 1: schema validator
138
+ │ │ │ └── rules.py # Gate 2: allow-list + security rules
139
+ │ │ └── snapshot/
140
+ │ │ ├── __init__.py
141
+ │ │ ├── store.py # SnapshotStore — capture/restore/commit/prune
142
+ │ │ ├── gitignore.py # .gitignore-aware file collector
143
+ │ │ └── lock.py # Cross-platform advisory file lock
144
+ │ └── tests/
145
+ │ ├── test_validation.py # Phase 1: 34 tests
146
+ │ ├── test_sandbox.py # Phase 2: 26 tests (cross-platform)
147
+ │ ├── test_sandbox_t3_windows.py # Phase 2: 3 tests (Windows-only)
148
+ │ └── test_snapshot.py # Phase 3: 31 tests
149
+ ├── architecture doc/
150
+ │ └── AI-Safe-Execution-Infrastructure-Documentation.md
151
+ └── crates/ # Legacy Aether language compiler (Cranelift/Rust)
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Quick Start
157
+
158
+ ### Install
159
+
160
+ ```bash
161
+ pip install aether-lang-runtime
162
+ ```
163
+
164
+ ### Basic usage
165
+
166
+ ```python
167
+ import uuid
168
+ from ai_runtime import PatchEngine
169
+
170
+ engine = PatchEngine()
171
+
172
+ patch = {
173
+ "schema_version": "1.0",
174
+ "patch_id": str(uuid.uuid4()), # must be valid UUID v4
175
+ "action": "modify_function",
176
+ "target": {
177
+ "file": "src/app.py", # relative path only
178
+ "symbol": "calculate_total",
179
+ "symbol_type": "function",
180
+ },
181
+ "changes": {
182
+ "operation": "replace_body",
183
+ "payload": " return sum(items)",
184
+ },
185
+ }
186
+
187
+ report = engine.validate(patch)
188
+ if report.ok:
189
+ engine.apply(patch)
190
+ print(f"✅ Applied in {report.elapsed_ms:.1f}ms")
191
+ else:
192
+ print(f"❌ Rejected: {report.first_error}")
193
+ ```
194
+
195
+ ### Agent CLI
196
+
197
+ After installation, agents can use Aether without writing Python glue:
198
+
199
+ ```bash
200
+ aether validate patch.json
201
+ aether apply patch.json
202
+ aether rollback <snapshot-id>
203
+ ```
204
+
205
+ `aether apply` runs validation through `PatchOrchestrator`, captures a snapshot,
206
+ applies the patch, and rolls back if application fails. `ae-safe` is kept as a
207
+ backwards-compatible alias for the same CLI.
208
+
209
+ ### With snapshot + auto-rollback
210
+
211
+ ```python
212
+ from ai_runtime import PatchEngine, Sandbox
213
+
214
+ sandbox = Sandbox(project_root=".")
215
+ engine = PatchEngine(sandbox=sandbox)
216
+
217
+ # Capture state before any change
218
+ handle = sandbox.snapshot(patch_id=patch["patch_id"])
219
+
220
+ report = engine.validate(patch)
221
+ if report.ok:
222
+ result = engine.apply(patch)
223
+ if result and result.failed:
224
+ # Execution failed — restore immediately
225
+ sandbox.restore(handle)
226
+ print(f"⚠️ Rolled back: {result.error}")
227
+ else:
228
+ sandbox.commit_snapshot(handle)
229
+ print("✅ Committed")
230
+ else:
231
+ print(f"❌ Rejected at gate {report.first_error}")
232
+ ```
233
+
234
+ ### Execute a sandboxed script
235
+
236
+ ```python
237
+ from ai_runtime import Sandbox
238
+
239
+ with Sandbox(project_root=".") as sb:
240
+ result = sb.execute(
241
+ payload="print('hello from sandbox')",
242
+ timeout_ms=5000,
243
+ memory_limit_mb=128,
244
+ )
245
+
246
+ print(result.stdout) # "hello from sandbox"
247
+ print(result.tier) # "t3_subprocess"
248
+ print(result.succeeded) # True
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Patch Schema
254
+
255
+ Every patch must be a JSON object conforming to [patch_schema.json](ai_runtime/validation/patch_schema.json) (JSON Schema Draft 2020-12).
256
+
257
+ ### Required fields
258
+
259
+ | Field | Type | Description |
260
+ |:------|:-----|:------------|
261
+ | `schema_version` | `"1.0"` | Schema version — must be exactly `"1.0"` |
262
+ | `patch_id` | UUID v4 string | Unique identifier for idempotency tracking |
263
+ | `action` | enum | One of the 7 supported actions below |
264
+ | `target.file` | string | **Relative** path to the target file |
265
+ | `changes.operation` | string | Operation type (must be in allow-list for action) |
266
+ | `changes.payload` | string | Code content, max 64 KB |
267
+
268
+ ### Supported actions
269
+
270
+ | Action | Operations | Description |
271
+ |:-------|:-----------|:------------|
272
+ | `modify_function` | `replace_body`, `insert_before`, `insert_after`, `update_logic` | Modify an existing function |
273
+ | `add_function` | `replace_body` | Insert a new function |
274
+ | `remove_function` | `replace_body` | Delete a function |
275
+ | `modify_class` | `replace_body`, `insert_before`, `insert_after` | Modify a class |
276
+ | `update_import` | `add_import`, `remove_import` | Add or remove imports |
277
+ | `replace_block` | `context_replace` | Context-based block replacement |
278
+ | `run_script` | `run` | Execute a script (requires `trust_level='elevated'`) |
279
+
280
+ ### Optional fields
281
+
282
+ ```json
283
+ {
284
+ "constraints": {
285
+ "timeout_ms": 5000,
286
+ "memory_limit_mb": 128,
287
+ "allow_network": false,
288
+ "allow_filesystem": false
289
+ },
290
+ "metadata": {
291
+ "generated_by": "my-agent-v1",
292
+ "model": "gemini-2.0-flash",
293
+ "confidence": 0.95
294
+ }
295
+ }
296
+ ```
297
+
298
+ ---
299
+
300
+ ## Security Model
301
+
302
+ ### Two-gate validation
303
+
304
+ ```
305
+ Patch JSON
306
+
307
+
308
+ Gate 1: JSON Schema ─── rejects malformed structure
309
+
310
+ ▼ (valid)
311
+ Gate 2: Security Rules
312
+ ├── Operation allow-list ────── unknown (action, operation) pairs rejected
313
+ ├── Path safety ─────────────── absolute paths, ../ traversal blocked
314
+ ├── Payload patterns ────────── os.system / subprocess / eval blocked
315
+ └── Trust elevation ─────────── run_script requires explicit elevated trust
316
+
317
+ ▼ (valid)
318
+ Execution
319
+ ```
320
+
321
+ ### What is NOT protected by this layer
322
+
323
+ - **AI model hallucination**: The runtime validates structure and security, not semantic correctness. A syntactically valid patch can still produce wrong program behaviour.
324
+ - **Supply chain attacks**: Malicious packages in the project's dependencies are not audited.
325
+ - **Persistent rootkits**: A sufficiently clever payload could attempt to escape the T3 subprocess sandbox. T1 (Cranelift) and T2 (WASM) are the hardened tiers for untrusted code.
326
+
327
+ ---
328
+
329
+ ## Sandbox Tiers
330
+
331
+ | Tier | Technology | Memory Limit | Syscall Restriction | Status |
332
+ |:-----|:-----------|:-------------|:--------------------|:-------|
333
+ | **T3** | OS subprocess | Win32 Job Objects / `RLIMIT_AS` | None (process boundary only) | ✅ v1.0 |
334
+ | **T2** | Wasmtime/WASI | WASM linear memory | WASI capabilities | 🔜 v1.1 |
335
+ | **T1** | Cranelift JIT | Custom memory allocator | Zero syscall surface | 🔜 v1.2 |
336
+
337
+ Tier selection is automatic (`preferred_tier="auto"`). T3 is always available; T1/T2 are used when their respective runtimes are detected.
338
+
339
+ ---
340
+
341
+ ## Snapshot System
342
+
343
+ ### Storage layout
344
+
345
+ ```
346
+ <project_root>/
347
+ └── .ai_runtime/
348
+ ├── snapshot.lock ← Advisory write lock (fcntl / msvcrt)
349
+ ├── snapshots.db ← SQLite index (WAL mode)
350
+ └── snapshots/
351
+ ├── <uuid>.tar.gz ← Compressed project archive
352
+ └── ...
353
+ ```
354
+
355
+ ### What gets snapshotted
356
+
357
+ The file collector applies a layered exclusion strategy:
358
+
359
+ ```
360
+ All files in project_root
361
+
362
+ ▼ Tier 1: O(1) frozenset fast-skip
363
+ │ (node_modules, .git, venv, __pycache__, dist, target, ...)
364
+
365
+ ▼ Tier 2: pathspec regex
366
+ │ (*.pyc, *.egg-info/, *.so, ...)
367
+
368
+ ▼ Tier 3: .gitignore patterns
369
+
370
+ ▼ Tier 4: .ai_runtimeignore patterns
371
+
372
+ ▼ Tier 5: Size ceiling (> 5 MB per file → skip)
373
+
374
+
375
+ Source files to archive
376
+ ```
377
+
378
+ ### Snapshot lifecycle
379
+
380
+ ```
381
+ capture("patch-123") status = 'pending'
382
+
383
+ ├── patch applied OK ──▶ commit(handle) status = 'committed'
384
+
385
+ └── execution failed ──▶ restore(handle) status = 'rolled_back'
386
+
387
+ prune(keep=10) ──▶ deletes oldest committed/rolled_back archives
388
+ ```
389
+
390
+ ### Concurrency
391
+
392
+ Multiple agents can operate on the same project simultaneously:
393
+ - `validate()` — fully parallel (read-only, no locking)
394
+ - `capture()` / `restore()` — serialized via advisory write lock per project root
395
+ - SQLite WAL mode — concurrent readers never block during write
396
+
397
+ ---
398
+
399
+ ## Performance SLOs
400
+
401
+ | Operation | Target | Measured (this machine) |
402
+ |:----------|:-------|:------------------------|
403
+ | `validate()` | < 20 ms | **0.12 ms** |
404
+ | `capture()` (< 50 MB project) | < 100 ms | passes ✅ |
405
+ | `restore()` | < 500 ms | passes ✅ |
406
+ | T3 sandbox overhead | < 500 ms | < 200 ms |
407
+ | T3 timeout enforcement | within 2× budget | ✅ |
408
+
409
+ ---
410
+
411
+ ## Testing
412
+
413
+ ```bash
414
+ # Install with dev dependencies
415
+ pip install -e ".[dev]"
416
+
417
+ # Run full suite
418
+ pytest tests/ -v
419
+
420
+ # Phase-by-phase
421
+ pytest tests/test_validation.py # Phase 1 — 34 tests
422
+ pytest tests/test_sandbox.py # Phase 2 — 26 tests
423
+ pytest tests/test_snapshot.py # Phase 3 — 31 tests
424
+ pytest tests/test_sandbox_t3_windows.py # Windows-only — 3 tests
425
+ ```
426
+
427
+ Current suite: **94 tests, 94 passed** (Python 3.14 / Windows 11)
428
+
429
+ ---
430
+
431
+ ## Roadmap
432
+
433
+ | Phase | Status | Description |
434
+ |:------|:-------|:------------|
435
+ | 1 — Validation Layer | ✅ Done | JSON Schema Gate + security rule allow-list |
436
+ | 2 — Sandbox (T3) | ✅ Done | Subprocess isolation, Windows Job Objects, Unix rlimit |
437
+ | 3 — Snapshot System | ✅ Done | `.tar.gz` archives, SQLite WAL, gitignore-aware, cross-platform locks |
438
+ | 4 — Observability | ✅ Done | Structured diffs, audit log, `aether status` CLI |
439
+ | 5 — AST Apply Engine | 🔄 Next | Real `modify_function` / `add_function` via `ast` + `libcst` |
440
+ | 6 — Node.js SDK | 🔜 Planned | `sdk/node/` TypeScript port |
441
+ | 7 — T2 Sandbox (WASM) | 🔜 Planned | Wasmtime WASI integration |
442
+ | 8 — T1 Sandbox (JIT) | 🔜 Planned | Cranelift FFI from existing `crates/ae-codegen` |
443
+
444
+ ---
445
+
446
+ ## Requirements
447
+
448
+ - Python ≥ 3.11
449
+ - `jsonschema >= 4.22`
450
+ - `pathspec >= 0.12`
451
+ - No Docker, no external daemons, no root required
452
+
453
+ ---
454
+
455
+ ## License
456
+
457
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,28 @@
1
+ ai_runtime/__init__.py,sha256=KsWuqEL2rNZImhJ_ApeiAzW5V_sV7u_PEAcvdcDOvSs,896
2
+ ai_runtime/_types.py,sha256=Rq-NCr9UdRMuZt8Cmj-mAW4sjQjEMXELNu19R8WcRgI,2333
3
+ ai_runtime/cli.py,sha256=_6YUWibr1mYQSUhSVCrZ_raCFa3ivGtR8QELNfMwYCY,8320
4
+ ai_runtime/orchestrator.py,sha256=tWEkO7ufvpx6gdUr9dX4Ij53auQDZgDD_e6_PLM_Pdc,13857
5
+ ai_runtime/patch_engine.py,sha256=Oj4RNs364hcSBzIfl1orLCVegvo0slFHcfc_b1AJQpQ,8654
6
+ ai_runtime/sandbox.py,sha256=l7Hzv80MvFW6ZjwYQ7hHD7hOHaoNYMevLLMGAXpNWxE,10359
7
+ ai_runtime/sandbox_runner.py,sha256=GxlomublWBXnBVZDFZyxIpEHg93CN9zRQTCGTRunELI,5494
8
+ ai_runtime/sandbox_t1.py,sha256=Ixt-DH7ZzIBK5q2kfd-neocD_alnDy9Xcvspx9CwxWM,12583
9
+ ai_runtime/sandbox_t2.py,sha256=bIISJZWcpp0USmWJNDokYnffXd9XeuyWuJvpXksPr1M,7575
10
+ ai_runtime/sandbox_t3.py,sha256=fZb4FKuOViZcepLmTuW7wNPzqR0d_B9v-j6PoIvgRVE,14957
11
+ ai_runtime/ast/engine.py,sha256=mYcVaIaL6GX9iZ2iTraq6TdGIASy7sJOr_Gxnv04sY4,11217
12
+ ai_runtime/observability/__init__.py,sha256=WLRRSBStKrJVJMUsS19ZxWjr5WKBUxaJS6KPKe5g3-w,421
13
+ ai_runtime/observability/audit_log.py,sha256=06kGe-XVTWbEOqXdWQ4MLYMQ0v50P40su_u2s8MGRIQ,7410
14
+ ai_runtime/observability/diff.py,sha256=MwI3Zr4dlEC7EubMBo-7pnWB6BVTkYnhz2x3kw3faig,10288
15
+ ai_runtime/observability/events.py,sha256=zUW_3c32kl0VK0YD3YKb4sNpXZHNrSj5UiUHZRSPOgc,2643
16
+ ai_runtime/snapshot/__init__.py,sha256=DeftVT4a9Ym_s3tpYX7vFfYq83i0L1LvECAxPl_xc8M,210
17
+ ai_runtime/snapshot/gitignore.py,sha256=xzF1UOhuDiBU8wKZ9cxErDkXs7HHOSr_kTNFSGcio-8,5903
18
+ ai_runtime/snapshot/lock.py,sha256=CBMcbzO1_VSzKKjoIwkjyGbRO5zYiYbTr6_DDKegO_Q,4139
19
+ ai_runtime/snapshot/store.py,sha256=xaPrhUnUlJk2XIr_Rs926aZsCIrbpy-KNSrAqt_1Z2M,16917
20
+ ai_runtime/validation/__init__.py,sha256=zapdN2L_XaRc9ZCoFBFmqlswGecHEnsMEAJ61g7a4Cw,692
21
+ ai_runtime/validation/ae_bridge.py,sha256=20p1r1vl4PwQHsxe_70Z_7kNSZXxrhjmw2tu_1rUAjE,12758
22
+ ai_runtime/validation/patch_schema.json,sha256=8Pqxj00L5PAdCFgFshFU2T5KPfvSSwiqwPbwqRNVbrI,7648
23
+ ai_runtime/validation/rules.py,sha256=mJ41KaMC9jK-vUKK9KBznL6cd8AZtbc9vLOZT4d2MDg,7952
24
+ ai_runtime/validation/schema.py,sha256=lX9zZ9CLCcdveftTGPEMkiXtE7wCALNj3O-5LdJ0UTA,3399
25
+ aether_lang_runtime-0.1.0.dist-info/METADATA,sha256=yiadBvHmw6EQvRHyXipjYqGU3v584UparxpjMX3ckmA,18077
26
+ aether_lang_runtime-0.1.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
27
+ aether_lang_runtime-0.1.0.dist-info/entry_points.txt,sha256=y4Z4L0w16GG2781mGkPXZKnzusU2bvW4_nB-1aRXWaM,77
28
+ aether_lang_runtime-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ ae-safe = ai_runtime.cli:main
3
+ aether = ai_runtime.cli:main
ai_runtime/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ """
2
+ ai_runtime
3
+ ~~~~~~~~~~~
4
+ AI-Safe Execution Infrastructure — Python SDK
5
+
6
+ Provides a safe, reversible, auditable execution layer for AI-driven code
7
+ modification. AI agents emit structured patches; this runtime validates,
8
+ sandboxes, and commits or rolls back the resulting changes.
9
+
10
+ Quick start:
11
+ from ai_runtime import PatchEngine, Sandbox
12
+
13
+ engine = PatchEngine()
14
+ report = engine.validate(my_patch_dict)
15
+ if report.ok:
16
+ engine.apply(my_patch_dict)
17
+ else:
18
+ print(report.first_error)
19
+ """
20
+
21
+ from .patch_engine import PatchEngine, ValidationReport
22
+ from .sandbox import Sandbox
23
+ from ._types import ExecutionResult, SnapshotHandle
24
+ from .orchestrator import PatchOrchestrator, OrchestratorResult
25
+
26
+ __version__ = "0.1.0"
27
+ __all__ = [
28
+ "PatchEngine", "ValidationReport", "Sandbox",
29
+ "ExecutionResult", "SnapshotHandle",
30
+ "PatchOrchestrator", "OrchestratorResult",
31
+ ]
ai_runtime/_types.py ADDED
@@ -0,0 +1,66 @@
1
+ """
2
+ ai_runtime._types
3
+ ~~~~~~~~~~~~~~~~~
4
+ Shared data-only types for the sandbox subsystem.
5
+ Kept in a separate module to eliminate circular imports between
6
+ sandbox.py and sandbox_t3.py.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import time
12
+ from dataclasses import dataclass, field
13
+ from typing import Optional
14
+
15
+
16
+ @dataclass
17
+ class ExecutionResult:
18
+ """Result of a sandboxed code execution."""
19
+ failed: bool
20
+ exit_code: int
21
+ stdout: str
22
+ stderr: str
23
+ elapsed_ms: float
24
+ tier: str # "t1_cranelift" | "t2_wasm" | "t3_subprocess"
25
+ error: Optional[str] = None
26
+ isolation_level: str = "unknown"
27
+ """
28
+ Isolation mechanism actually applied:
29
+ "audit_hook" — Python sys.addaudithook (T3). Bypassable by indirect imports.
30
+ See SECURITY.md for the full threat model.
31
+ "wasm_sandbox" — Wasmtime WASI sandbox (T2). Hardware-level memory isolation.
32
+ "cranelift_jit" — Cranelift JIT inside process via catch_unwind guard (T1).
33
+ No OS-level isolation; only safe for trusted Aether payloads.
34
+ """
35
+
36
+ @property
37
+ def succeeded(self) -> bool:
38
+ return not self.failed
39
+
40
+ def __bool__(self) -> bool:
41
+ return self.succeeded
42
+
43
+
44
+ @dataclass
45
+ class SnapshotHandle:
46
+ """
47
+ Reference to a pre-modification snapshot captured by SnapshotStore.
48
+
49
+ Fields:
50
+ snapshot_id: UUID identifying this snapshot in snapshots.db.
51
+ project_root: Absolute path to the captured project root.
52
+ patch_id: ID of the patch this snapshot was taken for.
53
+ path: Filesystem path to the .tar.gz archive.
54
+ status: 'pending' | 'committed' | 'rolled_back'
55
+ created_at: Unix timestamp of capture.
56
+ archive_size_bytes: Compressed archive size in bytes (0 if unknown).
57
+ file_count: Number of files in the snapshot (0 if unknown).
58
+ """
59
+ snapshot_id: str
60
+ project_root: str
61
+ patch_id: str = ""
62
+ path: Optional[str] = None
63
+ status: str = "pending"
64
+ created_at: float = field(default_factory=time.time)
65
+ archive_size_bytes: int = 0
66
+ file_count: int = 0