@echomem/mcp 1.4.44 → 1.4.45

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 (50) hide show
  1. package/README.md +28 -25
  2. package/dist/city/README.md +9 -0
  3. package/dist/city/echo-ai-city-only.html +2232 -0
  4. package/dist/city/echo-extraction-plate.html +330 -0
  5. package/dist/city/echo-face-cutout.png +0 -0
  6. package/dist/city/personality_stickers/bossy.png +0 -0
  7. package/dist/city/personality_stickers/ghosty.png +0 -0
  8. package/dist/city/personality_stickers/loopy.png +0 -0
  9. package/dist/city/personality_stickers/lusty.png +0 -0
  10. package/dist/city/personality_stickers/maxxy.png +0 -0
  11. package/dist/city/personality_stickers/tabby.png +0 -0
  12. package/dist/city/vendor/OrbitControls.js +1417 -0
  13. package/dist/city/vendor/RoundedBoxGeometry.js +155 -0
  14. package/dist/city/vendor/echo_general-file-21.riv +0 -0
  15. package/dist/city/vendor/rive.js +8139 -0
  16. package/dist/city/vendor/rive.wasm +0 -0
  17. package/dist/city/vendor/three.module.min.js +6 -0
  18. package/dist/context-analysis/claude-native-canonical.js +2 -2
  19. package/dist/context-analysis/vendored-canonical.js +2 -2
  20. package/dist/context-analysis/workspace-report.js +3 -3
  21. package/dist/forensics.js +1531 -0
  22. package/dist/hud/hooks.js +31 -43
  23. package/dist/index.js +79 -15
  24. package/dist/local-data-paths.js +38 -0
  25. package/dist/migrate.js +140 -70
  26. package/dist/report.js +721 -0
  27. package/dist/save-checkpoint-hook.js +1 -1
  28. package/dist/setup-page/client-core.js +372 -18
  29. package/dist/setup-page/client-extraction.js +204 -37
  30. package/dist/setup-page/client-lifecycle.js +101 -31
  31. package/dist/setup-page/client-report-audit.js +819 -0
  32. package/dist/setup-page/client-report-city.js +356 -0
  33. package/dist/setup-page/client-report.js +6 -0
  34. package/dist/setup-page/client.js +2 -0
  35. package/dist/setup-page/styles-city-report.js +880 -0
  36. package/dist/setup-page/styles-context-audit.js +470 -0
  37. package/dist/setup-page/styles-extraction.js +31 -1
  38. package/dist/setup-page/styles-foundation.js +89 -0
  39. package/dist/setup-page/styles-mvp.js +155 -10
  40. package/dist/setup-page/styles-website-alignment.js +204 -0
  41. package/dist/setup-page/styles.js +4 -0
  42. package/dist/setup-page.js +4 -4
  43. package/dist/setup-preview.js +212 -4
  44. package/dist/setup.js +702 -321
  45. package/dist/source-session.js +3 -9
  46. package/dist/v1-contract.js +8 -0
  47. package/package.json +7 -9
  48. package/dist/config-files.js +0 -63
  49. package/dist/local-jsonl.js +0 -87
  50. package/dist/onboarding-stats.js +0 -16
@@ -1,6 +1,8 @@
1
1
  // Generated by splitting the previous inline setup page. Keep this source readable: it is emitted into one browser IIFE.
2
- export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- local-history permission and setup routing ---------- */
3
- function renderLocalHistoryConsent() {
2
+ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-first poll for the forensic report ---------- */
3
+ function renderLocalScanConsent() {
4
+ setScanMode(false);
5
+ setCityMode(false);
4
6
  setExtractMode(false);
5
7
  setReadyMode(true);
6
8
  setHead("Local file access", "Consent");
@@ -12,15 +14,15 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- local
12
14
  '<img class="mvpConsentEcho" src="/hud-assets/echo-face-cutout.png" alt="" />' +
13
15
  '<div class="mvpConsentPitch">' +
14
16
  '<h2 id="mvpConsentTitle">Start with the context you’ve already built.</h2>' +
15
- '<p class="mvpConsentIntro">Choose which local coding conversations to bring into EchoMem.</p>' +
17
+ '<p class="mvpConsentIntro">See what you keep re-explaining—and what’s worth carrying into future sessions.</p>' +
16
18
  '</div>' +
17
19
  '</div>' +
18
- '<p class="mvpConsentTrustLine">Your history stays on this computer until you choose what to import. ' + dataHandlingLink("Data handling") + '</p>' +
19
- '<button type="button" class="primary mvpPrimary" id="allowLocalHistory">Continue <span aria-hidden="true">→</span></button>' +
20
+ '<p class="mvpConsentTrustLine">Your history stays on your Mac until you choose what to import. ' + dataHandlingLink("Data handling") + '</p>' +
21
+ '<button type="button" class="primary mvpPrimary" id="allowLocalScan">Build my private report <span aria-hidden="true">→</span></button>' +
20
22
  '<p class="consentFine" id="consentStatus" role="status" aria-live="polite"></p>' +
21
23
  '</section>';
22
- var allow = document.getElementById("allowLocalHistory");
23
- if (allow) allow.onclick = allowLocalHistory;
24
+ var allow = document.getElementById("allowLocalScan");
25
+ if (allow) allow.onclick = allowLocalScan;
24
26
  }
25
27
  function setConsentStatus(message, tone) {
26
28
  var node = document.getElementById("consentStatus");
@@ -29,26 +31,18 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- local
29
31
  node.classList.toggle("is-required", tone === "required");
30
32
  }
31
33
  }
32
- function continueAfterLocalHistoryConsent() {
33
- if (connected) {
34
- try { void refreshBillingStatus(); } catch (_) {}
35
- void waitForStats();
36
- return;
37
- }
38
- rememberSetupPlanChoice("");
39
- renderLocalLogin("");
40
- }
41
- async function allowLocalHistory() {
42
- var allow = document.getElementById("allowLocalHistory");
34
+ async function allowLocalScan() {
35
+ var allow = document.getElementById("allowLocalScan");
43
36
  if (allow) allow.disabled = true;
44
- setConsentStatus("Saving your choice...");
37
+ setConsentStatus("Starting local scan...");
45
38
  try {
46
- await postJson("/local-history-consent", { allowed: true }, 5000);
39
+ await postJson("/report-consent", { allowed: true }, 5000);
47
40
  localHistoryConsentGranted = true;
48
- continueAfterLocalHistoryConsent();
41
+ await showReport();
49
42
  } catch (error) {
50
43
  // The localhost bridge may have accepted consent even if the browser loses the POST
51
- // response while it swaps connections. Recover from the server's authoritative state.
44
+ // response while it swaps connections. Recover from the server's authoritative state
45
+ // instead of leaving the user forever on "Starting local scan...".
52
46
  try {
53
47
  var configResponse = await fetchWithTimeout(
54
48
  "/config?nonce=" + encodeURIComponent(nonce),
@@ -58,14 +52,80 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- local
58
52
  var config = configResponse.ok ? await configResponse.json() : null;
59
53
  if (config && config.consentGranted === true) {
60
54
  localHistoryConsentGranted = true;
61
- continueAfterLocalHistoryConsent();
55
+ await showReport();
62
56
  return;
63
57
  }
64
58
  } catch (_) {}
65
- if (allow) allow.disabled = false;
66
- setConsentStatus(error && error.message ? error.message : "Could not save local-history access.", "required");
59
+ renderReportIssue("CONSENT_SAVE_FAILED", error && error.message ? error.message : "Could not start the local scan.");
67
60
  }
68
61
  }
62
+ async function showReport() {
63
+ if (reportPollStarted) return;
64
+ reportPollStarted = true;
65
+ if (!report) renderLoading();
66
+ try {
67
+ var fails = 0;
68
+ for (;;) {
69
+ if (decisionMade) return;
70
+ var res;
71
+ try {
72
+ res = await fetchWithTimeout("/report?nonce=" + encodeURIComponent(nonce), { credentials: "omit", cache: "no-store" }, 12000);
73
+ } catch (_) {
74
+ // Only a RUN of consecutive failures is a real bridge problem. A long scan that keeps
75
+ // answering valid 202 envelopes must never trip this.
76
+ fails++;
77
+ if (fails >= 8) { renderBridgeIssue(); return; }
78
+ await sleep(700);
79
+ continue;
80
+ }
81
+ if (res.status === 403) {
82
+ renderReportIssue("SETUP_SESSION_INVALID", "This setup link is missing or has an invalid local session nonce.");
83
+ return;
84
+ }
85
+ var envelope;
86
+ try {
87
+ envelope = await res.json();
88
+ } catch (_) {
89
+ renderReportIssue("REPORT_RESPONSE_INVALID", "The local bridge returned a report response that could not be decoded.");
90
+ return;
91
+ }
92
+ try {
93
+ validateProductionReportEnvelope(envelope);
94
+ } catch (_) {
95
+ renderReportIssue("REPORT_SCHEMA_INVALID", "The local report failed its provenance or ledger consistency checks.");
96
+ return;
97
+ }
98
+ if (res.status === 202 && envelope.kind === "scanning") {
99
+ fails = 0;
100
+ reportEnvelope = envelope;
101
+ scheduleReportToCity();
102
+ renderLoading();
103
+ await sleep(700);
104
+ continue;
105
+ }
106
+ if (res.status === 200 && envelope.kind === "empty") {
107
+ renderEmptyReport();
108
+ return;
109
+ }
110
+ if (res.status === 200 && envelope.kind === "ready") {
111
+ reportEnvelope = envelope;
112
+ report = envelope.report;
113
+ try {
114
+ renderForensicReport();
115
+ } catch (_) {
116
+ renderReportIssue("RENDER_FAILED", "Your validated local report could not be rendered safely.");
117
+ }
118
+ return;
119
+ }
120
+ if (envelope.kind === "failed") {
121
+ renderReportIssue(envelope.error.code, envelope.error.message);
122
+ return;
123
+ }
124
+ renderReportIssue("REPORT_STATE_MISMATCH", "The local bridge returned a report state that did not match its HTTP status.");
125
+ return;
126
+ }
127
+ } finally { reportPollStarted = false; }
128
+ }
69
129
 
70
130
  window.addEventListener("message", function (event) {
71
131
  if (event.origin !== location.origin) return;
@@ -80,22 +140,27 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- local
80
140
  rememberSetupPlanChoice("");
81
141
  try { void refreshBillingStatus(); } catch (_) {}
82
142
  void waitForStats();
143
+ } else if (data.type === "echomem:city-ready" && data.nonce === nonce) {
144
+ scheduleReportToCity();
145
+ } else if (data.type === "echomem:connect-click") {
146
+ onConnectClick();
83
147
  }
84
148
  });
85
149
  async function init() {
86
150
  if (!nonce) throw new Error("Missing setup nonce. Re-run echomem-mcp init.");
151
+ // Older builds cached a report under the nonce. It is never an authority now; the current
152
+ // server envelope and scan identity are the only inputs allowed to unlock personalized UI.
153
+ try { sessionStorage.removeItem("echomem:setup-report:" + nonce); } catch (_) {}
87
154
  var configLoaded = false;
88
155
  var consentRequired = true;
89
156
  var consentGranted = false;
157
+ // Learn the connection state and server-side consent gate before routing.
90
158
  try {
91
159
  var cfg = await getJson("/config");
92
160
  configLoaded = true;
93
161
  connected = !!cfg.connected;
94
162
  setupFlow = cfg.flow === "login" ? "login" : "onboarding";
95
163
  workspacePath = cfg.workspacePath || workspacePath;
96
- setupPlatform = cfg.platform || setupPlatform;
97
- canOpenClaudeDesktop = !!(cfg.capabilities && cfg.capabilities.openClaudeDesktop);
98
- canOpenAgentSessions = !!(cfg.capabilities && cfg.capabilities.openAgentSessions);
99
164
  consentRequired = cfg.consentRequired !== false;
100
165
  consentGranted = cfg.consentGranted === true;
101
166
  localHistoryConsentGranted = consentGranted;
@@ -108,27 +173,32 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- local
108
173
  if (!connected) rememberSetupPlanChoice("");
109
174
  if (params.get("connected") === "1") {
110
175
  if (!configLoaded || (consentRequired && !consentGranted)) {
111
- renderLocalHistoryConsent();
176
+ renderLocalScanConsent();
112
177
  setConsentStatus("Local history access is required before you can connect EchoMem or continue setup.", "required");
113
178
  return;
114
179
  }
115
180
  connected = true;
116
181
  if (notifyOpenerConnected()) {
182
+ // Popup flow: hand the main tab back control, then this popup closes.
117
183
  setHead("EchoMem connected", "Done");
118
184
  app.className = "notice";
119
185
  app.innerHTML = '<h2 style="color:#203820">This device is connected</h2><p style="margin-top:10px">Returning to the local setup page...</p>';
186
+ // Fallback: if window.close() was blocked (auth opened as a tab, or the browser refused),
187
+ // this window would otherwise hang on "Returning..." forever. After a beat, take over here
188
+ // so the user always lands on the dashboard instead of a dead page.
120
189
  setTimeout(function () { if (!window.closed) void waitForStats(); }, 1500);
121
190
  } else {
191
+ // Same-tab fallback (popup was blocked): go straight to the extraction dashboard.
122
192
  try { void refreshBillingStatus(); } catch (_) {}
123
193
  void waitForStats();
124
194
  }
125
195
  return;
126
196
  }
127
197
  if (consentGranted) {
128
- continueAfterLocalHistoryConsent();
198
+ await showReport();
129
199
  return;
130
200
  }
131
- renderLocalHistoryConsent();
201
+ renderLocalScanConsent();
132
202
  }
133
203
  __ECHO_SETUP_STARTUP__;
134
204
  `;