You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`@execbox/worker`| Worker-thread executor that runs the QuickJS session behind a message boundary with pooled shells by default|
59
59
60
60
## End-to-End Execution Model
61
61
@@ -108,6 +108,6 @@ Key implications:
108
108
- In-process execution still shares the host process. Use a separate process, container, VM, or similar boundary when the code source is hostile or multi-tenant.
109
109
- Wrapping third-party MCP servers is a separate dependency-trust decision from letting end users author guest code.
110
110
111
-
## Current Architecture in One Paragraph
111
+
## Architecture In One Paragraph
112
112
113
-
Today, `@execbox/core` owns the stable execution contract, provider resolution, shared runner semantics, and MCP adapters. `@execbox/quickjs` and `@execbox/isolated-vm` each expose a runtime-specific reusable runner. `@execbox/process`, `@execbox/worker`, and `@execbox/remote` are transport adapters around the shared QuickJS protocol endpoint, while `@execbox/protocol` owns the transport boundary: message shapes plus the shared host session used to drive transport-backed execution without copying executor semantics.
113
+
`@execbox/core` owns the stable execution contract, provider resolution, shared runner semantics, and MCP adapters. `@execbox/quickjs` and `@execbox/isolated-vm` each expose a runtime-specific reusable runner. `@execbox/process`, `@execbox/worker`, and `@execbox/remote` are transport adapters around the shared QuickJS protocol endpoint, while `@execbox/protocol` owns the transport boundary: message shapes, shared host sessions, and reusable resource pools for transport-backed execution.
Copy file name to clipboardExpand all lines: docs/architecture/execbox-executors.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,31 +45,31 @@ flowchart LR
45
45
THREAD --> RUNNER
46
46
```
47
47
48
-
## QuickJS Today
48
+
## QuickJS
49
49
50
50
`QuickJsExecutor` is the default reference implementation for execbox. It uses the shared runner semantics from `@execbox/core`: providers are converted to manifests, host tool calls are dispatched through the shared dispatcher helper, and the reusable QuickJS runner turns them back into guest-visible async functions.
51
51
52
52
That design gives QuickJS two useful properties:
53
53
54
54
- the runtime semantics are centralized in one runner implementation
55
-
- the same guest/tool-call model can be reused behind a worker or future transport boundary
55
+
- the same guest/tool-call model can be reused behind worker, process, and remote transport boundaries
56
56
57
-
## isolated-vm Today
57
+
## isolated-vm
58
58
59
-
`IsolatedVmExecutor`now follows the same high-level runner contract as QuickJS, but keeps its native bridge internally. The reusable `runIsolatedVmSession()` runner accepts manifests and an `onToolCall` callback, then implements the runtime-specific bridge with `setSync()` / `applySyncPromise()` inside the `isolated-vm` context.
59
+
`IsolatedVmExecutor` follows the same high-level runner contract as QuickJS, but keeps its native bridge internally. The reusable `runIsolatedVmSession()` runner accepts manifests and an `onToolCall` callback, then implements the runtime-specific bridge with `setSync()` / `applySyncPromise()` inside the `isolated-vm` context.
60
60
61
61
That means:
62
62
63
-
- it does not currently depend on `execbox-protocol`
63
+
- it does not depend on `execbox-protocol`
64
64
- it avoids the extra message loop used by worker-backed execution
65
65
- its runtime-specific bridge logic still lives in the executor package itself
66
-
- it is now aligned with the same runner-level shape used by QuickJS and worker-backed execution
66
+
- it aligns to the same runner-level shape used by QuickJS and transport-backed execution
67
67
68
-
This is a cleaner maintainability point than the previous design: the package still keeps the native bridge where it belongs, but the executor no longer owns a separate copy of the host-side manifest and tool-dispatch semantics.
68
+
The package keeps its native bridge where it belongs while still sharing the same host-side manifest and tool-dispatch model as the other executors.
69
69
70
70
## Worker-Backed QuickJS
71
71
72
-
`WorkerExecutor` uses a worker thread for lifecycle isolation, but it does not invent a second scripting model. It loads the same QuickJS session runner used by the in-process QuickJS executor, reuses the shared QuickJS protocol endpoint inside the worker, and uses the shared `execbox-protocol` host session on the parent side. By default it keeps a worker shell warm between executions; `mode: "ephemeral"`restores the old fresh-worker-per-call lifecycle.
72
+
`WorkerExecutor` uses a worker thread for lifecycle isolation, but it does not invent a second scripting model. It loads the same QuickJS session runner used by the in-process QuickJS executor, reuses the shared QuickJS protocol endpoint inside the worker, and uses the shared `execbox-protocol` host session on the parent side. By default it keeps a worker shell warm between executions; `mode: "ephemeral"`switches to a freshworkerper execution.
73
73
74
74
```mermaid
75
75
sequenceDiagram
@@ -90,7 +90,7 @@ sequenceDiagram
90
90
91
91
## Process-Backed QuickJS
92
92
93
-
`ProcessExecutor` uses the same message-driven model as the worker executor, but runs it behind a child-process boundary. It loads the same QuickJS session runner used by the in-process QuickJS executor, reuses the same QuickJS protocol endpoint inside the child, and uses the shared `execbox-protocol` host session on the parent side. By default it keeps a child-process shell warm between executions; `mode: "ephemeral"`restores the old fresh-child-per-call lifecycle.
93
+
`ProcessExecutor` uses the same message-driven model as the worker executor, but runs it behind a child-process boundary. It loads the same QuickJS session runner used by the in-process QuickJS executor, reuses the same QuickJS protocol endpoint inside the child, and uses the shared `execbox-protocol` host session on the parent side. By default it keeps a child-process shell warm between executions; `mode: "ephemeral"`switches to a freshchild process per execution.
94
94
95
95
```mermaid
96
96
sequenceDiagram
@@ -123,12 +123,12 @@ The four executors expose the same public result shape, but they enforce limits
123
123
## Security and Operational Trade-offs
124
124
125
125
- All four executors are documented as best-effort isolation, not hard hostile-code boundaries.
126
-
- QuickJS is the easiest operational default and has the cleanest shared runtime story today.
126
+
- QuickJS is the easiest operational default and has the cleanest shared runtime story.
127
127
- Remote execution keeps the same executor API while moving the runtime behind an app-defined boundary, but execbox deliberately does not ship the network stack for you.
128
128
- Process-backed QuickJS gives a stronger lifecycle split than worker threads, but it is still not equivalent to a container or VM boundary.
129
129
-`isolated-vm` is the most specialized option and carries the most environment-specific operational requirements.
130
130
- Worker-backed QuickJS improves lifecycle isolation and hard-stop behavior, but not process-level trust isolation.
131
-
- Worker and process executors now share the same host-session and child-endpoint semantics, so most behavioral differences come from the transport boundary rather than from duplicated executor logic.
131
+
- Worker and process executors share the same host-session and child-endpoint semantics, so most behavioral differences come from the transport boundary rather than from duplicated executor logic.
132
132
133
133
## Pooled QuickJS Shells
134
134
@@ -170,7 +170,7 @@ If all shells are busy and the pool is already at `maxSize`, the next `acquire()
170
170
171
171
### Early Exit Handling
172
172
173
-
Pooling exposed a transport race that did not matter in the old one-shot model: a child or worker could exit before the host session subscribed to close events. The pooled transport wrappers now retain the first close reason and replay it to later `onClose(...)` subscribers, so an early shell death still resolves as `internal_error` instead of hanging the execution.
173
+
In pooled mode, a child or worker can exit before the host session subscribes to close events. The pooled transport wrappers retain the first close reason and replay it to later `onClose(...)` subscribers, so an early shell death still resolves as `internal_error` instead of hanging the execution.
0 commit comments