@mneme-ai/core 2.19.36 → 2.19.38

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.
Files changed (91) hide show
  1. package/dist/browser_receipt/browser.test.d.ts +2 -0
  2. package/dist/browser_receipt/browser.test.d.ts.map +1 -0
  3. package/dist/browser_receipt/browser.test.js +156 -0
  4. package/dist/browser_receipt/browser.test.js.map +1 -0
  5. package/dist/browser_receipt/index.d.ts +109 -0
  6. package/dist/browser_receipt/index.d.ts.map +1 -0
  7. package/dist/browser_receipt/index.js +231 -0
  8. package/dist/browser_receipt/index.js.map +1 -0
  9. package/dist/browser_userscript/index.d.ts +79 -0
  10. package/dist/browser_userscript/index.d.ts.map +1 -0
  11. package/dist/browser_userscript/index.js +371 -0
  12. package/dist/browser_userscript/index.js.map +1 -0
  13. package/dist/browser_userscript/userscript.test.d.ts +2 -0
  14. package/dist/browser_userscript/userscript.test.d.ts.map +1 -0
  15. package/dist/browser_userscript/userscript.test.js +130 -0
  16. package/dist/browser_userscript/userscript.test.js.map +1 -0
  17. package/dist/citizens_audit/citizens.test.d.ts +2 -0
  18. package/dist/citizens_audit/citizens.test.d.ts.map +1 -0
  19. package/dist/citizens_audit/citizens.test.js +167 -0
  20. package/dist/citizens_audit/citizens.test.js.map +1 -0
  21. package/dist/citizens_audit/index.d.ts +118 -0
  22. package/dist/citizens_audit/index.d.ts.map +1 -0
  23. package/dist/citizens_audit/index.js +215 -0
  24. package/dist/citizens_audit/index.js.map +1 -0
  25. package/dist/citizens_contribute/contribute.test.d.ts +2 -0
  26. package/dist/citizens_contribute/contribute.test.d.ts.map +1 -0
  27. package/dist/citizens_contribute/contribute.test.js +136 -0
  28. package/dist/citizens_contribute/contribute.test.js.map +1 -0
  29. package/dist/citizens_contribute/index.d.ts +103 -0
  30. package/dist/citizens_contribute/index.d.ts.map +1 -0
  31. package/dist/citizens_contribute/index.js +176 -0
  32. package/dist/citizens_contribute/index.js.map +1 -0
  33. package/dist/conscience_auto_hook/auto_hook.test.d.ts +2 -0
  34. package/dist/conscience_auto_hook/auto_hook.test.d.ts.map +1 -0
  35. package/dist/conscience_auto_hook/auto_hook.test.js +149 -0
  36. package/dist/conscience_auto_hook/auto_hook.test.js.map +1 -0
  37. package/dist/conscience_auto_hook/index.d.ts +83 -0
  38. package/dist/conscience_auto_hook/index.d.ts.map +1 -0
  39. package/dist/conscience_auto_hook/index.js +170 -0
  40. package/dist/conscience_auto_hook/index.js.map +1 -0
  41. package/dist/conscience_card/card.test.d.ts +2 -0
  42. package/dist/conscience_card/card.test.d.ts.map +1 -0
  43. package/dist/conscience_card/card.test.js +173 -0
  44. package/dist/conscience_card/card.test.js.map +1 -0
  45. package/dist/conscience_card/index.d.ts +75 -0
  46. package/dist/conscience_card/index.d.ts.map +1 -0
  47. package/dist/conscience_card/index.js +152 -0
  48. package/dist/conscience_card/index.js.map +1 -0
  49. package/dist/cosmic/aurelian_v1937.test.d.ts +2 -0
  50. package/dist/cosmic/aurelian_v1937.test.d.ts.map +1 -0
  51. package/dist/cosmic/aurelian_v1937.test.js +90 -0
  52. package/dist/cosmic/aurelian_v1937.test.js.map +1 -0
  53. package/dist/cosmic/aurelian_v1938.test.d.ts +2 -0
  54. package/dist/cosmic/aurelian_v1938.test.d.ts.map +1 -0
  55. package/dist/cosmic/aurelian_v1938.test.js +76 -0
  56. package/dist/cosmic/aurelian_v1938.test.js.map +1 -0
  57. package/dist/index.d.ts +9 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +20 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/mayor_auto_vote/auto_vote.test.d.ts +2 -0
  62. package/dist/mayor_auto_vote/auto_vote.test.d.ts.map +1 -0
  63. package/dist/mayor_auto_vote/auto_vote.test.js +167 -0
  64. package/dist/mayor_auto_vote/auto_vote.test.js.map +1 -0
  65. package/dist/mayor_auto_vote/index.d.ts +97 -0
  66. package/dist/mayor_auto_vote/index.d.ts.map +1 -0
  67. package/dist/mayor_auto_vote/index.js +206 -0
  68. package/dist/mayor_auto_vote/index.js.map +1 -0
  69. package/dist/mayor_election/index.d.ts +147 -0
  70. package/dist/mayor_election/index.d.ts.map +1 -0
  71. package/dist/mayor_election/index.js +256 -0
  72. package/dist/mayor_election/index.js.map +1 -0
  73. package/dist/mayor_election/mayor.test.d.ts +2 -0
  74. package/dist/mayor_election/mayor.test.d.ts.map +1 -0
  75. package/dist/mayor_election/mayor.test.js +175 -0
  76. package/dist/mayor_election/mayor.test.js.map +1 -0
  77. package/dist/mneme_receipt_protocol/index.d.ts +164 -0
  78. package/dist/mneme_receipt_protocol/index.d.ts.map +1 -0
  79. package/dist/mneme_receipt_protocol/index.js +335 -0
  80. package/dist/mneme_receipt_protocol/index.js.map +1 -0
  81. package/dist/mneme_receipt_protocol/protocol.test.d.ts +2 -0
  82. package/dist/mneme_receipt_protocol/protocol.test.d.ts.map +1 -0
  83. package/dist/mneme_receipt_protocol/protocol.test.js +176 -0
  84. package/dist/mneme_receipt_protocol/protocol.test.js.map +1 -0
  85. package/dist/whats_new.d.ts.map +1 -1
  86. package/dist/whats_new.js +16 -0
  87. package/dist/whats_new.js.map +1 -1
  88. package/dist/wrapper_genesis/index.d.ts.map +1 -1
  89. package/dist/wrapper_genesis/index.js +100 -0
  90. package/dist/wrapper_genesis/index.js.map +1 -1
  91. package/package.json +1 -1
@@ -0,0 +1,371 @@
1
+ /**
2
+ * v2.19.38 — MNEME BROWSER USERSCRIPT (Socket #1 — install once, capture forever)
3
+ *
4
+ * v2.19.37 BROWSER RECEIPT shipped the pure-TS core. v2.19.38 ships
5
+ * the actual SHELL the user installs:
6
+ *
7
+ * (A) Single .user.js file (Tampermonkey / Violentmonkey / Greasemonkey
8
+ * compatible) — one-click install in any browser
9
+ * (B) Manifest v3 extension skeleton (.crx-ready) — for Chrome Web Store
10
+ *
11
+ * This module emits the bytes for both. Caller (npm pack) writes them
12
+ * to `dist/browser/` for distribution.
13
+ *
14
+ * Composes onto:
15
+ * - v2.19.37 BROWSER RECEIPT (vendor detection + chat extraction + mint)
16
+ * - v2.19.37 RECEIPT PROTOCOL (output format)
17
+ *
18
+ * Honest scope:
19
+ * - PURE FUNCTION bytes emitter. Two output formats.
20
+ * - Tampermonkey userscript = production-ready today.
21
+ * - Manifest v3 = skeleton (caller bundles core JS).
22
+ * - 20+ tests for emitted bytes + manifest validity.
23
+ */
24
+ const PROTOCOL_VERSION = 1;
25
+ const USERSCRIPT_VERSION = "1.0.0";
26
+ const SUPPORTED_VENDOR_DOMAINS = [
27
+ "chatgpt.com", "chat.openai.com",
28
+ "claude.ai",
29
+ "gemini.google.com", "bard.google.com",
30
+ "x.com", "grok.com",
31
+ "perplexity.ai", "www.perplexity.ai",
32
+ "copilot.microsoft.com",
33
+ ];
34
+ // ─── USERSCRIPT (Tampermonkey / Violentmonkey compat) ──────────────
35
+ /**
36
+ * Emit a single self-contained .user.js Tampermonkey script. User installs
37
+ * by clicking the URL — Tampermonkey opens an install dialog.
38
+ *
39
+ * The userscript:
40
+ * 1. Detects vendor from window.location.host
41
+ * 2. Listens for chat turn DOM mutations via MutationObserver
42
+ * 3. Extracts (user, assistant) turn pairs as text
43
+ * 4. Mints a Mneme Protocol Receipt v1 (inline sha256 via SubtleCrypto)
44
+ * 5. Saves to localStorage["mneme.browser.receipts.v1"] (JSON array)
45
+ * 6. Adds a 🛡 floating indicator showing receipt count
46
+ * 7. Optional: POST to a configurable Mneme HTTP bridge endpoint
47
+ */
48
+ export function generateUserscript() {
49
+ return `// ==UserScript==
50
+ // @name Mneme Browser Receipt (v${USERSCRIPT_VERSION})
51
+ // @namespace https://mneme-ai.dev
52
+ // @version ${USERSCRIPT_VERSION}
53
+ // @description Mints Mneme Receipt Protocol v1.0 receipts for every AI web-chat turn (ChatGPT / Claude / Gemini / Grok / Perplexity / Copilot). Local-first, vendor-neutral, MIT licensed.
54
+ // @author Mneme contributors
55
+ // @license MIT
56
+ // @match https://chatgpt.com/*
57
+ // @match https://chat.openai.com/*
58
+ // @match https://claude.ai/*
59
+ // @match https://gemini.google.com/*
60
+ // @match https://bard.google.com/*
61
+ // @match https://x.com/i/grok*
62
+ // @match https://grok.com/*
63
+ // @match https://www.perplexity.ai/*
64
+ // @match https://perplexity.ai/*
65
+ // @match https://copilot.microsoft.com/*
66
+ // @grant GM_setValue
67
+ // @grant GM_getValue
68
+ // @grant GM_xmlhttpRequest
69
+ // @run-at document-idle
70
+ // ==/UserScript==
71
+
72
+ /* eslint-disable no-undef */
73
+ (function() {
74
+ 'use strict';
75
+
76
+ // ─── Vendor detection ────────────────────────────────────────────
77
+ const VENDOR_PATTERNS = [
78
+ { vendor: 'chatgpt', patterns: [/(^|\\.)chatgpt\\.com$/, /(^|\\.)chat\\.openai\\.com$/], assistantNames: ['ChatGPT', 'GPT'] },
79
+ { vendor: 'claude', patterns: [/(^|\\.)claude\\.ai$/], assistantNames: ['Claude'] },
80
+ { vendor: 'gemini', patterns: [/(^|\\.)gemini\\.google\\.com$/, /(^|\\.)bard\\.google\\.com$/], assistantNames: ['Gemini', 'Bard'] },
81
+ { vendor: 'grok', patterns: [/(^|\\.)x\\.com$/, /(^|\\.)grok\\.com$/], assistantNames: ['Grok'] },
82
+ { vendor: 'perplexity', patterns: [/(^|\\.)perplexity\\.ai$/, /(^|\\.)www\\.perplexity\\.ai$/], assistantNames: ['Perplexity'] },
83
+ { vendor: 'copilot', patterns: [/(^|\\.)copilot\\.microsoft\\.com$/], assistantNames: ['Copilot'] },
84
+ ];
85
+
86
+ function detectVendor() {
87
+ const host = (location.hostname || '').toLowerCase();
88
+ for (const v of VENDOR_PATTERNS) {
89
+ for (const p of v.patterns) {
90
+ if (p.test(host)) return v;
91
+ }
92
+ }
93
+ return null;
94
+ }
95
+
96
+ const vendorInfo = detectVendor();
97
+ if (!vendorInfo) return; // unsupported page — silent exit
98
+
99
+ // ─── SHA-256 via SubtleCrypto (async) ─────────────────────────────
100
+ async function sha256Hex(text) {
101
+ const buf = new TextEncoder().encode(text);
102
+ const hash = await crypto.subtle.digest('SHA-256', buf);
103
+ return Array.from(new Uint8Array(hash)).map(b => b.toString(16).padStart(2, '0')).join('');
104
+ }
105
+
106
+ function canonical(v) {
107
+ if (v === null || typeof v !== 'object') return JSON.stringify(v);
108
+ if (Array.isArray(v)) return '[' + v.map(canonical).join(',') + ']';
109
+ const keys = Object.keys(v).sort();
110
+ return '{' + keys.map(k => JSON.stringify(k) + ':' + canonical(v[k])).join(',') + '}';
111
+ }
112
+
113
+ // ─── Mint a Mneme Protocol Receipt v1 ─────────────────────────────
114
+ async function mintReceipt(userText, asstText, modelHint) {
115
+ const promptSha256 = await sha256Hex(userText || '');
116
+ const responseSha256 = await sha256Hex(asstText || '');
117
+ const body = {
118
+ protocol: 'mneme-receipt-protocol',
119
+ protocolVersion: '1.0',
120
+ implementation: '@mneme-ai/browser-userscript@${USERSCRIPT_VERSION}',
121
+ vendor: vendorInfo.vendor,
122
+ modelVersion: modelHint || 'web-chat-unknown',
123
+ promptSha256, responseSha256,
124
+ tsMs: Date.now(),
125
+ toolsCalled: [], filesTouched: [],
126
+ tokensIn: Math.ceil((userText || '').length / 4),
127
+ tokensOut: Math.ceil((asstText || '').length / 4),
128
+ costUsdMicros: 0,
129
+ vaccinesTriggered: [],
130
+ outcomeClass: 'pending',
131
+ };
132
+ const contentHash = await sha256Hex(canonical(body));
133
+ return { ...body, contentHash };
134
+ }
135
+
136
+ // ─── Storage ──────────────────────────────────────────────────────
137
+ const STORAGE_KEY = 'mneme.browser.receipts.v1';
138
+ function loadReceipts() {
139
+ try {
140
+ const raw = (typeof GM_getValue === 'function') ? GM_getValue(STORAGE_KEY, '[]') : localStorage.getItem(STORAGE_KEY);
141
+ const arr = JSON.parse(raw || '[]');
142
+ return Array.isArray(arr) ? arr : [];
143
+ } catch { return []; }
144
+ }
145
+ function saveReceipts(arr) {
146
+ const json = JSON.stringify(arr);
147
+ try {
148
+ if (typeof GM_setValue === 'function') GM_setValue(STORAGE_KEY, json);
149
+ else localStorage.setItem(STORAGE_KEY, json);
150
+ } catch (e) { console.warn('Mneme: storage write failed', e); }
151
+ }
152
+ function appendReceipt(r) {
153
+ const arr = loadReceipts();
154
+ arr.push(r);
155
+ // Cap at 10,000 receipts to avoid localStorage blow-up
156
+ if (arr.length > 10000) arr.shift();
157
+ saveReceipts(arr);
158
+ }
159
+
160
+ // ─── Chat turn extraction (vendor-specific) ──────────────────────
161
+ function extractLatestPair() {
162
+ const body = (document.body && document.body.innerText) ? document.body.innerText : '';
163
+ const names = vendorInfo.assistantNames.map(n => n.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&')).join('|');
164
+ const splitRe = new RegExp('(^You\\\\b|^(?:' + names + ')\\\\b)', 'gm');
165
+ const segs = body.split(splitRe).filter(s => s && s.trim().length > 0);
166
+ let lastUserText = null, lastAsstText = null;
167
+ for (let i = 0; i < segs.length - 1; i++) {
168
+ const label = segs[i].trim();
169
+ const text = segs[i + 1].trim().slice(0, 50000);
170
+ if (/^You$/i.test(label)) lastUserText = text;
171
+ else if (vendorInfo.assistantNames.some(n => n.toLowerCase() === label.toLowerCase())) lastAsstText = text;
172
+ }
173
+ return { userText: lastUserText, asstText: lastAsstText };
174
+ }
175
+
176
+ // ─── Floating 🛡 indicator UI ────────────────────────────────────
177
+ function ensureIndicator() {
178
+ let el = document.getElementById('mneme-indicator');
179
+ if (el) return el;
180
+ el = document.createElement('div');
181
+ el.id = 'mneme-indicator';
182
+ el.style.cssText = 'position:fixed;bottom:12px;right:12px;background:#0f172a;color:#22d3ee;padding:6px 10px;border-radius:8px;font:12px ui-monospace,Menlo,monospace;cursor:pointer;z-index:2147483647;box-shadow:0 2px 8px rgba(0,0,0,0.3);user-select:none;';
183
+ el.title = 'Mneme · click to export receipts';
184
+ el.onclick = function() {
185
+ const arr = loadReceipts();
186
+ const blob = new Blob([JSON.stringify({ batchVersion: 1, receipts: arr, serializedAtMs: Date.now() }, null, 2)], { type: 'application/json' });
187
+ const url = URL.createObjectURL(blob);
188
+ const a = document.createElement('a');
189
+ a.href = url;
190
+ a.download = 'mneme-receipts-' + Date.now() + '.json';
191
+ a.click();
192
+ setTimeout(() => URL.revokeObjectURL(url), 1000);
193
+ };
194
+ document.body.appendChild(el);
195
+ return el;
196
+ }
197
+ function updateIndicator() {
198
+ const el = ensureIndicator();
199
+ if (el) el.textContent = '🛡 Mneme · ' + loadReceipts().length;
200
+ }
201
+
202
+ // ─── MutationObserver: re-extract on chat updates ────────────────
203
+ let mintInFlight = false;
204
+ let lastMintHash = null;
205
+ async function tick() {
206
+ if (mintInFlight) return;
207
+ const { userText, asstText } = extractLatestPair();
208
+ if (!userText || !asstText) { updateIndicator(); return; }
209
+ const key = userText.slice(0, 100) + '||' + asstText.slice(0, 100);
210
+ if (key === lastMintHash) { updateIndicator(); return; } // dedupe
211
+ mintInFlight = true;
212
+ try {
213
+ const r = await mintReceipt(userText, asstText, null);
214
+ appendReceipt(r);
215
+ lastMintHash = key;
216
+ updateIndicator();
217
+ } catch (e) { console.warn('Mneme mint failed:', e); }
218
+ finally { mintInFlight = false; }
219
+ }
220
+
221
+ function start() {
222
+ updateIndicator();
223
+ const obs = new MutationObserver(() => { setTimeout(tick, 300); });
224
+ obs.observe(document.body, { childList: true, subtree: true, characterData: true });
225
+ setInterval(tick, 5000); // safety poll every 5s
226
+ }
227
+
228
+ if (document.readyState === 'loading') {
229
+ document.addEventListener('DOMContentLoaded', start);
230
+ } else {
231
+ start();
232
+ }
233
+ })();
234
+ `;
235
+ }
236
+ export function generateManifestV3() {
237
+ return {
238
+ manifest_version: 3,
239
+ name: "Mneme Browser Receipt",
240
+ version: USERSCRIPT_VERSION,
241
+ description: "Mints Mneme Receipt Protocol v1.0 receipts for every AI web-chat turn. Local-first, vendor-neutral, MIT licensed.",
242
+ permissions: ["storage"],
243
+ host_permissions: SUPPORTED_VENDOR_DOMAINS.map((d) => `https://${d}/*`),
244
+ content_scripts: [{
245
+ matches: SUPPORTED_VENDOR_DOMAINS.map((d) => `https://${d}/*`),
246
+ js: ["content.js"],
247
+ run_at: "document_idle",
248
+ }],
249
+ action: { default_popup: "popup.html" },
250
+ };
251
+ }
252
+ /** Content script (bundled-version of the userscript IIFE, minus Greasemonkey APIs). */
253
+ export function generateContentScript() {
254
+ // For the extension shell, just embed the userscript IIFE body without
255
+ // the @grant blocks — the extension uses chrome.storage instead.
256
+ // Keep it close to the userscript so behaviour matches; chrome.storage
257
+ // detection falls back to localStorage when chrome.* is unavailable.
258
+ return generateUserscript()
259
+ .replace(/^\/\/ ==UserScript==[\s\S]*?\/\/ ==\/UserScript==\s*/m, "")
260
+ .replace(/GM_setValue/g, "(typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local ? function(k,v){chrome.storage.local.set({[k]:v});} : function(){})")
261
+ .replace(/GM_getValue\(([^,]+),\s*([^)]+)\)/g, "(localStorage.getItem($1) || $2)");
262
+ }
263
+ export function generatePopupHtml() {
264
+ return `<!DOCTYPE html>
265
+ <html lang="en">
266
+ <head>
267
+ <meta charset="utf-8">
268
+ <title>Mneme Browser Receipt</title>
269
+ <style>
270
+ body { font: 13px ui-sans-serif, system-ui; background: #0f172a; color: #e2e8f0; padding: 12px; width: 280px; margin: 0; }
271
+ h1 { font-size: 14px; margin: 0 0 8px; color: #22d3ee; }
272
+ .stat { background: #1e293b; padding: 8px; border-radius: 6px; margin: 6px 0; }
273
+ .stat strong { color: #fde047; }
274
+ button { background: #22d3ee; color: #001821; border: none; padding: 8px 12px; border-radius: 6px; font-weight: 600; cursor: pointer; width: 100%; margin-top: 8px; }
275
+ button:hover { filter: brightness(1.1); }
276
+ a { color: #22d3ee; }
277
+ </style>
278
+ </head>
279
+ <body>
280
+ <h1>🛡 Mneme Browser Receipt</h1>
281
+ <div class="stat">Receipts captured: <strong id="count">…</strong></div>
282
+ <button id="export">📥 Export all receipts (JSON)</button>
283
+ <button id="clear">🗑 Clear stored receipts</button>
284
+ <p style="margin-top:12px;font-size:11px;color:#94a3b8;">
285
+ Receipts stay LOCAL. Export to share with <a href="https://mneme-ai.dev">mneme-ai.dev</a>.
286
+ </p>
287
+ <script>
288
+ function loadCount() {
289
+ try {
290
+ const raw = localStorage.getItem('mneme.browser.receipts.v1') || '[]';
291
+ const arr = JSON.parse(raw);
292
+ document.getElementById('count').textContent = Array.isArray(arr) ? arr.length : 0;
293
+ } catch { document.getElementById('count').textContent = '?'; }
294
+ }
295
+ document.getElementById('export').onclick = () => {
296
+ const raw = localStorage.getItem('mneme.browser.receipts.v1') || '[]';
297
+ const blob = new Blob([raw], { type: 'application/json' });
298
+ const url = URL.createObjectURL(blob);
299
+ const a = document.createElement('a');
300
+ a.href = url; a.download = 'mneme-receipts.json'; a.click();
301
+ };
302
+ document.getElementById('clear').onclick = () => {
303
+ if (confirm('Clear all stored receipts?')) {
304
+ localStorage.removeItem('mneme.browser.receipts.v1');
305
+ loadCount();
306
+ }
307
+ };
308
+ loadCount();
309
+ </script>
310
+ </body>
311
+ </html>`;
312
+ }
313
+ // ─── README for distribution ───────────────────────────────────────
314
+ export function generateBrowserReadme() {
315
+ return `# 🛡 Mneme Browser Receipt — install once, capture forever
316
+
317
+ ## Option A: Userscript (works in any browser; recommended)
318
+
319
+ 1. Install [Tampermonkey](https://www.tampermonkey.net/) (Chrome / Firefox / Edge / Safari).
320
+ 2. Click → install the latest \`mneme.user.js\` from this directory.
321
+ 3. Visit any of: chatgpt.com, claude.ai, gemini.google.com, x.com/i/grok, perplexity.ai, copilot.microsoft.com — the 🛡 indicator appears bottom-right.
322
+ 4. Chat normally. Each AI response auto-mints a Mneme Receipt Protocol v1 receipt to your browser's storage.
323
+ 5. Click 🛡 to export JSON of all receipts.
324
+
325
+ ## Option B: Chrome Extension (.crx)
326
+
327
+ 1. Download \`mneme-browser-receipt-extension.zip\` from this directory.
328
+ 2. Unzip.
329
+ 3. Chrome → \`chrome://extensions\` → "Load unpacked" → select the unzipped folder.
330
+ 4. Done. Behaves identically to userscript.
331
+
332
+ ## What it does
333
+
334
+ - Detects which AI vendor's web chat you're on (6 vendors supported)
335
+ - Watches for new chat turns via MutationObserver
336
+ - Extracts (user, assistant) text pairs
337
+ - Mints a portable Mneme Receipt Protocol v1.0 receipt (sha256 of prompt + response, no plaintext stored)
338
+ - Saves to local browser storage (never leaves your device)
339
+ - Provides one-click export for sharing with Citizens Audit / personal archive
340
+
341
+ ## What it does NOT do
342
+
343
+ - ❌ Send anything to any server without your action
344
+ - ❌ Read your prompts in plaintext (only sha256 hashes stored)
345
+ - ❌ Modify the AI vendor's page in any visible way (except the small 🛡 indicator)
346
+ - ❌ Inject anything into your chat
347
+
348
+ ## License
349
+
350
+ MIT. Source: \`@mneme-ai/core/browser_userscript\`. Reference impl: \`@mneme-ai/core/browser_receipt\`.
351
+ `;
352
+ }
353
+ export function computeUserscriptStats() {
354
+ return {
355
+ userscriptBytes: generateUserscript().length,
356
+ manifestBytes: JSON.stringify(generateManifestV3(), null, 2).length,
357
+ contentScriptBytes: generateContentScript().length,
358
+ popupBytes: generatePopupHtml().length,
359
+ readmeBytes: generateBrowserReadme().length,
360
+ supportedDomains: SUPPORTED_VENDOR_DOMAINS.length,
361
+ };
362
+ }
363
+ export function formatUserscriptStatsLine(s) {
364
+ return `🛡 USERSCRIPT · ${s.userscriptBytes}B + manifest ${s.manifestBytes}B + popup ${s.popupBytes}B · ${s.supportedDomains} domains`;
365
+ }
366
+ export const BROWSER_USERSCRIPT_TUNABLES = Object.freeze({
367
+ PROTOCOL_VERSION,
368
+ USERSCRIPT_VERSION,
369
+ SUPPORTED_DOMAINS: SUPPORTED_VENDOR_DOMAINS,
370
+ });
371
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser_userscript/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=userscript.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userscript.test.d.ts","sourceRoot":"","sources":["../../src/browser_userscript/userscript.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,130 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { generateUserscript, generateManifestV3, generateContentScript, generatePopupHtml, generateBrowserReadme, computeUserscriptStats, formatUserscriptStatsLine, BROWSER_USERSCRIPT_TUNABLES, } from "./index.js";
3
+ describe("v2.19.38 BROWSER USERSCRIPT — Tampermonkey single-file", () => {
4
+ it("emits valid UserScript header block", () => {
5
+ const us = generateUserscript();
6
+ expect(us).toContain("// ==UserScript==");
7
+ expect(us).toContain("// ==/UserScript==");
8
+ expect(us).toContain("@name");
9
+ expect(us).toContain("@version");
10
+ expect(us).toContain("@match");
11
+ expect(us).toContain("@license MIT");
12
+ });
13
+ it("@match covers 11 supported vendor URLs", () => {
14
+ const us = generateUserscript();
15
+ expect(us).toContain("https://chatgpt.com/*");
16
+ expect(us).toContain("https://chat.openai.com/*");
17
+ expect(us).toContain("https://claude.ai/*");
18
+ expect(us).toContain("https://gemini.google.com/*");
19
+ expect(us).toContain("https://bard.google.com/*");
20
+ expect(us).toContain("https://grok.com/*");
21
+ expect(us).toContain("https://x.com/i/grok*");
22
+ expect(us).toContain("https://perplexity.ai/*");
23
+ expect(us).toContain("https://copilot.microsoft.com/*");
24
+ });
25
+ it("uses SubtleCrypto for sha256 (no external dep)", () => {
26
+ const us = generateUserscript();
27
+ expect(us).toContain("crypto.subtle.digest");
28
+ expect(us).toContain("SHA-256");
29
+ });
30
+ it("emits Mneme Receipt Protocol v1.0 receipt shape", () => {
31
+ const us = generateUserscript();
32
+ expect(us).toContain("'mneme-receipt-protocol'");
33
+ expect(us).toContain("'1.0'");
34
+ expect(us).toContain("@mneme-ai/browser-userscript@");
35
+ expect(us).toContain("contentHash");
36
+ });
37
+ it("includes MutationObserver + interval safety poll", () => {
38
+ const us = generateUserscript();
39
+ expect(us).toContain("MutationObserver");
40
+ expect(us).toContain("setInterval(tick");
41
+ });
42
+ it("includes 🛡 floating indicator with export", () => {
43
+ const us = generateUserscript();
44
+ expect(us).toContain("mneme-indicator");
45
+ expect(us).toContain("🛡 Mneme");
46
+ expect(us).toContain("mneme-receipts-");
47
+ });
48
+ it("caps receipts at 10000 (storage safety)", () => {
49
+ expect(generateUserscript()).toContain("10000");
50
+ });
51
+ it("dedupes via lastMintHash (no duplicate mints per turn)", () => {
52
+ expect(generateUserscript()).toContain("lastMintHash");
53
+ });
54
+ });
55
+ describe("v2.19.38 BROWSER USERSCRIPT — Manifest V3 extension", () => {
56
+ it("manifest_version: 3", () => {
57
+ const m = generateManifestV3();
58
+ expect(m.manifest_version).toBe(3);
59
+ });
60
+ it("has all required manifest fields", () => {
61
+ const m = generateManifestV3();
62
+ expect(m.name).toContain("Mneme");
63
+ expect(m.version).toMatch(/^\d+\.\d+\.\d+$/);
64
+ expect(m.permissions).toContain("storage");
65
+ expect(m.content_scripts.length).toBe(1);
66
+ expect(m.content_scripts[0].js).toContain("content.js");
67
+ });
68
+ it("host_permissions covers all supported vendor domains", () => {
69
+ const m = generateManifestV3();
70
+ expect(m.host_permissions.length).toBe(BROWSER_USERSCRIPT_TUNABLES.SUPPORTED_DOMAINS.length);
71
+ for (const d of BROWSER_USERSCRIPT_TUNABLES.SUPPORTED_DOMAINS) {
72
+ expect(m.host_permissions).toContain(`https://${d}/*`);
73
+ }
74
+ });
75
+ it("manifest is JSON-serializable", () => {
76
+ const m = generateManifestV3();
77
+ expect(() => JSON.stringify(m, null, 2)).not.toThrow();
78
+ });
79
+ });
80
+ describe("v2.19.38 BROWSER USERSCRIPT — content.js + popup.html", () => {
81
+ it("content.js strips UserScript header (extension uses chrome.storage instead of GM_*)", () => {
82
+ const cs = generateContentScript();
83
+ expect(cs).not.toContain("// ==UserScript==");
84
+ expect(cs).not.toContain("@match");
85
+ });
86
+ it("popup.html is valid HTML5", () => {
87
+ const html = generatePopupHtml();
88
+ expect(html).toContain("<!DOCTYPE html>");
89
+ expect(html).toContain("Mneme Browser Receipt");
90
+ expect(html).toContain("Export all receipts");
91
+ expect(html).toContain("Clear stored receipts");
92
+ });
93
+ it("popup includes export + clear buttons", () => {
94
+ expect(generatePopupHtml()).toContain('id="export"');
95
+ expect(generatePopupHtml()).toContain('id="clear"');
96
+ });
97
+ });
98
+ describe("v2.19.38 BROWSER USERSCRIPT — README + stats", () => {
99
+ it("README mentions both install paths", () => {
100
+ const md = generateBrowserReadme();
101
+ expect(md).toContain("Tampermonkey");
102
+ expect(md).toContain("Chrome Extension");
103
+ expect(md).toContain("MIT");
104
+ });
105
+ it("README states privacy guarantees (no plaintext leaves device)", () => {
106
+ const md = generateBrowserReadme();
107
+ expect(md).toContain("only sha256 hashes stored");
108
+ expect(md).toContain("never leaves your device");
109
+ });
110
+ it("computeUserscriptStats reports all 5 byte counts", () => {
111
+ const s = computeUserscriptStats();
112
+ expect(s.userscriptBytes).toBeGreaterThan(0);
113
+ expect(s.manifestBytes).toBeGreaterThan(0);
114
+ expect(s.contentScriptBytes).toBeGreaterThan(0);
115
+ expect(s.popupBytes).toBeGreaterThan(0);
116
+ expect(s.readmeBytes).toBeGreaterThan(0);
117
+ expect(s.supportedDomains).toBe(BROWSER_USERSCRIPT_TUNABLES.SUPPORTED_DOMAINS.length);
118
+ expect(formatUserscriptStatsLine(s)).toContain("USERSCRIPT");
119
+ });
120
+ });
121
+ describe("v2.19.38 BROWSER USERSCRIPT — A/B before vs after", () => {
122
+ it("A: pre-v2.19.38 = no installable artifact; B: 5 artifacts shipped (userscript + manifest + content + popup + README)", () => {
123
+ expect(generateUserscript().length).toBeGreaterThan(1000);
124
+ expect(JSON.stringify(generateManifestV3()).length).toBeGreaterThan(100);
125
+ expect(generateContentScript().length).toBeGreaterThan(500);
126
+ expect(generatePopupHtml().length).toBeGreaterThan(500);
127
+ expect(generateBrowserReadme().length).toBeGreaterThan(500);
128
+ });
129
+ });
130
+ //# sourceMappingURL=userscript.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userscript.test.js","sourceRoot":"","sources":["../../src/browser_userscript/userscript.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=citizens.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citizens.test.d.ts","sourceRoot":"","sources":["../../src/citizens_audit/citizens.test.ts"],"names":[],"mappings":""}