@nimbus-sh/worker 0.1.5 → 0.1.6

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.
Files changed (135) hide show
  1. package/README.md +37 -0
  2. package/dist/_shared/crypto.d.ts +15 -0
  3. package/dist/_shared/crypto.d.ts.map +1 -0
  4. package/dist/_shared/crypto.js +122 -0
  5. package/dist/facets/manager.d.ts +24 -0
  6. package/dist/facets/manager.d.ts.map +1 -1
  7. package/dist/facets/manager.js +279 -70
  8. package/dist/facets/process.d.ts +11 -2
  9. package/dist/facets/process.d.ts.map +1 -1
  10. package/dist/facets/process.js +187 -21
  11. package/dist/facets/vite-dev-server.d.ts +2 -0
  12. package/dist/facets/vite-dev-server.d.ts.map +1 -1
  13. package/dist/facets/vite-dev-server.js +39 -12
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -0
  17. package/dist/loaders/child-process/spawn-facet.d.ts +1 -3
  18. package/dist/loaders/child-process/spawn-facet.d.ts.map +1 -1
  19. package/dist/loaders/child-process/spawn-facet.js +1 -12
  20. package/dist/loaders/child-process/spawn-pool.d.ts +1 -1
  21. package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
  22. package/dist/loaders/child-process/spawn-pool.js +1 -6
  23. package/dist/npm/installer.d.ts.map +1 -1
  24. package/dist/npm/installer.js +47 -27
  25. package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
  26. package/dist/npm/pre-bundle-facet.js +2 -1
  27. package/dist/npm/resolve-one-facet.d.ts.map +1 -1
  28. package/dist/npm/resolve-one-facet.js +41 -13
  29. package/dist/npm/resolver.d.ts.map +1 -1
  30. package/dist/npm/resolver.js +70 -35
  31. package/dist/router/index.d.ts.map +1 -1
  32. package/dist/router/index.js +45 -21
  33. package/dist/router/remote-api.d.ts.map +1 -1
  34. package/dist/router/remote-api.js +29 -8
  35. package/dist/runtime/barrel-synthesizer.d.ts +7 -0
  36. package/dist/runtime/barrel-synthesizer.d.ts.map +1 -1
  37. package/dist/runtime/barrel-synthesizer.js +11 -0
  38. package/dist/runtime/clang-runner.d.ts.map +1 -1
  39. package/dist/runtime/clang-runner.js +1 -8
  40. package/dist/runtime/esbuild-service.d.ts +12 -5
  41. package/dist/runtime/esbuild-service.d.ts.map +1 -1
  42. package/dist/runtime/esbuild-service.js +28 -14
  43. package/dist/runtime/node-runner.d.ts +2 -0
  44. package/dist/runtime/node-runner.d.ts.map +1 -1
  45. package/dist/runtime/node-shims.d.ts +4 -2
  46. package/dist/runtime/node-shims.d.ts.map +1 -1
  47. package/dist/runtime/node-shims.js +404 -55
  48. package/dist/runtime/os-contracts.d.ts +128 -0
  49. package/dist/runtime/os-contracts.d.ts.map +1 -0
  50. package/dist/runtime/os-contracts.js +1 -0
  51. package/dist/runtime/package-manager.d.ts.map +1 -1
  52. package/dist/runtime/package-manager.js +32 -7
  53. package/dist/runtime/port-registry.d.ts +5 -0
  54. package/dist/runtime/port-registry.d.ts.map +1 -1
  55. package/dist/runtime/port-registry.js +22 -1
  56. package/dist/runtime/pyodide-runtime-assets.d.ts +19 -0
  57. package/dist/runtime/pyodide-runtime-assets.d.ts.map +1 -0
  58. package/dist/runtime/pyodide-runtime-assets.js +44 -0
  59. package/dist/runtime/python-repl.d.ts +3 -1
  60. package/dist/runtime/python-repl.d.ts.map +1 -1
  61. package/dist/runtime/python-repl.js +11 -29
  62. package/dist/runtime/python-runner.d.ts +8 -9
  63. package/dist/runtime/python-runner.d.ts.map +1 -1
  64. package/dist/runtime/python-runner.js +897 -61
  65. package/dist/runtime/python-socket-shim.d.ts +11 -0
  66. package/dist/runtime/python-socket-shim.d.ts.map +1 -0
  67. package/dist/runtime/python-socket-shim.js +526 -0
  68. package/dist/runtime/require-resolver.d.ts.map +1 -1
  69. package/dist/runtime/require-resolver.js +2 -11
  70. package/dist/runtime/ruby-gems.d.ts +25 -0
  71. package/dist/runtime/ruby-gems.d.ts.map +1 -0
  72. package/dist/runtime/ruby-gems.js +582 -0
  73. package/dist/runtime/ruby-runner.d.ts +2 -4
  74. package/dist/runtime/ruby-runner.d.ts.map +1 -1
  75. package/dist/runtime/ruby-runner.js +335 -34
  76. package/dist/runtime/runtime-catalog.d.ts +16 -4
  77. package/dist/runtime/runtime-catalog.d.ts.map +1 -1
  78. package/dist/runtime/runtime-catalog.js +21 -10
  79. package/dist/runtime/runtime-registry.d.ts +3 -0
  80. package/dist/runtime/runtime-registry.d.ts.map +1 -1
  81. package/dist/runtime/runtime-registry.js +4 -0
  82. package/dist/runtime/sqlite-runtime-fs-bridge.d.ts +43 -0
  83. package/dist/runtime/sqlite-runtime-fs-bridge.d.ts.map +1 -0
  84. package/dist/runtime/sqlite-runtime-fs-bridge.js +224 -0
  85. package/dist/runtime/static-server.d.ts +3 -0
  86. package/dist/runtime/static-server.d.ts.map +1 -0
  87. package/dist/runtime/static-server.js +121 -0
  88. package/dist/runtime/vfs-snapshot.d.ts +57 -0
  89. package/dist/runtime/vfs-snapshot.d.ts.map +1 -0
  90. package/dist/runtime/vfs-snapshot.js +141 -0
  91. package/dist/runtime/virtual-socket-kernel.d.ts +16 -0
  92. package/dist/runtime/virtual-socket-kernel.d.ts.map +1 -0
  93. package/dist/runtime/virtual-socket-kernel.js +360 -0
  94. package/dist/runtime/wasi-instance.d.ts +6 -3
  95. package/dist/runtime/wasi-instance.d.ts.map +1 -1
  96. package/dist/runtime/wasm-runner.d.ts +1 -25
  97. package/dist/runtime/wasm-runner.d.ts.map +1 -1
  98. package/dist/runtime/wasm-runner.js +1 -160
  99. package/dist/session/agent.d.ts +43 -0
  100. package/dist/session/agent.d.ts.map +1 -0
  101. package/dist/session/agent.js +1252 -0
  102. package/dist/session/init.d.ts.map +1 -1
  103. package/dist/session/init.js +15 -16
  104. package/dist/session/nimbus-session.d.ts +13 -2
  105. package/dist/session/nimbus-session.d.ts.map +1 -1
  106. package/dist/session/nimbus-session.js +55 -7
  107. package/dist/session/programmatic.d.ts +10 -0
  108. package/dist/session/programmatic.d.ts.map +1 -1
  109. package/dist/session/programmatic.js +121 -0
  110. package/dist/session/routes.d.ts.map +1 -1
  111. package/dist/session/routes.js +19 -1
  112. package/dist/session/rpc.d.ts +11 -0
  113. package/dist/session/rpc.d.ts.map +1 -1
  114. package/dist/session/rpc.js +56 -43
  115. package/dist/session/supervisor-rpc.d.ts +15 -0
  116. package/dist/session/supervisor-rpc.d.ts.map +1 -1
  117. package/dist/session/supervisor-rpc.js +32 -0
  118. package/dist/session/ws.d.ts +4 -3
  119. package/dist/session/ws.d.ts.map +1 -1
  120. package/dist/session/ws.js +11 -1
  121. package/dist/shell/unix-commands.js +12 -16
  122. package/dist/vfs/path.d.ts +8 -4
  123. package/dist/vfs/path.d.ts.map +1 -1
  124. package/dist/vfs/path.js +16 -4
  125. package/dist/vfs/sqlite-vfs.d.ts +2 -0
  126. package/dist/vfs/sqlite-vfs.d.ts.map +1 -1
  127. package/dist/vfs/sqlite-vfs.js +11 -0
  128. package/dist/vfs/symlink-registry.d.ts +7 -1
  129. package/dist/vfs/symlink-registry.d.ts.map +1 -1
  130. package/dist/vfs/symlink-registry.js +16 -11
  131. package/package.json +4 -1
  132. package/public/index.html +240 -0
  133. package/public/s/index.html +1172 -146
  134. package/runtime-contracts/pyodide-workerd-adapter.json +18 -0
  135. package/scripts/bundle-runtime.mjs +99 -24
@@ -49,6 +49,7 @@
49
49
  * workerd CSP rejects that path.
50
50
  */
51
51
  import { WASI_INSTANCE_PREAMBLE_SRC, WASI_IMPLEMENTED_FNS } from './wasi-instance.js';
52
+ import { flushVfsDiff, snapshotVfs } from './vfs-snapshot.js';
52
53
  export const WASM_RUNNER_VERSION = '0.3.0';
53
54
  export const WASM_RUNNER_HELP = 'Usage: wasm-runner [options] <file.wasm> [exportName] [int args...]\n' +
54
55
  ' wasm-runner --version\n' +
@@ -123,166 +124,6 @@ function hasWasiImports(bytes) {
123
124
  }
124
125
  return false;
125
126
  }
126
- /**
127
- * Convert a Uint8Array to a base64 string. Used to encode VFS file
128
- * contents into the JSON-serializable `context` field of the loader
129
- * pool. Workerd's btoa is the standard one; we use it directly rather
130
- * than depending on Node's Buffer (which works in workerd via the
131
- * nodejs_compat polyfill but adds an import dependency).
132
- */
133
- function bytesToB64(bytes) {
134
- let s = '';
135
- for (let i = 0; i < bytes.length; i++)
136
- s += String.fromCharCode(bytes[i]);
137
- return btoa(s);
138
- }
139
- function b64ToBytes(b64) {
140
- const bin = atob(b64);
141
- const out = new Uint8Array(bin.length);
142
- for (let i = 0; i < bin.length; i++)
143
- out[i] = bin.charCodeAt(i);
144
- return out;
145
- }
146
- /**
147
- * Snapshot a VFS subtree rooted at `vfsRoot` into a JSON-serializable
148
- * `WasiFsSnapshot`. Used by the WASI runner to ship the user's session
149
- * filesystem into the facet isolate.
150
- *
151
- * Bounded by:
152
- * - 32 MiB total bytes. Bigger sessions need a streaming or incremental
153
- * filesystem transport instead of a single snapshot.
154
- * - 5000 file count.
155
- *
156
- * Returns null + a diagnostic if bounds are exceeded so the caller
157
- * can surface a clear error to the user.
158
- */
159
- function snapshotVfs(vfs, vfsRoot) {
160
- const MAX_BYTES = 32 * 1024 * 1024;
161
- const MAX_FILES = 5000;
162
- const root = vfsRoot.replace(/^\/+/, '').replace(/\/+$/, '');
163
- const files = {};
164
- const dirs = [];
165
- let totalBytes = 0;
166
- let fileCount = 0;
167
- const stack = [root];
168
- if (!vfs.exists(root)) {
169
- return { snapshot: { root, preopens: [], files: {}, dirs: [root] }, bytes: 0, files: 0 };
170
- }
171
- dirs.push(root);
172
- // Directory prefixes to skip during snapshot. The user's `~/.nimbus`
173
- // install root holds nimbus-managed runtime bundles (clang.wasm,
174
- // lld.wasm, sysroot.tar, Pyodide, …) that easily exceed the
175
- // 32 MiB per-snapshot cap and don't belong in the WASI sandbox
176
- // anyway. node_modules is similar — large, irrelevant to user
177
- // wasm execution.
178
- const skipSubdirs = new Set(['.nimbus', 'node_modules', '.cache', '.npm']);
179
- while (stack.length > 0) {
180
- const dir = stack.pop();
181
- let entries;
182
- try {
183
- entries = vfs.readdir(dir);
184
- }
185
- catch {
186
- continue;
187
- }
188
- for (const e of entries) {
189
- const childPath = dir + '/' + e.name;
190
- if (e.type === 'directory') {
191
- // Skip well-known large/irrelevant subdirs.
192
- if (skipSubdirs.has(e.name))
193
- continue;
194
- dirs.push(childPath);
195
- stack.push(childPath);
196
- continue;
197
- }
198
- let bytes;
199
- try {
200
- bytes = vfs.readFile(childPath);
201
- }
202
- catch {
203
- continue;
204
- }
205
- totalBytes += bytes.length;
206
- fileCount++;
207
- if (totalBytes > MAX_BYTES) {
208
- return { error: `WASI snapshot exceeded 32 MiB cap (current dir: ${dir})` };
209
- }
210
- if (fileCount > MAX_FILES) {
211
- return { error: `WASI snapshot exceeded 5000 file cap` };
212
- }
213
- files[childPath] = bytesToB64(bytes);
214
- }
215
- }
216
- return {
217
- snapshot: { root, preopens: [], files, dirs },
218
- bytes: totalBytes,
219
- files: fileCount,
220
- };
221
- }
222
- /**
223
- * Apply a WasiFsDiff produced by the facet back into the supervisor's
224
- * SqliteFS. Each operation is independent; failures on one path don't
225
- * abort the rest (we log to stderr and continue).
226
- */
227
- function flushVfsDiff(vfs, diff) {
228
- let written = 0, deleted = 0, mkdirs = 0, rmdirs = 0;
229
- let timesTouched = 0, symlinks = 0;
230
- for (const path of diff.dirsCreated) {
231
- try {
232
- vfs.mkdir(path, { recursive: true });
233
- mkdirs++;
234
- }
235
- catch { }
236
- }
237
- for (const [path, b64] of Object.entries(diff.filesWritten)) {
238
- try {
239
- const bytes = b64ToBytes(b64);
240
- // ensure parent dirs exist
241
- const lastSlash = path.lastIndexOf('/');
242
- if (lastSlash > 0) {
243
- const parent = path.substring(0, lastSlash);
244
- try {
245
- vfs.mkdir(parent, { recursive: true });
246
- }
247
- catch { }
248
- }
249
- vfs.writeFile(path, bytes);
250
- written++;
251
- }
252
- catch { }
253
- }
254
- for (const path of diff.filesDeleted) {
255
- try {
256
- vfs.unlink(path);
257
- deleted++;
258
- }
259
- catch { }
260
- }
261
- for (const path of diff.dirsDeleted) {
262
- try {
263
- vfs.rmdir(path);
264
- rmdirs++;
265
- }
266
- catch { }
267
- }
268
- // WASI socket and polling support B1+B3: count timesChanged / symlinks for diagnostics. The
269
- // current SqliteVFS doesn't expose utime() or symlink() on its public
270
- // surface, so we don't persist these across calls — they live only
271
- // within the call (mtimes are read back correctly via stat→filestat_get
272
- // before the snapshot returns). This is a documented v1 limitation.
273
- if (diff.timesChanged) {
274
- timesTouched = Object.keys(diff.timesChanged).length;
275
- // Future hook: when SqliteVFS gains a utime() method, call it here:
276
- // for (const [path, t] of Object.entries(diff.timesChanged)) {
277
- // try { vfs.utime(path, Number(t.atime) / 1e9, Number(t.mtime) / 1e9); } catch {}
278
- // }
279
- }
280
- if (diff.symlinksCreated) {
281
- symlinks = Object.keys(diff.symlinksCreated).length;
282
- // Future hook: when SqliteVFS gains a symlink() method, call it here.
283
- }
284
- return { written, deleted, mkdirs, rmdirs, timesTouched, symlinks };
285
- }
286
127
  /**
287
128
  * Build a `run` function suitable for RuntimeSpec.run(). Parameterised
288
129
  * over the VFS, env (for env.LOADER), ctx (for the pool's doId-scoped
@@ -0,0 +1,43 @@
1
+ /**
2
+ * session/agent.ts - Nimbus session chat agent and Cloudflare OAuth flow.
3
+ *
4
+ * The agent lives in the session Durable Object because that is where the
5
+ * VFS, shell, process table, port registry, and runtime package manager
6
+ * already live. AI calls go through Cloudflare's account REST API so a
7
+ * connected user can spend their own Workers AI quota instead of the
8
+ * Nimbus deployment owner quota.
9
+ */
10
+ interface AgentStorage {
11
+ get(key: string): Promise<unknown>;
12
+ put(key: string, value: unknown): Promise<void>;
13
+ delete(key: string): Promise<void>;
14
+ }
15
+ interface AgentVfs {
16
+ exists(path: string): boolean;
17
+ mkdir(path: string, options?: {
18
+ recursive?: boolean;
19
+ }): void;
20
+ readFileString(path: string): string;
21
+ readdir(path: string): Array<{
22
+ name: string;
23
+ type: string;
24
+ }>;
25
+ writeFile(path: string, content: string): void;
26
+ }
27
+ interface Host {
28
+ ctx: {
29
+ storage: AgentStorage;
30
+ };
31
+ env: Record<string, unknown>;
32
+ sqliteFs?: AgentVfs | null;
33
+ }
34
+ interface OAuthStatePayload {
35
+ v: 1;
36
+ nonce: string;
37
+ sessionId: string;
38
+ tenantSegment: string;
39
+ }
40
+ export declare function handleAgentRequest(self: Host, request: Request, url: URL): Promise<Response>;
41
+ export declare function parseAgentOAuthStateParam(state: string | null): OAuthStatePayload | null;
42
+ export {};
43
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/session/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmCH,UAAU,YAAY;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED,UAAU,QAAQ;IAChB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7D,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAChD;AAED,UAAU,IAAI;IACZ,GAAG,EAAE;QAAE,OAAO,EAAE,YAAY,CAAA;KAAE,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC5B;AAED,UAAU,iBAAiB;IACzB,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA0FD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwClG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAQxF"}