enigma-memory 0.1.0 → 0.1.2
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 +367 -379
- package/apps/browser-extension/manifest.json +41 -0
- package/apps/browser-extension/src/background.js +88 -0
- package/apps/browser-extension/src/content-script.js +602 -0
- package/apps/browser-extension/src/native-bridge.js +289 -0
- package/apps/cli/bin/enigma.mjs +347 -2
- package/apps/desktop/src/tray.js +231 -0
- package/docs/browser-extension-install.md +169 -0
- package/docs/developer-ecosystem.md +74 -0
- package/docs/hosted-cloud-product.md +68 -0
- package/docs/installers-and-desktop.md +76 -0
- package/docs/memory-benchmarks.md +51 -0
- package/docs/sdk-api.md +181 -0
- package/examples/ci/github-actions.yml +63 -0
- package/examples/node-basic-memory.mjs +84 -0
- package/package.json +22 -1
- package/packages/connectors/src/index.js +274 -39
- package/packages/hosted-cloud/src/index.js +538 -0
- package/packages/mcp-server/src/index.js +1 -1
- package/scripts/build-installer-assets.mjs +273 -0
- package/scripts/package-browser-extension.mjs +473 -0
- package/scripts/run-memory-benchmarks.mjs +585 -0
- package/scripts/verify-registry-install.mjs +410 -0
- package/templates/mcp-client-config.json +10 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
export const TRAY_MODEL_SCHEMA = 'enigma.desktop.tray_model.v1';
|
|
2
|
+
export const TRAY_MENU_SCHEMA = 'enigma.desktop.tray_menu.v1';
|
|
3
|
+
|
|
4
|
+
export const TRAY_ACTION_TYPES = Object.freeze({
|
|
5
|
+
STATUS: 'tray/status',
|
|
6
|
+
QUICKSTART: 'tray/quickstart',
|
|
7
|
+
CONNECT_CLIENTS: 'tray/connect-clients',
|
|
8
|
+
OPEN_DOCS: 'tray/open-docs',
|
|
9
|
+
RUN_DIAGNOSTICS: 'tray/run-diagnostics',
|
|
10
|
+
QUIT: 'tray/quit',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const DEFAULT_DOCS_URL = 'https://docs.enigmaprotocol.net/docs/install';
|
|
14
|
+
const STATUS_VALUES = Object.freeze(new Set(['not-installed', 'ready', 'needs-setup', 'running', 'degraded', 'offline']));
|
|
15
|
+
const DIAGNOSTIC_VALUES = Object.freeze(new Set(['idle', 'queued', 'running', 'passed', 'failed']));
|
|
16
|
+
const CLIENTS = Object.freeze([
|
|
17
|
+
Object.freeze({ id: 'claude-desktop', label: 'Claude Desktop', kind: 'mcp-client' }),
|
|
18
|
+
Object.freeze({ id: 'cursor', label: 'Cursor', kind: 'mcp-client' }),
|
|
19
|
+
Object.freeze({ id: 'vscode', label: 'VS Code', kind: 'mcp-client' }),
|
|
20
|
+
Object.freeze({ id: 'browser-bridge', label: 'Browser bridge', kind: 'extension' }),
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
function cleanString(value) {
|
|
24
|
+
return String(value ?? '').trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function normalizeStatus(value) {
|
|
28
|
+
const status = cleanString(value);
|
|
29
|
+
return STATUS_VALUES.has(status) ? status : 'needs-setup';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function normalizeDiagnostics(value) {
|
|
33
|
+
const status = cleanString(value);
|
|
34
|
+
return DIAGNOSTIC_VALUES.has(status) ? status : 'idle';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeClients(value) {
|
|
38
|
+
const requested = Array.isArray(value) ? value : [];
|
|
39
|
+
const seen = new Set();
|
|
40
|
+
const known = new Map(CLIENTS.map((client) => [client.id, client]));
|
|
41
|
+
const clients = [];
|
|
42
|
+
for (const item of requested) {
|
|
43
|
+
const id = cleanString(typeof item === 'string' ? item : item?.id);
|
|
44
|
+
const connected = typeof item === 'string' || item?.connected === true;
|
|
45
|
+
if (!known.has(id) || seen.has(id) || !connected) continue;
|
|
46
|
+
seen.add(id);
|
|
47
|
+
clients.push({ ...known.get(id), connected: true });
|
|
48
|
+
}
|
|
49
|
+
for (const client of CLIENTS) {
|
|
50
|
+
if (!seen.has(client.id)) clients.push({ ...client, connected: false });
|
|
51
|
+
}
|
|
52
|
+
return clients;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function menuItem(id, label, action, options = {}) {
|
|
56
|
+
return Object.freeze({
|
|
57
|
+
id,
|
|
58
|
+
label,
|
|
59
|
+
action,
|
|
60
|
+
enabled: options.enabled !== false,
|
|
61
|
+
checked: options.checked === true,
|
|
62
|
+
role: cleanString(options.role) || 'item',
|
|
63
|
+
honest_boundary: cleanString(options.honest_boundary),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function action(type, payload = {}) {
|
|
68
|
+
return Object.freeze({ type, ...payload });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createTrayState(options = {}) {
|
|
72
|
+
const status = normalizeStatus(options.status);
|
|
73
|
+
const clients = normalizeClients(options.connectedClients ?? options.clients);
|
|
74
|
+
const connectedCount = clients.filter((client) => client.connected).length;
|
|
75
|
+
return Object.freeze({
|
|
76
|
+
schema: TRAY_MODEL_SCHEMA,
|
|
77
|
+
model_only: true,
|
|
78
|
+
native_tray_started: false,
|
|
79
|
+
status,
|
|
80
|
+
status_label: statusLabel(status),
|
|
81
|
+
quickstart_available: options.quickstartAvailable !== false,
|
|
82
|
+
clients: Object.freeze(clients.map((client) => Object.freeze({ ...client }))),
|
|
83
|
+
connected_client_count: connectedCount,
|
|
84
|
+
docs_url: cleanString(options.docsUrl) || DEFAULT_DOCS_URL,
|
|
85
|
+
diagnostics: Object.freeze({
|
|
86
|
+
status: normalizeDiagnostics(options.diagnosticsStatus),
|
|
87
|
+
last_result: cleanString(options.diagnosticsResult),
|
|
88
|
+
}),
|
|
89
|
+
quit_requested: options.quitRequested === true,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function statusLabel(status) {
|
|
94
|
+
switch (normalizeStatus(status)) {
|
|
95
|
+
case 'ready':
|
|
96
|
+
return 'Ready';
|
|
97
|
+
case 'running':
|
|
98
|
+
return 'Running';
|
|
99
|
+
case 'degraded':
|
|
100
|
+
return 'Needs attention';
|
|
101
|
+
case 'offline':
|
|
102
|
+
return 'Offline';
|
|
103
|
+
case 'not-installed':
|
|
104
|
+
return 'Not installed';
|
|
105
|
+
default:
|
|
106
|
+
return 'Needs setup';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function createTrayMenu(state = createTrayState()) {
|
|
111
|
+
const model = state?.schema === TRAY_MODEL_SCHEMA ? state : createTrayState(state);
|
|
112
|
+
return Object.freeze({
|
|
113
|
+
schema: TRAY_MENU_SCHEMA,
|
|
114
|
+
model_only: true,
|
|
115
|
+
native_tray_started: false,
|
|
116
|
+
status: model.status,
|
|
117
|
+
items: Object.freeze([
|
|
118
|
+
menuItem('status', `Status: ${model.status_label}`, TRAY_ACTION_TYPES.STATUS, {
|
|
119
|
+
enabled: false,
|
|
120
|
+
honest_boundary: 'Local tray status is an application model snapshot, not cryptographic proof.',
|
|
121
|
+
}),
|
|
122
|
+
menuItem('quickstart', 'Run quickstart', TRAY_ACTION_TYPES.QUICKSTART, {
|
|
123
|
+
enabled: model.quickstart_available && model.status !== 'running',
|
|
124
|
+
honest_boundary: 'Emits an intent to run the existing quickstart command; this module does not execute commands.',
|
|
125
|
+
}),
|
|
126
|
+
menuItem('connect-clients', `Connect clients (${model.connected_client_count})`, TRAY_ACTION_TYPES.CONNECT_CLIENTS, {
|
|
127
|
+
honest_boundary: 'Opens client-connection intent only; no MCP client is configured by this pure model.',
|
|
128
|
+
}),
|
|
129
|
+
menuItem('open-docs', 'Open install docs', TRAY_ACTION_TYPES.OPEN_DOCS, {
|
|
130
|
+
honest_boundary: 'Emits a docs URL intent only; this module does not launch a browser.',
|
|
131
|
+
}),
|
|
132
|
+
menuItem('run-diagnostics', diagnosticsLabel(model.diagnostics.status), TRAY_ACTION_TYPES.RUN_DIAGNOSTICS, {
|
|
133
|
+
enabled: model.diagnostics.status !== 'running',
|
|
134
|
+
honest_boundary: 'Emits diagnostics intent only; the caller owns command execution and evidence capture.',
|
|
135
|
+
}),
|
|
136
|
+
menuItem('separator-before-quit', '—', '', { enabled: false, role: 'separator' }),
|
|
137
|
+
menuItem('quit', 'Quit Enigma tray', TRAY_ACTION_TYPES.QUIT, {
|
|
138
|
+
honest_boundary: 'Emits quit intent only; host application owns process shutdown.',
|
|
139
|
+
}),
|
|
140
|
+
]),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function diagnosticsLabel(status) {
|
|
145
|
+
switch (normalizeDiagnostics(status)) {
|
|
146
|
+
case 'queued':
|
|
147
|
+
return 'Diagnostics queued';
|
|
148
|
+
case 'running':
|
|
149
|
+
return 'Diagnostics running';
|
|
150
|
+
case 'passed':
|
|
151
|
+
return 'Run diagnostics (last passed)';
|
|
152
|
+
case 'failed':
|
|
153
|
+
return 'Run diagnostics (last failed)';
|
|
154
|
+
default:
|
|
155
|
+
return 'Run diagnostics';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function trayStatus(status) {
|
|
160
|
+
return action(TRAY_ACTION_TYPES.STATUS, { status: normalizeStatus(status) });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function runQuickstart(options = {}) {
|
|
164
|
+
return action(TRAY_ACTION_TYPES.QUICKSTART, { bundle: cleanString(options.bundle) || '<bundle-path>', overwrite: options.overwrite !== false });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function connectClients(clientIds = []) {
|
|
168
|
+
return action(TRAY_ACTION_TYPES.CONNECT_CLIENTS, { clients: normalizeClients(clientIds).filter((client) => client.connected).map((client) => client.id) });
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function openDocs(url = DEFAULT_DOCS_URL) {
|
|
172
|
+
return action(TRAY_ACTION_TYPES.OPEN_DOCS, { url: cleanString(url) || DEFAULT_DOCS_URL });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function runDiagnostics(scope = 'local') {
|
|
176
|
+
return action(TRAY_ACTION_TYPES.RUN_DIAGNOSTICS, { scope: cleanString(scope) || 'local' });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function quitTray() {
|
|
180
|
+
return action(TRAY_ACTION_TYPES.QUIT, { quit_requested: true });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function reduceTrayState(state = createTrayState(), requestedAction = {}) {
|
|
184
|
+
const model = state?.schema === TRAY_MODEL_SCHEMA ? state : createTrayState(state);
|
|
185
|
+
const type = cleanString(requestedAction.type);
|
|
186
|
+
switch (type) {
|
|
187
|
+
case TRAY_ACTION_TYPES.STATUS:
|
|
188
|
+
return createTrayState({ ...model, status: requestedAction.status });
|
|
189
|
+
case TRAY_ACTION_TYPES.QUICKSTART:
|
|
190
|
+
return createTrayState({ ...model, status: 'running', diagnosticsStatus: model.diagnostics.status });
|
|
191
|
+
case TRAY_ACTION_TYPES.CONNECT_CLIENTS:
|
|
192
|
+
return createTrayState({ ...model, connectedClients: requestedAction.clients });
|
|
193
|
+
case TRAY_ACTION_TYPES.OPEN_DOCS:
|
|
194
|
+
return createTrayState({ ...model, docsUrl: requestedAction.url });
|
|
195
|
+
case TRAY_ACTION_TYPES.RUN_DIAGNOSTICS:
|
|
196
|
+
return createTrayState({ ...model, diagnosticsStatus: 'queued' });
|
|
197
|
+
case TRAY_ACTION_TYPES.QUIT:
|
|
198
|
+
return createTrayState({ ...model, quitRequested: true });
|
|
199
|
+
default:
|
|
200
|
+
return model;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function trayActionIntent(requestedAction = {}) {
|
|
205
|
+
const type = cleanString(requestedAction.type);
|
|
206
|
+
switch (type) {
|
|
207
|
+
case TRAY_ACTION_TYPES.STATUS:
|
|
208
|
+
return Object.freeze({ kind: 'status', status: normalizeStatus(requestedAction.status), side_effect: false });
|
|
209
|
+
case TRAY_ACTION_TYPES.QUICKSTART:
|
|
210
|
+
return Object.freeze({ kind: 'quickstart', command: 'enigma', args: ['quickstart', '--bundle', '<bundle-path>', '--overwrite'], side_effect: 'caller-owned' });
|
|
211
|
+
case TRAY_ACTION_TYPES.CONNECT_CLIENTS:
|
|
212
|
+
return Object.freeze({ kind: 'connect_clients', clients: normalizeClients(requestedAction.clients).filter((client) => client.connected).map((client) => client.id), side_effect: 'caller-owned' });
|
|
213
|
+
case TRAY_ACTION_TYPES.OPEN_DOCS:
|
|
214
|
+
return Object.freeze({ kind: 'open_docs', url: cleanString(requestedAction.url) || DEFAULT_DOCS_URL, side_effect: 'caller-owned' });
|
|
215
|
+
case TRAY_ACTION_TYPES.RUN_DIAGNOSTICS:
|
|
216
|
+
return Object.freeze({ kind: 'run_diagnostics', command: 'enigma', args: ['doctor'], side_effect: 'caller-owned' });
|
|
217
|
+
case TRAY_ACTION_TYPES.QUIT:
|
|
218
|
+
return Object.freeze({ kind: 'quit', side_effect: 'caller-owned' });
|
|
219
|
+
default:
|
|
220
|
+
return Object.freeze({ kind: 'unknown', side_effect: false });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export const trayActions = Object.freeze({
|
|
225
|
+
trayStatus,
|
|
226
|
+
runQuickstart,
|
|
227
|
+
connectClients,
|
|
228
|
+
openDocs,
|
|
229
|
+
runDiagnostics,
|
|
230
|
+
quitTray,
|
|
231
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Browser extension local install
|
|
2
|
+
|
|
3
|
+
This guide is for local developer installation only. It does not submit Enigma to Chrome Web Store, Microsoft Edge Add-ons, Mozilla Add-ons, or any external account.
|
|
4
|
+
|
|
5
|
+
## Boundaries
|
|
6
|
+
|
|
7
|
+
- The extension is loaded by the user as an unpacked or temporary local extension.
|
|
8
|
+
- The native host is installed by the user and runs on the local machine as `com.enigma.native_host`.
|
|
9
|
+
- Context insertion requires two user clicks: request context, then approve insertion.
|
|
10
|
+
- The extension must not auto-inject context into a provider page.
|
|
11
|
+
- The extension does not use browser sync storage and must not store raw memory in browser storage.
|
|
12
|
+
- Provider-native memory is cache only. The local Enigma bundle/native host remains canonical.
|
|
13
|
+
|
|
14
|
+
## Package preflight
|
|
15
|
+
|
|
16
|
+
From the package root, validate the extension before loading or zipping it:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
node scripts/package-browser-extension.mjs
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The command emits public-safe JSON with a deterministic file list, SHA-256 checksums, and safety fields. To also write a deterministic local ZIP for manual inspection or enterprise review:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
node scripts/package-browser-extension.mjs --zip ./dist/enigma-browser-extension.zip
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The ZIP command does not publish, sign, upload, or submit the extension.
|
|
29
|
+
|
|
30
|
+
## Install the native host first
|
|
31
|
+
|
|
32
|
+
Install the npm package so both `enigma` and `enigma-native-host` are available:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npm install -g enigma-memory
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Create or select a local bundle:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
enigma init --bundle <absolute-bundle-path> --subject local-user --display-name "Local user"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Set `ENIGMA_BUNDLE` for the browser-launched host process, or point the native-host manifest at a small local wrapper that sets `ENIGMA_BUNDLE=<absolute-bundle-path>` before launching `enigma-native-host`. Native messaging manifests require an absolute executable path; they do not expand shell aliases, `~`, `$HOME`, `%USERPROFILE%`, or command arguments.
|
|
45
|
+
|
|
46
|
+
Resolve the absolute host executable path:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
command -v enigma-native-host
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Windows PowerShell:
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
(Get-Command enigma-native-host.cmd).Source
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Load the extension locally
|
|
59
|
+
|
|
60
|
+
### Chrome
|
|
61
|
+
|
|
62
|
+
1. Open `chrome://extensions`.
|
|
63
|
+
2. Enable **Developer mode**.
|
|
64
|
+
3. Select **Load unpacked**.
|
|
65
|
+
4. Choose `enigma/apps/browser-extension`.
|
|
66
|
+
5. Open the Enigma extension details and copy the 32-character extension ID.
|
|
67
|
+
|
|
68
|
+
### Microsoft Edge
|
|
69
|
+
|
|
70
|
+
1. Open `edge://extensions`.
|
|
71
|
+
2. Enable **Developer mode**.
|
|
72
|
+
3. Select **Load unpacked**.
|
|
73
|
+
4. Choose `enigma/apps/browser-extension`.
|
|
74
|
+
5. Open the Enigma extension details and copy the 32-character extension ID.
|
|
75
|
+
|
|
76
|
+
### Firefox
|
|
77
|
+
|
|
78
|
+
1. Open `about:debugging#/runtime/this-firefox`.
|
|
79
|
+
2. Select **Load Temporary Add-on**.
|
|
80
|
+
3. Choose `enigma/apps/browser-extension/manifest.json`.
|
|
81
|
+
4. Copy the temporary extension ID shown by Firefox. For repeatable development, use a stable development add-on ID and pass the same value to the native-host manifest generator.
|
|
82
|
+
|
|
83
|
+
## Generate the browser native-host manifest
|
|
84
|
+
|
|
85
|
+
Generate a manifest after you know the extension ID and absolute host path.
|
|
86
|
+
|
|
87
|
+
Chrome:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
enigma native-host manifest \
|
|
91
|
+
--browser chrome \
|
|
92
|
+
--host-path <absolute-enigma-native-host-path> \
|
|
93
|
+
--extension-id <chrome-extension-id> \
|
|
94
|
+
--out ./com.enigma.native_host.json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Edge:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
enigma native-host manifest \
|
|
101
|
+
--browser edge \
|
|
102
|
+
--host-path <absolute-enigma-native-host-path> \
|
|
103
|
+
--extension-id <edge-extension-id> \
|
|
104
|
+
--out ./com.enigma.native_host.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Firefox:
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
enigma native-host manifest \
|
|
111
|
+
--browser firefox \
|
|
112
|
+
--host-path <absolute-enigma-native-host-path> \
|
|
113
|
+
--extension-id <firefox-extension-id> \
|
|
114
|
+
--out ./com.enigma.native_host.json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Preview browser-specific install locations without mutating registry or profile state:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
enigma native-host install-plan \
|
|
121
|
+
--browser chrome \
|
|
122
|
+
--manifest <absolute-path-to-com.enigma.native_host.json>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Use `--browser edge` or `--browser firefox` for the other browsers. The install plan is a checklist: it does not copy manifests, write registry keys, or change browser profiles. Copy the generated manifest to the listed native messaging host location yourself, and on Windows review and run the listed registry command only when you are ready to register `com.enigma.native_host`.
|
|
126
|
+
|
|
127
|
+
## Register the native-host manifest locally
|
|
128
|
+
|
|
129
|
+
Use the paths from `enigma native-host install-plan` as the source of truth. These are the common manual targets:
|
|
130
|
+
|
|
131
|
+
### Chrome native host
|
|
132
|
+
|
|
133
|
+
- macOS per-user: `<home>/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.enigma.native_host.json`
|
|
134
|
+
- Linux per-user: `<home>/.config/google-chrome/NativeMessagingHosts/com.enigma.native_host.json`
|
|
135
|
+
- Windows per-user: copy the manifest to an operator-chosen local file, then set `HKCU\Software\Google\Chrome\NativeMessagingHosts\com.enigma.native_host` to that manifest path.
|
|
136
|
+
|
|
137
|
+
### Microsoft Edge native host
|
|
138
|
+
|
|
139
|
+
- macOS per-user: `<home>/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.enigma.native_host.json`
|
|
140
|
+
- Linux per-user: `<home>/.config/microsoft-edge/NativeMessagingHosts/com.enigma.native_host.json`
|
|
141
|
+
- Windows per-user: copy the manifest to an operator-chosen local file, then set `HKCU\Software\Microsoft\Edge\NativeMessagingHosts\com.enigma.native_host` to that manifest path.
|
|
142
|
+
|
|
143
|
+
### Firefox native host
|
|
144
|
+
|
|
145
|
+
- macOS per-user: `<home>/Library/Application Support/Mozilla/NativeMessagingHosts/com.enigma.native_host.json`
|
|
146
|
+
- Linux per-user: `<home>/.mozilla/native-messaging-hosts/com.enigma.native_host.json`
|
|
147
|
+
- Windows per-user: copy the manifest to an operator-chosen local file, then set `HKCU\Software\Mozilla\NativeMessagingHosts\com.enigma.native_host` to that manifest path.
|
|
148
|
+
|
|
149
|
+
All-users locations and registry hives are operator-managed deployment choices. Local developer install should prefer per-user targets unless an enterprise policy requires otherwise.
|
|
150
|
+
|
|
151
|
+
## Local insertion demo flow
|
|
152
|
+
|
|
153
|
+
1. Confirm the native-host manifest allowlist uses the extension ID from the local browser profile.
|
|
154
|
+
2. Restart the browser after native-host registration so it can discover `com.enigma.native_host`.
|
|
155
|
+
3. Visit a supported HTTPS provider page: ChatGPT, Claude, Kimi, or Perplexity.
|
|
156
|
+
4. Open the Enigma control shown by the content script.
|
|
157
|
+
5. Click **Request context**. The extension asks the local native host for a transient context pack; selected page text is included only if the user explicitly enables it for that request.
|
|
158
|
+
6. Review the returned context in the panel.
|
|
159
|
+
7. Click **Approve and insert** to insert plain text into the active prompt surface.
|
|
160
|
+
8. Submit to the provider only if you choose to. Enigma does not submit prompts for you.
|
|
161
|
+
|
|
162
|
+
After insertion, the extension records only target metadata, insertion timestamp, receipt metadata, and insertion counts. It must not write raw memory, context plaintext, or receipt plaintext into browser sync storage or public artifacts.
|
|
163
|
+
|
|
164
|
+
## Troubleshooting
|
|
165
|
+
|
|
166
|
+
- **Host not found**: confirm the manifest filename is `com.enigma.native_host.json`, the manifest `name` is `com.enigma.native_host`, and the browser-specific install location or registry key points to the manifest.
|
|
167
|
+
- **Host exits immediately**: confirm `ENIGMA_BUNDLE` is visible to the browser-launched process or use a local wrapper that sets it before launching `enigma-native-host`.
|
|
168
|
+
- **Extension cannot connect**: confirm the extension ID in the native-host manifest matches the locally loaded extension.
|
|
169
|
+
- **No insertion happens**: confirm you clicked both **Request context** and **Approve and insert**. The extension intentionally does not auto-inject.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Developer ecosystem
|
|
2
|
+
|
|
3
|
+
Enigma Memory is a local-first SDK, CLI, MCP server, and service-contract package. The developer surfaces are designed to be copied without secrets, cloud credentials, hidden local paths, or account identifiers.
|
|
4
|
+
|
|
5
|
+
## Copyable starting points
|
|
6
|
+
|
|
7
|
+
- SDK/API guide: [`docs/sdk-api.md`](./sdk-api.md)
|
|
8
|
+
- Node example app: [`examples/node-basic-memory.mjs`](../examples/node-basic-memory.mjs)
|
|
9
|
+
- GitHub Actions example: [`examples/ci/github-actions.yml`](../examples/ci/github-actions.yml)
|
|
10
|
+
- Generic MCP client template: [`templates/mcp-client-config.json`](../templates/mcp-client-config.json)
|
|
11
|
+
|
|
12
|
+
## Local SDK loop
|
|
13
|
+
|
|
14
|
+
Use the SDK when you want an app-owned vault and receipt-backed proof loop:
|
|
15
|
+
|
|
16
|
+
1. Create a local vault with `createVault`.
|
|
17
|
+
2. Add a generic, non-private memory with `remember`.
|
|
18
|
+
3. Create a passport with `createPassport`.
|
|
19
|
+
4. Compile a receipt-backed context pack with `compileContextPack`.
|
|
20
|
+
5. Export a proof-carrying bundle with `exportBundle`; keep full bundles private unless local import key material has been reviewed and removed.
|
|
21
|
+
6. Verify receipts with `verifyReceiptChain`, `enigma verify`, `enigma-verify`, or MCP `enigma_verify_receipts`.
|
|
22
|
+
|
|
23
|
+
The example app prints ids, counts, roots, and verification status only. It does not print raw memory text, generated key material, credentials, provider transcripts, or local absolute paths.
|
|
24
|
+
|
|
25
|
+
## CLI and CI loop
|
|
26
|
+
|
|
27
|
+
The CI example installs Node 24, installs the published `enigma-memory` package, runs:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
npx enigma quickstart --overwrite
|
|
31
|
+
npx enigma doctor
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
and then runs a small ESM import smoke. It does not require GitHub secrets, cloud provider credentials, npm tokens, private bundles, or local path assumptions.
|
|
35
|
+
|
|
36
|
+
Use the workflow as a template in a consumer repository. It is intentionally limited to install/import/doctor smoke coverage and local proof generation; it does not publish packages, deploy infrastructure, or contact hosted Enigma cloud.
|
|
37
|
+
|
|
38
|
+
## MCP client loop
|
|
39
|
+
|
|
40
|
+
The generic MCP template uses the installed `enigma-mcp` command and exactly one environment placeholder:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"enigma": {
|
|
46
|
+
"command": "enigma-mcp",
|
|
47
|
+
"env": {
|
|
48
|
+
"ENIGMA_BUNDLE": "<ENIGMA_BUNDLE>"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Replace `<ENIGMA_BUNDLE>` with the bundle file you control, or with the client-specific environment expansion syntax if your MCP client supports it. Do not commit private bundle paths if they reveal local usernames, workspace names, account ids, or other personal details.
|
|
56
|
+
|
|
57
|
+
## Claim boundaries for developers
|
|
58
|
+
|
|
59
|
+
Enigma proof artifacts cover Enigma-controlled or Enigma-mediated state: local vault events, receipts, active/tombstoned memory addresses, context-pack retrieval/injection receipts, relay/gateway records, usage events, and settlement receipts.
|
|
60
|
+
|
|
61
|
+
They do not prove:
|
|
62
|
+
|
|
63
|
+
- provider-side deletion;
|
|
64
|
+
- model forgetting;
|
|
65
|
+
- compliance certification;
|
|
66
|
+
- token ROI, investment outcome, or provider invoice savings;
|
|
67
|
+
- hosted-cloud readiness from a local demo;
|
|
68
|
+
- benchmark leadership from SDK mechanics alone.
|
|
69
|
+
|
|
70
|
+
Benchmark claims require benchmark-specific evidence. LoCoMo covers long-term conversational memory QA, event summarization, and multimodal generation across long conversations. LongMemEval covers extraction, multi-session reasoning, temporal reasoning, knowledge updates, and abstention. Agent-memory benchmark results can depend heavily on the agent/framework/tool loop, not only on the memory store. Keep those distinctions when writing integrations or public copy.
|
|
71
|
+
|
|
72
|
+
## What to keep out of examples
|
|
73
|
+
|
|
74
|
+
Do not add secrets, tokens, 2FA codes, cloud account ids, personal data, provider transcripts, raw private memory, absolute local paths, or unreviewed hosted endpoints to examples/templates. Public-safe examples should use generic ids, relative paths, placeholders, hashes, commitments, counts, receipt ids, and roots.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Hosted cloud product contract
|
|
2
|
+
|
|
3
|
+
This document separates the hosted-cloud product contract surface from the external systems still required before Enigma can sell or operate a hosted cloud service.
|
|
4
|
+
|
|
5
|
+
## Production contract-ready now
|
|
6
|
+
|
|
7
|
+
The source package now has pure contract builders and validators in `packages/hosted-cloud/src/index.js` for:
|
|
8
|
+
|
|
9
|
+
- user account records;
|
|
10
|
+
- tenant records;
|
|
11
|
+
- hosted vault records;
|
|
12
|
+
- API key metadata records;
|
|
13
|
+
- usage billing records;
|
|
14
|
+
- dashboard summaries;
|
|
15
|
+
- backup drill records;
|
|
16
|
+
- incident and SLA reference records.
|
|
17
|
+
|
|
18
|
+
These functions are contract and validation code only. They do not call an auth provider, billing provider, cloud deployment, KMS, backup target, support desk, status page, SIEM, or model provider. They are safe to import as package code because they do not start servers, read user files, mutate deployment state, publish packages, or contact external accounts.
|
|
19
|
+
|
|
20
|
+
The validators enforce hosted-cloud boundaries:
|
|
21
|
+
|
|
22
|
+
- contract artifacts must include `operator_evidence_refs` for auth provider, billing provider, legal docs, data processing terms, support ownership, and external security review;
|
|
23
|
+
- missing operator evidence references are rejected;
|
|
24
|
+
- raw memory, plaintext prompts, provider responses, transcripts, credential-looking values, token values, private keys, and API key secret material are rejected;
|
|
25
|
+
- financial outcome claims, token ROI/profit claims, provider-side deletion claims, and model-forgetting claims are rejected;
|
|
26
|
+
- API key contracts store identifiers, fingerprints, scopes, rotation refs, and timestamps only, not key material;
|
|
27
|
+
- hosted vault contracts are opaque-record and plaintext-minimized contracts only;
|
|
28
|
+
- billing records remain contract records until an external billing provider invoice flow is wired.
|
|
29
|
+
|
|
30
|
+
Every builder emits `readiness.contract_ready: true` and `readiness.integration_kind: "contract_validator_only"`. It also emits `readiness.hosted_cloud_sellable: false` because contract readiness is not provider wiring, legal approval, security review, or operator go-live approval.
|
|
31
|
+
|
|
32
|
+
## Externally blocked before hosted cloud can be sold
|
|
33
|
+
|
|
34
|
+
Hosted cloud remains blocked until an operator wires and records evidence for all of the following:
|
|
35
|
+
|
|
36
|
+
| Blocker | Required before selling hosted cloud |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| Auth provider | A real auth provider, tenant/user lifecycle, access-control rules, session/token handling, rotation, revocation, and audit evidence. |
|
|
39
|
+
| Billing provider | A real billing provider, customer/subscription mapping, invoice lifecycle, tax/legal handling, dunning/refund policy, and reconciliation evidence. |
|
|
40
|
+
| Legal docs | Approved hosted terms, privacy notice, service descriptions, acceptable-use terms, retention/deletion language, and claim review. |
|
|
41
|
+
| Data processing terms | Approved DPA or equivalent data-processing terms, subprocessors, data residency, retention, deletion, legal hold, and customer notice process. |
|
|
42
|
+
| Support ownership | Named support owner, escalation policy, incident owner, response process, status communication process, and support tooling. |
|
|
43
|
+
| External security review | External security review or audit scope, remediation tracking, approval record, and release sign-off. |
|
|
44
|
+
|
|
45
|
+
A `provided` operator evidence ref means the contract can point to external evidence. It still does not by itself make hosted cloud sellable; an operator must complete the release checklist and issue go-live approval. A `blocked_external_dependency` ref is an explicit blocker, not fake evidence.
|
|
46
|
+
|
|
47
|
+
## Non-claims
|
|
48
|
+
|
|
49
|
+
Hosted cloud collateral must not say or imply:
|
|
50
|
+
|
|
51
|
+
- Enigma has live hosted cloud tenants before provider wiring and operator acceptance exist;
|
|
52
|
+
- Enigma has made any model or provider forget data;
|
|
53
|
+
- Enigma has provider-side deletion proof;
|
|
54
|
+
- Enigma guarantees ROI, profit, investment return, token price movement, or invoice savings;
|
|
55
|
+
- Enigma has SOC 2, HIPAA, GDPR, or other compliance certification unless separately audited and approved;
|
|
56
|
+
- local/package evidence, contract validation, static docs, or dashboard summaries are live service evidence.
|
|
57
|
+
|
|
58
|
+
Safe wording:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
Enigma has hosted-cloud contract builders and validators for account, tenant, vault, API key, billing, dashboard, backup drill, and incident/SLA records. Hosted cloud remains blocked until auth, billing, legal/data-processing terms, support ownership, external security review, and operator go-live evidence are complete.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Avoid wording:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
Enigma hosted cloud is ready to sell because the contracts exist.
|
|
68
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Installers and desktop boundary
|
|
2
|
+
|
|
3
|
+
Enigma Memory currently has one production install tier and several source-asset tiers. This page is intentionally conservative: it documents what can be used now, what can be generated from source, and what is blocked before native installer distribution.
|
|
4
|
+
|
|
5
|
+
## Tier 1: npm package now
|
|
6
|
+
|
|
7
|
+
Use the published package path when you want the current supported local install:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install -g enigma-memory
|
|
11
|
+
enigma quickstart --bundle ./.enigma/bundle.json --overwrite
|
|
12
|
+
enigma doctor
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The package exposes the CLI bins `enigma`, `enigma-verify`, `enigma-mcp`, `enigma-relay`, `enigma-gateway`, and `enigma-native-host`. Node.js `>=24` is required. The local quickstart writes Enigma-controlled local artifacts only; it does not prove provider deletion, model forgetting, hosted availability, compliance certification, savings, or provider-native memory removal.
|
|
16
|
+
|
|
17
|
+
## Tier 2: generated source installer assets
|
|
18
|
+
|
|
19
|
+
The source checkout includes `scripts/build-installer-assets.mjs`, a dependency-free generator for reviewable installer source assets. Dry-run is the default:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
node scripts/build-installer-assets.mjs --out-dir dist/installer-assets
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Write mode is explicit:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
node scripts/build-installer-assets.mjs --out-dir dist/installer-assets --write
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Generated asset paths are listed in deterministic code-point lexical order:
|
|
32
|
+
|
|
33
|
+
- `homebrew/enigma-memory.rb` — Homebrew formula draft. It is not submitted to a tap by the generator; release engineering must replace the source archive URL and SHA before any tap workflow.
|
|
34
|
+
- `install-linux.sh` — POSIX shell source installer. It previews by default and only mutates global npm/local quickstart files when called with `--execute`.
|
|
35
|
+
- `install-windows.ps1` — PowerShell source installer. It previews by default and only runs `npm install -g enigma-memory`, `enigma quickstart`, and `enigma doctor` when called with `-Execute`.
|
|
36
|
+
- `installer-assets-manifest.json` — deterministic public manifest with checksums for the generated source assets.
|
|
37
|
+
- `macos-pkgbuild/README.md` — macOS package source plan and blockers, not a signed package.
|
|
38
|
+
- `macos-pkgbuild/manifest.json` — macOS package source metadata and blockers, not a signed package.
|
|
39
|
+
|
|
40
|
+
The generator intentionally redacts the requested output directory in its public manifest as `<requested-output-dir>`. The generated content must not embed tokens, local absolute paths, account identifiers, raw memory, provider transcripts, signing identities, or hosted credentials.
|
|
41
|
+
|
|
42
|
+
## Native `.exe` and `.pkg` blockers
|
|
43
|
+
|
|
44
|
+
No signed Windows `.exe` or signed/notarized macOS `.pkg` exists from this generator.
|
|
45
|
+
|
|
46
|
+
Windows `.exe` distribution is blocked on:
|
|
47
|
+
|
|
48
|
+
- A selected native installer builder and reproducible input tree.
|
|
49
|
+
- A Windows code-signing certificate and signing workflow.
|
|
50
|
+
- Release review that installer logs and metadata do not expose local paths, credentials, account data, raw memory, or provider transcripts.
|
|
51
|
+
|
|
52
|
+
macOS `.pkg` distribution is blocked on:
|
|
53
|
+
|
|
54
|
+
- macOS release runner access with `pkgbuild` and `productbuild`.
|
|
55
|
+
- A staged package layout for npm-installed command shims and package resources.
|
|
56
|
+
- Developer ID Installer certificate selection, signing, and notarization.
|
|
57
|
+
- Release review of package scripts and evidence output.
|
|
58
|
+
|
|
59
|
+
Until those blockers are cleared, use npm or generated source scripts only.
|
|
60
|
+
|
|
61
|
+
## Homebrew path
|
|
62
|
+
|
|
63
|
+
The formula generated under `homebrew/enigma-memory.rb` is a draft for a future tap workflow. It records the intended package name, license, Node dependency, command shims, and test shape. Before publication, release engineering must replace the placeholder tarball URL and SHA with a real release archive and confirm the formula installs only the intended package files.
|
|
64
|
+
|
|
65
|
+
## Desktop tray model boundary
|
|
66
|
+
|
|
67
|
+
`apps/desktop/src/tray.js` is a pure tray model module. It exposes deterministic state/menu/action helpers for:
|
|
68
|
+
|
|
69
|
+
- status
|
|
70
|
+
- quickstart
|
|
71
|
+
- connect clients
|
|
72
|
+
- open docs
|
|
73
|
+
- run diagnostics
|
|
74
|
+
- quit
|
|
75
|
+
|
|
76
|
+
It does not start a native tray process, create OS menu items, run shell commands, launch browsers, configure MCP clients, or quit a process. Host applications such as Electron, Tauri, WebView, or native wrappers must translate its action intents into real side effects and own their own OS integration, evidence capture, and shutdown behavior.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Memory benchmarks
|
|
2
|
+
|
|
3
|
+
Enigma includes a local, dependency-free memory benchmark harness for package-readiness evidence:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
cd enigma
|
|
7
|
+
node scripts/run-memory-benchmarks.mjs
|
|
8
|
+
node scripts/run-memory-benchmarks.mjs --out ./.enigma/memory-benchmark.json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The report schema is `enigma.memory_benchmark_suite.v1`. It is public-safe by design: aggregate metrics, commitments, citations, boundaries, and cross-provider profile labels are emitted, but raw fixture memory, question text, and answer text are not included.
|
|
12
|
+
|
|
13
|
+
## External standards and boundaries
|
|
14
|
+
|
|
15
|
+
- LoCoMo is the relevant long-term conversational-memory standard for multi-session QA, event summarization, and multimodal generation over long conversations. See https://snap-research.github.io/locomo/.
|
|
16
|
+
- LongMemEval is the relevant standard for information extraction, multi-session reasoning, temporal reasoning, knowledge updates, and abstention. See https://arxiv.org/abs/2410.10813.
|
|
17
|
+
- Letta's benchmark discussion is a useful boundary reminder: measured memory quality depends on the agent/framework/tool loop as well as memory-store mechanics. See https://www.letta.com/blog/benchmarking-ai-agent-memory/.
|
|
18
|
+
|
|
19
|
+
This repository harness does not download or run LoCoMo, LongMemEval, provider APIs, or third-party agents. It mirrors their task categories with a deterministic local fixture so Enigma can make narrow package claims about local vault operations, context-pack generation, optimizer token estimates, export/import, verification, deduplication, abstention behavior, and latency.
|
|
20
|
+
|
|
21
|
+
## What the harness measures
|
|
22
|
+
|
|
23
|
+
The fixture creates multiple sessions with facts, a knowledge update, temporal questions, an abstention question, duplicate memory candidates, and provider profile labels for `chatgpt`, `claude`, `kimi`, `cursor`, and `local-llm`.
|
|
24
|
+
|
|
25
|
+
The harness measures local Enigma operations only:
|
|
26
|
+
|
|
27
|
+
- vault remember/update operations;
|
|
28
|
+
- vault export and import;
|
|
29
|
+
- context-pack retrieval through the passport package;
|
|
30
|
+
- optimizer plan token estimates and duplicate removal;
|
|
31
|
+
- bundle and context-pack verification;
|
|
32
|
+
- p50/p95 latency with `performance.now`.
|
|
33
|
+
|
|
34
|
+
Reported metrics include exact-answer recall, abstention correctness, context-token reduction versus a full-context baseline, duplicate candidates removed, operation latency summaries, verification status, and same-boundary cross-provider profile rows.
|
|
35
|
+
|
|
36
|
+
## Claim limits
|
|
37
|
+
|
|
38
|
+
The benchmark report is evidence for this local deterministic fixture only. It is not provider deletion proof, model forgetting proof, compliance certification, ROI evidence, provider invoice savings evidence, benchmark leadership proof, hosted cloud readiness, or a substitute for external LoCoMo/LongMemEval evaluation.
|
|
39
|
+
|
|
40
|
+
Cross-provider rows are profile labels using the same Enigma context-pack boundary. They do not call or rank live provider models.
|
|
41
|
+
|
|
42
|
+
## Extending with external datasets later
|
|
43
|
+
|
|
44
|
+
To extend this harness with real external benchmark datasets without weakening claim boundaries:
|
|
45
|
+
|
|
46
|
+
1. Add an explicit dataset loader that reads a local file supplied by the operator; do not add network downloads to the benchmark command.
|
|
47
|
+
2. Preserve source license, version, split, and checksum metadata in the report.
|
|
48
|
+
3. Keep raw conversations, private memory, questions, and answers out of public reports unless the dataset license and review process explicitly allow publication.
|
|
49
|
+
4. Route every candidate through the same Enigma vault, context-pack, optimizer, export, and verify operations measured here.
|
|
50
|
+
5. Add separate agent/model evaluation only when the evaluated agent loop is fixed and documented; do not attribute agent/tool behavior solely to the memory store.
|
|
51
|
+
6. Keep release notes bounded to the observed command, dataset, timestamp, and review approval.
|