mumpix 1.0.19 → 1.0.29
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/CHANGELOG.md +42 -14
- package/README.md +185 -8
- package/bin/mumpix.js +1 -405
- package/examples/agent-memory.js +1 -1
- package/examples/basic.js +1 -1
- package/examples/behavioral-primitives.js +50 -0
- package/examples/verified-mode.js +1 -1
- package/package.json +17 -13
- package/scripts/test-license-modes.cjs +87 -0
- package/src/brp/index.js +1 -0
- package/src/collapse/index.js +1 -0
- package/src/core/MumpixDB.js +210 -322
- package/src/core/audit.js +1 -173
- package/src/core/auth.js +1 -232
- package/src/core/inverted-index.js +144 -0
- package/src/core/license.js +1 -267
- package/src/core/ml-dsa.mjs +1 -25
- package/src/core/ml-kem.mjs +1 -32
- package/src/core/recall.js +1 -176
- package/src/core/store.js +335 -286
- package/src/core/wal-writer.js +83 -0
- package/src/index.js +20 -34
- package/src/integrations/developer-sdk.js +1 -165
- package/src/integrations/langchain-official.js +1 -0
- package/src/integrations/langchain.js +1 -131
- package/src/integrations/llamaindex-official.js +1 -0
- package/src/integrations/llamaindex.js +1 -86
- package/src/integrations/vector-sidecar.js +325 -0
- package/src/rlp/index.js +1 -0
- package/src/temporal/engine.js +1 -1894
- package/src/temporal/indexes.js +1 -178
- package/src/temporal/operators.js +1 -186
- package/scripts/postinstall-auth.js +0 -101
package/bin/mumpix.js
CHANGED
|
@@ -1,406 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* mumpix CLI
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* mumpix remember ./agent.mumpix "User prefers TypeScript"
|
|
9
|
-
* mumpix recall ./agent.mumpix "what language?"
|
|
10
|
-
* mumpix list ./agent.mumpix
|
|
11
|
-
* mumpix clear ./agent.mumpix
|
|
12
|
-
* mumpix stats ./agent.mumpix
|
|
13
|
-
* mumpix audit ./agent.mumpix
|
|
14
|
-
* mumpix shell ./agent.mumpix # interactive REPL
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const path = require('path');
|
|
18
|
-
const readline = require('readline');
|
|
19
|
-
const { Mumpix } = require('../src/index');
|
|
20
|
-
const {
|
|
21
|
-
loadAuthState,
|
|
22
|
-
clearAuthState,
|
|
23
|
-
upsertStoredLicense,
|
|
24
|
-
exchangeTokenForLicense,
|
|
25
|
-
loginWithDeviceFlow,
|
|
26
|
-
authStatePath,
|
|
27
|
-
configDir,
|
|
28
|
-
} = require('../src/core/auth');
|
|
29
|
-
|
|
30
|
-
const USAGE = `
|
|
31
|
-
mumpix — SQLite for AI
|
|
32
|
-
|
|
33
|
-
Usage:
|
|
34
|
-
mumpix <command> <file> [args...]
|
|
35
|
-
|
|
36
|
-
Commands:
|
|
37
|
-
remember <file> "<text>" Store a memory
|
|
38
|
-
recall <file> "<query>" Recall the best match
|
|
39
|
-
search <file> "<query>" [k] Recall top-k matches
|
|
40
|
-
list <file> List all memories
|
|
41
|
-
clear <file> Clear all memories
|
|
42
|
-
stats <file> Show database stats
|
|
43
|
-
audit <file> Show audit log (verified mode)
|
|
44
|
-
shell <file> Start interactive REPL
|
|
45
|
-
auth <subcommand> Account login/logout/status
|
|
46
|
-
help Show this message
|
|
47
|
-
|
|
48
|
-
Options (append to any command):
|
|
49
|
-
--consistency=eventual|strict|verified (default: eventual)
|
|
50
|
-
|
|
51
|
-
Examples:
|
|
52
|
-
mumpix remember ./agent.mumpix "User prefers TypeScript"
|
|
53
|
-
mumpix recall ./agent.mumpix "what language?" --consistency=strict
|
|
54
|
-
mumpix search ./agent.mumpix "TypeScript" 3
|
|
55
|
-
mumpix shell ./agent.mumpix --consistency=verified
|
|
56
|
-
mumpix auth status
|
|
57
|
-
mumpix auth login --token=<account-token>
|
|
58
|
-
mumpix auth login --license=<signed-license-key>
|
|
59
|
-
`.trim();
|
|
60
|
-
|
|
61
|
-
function parseArgs(argv) {
|
|
62
|
-
const args = [];
|
|
63
|
-
const flags = {};
|
|
64
|
-
for (const arg of argv) {
|
|
65
|
-
if (arg.startsWith('--')) {
|
|
66
|
-
const [k, v] = arg.slice(2).split('=');
|
|
67
|
-
flags[k] = v !== undefined ? v : true;
|
|
68
|
-
} else {
|
|
69
|
-
args.push(arg);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return { args, flags };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function fmt(val) {
|
|
76
|
-
if (val === null) return 'null';
|
|
77
|
-
if (typeof val === 'string') return val;
|
|
78
|
-
return JSON.stringify(val, null, 2);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function colorize(text, code) {
|
|
82
|
-
if (!process.stdout.isTTY) return text;
|
|
83
|
-
return `\x1b[${code}m${text}\x1b[0m`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const dim = t => colorize(t, '2');
|
|
87
|
-
const cyan = t => colorize(t, '36');
|
|
88
|
-
const green = t => colorize(t, '32');
|
|
89
|
-
const yellow = t => colorize(t, '33');
|
|
90
|
-
const red = t => colorize(t, '31');
|
|
91
|
-
const bold = t => colorize(t, '1');
|
|
92
|
-
|
|
93
|
-
function fmtExpiry(ts) {
|
|
94
|
-
if (!ts) return '-';
|
|
95
|
-
const d = new Date(Number(ts));
|
|
96
|
-
if (Number.isNaN(d.getTime())) return '-';
|
|
97
|
-
return d.toISOString();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function mask(value, keep = 6) {
|
|
101
|
-
const s = String(value || '');
|
|
102
|
-
if (s.length <= keep) return s;
|
|
103
|
-
return `${s.slice(0, keep)}…`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async function runAuth(parts, flags) {
|
|
107
|
-
const sub = String(parts[0] || 'status').toLowerCase();
|
|
108
|
-
|
|
109
|
-
if (sub === 'status') {
|
|
110
|
-
const s = loadAuthState();
|
|
111
|
-
if (!s || !s.license || !s.license.key) {
|
|
112
|
-
console.log(dim('Not logged in.'));
|
|
113
|
-
console.log(dim(`Config dir: ${configDir()}`));
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
console.log(bold('Mumpix auth status'));
|
|
117
|
-
console.log(` account_id: ${s.account && s.account.id ? s.account.id : '-'}`);
|
|
118
|
-
console.log(` tier: ${s.license.tier || (s.account && s.account.tier) || '-'}`);
|
|
119
|
-
console.log(` issued_at: ${fmtExpiry(s.license.iat)}`);
|
|
120
|
-
console.log(` expires_at: ${fmtExpiry(s.license.exp)}`);
|
|
121
|
-
console.log(` license: ${green(mask(s.license.key, 18))}`);
|
|
122
|
-
console.log(` state: ${authStatePath()}`);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (sub === 'logout') {
|
|
127
|
-
clearAuthState();
|
|
128
|
-
console.log(green('✓') + ' Logged out. Local license removed.');
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (sub === 'login') {
|
|
133
|
-
const directLicense = flags.license || flags['license-key'] || null;
|
|
134
|
-
if (directLicense) {
|
|
135
|
-
const state = upsertStoredLicense(String(directLicense));
|
|
136
|
-
console.log(green('✓') + ' License saved.');
|
|
137
|
-
console.log(` tier: ${state.license.tier || '-'}`);
|
|
138
|
-
console.log(` expires_at: ${fmtExpiry(state.license.exp)}`);
|
|
139
|
-
console.log(` state: ${authStatePath()}`);
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const token = flags.token || process.env.MUMPIX_AUTH_TOKEN || '';
|
|
144
|
-
if (token) {
|
|
145
|
-
const state = await exchangeTokenForLicense(String(token).trim(), {});
|
|
146
|
-
console.log(green('✓') + ' Account linked and license saved.');
|
|
147
|
-
console.log(` account_id: ${state.account.id || '-'}`);
|
|
148
|
-
console.log(` tier: ${state.license.tier || state.account.tier || '-'}`);
|
|
149
|
-
console.log(` expires_at: ${fmtExpiry(state.license.exp)}`);
|
|
150
|
-
console.log(` state: ${authStatePath()}`);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const state = await loginWithDeviceFlow({
|
|
155
|
-
onPrompt: ({ userCode, verifyUrl, expiresInSec, intervalSec }) => {
|
|
156
|
-
console.log(bold('Mumpix device login'));
|
|
157
|
-
console.log(` 1) Open: ${verifyUrl}`);
|
|
158
|
-
console.log(` 2) Enter code: ${cyan(userCode)}`);
|
|
159
|
-
console.log(` 3) Waiting for approval... (expires in ${expiresInSec}s, polling ${intervalSec}s)`);
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
console.log(green('✓') + ' Account linked and license saved.');
|
|
163
|
-
console.log(` account_id: ${state.account.id || '-'}`);
|
|
164
|
-
console.log(` tier: ${state.license.tier || state.account.tier || '-'}`);
|
|
165
|
-
console.log(` expires_at: ${fmtExpiry(state.license.exp)}`);
|
|
166
|
-
console.log(` state: ${authStatePath()}`);
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
console.error(red(`Unknown auth subcommand: ${sub}`));
|
|
171
|
-
console.log('Usage: mumpix auth <status|login|logout> [--token=...] [--license=...]');
|
|
172
|
-
process.exit(1);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async function main() {
|
|
176
|
-
const { args, flags } = parseArgs(process.argv.slice(2));
|
|
177
|
-
const [command, arg1, ...rest] = args;
|
|
178
|
-
|
|
179
|
-
if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
180
|
-
console.log(USAGE);
|
|
181
|
-
process.exit(0);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (command === 'auth') {
|
|
185
|
-
await runAuth([arg1, ...rest], flags);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const filePath = arg1;
|
|
190
|
-
if (!filePath && command !== 'help') {
|
|
191
|
-
console.error(red('Error: file path required'));
|
|
192
|
-
console.log(USAGE);
|
|
193
|
-
process.exit(1);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const consistency = flags.consistency || 'eventual';
|
|
197
|
-
let db;
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
db = await Mumpix.open(filePath, { consistency });
|
|
201
|
-
} catch (err) {
|
|
202
|
-
console.error(red(`Error opening ${filePath}: ${err.message}`));
|
|
203
|
-
process.exit(1);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
try {
|
|
207
|
-
switch (command) {
|
|
208
|
-
|
|
209
|
-
case 'remember': {
|
|
210
|
-
const text = rest.join(' ').replace(/^["']|["']$/g, '');
|
|
211
|
-
if (!text) { console.error(red('Error: provide text to remember')); process.exit(1); }
|
|
212
|
-
const result = await db.remember(text);
|
|
213
|
-
console.log(green('✓') + ` Stored as #${result.id} (${result.consistency})`);
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
case 'recall': {
|
|
218
|
-
const query = rest.join(' ').replace(/^["']|["']$/g, '');
|
|
219
|
-
if (!query) { console.error(red('Error: provide a query')); process.exit(1); }
|
|
220
|
-
const result = await db.recall(query);
|
|
221
|
-
if (result === null) {
|
|
222
|
-
console.log(dim('No memories found.'));
|
|
223
|
-
} else {
|
|
224
|
-
console.log(green('→') + ' ' + result);
|
|
225
|
-
}
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
case 'search': {
|
|
230
|
-
const k = parseInt(rest[rest.length - 1], 10);
|
|
231
|
-
const limit = Number.isInteger(k) && k > 0 ? k : 5;
|
|
232
|
-
const queryParts = Number.isInteger(k) ? rest.slice(0, -1) : rest;
|
|
233
|
-
const query = queryParts.join(' ').replace(/^["']|["']$/g, '');
|
|
234
|
-
if (!query) { console.error(red('Error: provide a query')); process.exit(1); }
|
|
235
|
-
const results = await db.recallMany(query, limit);
|
|
236
|
-
if (!results.length) {
|
|
237
|
-
console.log(dim('No memories found.'));
|
|
238
|
-
} else {
|
|
239
|
-
results.forEach((r, i) => {
|
|
240
|
-
const score = r.score !== undefined ? dim(` (${(r.score * 100).toFixed(1)}%)`) : '';
|
|
241
|
-
console.log(`${cyan(`#${r.id}`)} ${r.content}${score}`);
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
case 'list': {
|
|
248
|
-
const memories = await db.list();
|
|
249
|
-
if (!memories.length) {
|
|
250
|
-
console.log(dim('No memories stored.'));
|
|
251
|
-
} else {
|
|
252
|
-
memories.forEach(m => {
|
|
253
|
-
const ts = new Date(m.ts).toLocaleString();
|
|
254
|
-
console.log(`${cyan(`#${m.id}`)} ${m.content} ${dim(ts)}`);
|
|
255
|
-
});
|
|
256
|
-
console.log(dim(`\n${memories.length} total`));
|
|
257
|
-
}
|
|
258
|
-
break;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
case 'clear': {
|
|
262
|
-
const { count } = await db.clear();
|
|
263
|
-
console.log(yellow('⚠') + ` Cleared ${count} ${count === 1 ? 'memory' : 'memories'}`);
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
case 'stats': {
|
|
268
|
-
const s = await db.stats();
|
|
269
|
-
console.log(bold('Mumpix stats'));
|
|
270
|
-
console.log(` path: ${s.path}`);
|
|
271
|
-
console.log(` consistency: ${cyan(s.consistency)}`);
|
|
272
|
-
console.log(` records: ${s.records}`);
|
|
273
|
-
console.log(` size: ${(s.sizeBytes / 1024).toFixed(2)} KB`);
|
|
274
|
-
console.log(` created: ${new Date(s.created).toLocaleString()}`);
|
|
275
|
-
console.log(` version: v${s.version}`);
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
case 'audit': {
|
|
280
|
-
let entries;
|
|
281
|
-
try {
|
|
282
|
-
entries = await db.audit();
|
|
283
|
-
} catch (err) {
|
|
284
|
-
console.error(red('Error: ') + err.message);
|
|
285
|
-
process.exit(1);
|
|
286
|
-
}
|
|
287
|
-
if (!entries.length) {
|
|
288
|
-
console.log(dim('Audit log is empty.'));
|
|
289
|
-
} else {
|
|
290
|
-
entries.forEach(e => {
|
|
291
|
-
const ts = new Date(e.ts).toISOString();
|
|
292
|
-
const type = e._type.padEnd(12);
|
|
293
|
-
const detail = e._type === 'write' ? `id=${e.id} hash=${e.hash}`
|
|
294
|
-
: e._type === 'recall' ? `queryHash=${e.queryHash} resultId=${e.resultId ?? 'null'} latency=${e.latencyMs}ms`
|
|
295
|
-
: e._type === 'clear' ? `count=${e.count}`
|
|
296
|
-
: '';
|
|
297
|
-
console.log(`${dim(ts)} ${yellow(type)} ${detail}`);
|
|
298
|
-
});
|
|
299
|
-
console.log(dim(`\n${entries.length} entries`));
|
|
300
|
-
}
|
|
301
|
-
break;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
case 'shell': {
|
|
305
|
-
await runShell(db, filePath, consistency);
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
default:
|
|
310
|
-
console.error(red(`Unknown command: ${command}`));
|
|
311
|
-
console.log(USAGE);
|
|
312
|
-
process.exit(1);
|
|
313
|
-
}
|
|
314
|
-
} finally {
|
|
315
|
-
if (command !== 'shell') await db.close();
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async function runShell(db, filePath, consistency) {
|
|
320
|
-
const rl = readline.createInterface({
|
|
321
|
-
input: process.stdin,
|
|
322
|
-
output: process.stdout,
|
|
323
|
-
prompt: cyan('mumpix') + dim(' › '),
|
|
324
|
-
historySize: 100,
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
console.log(bold('Mumpix interactive shell'));
|
|
328
|
-
console.log(dim(` file: ${filePath} consistency: ${consistency}`));
|
|
329
|
-
console.log(dim(' Commands: remember("…"), recall("…"), list(), clear(), stats(), audit(), exit\n'));
|
|
330
|
-
|
|
331
|
-
rl.prompt();
|
|
332
|
-
|
|
333
|
-
rl.on('line', async (line) => {
|
|
334
|
-
const raw = line.trim();
|
|
335
|
-
if (!raw) { rl.prompt(); return; }
|
|
336
|
-
if (raw === 'exit' || raw === 'quit' || raw === '.exit') {
|
|
337
|
-
console.log(dim('bye'));
|
|
338
|
-
rl.close();
|
|
339
|
-
await db.close();
|
|
340
|
-
process.exit(0);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const match = raw.match(/^(\w+)\s*\((.*)?\)$/s);
|
|
344
|
-
if (!match) {
|
|
345
|
-
console.log(red('Syntax error') + dim(' — try: remember("…") or recall("…")'));
|
|
346
|
-
rl.prompt();
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const [, fn, argsRaw] = match;
|
|
351
|
-
const strArg = (s => {
|
|
352
|
-
const m = (s || '').trim().match(/^["'`]([\s\S]*)["'`]$/);
|
|
353
|
-
return m ? m[1] : null;
|
|
354
|
-
})(argsRaw);
|
|
355
|
-
|
|
356
|
-
try {
|
|
357
|
-
let result;
|
|
358
|
-
switch (fn) {
|
|
359
|
-
case 'remember':
|
|
360
|
-
if (strArg === null) throw new Error('remember() expects a string');
|
|
361
|
-
result = await db.remember(strArg);
|
|
362
|
-
console.log(green('←') + ' ' + JSON.stringify(result));
|
|
363
|
-
break;
|
|
364
|
-
case 'recall':
|
|
365
|
-
if (strArg === null) throw new Error('recall() expects a string');
|
|
366
|
-
result = await db.recall(strArg);
|
|
367
|
-
console.log(green('←') + ' ' + (result === null ? dim('null') : JSON.stringify(result)));
|
|
368
|
-
break;
|
|
369
|
-
case 'list':
|
|
370
|
-
result = await db.list();
|
|
371
|
-
if (!result.length) console.log(dim('[]'));
|
|
372
|
-
else result.forEach(m => console.log(` ${cyan(`#${m.id}`)} ${m.content}`));
|
|
373
|
-
break;
|
|
374
|
-
case 'clear':
|
|
375
|
-
result = await db.clear();
|
|
376
|
-
console.log(green('←') + ' ' + JSON.stringify(result));
|
|
377
|
-
break;
|
|
378
|
-
case 'stats':
|
|
379
|
-
result = await db.stats();
|
|
380
|
-
console.log(green('←') + ' ' + JSON.stringify(result, null, 2));
|
|
381
|
-
break;
|
|
382
|
-
case 'audit':
|
|
383
|
-
result = await db.audit();
|
|
384
|
-
if (!result.length) console.log(dim('[]'));
|
|
385
|
-
else result.forEach(e => console.log(' ' + JSON.stringify(e)));
|
|
386
|
-
break;
|
|
387
|
-
default:
|
|
388
|
-
console.log(red(`Unknown: db.${fn}`));
|
|
389
|
-
}
|
|
390
|
-
} catch (err) {
|
|
391
|
-
console.log(red('Error: ') + err.message);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
rl.prompt();
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
rl.on('close', async () => {
|
|
398
|
-
await db.close();
|
|
399
|
-
process.exit(0);
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
main().catch(err => {
|
|
404
|
-
console.error(err.message);
|
|
405
|
-
process.exit(1);
|
|
406
|
-
});
|
|
2
|
+
"use strict";require("path");const e=require("readline"),{Mumpix:o}=require("../src/index"),{loadAuthState:t,clearAuthState:n,upsertStoredLicense:s,exchangeTokenForLicense:c,loginWithDeviceFlow:l,authStatePath:r,configDir:i}=require("../src/core/auth"),{LicenseManager:a}=require("../src/core/license"),g='\nmumpix \u2014 SQLite for AI\n\nUsage:\n mumpix <command> <file> [args...]\n\nCommands:\n remember <file> "<text>" Store a memory\n recall <file> "<query>" Recall the best match\n search <file> "<query>" [k] Recall top-k matches\n list <file> List all memories\n clear <file> Clear all memories\n stats <file> Show database stats\n audit <file> Show audit log (verified mode)\n shell <file> Start interactive REPL\n auth <subcommand> Account login/logout/status\n help Show this message\n\nOptions (append to any command):\n --consistency=eventual|strict|verified (default: eventual)\n\nExamples:\n mumpix remember ./agent.mumpix "User prefers TypeScript"\n mumpix recall ./agent.mumpix "what language?" --consistency=strict\n mumpix search ./agent.mumpix "TypeScript" 3\n mumpix shell ./agent.mumpix --consistency=verified\n mumpix auth status\n mumpix auth device-id\n mumpix auth login --token=<account-token>\n mumpix auth login --license=<signed-license-key>\n'.trim();function u(e,o){return process.stdout.isTTY?`\x1b[${o}m${e}\x1b[0m`:e}const m=e=>u(e,"2"),p=e=>u(e,"36"),d=e=>u(e,"32"),h=e=>u(e,"33"),$=e=>u(e,"31"),f=e=>u(e,"1");function y(e){if(!e)return"-";const o=new Date(Number(e));return Number.isNaN(o.getTime())?"-":o.toISOString()}async function x(e,o){const g=String(e[0]||"status").toLowerCase();if("status"===g){const e=t();return e&&e.license&&e.license.key?(console.log(f("Mumpix auth status")),console.log(` account_id: ${e.account&&e.account.id?e.account.id:"-"}`),console.log(` tier: ${e.license.tier||e.account&&e.account.tier||"-"}`),console.log(` issued_at: ${y(e.license.iat)}`),console.log(` expires_at: ${y(e.license.exp)}`),console.log(` license: ${d(function(e,o=6){const t=String(e||"");return t.length<=o?t:`${t.slice(0,o)}\u2026`}(e.license.key,18))}`),void console.log(` state: ${r()}`)):(console.log(m("Not logged in.")),void console.log(m(`Config dir: ${i()}`)))}if("logout"===g)return n(),void console.log(d("\u2713")+" Logged out. Local license removed.");if("device-id"===g||"device"===g||"fingerprint"===g){const e=new a,o=await e.deviceIdentityInfo();return console.log(f("Mumpix device identity")),console.log(` algorithm: ${o.algorithm}`),console.log(` fingerprint: ${d(o.publicKeyFingerprint)}`),console.log(` public_key: ${o.publicKeyB64}`),void console.log(` state: ${o.path}`)}if("login"===g){const e=o.license||o["license-key"]||null;if(e){const o=s(String(e));return console.log(d("\u2713")+" License saved."),console.log(` tier: ${o.license.tier||"-"}`),console.log(` expires_at: ${y(o.license.exp)}`),void console.log(` state: ${r()}`)}const t=o.token||process.env.MUMPIX_AUTH_TOKEN||"";if(t){const e=await c(String(t).trim(),{});return console.log(d("\u2713")+" Account linked and license saved."),console.log(` account_id: ${e.account.id||"-"}`),console.log(` tier: ${e.license.tier||e.account.tier||"-"}`),console.log(` expires_at: ${y(e.license.exp)}`),void console.log(` state: ${r()}`)}const n=await l({onPrompt:({userCode:e,verifyUrl:o,expiresInSec:t,intervalSec:n})=>{console.log(f("Mumpix device login")),console.log(` 1) Open: ${o}`),console.log(` 2) Enter code: ${p(e)}`),console.log(` 3) Waiting for approval... (expires in ${t}s, polling ${n}s)`)}});return console.log(d("\u2713")+" Account linked and license saved."),console.log(` account_id: ${n.account.id||"-"}`),console.log(` tier: ${n.license.tier||n.account.tier||"-"}`),console.log(` expires_at: ${y(n.license.exp)}`),void console.log(` state: ${r()}`)}console.error($(`Unknown auth subcommand: ${g}`)),console.log("Usage: mumpix auth <status|login|logout|device-id> [--token=...] [--license=...]"),process.exit(1)}(async function(){const{args:t,flags:n}=function(e){const o=[],t={};for(const n of e)if(n.startsWith("--")){const[e,o]=n.slice(2).split("=");t[e]=void 0===o||o}else o.push(n);return{args:o,flags:t}}(process.argv.slice(2)),[s,c,...l]=t;if(s&&"help"!==s&&"--help"!==s&&"-h"!==s||(console.log(g),process.exit(0)),"auth"===s)return void await x([c,...l],n);const r=c;r||"help"===s||(console.error($("Error: file path required")),console.log(g),process.exit(1));const i=n.consistency||"eventual";let a;try{a=await o.open(r,{consistency:i})}catch(e){console.error($(`Error opening ${r}: ${e.message}`)),process.exit(1)}try{switch(s){case"remember":{const e=l.join(" ").replace(/^["']|["']$/g,"");e||(console.error($("Error: provide text to remember")),process.exit(1));const o=await a.remember(e);console.log(d("\u2713")+` Stored as #${o.id} (${o.consistency})`);break}case"recall":{const e=l.join(" ").replace(/^["']|["']$/g,"");e||(console.error($("Error: provide a query")),process.exit(1));const o=await a.recall(e);null===o?console.log(m("No memories found.")):console.log(d("\u2192")+" "+o);break}case"search":{const e=parseInt(l[l.length-1],10),o=Number.isInteger(e)&&e>0?e:5,t=(Number.isInteger(e)?l.slice(0,-1):l).join(" ").replace(/^["']|["']$/g,"");t||(console.error($("Error: provide a query")),process.exit(1));const n=await a.recallMany(t,o);n.length?n.forEach((e,o)=>{const t=void 0!==e.score?m(` (${(100*e.score).toFixed(1)}%)`):"";console.log(`${p(`#${e.id}`)} ${e.content}${t}`)}):console.log(m("No memories found."));break}case"list":{const e=await a.list();e.length?(e.forEach(e=>{const o=new Date(e.ts).toLocaleString();console.log(`${p(`#${e.id}`)} ${e.content} ${m(o)}`)}),console.log(m(`\n${e.length} total`))):console.log(m("No memories stored."));break}case"clear":{const{count:e}=await a.clear();console.log(h("\u26a0")+` Cleared ${e} ${1===e?"memory":"memories"}`);break}case"stats":{const e=await a.stats();console.log(f("Mumpix stats")),console.log(` path: ${e.path}`),console.log(` consistency: ${p(e.consistency)}`),console.log(` records: ${e.records}`),console.log(` size: ${(e.sizeBytes/1024).toFixed(2)} KB`),console.log(` created: ${new Date(e.created).toLocaleString()}`),console.log(` version: v${e.version}`);break}case"audit":{let e;try{e=await a.audit()}catch(e){console.error($("Error: ")+e.message),process.exit(1)}e.length?(e.forEach(e=>{const o=new Date(e.ts).toISOString(),t=e._type.padEnd(12),n="write"===e._type?`id=${e.id} hash=${e.hash}`:"recall"===e._type?`queryHash=${e.queryHash} resultId=${e.resultId??"null"} latency=${e.latencyMs}ms`:"clear"===e._type?`count=${e.count}`:"";console.log(`${m(o)} ${h(t)} ${n}`)}),console.log(m(`\n${e.length} entries`))):console.log(m("Audit log is empty."));break}case"shell":await async function(o,t,n){const s=e.createInterface({input:process.stdin,output:process.stdout,prompt:p("mumpix")+m(" \u203a "),historySize:100});console.log(f("Mumpix interactive shell")),console.log(m(` file: ${t} consistency: ${n}`)),console.log(m(' Commands: remember("\u2026"), recall("\u2026"), list(), clear(), stats(), audit(), exit\n')),s.prompt(),s.on("line",async e=>{const t=e.trim();if(!t)return void s.prompt();"exit"!==t&&"quit"!==t&&".exit"!==t||(console.log(m("bye")),s.close(),await o.close(),process.exit(0));const n=t.match(/^(\w+)\s*\((.*)?\)$/s);if(!n)return console.log($("Syntax error")+m(' \u2014 try: remember("\u2026") or recall("\u2026")')),void s.prompt();const[,c,l]=n,r=(e=>{const o=(e||"").trim().match(/^["'`]([\s\S]*)["'`]$/);return o?o[1]:null})(l);try{let e;switch(c){case"remember":if(null===r)throw new Error("remember() expects a string");e=await o.remember(r),console.log(d("\u2190")+" "+JSON.stringify(e));break;case"recall":if(null===r)throw new Error("recall() expects a string");e=await o.recall(r),console.log(d("\u2190")+" "+(null===e?m("null"):JSON.stringify(e)));break;case"list":e=await o.list(),e.length?e.forEach(e=>console.log(` ${p(`#${e.id}`)} ${e.content}`)):console.log(m("[]"));break;case"clear":e=await o.clear(),console.log(d("\u2190")+" "+JSON.stringify(e));break;case"stats":e=await o.stats(),console.log(d("\u2190")+" "+JSON.stringify(e,null,2));break;case"audit":e=await o.audit(),e.length?e.forEach(e=>console.log(" "+JSON.stringify(e))):console.log(m("[]"));break;default:console.log($(`Unknown: db.${c}`))}}catch(e){console.log($("Error: ")+e.message)}s.prompt()}),s.on("close",async()=>{await o.close(),process.exit(0)})}(a,r,i);break;default:console.error($(`Unknown command: ${s}`)),console.log(g),process.exit(1)}}finally{"shell"!==s&&await a.close()}})().catch(e=>{console.error(e.message),process.exit(1)});
|
package/examples/agent-memory.js
CHANGED
|
@@ -17,7 +17,7 @@ const path = require('path');
|
|
|
17
17
|
const DB_PATH = path.join(__dirname, 'agent-memory.mumpix');
|
|
18
18
|
|
|
19
19
|
;(async () => {
|
|
20
|
-
const db = Mumpix.open(DB_PATH, { consistency: '
|
|
20
|
+
const db = await Mumpix.open(DB_PATH, { consistency: 'eventual' });
|
|
21
21
|
const { records } = await db.stats();
|
|
22
22
|
|
|
23
23
|
if (records === 0) {
|
package/examples/basic.js
CHANGED
|
@@ -13,7 +13,7 @@ const path = require('path');
|
|
|
13
13
|
|
|
14
14
|
;(async () => {
|
|
15
15
|
const dbPath = path.join(os.tmpdir(), 'mumpix-basic-demo.mumpix');
|
|
16
|
-
const db = Mumpix.open(dbPath, { consistency: '
|
|
16
|
+
const db = await Mumpix.open(dbPath, { consistency: 'eventual' });
|
|
17
17
|
|
|
18
18
|
// Store memories
|
|
19
19
|
await db.remember('User prefers TypeScript over JavaScript');
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { brp, rlp, collapse } = require('../src');
|
|
4
|
+
|
|
5
|
+
const gene = brp.normalizeBRP({
|
|
6
|
+
domain: 'browser',
|
|
7
|
+
trigger_signature: 'login page asks for workspace slug',
|
|
8
|
+
executable_payload: {
|
|
9
|
+
intent: 'DO',
|
|
10
|
+
sequence: [
|
|
11
|
+
{ verb: 'input-text', args: { selector: '#workspace', value: 'acme' } },
|
|
12
|
+
{ verb: 'click-element', args: { selector: 'button[type=submit]' } },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const updated = brp.updateSplitConfidence(gene, {
|
|
18
|
+
triggerMatched: true,
|
|
19
|
+
sequenceExecuted: true,
|
|
20
|
+
breakEvenThreshold: 3,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const match = brp.twoStageMatch([updated], {
|
|
24
|
+
domain: 'browser',
|
|
25
|
+
text: 'workspace login form',
|
|
26
|
+
payload_type: 'DO',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const actionBoundary = rlp.validateActionBoundary(updated);
|
|
30
|
+
|
|
31
|
+
const economics = collapse.analyzeCollapse({
|
|
32
|
+
stages: [
|
|
33
|
+
{ name: 'INDEX', token_cost: 200 },
|
|
34
|
+
{ name: 'SCAN', token_cost: 2400 },
|
|
35
|
+
{ name: 'DEBATE', token_cost: 7200 },
|
|
36
|
+
{ name: 'EXECUTE', token_cost: 2050 },
|
|
37
|
+
],
|
|
38
|
+
retrievalCost: 150,
|
|
39
|
+
promotionCost: 35550,
|
|
40
|
+
hits: 3,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log({
|
|
44
|
+
brp_id: updated.brp_id,
|
|
45
|
+
payload_type: updated.payload_type,
|
|
46
|
+
action_ok: actionBoundary.ok,
|
|
47
|
+
top_match: match[0] && match[0].brp.brp_id,
|
|
48
|
+
savings_per_hit: economics.savingsPerHit,
|
|
49
|
+
break_even_crossed: economics.breakEvenCrossed,
|
|
50
|
+
});
|
|
@@ -27,7 +27,7 @@ const DB_PATH = path.join(os.tmpdir(), 'mumpix-verified-demo.mumpix');
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
console.log('Opening Mumpix in Verified mode...\n');
|
|
30
|
-
const db = Mumpix.open(DB_PATH, { consistency: 'verified' });
|
|
30
|
+
const db = await Mumpix.open(DB_PATH, { consistency: 'verified' });
|
|
31
31
|
|
|
32
32
|
// Simulate a compliance-relevant workflow
|
|
33
33
|
await db.remember('Loan application #4821 approved — credit score: 742');
|
package/package.json
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mumpix",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29",
|
|
4
4
|
"description": "MumpixDB reasoning ledger and structured memory engine for AI systems",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mumpix": "bin/mumpix.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"postinstall": "node ./scripts/postinstall-auth.js",
|
|
12
|
-
"verify:claims": "node ./scripts/verify-claims.cjs",
|
|
13
|
-
"release:publish-and-deprecate": "node ./scripts/publish-and-deprecate.cjs",
|
|
14
|
-
"release:clean": "bash ./scripts/release-clean.sh",
|
|
15
|
-
"release:pack": "npm run build && npm run release:clean && node ./scripts/obfuscate.cjs && npm pack --cache /tmp/mumpix-npm-cache ; node ./scripts/restore.cjs"
|
|
10
|
+
"test:license-modes": "node ./scripts/test-license-modes.cjs"
|
|
16
11
|
},
|
|
17
12
|
"keywords": [
|
|
18
13
|
"ai",
|
|
@@ -48,16 +43,25 @@
|
|
|
48
43
|
"engines": {
|
|
49
44
|
"node": ">=18.0.0"
|
|
50
45
|
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@langchain/core": ">=1.1.49",
|
|
48
|
+
"llamaindex": ">=0.12.1"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@langchain/core": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"llamaindex": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
51
58
|
"files": [
|
|
52
59
|
"src/",
|
|
53
60
|
"bin/",
|
|
54
|
-
"scripts/
|
|
55
|
-
"examples
|
|
61
|
+
"scripts/test-license-modes.cjs",
|
|
62
|
+
"examples/*.js",
|
|
56
63
|
"CHANGELOG.md",
|
|
57
64
|
"README.md",
|
|
58
65
|
"LICENSE"
|
|
59
|
-
]
|
|
60
|
-
"devDependencies": {
|
|
61
|
-
"javascript-obfuscator": "^5.4.1"
|
|
62
|
-
}
|
|
66
|
+
]
|
|
63
67
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
const { Mumpix } = require('../src');
|
|
10
|
+
const { LicenseManager } = require('../src/core/license');
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mumpix-license-modes-'));
|
|
14
|
+
if (!process.env.MUMPIX_CONFIG_DIR) {
|
|
15
|
+
process.env.MUMPIX_CONFIG_DIR = path.join(tempRoot, 'config');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (typeof globalThis.crypto === 'undefined') {
|
|
19
|
+
globalThis.crypto = require('node:crypto').webcrypto;
|
|
20
|
+
}
|
|
21
|
+
const { ml_dsa44 } = await import('file://' + path.resolve(__dirname, '..', 'src/core/ml-dsa.mjs'));
|
|
22
|
+
|
|
23
|
+
const issuer = ml_dsa44.keygen();
|
|
24
|
+
process.env.MUMPIX_LICENSE_PUBLIC_KEY_B64 = Buffer.from(issuer.publicKey).toString('base64');
|
|
25
|
+
|
|
26
|
+
const lm = new LicenseManager();
|
|
27
|
+
const device = await lm.deviceIdentityInfo();
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
const payload = {
|
|
30
|
+
id: 'local-test-user',
|
|
31
|
+
tier: 'pro',
|
|
32
|
+
iat: now,
|
|
33
|
+
exp: now + 30 * 24 * 60 * 60 * 1000,
|
|
34
|
+
dpk: device.publicKeyFingerprint,
|
|
35
|
+
issuer: 'local-ml-dsa-test',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const payloadB64 = Buffer.from(JSON.stringify(payload)).toString('base64');
|
|
39
|
+
const signature = ml_dsa44.sign(Buffer.from(payloadB64, 'utf8'), issuer.secretKey);
|
|
40
|
+
const licenseKey = `${payloadB64}.${Buffer.from(signature).toString('base64')}`;
|
|
41
|
+
const licenseSha256 = crypto.createHash('sha256').update(licenseKey).digest('hex');
|
|
42
|
+
|
|
43
|
+
console.log('generated_license');
|
|
44
|
+
console.log(` tier=${payload.tier}`);
|
|
45
|
+
console.log(` exp=${new Date(payload.exp).toISOString()}`);
|
|
46
|
+
console.log(` device=${payload.dpk}`);
|
|
47
|
+
console.log(` license_sha256=${licenseSha256}`);
|
|
48
|
+
console.log(` license_key=${licenseKey}`);
|
|
49
|
+
|
|
50
|
+
const modes = ['eventual', 'strict', 'verified'];
|
|
51
|
+
const results = [];
|
|
52
|
+
for (const mode of modes) {
|
|
53
|
+
const dbPath = path.join(os.tmpdir(), `mumpix-${mode}-${Date.now()}-${crypto.randomBytes(4).toString('hex')}.mumpix`);
|
|
54
|
+
for (const suffix of ['', '.wal', '.lock', '.audit']) {
|
|
55
|
+
try { fs.unlinkSync(dbPath + suffix); } catch (_) {}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const db = await Mumpix.open(dbPath, { consistency: mode, licenseKey });
|
|
59
|
+
await db.remember(`Mode ${mode} remembers signed license verification`);
|
|
60
|
+
const recalled = await db.recall('signed license verification');
|
|
61
|
+
const stats = await db.stats();
|
|
62
|
+
let auditCount = null;
|
|
63
|
+
if (mode === 'verified') {
|
|
64
|
+
auditCount = (await db.audit()).length;
|
|
65
|
+
}
|
|
66
|
+
await db.close();
|
|
67
|
+
|
|
68
|
+
results.push({
|
|
69
|
+
mode,
|
|
70
|
+
effective: db.consistency,
|
|
71
|
+
records: stats.records,
|
|
72
|
+
recall: recalled ? 'ok' : 'missing',
|
|
73
|
+
auditCount,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log('mode_results');
|
|
78
|
+
for (const result of results) {
|
|
79
|
+
const audit = result.auditCount == null ? '' : ` audit=${result.auditCount}`;
|
|
80
|
+
console.log(` ${result.mode}: effective=${result.effective} records=${result.records} recall=${result.recall}${audit}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
main().catch((error) => {
|
|
85
|
+
console.error(error && error.stack ? error.stack : error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
package/src/brp/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const e=require("crypto"),r=["active","probationary","archived","fossilized"],t=["DO","PREFER"],n=["fresh_promotion","refined_from","trigger_refresh"],o=["navigate","read-dom","input-text","click-element","extract-kv","wait-for-state","scroll-page","compress-context","read-local-state"];function i(r="brp"){const t=e.randomUUID?e.randomUUID():e.randomBytes(16).toString("hex");return`${r}_${String(t).replace(/-/g,"").slice(0,16)}`}function a(e){return String(e||"").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)}function s(e){if(e&&"object"==typeof e)return e;if("string"!=typeof e||!e.trim())throw new Error("executable_payload is empty or null.");try{return JSON.parse(e)}catch{throw new Error("executable_payload failed JSON parse.")}}class c{constructor(e=o){this._verbs=new Map;for(const r of e)this.register(r)}register(e,r=null){const t=String(e||"").trim();if(!t)throw new Error("verb name is required");return this._verbs.set(t,r||!0),this}has(e){return this._verbs.has(String(e||"").trim())}list(){return Array.from(this._verbs.keys()).sort()}}function u(e,r={}){const n=r.verbRegistry||new c(r.verbs||o),i=s(e);if(!i||"object"!=typeof i)throw new Error("executable_payload must parse to an object.");if(!t.includes(i.intent))throw new Error("executable_payload intent must be DO or PREFER.");if("DO"===i.intent){if(!Array.isArray(i.sequence)||0===i.sequence.length)throw new Error("DO payload has empty sequence.");for(const e of i.sequence){if(!e||"object"!=typeof e)throw new Error("DO payload step must be an object.");if(!n.has(e.verb))throw new Error(`Unknown verb: ${e.verb}`);if(null!=e.args&&("object"!=typeof e.args||Array.isArray(e.args)))throw new Error(`DO payload step args must be an object for verb: ${e.verb}`)}}if("PREFER"===i.intent){if("string"!=typeof i.injected_context||!i.injected_context.trim())throw new Error("PREFER payload requires injected_context.");if(null!=i.negative_constraints&&!Array.isArray(i.negative_constraints))throw new Error("PREFER negative_constraints must be an array when present.")}return i}function g(e,t={}){try{if(!e||"object"!=typeof e)throw new Error("BRP candidate must be an object.");if(!e.domain)throw new Error("BRP must declare a domain.");if(!e.trigger_signature)throw new Error("BRP must declare a trigger_signature.");const n=u(e.executable_payload,t);if(e.status&&!r.includes(e.status))throw new Error(`Unknown BRP status: ${e.status}`);return{ok:!0,payload:n,payload_type:n.intent,warnings:[]}}catch(e){return{ok:!1,error:e.message,warnings:[]}}}function _(e,r={}){const t=r.domain?String(r.domain):null,n=r.statuses||["active","probationary"];return e.filter(e=>(!t||e.domain===t)&&(!(n&&!n.includes(e.status))&&(!r.payload_type||e.payload_type===r.payload_type)))}function d(e,r){const t=new Set(a(r));if(!t.size)return 0;const n=a(`${e.trigger_signature} ${e.domain} ${e.payload_type}`);let o=0;for(const e of n)t.has(e)&&(o+=1);return o+(Number(e.trigger_confidence||0)+Number(e.sequence_confidence||0))/2}module.exports={CORE_ACTION_VERBS:o,GENE_STATUSES:r,PAYLOAD_TYPES:t,PROVENANCE_TYPES:n,VerbRegistry:c,parseExecutablePayload:s,validatePayload:u,validateBRP:g,normalizeBRP:function(e,r={}){const t=g(e,r);if(!t.ok)throw new Error(t.error);const o=(new Date).toISOString(),a=t.payload;return{brp_id:e.brp_id||i("brp"),domain:String(e.domain),status:e.status||"active",trigger_signature:String(e.trigger_signature),trigger_embedding:Array.isArray(e.trigger_embedding)?e.trigger_embedding.map(Number):[],preconditions:e.preconditions&&"object"==typeof e.preconditions?{...e.preconditions}:{},executable_payload:"string"==typeof e.executable_payload?e.executable_payload:JSON.stringify(e.executable_payload),payload_type:a.intent,sequence_execution_count:Number(e.sequence_execution_count||0),sequence_confidence:Number.isFinite(Number(e.sequence_confidence))?Number(e.sequence_confidence):1,trigger_match_count:Number(e.trigger_match_count||0),trigger_confidence:Number.isFinite(Number(e.trigger_confidence))?Number(e.trigger_confidence):.5,trigger_version:Number(e.trigger_version||1),break_even_crossed:Boolean(e.break_even_crossed),created_at:e.created_at||o,status_changed_at:e.status_changed_at||o,...e.retirement_reason?{retirement_reason:String(e.retirement_reason)}:{},provenance:n.includes(e.provenance)?e.provenance:"fresh_promotion"}},updateSplitConfidence:function(e,r={}){const t={...e};r.triggerMatched&&(t.trigger_match_count=Number(t.trigger_match_count||0)+1,t.trigger_confidence=Math.min(1,Number(t.trigger_confidence||0)+.05)),r.triggerDrift&&(t.trigger_confidence=Math.max(0,Number(t.trigger_confidence||0)-.15),t.trigger_version=Number(t.trigger_version||1)+1),r.sequenceExecuted&&(t.sequence_execution_count=Number(t.sequence_execution_count||0)+1,t.sequence_confidence=Math.min(1,Number(t.sequence_confidence||0)+.03)),r.sequenceFailed&&(t.sequence_confidence=Math.max(0,Number(t.sequence_confidence||0)-.2));const n=Number.isFinite(Number(r.breakEvenThreshold))?Number(r.breakEvenThreshold):3;return t.break_even_crossed=Number(t.sequence_execution_count||0)>=n,t},transitionStatus:function(e,t,n=""){if(!r.includes(t))throw new Error(`Unknown BRP status: ${t}`);return{...e,status:t,status_changed_at:(new Date).toISOString(),...n?{retirement_reason:String(n)}:{}}},structuralPrefilter:_,twoStageMatch:function(e,r={},t={}){const n=_(e,r),o=r.text||r.trigger_signature||"",i=Number(t.k||r.k||5);return n.map(e=>({brp:e,score:d(e,o)})).sort((e,r)=>r.score-e.score).slice(0,i)}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function e(e){return"number"==typeof e?e:e&&"object"==typeof e&&Number(e.token_cost??e.tokens??e.cost??0)||0}function r(r=[]){if(!Array.isArray(r))throw new TypeError("graphCost() expects an array of stages or costs");return r.reduce((r,t)=>r+e(t),0)}function t(e=[],t={}){const o=Number.isFinite(Number(t.cycleCost))?Number(t.cycleCost):r(e),s=Number.isFinite(Number(t.retrievalCost))?Number(t.retrievalCost):150;return Math.max(0,o-s)}function o(e,r){const t=Number(e),o=Number(r);if(!Number.isFinite(t)||t<0)throw new TypeError("promotionCost must be a non-negative number");if(!Number.isFinite(o)||o<=0)throw new TypeError("cycleCost must be a positive number");return t/o}function s(e,r){const t=Number(e),o=Number(r);return!Number.isFinite(t)||!Number.isFinite(o)||o<=0?null:(t-o)/o}module.exports={DEFAULT_RETRIEVAL_COST:150,stageCost:e,graphCost:r,collapseSavings:t,breakEvenReuseThreshold:o,beta:s,analyzeCollapse:function(e={}){const i=e.stages||[],n=Number.isFinite(Number(e.cycleCost))?Number(e.cycleCost):r(i),u=Number.isFinite(Number(e.retrievalCost))?Number(e.retrievalCost):150,b=Number.isFinite(Number(e.promotionCost))?Number(e.promotionCost):3*n,m=o(b,n||1),a=t([],{cycleCost:n,retrievalCost:u}),c=Number(e.hits||1);return{cycleCost:n,promotionCost:b,retrievalCost:u,savingsPerHit:a,hits:c,totalSavings:a*c,breakEvenReuseThreshold:m,beta:s(b,n),breakEvenCrossed:c>=m}}};
|