@volter/world-core 3.0.156 → 3.0.158

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 (74) hide show
  1. package/attach.cjs +2 -0
  2. package/capability-decision.cjs +6 -4
  3. package/dist/attach.cjs +2 -0
  4. package/dist/capability-decision.cjs +6 -4
  5. package/dist/generated/pack-facts.json +77 -8
  6. package/dist/network-policy.cjs +11 -1
  7. package/dist/network-policy.d.cts +1 -0
  8. package/dist/pack-facts.d.cts +3 -0
  9. package/dist/required-credential-transport.cjs +29 -0
  10. package/dist/required-credential-transport.d.cts +3 -0
  11. package/dist/src/blob-store.d.ts +16 -0
  12. package/dist/src/blob-store.js +76 -1
  13. package/dist/src/derived-core.d.ts +72 -6
  14. package/dist/src/derived-core.js +192 -51
  15. package/dist/src/derived-real.js +97 -15
  16. package/dist/src/derived.d.ts +5 -0
  17. package/dist/src/executor.d.ts +7 -0
  18. package/dist/src/executor.js +15 -1
  19. package/dist/src/git/lfs.d.ts +13 -3
  20. package/dist/src/git/lfs.js +41 -9
  21. package/dist/src/head.d.ts +2 -0
  22. package/dist/src/head.js +6 -0
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.js +1 -0
  25. package/dist/src/live/ingest.js +9 -13
  26. package/dist/src/live/rtmp.js +7 -5
  27. package/dist/src/live/segmenter.js +7 -1
  28. package/dist/src/machines.js +5 -1
  29. package/dist/src/managed-go-programs.d.ts +55 -0
  30. package/dist/src/managed-go-programs.js +133 -0
  31. package/dist/src/mongodb/stream.d.ts +23 -0
  32. package/dist/src/pack-fetch.d.ts +6 -1
  33. package/dist/src/pack-fetch.js +53 -7
  34. package/dist/src/pack-paths.d.ts +2 -1
  35. package/dist/src/pack-paths.js +6 -1
  36. package/dist/src/resource-blob.d.ts +4 -0
  37. package/dist/src/resource-blob.js +8 -1
  38. package/dist/src/runtime.d.ts +3 -3
  39. package/dist/src/runtime.js +2 -2
  40. package/dist/src/serve-http.js +53 -3
  41. package/dist/src/sockets.d.ts +4 -1
  42. package/dist/src/sockets.js +59 -6
  43. package/dist/src/vendor-call.js +58 -0
  44. package/dist/src/world-store.d.ts +15 -1
  45. package/dist/src/world-store.js +78 -2
  46. package/generated/pack-facts.json +77 -8
  47. package/network-policy.cjs +11 -1
  48. package/network-policy.d.cts +1 -0
  49. package/pack-facts.d.cts +3 -0
  50. package/package.json +8 -1
  51. package/required-credential-transport.cjs +29 -0
  52. package/required-credential-transport.d.cts +3 -0
  53. package/src/blob-store.ts +59 -1
  54. package/src/derived-core.ts +215 -51
  55. package/src/derived-real.ts +80 -14
  56. package/src/derived.ts +6 -1
  57. package/src/executor.ts +17 -3
  58. package/src/git/lfs.ts +40 -9
  59. package/src/head.ts +6 -0
  60. package/src/index.ts +1 -0
  61. package/src/live/ingest.ts +7 -3
  62. package/src/live/rtmp.ts +7 -5
  63. package/src/live/segmenter.ts +7 -1
  64. package/src/machines.ts +5 -1
  65. package/src/managed-go-programs.ts +146 -0
  66. package/src/mongodb/stream.ts +10 -0
  67. package/src/pack-fetch.ts +50 -9
  68. package/src/pack-paths.ts +5 -1
  69. package/src/resource-blob.ts +9 -1
  70. package/src/runtime.ts +4 -2
  71. package/src/serve-http.ts +43 -3
  72. package/src/sockets.ts +39 -8
  73. package/src/vendor-call.ts +54 -0
  74. package/src/world-store.ts +66 -2
package/src/blob-store.ts CHANGED
@@ -19,7 +19,7 @@
19
19
  // local worlds change NOTHING — scrub, backup, and inspection all still see the same tree.
20
20
  // A remote adapter maps the path to an object key (namespace prefix + path).
21
21
  import { createHash, randomUUID } from 'node:crypto';
22
- import { closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
22
+ import { closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, renameSync, rmSync, statSync, writeFileSync, writeSync } from 'node:fs';
23
23
  import { dirname, join } from 'node:path';
24
24
  import { volterHome } from './volter-home.ts';
25
25
  import { sharedBlobIndex } from './shared-blob-index.ts';
@@ -46,6 +46,38 @@ export interface BlobStore {
46
46
  * whole. Optional: `readBlobRange` falls back to `get` (a whole read) for a backend without it —
47
47
  * the hosted World's R2 store today. */
48
48
  getRange?(key: string, start: number, endInclusive: number): Promise<Uint8Array | null>;
49
+ /** A body's chunks written to `key` as they arrive and hashed as they are written, kept (atomically, as `put`)
50
+ * only when `accept` holds for their size and SHA-256; otherwise nothing is kept. True when kept. So an upload
51
+ * of a large object (a model's weights) never holds more than a chunk. Optional: `writeBlobStream` collects
52
+ * the chunks and `put`s them for a backend without it. */
53
+ putStream?(key: string, chunks: AsyncIterable<Uint8Array>, accept: (written: BlobWritten) => boolean): Promise<boolean>;
54
+ }
55
+
56
+ /** What a streamed write wrote: its byte length and its SHA-256 (hex). */
57
+ export type BlobWritten = { size: number; sha256: string };
58
+
59
+ /** A body's chunks to `key` through the active store, kept when `accept` holds for what was written (the store's
60
+ * own streamed write where it has one, else the chunks collected and `put`). True when kept. */
61
+ export async function writeBlobStream(key: string, chunks: AsyncIterable<Uint8Array>, accept: (written: BlobWritten) => boolean): Promise<boolean> {
62
+ const store = getActiveBlobStore();
63
+ if (store.putStream) return store.putStream(key, chunks, accept);
64
+ const parts: Uint8Array[] = [];
65
+ let size = 0;
66
+ for await (const chunk of chunks) { parts.push(chunk); size += chunk.byteLength; }
67
+ const bytes = new Uint8Array(size);
68
+ let at = 0;
69
+ for (const part of parts) { bytes.set(part, at); at += part.byteLength; }
70
+ if (!accept({ size, sha256: blobDigest(bytes) })) return false;
71
+ await store.put(key, bytes);
72
+ return true;
73
+ }
74
+
75
+ /** A web stream's chunks, read by its reader (a browser's ReadableStream need not be async-iterable). */
76
+ export async function* streamChunks(body: ReadableStream<Uint8Array>): AsyncGenerator<Uint8Array> {
77
+ const reader = body.getReader();
78
+ try {
79
+ for (;;) { const { done, value } = await reader.read(); if (done) return; if (value) yield value; }
80
+ } finally { reader.releaseLock(); }
49
81
  }
50
82
 
51
83
  /** A range of the blob at `key` through the active store: native when the store has it, else sliced. */
@@ -86,6 +118,30 @@ export class FsBlobStore implements BlobStore {
86
118
  index?.record(key);
87
119
  } finally { rmSync(tmp, { force: true }); }
88
120
  }
121
+ async putStream(key: string, chunks: AsyncIterable<Uint8Array>, accept: (written: BlobWritten) => boolean): Promise<boolean> {
122
+ mkdirSync(dirname(key), { recursive: true });
123
+ const tmp = `${key}.tmp.${randomUUID()}`;
124
+ const hash = createHash('sha256');
125
+ let size = 0;
126
+ try {
127
+ const fd = openSync(tmp, 'wx');
128
+ try {
129
+ for await (const chunk of chunks) {
130
+ hash.update(chunk);
131
+ size += chunk.byteLength;
132
+ for (let at = 0; at < chunk.byteLength;) at += writeSync(fd, chunk, at, chunk.byteLength - at);
133
+ }
134
+ } finally { closeSync(fd); }
135
+ const sha256 = hash.digest('hex');
136
+ if (!accept({ size, sha256 })) return false;
137
+ renameSync(tmp, key);
138
+ if (this.options.sharedIndexRoot !== false) {
139
+ try { sharedBlobIndex(this.options.sharedIndexRoot ?? join(volterHome(), 'blob-index-v1'), statSync(dirname(key)).dev, sha256).record(key); }
140
+ catch { /* The index is an optimization, never a prerequisite for a blob write. */ }
141
+ }
142
+ return true;
143
+ } finally { rmSync(tmp, { force: true }); }
144
+ }
89
145
  async exists(key: string): Promise<boolean> {
90
146
  return existsSync(key);
91
147
  }
@@ -178,7 +234,9 @@ function readOnlyBlobs(store: BlobStore): BlobStore {
178
234
  exists: (key) => store.exists(key),
179
235
  list: (prefix) => store.list(prefix),
180
236
  size: (key) => store.size(key),
237
+ ...(store.getRange ? { getRange: (key: string, start: number, endInclusive: number) => store.getRange!(key, start, endInclusive) } : {}),
181
238
  put: async () => { refuseReadOnlyWrite('blobs'); },
239
+ putStream: async () => { refuseReadOnlyWrite('blobs'); return false; },
182
240
  remove: async () => { refuseReadOnlyWrite('blobs'); },
183
241
  };
184
242
  }