@amalgm/shell 0.1.164-preview.36809057014 → 0.1.164-preview.36824980905
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/PURPOSE.md +28 -3
- package/dist/authority-binding.d.ts +32 -0
- package/dist/authority-binding.js +23 -0
- package/dist/authority-binding.js.map +1 -0
- package/dist/content-cache-host.d.ts +1 -0
- package/dist/content-cache-host.js +21 -6
- package/dist/content-cache-host.js.map +1 -1
- package/dist/entity-apply-host.js +10 -7
- package/dist/entity-apply-host.js.map +1 -1
- package/dist/ground-database.js +7 -0
- package/dist/ground-database.js.map +1 -1
- package/dist/ground-inventory-schema.js +30 -14
- package/dist/ground-inventory-schema.js.map +1 -1
- package/dist/ground-save-ops.d.ts +2 -0
- package/dist/ground-save-ops.js +2 -0
- package/dist/ground-save-ops.js.map +1 -1
- package/dist/physical-path-witness.d.ts +9 -0
- package/dist/physical-path-witness.js +8 -0
- package/dist/physical-path-witness.js.map +1 -1
- package/dist/source-witness.d.ts +2 -2
- package/dist/source-witness.js +2 -1
- package/dist/source-witness.js.map +1 -1
- package/dist/user-ground-host.d.ts +4 -0
- package/dist/user-ground-host.js +14 -0
- package/dist/user-ground-host.js.map +1 -1
- package/examinations/fixtures/private-wire-authority.js +154 -72
- package/npm-shrinkwrap.json +59 -38
- package/package.json +5 -5
|
@@ -58,6 +58,19 @@ function sealContentEnvelope(resourceId, data) {
|
|
|
58
58
|
]);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/** A refusal the authority types: the code, status and retry posture the
|
|
62
|
+
* gateway answers on the wire. Any other failure is the authority's own. */
|
|
63
|
+
class AuthorityRefusal extends Error {
|
|
64
|
+
constructor(code, message, status, retryable) {
|
|
65
|
+
super(message);
|
|
66
|
+
this.code = code;
|
|
67
|
+
this.status = status;
|
|
68
|
+
this.retryable = retryable;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
73
|
+
|
|
61
74
|
/** Shared test authority for the exact private-resource/content/mutation
|
|
62
75
|
* frames used by the production host. It also serves the direct content
|
|
63
76
|
* plane: refs answer where each sealed envelope lives — a byte range of an
|
|
@@ -155,7 +168,34 @@ export function createPrivateWireAuthority({
|
|
|
155
168
|
response.end();
|
|
156
169
|
});
|
|
157
170
|
const sockets = new WebSocketServer({ server });
|
|
158
|
-
|
|
171
|
+
// Every private resource, by its id. The id is derived from the registry
|
|
172
|
+
// contract, so a runtime on another contract finds nothing until it ensures
|
|
173
|
+
// its own resource, exactly as the gateway's lookup answers it.
|
|
174
|
+
const resources = new Map();
|
|
175
|
+
let latestResourceId = null;
|
|
176
|
+
const latestResource = () => resources.get(latestResourceId) ?? null;
|
|
177
|
+
// Each authority's delivery prefix: positions are assigned per authority,
|
|
178
|
+
// behind that authority's own commit gate.
|
|
179
|
+
const deliveryPrefixes = new Map();
|
|
180
|
+
const deliveryPrefix = (authorityId) => deliveryPrefixes.get(authorityId) ?? 0;
|
|
181
|
+
// The gateway law: every frame is answered. A failure the authority did not
|
|
182
|
+
// type is its own fault, 503 and retryable, and is never thrown into the
|
|
183
|
+
// process hosting it. This ledger keeps every refusal for diagnosis.
|
|
184
|
+
const refusals = [];
|
|
185
|
+
const refuse = (socket, frame, cause) => {
|
|
186
|
+
const typed = cause instanceof AuthorityRefusal;
|
|
187
|
+
const failure = {
|
|
188
|
+
code: typed ? cause.code
|
|
189
|
+
: String(frame?.type).startsWith("entity.record.") ? "entity_record_realtime_internal_error"
|
|
190
|
+
: "shared_realtime_internal_error",
|
|
191
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
192
|
+
status: typed ? cause.status : 503,
|
|
193
|
+
retryable: typed ? cause.retryable : true,
|
|
194
|
+
};
|
|
195
|
+
refusals.push({ type: frame?.type ?? null, ...failure });
|
|
196
|
+
if (socket.readyState !== WebSocket.OPEN) return;
|
|
197
|
+
socket.send(JSON.stringify({ type: "shared.error", request_id: frame?.request_id, ...failure }));
|
|
198
|
+
};
|
|
159
199
|
const content = new Map();
|
|
160
200
|
// The pack law: each cargo segment is durable as ONE immutable byte string
|
|
161
201
|
// (chunk envelopes in artifact order, manifest envelopes at the tail) and
|
|
@@ -164,6 +204,17 @@ export function createPrivateWireAuthority({
|
|
|
164
204
|
const packLocations = new Map();
|
|
165
205
|
let contentPutsInFlight = 0;
|
|
166
206
|
let maxContentPutsInFlight = 0;
|
|
207
|
+
/** One content put, in flight from its admission until it is answered:
|
|
208
|
+
* stored, or refused on the wire. */
|
|
209
|
+
const storeContent = (socket, frame, store) => {
|
|
210
|
+
contentPutsInFlight += 1;
|
|
211
|
+
maxContentPutsInFlight = Math.max(maxContentPutsInFlight, contentPutsInFlight);
|
|
212
|
+
void (contentPutGate ? contentPutGate() : Promise.resolve())
|
|
213
|
+
.then(() => (contentPutDelayMs > 0 ? delay(contentPutDelayMs) : undefined))
|
|
214
|
+
.then(store)
|
|
215
|
+
.catch((cause) => refuse(socket, frame, cause))
|
|
216
|
+
.finally(() => { contentPutsInFlight -= 1; });
|
|
217
|
+
};
|
|
167
218
|
let contentPutAttempts = 0;
|
|
168
219
|
// Every put attempt's content hash, and the hashes the committed graph
|
|
169
220
|
// claims as pages. Pages ride the same content plane as file cargo, so
|
|
@@ -222,11 +273,16 @@ export function createPrivateWireAuthority({
|
|
|
222
273
|
const heldGraphSubmits = [];
|
|
223
274
|
let withholdGraphAcks = false;
|
|
224
275
|
const withheldGraphAcks = [];
|
|
276
|
+
// An examination hold on entity records, off unless armed: a submit the
|
|
277
|
+
// selector names parks before acceptance and replays, in arrival order,
|
|
278
|
+
// when released. It fixes the order the authority accepts concurrent
|
|
279
|
+
// writes in, which nothing else in a test controls.
|
|
280
|
+
let entityRecordHold = null;
|
|
281
|
+
const heldEntityRecordSubmits = [];
|
|
225
282
|
// Every answer to a mutation submit, in order: committed, duplicate, or
|
|
226
283
|
// the refusal code.
|
|
227
284
|
const graphAnswers = [];
|
|
228
285
|
const committedMutationAcks = new Map();
|
|
229
|
-
let deliverySequence = 0;
|
|
230
286
|
const entityRecords = [];
|
|
231
287
|
const entityHeads = new Map();
|
|
232
288
|
const entityDedup = new Map();
|
|
@@ -341,12 +397,20 @@ export function createPrivateWireAuthority({
|
|
|
341
397
|
grantWatchers.delete(socket);
|
|
342
398
|
});
|
|
343
399
|
const receive = (data, isBinary) => {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
400
|
+
let frame = null;
|
|
401
|
+
try {
|
|
402
|
+
frame = isBinary
|
|
403
|
+
? (() => {
|
|
404
|
+
const decoded = decodeBinaryFrame(data);
|
|
405
|
+
return { ...decoded.frame, data_bin: decoded.bytes };
|
|
406
|
+
})()
|
|
407
|
+
: JSON.parse(data.toString("utf8"));
|
|
408
|
+
dispatch(frame, data, isBinary);
|
|
409
|
+
} catch (cause) {
|
|
410
|
+
refuse(socket, frame, cause);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const dispatch = (frame, data, isBinary) => {
|
|
350
414
|
if (holdGraphSubmits && frame.type === "shared.mutation.submit"
|
|
351
415
|
&& frame.envelope?.operationKind === GRAPH_HEAD_OPERATION_KIND) {
|
|
352
416
|
const { mutationId, deviceId, baseVersion, deliveryWatermark } = frame.envelope;
|
|
@@ -354,6 +418,14 @@ export function createPrivateWireAuthority({
|
|
|
354
418
|
replay: () => receive(data, isBinary) });
|
|
355
419
|
return;
|
|
356
420
|
}
|
|
421
|
+
if (entityRecordHold && frame.type === "entity.record.submit") {
|
|
422
|
+
const submitted = decodeLocalEntityRecord(frame.record_json);
|
|
423
|
+
if (entityRecordHold(submitted)) {
|
|
424
|
+
heldEntityRecordSubmits.push({ entityId: submitted.entityId, mutationId: submitted.mutationId,
|
|
425
|
+
heldAt: epochNow(), replay: () => receive(data, isBinary) });
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
357
429
|
if (frame.type === "private.entity-content.put"
|
|
358
430
|
|| frame.type === "private.entity-content.put-blocks"
|
|
359
431
|
|| frame.type === "private.entity-content.put-cargo") {
|
|
@@ -366,26 +438,31 @@ export function createPrivateWireAuthority({
|
|
|
366
438
|
if (frame.type === "hello") {
|
|
367
439
|
socket.send(JSON.stringify({ type: "hello_ack", protocol_version: protocolVersion }));
|
|
368
440
|
} else if (frame.type === "private.resource.lookup") {
|
|
369
|
-
|
|
441
|
+
const resource = resources.get(frame.resource_id);
|
|
442
|
+
socket.send(JSON.stringify(resource ? ready(frame.request_id, resource, true) : {
|
|
370
443
|
type: "private.resource.missing",
|
|
371
444
|
request_id: frame.request_id,
|
|
372
445
|
resource_id: frame.resource_id,
|
|
373
446
|
contract: frame.contract,
|
|
374
447
|
}));
|
|
375
448
|
} else if (frame.type === "private.resource.ensure") {
|
|
376
|
-
const duplicate =
|
|
377
|
-
if (!
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
449
|
+
const duplicate = resources.has(frame.resource_id);
|
|
450
|
+
if (!duplicate) {
|
|
451
|
+
resources.set(frame.resource_id, {
|
|
452
|
+
resourceId: frame.resource_id,
|
|
453
|
+
contract: frame.contract,
|
|
454
|
+
checksum: frame.snapshot_checksum,
|
|
455
|
+
snapshotB64: frame.snapshot_b64,
|
|
456
|
+
rootRecords: recordsByRoot(JSON.parse(
|
|
457
|
+
Buffer.from(frame.snapshot_b64, "base64").toString("utf8"),
|
|
458
|
+
).records),
|
|
459
|
+
version: 0,
|
|
460
|
+
deliveryWatermark: 0,
|
|
461
|
+
authorityEpoch: 1,
|
|
462
|
+
});
|
|
463
|
+
latestResourceId = frame.resource_id;
|
|
464
|
+
}
|
|
465
|
+
socket.send(JSON.stringify(ready(frame.request_id, resources.get(frame.resource_id), duplicate)));
|
|
389
466
|
} else if (frame.type === "private.entity-content.inventory") {
|
|
390
467
|
contentInventories.push({ ...frame });
|
|
391
468
|
const manifestKey = contentKey({
|
|
@@ -424,9 +501,7 @@ export function createPrivateWireAuthority({
|
|
|
424
501
|
}));
|
|
425
502
|
return;
|
|
426
503
|
}
|
|
427
|
-
|
|
428
|
-
maxContentPutsInFlight = Math.max(maxContentPutsInFlight, contentPutsInFlight);
|
|
429
|
-
const store = () => {
|
|
504
|
+
storeContent(socket, frame, () => {
|
|
430
505
|
const data = Buffer.from(frame.data_bin);
|
|
431
506
|
assert.equal(sha256(data), frame.sha256, "a manifest seal proves its own digest");
|
|
432
507
|
const manifest = JSON.parse(data.toString("utf8"));
|
|
@@ -437,16 +512,8 @@ export function createPrivateWireAuthority({
|
|
|
437
512
|
sha256: chunk.sha256,
|
|
438
513
|
}));
|
|
439
514
|
if (absent) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
request_id: frame.request_id,
|
|
443
|
-
code: "entity_content_incomplete",
|
|
444
|
-
message: `manifest names absent block ${absent.sha256}`,
|
|
445
|
-
status: 409,
|
|
446
|
-
retryable: true,
|
|
447
|
-
}));
|
|
448
|
-
contentPutsInFlight -= 1;
|
|
449
|
-
return;
|
|
515
|
+
throw new AuthorityRefusal("entity_content_incomplete",
|
|
516
|
+
`manifest names absent block ${absent.sha256}`, 409, true);
|
|
450
517
|
}
|
|
451
518
|
content.set(contentKey(frame), {
|
|
452
519
|
sha256: frame.sha256,
|
|
@@ -462,12 +529,6 @@ export function createPrivateWireAuthority({
|
|
|
462
529
|
store_ms: 3,
|
|
463
530
|
seal_ms: 4,
|
|
464
531
|
}));
|
|
465
|
-
contentPutsInFlight -= 1;
|
|
466
|
-
};
|
|
467
|
-
const admitted = contentPutGate ? contentPutGate() : Promise.resolve();
|
|
468
|
-
void admitted.then(() => {
|
|
469
|
-
if (contentPutDelayMs > 0) setTimeout(store, contentPutDelayMs);
|
|
470
|
-
else store();
|
|
471
532
|
});
|
|
472
533
|
} else if (frame.type === "private.entity-content.put-blocks") {
|
|
473
534
|
// Provisional blocks addressed by their own digests: durable at
|
|
@@ -490,10 +551,8 @@ export function createPrivateWireAuthority({
|
|
|
490
551
|
}));
|
|
491
552
|
return;
|
|
492
553
|
}
|
|
493
|
-
contentPutsInFlight += 1;
|
|
494
|
-
maxContentPutsInFlight = Math.max(maxContentPutsInFlight, contentPutsInFlight);
|
|
495
554
|
const decodedBatch = decodeWireBatch(frame);
|
|
496
|
-
|
|
555
|
+
storeContent(socket, frame, () => {
|
|
497
556
|
let offset = 0;
|
|
498
557
|
for (const block of frame.blocks) {
|
|
499
558
|
const bytes = Buffer.from(decodedBatch.subarray(offset, offset + block.bytes));
|
|
@@ -514,12 +573,6 @@ export function createPrivateWireAuthority({
|
|
|
514
573
|
verify_ms: 2,
|
|
515
574
|
store_ms: 3,
|
|
516
575
|
}));
|
|
517
|
-
contentPutsInFlight -= 1;
|
|
518
|
-
};
|
|
519
|
-
const admitted = contentPutGate ? contentPutGate() : Promise.resolve();
|
|
520
|
-
void admitted.then(() => {
|
|
521
|
-
if (contentPutDelayMs > 0) setTimeout(store, contentPutDelayMs);
|
|
522
|
-
else store();
|
|
523
576
|
});
|
|
524
577
|
} else if (frame.type === "private.entity-content.put-cargo") {
|
|
525
578
|
assert.equal(isBinary, true, "cargo segments use the binary WebSocket rail");
|
|
@@ -546,10 +599,8 @@ export function createPrivateWireAuthority({
|
|
|
546
599
|
}));
|
|
547
600
|
return;
|
|
548
601
|
}
|
|
549
|
-
contentPutsInFlight += 1;
|
|
550
|
-
maxContentPutsInFlight = Math.max(maxContentPutsInFlight, contentPutsInFlight);
|
|
551
602
|
const decodedCargo = decodeWireBatch(frame);
|
|
552
|
-
|
|
603
|
+
storeContent(socket, frame, () => {
|
|
553
604
|
const packEntries = [];
|
|
554
605
|
let offset = 0;
|
|
555
606
|
for (const artifact of frame.artifacts) {
|
|
@@ -609,12 +660,6 @@ export function createPrivateWireAuthority({
|
|
|
609
660
|
store_ms: 3,
|
|
610
661
|
seal_ms: 4,
|
|
611
662
|
}));
|
|
612
|
-
contentPutsInFlight -= 1;
|
|
613
|
-
};
|
|
614
|
-
const admitted = contentPutGate ? contentPutGate() : Promise.resolve();
|
|
615
|
-
void admitted.then(() => {
|
|
616
|
-
if (contentPutDelayMs > 0) setTimeout(store, contentPutDelayMs);
|
|
617
|
-
else store();
|
|
618
663
|
});
|
|
619
664
|
} else if (frame.type === "private.entity-content.sealed") {
|
|
620
665
|
// Seal evidence under the current contract: a manifest in this
|
|
@@ -694,7 +739,8 @@ export function createPrivateWireAuthority({
|
|
|
694
739
|
}));
|
|
695
740
|
} else if (frame.type === "shared.mutation.submit") {
|
|
696
741
|
const answer = (value) => graphAnswers.push({ mutationId: frame.envelope?.mutationId,
|
|
697
|
-
deviceId: frame.envelope?.deviceId, answer: value,
|
|
742
|
+
deviceId: frame.envelope?.deviceId, answer: value,
|
|
743
|
+
version: resources.get(frame.envelope?.resourceId)?.version ?? null, at: epochNow() });
|
|
698
744
|
if (rejectMutationSubmits) {
|
|
699
745
|
answer("shared_realtime_internal_error");
|
|
700
746
|
socket.send(JSON.stringify({
|
|
@@ -740,12 +786,19 @@ export function createPrivateWireAuthority({
|
|
|
740
786
|
}));
|
|
741
787
|
return;
|
|
742
788
|
}
|
|
789
|
+
const current = resources.get(envelope.resourceId);
|
|
790
|
+
if (!current) {
|
|
791
|
+
answer("shared_resource_not_found");
|
|
792
|
+
throw new AuthorityRefusal("shared_resource_not_found",
|
|
793
|
+
"no private resource exists at that id", 404, false);
|
|
794
|
+
}
|
|
743
795
|
assert.equal(envelope.authorityEpoch, current.authorityEpoch);
|
|
744
796
|
// The production commit refuses a publication whose delivery prefix
|
|
745
797
|
// or graph head moved on, in that order; the gateway maps either
|
|
746
798
|
// refusal to its leading token, 400 and not retryable. The head
|
|
747
799
|
// comparison is the proposed strict CAS.
|
|
748
|
-
const moved = envelope.deliveryWatermark !==
|
|
800
|
+
const moved = envelope.deliveryWatermark !== deliveryPrefix(current.resourceId)
|
|
801
|
+
? "entity_delivery_watermark_changed"
|
|
749
802
|
: envelope.baseVersion !== current.version ? "entity_graph_head_changed" : null;
|
|
750
803
|
if (moved) {
|
|
751
804
|
answer(moved);
|
|
@@ -802,7 +855,7 @@ export function createPrivateWireAuthority({
|
|
|
802
855
|
} else {
|
|
803
856
|
assert.fail(`unsupported fake entity graph operation ${envelope.operationKind}`);
|
|
804
857
|
}
|
|
805
|
-
|
|
858
|
+
const next = {
|
|
806
859
|
...current,
|
|
807
860
|
snapshotB64: snapshotBytes.toString("base64"),
|
|
808
861
|
checksum: sha256(snapshotBytes),
|
|
@@ -810,15 +863,16 @@ export function createPrivateWireAuthority({
|
|
|
810
863
|
version: current.version + 1,
|
|
811
864
|
deliveryWatermark: envelope.deliveryWatermark,
|
|
812
865
|
};
|
|
866
|
+
resources.set(next.resourceId, next);
|
|
813
867
|
const ack = {
|
|
814
868
|
type: "shared.mutation.ack",
|
|
815
869
|
request_id: frame.request_id,
|
|
816
|
-
resource_id:
|
|
870
|
+
resource_id: next.resourceId,
|
|
817
871
|
mutation_id: envelope.mutationId,
|
|
818
|
-
version:
|
|
819
|
-
authority_epoch:
|
|
872
|
+
version: next.version,
|
|
873
|
+
authority_epoch: next.authorityEpoch,
|
|
820
874
|
committed_at: new Date().toISOString(),
|
|
821
|
-
delivery_watermark:
|
|
875
|
+
delivery_watermark: next.deliveryWatermark,
|
|
822
876
|
duplicate: false,
|
|
823
877
|
};
|
|
824
878
|
committedMutationAcks.set(envelope.mutationId, ack);
|
|
@@ -843,8 +897,13 @@ export function createPrivateWireAuthority({
|
|
|
843
897
|
status: retryEntityRecordSubmits ? 503 : 404, retryable: retryEntityRecordSubmits }));
|
|
844
898
|
return;
|
|
845
899
|
}
|
|
900
|
+
// A record on a superseded contract fails this decode and is refused,
|
|
901
|
+
// exactly as the production authority's own decode refuses it.
|
|
846
902
|
const submitted = decodeLocalEntityRecord(frame.record_json);
|
|
847
|
-
|
|
903
|
+
if (!resources.has(submitted.authorityId)) {
|
|
904
|
+
throw new AuthorityRefusal("entity_record_authority_not_found",
|
|
905
|
+
"no entity authority exists at that id", 404, false);
|
|
906
|
+
}
|
|
848
907
|
if (frame.cargo !== undefined) {
|
|
849
908
|
inlineCargoSubmits += 1;
|
|
850
909
|
const cargo = decodeInlineCargo(
|
|
@@ -905,7 +964,8 @@ export function createPrivateWireAuthority({
|
|
|
905
964
|
acceptedAt: Date.now(),
|
|
906
965
|
});
|
|
907
966
|
if (decision.kind === "append") {
|
|
908
|
-
deliverySequence
|
|
967
|
+
const deliverySequence = deliveryPrefix(submitted.authorityId) + 1;
|
|
968
|
+
deliveryPrefixes.set(submitted.authorityId, deliverySequence);
|
|
909
969
|
entityHeads.set(submitted.entityId, decision.record.globalSequence);
|
|
910
970
|
entityDedup.set(key, decision.record);
|
|
911
971
|
entityRecords.push({ delivery_sequence: deliverySequence, record: decision.record });
|
|
@@ -1021,9 +1081,12 @@ export function createPrivateWireAuthority({
|
|
|
1021
1081
|
return {
|
|
1022
1082
|
server,
|
|
1023
1083
|
sockets,
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
get
|
|
1084
|
+
/** The most recently ensured resource: the one a single-contract test
|
|
1085
|
+
* reads. Every resource remains in `resources`. */
|
|
1086
|
+
get current() { return latestResource(); },
|
|
1087
|
+
get resources() { return new Map(resources); },
|
|
1088
|
+
/** Every frame the authority refused, with the answer it sent. */
|
|
1089
|
+
get refusals() { return refusals.map((row) => ({ ...row })); },
|
|
1027
1090
|
/** The live access tables, in the gateway's own wire row shapes. */
|
|
1028
1091
|
get entityGrants() { return [...entityGrants.values()]; },
|
|
1029
1092
|
get accessRequests() { return [...accessRequests.values()]; },
|
|
@@ -1038,6 +1101,7 @@ export function createPrivateWireAuthority({
|
|
|
1038
1101
|
return [...content.values()].reduce((total, value) => total + value.data.length, 0);
|
|
1039
1102
|
},
|
|
1040
1103
|
contentArtifact(contentHash) {
|
|
1104
|
+
const current = latestResource();
|
|
1041
1105
|
if (!current) return null;
|
|
1042
1106
|
const manifest = findContent(content, {
|
|
1043
1107
|
resource_id: current.resourceId,
|
|
@@ -1129,6 +1193,7 @@ export function createPrivateWireAuthority({
|
|
|
1129
1193
|
* and inline Send cargo left behind. Small artifacts are single-chunk
|
|
1130
1194
|
* by construction (one chunk holds anything up to the chunk cap). */
|
|
1131
1195
|
adoptStandaloneArtifact(bytes) {
|
|
1196
|
+
const current = latestResource();
|
|
1132
1197
|
if (!current) throw new Error("no resource is registered yet");
|
|
1133
1198
|
const data = Buffer.from(bytes);
|
|
1134
1199
|
const contentHash = sha256(data);
|
|
@@ -1153,6 +1218,7 @@ export function createPrivateWireAuthority({
|
|
|
1153
1218
|
/** Remove only physical location rows for one sealed artifact. Its
|
|
1154
1219
|
* immutable manifest and blocks remain readable as standalone objects. */
|
|
1155
1220
|
makeArtifactStandalone(contentHash) {
|
|
1221
|
+
const current = latestResource();
|
|
1156
1222
|
if (!current) throw new Error("no resource is registered yet");
|
|
1157
1223
|
const manifest = findContent(content, {
|
|
1158
1224
|
resource_id: current.resourceId,
|
|
@@ -1170,6 +1236,7 @@ export function createPrivateWireAuthority({
|
|
|
1170
1236
|
* This models a legal standalone-to-pack placement convergence while a
|
|
1171
1237
|
* reader still holds refs from the earlier physical plan. */
|
|
1172
1238
|
moveArtifactToPack(contentHash) {
|
|
1239
|
+
const current = latestResource();
|
|
1173
1240
|
if (!current) throw new Error("no resource is registered yet");
|
|
1174
1241
|
const manifest = findContent(content, {
|
|
1175
1242
|
resource_id: current.resourceId,
|
|
@@ -1220,6 +1287,8 @@ export function createPrivateWireAuthority({
|
|
|
1220
1287
|
/** Content and head frames in the exact order they arrived. */
|
|
1221
1288
|
get frameOrder() { return [...frameOrder]; },
|
|
1222
1289
|
get maxContentPutsInFlight() { return maxContentPutsInFlight; },
|
|
1290
|
+
/** Every accepted entity record with its delivery position, in
|
|
1291
|
+
* acceptance order. */
|
|
1223
1292
|
get entityRecords() {
|
|
1224
1293
|
return entityRecords.map((item) => ({
|
|
1225
1294
|
deliverySequence: item.delivery_sequence,
|
|
@@ -1242,6 +1311,18 @@ export function createPrivateWireAuthority({
|
|
|
1242
1311
|
return held.map(({ replay, ...submit }) => submit);
|
|
1243
1312
|
},
|
|
1244
1313
|
get heldGraphCommits() { return heldGraphSubmits.map(({ replay, ...submit }) => submit); },
|
|
1314
|
+
/** Park every entity record submit `select(record)` names until released. */
|
|
1315
|
+
holdEntityRecords(select) {
|
|
1316
|
+
entityRecordHold = select;
|
|
1317
|
+
},
|
|
1318
|
+
/** Stop holding and replay each parked submit in arrival order. */
|
|
1319
|
+
releaseEntityRecords() {
|
|
1320
|
+
entityRecordHold = null;
|
|
1321
|
+
const held = heldEntityRecordSubmits.splice(0);
|
|
1322
|
+
for (const submit of held) submit.replay();
|
|
1323
|
+
return held.map(({ replay, ...submit }) => submit);
|
|
1324
|
+
},
|
|
1325
|
+
get heldEntityRecords() { return heldEntityRecordSubmits.map(({ replay, ...submit }) => submit); },
|
|
1245
1326
|
/** Commit graph heads but never send their acknowledgements while on. */
|
|
1246
1327
|
withholdGraphAcks(withhold) {
|
|
1247
1328
|
withholdGraphAcks = withhold;
|
|
@@ -1252,6 +1333,7 @@ export function createPrivateWireAuthority({
|
|
|
1252
1333
|
* after assembling them — the honest replacement for reading records out
|
|
1253
1334
|
* of an operation that no longer carries any. */
|
|
1254
1335
|
get graphRecords() {
|
|
1336
|
+
const current = latestResource();
|
|
1255
1337
|
return current ? [...current.rootRecords.values()].flat() : [];
|
|
1256
1338
|
},
|
|
1257
1339
|
};
|
|
@@ -1268,7 +1350,7 @@ function ready(requestId, current, duplicate) {
|
|
|
1268
1350
|
snapshot_checksum: current.checksum,
|
|
1269
1351
|
delivery_watermark: current.deliveryWatermark,
|
|
1270
1352
|
snapshot_b64: current.snapshotB64,
|
|
1271
|
-
contract:
|
|
1353
|
+
contract: current.contract,
|
|
1272
1354
|
schema_version: 1,
|
|
1273
1355
|
duplicate,
|
|
1274
1356
|
};
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amalgm/shell",
|
|
3
|
-
"version": "0.1.164-preview.
|
|
3
|
+
"version": "0.1.164-preview.36824980905",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@amalgm/shell",
|
|
9
|
-
"version": "0.1.164-preview.
|
|
9
|
+
"version": "0.1.164-preview.36824980905",
|
|
10
10
|
"license": "UNLICENSED",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@amalgm/agents": "0.2.3-preview.35795493380",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@amalgm/core": "0.5.1-preview.35541371724",
|
|
19
19
|
"@amalgm/live": "0.2.81-preview.36771680084",
|
|
20
20
|
"@amalgm/tools": "0.1.7-preview.35541586993",
|
|
21
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
21
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.285",
|
|
22
22
|
"@homebridge/node-pty-prebuilt-multiarch": "0.13.1",
|
|
23
23
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
24
24
|
"@napi-rs/keyring": "1.3.0",
|
|
@@ -248,21 +248,22 @@
|
|
|
248
248
|
}
|
|
249
249
|
},
|
|
250
250
|
"node_modules/@anthropic-ai/claude-agent-sdk": {
|
|
251
|
-
"version": "0.3.
|
|
252
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.
|
|
253
|
-
"integrity": "sha512-
|
|
251
|
+
"version": "0.3.285",
|
|
252
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.285.tgz",
|
|
253
|
+
"integrity": "sha512-e98yZH3cWjQ2nSXGxOcx5BrEqG9Y0+CoSoVIN1BaypxT7yGVShdhhH8ROYcJZWqjgiTFyTaN56JQSPJAjarOSg==",
|
|
254
|
+
"license": "SEE LICENSE IN README.md",
|
|
254
255
|
"engines": {
|
|
255
256
|
"node": ">=18.0.0"
|
|
256
257
|
},
|
|
257
258
|
"optionalDependencies": {
|
|
258
|
-
"@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.
|
|
259
|
-
"@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.
|
|
260
|
-
"@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.
|
|
261
|
-
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.
|
|
262
|
-
"@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.
|
|
263
|
-
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.
|
|
264
|
-
"@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.
|
|
265
|
-
"@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.
|
|
259
|
+
"@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.285",
|
|
260
|
+
"@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.285",
|
|
261
|
+
"@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.285",
|
|
262
|
+
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.285",
|
|
263
|
+
"@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.285",
|
|
264
|
+
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.285",
|
|
265
|
+
"@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.285",
|
|
266
|
+
"@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.285"
|
|
266
267
|
},
|
|
267
268
|
"peerDependencies": {
|
|
268
269
|
"@anthropic-ai/sdk": ">=0.93.0",
|
|
@@ -271,96 +272,116 @@
|
|
|
271
272
|
}
|
|
272
273
|
},
|
|
273
274
|
"node_modules/@anthropic-ai/claude-agent-sdk-darwin-arm64": {
|
|
274
|
-
"version": "0.3.
|
|
275
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.
|
|
276
|
-
"integrity": "sha512-
|
|
275
|
+
"version": "0.3.285",
|
|
276
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.285.tgz",
|
|
277
|
+
"integrity": "sha512-2h6iCTH5uPYKA9jBXB7Of0dXZ5hUdu88VnXq9u50AFfMnusy+w83dKgpu+TD+mWiO+mbvMdi1ZsGaoI8HPFTXQ==",
|
|
277
278
|
"cpu": [
|
|
278
279
|
"arm64"
|
|
279
280
|
],
|
|
281
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
280
282
|
"optional": true,
|
|
281
283
|
"os": [
|
|
282
284
|
"darwin"
|
|
283
285
|
]
|
|
284
286
|
},
|
|
285
287
|
"node_modules/@anthropic-ai/claude-agent-sdk-darwin-x64": {
|
|
286
|
-
"version": "0.3.
|
|
287
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.
|
|
288
|
-
"integrity": "sha512-
|
|
288
|
+
"version": "0.3.285",
|
|
289
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.285.tgz",
|
|
290
|
+
"integrity": "sha512-r9ulSFGRV+I5ztFvUBGoLCDGM4cJNQcZ/5+WWFCVaVj55FYB8wVcFA1tXvKwXfWYgYgnuglDRgPwQktsNAisPQ==",
|
|
289
291
|
"cpu": [
|
|
290
292
|
"x64"
|
|
291
293
|
],
|
|
294
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
292
295
|
"optional": true,
|
|
293
296
|
"os": [
|
|
294
297
|
"darwin"
|
|
295
298
|
]
|
|
296
299
|
},
|
|
297
300
|
"node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64": {
|
|
298
|
-
"version": "0.3.
|
|
299
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.
|
|
300
|
-
"integrity": "sha512-
|
|
301
|
+
"version": "0.3.285",
|
|
302
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.285.tgz",
|
|
303
|
+
"integrity": "sha512-YbYXqKGtyqpyqY92U8TRcKdrsnO38Ys6oO8aSBqugQyILcv9JEau8/Gtsw1e9cbkGyuNiUP2e2HIiwK3wMa9mg==",
|
|
301
304
|
"cpu": [
|
|
302
305
|
"arm64"
|
|
303
306
|
],
|
|
307
|
+
"libc": [
|
|
308
|
+
"glibc"
|
|
309
|
+
],
|
|
310
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
304
311
|
"optional": true,
|
|
305
312
|
"os": [
|
|
306
313
|
"linux"
|
|
307
314
|
]
|
|
308
315
|
},
|
|
309
316
|
"node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl": {
|
|
310
|
-
"version": "0.3.
|
|
311
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.
|
|
312
|
-
"integrity": "sha512-
|
|
317
|
+
"version": "0.3.285",
|
|
318
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64-musl/-/claude-agent-sdk-linux-arm64-musl-0.3.285.tgz",
|
|
319
|
+
"integrity": "sha512-EgsXJQJpspdSEJSwNl3tWILqJSmVoYje1c2gleHQrQAybNlvk9wx0EXoKrn55NjfoXW+qV1pWL9SeYa1QEuGuQ==",
|
|
313
320
|
"cpu": [
|
|
314
321
|
"arm64"
|
|
315
322
|
],
|
|
323
|
+
"libc": [
|
|
324
|
+
"musl"
|
|
325
|
+
],
|
|
326
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
316
327
|
"optional": true,
|
|
317
328
|
"os": [
|
|
318
329
|
"linux"
|
|
319
330
|
]
|
|
320
331
|
},
|
|
321
332
|
"node_modules/@anthropic-ai/claude-agent-sdk-linux-x64": {
|
|
322
|
-
"version": "0.3.
|
|
323
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.
|
|
324
|
-
"integrity": "sha512-
|
|
333
|
+
"version": "0.3.285",
|
|
334
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.285.tgz",
|
|
335
|
+
"integrity": "sha512-yVxQ3Xsmme5M9iXnpVQKaBxhGXktl2m2f19fEig30BblvhhRTjF/H1PY4SCA7g9V1D8Ety+0SKMhGZTca4WcWQ==",
|
|
325
336
|
"cpu": [
|
|
326
337
|
"x64"
|
|
327
338
|
],
|
|
339
|
+
"libc": [
|
|
340
|
+
"glibc"
|
|
341
|
+
],
|
|
342
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
328
343
|
"optional": true,
|
|
329
344
|
"os": [
|
|
330
345
|
"linux"
|
|
331
346
|
]
|
|
332
347
|
},
|
|
333
348
|
"node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl": {
|
|
334
|
-
"version": "0.3.
|
|
335
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.
|
|
336
|
-
"integrity": "sha512-
|
|
349
|
+
"version": "0.3.285",
|
|
350
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64-musl/-/claude-agent-sdk-linux-x64-musl-0.3.285.tgz",
|
|
351
|
+
"integrity": "sha512-3i2Pt5of+uqwWzrKzg5Duk3DQSKVkRqm4j9Nfy002XlV20/+z5fviHDjb/3urbI6dE9VYPVVb9L/dKm7uVOcrg==",
|
|
337
352
|
"cpu": [
|
|
338
353
|
"x64"
|
|
339
354
|
],
|
|
355
|
+
"libc": [
|
|
356
|
+
"musl"
|
|
357
|
+
],
|
|
358
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
340
359
|
"optional": true,
|
|
341
360
|
"os": [
|
|
342
361
|
"linux"
|
|
343
362
|
]
|
|
344
363
|
},
|
|
345
364
|
"node_modules/@anthropic-ai/claude-agent-sdk-win32-arm64": {
|
|
346
|
-
"version": "0.3.
|
|
347
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.
|
|
348
|
-
"integrity": "sha512-
|
|
365
|
+
"version": "0.3.285",
|
|
366
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-arm64/-/claude-agent-sdk-win32-arm64-0.3.285.tgz",
|
|
367
|
+
"integrity": "sha512-7vJftvSY9KIt1GCrRipwDAzHzoMGkVuUPuErXkHCf2mjMNZt2YTnAbvMWxx2lV6wyfSzLMgxSJjKsikKYgL91A==",
|
|
349
368
|
"cpu": [
|
|
350
369
|
"arm64"
|
|
351
370
|
],
|
|
371
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
352
372
|
"optional": true,
|
|
353
373
|
"os": [
|
|
354
374
|
"win32"
|
|
355
375
|
]
|
|
356
376
|
},
|
|
357
377
|
"node_modules/@anthropic-ai/claude-agent-sdk-win32-x64": {
|
|
358
|
-
"version": "0.3.
|
|
359
|
-
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.
|
|
360
|
-
"integrity": "sha512-
|
|
378
|
+
"version": "0.3.285",
|
|
379
|
+
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-win32-x64/-/claude-agent-sdk-win32-x64-0.3.285.tgz",
|
|
380
|
+
"integrity": "sha512-mzHxNJsKDJDKNbGkPZU7FFqqWqQAXbTyuDRyGeeVLCCxy89mfyvIOC4ko2yiPXsIFsK+F2rbVnFOBhsl2dtaow==",
|
|
361
381
|
"cpu": [
|
|
362
382
|
"x64"
|
|
363
383
|
],
|
|
384
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
364
385
|
"optional": true,
|
|
365
386
|
"os": [
|
|
366
387
|
"win32"
|