tesseract-agent 0.11.0 → 0.11.1
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/dist-bundle/cli.js
CHANGED
|
@@ -109820,6 +109820,36 @@ async function getPeerIdentityPub(opts) {
|
|
|
109820
109820
|
import { createSocket as createSocket2 } from "node:dgram";
|
|
109821
109821
|
import { createRequire as createRequire4 } from "node:module";
|
|
109822
109822
|
|
|
109823
|
+
// ../../packages/host-core/dist/mesh/bundle-gossip.js
|
|
109824
|
+
var BundleOfferLedger = class {
|
|
109825
|
+
#offered = /* @__PURE__ */ new Set();
|
|
109826
|
+
/**
|
|
109827
|
+
* Should we offer epoch `mine` to this peer, and record that we did?
|
|
109828
|
+
*
|
|
109829
|
+
* Returns false when we are not ahead (including equal — an offer would tell them
|
|
109830
|
+
* nothing), and false for a peer already offered THIS epoch. Keyed by epoch as well as
|
|
109831
|
+
* peer, so a newer bundle is offered afresh to someone we have already talked to.
|
|
109832
|
+
*/
|
|
109833
|
+
claim(peerHex, peerEpoch, mine) {
|
|
109834
|
+
if (!(mine > peerEpoch))
|
|
109835
|
+
return false;
|
|
109836
|
+
const key2 = `${peerHex}:${mine}`;
|
|
109837
|
+
if (this.#offered.has(key2))
|
|
109838
|
+
return false;
|
|
109839
|
+
this.#offered.add(key2);
|
|
109840
|
+
return true;
|
|
109841
|
+
}
|
|
109842
|
+
/**
|
|
109843
|
+
* Forget everything, because we just adopted a newer bundle and are now the node that is
|
|
109844
|
+
* ahead. Without this the ledger would still be keyed to the epoch we no longer hold —
|
|
109845
|
+
* harmless for correctness (the key carries the epoch) but it would grow without bound on
|
|
109846
|
+
* a long-lived node, one entry per peer per epoch forever.
|
|
109847
|
+
*/
|
|
109848
|
+
reset() {
|
|
109849
|
+
this.#offered.clear();
|
|
109850
|
+
}
|
|
109851
|
+
};
|
|
109852
|
+
|
|
109823
109853
|
// ../../packages/host-core/dist/mesh/config.js
|
|
109824
109854
|
init_credentials();
|
|
109825
109855
|
import { chmodSync as chmodSync5, existsSync as existsSync33, mkdirSync as mkdirSync36, readdirSync as readdirSync12, readFileSync as readFileSync47, renameSync as renameSync11, rmSync as rmSync7, writeFileSync as writeFileSync35 } from "node:fs";
|
|
@@ -110289,6 +110319,12 @@ var MeshNode = class {
|
|
|
110289
110319
|
#timer = null;
|
|
110290
110320
|
#unsubscribe = null;
|
|
110291
110321
|
#identity = null;
|
|
110322
|
+
/** The policy bundle we hold, as bytes, so we can OFFER it to a peer that is behind.
|
|
110323
|
+
* Kept beside the engine because the engine exposes an epoch but not the bytes. */
|
|
110324
|
+
#bundle = null;
|
|
110325
|
+
/** Who has already been offered which epoch — see `bundle-gossip.ts` for why a ledger
|
|
110326
|
+
* is needed at all (the relay broadcasts to the whole mesh, not to one peer). */
|
|
110327
|
+
#bundleOffered = new BundleOfferLedger();
|
|
110292
110328
|
#port = null;
|
|
110293
110329
|
#lastError = null;
|
|
110294
110330
|
/**
|
|
@@ -110405,8 +110441,10 @@ var MeshNode = class {
|
|
|
110405
110441
|
}
|
|
110406
110442
|
try {
|
|
110407
110443
|
this.#engine = new meshCore.MeshEngine(Buffer.from(id.genesis), Buffer.from(id.staticPrivate), Buffer.from(id.cert), 0, Buffer.alloc(16));
|
|
110408
|
-
if (id.bundle)
|
|
110444
|
+
if (id.bundle) {
|
|
110409
110445
|
this.#engine.setBundle(Buffer.from(id.bundle), Date.now());
|
|
110446
|
+
this.#bundle = id.bundle;
|
|
110447
|
+
}
|
|
110410
110448
|
} catch (e) {
|
|
110411
110449
|
this.#engine = null;
|
|
110412
110450
|
this.#lastError = e instanceof Error ? e.message : String(e);
|
|
@@ -110653,6 +110691,8 @@ var MeshNode = class {
|
|
|
110653
110691
|
engine.setBundle(bytes2, Date.now());
|
|
110654
110692
|
this.#stopIfRevoked(engine);
|
|
110655
110693
|
cacheBundle(new Uint8Array(bytes2), meshDirNameFromWireId(engine.meshId()) ?? void 0);
|
|
110694
|
+
this.#bundle = new Uint8Array(bytes2);
|
|
110695
|
+
this.#bundleOffered.reset();
|
|
110656
110696
|
break;
|
|
110657
110697
|
}
|
|
110658
110698
|
}
|
|
@@ -110661,6 +110701,48 @@ var MeshNode = class {
|
|
|
110661
110701
|
this.#lastError = e instanceof Error ? e.message : String(e);
|
|
110662
110702
|
}
|
|
110663
110703
|
}
|
|
110704
|
+
/**
|
|
110705
|
+
* Offer our policy bundle to a peer whose epoch is older than ours.
|
|
110706
|
+
*
|
|
110707
|
+
* ## The half of gossip that was never written
|
|
110708
|
+
*
|
|
110709
|
+
* `MeshPeerHint.epoch` is documented in the protocol as "the epoch the node advertises,
|
|
110710
|
+
* SO A LAGGING PEER KNOWS TO PULL", and the relay has always carried it. Nothing read
|
|
110711
|
+
* it, and — the part that made this total — nothing in the product ever SENT a
|
|
110712
|
+
* `mesh:bundle`. The broker forwarded a message with no sender anywhere.
|
|
110713
|
+
*
|
|
110714
|
+
* So a node's roster was frozen at the instant it joined. `joinWithToken` caches the
|
|
110715
|
+
* bundle the server returns, which is why a machine works at all; but every machine that
|
|
110716
|
+
* joins LATER is invisible to it forever, because the only thing that would have told it
|
|
110717
|
+
* is the gossip that never happened. On a four-machine network built in join order, the
|
|
110718
|
+
* first machine knew nobody, the last knew everyone, and every one of them reported
|
|
110719
|
+
* itself healthy. That is what this fixes.
|
|
110720
|
+
*
|
|
110721
|
+
* PUSH, not pull, because push needs no new message type and the protocol already hands
|
|
110722
|
+
* us exactly the fact we need — the peer's epoch. For any pair, whoever is ahead offers,
|
|
110723
|
+
* so the direction takes care of itself and a new joiner (who always has the newest
|
|
110724
|
+
* bundle, straight from the server) feeds it to everyone already there.
|
|
110725
|
+
*
|
|
110726
|
+
* Safe by construction: the bundle is CA-signed, so `setBundle` on the receiving side
|
|
110727
|
+
* verifies it against genesis and refuses anything that does not chain. Offering is
|
|
110728
|
+
* therefore never a policy change — the worst a wrong offer costs a peer is a parse.
|
|
110729
|
+
*/
|
|
110730
|
+
#offerBundleTo(peerHex, peerEpoch) {
|
|
110731
|
+
const engine = this.#engine;
|
|
110732
|
+
const bundle = this.#bundle;
|
|
110733
|
+
if (!engine || !bundle)
|
|
110734
|
+
return;
|
|
110735
|
+
if (!this.#bundleOffered.claim(peerHex, peerEpoch, engine.policyEpoch()))
|
|
110736
|
+
return;
|
|
110737
|
+
try {
|
|
110738
|
+
sendMesh({
|
|
110739
|
+
type: "mesh:bundle",
|
|
110740
|
+
meshId: engine.meshId(),
|
|
110741
|
+
bundle: Buffer.from(bundle).toString("base64")
|
|
110742
|
+
});
|
|
110743
|
+
} catch {
|
|
110744
|
+
}
|
|
110745
|
+
}
|
|
110664
110746
|
#learnPeer(p) {
|
|
110665
110747
|
const engine = this.#engine;
|
|
110666
110748
|
if (!engine)
|
|
@@ -110669,6 +110751,7 @@ var MeshNode = class {
|
|
|
110669
110751
|
if (pk.length !== 32)
|
|
110670
110752
|
return;
|
|
110671
110753
|
const hex6 = pk.toString("hex");
|
|
110754
|
+
this.#offerBundleTo(hex6, p.epoch ?? 0);
|
|
110672
110755
|
if (p.cert) {
|
|
110673
110756
|
try {
|
|
110674
110757
|
const bytes2 = Buffer.from(p.cert, "base64");
|