@mneme-ai/core 2.4.0 → 2.6.0
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/cognitive/curiosity.d.ts.map +1 -1
- package/dist/cognitive/curiosity.js +5 -9
- package/dist/cognitive/curiosity.js.map +1 -1
- package/dist/cognitive/debate.d.ts.map +1 -1
- package/dist/cognitive/debate.js +5 -9
- package/dist/cognitive/debate.js.map +1 -1
- package/dist/diaspora/session_capsule.d.ts.map +1 -1
- package/dist/diaspora/session_capsule.js +4 -8
- package/dist/diaspora/session_capsule.js.map +1 -1
- package/dist/exodus/genome.d.ts.map +1 -1
- package/dist/exodus/genome.js +5 -7
- package/dist/exodus/genome.js.map +1 -1
- package/dist/hyperscan/cross_source_qa.d.ts.map +1 -1
- package/dist/hyperscan/cross_source_qa.js +5 -7
- package/dist/hyperscan/cross_source_qa.js.map +1 -1
- package/dist/hyperscan/nucleus_dust_htc.d.ts.map +1 -1
- package/dist/hyperscan/nucleus_dust_htc.js +10 -12
- package/dist/hyperscan/nucleus_dust_htc.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/precog/sha_version_verifier.d.ts.map +1 -1
- package/dist/precog/sha_version_verifier.js +16 -25
- package/dist/precog/sha_version_verifier.js.map +1 -1
- package/dist/precog/temporal_verifier.d.ts.map +1 -1
- package/dist/precog/temporal_verifier.js +8 -15
- package/dist/precog/temporal_verifier.js.map +1 -1
- package/dist/squadron/acgv_neutrino.d.ts.map +1 -1
- package/dist/squadron/acgv_neutrino.js +18 -24
- package/dist/squadron/acgv_neutrino.js.map +1 -1
- package/dist/squadron/fact_grounding.d.ts.map +1 -1
- package/dist/squadron/fact_grounding.js +4 -8
- package/dist/squadron/fact_grounding.js.map +1 -1
- package/dist/truth_kernel/index.d.ts +92 -0
- package/dist/truth_kernel/index.d.ts.map +1 -0
- package/dist/truth_kernel/index.js +203 -0
- package/dist/truth_kernel/index.js.map +1 -0
- package/dist/truth_kernel/truth_kernel.test.d.ts +2 -0
- package/dist/truth_kernel/truth_kernel.test.d.ts.map +1 -0
- package/dist/truth_kernel/truth_kernel.test.js +126 -0
- package/dist/truth_kernel/truth_kernel.test.js.map +1 -0
- package/dist/wormhole/index.d.ts +112 -0
- package/dist/wormhole/index.d.ts.map +1 -0
- package/dist/wormhole/index.js +151 -0
- package/dist/wormhole/index.js.map +1 -0
- package/dist/wormhole/wormhole.test.d.ts +2 -0
- package/dist/wormhole/wormhole.test.d.ts.map +1 -0
- package/dist/wormhole/wormhole.test.js +154 -0
- package/dist/wormhole/wormhole.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.6.0 -- WORMHOLE: channel auto-negotiation for cross-device sync.
|
|
3
|
+
*
|
|
4
|
+
* "One call · every channel races · fastest live channel wins."
|
|
5
|
+
*
|
|
6
|
+
* The pattern Mneme accumulated by v2.5: more than ten folders all
|
|
7
|
+
* answering the same family of question — "how do I move this brain
|
|
8
|
+
* to another device / vendor?":
|
|
9
|
+
* ANCHOR — parent-pole / child-rope identity
|
|
10
|
+
* AURA — same-WiFi owner-only pairing
|
|
11
|
+
* RELAY — anonymous public paste services
|
|
12
|
+
* CHAMELEON — environment-adaptive transport selection
|
|
13
|
+
* RAINBOW — multi-channel handoff orchestrator
|
|
14
|
+
* SYNAPSE — short-code + QR
|
|
15
|
+
* CONDUIT — phantom-exec cross-vendor loop
|
|
16
|
+
* PERMEATE — userscript + bookmarklet route-around
|
|
17
|
+
* DIASPORA — gitignore + spore + HTTP bridge
|
|
18
|
+
* ABYSS — capsule TTL + replay
|
|
19
|
+
* SEAMLESS — voice directive
|
|
20
|
+
*
|
|
21
|
+
* The receiving AI never had a UNIFIED entry. WORMHOLE is that entry.
|
|
22
|
+
*
|
|
23
|
+
* Design — modeled on ICE/STUN/TURN connectivity establishment:
|
|
24
|
+
* 1. Caller asks: "send this payload to peer X with quality Q".
|
|
25
|
+
* 2. WORMHOLE enumerates registered CHANNELS (each wraps one of the
|
|
26
|
+
* existing transport modules).
|
|
27
|
+
* 3. Channels marked `probe: () => boolean` are pinged in parallel
|
|
28
|
+
* with a hard timeout. Live ones survive.
|
|
29
|
+
* 4. Among live channels, WORMHOLE sorts by ADAPTIVE SCORE (recent
|
|
30
|
+
* success rate × inverse latency × user preference).
|
|
31
|
+
* 5. The first channel to successfully `send()` wins; the rest are
|
|
32
|
+
* cancelled. WORMHOLE records the outcome (success/latency) for
|
|
33
|
+
* the next negotiation's score.
|
|
34
|
+
*
|
|
35
|
+
* Wild move: the score is not static. Channels that worked yesterday
|
|
36
|
+
* but flake today see their weight decay fast (~30-trial half-life).
|
|
37
|
+
* A WiFi pairing channel scores high on a home network, low on a
|
|
38
|
+
* coffee-shop captive portal — without anyone configuring anything.
|
|
39
|
+
*
|
|
40
|
+
* Transports stay independently usable (no breaking change). WORMHOLE
|
|
41
|
+
* is a NEW SURFACE that composes them.
|
|
42
|
+
*/
|
|
43
|
+
const EWMA_ALPHA = 1 / 30; // ~30-trial half-life
|
|
44
|
+
/** Update channel stats with one new trial. Returns the new stats
|
|
45
|
+
* object — callers persist this (e.g. into .mneme/wormhole-stats.json). */
|
|
46
|
+
export function ingestTrial(prev, trial) {
|
|
47
|
+
const trials = (prev?.trials ?? 0) + 1;
|
|
48
|
+
const succeeded = (prev?.succeeded ?? 0) + (trial.outcome === "succeeded" ? 1 : 0);
|
|
49
|
+
const wasSuccess = trial.outcome === "succeeded" ? 1 : 0;
|
|
50
|
+
const ewmaSuccess = prev ? prev.ewmaSuccess * (1 - EWMA_ALPHA) + wasSuccess * EWMA_ALPHA : wasSuccess;
|
|
51
|
+
const ewmaLatencyMs = prev ? prev.ewmaLatencyMs * (1 - EWMA_ALPHA) + trial.ms * EWMA_ALPHA : trial.ms;
|
|
52
|
+
return { channel: trial.channel, trials, succeeded, ewmaSuccess, ewmaLatencyMs };
|
|
53
|
+
}
|
|
54
|
+
/** Adaptive score: weight a channel by its EWMA success rate, inverse
|
|
55
|
+
* latency, and caller preference. Channels never tried before get a
|
|
56
|
+
* neutral 0.5 success rate so they actually get a chance to compete. */
|
|
57
|
+
function adaptiveScore(c, stats) {
|
|
58
|
+
const success = stats ? stats.ewmaSuccess : 0.5;
|
|
59
|
+
const latencyPenalty = stats ? 1 / (1 + stats.ewmaLatencyMs / 1000) : 1; // 1s → 0.5
|
|
60
|
+
const pref = c.preference ?? 1;
|
|
61
|
+
return success * latencyPenalty * pref;
|
|
62
|
+
}
|
|
63
|
+
async function runWithTimeout(p, ms) {
|
|
64
|
+
let timer;
|
|
65
|
+
const timeoutP = new Promise((resolve) => {
|
|
66
|
+
timer = setTimeout(() => resolve("timeout"), ms);
|
|
67
|
+
});
|
|
68
|
+
try {
|
|
69
|
+
return await Promise.race([Promise.resolve(p), timeoutP]);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (timer)
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Run the negotiation. Returns the winning channel's receipt or null. */
|
|
77
|
+
export async function sendViaWormhole(input) {
|
|
78
|
+
const t0 = Date.now();
|
|
79
|
+
const trials = [];
|
|
80
|
+
if (input.channels.length === 0) {
|
|
81
|
+
return { winner: null, receipt: null, trials, totalMs: 0, scoresAtNegotiation: {} };
|
|
82
|
+
}
|
|
83
|
+
// Phase 1: probe in parallel.
|
|
84
|
+
const probeTimeout = input.probeTimeoutMs ?? 1500;
|
|
85
|
+
const probes = await Promise.all(input.channels.map(async (c) => {
|
|
86
|
+
const probeStart = Date.now();
|
|
87
|
+
const res = await runWithTimeout(Promise.resolve(c.probe(input.ctx)), probeTimeout);
|
|
88
|
+
const ms = Date.now() - probeStart;
|
|
89
|
+
if (res === "timeout") {
|
|
90
|
+
trials.push({ channel: c.id, outcome: "unavailable", ms, reason: "probe timeout", ts: Date.now() });
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
if (res === "unavailable") {
|
|
94
|
+
trials.push({ channel: c.id, outcome: "unavailable", ms, ts: Date.now() });
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
if (res === "needs-pairing") {
|
|
98
|
+
trials.push({ channel: c.id, outcome: "needs-pairing", ms, ts: Date.now() });
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return c;
|
|
102
|
+
}));
|
|
103
|
+
const live = probes.filter((x) => x !== null);
|
|
104
|
+
const scoresAtNegotiation = {};
|
|
105
|
+
for (const c of input.channels)
|
|
106
|
+
scoresAtNegotiation[c.id] = adaptiveScore(c, input.stats?.[c.id]);
|
|
107
|
+
if (live.length === 0) {
|
|
108
|
+
return { winner: null, receipt: null, trials, totalMs: Date.now() - t0, scoresAtNegotiation };
|
|
109
|
+
}
|
|
110
|
+
// Phase 2: rank by adaptive score, slice to concurrency, race.
|
|
111
|
+
const sorted = live.slice().sort((a, b) => adaptiveScore(b, input.stats?.[b.id]) - adaptiveScore(a, input.stats?.[a.id]));
|
|
112
|
+
const racers = sorted.slice(0, Math.max(1, input.concurrency ?? 3));
|
|
113
|
+
const sendTimeout = input.sendTimeoutMs ?? 15000;
|
|
114
|
+
let winner = null;
|
|
115
|
+
const racePromises = racers.map(async (c) => {
|
|
116
|
+
const sendStart = Date.now();
|
|
117
|
+
const res = await runWithTimeout(c.send(input.payload, input.ctx), sendTimeout);
|
|
118
|
+
const ms = Date.now() - sendStart;
|
|
119
|
+
if (res === "timeout") {
|
|
120
|
+
trials.push({ channel: c.id, outcome: "failed", ms, reason: "send timeout", ts: Date.now() });
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
if (!res.ok) {
|
|
124
|
+
trials.push({ channel: c.id, outcome: "failed", ms, reason: res.reason, ts: Date.now() });
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
trials.push({ channel: c.id, outcome: "succeeded", ms, ts: Date.now() });
|
|
128
|
+
return { channel: c.id, receipt: res.receipt };
|
|
129
|
+
});
|
|
130
|
+
// First-to-succeed wins. We still wait for all so the trials list is
|
|
131
|
+
// complete (the AI may want to surface why losers lost).
|
|
132
|
+
const results = await Promise.all(racePromises);
|
|
133
|
+
for (const r of results) {
|
|
134
|
+
if (r && !winner)
|
|
135
|
+
winner = r;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
winner: winner?.channel ?? null,
|
|
139
|
+
receipt: winner?.receipt ?? null,
|
|
140
|
+
trials,
|
|
141
|
+
totalMs: Date.now() - t0,
|
|
142
|
+
scoresAtNegotiation,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Compact one-line pulse summary. */
|
|
146
|
+
export function formatWormholePulseLine(n) {
|
|
147
|
+
if (!n.winner)
|
|
148
|
+
return `WORMHOLE · NO-CHANNEL · tried=${n.trials.length} · ${n.totalMs}ms`;
|
|
149
|
+
return `WORMHOLE · OK · winner=${n.winner} · tried=${n.trials.length} · ${n.totalMs}ms`;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wormhole/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wormhole.test.d.ts","sourceRoot":"","sources":["../../src/wormhole/wormhole.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { sendViaWormhole, ingestTrial, formatWormholePulseLine } from "./index.js";
|
|
3
|
+
function fakeChannel(id, opts = { probe: "available" }) {
|
|
4
|
+
return {
|
|
5
|
+
id,
|
|
6
|
+
preference: opts.preference,
|
|
7
|
+
probe: () => opts.probe,
|
|
8
|
+
send: async () => {
|
|
9
|
+
if (opts.sendDelay)
|
|
10
|
+
await new Promise((r) => setTimeout(r, opts.sendDelay));
|
|
11
|
+
if (opts.sendOk === false)
|
|
12
|
+
return { ok: false, reason: opts.reason ?? "fake-fail" };
|
|
13
|
+
return { ok: true, receipt: `delivered-via-${id}` };
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
describe("v2.6 WORMHOLE · negotiation", () => {
|
|
18
|
+
it("single available channel wins immediately", async () => {
|
|
19
|
+
const r = await sendViaWormhole({
|
|
20
|
+
payload: "hello",
|
|
21
|
+
channels: [fakeChannel("lan", { probe: "available" })],
|
|
22
|
+
});
|
|
23
|
+
expect(r.winner).toBe("lan");
|
|
24
|
+
expect(r.receipt).toBe("delivered-via-lan");
|
|
25
|
+
});
|
|
26
|
+
it("unavailable channels are filtered before send", async () => {
|
|
27
|
+
const r = await sendViaWormhole({
|
|
28
|
+
payload: "hello",
|
|
29
|
+
channels: [
|
|
30
|
+
fakeChannel("lan", { probe: "unavailable" }),
|
|
31
|
+
fakeChannel("paste", { probe: "available" }),
|
|
32
|
+
],
|
|
33
|
+
});
|
|
34
|
+
expect(r.winner).toBe("paste");
|
|
35
|
+
const lanTrial = r.trials.find((t) => t.channel === "lan");
|
|
36
|
+
expect(lanTrial?.outcome).toBe("unavailable");
|
|
37
|
+
});
|
|
38
|
+
it("needs-pairing channels are excluded", async () => {
|
|
39
|
+
const r = await sendViaWormhole({
|
|
40
|
+
payload: "hello",
|
|
41
|
+
channels: [
|
|
42
|
+
fakeChannel("aura", { probe: "needs-pairing" }),
|
|
43
|
+
fakeChannel("paste", { probe: "available" }),
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
expect(r.winner).toBe("paste");
|
|
47
|
+
const auraTrial = r.trials.find((t) => t.channel === "aura");
|
|
48
|
+
expect(auraTrial?.outcome).toBe("needs-pairing");
|
|
49
|
+
});
|
|
50
|
+
it("no live channels → NO-CHANNEL winner null", async () => {
|
|
51
|
+
const r = await sendViaWormhole({
|
|
52
|
+
payload: "hello",
|
|
53
|
+
channels: [fakeChannel("a", { probe: "unavailable" }), fakeChannel("b", { probe: "unavailable" })],
|
|
54
|
+
});
|
|
55
|
+
expect(r.winner).toBeNull();
|
|
56
|
+
expect(r.receipt).toBeNull();
|
|
57
|
+
});
|
|
58
|
+
it("send failure on one channel allows another to win", async () => {
|
|
59
|
+
const r = await sendViaWormhole({
|
|
60
|
+
payload: "hello",
|
|
61
|
+
channels: [
|
|
62
|
+
fakeChannel("flaky", { probe: "available", sendOk: false, reason: "503" }),
|
|
63
|
+
fakeChannel("solid", { probe: "available" }),
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
expect(r.winner).toBe("solid");
|
|
67
|
+
const flakyTrial = r.trials.find((t) => t.channel === "flaky");
|
|
68
|
+
expect(flakyTrial?.outcome).toBe("failed");
|
|
69
|
+
expect(flakyTrial?.reason).toBe("503");
|
|
70
|
+
});
|
|
71
|
+
it("send timeout marks channel as failed", async () => {
|
|
72
|
+
const r = await sendViaWormhole({
|
|
73
|
+
payload: "hello",
|
|
74
|
+
channels: [
|
|
75
|
+
fakeChannel("slow", { probe: "available", sendDelay: 200 }),
|
|
76
|
+
fakeChannel("fast", { probe: "available" }),
|
|
77
|
+
],
|
|
78
|
+
sendTimeoutMs: 50,
|
|
79
|
+
concurrency: 2,
|
|
80
|
+
});
|
|
81
|
+
expect(r.winner).toBe("fast");
|
|
82
|
+
const slowTrial = r.trials.find((t) => t.channel === "slow");
|
|
83
|
+
expect(slowTrial?.reason).toContain("timeout");
|
|
84
|
+
});
|
|
85
|
+
it("higher preference channel runs first when scores tied", async () => {
|
|
86
|
+
const r = await sendViaWormhole({
|
|
87
|
+
payload: "hello",
|
|
88
|
+
channels: [
|
|
89
|
+
fakeChannel("low", { probe: "available", preference: 0.1 }),
|
|
90
|
+
fakeChannel("high", { probe: "available", preference: 10 }),
|
|
91
|
+
],
|
|
92
|
+
concurrency: 1,
|
|
93
|
+
});
|
|
94
|
+
expect(r.winner).toBe("high");
|
|
95
|
+
});
|
|
96
|
+
it("empty channel list → NO-CHANNEL", async () => {
|
|
97
|
+
const r = await sendViaWormhole({ payload: "x", channels: [] });
|
|
98
|
+
expect(r.winner).toBeNull();
|
|
99
|
+
expect(r.trials.length).toBe(0);
|
|
100
|
+
});
|
|
101
|
+
it("scoresAtNegotiation reports per-channel scores", async () => {
|
|
102
|
+
const r = await sendViaWormhole({
|
|
103
|
+
payload: "x",
|
|
104
|
+
channels: [fakeChannel("a"), fakeChannel("b")],
|
|
105
|
+
});
|
|
106
|
+
expect(r.scoresAtNegotiation["a"]).toBeGreaterThan(0);
|
|
107
|
+
expect(r.scoresAtNegotiation["b"]).toBeGreaterThan(0);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe("v2.6 WORMHOLE · EWMA stats", () => {
|
|
111
|
+
it("first success → ewmaSuccess = 1", () => {
|
|
112
|
+
const s = ingestTrial(undefined, { channel: "a", outcome: "succeeded", ms: 100, ts: 0 });
|
|
113
|
+
expect(s.ewmaSuccess).toBe(1);
|
|
114
|
+
expect(s.succeeded).toBe(1);
|
|
115
|
+
expect(s.trials).toBe(1);
|
|
116
|
+
});
|
|
117
|
+
it("first failure → ewmaSuccess = 0", () => {
|
|
118
|
+
const s = ingestTrial(undefined, { channel: "a", outcome: "failed", ms: 100, ts: 0 });
|
|
119
|
+
expect(s.ewmaSuccess).toBe(0);
|
|
120
|
+
expect(s.succeeded).toBe(0);
|
|
121
|
+
expect(s.trials).toBe(1);
|
|
122
|
+
});
|
|
123
|
+
it("repeated successes converge ewmaSuccess to 1", () => {
|
|
124
|
+
let s = ingestTrial(undefined, { channel: "a", outcome: "failed", ms: 100, ts: 0 });
|
|
125
|
+
for (let i = 0; i < 60; i++) {
|
|
126
|
+
s = ingestTrial(s, { channel: "a", outcome: "succeeded", ms: 100, ts: i });
|
|
127
|
+
}
|
|
128
|
+
expect(s.ewmaSuccess).toBeGreaterThan(0.85);
|
|
129
|
+
expect(s.trials).toBe(61);
|
|
130
|
+
expect(s.succeeded).toBe(60);
|
|
131
|
+
});
|
|
132
|
+
it("recent failures pull ewmaSuccess down even after long success streak", () => {
|
|
133
|
+
let s = ingestTrial(undefined, { channel: "a", outcome: "succeeded", ms: 100, ts: 0 });
|
|
134
|
+
for (let i = 0; i < 30; i++)
|
|
135
|
+
s = ingestTrial(s, { channel: "a", outcome: "succeeded", ms: 100, ts: i });
|
|
136
|
+
const before = s.ewmaSuccess;
|
|
137
|
+
for (let i = 0; i < 30; i++)
|
|
138
|
+
s = ingestTrial(s, { channel: "a", outcome: "failed", ms: 100, ts: i });
|
|
139
|
+
expect(s.ewmaSuccess).toBeLessThan(before);
|
|
140
|
+
expect(s.ewmaSuccess).toBeLessThan(0.5);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe("v2.6 WORMHOLE · pulse", () => {
|
|
144
|
+
it("formatWormholePulseLine OK case", async () => {
|
|
145
|
+
const r = await sendViaWormhole({ payload: "x", channels: [fakeChannel("a")] });
|
|
146
|
+
expect(formatWormholePulseLine(r)).toContain("OK");
|
|
147
|
+
expect(formatWormholePulseLine(r)).toContain("winner=a");
|
|
148
|
+
});
|
|
149
|
+
it("formatWormholePulseLine NO-CHANNEL case", async () => {
|
|
150
|
+
const r = await sendViaWormhole({ payload: "x", channels: [fakeChannel("a", { probe: "unavailable" })] });
|
|
151
|
+
expect(formatWormholePulseLine(r)).toContain("NO-CHANNEL");
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=wormhole.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wormhole.test.js","sourceRoot":"","sources":["../../src/wormhole/wormhole.test.ts"],"names":[],"mappings":"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"}
|