@volter/world-core 3.0.156 → 3.0.157
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/attach.cjs +2 -0
- package/capability-decision.cjs +6 -4
- package/dist/attach.cjs +2 -0
- package/dist/capability-decision.cjs +6 -4
- package/dist/generated/pack-facts.json +77 -8
- package/dist/network-policy.cjs +11 -1
- package/dist/network-policy.d.cts +1 -0
- package/dist/pack-facts.d.cts +3 -0
- package/dist/required-credential-transport.cjs +29 -0
- package/dist/required-credential-transport.d.cts +3 -0
- package/dist/src/blob-store.d.ts +16 -0
- package/dist/src/blob-store.js +76 -1
- package/dist/src/derived-core.d.ts +72 -6
- package/dist/src/derived-core.js +192 -51
- package/dist/src/derived-real.js +97 -15
- package/dist/src/derived.d.ts +5 -0
- package/dist/src/executor.d.ts +7 -0
- package/dist/src/executor.js +15 -1
- package/dist/src/git/lfs.d.ts +13 -3
- package/dist/src/git/lfs.js +41 -9
- package/dist/src/head.d.ts +2 -0
- package/dist/src/head.js +6 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/live/ingest.js +9 -13
- package/dist/src/live/rtmp.js +7 -5
- package/dist/src/live/segmenter.js +7 -1
- package/dist/src/machines.js +5 -1
- package/dist/src/managed-go-programs.d.ts +55 -0
- package/dist/src/managed-go-programs.js +133 -0
- package/dist/src/mongodb/stream.d.ts +23 -0
- package/dist/src/pack-fetch.d.ts +6 -1
- package/dist/src/pack-fetch.js +49 -6
- package/dist/src/pack-paths.d.ts +2 -1
- package/dist/src/pack-paths.js +6 -1
- package/dist/src/resource-blob.d.ts +4 -0
- package/dist/src/resource-blob.js +8 -1
- package/dist/src/runtime.d.ts +3 -3
- package/dist/src/runtime.js +2 -2
- package/dist/src/serve-http.js +53 -3
- package/dist/src/sockets.d.ts +4 -1
- package/dist/src/sockets.js +59 -6
- package/dist/src/vendor-call.js +58 -0
- package/dist/src/world-store.d.ts +15 -1
- package/dist/src/world-store.js +78 -2
- package/generated/pack-facts.json +77 -8
- package/network-policy.cjs +11 -1
- package/network-policy.d.cts +1 -0
- package/pack-facts.d.cts +3 -0
- package/package.json +8 -1
- package/required-credential-transport.cjs +29 -0
- package/required-credential-transport.d.cts +3 -0
- package/src/blob-store.ts +59 -1
- package/src/derived-core.ts +215 -51
- package/src/derived-real.ts +80 -14
- package/src/derived.ts +6 -1
- package/src/executor.ts +17 -3
- package/src/git/lfs.ts +40 -9
- package/src/head.ts +6 -0
- package/src/index.ts +1 -0
- package/src/live/ingest.ts +7 -3
- package/src/live/rtmp.ts +7 -5
- package/src/live/segmenter.ts +7 -1
- package/src/machines.ts +5 -1
- package/src/managed-go-programs.ts +146 -0
- package/src/mongodb/stream.ts +10 -0
- package/src/pack-fetch.ts +46 -8
- package/src/pack-paths.ts +5 -1
- package/src/resource-blob.ts +9 -1
- package/src/runtime.ts +4 -2
- package/src/serve-http.ts +43 -3
- package/src/sockets.ts +39 -8
- package/src/vendor-call.ts +54 -0
- 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
|
}
|