@amalgm/shell 0.1.93 → 0.1.94

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.
@@ -12,7 +12,8 @@ import { EntityRecordSqliteStore } from "./entity-record-store.js";
12
12
  import { observeEntityRecordPorts } from "./entity-record-observability.js";
13
13
  import { indexRowsByOutermostRoot } from "./ground-root-index.js";
14
14
  import { ContentCacheDownload, captureContentFile, hashContentFile, sealCapturedArtifact, } from "./content-cache-host.js";
15
- import { decodeContentWireBytes, encodeContentWireBytes } from "./content-wire-codec.js";
15
+ import { DirectContentPlane } from "./content-direct.js";
16
+ import { encodeContentWireBytes } from "./content-wire-codec.js";
16
17
  import { exactTextReplay, planGroundDetection, reconcileGroundUUIDs, } from "./detection/portable.js";
17
18
  import { AcceptedInboxResultIndex } from "./detection/accepted-result.js";
18
19
  import { sameNotebookBasisRow } from "./detection/notebook-basis.js";
@@ -26,8 +27,13 @@ import { GroundCoordinator } from "./ground-coordination.js";
26
27
  import { submitMutationOperation } from "./paged-mutation-submit.js";
27
28
  import { WireClient, WireRequestError } from "./wire-client.js";
28
29
  const SMALL_CONTENT_UPLOAD_CONCURRENCY = 16;
29
- const FILE_CONTENT_DOWNLOAD_CONCURRENCY = 4;
30
- const FILE_BATCH_DOWNLOAD_CONCURRENCY = 2;
30
+ /** Artifact lanes for a download phase. Direct storage fetches cost the
31
+ * gateway nothing, so parallelism is bounded by this machine's pipe rather
32
+ * than authority fairness. */
33
+ const FILE_CONTENT_DOWNLOAD_CONCURRENCY = 16;
34
+ /** Block lanes within one artifact. Most files are a single block; large
35
+ * repository packs fan their chunks across this. */
36
+ const DIRECT_BLOCK_DOWNLOAD_CONCURRENCY = 8;
31
37
  const DETECT_QUIET_MS = 12;
32
38
  const DETECT_MAX_DEFERRAL_MS = 75;
33
39
  const DETECT_RETRY_MS = 250;
@@ -47,6 +53,7 @@ const GROUND_ROW_COLUMNS = [
47
53
  export class UserGroundHost {
48
54
  options;
49
55
  wire;
56
+ direct;
50
57
  watchHost;
51
58
  activeIdentity = null;
52
59
  rescanTimer = null;
@@ -75,6 +82,9 @@ export class UserGroundHost {
75
82
  runtimeVersion: options.runtimeVersion,
76
83
  requestTimeoutMs: options.wireRequestTimeoutMs,
77
84
  });
85
+ this.direct = new DirectContentPlane({
86
+ request: (frame, accept) => this.wire.request(frame, accept),
87
+ });
78
88
  this.watchHost = new NodeWatchHost({
79
89
  open: options.openWatch,
80
90
  onSignal: () => this.scheduleRescan(),
@@ -670,10 +680,10 @@ export class UserGroundHost {
670
680
  throw new Error("entity Record rail already started");
671
681
  await this.wire.open();
672
682
  // One floor, no per-feature gates: this shell and its gateway release
673
- // together, and the gateway ships first. 8 = paged mutation operations;
674
- // an older gateway drops the stage frame and a large graph could never
675
- // publish.
676
- if (this.wire.protocolVersion < 8) {
683
+ // together, and the gateway ships first. 9 = direct content downloads;
684
+ // an older gateway still relays download bytes itself and drops the key
685
+ // and presign frames this shell depends on.
686
+ if (this.wire.protocolVersion < 9) {
677
687
  throw new Error("gateway speaks an older wire protocol than this shell");
678
688
  }
679
689
  const store = new EntityRecordSqliteStore(initializeDatabase(this.databasePath(identity)));
@@ -1220,42 +1230,13 @@ export class UserGroundHost {
1220
1230
  measurements: { journey: trace?.journey ?? "bootstrap", kind: artifact.kind },
1221
1231
  });
1222
1232
  const cache = { target: null };
1223
- // A cold artifactno local manifest — is fetched whole in one round
1224
- // trip: get-artifact answers with the manifest and, for artifacts within
1225
- // the batch caps, every block packed in part order. Chunk reads then
1226
- // slice this buffer instead of paying a second round trip.
1227
- const prefetched = { bytes: null };
1228
- const sliceChunks = (packed, manifest, indexes) => {
1229
- const offsets = [];
1230
- let offset = 0;
1231
- for (const chunk of manifest.chunks) {
1232
- offsets.push(offset);
1233
- offset += chunk.bytes;
1234
- }
1235
- return Buffer.concat(indexes.map((index) => {
1236
- const chunk = manifest.chunks[index];
1237
- const start = offsets[index];
1238
- if (!chunk || start === undefined)
1239
- throw new Error(`content manifest has no chunk ${index}`);
1240
- return packed.subarray(start, start + chunk.bytes);
1241
- }));
1242
- };
1243
- const getChunk = async (manifest, index) => {
1244
- if (prefetched.bytes)
1245
- return sliceChunks(prefetched.bytes, manifest, [index]);
1246
- const chunk = manifest.chunks[index];
1247
- if (!chunk)
1248
- throw new Error(`content manifest has no chunk ${index}`);
1233
+ // Every storage objectthe manifest and each block — is fetched
1234
+ // straight from content storage over a presigned URL and opened locally;
1235
+ // the wire carries only the key handoff and signing requests. A retry
1236
+ // asks for a fresh URL every attempt.
1237
+ const fetchObject = async (object) => {
1249
1238
  requests += 1;
1250
- const frame = await retryContent(() => this.wire.request({
1251
- type: "private.entity-content.get",
1252
- resource_id: resourceId,
1253
- content_hash: artifact.contentHash,
1254
- kind: "chunk",
1255
- part_index: index,
1256
- sha256: chunk.sha256,
1257
- }, ["private.entity-content.data"]), true, retryAttempts);
1258
- const bytes = binaryFrameBytes(frame);
1239
+ const bytes = await retryContent(() => this.direct.fetchObject(resourceId, object), true, retryAttempts);
1259
1240
  downloadedBytes += bytes.byteLength;
1260
1241
  return bytes;
1261
1242
  };
@@ -1267,73 +1248,39 @@ export class UserGroundHost {
1267
1248
  // proves chunk identity; downloaded bytes are still hash-verified,
1268
1249
  // so a stale local manifest can only fail loudly, never corrupt.
1269
1250
  const local = knownManifest ?? readCachedManifest(cacheDir, artifact.contentHash);
1270
- if (local) {
1271
- cache.target = new ContentCacheDownload(cacheDir, artifact, local);
1272
- return local;
1273
- }
1274
- requests += 1;
1275
- const frame = await retryContent(() => this.wire.request({
1276
- type: "private.entity-content.get-artifact",
1277
- resource_id: resourceId,
1278
- content_hash: artifact.contentHash,
1279
- }, ["private.entity-content.artifact"]), true, retryAttempts);
1280
- const manifestJson = String(frame.manifest_json ?? "");
1281
- downloadedBytes += Buffer.byteLength(manifestJson);
1282
- const checked = checkContentManifest(JSON.parse(manifestJson), artifact.contentHash);
1283
- if (!checked.ok)
1284
- throw new Error(checked.error);
1285
- if (frame.complete === true) {
1286
- const decoded = await decodeContentWireBytes(binaryWireFrameBytes(frame), frame.content_encoding, Number(frame.bytes));
1287
- if (decoded.byteLength !== checked.value.bytes) {
1288
- throw new Error("artifact payload does not match its manifest");
1289
- }
1290
- prefetched.bytes = decoded;
1291
- downloadedBytes += Number(frame.wire_bytes ?? frame.bytes);
1292
- }
1293
- cache.target = new ContentCacheDownload(cacheDir, artifact, checked.value);
1294
- return checked.value;
1251
+ const manifest = local ?? await (async () => {
1252
+ const bytes = await fetchObject({ kind: "manifest", sha256: artifact.contentHash });
1253
+ const checked = checkContentManifest(JSON.parse(bytes.toString("utf8")), artifact.contentHash);
1254
+ if (!checked.ok)
1255
+ throw new Error(checked.error);
1256
+ return checked.value;
1257
+ })();
1258
+ cache.target = new ContentCacheDownload(cacheDir, artifact, manifest);
1259
+ return manifest;
1295
1260
  },
1296
1261
  hasChunk: async (_candidate, _manifest, index) => {
1297
1262
  if (!cache.target)
1298
1263
  throw new Error("download cache has no content manifest");
1299
1264
  return cache.target.hasChunk(index);
1300
1265
  },
1301
- getChunk: async (_candidate, manifest, index) => getChunk(manifest, index),
1302
- getChunkBatch: async (_candidate, manifest, indexes) => {
1303
- if (prefetched.bytes)
1304
- return sliceChunks(prefetched.bytes, manifest, indexes);
1305
- const frame = await retryContent(() => this.wire.request({
1306
- type: "private.entity-content.get-batch",
1307
- resource_id: resourceId,
1308
- content_hash: artifact.contentHash,
1309
- chunks: indexes.map((index) => ({
1310
- part_index: index,
1311
- sha256: manifest.chunks[index]?.sha256,
1312
- bytes: manifest.chunks[index]?.bytes,
1313
- })),
1314
- }, ["private.entity-content.data-batch"]), true, retryAttempts);
1315
- requests += 1;
1316
- const decoded = await decodeContentWireBytes(binaryWireFrameBytes(frame), frame.content_encoding, Number(frame.bytes));
1317
- downloadedBytes += Number(frame.wire_bytes ?? frame.bytes);
1318
- return decoded;
1266
+ getChunk: async (_candidate, manifest, index) => {
1267
+ const chunk = manifest.chunks[index];
1268
+ if (!chunk)
1269
+ throw new Error(`content manifest has no chunk ${index}`);
1270
+ return fetchObject({ kind: "block", sha256: chunk.sha256 });
1319
1271
  },
1320
1272
  putChunk: async (_candidate, _manifest, index, bytes) => {
1321
1273
  if (!cache.target)
1322
1274
  throw new Error("download cache has no content manifest");
1323
1275
  await cache.target.putChunk(index, bytes);
1324
1276
  },
1325
- putChunkBatch: async (_candidate, _manifest, indexes, bytes) => {
1326
- if (!cache.target)
1327
- throw new Error("download cache has no content manifest");
1328
- await cache.target.putChunkBatch(indexes, bytes);
1329
- },
1330
1277
  sealArtifact: async () => {
1331
1278
  if (!cache.target)
1332
1279
  throw new Error("download cache has no content manifest");
1333
1280
  const sealed = await cache.target.seal();
1334
1281
  return { local: sealed, bytes: sealed.bytes, contentHash: sealed.contentHash };
1335
1282
  },
1336
- }, artifact.kind === "file" ? { concurrency: FILE_BATCH_DOWNLOAD_CONCURRENCY } : {});
1283
+ }, { concurrency: DIRECT_BLOCK_DOWNLOAD_CONCURRENCY });
1337
1284
  this.stage({
1338
1285
  primitive: "download",
1339
1286
  stage: "immutable-content",
@@ -4689,28 +4636,6 @@ function readyFromFrame(frame) {
4689
4636
  },
4690
4637
  };
4691
4638
  }
4692
- /** Expose the WebSocket payload as a view. Live verifies content blocks
4693
- * against their manifest, so the host must not copy or hash those bytes a
4694
- * second time before returning them to the portable operation. */
4695
- function binaryFrameBytes(frame) {
4696
- const bytes = binaryWireFrameBytes(frame);
4697
- if (frame.content_encoding !== undefined || bytes.length !== Number(frame.bytes)) {
4698
- throw new Error("wire content byte count does not match its header");
4699
- }
4700
- return bytes;
4701
- }
4702
- function binaryWireFrameBytes(frame) {
4703
- if (!(frame.data_bin instanceof Uint8Array)) {
4704
- throw new Error("wire content response is not a binary frame");
4705
- }
4706
- const bytes = Buffer.isBuffer(frame.data_bin)
4707
- ? frame.data_bin
4708
- : Buffer.from(frame.data_bin.buffer, frame.data_bin.byteOffset, frame.data_bin.byteLength);
4709
- if (bytes.length !== Number(frame.wire_bytes ?? frame.bytes)) {
4710
- throw new Error("wire content byte count does not match its header");
4711
- }
4712
- return bytes;
4713
- }
4714
4639
  /** Immutable content reads and writes are idempotent. Retry transient wire or
4715
4640
  * authority failures; reads additionally tolerate the brief not-found window
4716
4641
  * between an immutable object acknowledgement and globally visible R2 state. */