enigma-memory 0.1.4 → 0.1.6
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/README.md +43 -35
- package/apps/cli/bin/enigma.mjs +662 -67
- package/docs/benchmark-reproducibility.md +122 -26
- package/docs/developer-ecosystem.md +85 -8
- package/docs/memory-benchmarks.md +41 -9
- package/docs/sdk-api.md +1 -1
- package/examples/ci/github-actions.yml +27 -1
- package/package.json +5 -1
- package/packages/mcp-server/src/index.js +1 -1
- package/scripts/build-installer-assets.mjs +1 -1
- package/scripts/download-standard-benchmarks.mjs +399 -0
- package/scripts/run-standard-memory-benchmarks.mjs +1070 -0
package/apps/cli/bin/enigma.mjs
CHANGED
|
@@ -11,13 +11,17 @@ import { runBoundarySimulation } from '../../../packages/boundary/src/index.js';
|
|
|
11
11
|
import { startStdioServer } from '../../../packages/mcp-server/src/index.js';
|
|
12
12
|
import { runMeshDemo } from '../../../packages/mesh/src/index.js';
|
|
13
13
|
import { runEnterpriseDemo } from '../../../packages/enterprise/src/index.js';
|
|
14
|
-
import { connectClient, disconnectClient, doctorConnectors, getClientProfile, renderMcpConfig, supportedClients } from '../../../packages/connectors/src/index.js';
|
|
14
|
+
import { connectClient, disconnectClient, doctorConnectors, getClientProfile, planConnectWizard, renderMcpConfig, supportedClients } from '../../../packages/connectors/src/index.js';
|
|
15
15
|
import { exportEnigmaCapsule, importChatGptExport, importClaudeMemory, importEnigmaCapsule, importLangGraphStore, importLettaAgentFile, importMem0Export, importZepGraphitiExport } from '../../../packages/importers/src/index.js';
|
|
16
16
|
import * as relayServer from '../../relay/src/server.mjs';
|
|
17
17
|
import * as gatewayServer from '../../gateway/src/server.mjs';
|
|
18
18
|
import { verifyBundle } from '../../verifier/bin/enigma-verify.mjs';
|
|
19
19
|
import { createNativeHostInstallPlan, createNativeHostManifest } from '../../native-host/bin/enigma-native-host.mjs';
|
|
20
20
|
import { aggregateUsageEvents, createUsageEvent } from '../../../packages/metering/src/index.js';
|
|
21
|
+
import {
|
|
22
|
+
createMemoryAccessReceipt,
|
|
23
|
+
createMemoryOptimizationPlan,
|
|
24
|
+
} from '../../../packages/optimizer/src/index.js';
|
|
21
25
|
import {
|
|
22
26
|
createConsumerGpuCapacityProfile,
|
|
23
27
|
createOperatorServiceQuote,
|
|
@@ -33,6 +37,21 @@ export const DEFAULT_GATEWAY_PORT = 8797;
|
|
|
33
37
|
const DEFAULT_QUICKSTART_MEMORY = 'Enigma quickstart demo memory: local proof bundles can be created and verified without provider or cloud credentials.';
|
|
34
38
|
const DEFAULT_CROSS_MODEL_DEMO_BUNDLE = '.enigma/cross-model-demo-bundle.json';
|
|
35
39
|
const DEFAULT_CROSS_MODEL_MEMORY = 'Enigma cross-model demo memory: a local encrypted memory can be packaged for ChatGPT, Claude, Kimi, Cursor, and a local LLM without provider credentials.';
|
|
40
|
+
const DEFAULT_SETUP_CLIENTS = Object.freeze(['generic-mcp', 'claude-desktop', 'cursor', 'kimi-code']);
|
|
41
|
+
const SETUP_CLAIM_BOUNDARIES = Object.freeze({
|
|
42
|
+
local_only: true,
|
|
43
|
+
provider_credentials_required: false,
|
|
44
|
+
provider_native_memory_canonical: false,
|
|
45
|
+
provider_deletion_proof: false,
|
|
46
|
+
model_forgetting_proof: false,
|
|
47
|
+
roi_or_savings_guarantee: false,
|
|
48
|
+
compliance_certification: false,
|
|
49
|
+
});
|
|
50
|
+
const QUICKSTART_ARTIFACT_NAMES = Object.freeze({
|
|
51
|
+
contextPack: 'context-pack.json',
|
|
52
|
+
export: 'export.json',
|
|
53
|
+
verifyReport: 'verify-report.json',
|
|
54
|
+
});
|
|
36
55
|
const CROSS_MODEL_PROFILES = Object.freeze([
|
|
37
56
|
{ id: 'chatgpt', provider: 'chatgpt', model: 'chatgpt-mcp-profile', label: 'ChatGPT' },
|
|
38
57
|
{ id: 'claude', provider: 'claude', model: 'claude-mcp-profile', label: 'Claude' },
|
|
@@ -77,6 +96,19 @@ const IMPORTERS = Object.freeze({
|
|
|
77
96
|
|
|
78
97
|
export const REQUIRED_PACKAGE_BINS = Object.freeze(['enigma', 'enigma-verify', 'enigma-mcp', 'enigma-relay', 'enigma-gateway', 'enigma-native-host']);
|
|
79
98
|
|
|
99
|
+
function setFlagValue(flags, name, value) {
|
|
100
|
+
if (!flags.has(name)) {
|
|
101
|
+
flags.set(name, value);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const current = flags.get(name);
|
|
105
|
+
if (Array.isArray(current)) {
|
|
106
|
+
current.push(value);
|
|
107
|
+
} else {
|
|
108
|
+
flags.set(name, [current, value]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
80
112
|
function parseArgs(argv) {
|
|
81
113
|
const flags = new Map();
|
|
82
114
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -84,11 +116,11 @@ function parseArgs(argv) {
|
|
|
84
116
|
if (!arg.startsWith('--')) continue;
|
|
85
117
|
const eq = arg.indexOf('=');
|
|
86
118
|
if (eq !== -1) {
|
|
87
|
-
flags
|
|
119
|
+
setFlagValue(flags, arg.slice(2, eq), arg.slice(eq + 1));
|
|
88
120
|
} else if (!argv[i + 1] || argv[i + 1].startsWith('--')) {
|
|
89
|
-
flags
|
|
121
|
+
setFlagValue(flags, arg.slice(2), true);
|
|
90
122
|
} else {
|
|
91
|
-
flags
|
|
123
|
+
setFlagValue(flags, arg.slice(2), argv[i + 1]);
|
|
92
124
|
i += 1;
|
|
93
125
|
}
|
|
94
126
|
}
|
|
@@ -100,6 +132,19 @@ function getFlag(flags, names, fallback = undefined) {
|
|
|
100
132
|
return fallback;
|
|
101
133
|
}
|
|
102
134
|
|
|
135
|
+
function lastFlagValue(value) {
|
|
136
|
+
return Array.isArray(value) ? value[value.length - 1] : value;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function booleanFlag(flags, names, fallback = false) {
|
|
140
|
+
const value = lastFlagValue(getFlag(flags, names, fallback));
|
|
141
|
+
if (value === true || value === false) return value;
|
|
142
|
+
if (value === undefined || value === '') return fallback;
|
|
143
|
+
if (String(value) === 'true') return true;
|
|
144
|
+
if (String(value) === 'false') return false;
|
|
145
|
+
throw new Error(`--${names[0]} must be true or false.`);
|
|
146
|
+
}
|
|
147
|
+
|
|
103
148
|
function requireFlag(flags, names, label = names[0]) {
|
|
104
149
|
const value = getFlag(flags, names);
|
|
105
150
|
if (value === undefined || value === true || value === '') throw new Error(`Missing required --${label}.`);
|
|
@@ -166,7 +211,7 @@ async function fileExists(path) {
|
|
|
166
211
|
}
|
|
167
212
|
|
|
168
213
|
function pathFlag(flags, names, fallback) {
|
|
169
|
-
const value = getFlag(flags, names, fallback);
|
|
214
|
+
const value = lastFlagValue(getFlag(flags, names, fallback));
|
|
170
215
|
if (value === true || value === '') throw new Error(`Missing required --${names[0]}.`);
|
|
171
216
|
return String(value);
|
|
172
217
|
}
|
|
@@ -210,6 +255,74 @@ async function quickstartMemoryTextFromFlags(flags) {
|
|
|
210
255
|
return DEFAULT_QUICKSTART_MEMORY;
|
|
211
256
|
}
|
|
212
257
|
|
|
258
|
+
function quickstartOutputs(bundleInput, outDirInput) {
|
|
259
|
+
const bundlePath = resolve(bundleInput);
|
|
260
|
+
const outDirPath = resolve(outDirInput);
|
|
261
|
+
const contextPackPath = resolve(outDirPath, QUICKSTART_ARTIFACT_NAMES.contextPack);
|
|
262
|
+
const exportPath = resolve(outDirPath, QUICKSTART_ARTIFACT_NAMES.export);
|
|
263
|
+
const verifyReportPath = resolve(outDirPath, QUICKSTART_ARTIFACT_NAMES.verifyReport);
|
|
264
|
+
return {
|
|
265
|
+
bundlePath,
|
|
266
|
+
outDirPath,
|
|
267
|
+
contextPackPath,
|
|
268
|
+
exportPath,
|
|
269
|
+
verifyReportPath,
|
|
270
|
+
contextPackDisplay: quickstartPathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.contextPack),
|
|
271
|
+
exportDisplay: quickstartPathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.export),
|
|
272
|
+
verifyReportDisplay: quickstartPathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.verifyReport),
|
|
273
|
+
outputs: [
|
|
274
|
+
{ path: bundlePath, display: bundleInput },
|
|
275
|
+
{ path: contextPackPath, display: quickstartPathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.contextPack) },
|
|
276
|
+
{ path: exportPath, display: quickstartPathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.export) },
|
|
277
|
+
{ path: verifyReportPath, display: quickstartPathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.verifyReport) },
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function buildQuickstartArtifacts(flags, { bundleInput = DEFAULT_BUNDLE, outDirInput = dirname(bundleInput), overwrite = false, write = true } = {}) {
|
|
283
|
+
const paths = quickstartOutputs(bundleInput, outDirInput);
|
|
284
|
+
ensureDistinctOutputPaths(paths.outputs.map((output) => output.path));
|
|
285
|
+
await assertCanWriteQuickstartOutputs(paths.outputs, overwrite);
|
|
286
|
+
|
|
287
|
+
const vault = createVault({
|
|
288
|
+
subjectId: String(getFlag(flags, ['subject', 'subject-id'], 'local-user')),
|
|
289
|
+
displayName: String(getFlag(flags, ['display-name', 'name'], 'Local user')),
|
|
290
|
+
passphrase: String(getFlag(flags, ['passphrase'], 'local-development-passphrase')),
|
|
291
|
+
});
|
|
292
|
+
const passport = createPassport({
|
|
293
|
+
vault,
|
|
294
|
+
subjectId: vault.subject_id,
|
|
295
|
+
displayName: String(getFlag(flags, ['display-name', 'name'], 'Local user')),
|
|
296
|
+
});
|
|
297
|
+
remember({
|
|
298
|
+
vault,
|
|
299
|
+
passport,
|
|
300
|
+
text: await quickstartMemoryTextFromFlags(flags),
|
|
301
|
+
purpose: 'quickstart_local_proof',
|
|
302
|
+
purpose_tags: ['quickstart'],
|
|
303
|
+
metadata: { source: 'enigma quickstart' },
|
|
304
|
+
});
|
|
305
|
+
const contextPack = compileContextPack({
|
|
306
|
+
vault,
|
|
307
|
+
passport,
|
|
308
|
+
query: '',
|
|
309
|
+
purpose: 'quickstart_local_context',
|
|
310
|
+
limit: 8,
|
|
311
|
+
});
|
|
312
|
+
const exported = exportBundle({ vault, includePlaintext: false });
|
|
313
|
+
const bundle = exported.bundle ?? exported;
|
|
314
|
+
const verifyReport = verifyBundle(bundle);
|
|
315
|
+
|
|
316
|
+
if (write) {
|
|
317
|
+
await writeJson(paths.bundlePath, bundle);
|
|
318
|
+
await writeJson(paths.contextPackPath, contextPack);
|
|
319
|
+
await writeJson(paths.exportPath, bundle);
|
|
320
|
+
await writeJson(paths.verifyReportPath, verifyReport);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return { ...paths, vault, passport, contextPack, bundle, verifyReport };
|
|
324
|
+
}
|
|
325
|
+
|
|
213
326
|
async function crossModelMemoryTextFromFlags(flags) {
|
|
214
327
|
const textFile = getFlag(flags, ['memory-file', 'memoryFile', 'text-file', 'textFile']);
|
|
215
328
|
if (textFile === undefined) return DEFAULT_CROSS_MODEL_MEMORY;
|
|
@@ -273,6 +386,157 @@ function publicContextPackSummary(pack) {
|
|
|
273
386
|
};
|
|
274
387
|
}
|
|
275
388
|
|
|
389
|
+
const SEARCH_RELEVANCE_STOPWORDS = new Set([
|
|
390
|
+
'about',
|
|
391
|
+
'after',
|
|
392
|
+
'again',
|
|
393
|
+
'against',
|
|
394
|
+
'also',
|
|
395
|
+
'and',
|
|
396
|
+
'any',
|
|
397
|
+
'are',
|
|
398
|
+
'assistant',
|
|
399
|
+
'because',
|
|
400
|
+
'been',
|
|
401
|
+
'before',
|
|
402
|
+
'being',
|
|
403
|
+
'between',
|
|
404
|
+
'can',
|
|
405
|
+
'could',
|
|
406
|
+
'current',
|
|
407
|
+
'does',
|
|
408
|
+
'from',
|
|
409
|
+
'has',
|
|
410
|
+
'have',
|
|
411
|
+
'how',
|
|
412
|
+
'into',
|
|
413
|
+
'its',
|
|
414
|
+
'latest',
|
|
415
|
+
'more',
|
|
416
|
+
'most',
|
|
417
|
+
'number',
|
|
418
|
+
'own',
|
|
419
|
+
'owns',
|
|
420
|
+
'please',
|
|
421
|
+
'should',
|
|
422
|
+
'that',
|
|
423
|
+
'the',
|
|
424
|
+
'their',
|
|
425
|
+
'then',
|
|
426
|
+
'there',
|
|
427
|
+
'these',
|
|
428
|
+
'they',
|
|
429
|
+
'this',
|
|
430
|
+
'use',
|
|
431
|
+
'using',
|
|
432
|
+
'was',
|
|
433
|
+
'what',
|
|
434
|
+
'when',
|
|
435
|
+
'where',
|
|
436
|
+
'which',
|
|
437
|
+
'who',
|
|
438
|
+
'whose',
|
|
439
|
+
'why',
|
|
440
|
+
'with',
|
|
441
|
+
'would',
|
|
442
|
+
]);
|
|
443
|
+
|
|
444
|
+
function addSearchToken(tokens, token) {
|
|
445
|
+
if (token.length < 3) return;
|
|
446
|
+
if (!/[a-z]/u.test(token)) return;
|
|
447
|
+
if (SEARCH_RELEVANCE_STOPWORDS.has(token)) return;
|
|
448
|
+
tokens.add(token);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function searchTokensFrom(value) {
|
|
452
|
+
const tokens = new Set();
|
|
453
|
+
if (value === undefined || value === null) return tokens;
|
|
454
|
+
for (const match of String(value).toLowerCase().matchAll(/[a-z0-9]+(?:[-_][a-z0-9]+)*/gu)) {
|
|
455
|
+
const token = match[0];
|
|
456
|
+
addSearchToken(tokens, token);
|
|
457
|
+
if (token.includes('-') || token.includes('_')) {
|
|
458
|
+
for (const part of token.split(/[-_]+/u)) addSearchToken(tokens, part);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return tokens;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function addSearchTokensFromValue(tokens, value) {
|
|
465
|
+
for (const token of searchTokensFrom(value)) tokens.add(token);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function recordSearchTokens(record, content) {
|
|
469
|
+
const tokens = new Set();
|
|
470
|
+
addSearchTokensFromValue(tokens, content);
|
|
471
|
+
addSearchTokensFromValue(tokens, record?.kind);
|
|
472
|
+
for (const tag of record?.purpose_tags ?? []) addSearchTokensFromValue(tokens, tag);
|
|
473
|
+
return tokens;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function searchScore(queryTokens, memoryTokens) {
|
|
477
|
+
if (queryTokens.size === 0) return 0;
|
|
478
|
+
let overlap = 0;
|
|
479
|
+
for (const token of queryTokens) {
|
|
480
|
+
if (memoryTokens.has(token)) overlap += 1;
|
|
481
|
+
}
|
|
482
|
+
return Math.round((overlap / queryTokens.size) * 1_000_000) / 1_000_000;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function searchResultReceiptIds(vault, memoryAddr) {
|
|
486
|
+
return vault.receipts
|
|
487
|
+
.filter((receipt) => receipt?.memory_addr === memoryAddr || receipt?.source_addr === memoryAddr)
|
|
488
|
+
.map((receipt) => receipt.receipt_id)
|
|
489
|
+
.filter((receiptId) => typeof receiptId === 'string' && receiptId.length > 0);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function publicAccessReceiptRef(receipt) {
|
|
493
|
+
return {
|
|
494
|
+
access_receipt_ref: `enigma://memory-access/${receipt.receipt_id}`,
|
|
495
|
+
receipt_id: receipt.receipt_id,
|
|
496
|
+
operation: receipt.operation,
|
|
497
|
+
memory_addr: receipt.address,
|
|
498
|
+
plan_hash: receipt.plan_hash,
|
|
499
|
+
estimated_prompt_tokens: receipt.estimated_prompt_tokens,
|
|
500
|
+
access_boundary: receipt.access_boundary,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function searchCandidates(vault, queryTokens) {
|
|
505
|
+
const candidates = [];
|
|
506
|
+
const byAddress = new Map();
|
|
507
|
+
for (const memoryAddr of [...vault.activeAddresses].sort()) {
|
|
508
|
+
const record = vault.__getRecord(memoryAddr);
|
|
509
|
+
if (!record || record.state !== 'active') continue;
|
|
510
|
+
const content = vault.__getPlaintext(memoryAddr);
|
|
511
|
+
const score = searchScore(queryTokens, recordSearchTokens(record, content));
|
|
512
|
+
if (queryTokens.size > 0 && score === 0) continue;
|
|
513
|
+
const candidate = {
|
|
514
|
+
address: memoryAddr,
|
|
515
|
+
content,
|
|
516
|
+
importance: typeof record.importance === 'number' ? record.importance : typeof record.confidence === 'number' ? record.confidence : undefined,
|
|
517
|
+
last_accessed_at: record.updated_at ?? record.created_at,
|
|
518
|
+
metadata: {
|
|
519
|
+
kind: record.kind,
|
|
520
|
+
sensitivity: record.sensitivity,
|
|
521
|
+
purpose_tags: record.purpose_tags ?? [],
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
candidates.push(candidate);
|
|
525
|
+
byAddress.set(memoryAddr, { record, content, score });
|
|
526
|
+
}
|
|
527
|
+
return { candidates, byAddress };
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function connectorReadinessSummary(bundlePath) {
|
|
531
|
+
return {
|
|
532
|
+
ready: true,
|
|
533
|
+
bundle: bundlePath,
|
|
534
|
+
bundle_env: 'ENIGMA_BUNDLE',
|
|
535
|
+
mcp_command: 'enigma-mcp',
|
|
536
|
+
supported_clients: supportedClients,
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
|
|
276
540
|
function demoBundleRef(bundleWasSupplied) {
|
|
277
541
|
return bundleWasSupplied ? 'supplied_bundle' : DEFAULT_CROSS_MODEL_DEMO_BUNDLE;
|
|
278
542
|
}
|
|
@@ -493,85 +757,275 @@ async function initCommand(flags, io) {
|
|
|
493
757
|
return 0;
|
|
494
758
|
}
|
|
495
759
|
|
|
496
|
-
|
|
760
|
+
function setupClientIds(flags) {
|
|
761
|
+
const raw = getFlag(flags, ['client']);
|
|
762
|
+
if (raw === undefined) return [...DEFAULT_SETUP_CLIENTS];
|
|
763
|
+
const values = Array.isArray(raw) ? raw : [raw];
|
|
764
|
+
const clients = [];
|
|
765
|
+
for (const value of values) {
|
|
766
|
+
if (value === true || value === '') throw new Error('Missing required --client.');
|
|
767
|
+
for (const client of String(value).split(',').map((item) => item.trim()).filter(Boolean)) {
|
|
768
|
+
getClientProfile(client);
|
|
769
|
+
if (!clients.includes(client)) clients.push(client);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return clients.length > 0 ? clients : [...DEFAULT_SETUP_CLIENTS];
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
function setupMemorySource(flags) {
|
|
776
|
+
if (getFlag(flags, ['memory-file', 'memoryFile', 'text-file', 'textFile']) !== undefined) return 'memory_file';
|
|
777
|
+
if (getFlag(flags, ['memory-text', 'memoryText']) !== undefined) return 'demo_text';
|
|
778
|
+
return 'default_demo';
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function commandPath(path) {
|
|
782
|
+
return `"${String(path).replace(/"/g, '\\"')}"`;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function publicPathDisplay(path, label) {
|
|
786
|
+
const value = String(path);
|
|
787
|
+
if (/^[A-Za-z]:[\\/]/.test(value) || value.startsWith('/') || value.startsWith('\\\\')) return `<${label}>`;
|
|
788
|
+
return value;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function setupPublicDisplays(bundleInput, outDirInput) {
|
|
792
|
+
const outDir = publicPathDisplay(outDirInput, 'out-dir');
|
|
793
|
+
return {
|
|
794
|
+
bundle: publicPathDisplay(bundleInput, 'bundle-path'),
|
|
795
|
+
context_pack: quickstartPathDisplay(outDir, QUICKSTART_ARTIFACT_NAMES.contextPack),
|
|
796
|
+
export: quickstartPathDisplay(outDir, QUICKSTART_ARTIFACT_NAMES.export),
|
|
797
|
+
verify_report: quickstartPathDisplay(outDir, QUICKSTART_ARTIFACT_NAMES.verifyReport),
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function setupRawDisplays(bundleInput, outDirInput) {
|
|
802
|
+
const plan = quickstartOutputs(bundleInput, outDirInput);
|
|
803
|
+
return {
|
|
804
|
+
bundle: plan.outputs[0].display,
|
|
805
|
+
context_pack: plan.contextPackDisplay,
|
|
806
|
+
export: plan.exportDisplay,
|
|
807
|
+
verify_report: plan.verifyReportDisplay,
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function publicSetupError(error, rawDisplays, publicDisplays) {
|
|
812
|
+
let message = error.message;
|
|
813
|
+
for (const [raw, safe] of Object.entries({
|
|
814
|
+
[rawDisplays.bundle]: publicDisplays.bundle,
|
|
815
|
+
[rawDisplays.context_pack]: publicDisplays.context_pack,
|
|
816
|
+
[rawDisplays.export]: publicDisplays.export,
|
|
817
|
+
[rawDisplays.verify_report]: publicDisplays.verify_report,
|
|
818
|
+
})) {
|
|
819
|
+
message = message.split(raw).join(safe);
|
|
820
|
+
}
|
|
821
|
+
return new Error(message);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function setupNextCommands(bundleInput, exportDisplay, clients, writeConnectors) {
|
|
825
|
+
const primaryClient = clients[0] ?? DEFAULT_SETUP_CLIENTS[0];
|
|
826
|
+
const commands = [
|
|
827
|
+
`enigma remember --bundle ${commandPath(bundleInput)} --text-file ./memory.txt`,
|
|
828
|
+
`enigma search --bundle ${commandPath(bundleInput)} --query "project context"`,
|
|
829
|
+
`enigma context --bundle ${commandPath(bundleInput)} --query "project context"`,
|
|
830
|
+
`enigma verify --export ${commandPath(exportDisplay)}`,
|
|
831
|
+
];
|
|
832
|
+
if (!writeConnectors) commands.push(`enigma connect ${primaryClient} --bundle ${commandPath(bundleInput)}`);
|
|
833
|
+
return commands;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
async function setupDoctorChecks(flags, artifacts, clients, displays) {
|
|
837
|
+
const packageJson = await readPackageJson();
|
|
838
|
+
const requiredNodeMajor = minimumNodeMajor(packageJson.engines?.node);
|
|
839
|
+
const currentNodeMajor = nodeMajor(process.versions.node);
|
|
840
|
+
const binMap = packageJson.bin && typeof packageJson.bin === 'object' && !Array.isArray(packageJson.bin) ? packageJson.bin : {};
|
|
841
|
+
const binEntries = await Promise.all(REQUIRED_PACKAGE_BINS.map(async (name) => {
|
|
842
|
+
const target = binMap[name];
|
|
843
|
+
const declared = typeof target === 'string' && target.length > 0;
|
|
844
|
+
return {
|
|
845
|
+
name,
|
|
846
|
+
target: declared ? target : null,
|
|
847
|
+
declared,
|
|
848
|
+
exists: declared ? await fileExists(packageFileUrl(target)) : false,
|
|
849
|
+
};
|
|
850
|
+
}));
|
|
851
|
+
const schemas = await schemaFiles();
|
|
852
|
+
const connectorBaseOptions = {
|
|
853
|
+
...connectorOptions(flags),
|
|
854
|
+
bundlePath: artifacts.bundlePath,
|
|
855
|
+
redactPaths: true,
|
|
856
|
+
};
|
|
857
|
+
const connectorClients = [];
|
|
858
|
+
for (const client of clients) {
|
|
859
|
+
const doctor = await doctorConnectors({ ...connectorBaseOptions, clientId: client });
|
|
860
|
+
connectorClients.push(...doctor.clients);
|
|
861
|
+
}
|
|
862
|
+
const checks = {
|
|
863
|
+
node: {
|
|
864
|
+
ok: requiredNodeMajor === 0 || currentNodeMajor >= requiredNodeMajor,
|
|
865
|
+
current: process.versions.node,
|
|
866
|
+
required: packageJson.engines?.node ?? null,
|
|
867
|
+
},
|
|
868
|
+
package_bins: {
|
|
869
|
+
ok: binEntries.every((entry) => entry.declared && entry.exists),
|
|
870
|
+
required: REQUIRED_PACKAGE_BINS,
|
|
871
|
+
entries: binEntries,
|
|
872
|
+
missing: binEntries.filter((entry) => !entry.declared).map((entry) => entry.name),
|
|
873
|
+
missing_targets: binEntries.filter((entry) => entry.declared && !entry.exists).map((entry) => entry.name),
|
|
874
|
+
},
|
|
875
|
+
artifacts: {
|
|
876
|
+
ok: artifacts.verifyReport.ok === true,
|
|
877
|
+
bundle: displays.bundle,
|
|
878
|
+
context_pack: displays.context_pack,
|
|
879
|
+
export: displays.export,
|
|
880
|
+
verify_report: displays.verify_report,
|
|
881
|
+
},
|
|
882
|
+
schemas: {
|
|
883
|
+
ok: schemas.length > 0,
|
|
884
|
+
count: schemas.length,
|
|
885
|
+
files: schemas,
|
|
886
|
+
},
|
|
887
|
+
connectors: {
|
|
888
|
+
ok: connectorClients.every((client) => client.ok !== false),
|
|
889
|
+
clients: connectorClients,
|
|
890
|
+
},
|
|
891
|
+
};
|
|
892
|
+
return { ok: Object.values(checks).every((check) => check.ok !== false), checks };
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
function publicConnectPlan(plan, wizard, profile, snippet) {
|
|
896
|
+
const changed = plan?.changed !== false;
|
|
897
|
+
const dryRun = plan?.dryRun === true || plan?.dry_run === true;
|
|
898
|
+
const plannedWrites = changed ? [{ type: 'write', path: wizard.default_config_path }] : [];
|
|
899
|
+
return {
|
|
900
|
+
ok: plan?.ok !== false,
|
|
901
|
+
action: 'connect',
|
|
902
|
+
client_id: profile.client_id,
|
|
903
|
+
configPath: wizard.default_config_path,
|
|
904
|
+
config_path: wizard.default_config_path,
|
|
905
|
+
serverName: profile.server_name,
|
|
906
|
+
server_name: profile.server_name,
|
|
907
|
+
changed,
|
|
908
|
+
dryRun,
|
|
909
|
+
dry_run: dryRun,
|
|
910
|
+
writes_performed: changed && !dryRun,
|
|
911
|
+
backup_planned: Boolean(plan?.backupPath),
|
|
912
|
+
plannedWrites,
|
|
913
|
+
planned_writes: plannedWrites,
|
|
914
|
+
config: snippet,
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
async function setupConnectorPlans(flags, artifacts, clients, writeConnectors, displays) {
|
|
919
|
+
const publicOptions = {
|
|
920
|
+
...connectorOptions(flags),
|
|
921
|
+
bundlePath: displays.bundle,
|
|
922
|
+
};
|
|
923
|
+
const writeOptions = {
|
|
924
|
+
...connectorOptions(flags),
|
|
925
|
+
bundlePath: artifacts.bundlePath,
|
|
926
|
+
};
|
|
927
|
+
const connectors = [];
|
|
928
|
+
for (const client of clients) {
|
|
929
|
+
const profile = getClientProfile(client, publicOptions);
|
|
930
|
+
const snippet = renderMcpConfig(client, publicOptions);
|
|
931
|
+
const wizard = planConnectWizard(client, { platform: profile.platform }).clients[0];
|
|
932
|
+
const rawPlan = writeConnectors
|
|
933
|
+
? await connectClient(client, { ...writeOptions, dryRun: false })
|
|
934
|
+
: { ok: true, changed: true, dryRun: true };
|
|
935
|
+
const plan = publicConnectPlan(rawPlan, wizard, profile, snippet);
|
|
936
|
+
connectors.push({
|
|
937
|
+
client_id: client,
|
|
938
|
+
display_name: profile.display_name,
|
|
939
|
+
default_config_path: wizard.default_config_path,
|
|
940
|
+
mcp_config_snippet: snippet,
|
|
941
|
+
connect_command: `enigma connect ${client} --bundle ${commandPath(displays.bundle)}`,
|
|
942
|
+
connect_plan: plan,
|
|
943
|
+
wizard,
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
return connectors;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
export async function setupCommand(flags, io) {
|
|
497
950
|
const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
|
|
498
951
|
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], dirname(bundleInput));
|
|
499
|
-
const
|
|
500
|
-
const
|
|
501
|
-
const
|
|
502
|
-
const
|
|
503
|
-
const
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
const overwrite = getFlag(flags, ['overwrite'], false) === true || getFlag(flags, ['overwrite'], false) === 'true';
|
|
515
|
-
await assertCanWriteQuickstartOutputs(outputs, overwrite);
|
|
952
|
+
const clients = setupClientIds(flags);
|
|
953
|
+
const overwrite = booleanFlag(flags, ['overwrite'], false);
|
|
954
|
+
const dryRun = booleanFlag(flags, ['dry-run', 'dryRun'], false);
|
|
955
|
+
const writeConnectors = booleanFlag(flags, ['write-connectors', 'writeConnectors'], false) && !dryRun;
|
|
956
|
+
const displays = setupPublicDisplays(bundleInput, outDirInput);
|
|
957
|
+
const rawDisplays = setupRawDisplays(bundleInput, outDirInput);
|
|
958
|
+
let artifacts;
|
|
959
|
+
try {
|
|
960
|
+
artifacts = await buildQuickstartArtifacts(flags, { bundleInput, outDirInput, overwrite, write: !dryRun });
|
|
961
|
+
} catch (error) {
|
|
962
|
+
throw publicSetupError(error, rawDisplays, displays);
|
|
963
|
+
}
|
|
964
|
+
const connectors = await setupConnectorPlans(flags, artifacts, clients, writeConnectors, displays);
|
|
965
|
+
const doctor = await setupDoctorChecks(flags, artifacts, clients, displays);
|
|
966
|
+
const ok = artifacts.verifyReport.ok === true;
|
|
516
967
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
968
|
+
print({
|
|
969
|
+
ok,
|
|
970
|
+
schema: 'enigma.setup.v1',
|
|
971
|
+
command: 'enigma setup',
|
|
972
|
+
dry_run: dryRun,
|
|
973
|
+
artifacts_written: !dryRun,
|
|
974
|
+
client_configs_written: writeConnectors,
|
|
975
|
+
bundle: displays.bundle,
|
|
976
|
+
context_pack: displays.context_pack,
|
|
977
|
+
export: displays.export,
|
|
978
|
+
verify_report: displays.verify_report,
|
|
979
|
+
memory_source: setupMemorySource(flags),
|
|
980
|
+
memory_plaintext_echoed: false,
|
|
981
|
+
memory_count: Array.isArray(artifacts.bundle.memory_objects) ? artifacts.bundle.memory_objects.length : 0,
|
|
982
|
+
receipt_count: Array.isArray(artifacts.bundle.receipts) ? artifacts.bundle.receipts.length : 0,
|
|
983
|
+
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
984
|
+
verify_ok: artifacts.verifyReport.ok === true,
|
|
985
|
+
provider_credentials_required: false,
|
|
986
|
+
provider_native_memory_canonical: false,
|
|
987
|
+
selected_clients: clients,
|
|
988
|
+
connectors,
|
|
989
|
+
mcp_config_snippets: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.mcp_config_snippet])),
|
|
990
|
+
connect_plans: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.connect_plan])),
|
|
991
|
+
next_commands: setupNextCommands(displays.bundle, displays.export, clients, writeConnectors),
|
|
992
|
+
checks: doctor.checks,
|
|
993
|
+
claim_boundaries: { ...SETUP_CLAIM_BOUNDARIES },
|
|
994
|
+
}, io);
|
|
995
|
+
return ok ? 0 : 1;
|
|
996
|
+
}
|
|
545
997
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
998
|
+
export async function quickstartCommand(flags, io) {
|
|
999
|
+
const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
|
|
1000
|
+
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], dirname(bundleInput));
|
|
1001
|
+
const overwrite = booleanFlag(flags, ['overwrite'], false);
|
|
1002
|
+
const artifacts = await buildQuickstartArtifacts(flags, { bundleInput, outDirInput, overwrite, write: true });
|
|
550
1003
|
|
|
551
1004
|
print({
|
|
552
|
-
ok: verifyReport.ok === true,
|
|
1005
|
+
ok: artifacts.verifyReport.ok === true,
|
|
553
1006
|
bundle: bundleInput,
|
|
554
|
-
context_pack: contextPackDisplay,
|
|
555
|
-
export: exportDisplay,
|
|
556
|
-
verify_report: verifyReportDisplay,
|
|
557
|
-
memory_count: Array.isArray(bundle.memory_objects) ? bundle.memory_objects.length : 0,
|
|
558
|
-
receipt_count: Array.isArray(bundle.receipts) ? bundle.receipts.length : 0,
|
|
559
|
-
context_item_count: Array.isArray(contextPack.memories) ? contextPack.memories.length : 0,
|
|
560
|
-
verify_ok: verifyReport.ok === true,
|
|
1007
|
+
context_pack: artifacts.contextPackDisplay,
|
|
1008
|
+
export: artifacts.exportDisplay,
|
|
1009
|
+
verify_report: artifacts.verifyReportDisplay,
|
|
1010
|
+
memory_count: Array.isArray(artifacts.bundle.memory_objects) ? artifacts.bundle.memory_objects.length : 0,
|
|
1011
|
+
receipt_count: Array.isArray(artifacts.bundle.receipts) ? artifacts.bundle.receipts.length : 0,
|
|
1012
|
+
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
1013
|
+
verify_ok: artifacts.verifyReport.ok === true,
|
|
561
1014
|
next_commands: [
|
|
562
|
-
`enigma verify --export ${exportDisplay}`,
|
|
1015
|
+
`enigma verify --export ${artifacts.exportDisplay}`,
|
|
563
1016
|
`enigma connect generic-mcp --bundle ${bundleInput} --dry-run`,
|
|
564
1017
|
],
|
|
565
1018
|
claim_boundaries: {
|
|
566
1019
|
local_only: true,
|
|
567
1020
|
provider_credentials_required: false,
|
|
1021
|
+
provider_native_memory_canonical: false,
|
|
568
1022
|
provider_deletion_proof: false,
|
|
569
1023
|
model_forgetting_proof: false,
|
|
570
1024
|
roi_or_savings_guarantee: false,
|
|
571
1025
|
compliance_certification: false,
|
|
572
1026
|
},
|
|
573
1027
|
}, io);
|
|
574
|
-
return verifyReport.ok === true ? 0 : 1;
|
|
1028
|
+
return artifacts.verifyReport.ok === true ? 0 : 1;
|
|
575
1029
|
}
|
|
576
1030
|
|
|
577
1031
|
export async function crossModelDemoCommand(flags, io) {
|
|
@@ -767,6 +1221,118 @@ async function contextCommand(flags, io) {
|
|
|
767
1221
|
return 0;
|
|
768
1222
|
}
|
|
769
1223
|
|
|
1224
|
+
|
|
1225
|
+
async function searchCommand(flags, io) {
|
|
1226
|
+
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1227
|
+
const query = String(requireFlag(flags, ['query', 'q'], 'query'));
|
|
1228
|
+
const limit = integerFlag(flags, ['limit'], 'limit', 8);
|
|
1229
|
+
if (limit < 0) throw new Error('--limit must be non-negative.');
|
|
1230
|
+
const includeContent = getFlag(flags, ['include-content', 'includeContent']) === true || getFlag(flags, ['include-content', 'includeContent']) === 'true';
|
|
1231
|
+
const { vault } = await loadState(bundlePath);
|
|
1232
|
+
const roots = vault.__computeRoots();
|
|
1233
|
+
const queryTokens = searchTokensFrom(query);
|
|
1234
|
+
const { candidates, byAddress } = searchCandidates(vault, queryTokens);
|
|
1235
|
+
const plan = createMemoryOptimizationPlan({
|
|
1236
|
+
candidates,
|
|
1237
|
+
prompt: query,
|
|
1238
|
+
now: getFlag(flags, ['now'], '2026-01-01T00:00:00.000Z'),
|
|
1239
|
+
});
|
|
1240
|
+
const planIndex = new Map(plan.items.map((item, index) => [item.address, index]));
|
|
1241
|
+
const selectedItems = plan.items
|
|
1242
|
+
.filter((item) => byAddress.has(item.address))
|
|
1243
|
+
.sort((left, right) => {
|
|
1244
|
+
const scoreDiff = byAddress.get(right.address).score - byAddress.get(left.address).score;
|
|
1245
|
+
if (scoreDiff !== 0) return scoreDiff;
|
|
1246
|
+
return planIndex.get(left.address) - planIndex.get(right.address);
|
|
1247
|
+
})
|
|
1248
|
+
.slice(0, limit);
|
|
1249
|
+
const accessReceipts = selectedItems.map((item, index) => createMemoryAccessReceipt({
|
|
1250
|
+
item,
|
|
1251
|
+
plan,
|
|
1252
|
+
sequence: index,
|
|
1253
|
+
timestamp: null,
|
|
1254
|
+
pricing: plan.pricing,
|
|
1255
|
+
}));
|
|
1256
|
+
const accessReceiptByAddress = new Map(accessReceipts.map((receipt) => [receipt.address, publicAccessReceiptRef(receipt)]));
|
|
1257
|
+
const results = selectedItems.map((item) => {
|
|
1258
|
+
const hit = byAddress.get(item.address);
|
|
1259
|
+
const record = hit.record;
|
|
1260
|
+
const accessReceipt = accessReceiptByAddress.get(item.address);
|
|
1261
|
+
return {
|
|
1262
|
+
memory_ref: `enigma://memory/${item.address}`,
|
|
1263
|
+
memory_addr: item.address,
|
|
1264
|
+
address: item.address,
|
|
1265
|
+
kind: record.kind,
|
|
1266
|
+
sensitivity: record.sensitivity,
|
|
1267
|
+
tags: Array.isArray(record.purpose_tags) ? [...record.purpose_tags] : [],
|
|
1268
|
+
purpose_tags: Array.isArray(record.purpose_tags) ? [...record.purpose_tags] : [],
|
|
1269
|
+
score: hit.score,
|
|
1270
|
+
tier: item.tier,
|
|
1271
|
+
receipt_ids: searchResultReceiptIds(vault, item.address),
|
|
1272
|
+
access_receipt_ref: accessReceipt?.access_receipt_ref,
|
|
1273
|
+
access_receipt_id: accessReceipt?.receipt_id,
|
|
1274
|
+
access_receipt_refs: accessReceipt?.access_receipt_ref ? [accessReceipt.access_receipt_ref] : [],
|
|
1275
|
+
content_redacted: !includeContent,
|
|
1276
|
+
...(includeContent ? { content: hit.content } : {}),
|
|
1277
|
+
};
|
|
1278
|
+
});
|
|
1279
|
+
print({
|
|
1280
|
+
ok: true,
|
|
1281
|
+
schema: 'enigma.memory_search.v1',
|
|
1282
|
+
bundle: bundlePath,
|
|
1283
|
+
query_redacted: true,
|
|
1284
|
+
limit,
|
|
1285
|
+
result_count: results.length,
|
|
1286
|
+
results,
|
|
1287
|
+
access_receipts: accessReceipts.map(publicAccessReceiptRef),
|
|
1288
|
+
active_set_root: roots.active_set_root,
|
|
1289
|
+
receipt_log_root: roots.receipt_log_root,
|
|
1290
|
+
claim_boundary: includeContent
|
|
1291
|
+
? 'Search ran against the selected local bundle and includes plaintext only because --include-content was explicit; this does not prove provider deletion, provider-native memory state, or model forgetting.'
|
|
1292
|
+
: 'Search ran against the selected local bundle and redacts plaintext by default; refs, scores, tags, roots, and receipt refs are not provider deletion proof or model forgetting proof.',
|
|
1293
|
+
}, io);
|
|
1294
|
+
return 0;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
async function statusCommand(flags, io) {
|
|
1298
|
+
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1299
|
+
const { stored, vault, passport } = await loadState(bundlePath);
|
|
1300
|
+
const roots = vault.__computeRoots();
|
|
1301
|
+
const activeCount = activeMemoryCount(vault);
|
|
1302
|
+
const tombstoneCount = vault.tombstones instanceof Map ? vault.tombstones.size : 0;
|
|
1303
|
+
const receiptCount = Array.isArray(vault.receipts) ? vault.receipts.length : 0;
|
|
1304
|
+
print({
|
|
1305
|
+
ok: true,
|
|
1306
|
+
schema: 'enigma.passport_status.v1',
|
|
1307
|
+
bundle: bundlePath,
|
|
1308
|
+
passport_ref: `enigma://passport/${passport.passport_id}`,
|
|
1309
|
+
owner: {
|
|
1310
|
+
subject_id: stored.owner?.subject_id ?? stored.passport?.owner?.subject_id ?? stored.vault?.subject_id ?? passport.owner?.subject_id ?? vault.subject_id,
|
|
1311
|
+
display_name: stored.owner?.display_name ?? stored.passport?.owner?.display_name ?? stored.vault?.display_name ?? passport.owner?.display_name ?? 'Local user',
|
|
1312
|
+
},
|
|
1313
|
+
counts: {
|
|
1314
|
+
active_memories: activeCount,
|
|
1315
|
+
tombstoned_memories: tombstoneCount,
|
|
1316
|
+
receipts: receiptCount,
|
|
1317
|
+
},
|
|
1318
|
+
active_memory_count: activeCount,
|
|
1319
|
+
tombstoned_memory_count: tombstoneCount,
|
|
1320
|
+
receipt_count: receiptCount,
|
|
1321
|
+
active_set_root: roots.active_set_root,
|
|
1322
|
+
receipt_log_root: roots.receipt_log_root,
|
|
1323
|
+
connector_readiness: connectorReadinessSummary(bundlePath),
|
|
1324
|
+
next_recommended_commands: [
|
|
1325
|
+
`enigma remember --bundle "${bundlePath}" --text-file <path>`,
|
|
1326
|
+
`enigma search --bundle "${bundlePath}" --query <text>`,
|
|
1327
|
+
`enigma context --bundle "${bundlePath}" --query <text>`,
|
|
1328
|
+
`enigma verify --bundle "${bundlePath}"`,
|
|
1329
|
+
`enigma connect <client> --bundle "${bundlePath}"`,
|
|
1330
|
+
],
|
|
1331
|
+
claim_boundary: 'Status reports local bundle counters, owner display fields, connector readiness hints, and commitment roots only; it does not expose raw memory, certify compliance, prove provider deletion, or prove model forgetting.',
|
|
1332
|
+
}, io);
|
|
1333
|
+
return 0;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
770
1336
|
async function exportCommand(flags, io) {
|
|
771
1337
|
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
772
1338
|
const { vault } = await loadState(bundlePath);
|
|
@@ -1272,6 +1838,7 @@ function usage() {
|
|
|
1272
1838
|
usage: 'enigma <command> [options]',
|
|
1273
1839
|
commands: [
|
|
1274
1840
|
'init',
|
|
1841
|
+
'setup',
|
|
1275
1842
|
'quickstart',
|
|
1276
1843
|
'demo cross-model',
|
|
1277
1844
|
'doctor',
|
|
@@ -1283,6 +1850,9 @@ function usage() {
|
|
|
1283
1850
|
'update',
|
|
1284
1851
|
'delete',
|
|
1285
1852
|
'context',
|
|
1853
|
+
'search',
|
|
1854
|
+
'status',
|
|
1855
|
+
'passport status',
|
|
1286
1856
|
'export',
|
|
1287
1857
|
'import <source>',
|
|
1288
1858
|
'capsule export',
|
|
@@ -1318,6 +1888,27 @@ function usage() {
|
|
|
1318
1888
|
'--text <text>': 'Inline local memory text. Avoid for private content because argv can be logged by process tooling.',
|
|
1319
1889
|
'--text-file <path>': 'Read local memory text from a file so private smoke input is not exposed in shell argv. Aliases: --memory-file, --textFile, --memoryFile.',
|
|
1320
1890
|
},
|
|
1891
|
+
search_options: {
|
|
1892
|
+
'--query <text>': 'Required local query. Output redacts the query and memory plaintext by default. Alias: --q.',
|
|
1893
|
+
'--bundle <path>': 'Bundle JSON to search. Defaults to .enigma/bundle.json.',
|
|
1894
|
+
'--limit <n>': 'Maximum ranked active memories to return. Defaults to 8.',
|
|
1895
|
+
'--json': 'Reserved for explicit JSON output; CLI output is JSON by default.',
|
|
1896
|
+
'--include-content': 'Opt in to returning plaintext local memory content in the JSON result.',
|
|
1897
|
+
},
|
|
1898
|
+
status_options: {
|
|
1899
|
+
'enigma status --bundle <path>': 'Show local Memory Passport counts, roots, owner display fields, connector readiness, and next commands.',
|
|
1900
|
+
'enigma passport status --bundle <path>': 'Alias for enigma status.',
|
|
1901
|
+
},
|
|
1902
|
+
setup_options: {
|
|
1903
|
+
'--bundle <path>': 'Bundle JSON to create. Defaults to .enigma/bundle.json.',
|
|
1904
|
+
'--out-dir <path>': 'Directory for context-pack.json, export.json, and verify-report.json. Defaults to the bundle directory.',
|
|
1905
|
+
'--client <id>': `Client to plan; repeat or comma-separate. Defaults to ${DEFAULT_SETUP_CLIENTS.join(', ')}.`,
|
|
1906
|
+
'--memory-file <path>': 'Read local memory text from a file without echoing plaintext. Alias: --text-file.',
|
|
1907
|
+
'--memory-text <text>': 'Inline demo-only memory text. Avoid for private content because argv can be logged.',
|
|
1908
|
+
'--overwrite': 'Replace existing local setup artifacts.',
|
|
1909
|
+
'--dry-run': 'Plan setup without writing local artifacts or client configs.',
|
|
1910
|
+
'--write-connectors': 'Also write selected client MCP config files. Defaults to false.',
|
|
1911
|
+
},
|
|
1321
1912
|
quickstart_options: {
|
|
1322
1913
|
'--bundle <path>': 'Bundle JSON to create. Defaults to .enigma/bundle.json.',
|
|
1323
1914
|
'--out-dir <path>': 'Directory for context-pack.json, export.json, and verify-report.json. Defaults to the bundle directory.',
|
|
@@ -1398,15 +1989,16 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
1398
1989
|
print(usage(), io);
|
|
1399
1990
|
return 0;
|
|
1400
1991
|
}
|
|
1401
|
-
const twoPartCommands = ['boundary', 'mcp', 'mesh', 'enterprise', 'capsule', 'relay', 'gateway', 'connect', 'disconnect', 'import', 'native-host', 'meter', 'settlement', 'demo'];
|
|
1992
|
+
const twoPartCommands = ['boundary', 'mcp', 'mesh', 'enterprise', 'capsule', 'relay', 'gateway', 'connect', 'disconnect', 'import', 'native-host', 'meter', 'settlement', 'demo', 'passport'];
|
|
1402
1993
|
const flags = parseArgs(twoPartCommands.includes(command) ? argv.slice(2) : argv.slice(1));
|
|
1403
1994
|
const positionalFile = optionalPositional(argv[2]);
|
|
1404
|
-
if ((flags.has('help') || argv.includes('-h')) && (((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model'))) {
|
|
1995
|
+
if ((flags.has('help') || argv.includes('-h')) && (command === 'setup' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model'))) {
|
|
1405
1996
|
print(usage(), io);
|
|
1406
1997
|
return 0;
|
|
1407
1998
|
}
|
|
1408
1999
|
try {
|
|
1409
2000
|
if (command === 'init') return await initCommand(flags, io);
|
|
2001
|
+
if (command === 'setup') return await setupCommand(flags, io);
|
|
1410
2002
|
if (command === 'quickstart') return await quickstartCommand(flags, io);
|
|
1411
2003
|
if (command === 'demo' && subcommand === 'cross-model') return await crossModelDemoCommand(flags, io);
|
|
1412
2004
|
if (command === 'doctor') return await doctorCommand(flags, io);
|
|
@@ -1418,6 +2010,9 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
1418
2010
|
if (command === 'update') return await updateCommand(flags, io);
|
|
1419
2011
|
if (command === 'delete') return await deleteCommand(flags, io);
|
|
1420
2012
|
if (command === 'context') return await contextCommand(flags, io);
|
|
2013
|
+
if (command === 'search') return await searchCommand(flags, io);
|
|
2014
|
+
if (command === 'status') return await statusCommand(flags, io);
|
|
2015
|
+
if (command === 'passport' && subcommand === 'status') return await statusCommand(flags, io);
|
|
1421
2016
|
if (command === 'export') return await exportCommand(flags, io);
|
|
1422
2017
|
if (command === 'import') return await importCommand(subcommand, flags, io, positionalFile);
|
|
1423
2018
|
if (command === 'capsule' && subcommand === 'export') return await capsuleExportCommand(flags, io, positionalFile);
|