@roj-ai/isolate-runtime 0.0.0-stage → 0.2.14
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/README.md +63 -2
- package/dist/alarm-scheduler.d.ts +78 -0
- package/dist/alarm-scheduler.d.ts.map +1 -0
- package/dist/alarm-scheduler.js +168 -0
- package/dist/alarm-scheduler.js.map +1 -0
- package/dist/build.d.ts +19 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +86 -0
- package/dist/build.js.map +1 -0
- package/dist/host-contract.d.ts +23 -0
- package/dist/host-contract.d.ts.map +1 -0
- package/dist/host-contract.js +6 -0
- package/dist/host-contract.js.map +1 -0
- package/dist/host.d.ts +9 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +7 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/info.d.ts +4 -0
- package/dist/info.d.ts.map +1 -0
- package/dist/info.js +5 -0
- package/dist/info.js.map +1 -0
- package/dist/modules.d.ts +26 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +52 -0
- package/dist/modules.js.map +1 -0
- package/dist/runtime.d.ts +48 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +80 -0
- package/dist/runtime.js.map +1 -0
- package/dist/testing.d.ts +17 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +25 -0
- package/dist/testing.js.map +1 -0
- package/package.json +61 -5
- package/src/alarm-scheduler.ts +234 -0
- package/src/build.ts +95 -0
- package/src/host-contract.ts +25 -0
- package/src/host.ts +9 -0
- package/src/index.ts +12 -0
- package/src/info.ts +6 -0
- package/src/modules.ts +58 -0
- package/src/runtime.ts +115 -0
- package/src/testing.ts +33 -0
- package/src/worker/facet.ts +29 -0
- package/src/worker/main.ts +6 -0
- package/src/worker/roj-app-bundle.d.ts +4 -0
package/README.md
CHANGED
|
@@ -1,3 +1,64 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @roj-ai/isolate-runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Runs the Roj runtime and an app's `roj build` bundle inside a Cloudflare Durable Object, without a VM.
|
|
4
|
+
The host loads the code through the [Worker Loader](https://developers.cloudflare.com/workers/runtime-apis/bindings/worker-loader/)
|
|
5
|
+
and runs it as a [Durable Object facet](https://developers.cloudflare.com/durable-objects/api/facets/) of its own instance object.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
client ──► host DO (trusted) facet "runtime" (loaded code, untrusted)
|
|
9
|
+
authenticates, stamps `_caller` ──fetch──► SDK + kompjutr + app bundle
|
|
10
|
+
alarm() ─────────────────────────── deliverWakes► own SQLite: filesystem, events, LLM log, wakes
|
|
11
|
+
RuntimeHost entrypoint = env.HOST ◄────────── setAlarm / deleteAlarm / broadcast
|
|
12
|
+
egress gateway = globalOutbound ◄────────── every fetch: allowlist, provider key, tool credentials
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The runtime holds no keys and no bindings. Its only capability is `env.HOST`. Every `fetch` it or the app
|
|
16
|
+
makes goes to the gateway the host set as `globalOutbound`, which adds the provider key and any tool
|
|
17
|
+
credentials. The runtime sends the placeholder `EGRESS_PROVIDED_KEY` as its OpenRouter key.
|
|
18
|
+
|
|
19
|
+
## What the host provides
|
|
20
|
+
|
|
21
|
+
| | |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `env.HOST` | A `RuntimeHost` (`src/host-contract.ts`): the host DO's alarm slot and a sink for user-output notifications (`{ type, payload, ts }`, the shape the sandbox runtime sends over its agent WebSocket). A notification is app output: treat it as untrusted. Each is a separate call, so two may arrive out of order. |
|
|
24
|
+
| `globalOutbound` | The egress gateway. It must not follow redirects: return them, so the next hop comes through the gateway again. |
|
|
25
|
+
| `alarm()` | Calls `deliverWakes()` on the facet. A facet has no alarm of its own. |
|
|
26
|
+
| Caller | The facet serves the sandbox runtime's HTTP surface (`/rpc`, `/status`, `/sessions/*`) with no auth of its own. The host sets `_caller` on every RPC from the principal it authenticated, and drops whatever the client sent. |
|
|
27
|
+
|
|
28
|
+
`e2e/host.ts` is a complete minimal host.
|
|
29
|
+
|
|
30
|
+
## Exports
|
|
31
|
+
|
|
32
|
+
| | |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `.` | The runtime: `createIsolateRuntime`, the alarm scheduler. Runs inside the facet. |
|
|
35
|
+
| `./host` | For the host Worker: the `RuntimeHost` contract, `withAppBundle`, `unresolvedImports`, the runtime version. Imports nothing from the runtime. |
|
|
36
|
+
| `./build` | Bun only: `buildRuntimeModules`. |
|
|
37
|
+
|
|
38
|
+
## Building the modules
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { buildRuntimeModules, withAppBundle } from '@roj-ai/isolate-runtime/build'
|
|
42
|
+
|
|
43
|
+
const runtime = await buildRuntimeModules() // once per runtime version, needs Bun
|
|
44
|
+
const { mainModule, modules } = withAppBundle(runtime, appBundleSource)
|
|
45
|
+
env.LOADER.get(`${bundleRevision}:${runtimeVersion}`, () => ({ mainModule, modules, ... }))
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- The SDK is built once and shared by every bundle. The app bundle must be built in `externalSdk` mode (`runtime: { external: true }`). Its `@roj-ai/sdk/*` imports resolve to shim modules that re-export the shared build. Any other `@roj-ai/*` import fails at load.
|
|
49
|
+
- `unresolvedImports(modules)` lists imports that would not resolve under the loader's rules: a specifier resolves relative to the importing module's directory, even a bare one.
|
|
50
|
+
- About 3 MB raw: the SDK chunks plus a `main.js` of about 1.9 MB, which bundles kompjutr.
|
|
51
|
+
|
|
52
|
+
## Evictions
|
|
53
|
+
|
|
54
|
+
Event sourcing restores a session, not a request in flight. When a delivery starts, the scheduler arms a
|
|
55
|
+
retry (`inFlightRetryMs`, 5 minutes by default) and clears it when the delivery ends. If the isolate is
|
|
56
|
+
evicted mid-turn, the retry fires the host alarm, the facet loads its sessions again, and the SDK resets
|
|
57
|
+
agents left `inferring` to `pending`. The lost provider call is made again and billed twice.
|
|
58
|
+
|
|
59
|
+
## Tests
|
|
60
|
+
|
|
61
|
+
- `bun test packages/isolate-runtime/src`: scheduler, runtime on `bun:sqlite`, module build. Part of `bun run test`.
|
|
62
|
+
- `bun run --cwd packages/isolate-runtime test:e2e`: the runtime in workerd under `wrangler dev`, with a fake provider behind the gateway. Run by hand, from the package directory: under `bun test` started at the repo root, `Bun.build` fails to resolve the `@kompjutr/do` subpath exports.
|
|
63
|
+
|
|
64
|
+
Facets and the Worker Loader are in open beta. Locally they need the `experimental` compatibility flag.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler over a Durable Object's single alarm slot.
|
|
3
|
+
*
|
|
4
|
+
* A DO has no process between wakes, so it implements the plain {@link Scheduler}
|
|
5
|
+
* port rather than `LiveScheduler`: the host delivers through {@link AlarmScheduler.deliverDue}
|
|
6
|
+
* from its own `alarm()` handler, in whichever isolate happens to be alive by then.
|
|
7
|
+
* The slot is reached through {@link AlarmStorageLike}, so a DO facet, which has no
|
|
8
|
+
* alarm of its own, can borrow its parent's.
|
|
9
|
+
*
|
|
10
|
+
* Two shapes of the SDK dictate the design. It arms without awaiting —
|
|
11
|
+
* `scheduleProcessing()` and `shutdown()` are synchronous, so the promises are
|
|
12
|
+
* dropped — and it cancels a key then re-arms it in the same frame. So the state
|
|
13
|
+
* that decides what is due (in-memory key→dueAt maps and their rows in the DO's
|
|
14
|
+
* synchronous KV) moves synchronously, where nothing can reorder it; the alarm
|
|
15
|
+
* slot, which is asynchronous storage I/O, is reconciled afterwards against the
|
|
16
|
+
* maps as they stand when the write runs — never against the arguments that queued it.
|
|
17
|
+
*/
|
|
18
|
+
import type { Scheduler, WakeHandler } from '@roj-ai/sdk/platform';
|
|
19
|
+
/** Synchronous key-value surface of a SQLite-backed Durable Object (`storage.kv`). */
|
|
20
|
+
export interface SyncKvLike {
|
|
21
|
+
list(options?: {
|
|
22
|
+
prefix?: string;
|
|
23
|
+
}): Iterable<[string, unknown]>;
|
|
24
|
+
put(key: string, value: unknown): void;
|
|
25
|
+
delete(key: string): boolean;
|
|
26
|
+
}
|
|
27
|
+
/** The parts of `DurableObjectStorage` a wake needs: one alarm, and rows to survive in. */
|
|
28
|
+
export interface AlarmStorageLike {
|
|
29
|
+
kv: SyncKvLike;
|
|
30
|
+
setAlarm(scheduledTime: number): Promise<void>;
|
|
31
|
+
deleteAlarm(): Promise<void>;
|
|
32
|
+
/** Optional so a test double need not implement it; see `applyAlarm`. */
|
|
33
|
+
sync?(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface AlarmSchedulerHost {
|
|
36
|
+
storage: AlarmStorageLike;
|
|
37
|
+
/**
|
|
38
|
+
* Keeps a promise nobody awaits alive. `DurableObjectState.waitUntil` puts it
|
|
39
|
+
* on the actor's IoContext, so an arm issued during a request outlives the
|
|
40
|
+
* frame that issued it.
|
|
41
|
+
*/
|
|
42
|
+
waitUntil?(promise: Promise<unknown>): void;
|
|
43
|
+
/** How long after a delivery starts it is delivered again unless it finished. Default 5 minutes. */
|
|
44
|
+
inFlightRetryMs?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface AlarmSchedulerStats {
|
|
47
|
+
/** Wakes armed and not yet delivered. */
|
|
48
|
+
pending: number;
|
|
49
|
+
/** Deliveries started and not finished, each with a retry armed. */
|
|
50
|
+
inFlight: number;
|
|
51
|
+
/** What the alarm slot holds, as far as this isolate knows. */
|
|
52
|
+
armedAt: number | null;
|
|
53
|
+
/** Alarms drained since this isolate booted. */
|
|
54
|
+
drains: number;
|
|
55
|
+
/** Wakes handed to a delivery handler since this isolate booted. */
|
|
56
|
+
delivered: number;
|
|
57
|
+
}
|
|
58
|
+
export interface AlarmScheduler extends Scheduler {
|
|
59
|
+
/**
|
|
60
|
+
* Drain every wake now due, re-arm for the next, then hand each drained key to
|
|
61
|
+
* `deliver`. Call from the DO's `alarm()`; returns the keys delivered.
|
|
62
|
+
*/
|
|
63
|
+
deliverDue(deliver: WakeHandler): Promise<string[]>;
|
|
64
|
+
/** Settle the pending alarm writes. Call before an entry point returns. Throws when the slot cannot be written. */
|
|
65
|
+
flush(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Ignore wakes and cancels while `fn` runs.
|
|
68
|
+
*
|
|
69
|
+
* `SessionManager.shutdown()` cancels every agent's wakes — right when a
|
|
70
|
+
* session is being torn down, wrong when the isolate is merely going away,
|
|
71
|
+
* which drops exactly the wake this port exists to preserve. Only the host
|
|
72
|
+
* knows which of the two it is doing.
|
|
73
|
+
*/
|
|
74
|
+
suspend<T>(fn: () => Promise<T>): Promise<T>;
|
|
75
|
+
stats(): AlarmSchedulerStats;
|
|
76
|
+
}
|
|
77
|
+
export declare function createAlarmScheduler(host: AlarmSchedulerHost): AlarmScheduler;
|
|
78
|
+
//# sourceMappingURL=alarm-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alarm-scheduler.d.ts","sourceRoot":"","sources":["../src/alarm-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElE,sFAAsF;AACtF,MAAM,WAAW,UAAU;IAC1B,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAChE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC5B;AAED,2FAA2F;AAC3F,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,UAAU,CAAA;IACd,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,yEAAyE;IACzE,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,gBAAgB,CAAA;IACzB;;;;OAIG;IACH,SAAS,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IAC3C,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IACnC,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;IACd,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS;IAChD;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACnD,mHAAmH;IACnH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB;;;;;;;OAOG;IACH,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5C,KAAK,IAAI,mBAAmB,CAAA;CAC5B;AAsCD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CAoH7E"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler over a Durable Object's single alarm slot.
|
|
3
|
+
*
|
|
4
|
+
* A DO has no process between wakes, so it implements the plain {@link Scheduler}
|
|
5
|
+
* port rather than `LiveScheduler`: the host delivers through {@link AlarmScheduler.deliverDue}
|
|
6
|
+
* from its own `alarm()` handler, in whichever isolate happens to be alive by then.
|
|
7
|
+
* The slot is reached through {@link AlarmStorageLike}, so a DO facet, which has no
|
|
8
|
+
* alarm of its own, can borrow its parent's.
|
|
9
|
+
*
|
|
10
|
+
* Two shapes of the SDK dictate the design. It arms without awaiting —
|
|
11
|
+
* `scheduleProcessing()` and `shutdown()` are synchronous, so the promises are
|
|
12
|
+
* dropped — and it cancels a key then re-arms it in the same frame. So the state
|
|
13
|
+
* that decides what is due (in-memory key→dueAt maps and their rows in the DO's
|
|
14
|
+
* synchronous KV) moves synchronously, where nothing can reorder it; the alarm
|
|
15
|
+
* slot, which is asynchronous storage I/O, is reconciled afterwards against the
|
|
16
|
+
* maps as they stand when the write runs — never against the arguments that queued it.
|
|
17
|
+
*/
|
|
18
|
+
/** Namespaced so wakes cannot collide with whatever else the host keeps in storage. */
|
|
19
|
+
const WAKE_PREFIX = 'roj:wake:';
|
|
20
|
+
const RETRY_PREFIX = 'roj:retry:';
|
|
21
|
+
const DEFAULT_IN_FLIGHT_RETRY_MS = 5 * 60_000;
|
|
22
|
+
/**
|
|
23
|
+
* Clock slack when draining. workerd pins `Date.now()` between I/O, so an alarm
|
|
24
|
+
* can read as fractionally early; without slack that costs an extra round trip.
|
|
25
|
+
*/
|
|
26
|
+
const DRAIN_SLACK_MS = 10;
|
|
27
|
+
/** A key→time map mirrored into KV rows, so it outlives the isolate. */
|
|
28
|
+
function persistedTimes(kv, prefix) {
|
|
29
|
+
const times = new Map();
|
|
30
|
+
for (const [key, value] of kv.list({ prefix })) {
|
|
31
|
+
if (typeof value === 'number')
|
|
32
|
+
times.set(key.slice(prefix.length), value);
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
times,
|
|
36
|
+
set(key, at) {
|
|
37
|
+
times.set(key, at);
|
|
38
|
+
kv.put(prefix + key, at);
|
|
39
|
+
},
|
|
40
|
+
delete(key) {
|
|
41
|
+
// The map mirrors the rows, so a key it does not hold has no row either.
|
|
42
|
+
if (!times.delete(key))
|
|
43
|
+
return false;
|
|
44
|
+
kv.delete(prefix + key);
|
|
45
|
+
return true;
|
|
46
|
+
},
|
|
47
|
+
dueBy(cutoff) {
|
|
48
|
+
return [...times].filter(([, at]) => at <= cutoff).map(([key]) => key);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function createAlarmScheduler(host) {
|
|
53
|
+
const storage = host.storage;
|
|
54
|
+
const track = host.waitUntil?.bind(host);
|
|
55
|
+
const inFlightRetryMs = host.inFlightRetryMs ?? DEFAULT_IN_FLIGHT_RETRY_MS;
|
|
56
|
+
const wakes = persistedTimes(storage.kv, WAKE_PREFIX);
|
|
57
|
+
// A delivery lost to an eviction never reaches its end, and its wake row is already gone.
|
|
58
|
+
// The retry row brings the alarm back, so the session loads and recovers its agents.
|
|
59
|
+
const retries = persistedTimes(storage.kv, RETRY_PREFIX);
|
|
60
|
+
let armedAt;
|
|
61
|
+
let tail = Promise.resolve();
|
|
62
|
+
let suspended = 0;
|
|
63
|
+
let drains = 0;
|
|
64
|
+
let delivered = 0;
|
|
65
|
+
const earliest = () => {
|
|
66
|
+
let min;
|
|
67
|
+
for (const at of [...wakes.times.values(), ...retries.times.values()]) {
|
|
68
|
+
if (min === undefined || at < min)
|
|
69
|
+
min = at;
|
|
70
|
+
}
|
|
71
|
+
return min;
|
|
72
|
+
};
|
|
73
|
+
const applyAlarm = async () => {
|
|
74
|
+
const target = earliest();
|
|
75
|
+
if (target === armedAt)
|
|
76
|
+
return;
|
|
77
|
+
if (target === undefined)
|
|
78
|
+
await storage.deleteAlarm();
|
|
79
|
+
else
|
|
80
|
+
await storage.setAlarm(target);
|
|
81
|
+
armedAt = target;
|
|
82
|
+
// Awaiting the write only queues it; sync() is what waits for it to be durable,
|
|
83
|
+
// and an isolate aborted before that point loses the arm.
|
|
84
|
+
await storage.sync?.();
|
|
85
|
+
};
|
|
86
|
+
/** Queue one alarm write. Serialized, because there is only one slot to race over. */
|
|
87
|
+
const reconcile = () => {
|
|
88
|
+
const next = tail.then(applyAlarm);
|
|
89
|
+
// The tail must never reject, or every later reconcile inherits this failure.
|
|
90
|
+
const settled = next.catch(() => undefined);
|
|
91
|
+
tail = settled;
|
|
92
|
+
track?.(settled);
|
|
93
|
+
return next;
|
|
94
|
+
};
|
|
95
|
+
// A previous isolate may have died between writing rows and committing its alarm.
|
|
96
|
+
if (wakes.times.size > 0 || retries.times.size > 0)
|
|
97
|
+
void reconcile().catch(() => undefined);
|
|
98
|
+
return {
|
|
99
|
+
async wake(key, delayMs) {
|
|
100
|
+
if (suspended > 0)
|
|
101
|
+
return;
|
|
102
|
+
// Synchronous, so the cancel-then-arm pair the SDK issues in one frame
|
|
103
|
+
// cannot land out of order however long the alarm write takes.
|
|
104
|
+
wakes.set(key, Date.now() + Math.max(delayMs, 0));
|
|
105
|
+
await reconcile();
|
|
106
|
+
},
|
|
107
|
+
async cancel(key) {
|
|
108
|
+
if (suspended > 0)
|
|
109
|
+
return;
|
|
110
|
+
if (!wakes.delete(key))
|
|
111
|
+
return;
|
|
112
|
+
await reconcile();
|
|
113
|
+
},
|
|
114
|
+
async deliverDue(deliver) {
|
|
115
|
+
// workerd clears the slot before delivering, so this isolate holds nothing.
|
|
116
|
+
armedAt = undefined;
|
|
117
|
+
drains += 1;
|
|
118
|
+
const cutoff = Date.now() + DRAIN_SLACK_MS;
|
|
119
|
+
const due = [...new Set([...wakes.dueBy(cutoff), ...retries.dueBy(cutoff)])];
|
|
120
|
+
const retryAt = Date.now() + inFlightRetryMs;
|
|
121
|
+
for (const key of due) {
|
|
122
|
+
wakes.delete(key);
|
|
123
|
+
retries.set(key, retryAt);
|
|
124
|
+
}
|
|
125
|
+
// Re-arm before dispatching: a wake that runs long, or throws, must not
|
|
126
|
+
// strand the ones behind it.
|
|
127
|
+
await reconcile();
|
|
128
|
+
// Concurrently: one wake runs a whole agent turn, and the slot fires one alarm at a time.
|
|
129
|
+
await Promise.all(due.map(async (key) => {
|
|
130
|
+
delivered += 1;
|
|
131
|
+
try {
|
|
132
|
+
await deliver(key);
|
|
133
|
+
retries.delete(key);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// The handler owns its error reporting. The retry row stays, so the wake is delivered again.
|
|
137
|
+
}
|
|
138
|
+
}));
|
|
139
|
+
if (due.length > 0)
|
|
140
|
+
await reconcile();
|
|
141
|
+
return due;
|
|
142
|
+
},
|
|
143
|
+
async flush() {
|
|
144
|
+
// Deliveries and agent work chain further reconciles as they run.
|
|
145
|
+
let seen;
|
|
146
|
+
while (seen !== tail) {
|
|
147
|
+
seen = tail;
|
|
148
|
+
await seen;
|
|
149
|
+
}
|
|
150
|
+
// A failed write leaves rows the slot does not cover. Try once more, and let a second failure surface.
|
|
151
|
+
if (earliest() !== armedAt)
|
|
152
|
+
await reconcile();
|
|
153
|
+
},
|
|
154
|
+
async suspend(fn) {
|
|
155
|
+
suspended += 1;
|
|
156
|
+
try {
|
|
157
|
+
return await fn();
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
suspended -= 1;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
stats() {
|
|
164
|
+
return { pending: wakes.times.size, inFlight: retries.times.size, armedAt: armedAt ?? null, drains, delivered };
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=alarm-scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alarm-scheduler.js","sourceRoot":"","sources":["../src/alarm-scheduler.ts"],"names":[],"mappings":"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"}
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the modules a host hands to the Worker Loader to run the runtime as a facet.
|
|
3
|
+
*
|
|
4
|
+
* The SDK is built once per runtime version and shared by every app bundle. An app
|
|
5
|
+
* bundle is `roj build` output in `externalSdk` mode: it imports `@roj-ai/sdk` and its
|
|
6
|
+
* subpaths as bare specifiers, which resolve to small shim modules re-exporting the
|
|
7
|
+
* shared build. The runtime's main module imports the same shims, so the app and the
|
|
8
|
+
* runtime share one SDK instance.
|
|
9
|
+
*
|
|
10
|
+
* The loader resolves a specifier relative to the importing module's directory, a bare
|
|
11
|
+
* one included. The shims sit at the root, so the app bundle and the main module reach
|
|
12
|
+
* them by name; the shims reach the SDK by absolute path.
|
|
13
|
+
*/
|
|
14
|
+
import { type RuntimeModules } from './modules.js';
|
|
15
|
+
export type { LoaderModule, RuntimeModules } from './modules.js';
|
|
16
|
+
export { APP_BUNDLE_MODULE, unresolvedImports, withAppBundle } from './modules.js';
|
|
17
|
+
/** Builds the runtime from the installed `@roj-ai/*` packages. Needs Bun. */
|
|
18
|
+
export declare function buildRuntimeModules(): Promise<RuntimeModules>;
|
|
19
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAExF,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAmClF,6EAA6E;AAC7E,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,cAAc,CAAC,CAuCnE"}
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the modules a host hands to the Worker Loader to run the runtime as a facet.
|
|
3
|
+
*
|
|
4
|
+
* The SDK is built once per runtime version and shared by every app bundle. An app
|
|
5
|
+
* bundle is `roj build` output in `externalSdk` mode: it imports `@roj-ai/sdk` and its
|
|
6
|
+
* subpaths as bare specifiers, which resolve to small shim modules re-exporting the
|
|
7
|
+
* shared build. The runtime's main module imports the same shims, so the app and the
|
|
8
|
+
* runtime share one SDK instance.
|
|
9
|
+
*
|
|
10
|
+
* The loader resolves a specifier relative to the importing module's directory, a bare
|
|
11
|
+
* one included. The shims sit at the root, so the app bundle and the main module reach
|
|
12
|
+
* them by name; the shims reach the SDK by absolute path.
|
|
13
|
+
*/
|
|
14
|
+
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
15
|
+
import { join, posix } from 'node:path';
|
|
16
|
+
import { APP_BUNDLE_MODULE } from './modules.js';
|
|
17
|
+
export { APP_BUNDLE_MODULE, unresolvedImports, withAppBundle } from './modules.js';
|
|
18
|
+
const MAIN_MODULE = 'main.js';
|
|
19
|
+
const SDK_DIR = 'sdk';
|
|
20
|
+
const PLATFORM_EXTERNALS = ['node:*', 'cloudflare:*'];
|
|
21
|
+
/** SDK subpaths an isolate cannot run or an app bundle has no use for. */
|
|
22
|
+
const EXCLUDED_SDK_EXPORTS = new Set(['./package.json', './bun-platform', './testing']);
|
|
23
|
+
const packageRoot = join(import.meta.dir, '..');
|
|
24
|
+
async function bunBuild(options) {
|
|
25
|
+
const result = await Bun.build({ target: 'node', format: 'esm', ...options });
|
|
26
|
+
if (!result.success)
|
|
27
|
+
throw new AggregateError(result.logs, 'isolate runtime build failed');
|
|
28
|
+
}
|
|
29
|
+
async function sdkSubpaths() {
|
|
30
|
+
const manifestPath = Bun.resolveSync('@roj-ai/sdk/package.json', packageRoot);
|
|
31
|
+
const manifest = await Bun.file(manifestPath).json();
|
|
32
|
+
const bunOnly = new Set(manifest.roj?.bunOnlyExports ?? []);
|
|
33
|
+
return Object.keys(manifest.exports).filter(subpath => !EXCLUDED_SDK_EXPORTS.has(subpath) && !bunOnly.has(subpath));
|
|
34
|
+
}
|
|
35
|
+
/** `.` → `@roj-ai/sdk`, `./tools/shell` → `@roj-ai/sdk/tools/shell`. */
|
|
36
|
+
const specifierOf = (subpath) => (subpath === '.' ? '@roj-ai/sdk' : `@roj-ai/sdk/${subpath.slice(2)}`);
|
|
37
|
+
/** `.` → `index`, `./tools/shell` → `tools__shell`: flat, so every entry lands in one directory. */
|
|
38
|
+
const entryNameOf = (subpath) => (subpath === '.' ? 'index' : subpath.slice(2).replaceAll('/', '__'));
|
|
39
|
+
async function readModules(dir, prefix) {
|
|
40
|
+
const modules = {};
|
|
41
|
+
for (const file of await readdir(dir)) {
|
|
42
|
+
modules[posix.join(prefix, file)] = await readFile(join(dir, file), 'utf8');
|
|
43
|
+
}
|
|
44
|
+
return modules;
|
|
45
|
+
}
|
|
46
|
+
/** Builds the runtime from the installed `@roj-ai/*` packages. Needs Bun. */
|
|
47
|
+
export async function buildRuntimeModules() {
|
|
48
|
+
// Entries must resolve `@roj-ai/sdk` the way this package does, so they live inside it.
|
|
49
|
+
const workDir = join(packageRoot, `.isolate-build-${crypto.randomUUID()}`);
|
|
50
|
+
try {
|
|
51
|
+
const subpaths = await sdkSubpaths();
|
|
52
|
+
const entriesDir = join(workDir, 'entries');
|
|
53
|
+
await mkdir(entriesDir, { recursive: true });
|
|
54
|
+
const entries = [];
|
|
55
|
+
for (const subpath of subpaths) {
|
|
56
|
+
const entry = join(entriesDir, `${entryNameOf(subpath)}.ts`);
|
|
57
|
+
await writeFile(entry, `export * from '${specifierOf(subpath)}'\n`);
|
|
58
|
+
entries.push(entry);
|
|
59
|
+
}
|
|
60
|
+
await bunBuild({
|
|
61
|
+
entrypoints: entries,
|
|
62
|
+
outdir: join(workDir, SDK_DIR),
|
|
63
|
+
splitting: true,
|
|
64
|
+
external: PLATFORM_EXTERNALS,
|
|
65
|
+
naming: { entry: '[name].js', chunk: 'chunk-[hash].js' },
|
|
66
|
+
});
|
|
67
|
+
await bunBuild({
|
|
68
|
+
entrypoints: [join(packageRoot, 'src/worker/main.ts')],
|
|
69
|
+
outdir: join(workDir, 'main'),
|
|
70
|
+
naming: MAIN_MODULE,
|
|
71
|
+
external: [...PLATFORM_EXTERNALS, '@roj-ai/sdk', '@roj-ai/sdk/*', APP_BUNDLE_MODULE],
|
|
72
|
+
});
|
|
73
|
+
const modules = {
|
|
74
|
+
[MAIN_MODULE]: await readFile(join(workDir, 'main', MAIN_MODULE), 'utf8'),
|
|
75
|
+
...(await readModules(join(workDir, SDK_DIR), SDK_DIR)),
|
|
76
|
+
};
|
|
77
|
+
for (const subpath of subpaths) {
|
|
78
|
+
modules[specifierOf(subpath)] = { js: `export * from '/${SDK_DIR}/${entryNameOf(subpath)}.js'\n` };
|
|
79
|
+
}
|
|
80
|
+
return { mainModule: MAIN_MODULE, modules };
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
await rm(workDir, { recursive: true, force: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract between the runtime and the Durable Object hosting it. Kept free of imports,
|
|
3
|
+
* so a host type-checked against Workers types can use it without the SDK.
|
|
4
|
+
*/
|
|
5
|
+
/** A user-output notification in the shape the sandbox runtime sends over its agent WebSocket. */
|
|
6
|
+
export interface RuntimeBroadcast {
|
|
7
|
+
type: string;
|
|
8
|
+
payload: unknown;
|
|
9
|
+
ts: number;
|
|
10
|
+
}
|
|
11
|
+
/** What the host gives the runtime. Bound to one instance by the host; the runtime cannot name another. */
|
|
12
|
+
export interface RuntimeHost {
|
|
13
|
+
/** The single alarm slot of the host's Durable Object, lent to the runtime. */
|
|
14
|
+
setAlarm(scheduledTime: number): Promise<void>;
|
|
15
|
+
deleteAlarm(): Promise<void>;
|
|
16
|
+
broadcast(message: RuntimeBroadcast): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/** What the host calls on the facet's stub. */
|
|
19
|
+
export interface RuntimeFacetRpc {
|
|
20
|
+
fetch(request: Request): Promise<Response>;
|
|
21
|
+
deliverWakes(): Promise<string[]>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=host-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-contract.d.ts","sourceRoot":"","sources":["../src/host-contract.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kGAAkG;AAClG,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;CACV;AAED,2GAA2G;AAC3G,MAAM,WAAW,WAAW;IAC3B,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnD;AAED,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC/B,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1C,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-contract.js","sourceRoot":"","sources":["../src/host-contract.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host needs at run time: the contract with the facet, the module map helpers and the
|
|
3
|
+
* runtime version. Imports nothing from the runtime itself, so it adds nothing to a host's bundle.
|
|
4
|
+
*/
|
|
5
|
+
export type { RuntimeBroadcast, RuntimeFacetRpc, RuntimeHost } from './host-contract.js';
|
|
6
|
+
export { ISOLATE_RUNTIME_NAME, ISOLATE_RUNTIME_VERSION } from './info.js';
|
|
7
|
+
export type { LoaderModule, RuntimeModules } from './modules.js';
|
|
8
|
+
export { APP_BUNDLE_MODULE, unresolvedImports, withAppBundle } from './modules.js';
|
|
9
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACzE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host needs at run time: the contract with the facet, the module map helpers and the
|
|
3
|
+
* runtime version. Imports nothing from the runtime itself, so it adds nothing to a host's bundle.
|
|
4
|
+
*/
|
|
5
|
+
export { ISOLATE_RUNTIME_NAME, ISOLATE_RUNTIME_VERSION } from './info.js';
|
|
6
|
+
export { APP_BUNDLE_MODULE, unresolvedImports, withAppBundle } from './modules.js';
|
|
7
|
+
//# sourceMappingURL=host.js.map
|
package/dist/host.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAEzE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { AlarmScheduler, AlarmSchedulerHost, AlarmSchedulerStats, AlarmStorageLike, SyncKvLike, } from './alarm-scheduler.js';
|
|
2
|
+
export { createAlarmScheduler } from './alarm-scheduler.js';
|
|
3
|
+
export { ISOLATE_RUNTIME_NAME, ISOLATE_RUNTIME_VERSION } from './info.js';
|
|
4
|
+
export type { RuntimeBroadcast, RuntimeFacetRpc, RuntimeHost } from './host-contract.js';
|
|
5
|
+
export type { IsolateRuntime, IsolateRuntimeOptions, IsolateRuntimeState } from './runtime.js';
|
|
6
|
+
export { createIsolateRuntime, EGRESS_PROVIDED_KEY } from './runtime.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,GACV,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AACzE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC9F,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAGzE,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA"}
|
package/dist/info.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../src/info.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAI/E,eAAO,MAAM,uBAAuB,QAAc,CAAA;AAClD,eAAO,MAAM,oBAAoB,QAAW,CAAA"}
|
package/dist/info.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Read from this package's own package.json, so the value tracks releases. */
|
|
2
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
3
|
+
export const ISOLATE_RUNTIME_VERSION = pkg.version;
|
|
4
|
+
export const ISOLATE_RUNTIME_NAME = pkg.name;
|
|
5
|
+
//# sourceMappingURL=info.js.map
|
package/dist/info.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../src/info.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAEvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC,OAAO,CAAA;AAClD,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Worker Loader module map a host builds once per runtime version (`./build`) and completes with
|
|
3
|
+
* one app bundle per instance. Free of Bun and Node APIs, so a host can use it inside a Worker.
|
|
4
|
+
*/
|
|
5
|
+
/** A Worker Loader module: a `.js` name maps to ES module source, any other name needs its type. */
|
|
6
|
+
export type LoaderModule = string | {
|
|
7
|
+
js: string;
|
|
8
|
+
};
|
|
9
|
+
export interface RuntimeModules {
|
|
10
|
+
mainModule: string;
|
|
11
|
+
modules: Record<string, LoaderModule>;
|
|
12
|
+
}
|
|
13
|
+
/** The module name the main module imports the app's config from. */
|
|
14
|
+
export declare const APP_BUNDLE_MODULE = "roj-app-bundle";
|
|
15
|
+
/** The runtime's modules plus one app bundle: what a host passes to `LOADER.get()`. */
|
|
16
|
+
export declare function withAppBundle(runtime: RuntimeModules, appBundle: string): RuntimeModules;
|
|
17
|
+
/**
|
|
18
|
+
* Imports that would not resolve under the loader's rules, plus any use of `import.meta.require`,
|
|
19
|
+
* reported with that as the specifier. Bun's unminified ESM output keeps every static import at the
|
|
20
|
+
* start of a line, which is what the scan relies on. Platform builtins (`node:`, `cloudflare:`) are not checked.
|
|
21
|
+
*/
|
|
22
|
+
export declare function unresolvedImports(modules: Record<string, LoaderModule>): {
|
|
23
|
+
module: string;
|
|
24
|
+
specifier: string;
|
|
25
|
+
}[];
|
|
26
|
+
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oGAAoG;AACpG,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAElD,MAAM,WAAW,cAAc;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CACrC;AAED,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,mBAAmB,CAAA;AAEjD,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAExF;AAkBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,CAehH"}
|