@echomem/mcp 1.4.26 → 1.4.27

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.
@@ -8,22 +8,21 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-
8
8
  setHead("Local file access", "Consent");
9
9
  app.className = "consentStage mvpConsentStage";
10
10
  app.innerHTML =
11
+ setupJourney(1) +
11
12
  '<section class="mvpConsent" aria-labelledby="mvpConsentTitle">' +
12
- '<img class="mvpConsentEcho" src="/hud-assets/echo-face-cutout.png" alt="" />' +
13
- '<p class="mvpKicker">Before we begin</p>' +
14
- '<h2 id="mvpConsentTitle">Echo has something for you.</h2>' +
15
- '<p class="mvpConsentIntro">Let Echo read your local Codex and Claude Code history to build a private report. Youll see what’s filling your context window, what keeps getting repeated, and where memory could help.</p>' +
16
- '<p class="mvpPrivacy">The scan runs on this Mac. Nothing leaves it unless you later choose memories to extract.</p>' +
17
- '<button type="button" class="primary mvpPrimary" id="allowLocalScan">Allow scan &amp; build my report <span aria-hidden="true">→</span></button>' +
18
- '<button type="button" class="mvpQuiet" id="declineLocalScan">Not now</button>' +
13
+ '<div class="mvpConsentHero">' +
14
+ '<img class="mvpConsentEcho" src="/hud-assets/echo-face-cutout.png" alt="" />' +
15
+ '<div class="mvpConsentPitch">' +
16
+ '<h2 id="mvpConsentTitle">Start with the context youve already built.</h2>' +
17
+ '<p class="mvpConsentIntro">See what you keep re-explaining—and what’s worth carrying into future sessions.</p>' +
18
+ '</div>' +
19
+ '</div>' +
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>' +
19
22
  '<p class="consentFine" id="consentStatus" role="status" aria-live="polite"></p>' +
20
23
  '</section>';
21
24
  var allow = document.getElementById("allowLocalScan");
22
25
  if (allow) allow.onclick = allowLocalScan;
23
- var decline = document.getElementById("declineLocalScan");
24
- if (decline) decline.onclick = function () {
25
- setConsentStatus("Echo can't continue setup without permission to scan your local history.", "required");
26
- };
27
26
  }
28
27
  function setConsentStatus(message, tone) {
29
28
  var node = document.getElementById("consentStatus");
@@ -716,8 +716,9 @@ export const SETUP_PAGE_CLIENT_REPORT_AUDIT = String.raw ` /* ---------- fo
716
716
  '</section>' +
717
717
  '<div class="audit-list">' + groups.map(function (group, index) { return auditRowHtml(group, index, totalWaste, slices[index]); }).join('') + '</div>' +
718
718
  '<footer class="audit-end">' +
719
- '<h3>Stop burning tokens on these mistakes.</h3>' +
720
- '<button class="rdo-cta" data-connect-echo>' + (connected ? 'Continue' : 'Connect Echo') +
719
+ '<h3>Turn this lost context into memory.</h3>' +
720
+ '<p class="audit-memory-bridge">Your report found where context is being repeated. Next, Echo can turn selected coding sessions into memories your agents can recall.</p>' +
721
+ '<button class="rdo-cta" data-connect-echo>Build my first memories' +
721
722
  '<img class="cta-face" src="/hud-assets/echo-face-cutout.png" alt="Echo" />' +
722
723
  '<svg class="cta-arrow" viewBox="0 0 64 26" aria-hidden="true">' +
723
724
  '<defs><filter id="ctaPencil" x="-20%" y="-40%" width="140%" height="180%"><feTurbulence type="fractalNoise" baseFrequency="0.05 0.12" numOctaves="3" seed="11"/><feDisplacementMap in="SourceGraphic" scale="2.6"/></filter></defs>' +
@@ -119,10 +119,11 @@ export const SETUP_PAGE_CLIENT_REPORT_CITY = String.raw ` /* ---------- ful
119
119
  'Local Only' +
120
120
  '</span>' +
121
121
  '</nav>' +
122
- '<button class="navConnect" data-connect-echo><span class="navDot"></span>Start Now' +
122
+ '<button class="navConnect" data-connect-echo><span class="navDot"></span>Build my first memories' +
123
123
  '<svg viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M3.5 8.5 8.5 3.5M4.5 3.5h4v4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
124
124
  '</button>' +
125
125
  '</header>' +
126
+ setupJourney(2) +
126
127
  '<section class="cityHero"><div class="cityFigureRow">' +
127
128
  '<figure class="cityFig">' +
128
129
  '<div class="cityShell" id="city-shell">' +
@@ -130,7 +131,7 @@ export const SETUP_PAGE_CLIENT_REPORT_CITY = String.raw ` /* ---------- ful
130
131
  '</div>' +
131
132
  '<button class="cityFullBtn" id="city-full-btn" type="button">' +
132
133
  '<svg viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M7.5 1.5h3v3M4.5 10.5h-3v-3M10.5 1.5 7 5M1.5 10.5 5 7" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
133
- 'Enter' +
134
+ 'Explore the memory city' +
134
135
  '</button>' +
135
136
  '</figure>' +
136
137
  '<div class="cityNote" id="city-fieldnote"></div>' +
@@ -170,57 +171,52 @@ export const SETUP_PAGE_CLIENT_REPORT_CITY = String.raw ` /* ---------- ful
170
171
  }
171
172
  function renderLoading() {
172
173
  var progress = reportEnvelope && reportEnvelope.kind === "scanning" ? (reportEnvelope.progress || {}) : {};
173
- var scanned = Math.max(0, Number(progress.scanned || 0));
174
- var total = Math.max(0, Number(progress.total || 0));
175
- var pct = total > 0 ? Math.min(100, Math.round((scanned / total) * 100)) : 0;
176
- if (!reportEstimateDeadline) reportEstimateDeadline = Date.now() + 30000;
177
- function estimateCaption() {
178
- var seconds = Math.ceil((reportEstimateDeadline - Date.now()) / 1000);
179
- return seconds > 0
180
- ? "About " + seconds + " seconds remaining"
181
- : "Still working your report will be ready soon.";
182
- }
183
- var caption = estimateCaption();
184
- function updateEstimateCaption() {
185
- var node = document.getElementById("scan-load-caption");
186
- if (!node) return;
187
- node.textContent = estimateCaption();
188
- if (Date.now() >= reportEstimateDeadline && reportEstimateTimer) {
189
- clearInterval(reportEstimateTimer);
190
- reportEstimateTimer = null;
191
- }
174
+ var scannedValue = Number(progress.scanned);
175
+ var totalValue = Number(progress.total);
176
+ var scanned = isFinite(scannedValue) ? Math.max(0, scannedValue) : 0;
177
+ var total = isFinite(totalValue) ? Math.max(0, totalValue) : 0;
178
+ var visibleScanned = total > 0 ? Math.min(scanned, total) : scanned;
179
+ // The bar tracks the whole scan (reading summary → classifying → finalizing), which the
180
+ // file counters alone cannot express: they hit their maximum while analysis is still running.
181
+ var overallValue = Number(progress.overall);
182
+ var overall = isFinite(overallValue) ? Math.min(1, Math.max(0, overallValue)) : 0;
183
+ var pct = Math.round(overall * 100);
184
+ var stage = String(progress.stage || "starting");
185
+ var progressText = "";
186
+ if (total > 0 && stage === "reading-transcripts") {
187
+ progressText = "Reading " + number(visibleScanned) + " of " + number(total) + " sessions…";
188
+ } else if (stage === "building-summary" || stage === "classifying-repeated-context") {
189
+ progressText = total > 0
190
+ ? "Analyzing repeated context across " + number(total) + " sessions…"
191
+ : "Analyzing repeated context…";
192
+ } else if (stage === "finalizing-report") {
193
+ progressText = "Preparing your report…";
192
194
  }
193
195
  var fill = document.getElementById("scan-load-fill");
196
+ var caption = document.getElementById("scan-load-caption");
194
197
  if (app.className === "scanLoading" && fill) {
195
198
  fill.style.width = pct + "%";
196
199
  fill.parentElement.setAttribute("aria-valuenow", String(pct));
197
- var existingCaption = document.getElementById("scan-load-caption");
198
- if (existingCaption) existingCaption.textContent = caption;
200
+ fill.parentElement.setAttribute("aria-valuetext", progressText || "Preparing session count");
201
+ if (caption) {
202
+ caption.textContent = progressText;
203
+ caption.hidden = !progressText;
204
+ }
199
205
  return;
200
206
  }
201
207
  setScanMode(true);
202
- setHead("Reading your local coding history", "Local scan");
208
+ setHead("Building your report", "Local scan");
203
209
  app.className = "scanLoading";
204
210
  app.innerHTML =
205
- '<section class="mvpReading" aria-live="polite">' +
206
- '<span class="scanMascot mvpReadingAnimation" aria-hidden="true">' +
207
- '<span class="scanMascotFrames">' +
208
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-01-ready.png" alt="" />' +
209
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-02-open.png" alt="" />' +
210
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-03-pull.png" alt="" />' +
211
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-04-read.png" alt="" />' +
212
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-04-read.png" alt="" />' +
213
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-05-file.png" alt="" />' +
214
- '<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-06-close.png" alt="" />' +
215
- '</span>' +
216
- '</span>' +
217
- '<h2>Reading your coding history…</h2>' +
218
- '<p id="scan-load-caption" class="scanCaption">' + esc(caption) + '</p>' +
219
- '<div class="scanProgress mvpReadingProgress" role="progressbar" aria-label="Local scan progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' + pct + '">' +
211
+ setupJourney(1) +
212
+ '<section class="mvpReading" aria-labelledby="scanLoadingTitle">' +
213
+ '<img class="mvpReadingMascot" src="/hud-assets/scan-loop/frame-04-read.png" alt="" aria-hidden="true" />' +
214
+ '<h2 id="scanLoadingTitle">Building your report…</h2>' +
215
+ '<p class="mvpReadingCount" id="scan-load-caption" aria-live="polite"' + (progressText ? "" : " hidden") + '>' + esc(progressText) + '</p>' +
216
+ '<div class="scanProgress mvpReadingProgress" role="progressbar" aria-labelledby="scanLoadingTitle" aria-valuemin="0" aria-valuemax="100" aria-valuenow="' + pct + '" aria-valuetext="' + esc(progressText || "Preparing session count") + '">' +
220
217
  '<i id="scan-load-fill" class="scanProgressFill" style="width:' + pct + '%"></i>' +
221
218
  '</div>' +
222
219
  '</section>';
223
- if (!reportEstimateTimer) reportEstimateTimer = setInterval(updateEstimateCaption, 1000);
224
220
  }
225
221
 
226
222
  `;
@@ -165,7 +165,9 @@ export const SETUP_PAGE_STYLES_FOUNDATION = String.raw ` :root {
165
165
  min-width: 10px;
166
166
  border-radius: 0;
167
167
  background: var(--echo-ink-primary);
168
- transition: width 320ms ease;
168
+ /* Matched to the 700ms report poll so the fill glides between updates instead of
169
+ stepping and then sitting still for the rest of the interval. */
170
+ transition: width 700ms linear;
169
171
  }
170
172
  .scanCaption {
171
173
  margin: 20px 0 0;