@elizaos/interop 2.0.0-alpha
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.
- package/LICENSE +21 -0
- package/README.md +436 -0
- package/dist/packages/interop/tsconfig.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/typescript/index.d.ts +33 -0
- package/dist/typescript/index.d.ts.map +1 -0
- package/dist/typescript/index.js +121 -0
- package/dist/typescript/python-bridge.d.ts +80 -0
- package/dist/typescript/python-bridge.d.ts.map +1 -0
- package/dist/typescript/python-bridge.js +334 -0
- package/dist/typescript/types.d.ts +301 -0
- package/dist/typescript/types.d.ts.map +1 -0
- package/dist/typescript/types.js +10 -0
- package/dist/typescript/wasm-loader.d.ts +32 -0
- package/dist/typescript/wasm-loader.d.ts.map +1 -0
- package/dist/typescript/wasm-loader.js +269 -0
- package/package.json +43 -0
- package/python/__init__.py +50 -0
- package/python/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/__pycache__/rust_ffi.cpython-313.pyc +0 -0
- package/python/__pycache__/ts_bridge.cpython-313.pyc +0 -0
- package/python/__pycache__/wasm_loader.cpython-313.pyc +0 -0
- package/python/bridge_server.py +505 -0
- package/python/rust_ffi.py +418 -0
- package/python/tests/__init__.py +1 -0
- package/python/tests/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/tests/__pycache__/test_bridge_server.cpython-313-pytest-9.0.2.pyc +0 -0
- package/python/tests/__pycache__/test_interop.cpython-313-pytest-9.0.2.pyc +0 -0
- package/python/tests/__pycache__/test_rust_ffi.cpython-313-pytest-9.0.2.pyc +0 -0
- package/python/tests/__pycache__/test_rust_ffi_loader.cpython-313-pytest-9.0.2.pyc +0 -0
- package/python/tests/test_bridge_server.py +525 -0
- package/python/tests/test_interop.py +319 -0
- package/python/tests/test_rust_ffi.py +352 -0
- package/python/tests/test_rust_ffi_loader.py +71 -0
- package/python/ts_bridge.py +452 -0
- package/python/ts_bridge_runner.mjs +284 -0
- package/python/wasm_loader.py +517 -0
- package/rust/ffi_exports.rs +362 -0
- package/rust/mod.rs +21 -0
- package/rust/py_loader.rs +412 -0
- package/rust/ts_loader.rs +467 -0
- package/rust/wasm_plugin.rs +320 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shaw Walters and elizaOS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# elizaOS Cross-Language Plugin Interoperability
|
|
2
|
+
|
|
3
|
+
This module provides seamless interoperability between elizaOS runtimes written in different languages (Rust, TypeScript, Python). **Any runtime can load any plugin**, regardless of the language it was written in.
|
|
4
|
+
|
|
5
|
+
## Architecture Overview
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────┐
|
|
9
|
+
│ Protocol Buffer Schemas │
|
|
10
|
+
│ (Single source of truth for types) │
|
|
11
|
+
└──────────────────┬──────────────────┘
|
|
12
|
+
│
|
|
13
|
+
┌──────────────────────────────┼──────────────────────────────┐
|
|
14
|
+
▼ ▼ ▼
|
|
15
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
16
|
+
│ RUST RUNTIME │ │ TS RUNTIME │ │ PYTHON RUNTIME │
|
|
17
|
+
│ │ │ │ │ │
|
|
18
|
+
│ • Native Rust │ │ • Native TS │ │ • Native Python │
|
|
19
|
+
│ • TS via IPC │◄──────────►│ • Rust via WASM │◄──────────►│ • Rust via FFI │
|
|
20
|
+
│ • Python via IPC│ │ • Python via IPC│ │ • TS via IPC │
|
|
21
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
22
|
+
│ │ │
|
|
23
|
+
└──────────────────────────────┴──────────────────────────────┘
|
|
24
|
+
│
|
|
25
|
+
┌────────┴────────┐
|
|
26
|
+
▼ ▼
|
|
27
|
+
┌─────────────┐ ┌─────────────────┐
|
|
28
|
+
│ PLUGINS │ │ TEST PLUGINS │
|
|
29
|
+
│ │ │ │
|
|
30
|
+
│ • Rust │ │ • eliza-classic │
|
|
31
|
+
│ • TypeScript│ │ • inmemorydb │
|
|
32
|
+
│ • Python │ │ │
|
|
33
|
+
└─────────────┘ └─────────────────┘
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Complete Interop Matrix
|
|
37
|
+
|
|
38
|
+
Every combination is supported:
|
|
39
|
+
|
|
40
|
+
| Host Runtime | Plugin Language | Method | Performance | Sandboxed |
|
|
41
|
+
| -------------- | --------------- | ------ | ----------- | --------- |
|
|
42
|
+
| **TypeScript** | Rust | WASM | High | ✅ Yes |
|
|
43
|
+
| **TypeScript** | Python | IPC | Medium | ✅ Yes |
|
|
44
|
+
| **TypeScript** | TypeScript | Direct | Native | ❌ No |
|
|
45
|
+
| **Python** | Rust | FFI | Native | ❌ No |
|
|
46
|
+
| **Python** | Rust | WASM | High | ✅ Yes |
|
|
47
|
+
| **Python** | TypeScript | IPC | Medium | ✅ Yes |
|
|
48
|
+
| **Python** | Python | Direct | Native | ❌ No |
|
|
49
|
+
| **Rust** | TypeScript | IPC | Medium | ✅ Yes |
|
|
50
|
+
| **Rust** | Python | IPC | Medium | ✅ Yes |
|
|
51
|
+
| **Rust** | Rust | Direct | Native | ❌ No |
|
|
52
|
+
|
|
53
|
+
## Interop Methods
|
|
54
|
+
|
|
55
|
+
### 1. **WASM (WebAssembly)** - Rust ↔ TypeScript
|
|
56
|
+
|
|
57
|
+
- Rust plugins compile to WASM via `wasm-bindgen`
|
|
58
|
+
- TypeScript runtime loads WASM modules dynamically
|
|
59
|
+
- High performance, sandboxed execution
|
|
60
|
+
|
|
61
|
+
### 2. **PyO3/FFI** - Rust ↔ Python
|
|
62
|
+
|
|
63
|
+
- Rust plugins expose Python bindings via PyO3
|
|
64
|
+
- Python can call Rust code directly via FFI
|
|
65
|
+
- Native performance, type-safe
|
|
66
|
+
|
|
67
|
+
### 3. **IPC (Inter-Process Communication)** - Any ↔ Any
|
|
68
|
+
|
|
69
|
+
- JSON-RPC over Unix sockets or TCP
|
|
70
|
+
- Works for all language combinations
|
|
71
|
+
- Flexible but has serialization overhead
|
|
72
|
+
|
|
73
|
+
### 4. **subprocess** - TypeScript/Python host ↔ Rust/Python plugin
|
|
74
|
+
|
|
75
|
+
- Spawn plugin as subprocess
|
|
76
|
+
- Communicate via stdin/stdout JSON
|
|
77
|
+
- Simplest to implement, good isolation
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
### Loading a Rust Plugin in TypeScript
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { loadWasmPlugin } from "@elizaos/interop";
|
|
85
|
+
|
|
86
|
+
const plugin = await loadWasmPlugin("./my-rust-plugin.wasm");
|
|
87
|
+
runtime.registerPlugin(plugin);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Loading a TypeScript Plugin in Rust
|
|
91
|
+
|
|
92
|
+
```rust
|
|
93
|
+
use elizaos::interop::WasmPluginLoader;
|
|
94
|
+
|
|
95
|
+
let plugin = WasmPluginLoader::load("./my-ts-plugin.wasm").await?;
|
|
96
|
+
runtime.register_plugin(plugin);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Loading a Python Plugin in TypeScript
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { loadPythonPlugin } from "@elizaos/interop";
|
|
103
|
+
|
|
104
|
+
const plugin = await loadPythonPlugin("my_python_plugin");
|
|
105
|
+
runtime.registerPlugin(plugin);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Loading a Rust Plugin in Python
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from elizaos.interop import load_rust_plugin
|
|
112
|
+
|
|
113
|
+
plugin = load_rust_plugin("./my_rust_plugin.so")
|
|
114
|
+
await runtime.register_plugin(plugin)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Plugin Manifest
|
|
118
|
+
|
|
119
|
+
Every cross-language plugin must include a `plugin.json` manifest:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"name": "my-plugin",
|
|
124
|
+
"description": "A cross-language plugin",
|
|
125
|
+
"version": "1.0.0",
|
|
126
|
+
"language": "rust",
|
|
127
|
+
"interop": {
|
|
128
|
+
"protocol": "wasm",
|
|
129
|
+
"wasmPath": "./dist/my_plugin.wasm"
|
|
130
|
+
},
|
|
131
|
+
"actions": [
|
|
132
|
+
{
|
|
133
|
+
"name": "MY_ACTION",
|
|
134
|
+
"description": "Does something cool"
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Building Cross-Language Plugins
|
|
141
|
+
|
|
142
|
+
### Rust → WASM (for TypeScript)
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
cd packages/my-rust-plugin
|
|
146
|
+
cargo build --target wasm32-unknown-unknown --release
|
|
147
|
+
wasm-bindgen target/wasm32-unknown-unknown/release/my_plugin.wasm --out-dir dist
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Rust → Python Extension
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
cd packages/my-rust-plugin
|
|
154
|
+
maturin build --release
|
|
155
|
+
pip install target/wheels/my_plugin-*.whl
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### TypeScript → WASM (experimental)
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Using AssemblyScript or similar
|
|
162
|
+
cd packages/my-ts-plugin
|
|
163
|
+
asc src/index.ts -o dist/plugin.wasm
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Protocol Messages
|
|
167
|
+
|
|
168
|
+
All interop communication uses JSON-serialized messages:
|
|
169
|
+
|
|
170
|
+
### Action Invocation
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"type": "action.invoke",
|
|
175
|
+
"id": "uuid",
|
|
176
|
+
"action": "MY_ACTION",
|
|
177
|
+
"memory": { ... },
|
|
178
|
+
"state": { ... },
|
|
179
|
+
"options": { ... }
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Action Response
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"type": "action.result",
|
|
188
|
+
"id": "uuid",
|
|
189
|
+
"result": {
|
|
190
|
+
"success": true,
|
|
191
|
+
"text": "Action completed",
|
|
192
|
+
"data": { ... }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Provider Request
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"type": "provider.get",
|
|
202
|
+
"id": "uuid",
|
|
203
|
+
"provider": "MY_PROVIDER",
|
|
204
|
+
"memory": { ... },
|
|
205
|
+
"state": { ... }
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Provider Response
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"type": "provider.result",
|
|
214
|
+
"id": "uuid",
|
|
215
|
+
"result": {
|
|
216
|
+
"text": "Provider data",
|
|
217
|
+
"values": { ... },
|
|
218
|
+
"data": { ... }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Quick Start Examples
|
|
224
|
+
|
|
225
|
+
### TypeScript Loading Any Plugin
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { loadPlugin, loadWasmPlugin, loadPythonPlugin } from "@elizaos/interop";
|
|
229
|
+
|
|
230
|
+
// Universal loader (auto-detects from manifest)
|
|
231
|
+
const plugin = await loadPlugin("./path/to/plugin");
|
|
232
|
+
|
|
233
|
+
// Or be explicit:
|
|
234
|
+
const rustPlugin = await loadWasmPlugin("./rust-plugin.wasm");
|
|
235
|
+
const pythonPlugin = await loadPythonPlugin("./python-plugin");
|
|
236
|
+
|
|
237
|
+
// Use like any native plugin
|
|
238
|
+
runtime.registerPlugin(plugin);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Python Loading Any Plugin
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
from elizaos.interop import load_plugin, load_rust_plugin, load_ts_plugin, load_wasm_plugin
|
|
245
|
+
|
|
246
|
+
# Universal loader
|
|
247
|
+
plugin = load_plugin('./path/to/plugin')
|
|
248
|
+
|
|
249
|
+
# Or be explicit:
|
|
250
|
+
rust_ffi_plugin = load_rust_plugin('./libplugin.so') # FFI
|
|
251
|
+
rust_wasm_plugin = load_wasm_plugin('./plugin.wasm') # WASM
|
|
252
|
+
ts_plugin = load_ts_plugin('./typescript-plugin') # IPC
|
|
253
|
+
|
|
254
|
+
# Use like any native plugin
|
|
255
|
+
await runtime.register_plugin(plugin)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Rust Loading Any Plugin
|
|
259
|
+
|
|
260
|
+
```rust
|
|
261
|
+
use elizaos::interop::{load_plugin, TypeScriptPluginLoader, PythonPluginLoader};
|
|
262
|
+
|
|
263
|
+
// Via IPC subprocess
|
|
264
|
+
let ts_plugin = TypeScriptPluginLoader::new().load("./ts-plugin")?;
|
|
265
|
+
let py_plugin = PythonPluginLoader::new().load("./python-plugin")?;
|
|
266
|
+
|
|
267
|
+
// Native Rust - just use directly!
|
|
268
|
+
use my_rust_plugin::plugin;
|
|
269
|
+
runtime.register_plugin(plugin);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Test Plugins
|
|
273
|
+
|
|
274
|
+
Two reference plugins demonstrate all interop paths:
|
|
275
|
+
|
|
276
|
+
### plugin-eliza-classic
|
|
277
|
+
|
|
278
|
+
Classic ELIZA pattern matching chatbot, implemented in all three languages:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# Rust (with WASM + FFI + IPC support)
|
|
282
|
+
cd plugins/plugin-eliza-classic/rust
|
|
283
|
+
cargo build --features wasm,ffi,ipc
|
|
284
|
+
|
|
285
|
+
# Python
|
|
286
|
+
cd plugins/plugin-eliza-classic/python
|
|
287
|
+
pip install -e .
|
|
288
|
+
|
|
289
|
+
# TypeScript
|
|
290
|
+
cd plugins/plugin-eliza-classic/typescript
|
|
291
|
+
pnpm build
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### plugin-inmemorydb
|
|
295
|
+
|
|
296
|
+
Ephemeral in-memory database adapter with vector search:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Available in all three languages with identical API
|
|
300
|
+
plugins/plugin-inmemorydb/
|
|
301
|
+
├── rust/ # Native Rust implementation
|
|
302
|
+
├── python/ # Native Python implementation
|
|
303
|
+
└── typescript/ # Native TypeScript implementation
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Building Plugins for Interop
|
|
307
|
+
|
|
308
|
+
### Rust Plugin (WASM + FFI + IPC)
|
|
309
|
+
|
|
310
|
+
```toml
|
|
311
|
+
# Cargo.toml
|
|
312
|
+
[features]
|
|
313
|
+
wasm = ["wasm-bindgen"]
|
|
314
|
+
ffi = []
|
|
315
|
+
ipc = ["tokio"]
|
|
316
|
+
|
|
317
|
+
[lib]
|
|
318
|
+
crate-type = ["cdylib", "rlib"]
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
# WASM for TypeScript
|
|
323
|
+
cargo build --target wasm32-unknown-unknown --features wasm
|
|
324
|
+
|
|
325
|
+
# Shared lib for Python FFI
|
|
326
|
+
cargo build --release --features ffi
|
|
327
|
+
|
|
328
|
+
# IPC server binary
|
|
329
|
+
cargo build --features ipc --bin my-plugin-ipc
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Python Plugin (IPC)
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
# my_plugin/__init__.py
|
|
336
|
+
from elizaos import Plugin
|
|
337
|
+
|
|
338
|
+
plugin = Plugin(
|
|
339
|
+
name="my-plugin",
|
|
340
|
+
actions=[...],
|
|
341
|
+
providers=[...],
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# Can be loaded via:
|
|
345
|
+
# python -m elizaos.interop.bridge_server my_plugin
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### TypeScript Plugin (IPC)
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// index.ts
|
|
352
|
+
export const plugin: Plugin = {
|
|
353
|
+
name: 'my-plugin',
|
|
354
|
+
actions: [...],
|
|
355
|
+
providers: [...],
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// Can be loaded via ts-bridge-server
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## File Structure
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
packages/interop/
|
|
365
|
+
├── README.md # This file
|
|
366
|
+
├── examples/ # Complete examples for all interop paths
|
|
367
|
+
│ ├── README.md # Example documentation
|
|
368
|
+
│ ├── ts-loads-all.ts # TypeScript loading all languages
|
|
369
|
+
│ ├── py_loads_all.py # Python loading all languages
|
|
370
|
+
│ └── rust_loads_all.rs # Rust loading all languages
|
|
371
|
+
├── typescript/ # TypeScript interop implementations
|
|
372
|
+
│ ├── index.ts # Main exports
|
|
373
|
+
│ ├── wasm-loader.ts # Load Rust WASM plugins
|
|
374
|
+
│ ├── python-bridge.ts # IPC bridge to Python plugins
|
|
375
|
+
│ └── types.ts # Interop types
|
|
376
|
+
├── rust/ # Rust interop implementations
|
|
377
|
+
│ ├── mod.rs # Module exports
|
|
378
|
+
│ ├── wasm_plugin.rs # WASM export traits/macros
|
|
379
|
+
│ ├── ffi_exports.rs # FFI export for Python
|
|
380
|
+
│ ├── ts_loader.rs # Load TypeScript via IPC
|
|
381
|
+
│ └── py_loader.rs # Load Python via IPC
|
|
382
|
+
└── python/ # Python interop implementations
|
|
383
|
+
├── __init__.py # Package exports
|
|
384
|
+
├── rust_ffi.py # Load Rust via ctypes FFI
|
|
385
|
+
├── wasm_loader.py # Load Rust via wasmtime
|
|
386
|
+
├── ts_bridge.py # Load TypeScript via IPC
|
|
387
|
+
└── bridge_server.py # IPC server for Python plugins
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Performance Comparison
|
|
391
|
+
|
|
392
|
+
| Method | Latency | Throughput | Memory | Use Case |
|
|
393
|
+
| ---------- | ------- | ---------- | -------- | -------------------------- |
|
|
394
|
+
| **Direct** | ~1ns | Highest | Shared | Same language |
|
|
395
|
+
| **WASM** | ~1μs | High | Isolated | TS↔Rust, sandboxed |
|
|
396
|
+
| **FFI** | ~10ns | Very High | Shared | Python↔Rust, perf-critical |
|
|
397
|
+
| **IPC** | ~1ms | Medium | Isolated | Any↔Any, maximum isolation |
|
|
398
|
+
|
|
399
|
+
**Recommendations:**
|
|
400
|
+
|
|
401
|
+
- Use **Direct** when host and plugin are same language
|
|
402
|
+
- Use **WASM** for TypeScript↔Rust when sandboxing is important
|
|
403
|
+
- Use **FFI** for Python↔Rust when performance is critical
|
|
404
|
+
- Use **IPC** for maximum flexibility and isolation
|
|
405
|
+
|
|
406
|
+
## Security & SOC2 Readiness Notes
|
|
407
|
+
|
|
408
|
+
This package is often used at a trust boundary (loading plugins). For SOC 2–aligned deployments:
|
|
409
|
+
|
|
410
|
+
### Sandbox boundaries (be explicit)
|
|
411
|
+
|
|
412
|
+
- **Direct (same-language)**: no sandbox. Plugin code runs with full process privileges.
|
|
413
|
+
- **FFI (Python↔Rust shared library)**: **no sandbox**. This is native code execution in the host process.
|
|
414
|
+
- **IPC (subprocess stdin/stdout)**: isolates memory space, but **does not prevent exfiltration** (plugins can still perform network/file I/O unless the operator constrains the process).
|
|
415
|
+
- **WASM**: provides isolation from host memory, but security depends on the host runtime imports and resource limits. It is not an automatic “secure enclave.”
|
|
416
|
+
|
|
417
|
+
### Resource limits (recommended defaults)
|
|
418
|
+
|
|
419
|
+
- **TypeScript→Python IPC** (`packages/interop/typescript/python-bridge.ts`)
|
|
420
|
+
- Supports `maxPendingRequests`, `maxMessageBytes`, and `maxBufferBytes` to prevent unbounded memory growth from malformed or hostile plugin output.
|
|
421
|
+
- Supports `inheritEnv` and `envDenylist` to reduce accidental secret exposure to subprocesses.
|
|
422
|
+
|
|
423
|
+
- **WASM loading**
|
|
424
|
+
- TypeScript loader supports `maxWasmBytes` and `maxMemoryBytes` to limit module and initial memory footprint, and provides a secure `random_get` implementation for WASI.
|
|
425
|
+
- Python loader supports `max_module_bytes`, `max_memory_bytes`, and `fuel` (wasmtime fuel) for coarse CPU budgeting.
|
|
426
|
+
|
|
427
|
+
### Logging
|
|
428
|
+
|
|
429
|
+
Interop subprocess/WASM output is routed through the core logger (when used from the TypeScript runtime) so existing redaction rules apply. Operators should still treat plugin logs as potentially sensitive and configure log retention accordingly.
|
|
430
|
+
|
|
431
|
+
## See Also
|
|
432
|
+
|
|
433
|
+
- [Examples README](./examples/README.md) - Complete working examples
|
|
434
|
+
- [Protocol Buffers Schemas](../@schemas/README.md) - Type definitions
|
|
435
|
+
- [plugin-eliza-classic](../../plugins/plugin-eliza-classic/) - Reference implementation
|
|
436
|
+
- [plugin-inmemorydb](../../plugins/plugin-inmemorydb/) - Database adapter example
|