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
Tighten the pre-1.0 public API surface by keeping low-level core helpers out of the main `@execbox/core` entrypoint, removing unsupported QuickJS runner subpath exports, and keeping runner-side remote endpoint types with `@execbox/quickjs/remote-endpoint`.
6
+
Tighten the pre-1.0 public API surface by keeping low-level core helpers out of the main `@execbox/core` entrypoint and removing unsupported QuickJS runner subpath exports. The v1 runtime surface is now inline QuickJS plus worker-hosted QuickJS.
Copy file name to clipboardExpand all lines: AGENTS.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
5
5
-`execbox` is a Node.js 22+ npm workspace that publishes the `@execbox/*` package family.
6
6
- Core source lives under `packages/*/src`, tests live under `packages/*/__tests__`, runnable examples live under `examples/`, and the public docs site lives under `docs/`.
7
-
- The workspace currently contains `@execbox/core`, `@execbox/quickjs`, and `@execbox/remote`.
7
+
- The workspace currently contains `@execbox/core`and `@execbox/quickjs`.
8
8
- Keep changes aligned with existing package boundaries. Prefer changing the owning package instead of introducing cross-package shortcuts.
9
9
10
10
## Setup Commands
@@ -30,8 +30,9 @@
30
30
31
31
- For most code changes, run `npm run format:check`, `npm run lint`, `npm run typecheck`, `npm test`, and `npm run build`.
32
32
- If you change package exports, manifest fields, or published type-resolution behavior, also run `npm run package:check`.
33
-
- If you change the public API of any entrypoint listed in `scripts/workspace-entrypoints.ts`, including `@execbox/core/runtime` and `@execbox/quickjs/remote-endpoint`, also run `npm run api:check`.
34
-
- If you change docs site content, navigation, or VitePress config, also run `npm run docs:build`.
33
+
- If you change the public API of any entrypoint listed in `scripts/workspace-entrypoints.ts`, including `@execbox/core/runtime`, also run `npm run api:check`.
34
+
- If you change examples or runtime guidance, also run `npm run examples`.
35
+
- If you change docs site content, navigation, or Starlight/Astro config, also run `npm run docs:build`.
35
36
- If you touch execution boundaries, timeout handling, abort propagation, schema validation, or log/memory controls, also run `npm run test:security`.
36
37
37
38
## Security Notes
@@ -51,6 +52,6 @@
51
52
## Useful References
52
53
53
54
- Start with `README.md` for the package map.
54
-
- Use `docs/getting-started.md` for install and example expectations.
55
-
- Use `docs/security.md` and `docs/architecture/README.md` before changing execution boundaries or runtime claims.
55
+
- Use `docs/src/content/docs/getting-started.md` for install and example expectations.
56
+
- Use `docs/src/content/docs/security.md` and `docs/src/content/docs/architecture/index.md` before changing execution boundaries or runtime claims.
56
57
- For the human-oriented contribution workflow, see `CONTRIBUTING.md`.
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,12 +21,13 @@ This guide is for both humans and coding agents. Agent-specific operating instru
21
21
22
22
- General code changes: `npm run format:check`, `npm run lint`, `npm run typecheck`, `npm test`, and `npm run build`
23
23
- Package export, manifest, or published type-resolution changes: `npm run package:check`
24
+
- Example or runtime guidance changes: `npm run examples`
24
25
- Docs site changes: `npm run docs:build`
25
26
- Security or execution-boundary changes: `npm run test:security`
26
27
27
28
Choose the smallest verification set that covers your change, and include the commands you ran in your PR or handoff notes when the context would help reviewers.
28
29
29
-
- Public API changes to any entrypoint listed in `scripts/workspace-entrypoints.ts`, including `@execbox/core/runtime` and `@execbox/quickjs/remote-endpoint`: run `npm run api:check`
30
+
- Public API changes to any entrypoint listed in `scripts/workspace-entrypoints.ts`, including `@execbox/core/runtime`: run `npm run api:check`
30
31
- Put security-focused specs under `packages/*/__tests__/security/`; `npm run test:security` runs those grouped suites.
Execbox turns host tool catalogs into callable guest namespaces, supports MCP wrapping on both sides of the boundary, and lets you place guest JavaScript where it fits your deployment: inline QuickJS, worker-hosted QuickJS, or a remote runner behind your own transport.
13
+
Execbox turns host tool catalogs into callable guest namespaces, supports MCP wrapping on both sides of the boundary, and lets you run guest JavaScript through inline QuickJS or worker-hosted QuickJS.
|[`@execbox/quickjs`](./packages/quickjs/)|[](https://www.npmjs.com/package/@execbox/quickjs)| QuickJS executor for inline and worker hosts |
21
-
|[`@execbox/remote`](./packages/remote/)|[](https://www.npmjs.com/package/@execbox/remote)| Advanced transport-backed executor for app-owned runtime boundaries |
Copy file name to clipboardExpand all lines: benchmarks/results.md
-1Lines changed: 0 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -139,4 +139,3 @@ This suite only measures the parent Node process.
139
139
### What this snapshot does not prove
140
140
141
141
- It does not prove exact throughput rankings for every workload or host. The concurrency and tool-call suites are still sensitive to local scheduler noise.
142
-
- It does not measure `RemoteExecutor`, because remote performance depends on the caller-owned transport and remote runtime deployment.
Copy file name to clipboardExpand all lines: docs/src/content/docs/architecture/execbox-core.md
+3-4Lines changed: 3 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,7 +71,7 @@ The resolved provider also carries two maps:
71
71
72
72
## Guest Code Normalization
73
73
74
-
Executors do not evaluate arbitrary snippets directly. Runtime implementers import `normalizeCode()` from `@execbox/core/runtime` to turn model- or user-produced text into a consistent async function body.
74
+
Executors normalize snippets before evaluation. Runtime implementers import `normalizeCode()` from `@execbox/core/runtime` to turn model- or user-produced text into a consistent async function body.
75
75
76
76
That normalization handles:
77
77
@@ -129,7 +129,7 @@ interface Executor {
129
129
}
130
130
```
131
131
132
-
The core package intentionally does not decide where the code runs. It only defines what the runtime must honor.
132
+
The core package defines what every runtime must honor while executor packages decide where code runs.
133
133
134
134
```mermaid
135
135
sequenceDiagram
@@ -194,12 +194,11 @@ Executors are responsible for their own runtime-specific classification rules, b
194
194
195
195
## Why the Core Stays Small
196
196
197
-
The core package does not own QuickJS, worker threads, process boundaries, or transport mechanics. That separation keeps the core useful for:
197
+
The core package stays focused on provider, execution, MCP, runtime-helper, and protocol contracts. That separation keeps the core useful for:
|`QuickJsExecutor` with `host: "worker"`| Worker thread + fresh QuickJS runtime | Shared host session + messages | Hard-stop worker termination, pooled by default | Still same OS process; ephemeral mode is slower |
14
-
|`RemoteExecutor`| App-defined remote transport boundary | Shared host session + transport | Same API across a remote boundary | You own transport/runtime deployment |
10
+
| Executor or mode | Runtime boundary | Tool bridge style | Main strengths | Main constraints |
|`QuickJsExecutor` with `host: "worker"`| Worker thread + fresh QuickJS runtime | Shared host session + messages | Hard-stop worker termination, pooled by default | Still same OS process; ephemeral mode is slower |
- the runtime semantics are centralized in one runner implementation
46
-
- the same guest/tool-call model can be reused behind worker-hosted and remote transport boundaries
40
+
- the same guest/tool-call model can be reused behind worker-hosted execution
47
41
48
42
## Worker-Hosted QuickJS
49
43
50
-
`QuickJsExecutor` with `host: "worker"` 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 inline QuickJS executor, reuses the shared QuickJS protocol endpoint inside the worker, and uses the shared `@execbox/core/protocol` host session on the parent side. By default it keeps a worker shell warm between executions; `mode: "ephemeral"` switches to a fresh worker per execution.
44
+
`QuickJsExecutor` with `host: "worker"` uses a worker thread for lifecycle isolation while keeping the same scripting model as inline QuickJS. It loads the same QuickJS session runner used by the inline QuickJS executor, reuses the shared QuickJS protocol endpoint inside the worker, and uses the shared `@execbox/core/protocol` host session on the parent side. By default it keeps a worker shell warm between executions; `mode: "ephemeral"` switches to a fresh worker per execution.
51
45
52
46
```mermaid
53
47
sequenceDiagram
@@ -70,19 +64,18 @@ sequenceDiagram
70
64
71
65
The available executors expose the same public result shape, but they enforce limits differently.
| Memory | QuickJS runtime memory limit |Remote runtime decides the hard boundary; execbox still forwards limits |QuickJS memory limit inside worker, optional worker resource limits as backstop |
77
-
| Abort to host tools | Abort signal passed through core callback | Abort signal passed through shared host session | Abort signal passed through shared host session |
78
-
| Log capture | Captured inside runner | Captured inside the remote runner and returned over the transport boundary | Captured inside worker-side QuickJS runner |
- All executor modes provide defense-in-depth measures, not standalone hard hostile-code boundaries.
76
+
- All executor modes provide defense-in-depth measures around guest execution.
83
77
- QuickJS is the easiest operational default and has the cleanest shared runtime story.
84
-
- 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.
85
-
- Worker-hosted QuickJS improves lifecycle isolation and hard-stop behavior, but not process-level trust isolation.
78
+
- Worker-hosted QuickJS improves lifecycle isolation and hard-stop behavior inside the host process.
86
79
87
80
## Pooled QuickJS Shells
88
81
@@ -99,7 +92,7 @@ Pooling is implemented at the host-shell layer, not at the QuickJS runtime layer
99
92
-`@execbox/core/protocol` exposes a small bounded async `createResourcePool()` helper that owns reusable shells, idle eviction, and `prewarm()` / `dispose()` support.
100
93
- Worker-hosted `QuickJsExecutor` pools `Worker` shells. Each shell owns one long-lived transport wrapper plus one attached QuickJS protocol endpoint.
101
94
- The worker entrypoint only attaches `attachQuickJsProtocolEndpoint(...)` once. That endpoint accepts one active `execute` message at a time and starts a fresh `runQuickJsSession()` for each message.
102
-
- Concurrency therefore comes from pool size, not from multiplexing several executions through one shell.
95
+
- Concurrency comes from pool size: each shell handles one active execution at a time.
103
96
104
97
At execution time the flow is:
105
98
@@ -116,7 +109,7 @@ If all shells are busy and the pool is already at `maxSize`, the next `acquire()
116
109
### Reuse And Eviction Rules
117
110
118
111
- Successful executions return the shell to the pool.
119
-
- Normal guest/runtime/tool failures also return the shell, because they do not imply a poisoned host shell.
112
+
- Normal guest/runtime/tool failures also return the shell, because the host shell remains reusable after those outcomes.
120
113
-`timeout` and `internal_error` results evict the shell, because those outcomes mean the worker or transport state may no longer be trustworthy.
121
114
- Idle pooled shells are evicted after `idleTimeoutMs`, down to `minSize`.
122
115
-`dispose()` tears down the executor-owned pool and any idle shells it still owns.
@@ -125,13 +118,7 @@ If all shells are busy and the pool is already at `maxSize`, the next `acquire()
125
118
126
119
In pooled mode, a 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.
127
120
128
-
### What Is Not Pooled
129
-
130
-
-`QuickJsExecutor` stays in-process and ephemeral because there is no expensive transport shell to reuse.
131
-
-`RemoteExecutor` stays transport-factory based and ephemeral because transport ownership belongs to the caller.
132
-
133
121
## Choosing an Executor
134
122
135
123
- Choose `QuickJsExecutor` when you want the default backend with the least operational friction.
136
-
- Choose `RemoteExecutor` when you want the same execution API but need the runtime to live behind an application-defined process, container, VM, or network boundary.
137
124
- Choose `QuickJsExecutor` with `host: "worker"` when you want the QuickJS semantics off the main thread with a hard-stop termination path and low-latency pooled reuse by default.
0 commit comments