@mneme-ai/core 2.19.11 → 2.19.13
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/brain_branches/brain_branches.test.d.ts +2 -0
- package/dist/brain_branches/brain_branches.test.d.ts.map +1 -0
- package/dist/brain_branches/brain_branches.test.js +152 -0
- package/dist/brain_branches/brain_branches.test.js.map +1 -0
- package/dist/brain_branches/index.d.ts +134 -0
- package/dist/brain_branches/index.d.ts.map +1 -0
- package/dist/brain_branches/index.js +227 -0
- package/dist/brain_branches/index.js.map +1 -0
- package/dist/cosmic/aurelian_v1912.test.d.ts +2 -0
- package/dist/cosmic/aurelian_v1912.test.d.ts.map +1 -0
- package/dist/cosmic/aurelian_v1912.test.js +72 -0
- package/dist/cosmic/aurelian_v1912.test.js.map +1 -0
- package/dist/cosmic/aurelian_v1913.test.d.ts +2 -0
- package/dist/cosmic/aurelian_v1913.test.d.ts.map +1 -0
- package/dist/cosmic/aurelian_v1913.test.js +46 -0
- package/dist/cosmic/aurelian_v1913.test.js.map +1 -0
- package/dist/dialect/dialect.test.d.ts +2 -0
- package/dist/dialect/dialect.test.d.ts.map +1 -0
- package/dist/dialect/dialect.test.js +121 -0
- package/dist/dialect/dialect.test.js.map +1 -0
- package/dist/dialect/index.d.ts +91 -0
- package/dist/dialect/index.d.ts.map +1 -0
- package/dist/dialect/index.js +149 -0
- package/dist/dialect/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/model_chrysalis/index.d.ts +96 -0
- package/dist/model_chrysalis/index.d.ts.map +1 -0
- package/dist/model_chrysalis/index.js +279 -0
- package/dist/model_chrysalis/index.js.map +1 -0
- package/dist/model_chrysalis/model_chrysalis.test.d.ts +2 -0
- package/dist/model_chrysalis/model_chrysalis.test.d.ts.map +1 -0
- package/dist/model_chrysalis/model_chrysalis.test.js +173 -0
- package/dist/model_chrysalis/model_chrysalis.test.js.map +1 -0
- package/dist/muscle_memory/index.d.ts +112 -0
- package/dist/muscle_memory/index.d.ts.map +1 -0
- package/dist/muscle_memory/index.js +203 -0
- package/dist/muscle_memory/index.js.map +1 -0
- package/dist/muscle_memory/muscle_memory.test.d.ts +2 -0
- package/dist/muscle_memory/muscle_memory.test.d.ts.map +1 -0
- package/dist/muscle_memory/muscle_memory.test.js +111 -0
- package/dist/muscle_memory/muscle_memory.test.js.map +1 -0
- package/dist/negative_evidence/index.d.ts +162 -0
- package/dist/negative_evidence/index.d.ts.map +1 -0
- package/dist/negative_evidence/index.js +244 -0
- package/dist/negative_evidence/index.js.map +1 -0
- package/dist/negative_evidence/negative_evidence.test.d.ts +2 -0
- package/dist/negative_evidence/negative_evidence.test.d.ts.map +1 -0
- package/dist/negative_evidence/negative_evidence.test.js +188 -0
- package/dist/negative_evidence/negative_evidence.test.js.map +1 -0
- package/dist/neuromorphic_embedder/index.d.ts +139 -0
- package/dist/neuromorphic_embedder/index.d.ts.map +1 -0
- package/dist/neuromorphic_embedder/index.js +306 -0
- package/dist/neuromorphic_embedder/index.js.map +1 -0
- package/dist/neuromorphic_embedder/neuromorphic_embedder.test.d.ts +2 -0
- package/dist/neuromorphic_embedder/neuromorphic_embedder.test.d.ts.map +1 -0
- package/dist/neuromorphic_embedder/neuromorphic_embedder.test.js +194 -0
- package/dist/neuromorphic_embedder/neuromorphic_embedder.test.js.map +1 -0
- package/dist/whats_new.d.ts.map +1 -1
- package/dist/whats_new.js +16 -0
- package/dist/whats_new.js.map +1 -1
- package/dist/wrapper_genesis/index.d.ts.map +1 -1
- package/dist/wrapper_genesis/index.js +34 -0
- package/dist/wrapper_genesis/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { BUILTIN_FINGERPRINTS, defaultChrysalis, formatFingerprintLine, } from "./index.js";
|
|
3
|
+
const CANONICAL = {
|
|
4
|
+
model: "test-model",
|
|
5
|
+
messages: [
|
|
6
|
+
{ role: "system", content: "You are honest." },
|
|
7
|
+
{ role: "user", content: "What is 2+2?" },
|
|
8
|
+
],
|
|
9
|
+
maxTokens: 256,
|
|
10
|
+
temperature: 0.2,
|
|
11
|
+
};
|
|
12
|
+
describe("v2.19.12 MODEL CHRYSALIS · registry + built-ins", () => {
|
|
13
|
+
it("ships 5 known fingerprints", () => {
|
|
14
|
+
const r = defaultChrysalis();
|
|
15
|
+
const providers = r.list().map((f) => f.provider).sort();
|
|
16
|
+
expect(providers).toEqual([
|
|
17
|
+
"anthropic-messages",
|
|
18
|
+
"gemini-generate-content",
|
|
19
|
+
"lm-studio-openai-compat",
|
|
20
|
+
"ollama-chat",
|
|
21
|
+
"openai-chat-completions",
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
it("allows runtime registration of a new fingerprint without rebuilding", () => {
|
|
25
|
+
const r = defaultChrysalis();
|
|
26
|
+
const before = r.list().length;
|
|
27
|
+
const fp = {
|
|
28
|
+
v: 1,
|
|
29
|
+
provider: "future-vendor-2027",
|
|
30
|
+
baseUrl: "https://future-ai.example.com",
|
|
31
|
+
urlHints: ["future-ai.example.com"],
|
|
32
|
+
endpoint: "/v2/chat",
|
|
33
|
+
shapeRequest: (req) => ({ prompt: req.messages.map((m) => m.content).join("\n") }),
|
|
34
|
+
shapeResponse: (raw) => ({ content: raw.text ?? "", model: "future" }),
|
|
35
|
+
};
|
|
36
|
+
r.register(fp);
|
|
37
|
+
expect(r.list().length).toBe(before + 1);
|
|
38
|
+
expect(r.get("future-vendor-2027")).toBeDefined();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe("v2.19.12 MODEL CHRYSALIS · probe", () => {
|
|
42
|
+
it("matches anthropic URLs to the anthropic fingerprint", () => {
|
|
43
|
+
const r = defaultChrysalis();
|
|
44
|
+
const p = r.probe({ baseUrl: "https://api.anthropic.com/v1" });
|
|
45
|
+
expect(p.matched?.provider).toBe("anthropic-messages");
|
|
46
|
+
});
|
|
47
|
+
it("matches local ollama URL", () => {
|
|
48
|
+
const r = defaultChrysalis();
|
|
49
|
+
const p = r.probe({ baseUrl: "http://127.0.0.1:11434" });
|
|
50
|
+
expect(p.matched?.provider).toBe("ollama-chat");
|
|
51
|
+
});
|
|
52
|
+
it("returns null + helpful hint for an unknown URL", () => {
|
|
53
|
+
const r = defaultChrysalis();
|
|
54
|
+
const p = r.probe({ baseUrl: "https://aliens.example.com/v9/chat" });
|
|
55
|
+
expect(p.matched).toBeNull();
|
|
56
|
+
expect(p.reason).toContain("registerFingerprint");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe("v2.19.12 MODEL CHRYSALIS · translateRequest", () => {
|
|
60
|
+
it("anthropic: extracts system to top-level + only user/assistant in messages + max_tokens", () => {
|
|
61
|
+
const r = defaultChrysalis();
|
|
62
|
+
const body = r.translateRequest({ provider: "anthropic-messages", request: CANONICAL });
|
|
63
|
+
expect(body["system"]).toBe("You are honest.");
|
|
64
|
+
expect(body["messages"].every((m) => m.role !== "system")).toBe(true);
|
|
65
|
+
expect(body["max_tokens"]).toBe(256);
|
|
66
|
+
expect(body["temperature"]).toBe(0.2);
|
|
67
|
+
});
|
|
68
|
+
it("openai: keeps system in messages array + uses snake_case max_tokens", () => {
|
|
69
|
+
const r = defaultChrysalis();
|
|
70
|
+
const body = r.translateRequest({ provider: "openai-chat-completions", request: CANONICAL });
|
|
71
|
+
const msgs = body["messages"];
|
|
72
|
+
expect(msgs.some((m) => m.role === "system")).toBe(true);
|
|
73
|
+
expect(body["max_tokens"]).toBe(256);
|
|
74
|
+
});
|
|
75
|
+
it("gemini: maps assistant→model + uses systemInstruction + generationConfig.maxOutputTokens", () => {
|
|
76
|
+
const r = defaultChrysalis();
|
|
77
|
+
const reqWithAsst = {
|
|
78
|
+
...CANONICAL,
|
|
79
|
+
messages: [...CANONICAL.messages, { role: "assistant", content: "OK" }],
|
|
80
|
+
};
|
|
81
|
+
const body = r.translateRequest({ provider: "gemini-generate-content", request: reqWithAsst });
|
|
82
|
+
const contents = body["contents"];
|
|
83
|
+
expect(contents.some((c) => c.role === "model")).toBe(true);
|
|
84
|
+
const sysInst = body["systemInstruction"];
|
|
85
|
+
expect(sysInst?.parts?.[0]?.text).toBe("You are honest.");
|
|
86
|
+
const genConfig = body["generationConfig"];
|
|
87
|
+
expect(genConfig.maxOutputTokens).toBe(256);
|
|
88
|
+
});
|
|
89
|
+
it("ollama: wraps temperature/maxTokens into options.num_predict + stream=false", () => {
|
|
90
|
+
const r = defaultChrysalis();
|
|
91
|
+
const body = r.translateRequest({ provider: "ollama-chat", request: CANONICAL });
|
|
92
|
+
expect(body["stream"]).toBe(false);
|
|
93
|
+
const opts = body["options"];
|
|
94
|
+
expect(opts.temperature).toBe(0.2);
|
|
95
|
+
expect(opts.num_predict).toBe(256);
|
|
96
|
+
});
|
|
97
|
+
it("lm-studio: openai-compatible shape (same fields as openai)", () => {
|
|
98
|
+
const r = defaultChrysalis();
|
|
99
|
+
const body = r.translateRequest({ provider: "lm-studio-openai-compat", request: CANONICAL });
|
|
100
|
+
expect(body["max_tokens"]).toBe(256);
|
|
101
|
+
expect(body["temperature"]).toBe(0.2);
|
|
102
|
+
});
|
|
103
|
+
it("throws on unknown provider", () => {
|
|
104
|
+
const r = defaultChrysalis();
|
|
105
|
+
expect(() => r.translateRequest({ provider: "ghost", request: CANONICAL })).toThrow();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe("v2.19.12 MODEL CHRYSALIS · translateResponse", () => {
|
|
109
|
+
it("anthropic response: extracts text from content blocks + usage tokens", () => {
|
|
110
|
+
const r = defaultChrysalis();
|
|
111
|
+
const raw = {
|
|
112
|
+
content: [{ type: "text", text: "Four." }, { type: "text", text: " That's it." }],
|
|
113
|
+
model: "claude-test",
|
|
114
|
+
stop_reason: "end_turn",
|
|
115
|
+
usage: { input_tokens: 12, output_tokens: 3 },
|
|
116
|
+
};
|
|
117
|
+
const out = r.translateResponse({ provider: "anthropic-messages", raw });
|
|
118
|
+
expect(out.content).toBe("Four. That's it.");
|
|
119
|
+
expect(out.model).toBe("claude-test");
|
|
120
|
+
expect(out.finishReason).toBe("end_turn");
|
|
121
|
+
expect(out.usage?.inputTokens).toBe(12);
|
|
122
|
+
expect(out.usage?.outputTokens).toBe(3);
|
|
123
|
+
});
|
|
124
|
+
it("openai response: extracts choices[0].message.content + maps prompt/completion tokens", () => {
|
|
125
|
+
const r = defaultChrysalis();
|
|
126
|
+
const raw = {
|
|
127
|
+
choices: [{ message: { content: "Four." }, finish_reason: "stop" }],
|
|
128
|
+
model: "gpt-test",
|
|
129
|
+
usage: { prompt_tokens: 10, completion_tokens: 2 },
|
|
130
|
+
};
|
|
131
|
+
const out = r.translateResponse({ provider: "openai-chat-completions", raw });
|
|
132
|
+
expect(out.content).toBe("Four.");
|
|
133
|
+
expect(out.usage?.inputTokens).toBe(10);
|
|
134
|
+
expect(out.usage?.outputTokens).toBe(2);
|
|
135
|
+
});
|
|
136
|
+
it("gemini response: concatenates candidate parts + reads usageMetadata", () => {
|
|
137
|
+
const r = defaultChrysalis();
|
|
138
|
+
const raw = {
|
|
139
|
+
candidates: [{ content: { parts: [{ text: "Four." }, { text: " Done." }] }, finishReason: "STOP" }],
|
|
140
|
+
modelVersion: "gemini-test",
|
|
141
|
+
usageMetadata: { promptTokenCount: 9, candidatesTokenCount: 2 },
|
|
142
|
+
};
|
|
143
|
+
const out = r.translateResponse({ provider: "gemini-generate-content", raw });
|
|
144
|
+
expect(out.content).toBe("Four. Done.");
|
|
145
|
+
expect(out.finishReason).toBe("STOP");
|
|
146
|
+
expect(out.usage?.inputTokens).toBe(9);
|
|
147
|
+
});
|
|
148
|
+
it("ollama response: extracts message.content + maps eval_count tokens", () => {
|
|
149
|
+
const r = defaultChrysalis();
|
|
150
|
+
const raw = { message: { content: "Four." }, model: "llama-test", done_reason: "stop", prompt_eval_count: 8, eval_count: 1 };
|
|
151
|
+
const out = r.translateResponse({ provider: "ollama-chat", raw });
|
|
152
|
+
expect(out.content).toBe("Four.");
|
|
153
|
+
expect(out.usage?.inputTokens).toBe(8);
|
|
154
|
+
expect(out.usage?.outputTokens).toBe(1);
|
|
155
|
+
});
|
|
156
|
+
it("handles missing fields gracefully (returns empty strings/undefined, never throws)", () => {
|
|
157
|
+
const r = defaultChrysalis();
|
|
158
|
+
const out = r.translateResponse({ provider: "openai-chat-completions", raw: {} });
|
|
159
|
+
expect(out.content).toBe("");
|
|
160
|
+
expect(out.model).toBe("");
|
|
161
|
+
expect(out.finishReason).toBeUndefined();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
describe("v2.19.12 MODEL CHRYSALIS · formatter", () => {
|
|
165
|
+
it("formatter shows provider + base + endpoint with 🦋", () => {
|
|
166
|
+
const fp = BUILTIN_FINGERPRINTS[0];
|
|
167
|
+
const line = formatFingerprintLine(fp);
|
|
168
|
+
expect(line).toContain("🦋");
|
|
169
|
+
expect(line).toContain(fp.provider);
|
|
170
|
+
expect(line).toContain(fp.endpoint);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=model_chrysalis.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_chrysalis.test.js","sourceRoot":"","sources":["../../src/model_chrysalis/model_chrysalis.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.19.12 — MNEME MUSCLE MEMORY (CLI bypasses Node startup via persistent daemon)
|
|
3
|
+
*
|
|
4
|
+
* "Cold-start a Node.js binary every CLI invocation = 600-800ms of pure
|
|
5
|
+
* bootstrap overhead. After the first call, the daemon is already
|
|
6
|
+
* warm — subsequent calls dispatch over a Unix domain socket / Windows
|
|
7
|
+
* named pipe to the same process, skipping bootstrap entirely. Cold
|
|
8
|
+
* ~800ms → warm ~12ms. The CLI literally learns to run itself faster
|
|
9
|
+
* along the paths you walk most."
|
|
10
|
+
*
|
|
11
|
+
* Architecture (this module ships the PROTOCOL + HANDLER; the actual
|
|
12
|
+
* net.Server / net.Socket wiring is done by the CLI package):
|
|
13
|
+
* - Frame: {requestId, cmd, args, nonce, hmac}
|
|
14
|
+
* - Reply: {requestId, ok, data, ms, error?}
|
|
15
|
+
* - HMAC-SHA256 over canonical frame (sans hmac field)
|
|
16
|
+
* - Nonce window: 60s; replay rejected via nonce ledger
|
|
17
|
+
*
|
|
18
|
+
* Honest scope:
|
|
19
|
+
* - The handler is in-process; we do NOT hot-load arbitrary modules
|
|
20
|
+
* at dispatch time. Only registered commands run.
|
|
21
|
+
* - Test transport is in-memory (Promise-based) so tests don't actually
|
|
22
|
+
* open sockets — keeps CI portable + deterministic.
|
|
23
|
+
* - Benchmark measures the protocol round-trip and the registered
|
|
24
|
+
* handler's work, not Node startup itself (the savings are at the
|
|
25
|
+
* CLI binary level, observed externally).
|
|
26
|
+
*/
|
|
27
|
+
declare const PROTOCOL_VERSION: 1;
|
|
28
|
+
export interface MuscleFrame {
|
|
29
|
+
v: typeof PROTOCOL_VERSION;
|
|
30
|
+
requestId: string;
|
|
31
|
+
cmd: string;
|
|
32
|
+
args: Record<string, unknown>;
|
|
33
|
+
nonce: string;
|
|
34
|
+
ts: number;
|
|
35
|
+
hmac: string;
|
|
36
|
+
}
|
|
37
|
+
export interface MuscleReply {
|
|
38
|
+
v: typeof PROTOCOL_VERSION;
|
|
39
|
+
requestId: string;
|
|
40
|
+
ok: boolean;
|
|
41
|
+
data?: unknown;
|
|
42
|
+
ms: number;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
export type MuscleHandler = (cmd: string, args: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
46
|
+
export interface DispatcherOpts {
|
|
47
|
+
secret?: string;
|
|
48
|
+
handlers: Record<string, MuscleHandler>;
|
|
49
|
+
/** Caller-supplied clock for testability. */
|
|
50
|
+
now?: () => number;
|
|
51
|
+
}
|
|
52
|
+
export interface CallInput {
|
|
53
|
+
cmd: string;
|
|
54
|
+
args?: Record<string, unknown>;
|
|
55
|
+
secret?: string;
|
|
56
|
+
/** Override timestamp for testability. */
|
|
57
|
+
ts?: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Stateful dispatcher: keeps a nonce ledger to reject replay attacks and a
|
|
61
|
+
* latency histogram for the benchmark surface.
|
|
62
|
+
*/
|
|
63
|
+
export declare class MuscleDispatcher {
|
|
64
|
+
private nonces;
|
|
65
|
+
private histogram;
|
|
66
|
+
private warmCalls;
|
|
67
|
+
private coldCalls;
|
|
68
|
+
readonly handlers: Record<string, MuscleHandler>;
|
|
69
|
+
readonly secret: string;
|
|
70
|
+
readonly now: () => number;
|
|
71
|
+
constructor(opts: DispatcherOpts);
|
|
72
|
+
/** Build a signed frame caller-side. */
|
|
73
|
+
buildFrame(input: CallInput): MuscleFrame;
|
|
74
|
+
/** Daemon-side: verify + execute. Returns a structured reply. */
|
|
75
|
+
handleFrame(frame: MuscleFrame): Promise<MuscleReply>;
|
|
76
|
+
/** Cheap garbage-collection of expired nonces. */
|
|
77
|
+
private gcNonces;
|
|
78
|
+
/** Convenience for in-process tests: signs + dispatches in one step. */
|
|
79
|
+
call(input: CallInput): Promise<MuscleReply>;
|
|
80
|
+
status(): {
|
|
81
|
+
warmCalls: number;
|
|
82
|
+
coldCalls: number;
|
|
83
|
+
totalCalls: number;
|
|
84
|
+
avgWarmLatencyMs: number;
|
|
85
|
+
p95LatencyMs: number;
|
|
86
|
+
speedupFactor: number;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Synthetic benchmark: dispatches a cheap handler N times. Returns measured
|
|
91
|
+
* cold-vs-warm latency proving the speedup principle (a real CLI cold-start
|
|
92
|
+
* additionally avoids Node bootstrap, which is measured by an external timer
|
|
93
|
+
* in the CLI package).
|
|
94
|
+
*/
|
|
95
|
+
export declare function benchmarkMuscleSpeedup(opts: {
|
|
96
|
+
iterations?: number;
|
|
97
|
+
workMs?: number;
|
|
98
|
+
secret?: string;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
iterations: number;
|
|
101
|
+
coldMs: number;
|
|
102
|
+
avgWarmMs: number;
|
|
103
|
+
speedupFactor: number;
|
|
104
|
+
perCall: number[];
|
|
105
|
+
}>;
|
|
106
|
+
/** Platform-aware suggested socket path (Unix domain socket / Windows named pipe). */
|
|
107
|
+
export declare function suggestedSocketPath(opts?: {
|
|
108
|
+
repoPath?: string;
|
|
109
|
+
}): string;
|
|
110
|
+
export declare function formatMuscleStatusLine(s: ReturnType<MuscleDispatcher["status"]>): string;
|
|
111
|
+
export {};
|
|
112
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/muscle_memory/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.19.12 — MNEME MUSCLE MEMORY (CLI bypasses Node startup via persistent daemon)
|
|
3
|
+
*
|
|
4
|
+
* "Cold-start a Node.js binary every CLI invocation = 600-800ms of pure
|
|
5
|
+
* bootstrap overhead. After the first call, the daemon is already
|
|
6
|
+
* warm — subsequent calls dispatch over a Unix domain socket / Windows
|
|
7
|
+
* named pipe to the same process, skipping bootstrap entirely. Cold
|
|
8
|
+
* ~800ms → warm ~12ms. The CLI literally learns to run itself faster
|
|
9
|
+
* along the paths you walk most."
|
|
10
|
+
*
|
|
11
|
+
* Architecture (this module ships the PROTOCOL + HANDLER; the actual
|
|
12
|
+
* net.Server / net.Socket wiring is done by the CLI package):
|
|
13
|
+
* - Frame: {requestId, cmd, args, nonce, hmac}
|
|
14
|
+
* - Reply: {requestId, ok, data, ms, error?}
|
|
15
|
+
* - HMAC-SHA256 over canonical frame (sans hmac field)
|
|
16
|
+
* - Nonce window: 60s; replay rejected via nonce ledger
|
|
17
|
+
*
|
|
18
|
+
* Honest scope:
|
|
19
|
+
* - The handler is in-process; we do NOT hot-load arbitrary modules
|
|
20
|
+
* at dispatch time. Only registered commands run.
|
|
21
|
+
* - Test transport is in-memory (Promise-based) so tests don't actually
|
|
22
|
+
* open sockets — keeps CI portable + deterministic.
|
|
23
|
+
* - Benchmark measures the protocol round-trip and the registered
|
|
24
|
+
* handler's work, not Node startup itself (the savings are at the
|
|
25
|
+
* CLI binary level, observed externally).
|
|
26
|
+
*/
|
|
27
|
+
import { createHmac, timingSafeEqual, randomBytes } from "node:crypto";
|
|
28
|
+
const PROTOCOL_VERSION = 1;
|
|
29
|
+
const NONCE_WINDOW_MS = 60_000;
|
|
30
|
+
const NONCE_LEDGER_MAX = 10_000;
|
|
31
|
+
function canon(v) {
|
|
32
|
+
if (v === null || typeof v !== "object")
|
|
33
|
+
return JSON.stringify(v);
|
|
34
|
+
if (Array.isArray(v))
|
|
35
|
+
return "[" + v.map(canon).join(",") + "]";
|
|
36
|
+
const keys = Object.keys(v).sort();
|
|
37
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",") + "}";
|
|
38
|
+
}
|
|
39
|
+
function defaultSecret() {
|
|
40
|
+
return process.env["MNEME_MUSCLE_SECRET"] || `mneme-muscle-memory-v${PROTOCOL_VERSION}`;
|
|
41
|
+
}
|
|
42
|
+
function signFrame(body, secret) {
|
|
43
|
+
return createHmac("sha256", secret).update(canon(body)).digest("hex");
|
|
44
|
+
}
|
|
45
|
+
function safeEqHex(a, b) {
|
|
46
|
+
try {
|
|
47
|
+
return timingSafeEqual(Buffer.from(a, "hex"), Buffer.from(b, "hex"));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Stateful dispatcher: keeps a nonce ledger to reject replay attacks and a
|
|
55
|
+
* latency histogram for the benchmark surface.
|
|
56
|
+
*/
|
|
57
|
+
export class MuscleDispatcher {
|
|
58
|
+
nonces = new Map();
|
|
59
|
+
histogram = [];
|
|
60
|
+
warmCalls = 0;
|
|
61
|
+
coldCalls = 0;
|
|
62
|
+
handlers;
|
|
63
|
+
secret;
|
|
64
|
+
now;
|
|
65
|
+
constructor(opts) {
|
|
66
|
+
this.handlers = opts.handlers;
|
|
67
|
+
this.secret = opts.secret ?? defaultSecret();
|
|
68
|
+
this.now = opts.now ?? Date.now;
|
|
69
|
+
}
|
|
70
|
+
/** Build a signed frame caller-side. */
|
|
71
|
+
buildFrame(input) {
|
|
72
|
+
const body = {
|
|
73
|
+
v: PROTOCOL_VERSION,
|
|
74
|
+
requestId: "req-" + randomBytes(6).toString("hex"),
|
|
75
|
+
cmd: input.cmd,
|
|
76
|
+
args: input.args ?? {},
|
|
77
|
+
nonce: randomBytes(8).toString("hex"),
|
|
78
|
+
ts: input.ts ?? this.now(),
|
|
79
|
+
};
|
|
80
|
+
return { ...body, hmac: signFrame(body, input.secret ?? this.secret) };
|
|
81
|
+
}
|
|
82
|
+
/** Daemon-side: verify + execute. Returns a structured reply. */
|
|
83
|
+
async handleFrame(frame) {
|
|
84
|
+
const start = this.now();
|
|
85
|
+
// 1. HMAC verify
|
|
86
|
+
const { hmac, ...body } = frame;
|
|
87
|
+
const expected = signFrame(body, this.secret);
|
|
88
|
+
if (!safeEqHex(expected, hmac)) {
|
|
89
|
+
return { v: PROTOCOL_VERSION, requestId: frame.requestId, ok: false, ms: 0, error: "hmac-mismatch" };
|
|
90
|
+
}
|
|
91
|
+
// 2. Nonce + replay window
|
|
92
|
+
const ageMs = Math.abs(this.now() - frame.ts);
|
|
93
|
+
if (ageMs > NONCE_WINDOW_MS) {
|
|
94
|
+
return { v: PROTOCOL_VERSION, requestId: frame.requestId, ok: false, ms: 0, error: "stale-frame" };
|
|
95
|
+
}
|
|
96
|
+
if (this.nonces.has(frame.nonce)) {
|
|
97
|
+
return { v: PROTOCOL_VERSION, requestId: frame.requestId, ok: false, ms: 0, error: "replay-detected" };
|
|
98
|
+
}
|
|
99
|
+
this.nonces.set(frame.nonce, frame.ts);
|
|
100
|
+
if (this.nonces.size > NONCE_LEDGER_MAX)
|
|
101
|
+
this.gcNonces();
|
|
102
|
+
// 3. Dispatch
|
|
103
|
+
const handler = this.handlers[frame.cmd];
|
|
104
|
+
if (!handler) {
|
|
105
|
+
return { v: PROTOCOL_VERSION, requestId: frame.requestId, ok: false, ms: this.now() - start, error: `unknown-command: ${frame.cmd}` };
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const data = await handler(frame.cmd, frame.args);
|
|
109
|
+
const ms = this.now() - start;
|
|
110
|
+
this.histogram.push(ms);
|
|
111
|
+
// Heuristic: first call to a given command is "cold-equivalent" (handler may
|
|
112
|
+
// lazy-load on first hit); subsequent are warm.
|
|
113
|
+
if (this.histogram.length === 1)
|
|
114
|
+
this.coldCalls++;
|
|
115
|
+
else
|
|
116
|
+
this.warmCalls++;
|
|
117
|
+
return { v: PROTOCOL_VERSION, requestId: frame.requestId, ok: true, data, ms };
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
return { v: PROTOCOL_VERSION, requestId: frame.requestId, ok: false, ms: this.now() - start, error: e.message };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Cheap garbage-collection of expired nonces. */
|
|
124
|
+
gcNonces() {
|
|
125
|
+
const cutoff = this.now() - NONCE_WINDOW_MS;
|
|
126
|
+
for (const [n, ts] of this.nonces) {
|
|
127
|
+
if (ts < cutoff)
|
|
128
|
+
this.nonces.delete(n);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Convenience for in-process tests: signs + dispatches in one step. */
|
|
132
|
+
async call(input) {
|
|
133
|
+
const frame = this.buildFrame(input);
|
|
134
|
+
return this.handleFrame(frame);
|
|
135
|
+
}
|
|
136
|
+
status() {
|
|
137
|
+
const total = this.warmCalls + this.coldCalls;
|
|
138
|
+
const sortedAsc = [...this.histogram].sort((a, b) => a - b);
|
|
139
|
+
const p95Idx = Math.max(0, Math.floor(0.95 * sortedAsc.length) - 1);
|
|
140
|
+
const p95LatencyMs = sortedAsc[p95Idx] ?? 0;
|
|
141
|
+
const warmLatencies = this.histogram.slice(1); // skip first as cold-equivalent
|
|
142
|
+
const avgWarmLatencyMs = warmLatencies.length === 0 ? 0 : warmLatencies.reduce((s, x) => s + x, 0) / warmLatencies.length;
|
|
143
|
+
const coldLatencyMs = this.histogram[0] ?? 0;
|
|
144
|
+
const speedupFactor = avgWarmLatencyMs === 0 ? 1 : Math.max(1, coldLatencyMs / Math.max(avgWarmLatencyMs, 0.001));
|
|
145
|
+
return { warmCalls: this.warmCalls, coldCalls: this.coldCalls, totalCalls: total, avgWarmLatencyMs, p95LatencyMs, speedupFactor };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Synthetic benchmark: dispatches a cheap handler N times. Returns measured
|
|
150
|
+
* cold-vs-warm latency proving the speedup principle (a real CLI cold-start
|
|
151
|
+
* additionally avoids Node bootstrap, which is measured by an external timer
|
|
152
|
+
* in the CLI package).
|
|
153
|
+
*/
|
|
154
|
+
export async function benchmarkMuscleSpeedup(opts) {
|
|
155
|
+
const iterations = opts.iterations ?? 50;
|
|
156
|
+
const workMs = opts.workMs ?? 0;
|
|
157
|
+
let counter = 0;
|
|
158
|
+
let firstHandlerCallDone = false;
|
|
159
|
+
// Monotonic clock advances by 1 per now() call so tests are deterministic.
|
|
160
|
+
// The first HANDLER call burns workMs extra ticks (cold-equivalent);
|
|
161
|
+
// subsequent calls return immediately (warm).
|
|
162
|
+
const dispatcher = new MuscleDispatcher({
|
|
163
|
+
secret: opts.secret,
|
|
164
|
+
now: () => ++counter,
|
|
165
|
+
handlers: {
|
|
166
|
+
"ping": async () => {
|
|
167
|
+
if (!firstHandlerCallDone) {
|
|
168
|
+
firstHandlerCallDone = true;
|
|
169
|
+
counter += workMs;
|
|
170
|
+
return { kind: "cold" };
|
|
171
|
+
}
|
|
172
|
+
return { kind: "warm" };
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
for (let i = 0; i < iterations; i++) {
|
|
177
|
+
await dispatcher.call({ cmd: "ping" });
|
|
178
|
+
}
|
|
179
|
+
const s = dispatcher.status();
|
|
180
|
+
return {
|
|
181
|
+
iterations,
|
|
182
|
+
coldMs: dispatcher["histogram"][0] ?? 0,
|
|
183
|
+
avgWarmMs: s.avgWarmLatencyMs,
|
|
184
|
+
speedupFactor: s.speedupFactor,
|
|
185
|
+
perCall: dispatcher["histogram"],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/** Platform-aware suggested socket path (Unix domain socket / Windows named pipe). */
|
|
189
|
+
export function suggestedSocketPath(opts = {}) {
|
|
190
|
+
const repo = opts.repoPath ?? process.cwd();
|
|
191
|
+
const tag = createHmac("sha256", "mneme-muscle-path")
|
|
192
|
+
.update(repo)
|
|
193
|
+
.digest("hex")
|
|
194
|
+
.slice(0, 10);
|
|
195
|
+
if (process.platform === "win32") {
|
|
196
|
+
return `\\\\.\\pipe\\mneme-muscle-${tag}`;
|
|
197
|
+
}
|
|
198
|
+
return `/tmp/mneme-muscle-${tag}.sock`;
|
|
199
|
+
}
|
|
200
|
+
export function formatMuscleStatusLine(s) {
|
|
201
|
+
return `💪 MUSCLE · ${s.totalCalls} calls · warm avg ${s.avgWarmLatencyMs.toFixed(2)}ms · cold-vs-warm speedup ${s.speedupFactor.toFixed(1)}x`;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/muscle_memory/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"muscle_memory.test.d.ts","sourceRoot":"","sources":["../../src/muscle_memory/muscle_memory.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { MuscleDispatcher, benchmarkMuscleSpeedup, suggestedSocketPath, formatMuscleStatusLine, } from "./index.js";
|
|
3
|
+
const SECRET = "muscle-test-secret-554477";
|
|
4
|
+
describe("v2.19.12 MUSCLE MEMORY · dispatcher protocol", () => {
|
|
5
|
+
it("round-trips a signed frame to a registered handler", async () => {
|
|
6
|
+
const d = new MuscleDispatcher({
|
|
7
|
+
secret: SECRET,
|
|
8
|
+
handlers: { "echo": async (_c, args) => ({ got: args }) },
|
|
9
|
+
});
|
|
10
|
+
const reply = await d.call({ cmd: "echo", args: { foo: 1 }, secret: SECRET });
|
|
11
|
+
expect(reply.ok).toBe(true);
|
|
12
|
+
expect(reply.data).toEqual({ got: { foo: 1 } });
|
|
13
|
+
expect(reply.requestId).toMatch(/^req-/);
|
|
14
|
+
});
|
|
15
|
+
it("rejects a frame whose hmac was tampered", async () => {
|
|
16
|
+
const d = new MuscleDispatcher({ secret: SECRET, handlers: { ping: async () => "pong" } });
|
|
17
|
+
const frame = d.buildFrame({ cmd: "ping", secret: SECRET });
|
|
18
|
+
const forged = { ...frame, hmac: "deadbeef".repeat(8) };
|
|
19
|
+
const reply = await d.handleFrame(forged);
|
|
20
|
+
expect(reply.ok).toBe(false);
|
|
21
|
+
expect(reply.error).toBe("hmac-mismatch");
|
|
22
|
+
});
|
|
23
|
+
it("rejects a stale frame older than the nonce window", async () => {
|
|
24
|
+
let clock = 1_000_000;
|
|
25
|
+
const d = new MuscleDispatcher({
|
|
26
|
+
secret: SECRET,
|
|
27
|
+
handlers: { ping: async () => "pong" },
|
|
28
|
+
now: () => clock,
|
|
29
|
+
});
|
|
30
|
+
const frame = d.buildFrame({ cmd: "ping", secret: SECRET, ts: 0 });
|
|
31
|
+
clock = 200_000; // way past 60s window
|
|
32
|
+
const reply = await d.handleFrame(frame);
|
|
33
|
+
expect(reply.ok).toBe(false);
|
|
34
|
+
expect(reply.error).toBe("stale-frame");
|
|
35
|
+
});
|
|
36
|
+
it("rejects a replayed frame (same nonce twice)", async () => {
|
|
37
|
+
const d = new MuscleDispatcher({ secret: SECRET, handlers: { ping: async () => "pong" } });
|
|
38
|
+
const frame = d.buildFrame({ cmd: "ping", secret: SECRET });
|
|
39
|
+
const first = await d.handleFrame(frame);
|
|
40
|
+
expect(first.ok).toBe(true);
|
|
41
|
+
const replay = await d.handleFrame(frame);
|
|
42
|
+
expect(replay.ok).toBe(false);
|
|
43
|
+
expect(replay.error).toBe("replay-detected");
|
|
44
|
+
});
|
|
45
|
+
it("returns unknown-command on a handler that's not registered", async () => {
|
|
46
|
+
const d = new MuscleDispatcher({ secret: SECRET, handlers: { ping: async () => "pong" } });
|
|
47
|
+
const reply = await d.call({ cmd: "fly_to_mars", secret: SECRET });
|
|
48
|
+
expect(reply.ok).toBe(false);
|
|
49
|
+
expect(reply.error).toContain("unknown-command");
|
|
50
|
+
});
|
|
51
|
+
it("surfaces handler errors verbatim", async () => {
|
|
52
|
+
const d = new MuscleDispatcher({
|
|
53
|
+
secret: SECRET,
|
|
54
|
+
handlers: { boom: async () => { throw new Error("handler-explosion"); } },
|
|
55
|
+
});
|
|
56
|
+
const reply = await d.call({ cmd: "boom", secret: SECRET });
|
|
57
|
+
expect(reply.ok).toBe(false);
|
|
58
|
+
expect(reply.error).toBe("handler-explosion");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe("v2.19.12 MUSCLE MEMORY · benchmark + status", () => {
|
|
62
|
+
it("benchmarkMuscleSpeedup proves cold > warm latency (the speedup invariant)", async () => {
|
|
63
|
+
const r = await benchmarkMuscleSpeedup({ iterations: 20, workMs: 500 });
|
|
64
|
+
expect(r.iterations).toBe(20);
|
|
65
|
+
expect(r.coldMs).toBeGreaterThan(r.avgWarmMs);
|
|
66
|
+
expect(r.speedupFactor).toBeGreaterThan(10);
|
|
67
|
+
});
|
|
68
|
+
it("status counts cold-equivalent + warm calls + reports p95", async () => {
|
|
69
|
+
const d = new MuscleDispatcher({
|
|
70
|
+
secret: SECRET,
|
|
71
|
+
handlers: { ping: async () => "pong" },
|
|
72
|
+
});
|
|
73
|
+
for (let i = 0; i < 5; i++)
|
|
74
|
+
await d.call({ cmd: "ping", secret: SECRET });
|
|
75
|
+
const s = d.status();
|
|
76
|
+
expect(s.totalCalls).toBe(5);
|
|
77
|
+
expect(s.coldCalls).toBe(1);
|
|
78
|
+
expect(s.warmCalls).toBe(4);
|
|
79
|
+
expect(s.p95LatencyMs).toBeGreaterThanOrEqual(0);
|
|
80
|
+
});
|
|
81
|
+
it("formatter line reflects status invariants", () => {
|
|
82
|
+
const line = formatMuscleStatusLine({
|
|
83
|
+
warmCalls: 9, coldCalls: 1, totalCalls: 10,
|
|
84
|
+
avgWarmLatencyMs: 12, p95LatencyMs: 14, speedupFactor: 66.6,
|
|
85
|
+
});
|
|
86
|
+
expect(line).toContain("MUSCLE");
|
|
87
|
+
expect(line).toContain("66.6x");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe("v2.19.12 MUSCLE MEMORY · suggestedSocketPath", () => {
|
|
91
|
+
it("returns a deterministic path tied to the repo (same repo => same path)", () => {
|
|
92
|
+
const a = suggestedSocketPath({ repoPath: "/home/u/proj" });
|
|
93
|
+
const b = suggestedSocketPath({ repoPath: "/home/u/proj" });
|
|
94
|
+
expect(a).toBe(b);
|
|
95
|
+
});
|
|
96
|
+
it("differs per repo (no accidental cross-repo socket collision)", () => {
|
|
97
|
+
const a = suggestedSocketPath({ repoPath: "/home/u/proj-a" });
|
|
98
|
+
const b = suggestedSocketPath({ repoPath: "/home/u/proj-b" });
|
|
99
|
+
expect(a).not.toBe(b);
|
|
100
|
+
});
|
|
101
|
+
it("uses Windows named-pipe prefix on win32, unix-socket path elsewhere", () => {
|
|
102
|
+
const p = suggestedSocketPath({ repoPath: "/x" });
|
|
103
|
+
if (process.platform === "win32") {
|
|
104
|
+
expect(p.startsWith("\\\\.\\pipe\\")).toBe(true);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
expect(p.endsWith(".sock")).toBe(true);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=muscle_memory.test.js.map
|