@mneme-ai/core 1.91.0 → 1.93.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/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/nucleus_daemon.d.ts.map +1 -1
- package/dist/nucleus_daemon.js +36 -3
- package/dist/nucleus_daemon.js.map +1 -1
- package/dist/rainbow/boomerang.d.ts +79 -0
- package/dist/rainbow/boomerang.d.ts.map +1 -0
- package/dist/rainbow/boomerang.js +130 -0
- package/dist/rainbow/boomerang.js.map +1 -0
- package/dist/rainbow/index.d.ts +3 -0
- package/dist/rainbow/index.d.ts.map +1 -1
- package/dist/rainbow/index.js +3 -0
- package/dist/rainbow/index.js.map +1 -1
- package/dist/rainbow/page_renderer.d.ts.map +1 -1
- package/dist/rainbow/page_renderer.js +8 -0
- package/dist/rainbow/page_renderer.js.map +1 -1
- package/dist/rainbow/phoenix.d.ts +72 -0
- package/dist/rainbow/phoenix.d.ts.map +1 -0
- package/dist/rainbow/phoenix.js +159 -0
- package/dist/rainbow/phoenix.js.map +1 -0
- package/dist/rainbow/same_shell.d.ts +34 -0
- package/dist/rainbow/same_shell.d.ts.map +1 -0
- package/dist/rainbow/same_shell.js +167 -0
- package/dist/rainbow/same_shell.js.map +1 -0
- package/dist/rainbow/v1_92.test.d.ts +2 -0
- package/dist/rainbow/v1_92.test.d.ts.map +1 -0
- package/dist/rainbow/v1_92.test.js +295 -0
- package/dist/rainbow/v1_92.test.js.map +1 -0
- package/dist/system_compat/index.d.ts +119 -0
- package/dist/system_compat/index.d.ts.map +1 -0
- package/dist/system_compat/index.js +283 -0
- package/dist/system_compat/index.js.map +1 -0
- package/dist/system_compat/system_compat.test.d.ts +2 -0
- package/dist/system_compat/system_compat.test.d.ts.map +1 -0
- package/dist/system_compat/system_compat.test.js +208 -0
- package/dist/system_compat/system_compat.test.js.map +1 -0
- package/dist/token_nova/index.d.ts +181 -0
- package/dist/token_nova/index.d.ts.map +1 -0
- package/dist/token_nova/index.js +352 -0
- package/dist/token_nova/index.js.map +1 -0
- package/dist/token_nova/token_nova.test.d.ts +2 -0
- package/dist/token_nova/token_nova.test.d.ts.map +1 -0
- package/dist/token_nova/token_nova.test.js +223 -0
- package/dist/token_nova/token_nova.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mkdtempSync, readFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { renderSameShellPage } from "./same_shell.js";
|
|
6
|
+
import { createPhoenix, renderPhoenixSubscriberScript, formatUrlChangeSseFrame, } from "./phoenix.js";
|
|
7
|
+
import { openBoomerangInbox, handleReturnPost, formatPulseLine, } from "./boomerang.js";
|
|
8
|
+
function freshInboxPath() {
|
|
9
|
+
const dir = mkdtempSync(join(tmpdir(), "mneme-boomerang-"));
|
|
10
|
+
return join(dir, "homunculus-return.jsonl");
|
|
11
|
+
}
|
|
12
|
+
const VALID_RETURN = `
|
|
13
|
+
some preamble text from the Web AI
|
|
14
|
+
|
|
15
|
+
# HOMUNCULUS RETURN
|
|
16
|
+
originator: claude-opus-4-7
|
|
17
|
+
returning_from: gemini-2.5-pro
|
|
18
|
+
decisions: |
|
|
19
|
+
- Use Postgres for v1
|
|
20
|
+
- Skip Redis for now
|
|
21
|
+
reasoning: |
|
|
22
|
+
- Postgres native JSONB handles the schema-less case
|
|
23
|
+
next_actions: |
|
|
24
|
+
- bench typeorm vs prisma
|
|
25
|
+
- settle on one ORM by Friday
|
|
26
|
+
`.trim();
|
|
27
|
+
// ============================== SAME-SHELL ==================================
|
|
28
|
+
describe("v1.92 RAINBOW · SAME-SHELL same-machine page", () => {
|
|
29
|
+
it("emits a complete HTML document", () => {
|
|
30
|
+
const html = renderSameShellPage({ soulText: "# SOUL\nbody", port: 7741 });
|
|
31
|
+
expect(html.startsWith("<!doctype html>")).toBe(true);
|
|
32
|
+
expect(html).toContain("</html>");
|
|
33
|
+
expect(html).toContain("Clone to another AI on this PC");
|
|
34
|
+
});
|
|
35
|
+
it("auto-copies soul to clipboard on load (no user click required)", () => {
|
|
36
|
+
const html = renderSameShellPage({ soulText: "x", port: 7741 });
|
|
37
|
+
// copySoul(false) called from top-level script -> auto-copy on load
|
|
38
|
+
expect(html).toContain("copySoul(false)");
|
|
39
|
+
expect(html).toContain("navigator.clipboard");
|
|
40
|
+
});
|
|
41
|
+
it("includes the full TH+EN capability matrix (paste-only truth)", () => {
|
|
42
|
+
const html = renderSameShellPage({ soulText: "x", port: 7741 });
|
|
43
|
+
// EN side
|
|
44
|
+
expect(html).toContain("On a train, only have your phone");
|
|
45
|
+
expect(html).toContain("Switch models for a second opinion");
|
|
46
|
+
expect(html).toContain("Backup the whole conversation");
|
|
47
|
+
expect(html).toContain("Call Mneme tools");
|
|
48
|
+
expect(html).toContain("Modify your code");
|
|
49
|
+
// TH side
|
|
50
|
+
expect(html).toContain("อยู่บนรถไฟ มีแค่มือถือ");
|
|
51
|
+
expect(html).toContain("Backup บทสนทนา");
|
|
52
|
+
expect(html).toContain("เรียก Mneme tools");
|
|
53
|
+
expect(html).toContain("แก้ code ของคุณ");
|
|
54
|
+
});
|
|
55
|
+
it("includes 4 AI deep-links that also re-copy clipboard on click", () => {
|
|
56
|
+
const html = renderSameShellPage({ soulText: "x", port: 7741 });
|
|
57
|
+
expect(html).toContain("chatgpt.com");
|
|
58
|
+
expect(html).toContain("gemini.google.com");
|
|
59
|
+
expect(html).toContain("claude.ai");
|
|
60
|
+
expect(html).toContain("perplexity.ai");
|
|
61
|
+
// Click handlers re-copy to defend against tab-switch clipboard wipe
|
|
62
|
+
expect(html).toContain('document.getElementById("lk-cg").addEventListener("click"');
|
|
63
|
+
});
|
|
64
|
+
it("XSS-safe: </script> in soul is escaped", () => {
|
|
65
|
+
const html = renderSameShellPage({ soulText: 'evil </script><img onerror=1>', port: 7741 });
|
|
66
|
+
expect(html).toContain("<\\/script>");
|
|
67
|
+
const start = html.indexOf("const SOUL = ");
|
|
68
|
+
const end = html.indexOf(";", start);
|
|
69
|
+
expect(html.slice(start, end)).not.toContain("</script>");
|
|
70
|
+
});
|
|
71
|
+
it("includes BOOMERANG return-pad when returnEndpoint is provided", () => {
|
|
72
|
+
const html = renderSameShellPage({ soulText: "x", port: 7741, returnEndpoint: "http://localhost:7741/return" });
|
|
73
|
+
expect(html).toContain("🪃 BOOMERANG");
|
|
74
|
+
expect(html).toContain("textarea");
|
|
75
|
+
expect(html).toContain('id="rp"');
|
|
76
|
+
expect(html).toContain('id="rb"');
|
|
77
|
+
expect(html).toContain("/return");
|
|
78
|
+
// Submit handler does POST with body
|
|
79
|
+
expect(html).toContain('method: "POST"');
|
|
80
|
+
});
|
|
81
|
+
it("omits BOOMERANG return-pad when returnEndpoint absent", () => {
|
|
82
|
+
const html = renderSameShellPage({ soulText: "x", port: 7741 });
|
|
83
|
+
expect(html).not.toContain("🪃 BOOMERANG");
|
|
84
|
+
expect(html).not.toContain('id="rp"');
|
|
85
|
+
});
|
|
86
|
+
it("footer states 'no QR / no tunnel / no network' truth", () => {
|
|
87
|
+
const html = renderSameShellPage({ soulText: "x", port: 7741 });
|
|
88
|
+
expect(html).toContain("no QR, no tunnel, no network needed");
|
|
89
|
+
expect(html).toContain("ไม่ต้องใช้ QR / tunnel / network");
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
// ============================== PHOENIX =====================================
|
|
93
|
+
describe("v1.92 RAINBOW · PHOENIX tunnel watchdog", () => {
|
|
94
|
+
function probeFnSeq(seq) {
|
|
95
|
+
let i = 0;
|
|
96
|
+
return async (url) => {
|
|
97
|
+
const r = seq[Math.min(i, seq.length - 1)];
|
|
98
|
+
i++;
|
|
99
|
+
return { url, ok: r.ok, status: r.status, elapsedMs: 0, reason: r.reason };
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
it("getUrl returns initial URL", () => {
|
|
103
|
+
const h = createPhoenix({
|
|
104
|
+
initialUrl: "https://a.trycloudflare.com",
|
|
105
|
+
probeIntervalMs: 9_999_999,
|
|
106
|
+
probeFn: probeFnSeq([{ ok: true, status: 200 }]),
|
|
107
|
+
respawnFn: async () => null,
|
|
108
|
+
});
|
|
109
|
+
expect(h.getUrl()).toBe("https://a.trycloudflare.com");
|
|
110
|
+
h.stop();
|
|
111
|
+
});
|
|
112
|
+
it("respawns + fires onUrlChange after N consecutive failures", async () => {
|
|
113
|
+
let respawnCount = 0;
|
|
114
|
+
const events = [];
|
|
115
|
+
const h = createPhoenix({
|
|
116
|
+
initialUrl: "https://dead.trycloudflare.com",
|
|
117
|
+
probeIntervalMs: 5,
|
|
118
|
+
failuresBeforeRespawn: 2,
|
|
119
|
+
probeFn: probeFnSeq([
|
|
120
|
+
{ ok: false, status: 404, reason: "tunnel edge returned 404" },
|
|
121
|
+
{ ok: false, status: 404, reason: "tunnel edge returned 404" },
|
|
122
|
+
{ ok: true, status: 200 },
|
|
123
|
+
{ ok: true, status: 200 },
|
|
124
|
+
]),
|
|
125
|
+
respawnFn: async () => {
|
|
126
|
+
respawnCount++;
|
|
127
|
+
return "https://alive.trycloudflare.com";
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
h.onUrlChange((n, o) => events.push([o, n]));
|
|
131
|
+
// Wait for two probe failures + respawn.
|
|
132
|
+
await new Promise((res) => setTimeout(res, 200));
|
|
133
|
+
h.stop();
|
|
134
|
+
expect(respawnCount).toBeGreaterThanOrEqual(1);
|
|
135
|
+
expect(h.getUrl()).toBe("https://alive.trycloudflare.com");
|
|
136
|
+
expect(events.length).toBeGreaterThanOrEqual(1);
|
|
137
|
+
expect(events[0][0]).toBe("https://dead.trycloudflare.com");
|
|
138
|
+
expect(events[0][1]).toBe("https://alive.trycloudflare.com");
|
|
139
|
+
});
|
|
140
|
+
it("does not respawn on single transient failure", async () => {
|
|
141
|
+
let respawnCount = 0;
|
|
142
|
+
const h = createPhoenix({
|
|
143
|
+
initialUrl: "https://x.trycloudflare.com",
|
|
144
|
+
probeIntervalMs: 5,
|
|
145
|
+
failuresBeforeRespawn: 3,
|
|
146
|
+
probeFn: probeFnSeq([
|
|
147
|
+
{ ok: false, status: 404 },
|
|
148
|
+
{ ok: true, status: 200 },
|
|
149
|
+
{ ok: true, status: 200 },
|
|
150
|
+
{ ok: true, status: 200 },
|
|
151
|
+
]),
|
|
152
|
+
respawnFn: async () => { respawnCount++; return "x"; },
|
|
153
|
+
});
|
|
154
|
+
await new Promise((res) => setTimeout(res, 80));
|
|
155
|
+
h.stop();
|
|
156
|
+
expect(respawnCount).toBe(0);
|
|
157
|
+
});
|
|
158
|
+
it("history records every probe + respawn", async () => {
|
|
159
|
+
const h = createPhoenix({
|
|
160
|
+
initialUrl: "https://q.trycloudflare.com",
|
|
161
|
+
probeIntervalMs: 5,
|
|
162
|
+
failuresBeforeRespawn: 1,
|
|
163
|
+
probeFn: probeFnSeq([
|
|
164
|
+
{ ok: false, status: 404, reason: "edge 404" },
|
|
165
|
+
{ ok: true, status: 200 },
|
|
166
|
+
]),
|
|
167
|
+
respawnFn: async () => "https://r.trycloudflare.com",
|
|
168
|
+
});
|
|
169
|
+
await new Promise((res) => setTimeout(res, 80));
|
|
170
|
+
h.stop();
|
|
171
|
+
const hist = h.getHistory();
|
|
172
|
+
expect(hist.length).toBeGreaterThanOrEqual(2);
|
|
173
|
+
expect(hist.some((e) => e.kind === "probe")).toBe(true);
|
|
174
|
+
expect(hist.some((e) => e.kind === "respawn")).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
it("renderPhoenixSubscriberScript emits an EventSource subscription IIFE", () => {
|
|
177
|
+
const s = renderPhoenixSubscriberScript({ eventsUrl: "/events", qrImgId: "qr", urlTextId: "url" });
|
|
178
|
+
expect(s).toContain("EventSource");
|
|
179
|
+
expect(s).toContain('"/events"');
|
|
180
|
+
expect(s).toContain('"qr"');
|
|
181
|
+
expect(s).toContain('"url"');
|
|
182
|
+
expect(s).toContain("url-change");
|
|
183
|
+
expect(s).toContain("api.qrserver.com");
|
|
184
|
+
});
|
|
185
|
+
it("formatUrlChangeSseFrame returns valid SSE wire format", () => {
|
|
186
|
+
const f = formatUrlChangeSseFrame("https://new.trycloudflare.com");
|
|
187
|
+
expect(f).toBe("event: url-change\ndata: https://new.trycloudflare.com\n\n");
|
|
188
|
+
});
|
|
189
|
+
it("formatUrlChangeSseFrame strips newlines from input (defensive)", () => {
|
|
190
|
+
const f = formatUrlChangeSseFrame("https://x.com\ninjected\nstuff");
|
|
191
|
+
expect(f).not.toContain("\ninjected");
|
|
192
|
+
expect(f).toContain("https://x.cominjectedstuff");
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
// ============================== BOOMERANG ===================================
|
|
196
|
+
describe("v1.92 RAINBOW · BOOMERANG return-pad inbox", () => {
|
|
197
|
+
it("ingests a valid HOMUNCULUS RETURN block + writes one JSONL line", () => {
|
|
198
|
+
const path = freshInboxPath();
|
|
199
|
+
const inbox = openBoomerangInbox(path);
|
|
200
|
+
const r = inbox.ingest({ raw: VALID_RETURN, source: "same-shell" });
|
|
201
|
+
expect(r.ok).toBe(true);
|
|
202
|
+
expect(r.id).toMatch(/^[0-9a-f]{12}$/);
|
|
203
|
+
expect(r.parsed?.decisions.length).toBe(2);
|
|
204
|
+
expect(r.parsed?.nextActions.length).toBe(2);
|
|
205
|
+
const lines = readFileSync(path, "utf8").trim().split("\n");
|
|
206
|
+
expect(lines.length).toBe(1);
|
|
207
|
+
const entry = JSON.parse(lines[0]);
|
|
208
|
+
expect(entry.id).toBe(r.id);
|
|
209
|
+
expect(entry.source).toBe("same-shell");
|
|
210
|
+
expect(entry.ingested).toBe(false);
|
|
211
|
+
expect(entry.parsed.originator).toBe("claude-opus-4-7");
|
|
212
|
+
});
|
|
213
|
+
it("rejects body without HOMUNCULUS RETURN block", () => {
|
|
214
|
+
const inbox = openBoomerangInbox(freshInboxPath());
|
|
215
|
+
const r = inbox.ingest({ raw: "just a normal AI reply, no return block here" });
|
|
216
|
+
expect(r.ok).toBe(false);
|
|
217
|
+
expect(r.error).toContain("HOMUNCULUS RETURN block");
|
|
218
|
+
});
|
|
219
|
+
it("rejects empty body", () => {
|
|
220
|
+
const inbox = openBoomerangInbox(freshInboxPath());
|
|
221
|
+
const r = inbox.ingest({ raw: "" });
|
|
222
|
+
expect(r.ok).toBe(false);
|
|
223
|
+
expect(r.error).toContain("empty");
|
|
224
|
+
});
|
|
225
|
+
it("rejects body over 256KB", () => {
|
|
226
|
+
const inbox = openBoomerangInbox(freshInboxPath());
|
|
227
|
+
const huge = "x".repeat(300 * 1024);
|
|
228
|
+
const r = inbox.ingest({ raw: huge });
|
|
229
|
+
expect(r.ok).toBe(false);
|
|
230
|
+
expect(r.error).toContain("too large");
|
|
231
|
+
});
|
|
232
|
+
it("dedup: same body twice -> same id, single line in file", () => {
|
|
233
|
+
const path = freshInboxPath();
|
|
234
|
+
const inbox = openBoomerangInbox(path);
|
|
235
|
+
const r1 = inbox.ingest({ raw: VALID_RETURN, source: "same-shell" });
|
|
236
|
+
const r2 = inbox.ingest({ raw: VALID_RETURN, source: "tunnel" });
|
|
237
|
+
expect(r1.id).toBe(r2.id);
|
|
238
|
+
const lines = readFileSync(path, "utf8").trim().split("\n");
|
|
239
|
+
expect(lines.length).toBe(1);
|
|
240
|
+
});
|
|
241
|
+
it("pending() returns un-ingested entries; markIngested moves them", () => {
|
|
242
|
+
const path = freshInboxPath();
|
|
243
|
+
const inbox = openBoomerangInbox(path);
|
|
244
|
+
const a = inbox.ingest({ raw: VALID_RETURN }).id;
|
|
245
|
+
expect(inbox.pending().length).toBe(1);
|
|
246
|
+
const moved = inbox.markIngested([a], "applied via mneme.abyss.homunculus.ingest");
|
|
247
|
+
expect(moved).toBe(1);
|
|
248
|
+
expect(inbox.pending().length).toBe(0);
|
|
249
|
+
const all = inbox.list();
|
|
250
|
+
expect(all[0].ingested).toBe(true);
|
|
251
|
+
expect(all[0].ingestNote).toContain("applied");
|
|
252
|
+
// Second mark is idempotent.
|
|
253
|
+
expect(inbox.markIngested([a])).toBe(0);
|
|
254
|
+
});
|
|
255
|
+
it("handleReturnPost returns 200 + {ok,id} on valid body", () => {
|
|
256
|
+
const inbox = openBoomerangInbox(freshInboxPath());
|
|
257
|
+
const r = handleReturnPost({ inbox, body: VALID_RETURN, source: "same-shell" });
|
|
258
|
+
expect(r.status).toBe(200);
|
|
259
|
+
expect(r.body.ok).toBe(true);
|
|
260
|
+
expect(r.body.id).toMatch(/^[0-9a-f]{12}$/);
|
|
261
|
+
});
|
|
262
|
+
it("handleReturnPost returns 400 + {ok:false,error} on garbage", () => {
|
|
263
|
+
const inbox = openBoomerangInbox(freshInboxPath());
|
|
264
|
+
const r = handleReturnPost({ inbox, body: "not a return block", source: "same-shell" });
|
|
265
|
+
expect(r.status).toBe(400);
|
|
266
|
+
expect(r.body.ok).toBe(false);
|
|
267
|
+
expect(r.body.error).toBeTruthy();
|
|
268
|
+
});
|
|
269
|
+
it("formatPulseLine produces compact one-line summary", () => {
|
|
270
|
+
const inbox = openBoomerangInbox(freshInboxPath());
|
|
271
|
+
const r = inbox.ingest({ raw: VALID_RETURN });
|
|
272
|
+
const entry = inbox.list()[0];
|
|
273
|
+
const line = formatPulseLine(entry);
|
|
274
|
+
expect(line).toContain("[BOOMERANG");
|
|
275
|
+
expect(line).toContain(r.id);
|
|
276
|
+
expect(line).toContain("gemini-2.5-pro");
|
|
277
|
+
expect(line).toContain("d:2"); // 2 decisions
|
|
278
|
+
expect(line).toContain("n:2"); // 2 next_actions
|
|
279
|
+
});
|
|
280
|
+
it("survives corrupt JSONL lines (forward-compat)", () => {
|
|
281
|
+
const path = freshInboxPath();
|
|
282
|
+
const inbox = openBoomerangInbox(path);
|
|
283
|
+
inbox.ingest({ raw: VALID_RETURN });
|
|
284
|
+
// Append a malformed line that future versions might write.
|
|
285
|
+
readFileSync(path, "utf8");
|
|
286
|
+
appendCorruptLine(path);
|
|
287
|
+
expect(() => inbox.list()).not.toThrow();
|
|
288
|
+
expect(inbox.list().length).toBe(1);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
function appendCorruptLine(path) {
|
|
292
|
+
const fs = require("node:fs");
|
|
293
|
+
fs.appendFileSync(path, "{not json}\n", "utf8");
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=v1_92.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v1_92.test.js","sourceRoot":"","sources":["../../src/rainbow/v1_92.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1.93.0 -- SYSTEM-COMPAT bot: probe the upgrade environment BEFORE
|
|
3
|
+
* the daemon runs `mneme upgrade --force` so silent failures are
|
|
4
|
+
* impossible.
|
|
5
|
+
*
|
|
6
|
+
* The user's instruction (verbatim):
|
|
7
|
+
* "ต้องมี bot เชคว่าใช้ได้ทุก environment ไหมนะ ทั้ง linux, windows,
|
|
8
|
+
* mac os และแต่ละ os มันก็มีเวอร์ชั่น ต้องเชคด้วย และต้องใช้ได้แบบ
|
|
9
|
+
* smooth super wisdom และไม่มีปัญหากับ node, brew ต้องเข้าใจกันหมด"
|
|
10
|
+
*
|
|
11
|
+
* What this module decides:
|
|
12
|
+
* 1. Is Node new enough? (>= 22)
|
|
13
|
+
* 2. Is the global install path writable WITHOUT sudo?
|
|
14
|
+
* 3. Which package managers are available? (npm / yarn / pnpm / brew / docker)
|
|
15
|
+
* 4. Which upgrade strategy will succeed on THIS machine? (global-npm /
|
|
16
|
+
* user-npm / brew / docker / manual)
|
|
17
|
+
* 5. Final verdict: SAFE (proceed) / DEFER (wait, ask user) / BLOCK
|
|
18
|
+
* (refuse, would damage the system).
|
|
19
|
+
*
|
|
20
|
+
* The daemon calls probeUpgradeEnvironment() before spawning the upgrade.
|
|
21
|
+
* On BLOCK → push a clear inbox message + skip the spawn. On DEFER →
|
|
22
|
+
* push a "needs-attention" inbox + skip. On SAFE → proceed.
|
|
23
|
+
*
|
|
24
|
+
* Pure functions only — every probe returns synchronously. No network,
|
|
25
|
+
* no LLM, no surprises.
|
|
26
|
+
*/
|
|
27
|
+
export interface NodeInfo {
|
|
28
|
+
version: string;
|
|
29
|
+
major: number;
|
|
30
|
+
ok: boolean;
|
|
31
|
+
minRequired: string;
|
|
32
|
+
}
|
|
33
|
+
export interface PkgManagerInfo {
|
|
34
|
+
available: boolean;
|
|
35
|
+
version: string | null;
|
|
36
|
+
path: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface OsInfo {
|
|
39
|
+
platform: NodeJS.Platform;
|
|
40
|
+
release: string;
|
|
41
|
+
arch: string;
|
|
42
|
+
/** Human label e.g. "Windows 11", "macOS 14", "Linux ubuntu-22.04". */
|
|
43
|
+
label: string;
|
|
44
|
+
}
|
|
45
|
+
export interface GlobalInstallInfo {
|
|
46
|
+
/** Resolved npm prefix (e.g. /usr/local on POSIX, %APPDATA%\npm on Windows). */
|
|
47
|
+
prefix: string | null;
|
|
48
|
+
/** Where global bins land. */
|
|
49
|
+
binDir: string | null;
|
|
50
|
+
/** Where global modules land. */
|
|
51
|
+
modulesDir: string | null;
|
|
52
|
+
/** True if writable WITHOUT sudo. */
|
|
53
|
+
writable: boolean;
|
|
54
|
+
/** True if writing would require admin/sudo. */
|
|
55
|
+
needsElevation: boolean;
|
|
56
|
+
/** Why writable=false, when false. */
|
|
57
|
+
notWritableReason: string | null;
|
|
58
|
+
}
|
|
59
|
+
export type UpgradeStrategy = "global-npm" | "user-npm" | "brew" | "docker" | "manual";
|
|
60
|
+
export type Verdict = "SAFE" | "DEFER" | "BLOCK";
|
|
61
|
+
export interface SystemCompatProbe {
|
|
62
|
+
ts: number;
|
|
63
|
+
os: OsInfo;
|
|
64
|
+
node: NodeInfo;
|
|
65
|
+
packageManagers: {
|
|
66
|
+
npm: PkgManagerInfo;
|
|
67
|
+
yarn: PkgManagerInfo;
|
|
68
|
+
pnpm: PkgManagerInfo;
|
|
69
|
+
brew: PkgManagerInfo;
|
|
70
|
+
docker: PkgManagerInfo;
|
|
71
|
+
};
|
|
72
|
+
globalInstall: GlobalInstallInfo;
|
|
73
|
+
upgradeStrategy: UpgradeStrategy;
|
|
74
|
+
verdict: Verdict;
|
|
75
|
+
reasons: string[];
|
|
76
|
+
/** Human-readable single-line summary for the pulse / inbox. */
|
|
77
|
+
pulseLine: string;
|
|
78
|
+
}
|
|
79
|
+
export declare function probeOs(): OsInfo;
|
|
80
|
+
export declare function probeNode(): NodeInfo;
|
|
81
|
+
export declare function probePackageManagers(): SystemCompatProbe["packageManagers"];
|
|
82
|
+
export declare function probeGlobalInstall(): GlobalInstallInfo;
|
|
83
|
+
export declare function decideStrategy(probe: Pick<SystemCompatProbe, "node" | "packageManagers" | "globalInstall" | "os">): {
|
|
84
|
+
strategy: UpgradeStrategy;
|
|
85
|
+
verdict: Verdict;
|
|
86
|
+
reasons: string[];
|
|
87
|
+
};
|
|
88
|
+
export declare function probeUpgradeEnvironment(): SystemCompatProbe;
|
|
89
|
+
export declare function formatPulseLine(args: {
|
|
90
|
+
os: OsInfo;
|
|
91
|
+
node: NodeInfo;
|
|
92
|
+
verdict: Verdict;
|
|
93
|
+
strategy: UpgradeStrategy;
|
|
94
|
+
}): string;
|
|
95
|
+
/** Produce the actual shell args the daemon should spawn for a given
|
|
96
|
+
* strategy. Returns null if strategy is "manual" (don't auto-execute). */
|
|
97
|
+
export declare function commandFor(strategy: UpgradeStrategy): {
|
|
98
|
+
cmd: string;
|
|
99
|
+
args: string[];
|
|
100
|
+
} | null;
|
|
101
|
+
/** Used by stat-based ancestry probes — kept exported so tests can verify
|
|
102
|
+
* the algorithm works on synthetic paths. */
|
|
103
|
+
export declare function _testNearestAncestor(p: string): string | null;
|
|
104
|
+
/** Used by the daemon's drainQueue when it sees mneme.system.upgrade. */
|
|
105
|
+
export interface DaemonGuard {
|
|
106
|
+
shouldProceed: boolean;
|
|
107
|
+
inboxLine?: string;
|
|
108
|
+
command?: {
|
|
109
|
+
cmd: string;
|
|
110
|
+
args: string[];
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export declare function gateDaemonUpgrade(): DaemonGuard;
|
|
114
|
+
/** Stat helper exported for test introspection only. */
|
|
115
|
+
export declare function _statSafe(p: string): {
|
|
116
|
+
exists: boolean;
|
|
117
|
+
isDir: boolean;
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/system_compat/index.ts"],"names":[],"mappings":"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"}
|