@echomem/mcp 1.4.9 → 1.4.12

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 (45) hide show
  1. package/assets/hud/github.svg +1 -0
  2. package/dist/city/README.md +9 -0
  3. package/dist/city/echo-ai-city-only.html +54 -93
  4. package/dist/context-analysis/claude-native-canonical.js +35 -12
  5. package/dist/context-metrics/calculate.js +2 -15
  6. package/dist/context-metrics/estimator.js +45 -0
  7. package/dist/context-metrics/ledger.js +507 -0
  8. package/dist/context-metrics/parse-claude.js +227 -0
  9. package/dist/context-metrics/parse-codex.js +276 -0
  10. package/dist/hud/adapters.js +69 -198
  11. package/dist/hud/electron-main.js +3 -2
  12. package/dist/hud/fs.js +14 -0
  13. package/dist/hud/metric.js +4 -98
  14. package/dist/hud/monitor.js +1 -12
  15. package/dist/hud/render.js +4 -3
  16. package/dist/hud/server.js +30 -0
  17. package/dist/hud/web.js +409 -186
  18. package/dist/index.js +1 -0
  19. package/dist/setup-page/client-core.js +475 -0
  20. package/dist/setup-page/client-extraction.js +550 -0
  21. package/dist/setup-page/client-lifecycle.js +116 -0
  22. package/dist/setup-page/client-report-audit.js +818 -0
  23. package/dist/setup-page/client-report-city.js +204 -0
  24. package/dist/setup-page/client-report.js +6 -0
  25. package/dist/setup-page/client.js +15 -0
  26. package/dist/setup-page/document.js +37 -0
  27. package/dist/setup-page/styles-city-report.js +880 -0
  28. package/dist/setup-page/styles-context-audit.js +470 -0
  29. package/dist/setup-page/styles-extraction.js +821 -0
  30. package/dist/setup-page/styles-foundation.js +231 -0
  31. package/dist/setup-page/styles.js +11 -0
  32. package/dist/setup-page.js +6 -5623
  33. package/dist/setup.js +24 -10
  34. package/package.json +4 -4
  35. package/dist/city/10-problems-report.html +0 -649
  36. package/dist/city/_live.html +0 -37
  37. package/dist/city/_serve.mjs +0 -45
  38. package/dist/city/card-data.json +0 -15
  39. package/dist/city/chaos-to-clarity-pencil.html +0 -582
  40. package/dist/city/city-data.json +0 -248
  41. package/dist/city/echo-ai-city-only.template.html +0 -2271
  42. package/dist/city/generate-echo-city-only.mjs +0 -112
  43. package/dist/city/pencil-pie-generator.html +0 -883
  44. package/dist/city/pencil-webgl-landscape.html +0 -1239
  45. package/dist/city/spatial-fan-story.html +0 -479
package/dist/setup.js CHANGED
@@ -765,6 +765,12 @@ function repoCityArtifactsRoot() {
765
765
  function serveRepoCityAsset(reqPath, res) {
766
766
  const root = repoCityArtifactsRoot();
767
767
  const rel = reqPath === "/city" || reqPath === "/city/" ? "echo-ai-city-only.html" : decodeURIComponent(reqPath.slice("/city/".length));
768
+ // Archives stay in the checkout for recovery, but must never become a localhost UI surface.
769
+ const normalizedRel = rel.replace(/\\/g, "/");
770
+ if (normalizedRel === "archive" || normalizedRel.startsWith("archive/")) {
771
+ res.writeHead(404).end("not found");
772
+ return true;
773
+ }
768
774
  const filePath = path.resolve(root, rel);
769
775
  const rootWithSep = root.endsWith(path.sep) ? root : root + path.sep;
770
776
  if (!filePath.startsWith(rootWithSep)) {
@@ -1062,7 +1068,10 @@ function publicRunningForensicProgress(value) {
1062
1068
  * import session.
1063
1069
  */
1064
1070
  export function startCallbackServer(opts = {}) {
1065
- const timeoutMs = opts.timeoutMs ?? 300_000;
1071
+ const timeoutMs = opts.timeoutMs ?? 15 * 60_000;
1072
+ const approvalTimeoutLabel = timeoutMs >= 60_000
1073
+ ? `${Math.round(timeoutMs / 60_000)} minutes`
1074
+ : `${Math.ceil(timeoutMs / 1000)} seconds`;
1066
1075
  const dashboardTimeoutMs = 4 * 60 * 60 * 1000;
1067
1076
  const expectedNonce = opts.nonce;
1068
1077
  const scanId = opts.scanId ?? randomUUID();
@@ -1106,7 +1115,7 @@ export function startCallbackServer(opts = {}) {
1106
1115
  const waitMs = onToken.settled() ? dashboardTimeoutMs : timeoutMs;
1107
1116
  timer = setTimeout(() => {
1108
1117
  if (!onToken.settled()) {
1109
- onToken.reject(new Error("timed out waiting for browser approval"));
1118
+ onToken.reject(new Error(`browser approval did not finish in ${approvalTimeoutLabel}`));
1110
1119
  }
1111
1120
  else if (!decision.settled()) {
1112
1121
  decision.resolve("timeout");
@@ -1120,6 +1129,7 @@ export function startCallbackServer(opts = {}) {
1120
1129
  return void text(res, 403, "bad nonce");
1121
1130
  if (!token)
1122
1131
  return void text(res, 400, "missing token");
1132
+ console.log(`[${new Date().toISOString()}] Browser approval callback received.`);
1123
1133
  const firstToken = !onToken.settled();
1124
1134
  connected = true;
1125
1135
  const setupPath = `/setup?nonce=${encodeURIComponent(nonce || "")}&connected=1`;
@@ -1634,8 +1644,10 @@ async function cmdInit(flags) {
1634
1644
  await cmdSetupHud(flags);
1635
1645
  // 3. Start onboarding — opens the browser dashboard (scan → connect → extraction) and waits there.
1636
1646
  console.log("");
1637
- if (!flags["skip-login"] && !flags["no-login"])
1638
- await cmdLogin(flags);
1647
+ if (!flags["skip-login"] && !flags["no-login"] && !await cmdLogin(flags)) {
1648
+ console.log("\nEchoMem is configured, but this device was not connected. Restart EchoMem and use the new page it opens.");
1649
+ return;
1650
+ }
1639
1651
  console.log("");
1640
1652
  console.log("🎉 EchoMem is ready.");
1641
1653
  console.log(" • MCP memory is configured for every coding agent installed on this machine.");
@@ -1750,7 +1762,7 @@ async function cmdLogin(flags) {
1750
1762
  });
1751
1763
  if (!ok)
1752
1764
  process.exitCode = 1;
1753
- return;
1765
+ return ok;
1754
1766
  }
1755
1767
  // Browser path: open a localhost dashboard. It briefly leaves for hosted auth, then returns here
1756
1768
  // after the web page has delivered the token+key to the callback. The nonce gates every local route.
@@ -1799,6 +1811,7 @@ async function cmdLogin(flags) {
1799
1811
  srv.setAuthUrl(connectUrl, switchAccountUrl.toString());
1800
1812
  openBrowser(localSetupUrl);
1801
1813
  console.log(`If it didn't open, visit:\n ${localSetupUrl}\n`);
1814
+ console.log("Waiting for browser approval for up to 15 minutes…");
1802
1815
  // Scan-first: build the local forensic "Context Doctor" report off-thread so the page shows it
1803
1816
  // BEFORE the user connects an account (the scan is local-only; nothing leaves the machine).
1804
1817
  buildForensicReportOffThread((progress) => {
@@ -1846,14 +1859,14 @@ async function cmdLogin(flags) {
1846
1859
  }
1847
1860
  catch (e) {
1848
1861
  srv.close();
1849
- console.error(`❌ ${e?.message || e}. You can instead run: echomem-mcp login --token ec_… [--passphrase <vault pass>]`);
1862
+ console.error(`❌ ${e?.message || e}. Restart EchoMem and use the new page it opens.`);
1850
1863
  process.exitCode = 1;
1851
- return;
1864
+ return false;
1852
1865
  }
1853
1866
  if (!await verifyAndPrint({ token, key })) {
1854
1867
  srv.close();
1855
1868
  process.exitCode = 1;
1856
- return;
1869
+ return false;
1857
1870
  }
1858
1871
  let disc = null;
1859
1872
  let exactDiscovery = Promise.resolve(null);
@@ -2186,7 +2199,7 @@ async function cmdLogin(flags) {
2186
2199
  sendMigrate({ error: "IMPORT_START_FAILED", message: "Local session discovery did not finish." }, 500);
2187
2200
  srv.close();
2188
2201
  process.exitCode = 1;
2189
- return;
2202
+ return true;
2190
2203
  }
2191
2204
  activeJobCount = exact.pending.length;
2192
2205
  const updateProgress = (patch) => {
@@ -2218,7 +2231,7 @@ async function cmdLogin(flags) {
2218
2231
  sendMigrate({ error: "NO_PENDING_SESSIONS" }, 409);
2219
2232
  srv.close();
2220
2233
  console.log("Setup complete — no unprocessed local conversations to extract.");
2221
- return;
2234
+ return true;
2222
2235
  }
2223
2236
  updateProgress({ status: "starting", running: 0, queued: exact.pending.length, latest: "Creating import session." });
2224
2237
  // Plan caps limit how many conversations one import session accepts (IMPORT_LIMIT_EXCEEDED →
@@ -2332,6 +2345,7 @@ async function cmdLogin(flags) {
2332
2345
  console.log("Setup complete — run `echomem-mcp migrate` later to back-fill your history.");
2333
2346
  srv.close();
2334
2347
  }
2348
+ return true;
2335
2349
  }
2336
2350
  async function cmdUnlock(flags) {
2337
2351
  const store = new KeyStore();
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@echomem/mcp",
3
- "version": "1.4.9",
3
+ "version": "1.4.12",
4
4
  "description": "EchoMem MCP bridge: cloud-first memory tools, local context HUD, and the Agent Doctor workspace forensics report (cost ledger + 3D repo city)",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "mcp": "./dist/index.js",
9
- "echomem-mcp": "./dist/index.js",
10
- "echomem-hud": "./dist/hud/cli.js"
8
+ "mcp": "dist/index.js",
9
+ "echomem-mcp": "dist/index.js",
10
+ "echomem-hud": "dist/hud/cli.js"
11
11
  },
12
12
  "files": [
13
13
  "dist",