@echomem/mcp 1.4.20 → 1.4.22
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 +1 -1
- package/assets/hud/echo-pricing-free-sticker.png +0 -0
- package/assets/hud/echo-pricing-power-sticker.png +0 -0
- package/assets/hud/echo-pricing-pro-sticker.png +0 -0
- package/assets/hud/scan-loop/frame-01-ready.png +0 -0
- package/assets/hud/scan-loop/frame-02-open.png +0 -0
- package/assets/hud/scan-loop/frame-03-pull.png +0 -0
- package/assets/hud/scan-loop/frame-04-read.png +0 -0
- package/assets/hud/scan-loop/frame-05-file.png +0 -0
- package/assets/hud/scan-loop/frame-06-close.png +0 -0
- package/dist/crypto.js +4 -0
- package/dist/encryption.js +14 -2
- package/dist/index.js +52 -117
- package/dist/migrate.js +38 -1
- package/dist/setup-page/client-core.js +286 -26
- package/dist/setup-page/client-extraction.js +322 -101
- package/dist/setup-page/client-lifecycle.js +46 -44
- package/dist/setup-page/client-report-audit.js +1 -1
- package/dist/setup-page/client-report-city.js +35 -22
- package/dist/setup-page/document.js +1 -1
- package/dist/setup-page/styles-extraction.js +455 -0
- package/dist/setup-page/styles-mvp.js +976 -0
- package/dist/setup-page/styles-website-alignment.js +237 -5
- package/dist/setup-page/styles.js +2 -0
- package/dist/setup-page.js +1 -0
- package/dist/setup-preview.js +142 -37
- package/dist/setup.js +527 -61
- package/dist/v1-contract.js +1 -11
- package/package.json +6 -2
|
@@ -6,39 +6,24 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-
|
|
|
6
6
|
setExtractMode(false);
|
|
7
7
|
setReadyMode(true);
|
|
8
8
|
setHead("Local file access", "Consent");
|
|
9
|
-
app.className = "consentStage";
|
|
9
|
+
app.className = "consentStage mvpConsentStage";
|
|
10
10
|
app.innerHTML =
|
|
11
|
-
'<section class="
|
|
12
|
-
'<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'
|
|
18
|
-
'<
|
|
19
|
-
|
|
20
|
-
'<div class="consentScope" aria-label="What this permission allows">' +
|
|
21
|
-
'<div><span class="consentScopeNumber" aria-hidden="true">01</span><p><strong>Reads supported session logs</strong><small>Only local Codex and Claude Code history on this device.</small></p></div>' +
|
|
22
|
-
'<div><span class="consentScopeNumber" aria-hidden="true">02</span><p><strong>Builds the Agent Doctor report</strong><small>Usage patterns and visualizations are computed locally.</small></p></div>' +
|
|
23
|
-
'<div><span class="consentScopeNumber" aria-hidden="true">03</span><p><strong>Keeps transcripts on this device</strong><small>Nothing is uploaded unless you later select conversations for memory extraction.</small></p></div>' +
|
|
24
|
-
'</div>' +
|
|
25
|
-
'<label class="consentCheck"><input type="checkbox" id="localScanConsentCheck" /><span><strong>I understand and allow this local scan</strong><small>Required for Agent Doctor and to choose local conversations for extraction.</small></span></label>' +
|
|
26
|
-
'<div class="consentActions">' +
|
|
27
|
-
'<button type="button" class="primary" id="allowLocalScan" disabled>Allow local scan</button>' +
|
|
28
|
-
'<button type="button" class="textButton" id="declineLocalScan">Not now</button>' +
|
|
29
|
-
'</div>' +
|
|
30
|
-
'<p class="consentFine" id="consentStatus" role="status" aria-live="polite"></p>' +
|
|
31
|
-
'</div>' +
|
|
11
|
+
'<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. You’ll 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 & build my report <span aria-hidden="true">→</span></button>' +
|
|
18
|
+
'<button type="button" class="mvpQuiet" id="declineLocalScan">Not now</button>' +
|
|
19
|
+
'<p class="consentFine" id="consentStatus" role="status" aria-live="polite"></p>' +
|
|
32
20
|
'</section>';
|
|
33
21
|
var allow = document.getElementById("allowLocalScan");
|
|
34
22
|
if (allow) allow.onclick = allowLocalScan;
|
|
35
|
-
var consentCheck = document.getElementById("localScanConsentCheck");
|
|
36
|
-
if (consentCheck && allow) consentCheck.onchange = function () {
|
|
37
|
-
allow.disabled = !consentCheck.checked;
|
|
38
|
-
if (consentCheck.checked) setConsentStatus("");
|
|
39
|
-
};
|
|
40
23
|
var decline = document.getElementById("declineLocalScan");
|
|
41
|
-
if (decline) decline.onclick =
|
|
24
|
+
if (decline) decline.onclick = function () {
|
|
25
|
+
setConsentStatus("Echo can't continue setup without permission to scan your local history.", "required");
|
|
26
|
+
};
|
|
42
27
|
}
|
|
43
28
|
function setConsentStatus(message, tone) {
|
|
44
29
|
var node = document.getElementById("consentStatus");
|
|
@@ -48,22 +33,33 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-
|
|
|
48
33
|
}
|
|
49
34
|
}
|
|
50
35
|
async function allowLocalScan() {
|
|
36
|
+
var allow = document.getElementById("allowLocalScan");
|
|
37
|
+
if (allow) allow.disabled = true;
|
|
51
38
|
setConsentStatus("Starting local scan...");
|
|
52
39
|
try {
|
|
53
|
-
await postJson("/report-consent", { allowed: true });
|
|
40
|
+
await postJson("/report-consent", { allowed: true }, 5000);
|
|
54
41
|
localHistoryConsentGranted = true;
|
|
55
42
|
await showReport();
|
|
56
43
|
} catch (error) {
|
|
44
|
+
// The localhost bridge may have accepted consent even if the browser loses the POST
|
|
45
|
+
// response while it swaps connections. Recover from the server's authoritative state
|
|
46
|
+
// instead of leaving the user forever on "Starting local scan...".
|
|
47
|
+
try {
|
|
48
|
+
var configResponse = await fetchWithTimeout(
|
|
49
|
+
"/config?nonce=" + encodeURIComponent(nonce),
|
|
50
|
+
{ credentials: "omit", cache: "no-store" },
|
|
51
|
+
3000
|
|
52
|
+
);
|
|
53
|
+
var config = configResponse.ok ? await configResponse.json() : null;
|
|
54
|
+
if (config && config.consentGranted === true) {
|
|
55
|
+
localHistoryConsentGranted = true;
|
|
56
|
+
await showReport();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
} catch (_) {}
|
|
57
60
|
renderReportIssue("CONSENT_SAVE_FAILED", error && error.message ? error.message : "Could not start the local scan.");
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
|
-
async function declineLocalScan() {
|
|
61
|
-
localHistoryConsentGranted = false;
|
|
62
|
-
try {
|
|
63
|
-
await postJson("/report-consent", { allowed: false });
|
|
64
|
-
} catch (_) {}
|
|
65
|
-
setConsentStatus("Local history access is required to continue setup. Nothing will be scanned or uploaded unless you allow it.", "required");
|
|
66
|
-
}
|
|
67
63
|
async function showReport() {
|
|
68
64
|
if (reportPollStarted) return;
|
|
69
65
|
reportPollStarted = true;
|
|
@@ -136,14 +132,14 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-
|
|
|
136
132
|
if (event.origin !== location.origin) return;
|
|
137
133
|
var data = event.data || {};
|
|
138
134
|
if (data.type === "echomem:connected" && data.nonce === nonce) {
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
setConsentStatus("Local history access is required before you can connect EchoMem or continue setup.", "required");
|
|
135
|
+
if (setupFlow === "login") {
|
|
136
|
+
connected = true;
|
|
137
|
+
renderLocalLoginComplete();
|
|
143
138
|
return;
|
|
144
139
|
}
|
|
145
140
|
connected = true;
|
|
146
|
-
|
|
141
|
+
rememberSetupPlanChoice("");
|
|
142
|
+
try { void refreshBillingStatus(); } catch (_) {}
|
|
147
143
|
void waitForStats();
|
|
148
144
|
} else if (data.type === "echomem:city-ready" && data.nonce === nonce) {
|
|
149
145
|
scheduleReportToCity();
|
|
@@ -159,18 +155,23 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-
|
|
|
159
155
|
var configLoaded = false;
|
|
160
156
|
var consentRequired = true;
|
|
161
157
|
var consentGranted = false;
|
|
162
|
-
// Learn the
|
|
158
|
+
// Learn the connection state and server-side consent gate before routing.
|
|
163
159
|
try {
|
|
164
160
|
var cfg = await getJson("/config");
|
|
165
161
|
configLoaded = true;
|
|
166
|
-
authUrl = cfg.authUrl || authUrl;
|
|
167
|
-
switchAccountUrl = cfg.switchAccountUrl || switchAccountUrl || authUrl;
|
|
168
162
|
connected = !!cfg.connected;
|
|
163
|
+
setupFlow = cfg.flow === "login" ? "login" : "onboarding";
|
|
169
164
|
workspacePath = cfg.workspacePath || workspacePath;
|
|
170
165
|
consentRequired = cfg.consentRequired !== false;
|
|
171
166
|
consentGranted = cfg.consentGranted === true;
|
|
172
167
|
localHistoryConsentGranted = consentGranted;
|
|
173
168
|
} catch (_) {}
|
|
169
|
+
if (setupFlow === "login") {
|
|
170
|
+
if (connected) renderLocalLoginComplete();
|
|
171
|
+
else renderLocalLogin("");
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (!connected) rememberSetupPlanChoice("");
|
|
174
175
|
if (params.get("connected") === "1") {
|
|
175
176
|
if (!configLoaded || (consentRequired && !consentGranted)) {
|
|
176
177
|
renderLocalScanConsent();
|
|
@@ -189,6 +190,7 @@ export const SETUP_PAGE_CLIENT_LIFECYCLE = String.raw ` /* ---------- scan-
|
|
|
189
190
|
setTimeout(function () { if (!window.closed) void waitForStats(); }, 1500);
|
|
190
191
|
} else {
|
|
191
192
|
// Same-tab fallback (popup was blocked): go straight to the extraction dashboard.
|
|
193
|
+
try { void refreshBillingStatus(); } catch (_) {}
|
|
192
194
|
void waitForStats();
|
|
193
195
|
}
|
|
194
196
|
return;
|
|
@@ -717,7 +717,7 @@ export const SETUP_PAGE_CLIENT_REPORT_AUDIT = String.raw ` /* ---------- fo
|
|
|
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
719
|
'<h3>Stop burning tokens on these mistakes.</h3>' +
|
|
720
|
-
'<button class="rdo-cta" data-connect-echo>' + (connected ? 'Continue' : '
|
|
720
|
+
'<button class="rdo-cta" data-connect-echo>' + (connected ? 'Continue' : 'Connect Echo') +
|
|
721
721
|
'<img class="cta-face" src="/hud-assets/echo-face-cutout.png" alt="Echo" />' +
|
|
722
722
|
'<svg class="cta-arrow" viewBox="0 0 64 26" aria-hidden="true">' +
|
|
723
723
|
'<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>' +
|
|
@@ -173,12 +173,23 @@ export const SETUP_PAGE_CLIENT_REPORT_CITY = String.raw ` /* ---------- ful
|
|
|
173
173
|
var scanned = Math.max(0, Number(progress.scanned || 0));
|
|
174
174
|
var total = Math.max(0, Number(progress.total || 0));
|
|
175
175
|
var pct = total > 0 ? Math.min(100, Math.round((scanned / total) * 100)) : 0;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
+
}
|
|
192
|
+
}
|
|
182
193
|
var fill = document.getElementById("scan-load-fill");
|
|
183
194
|
if (app.className === "scanLoading" && fill) {
|
|
184
195
|
fill.style.width = pct + "%";
|
|
@@ -191,23 +202,25 @@ export const SETUP_PAGE_CLIENT_REPORT_CITY = String.raw ` /* ---------- ful
|
|
|
191
202
|
setHead("Reading your local coding history", "Local scan");
|
|
192
203
|
app.className = "scanLoading";
|
|
193
204
|
app.innerHTML =
|
|
194
|
-
'<
|
|
195
|
-
'<
|
|
196
|
-
'<span class="
|
|
197
|
-
|
|
198
|
-
'<
|
|
199
|
-
'<
|
|
200
|
-
'<
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
'
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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 + '">' +
|
|
220
|
+
'<i id="scan-load-fill" class="scanProgressFill" style="width:' + pct + '%"></i>' +
|
|
208
221
|
'</div>' +
|
|
209
|
-
|
|
210
|
-
|
|
222
|
+
'</section>';
|
|
223
|
+
if (!reportEstimateTimer) reportEstimateTimer = setInterval(updateEstimateCaption, 1000);
|
|
211
224
|
}
|
|
212
225
|
|
|
213
226
|
`;
|
|
@@ -11,7 +11,7 @@ const SETUP_PAGE_BODY = String.raw `
|
|
|
11
11
|
</div>
|
|
12
12
|
<div class="pill" id="status">Local</div>
|
|
13
13
|
</header>
|
|
14
|
-
<section id="app" class="state"
|
|
14
|
+
<section id="app" class="state" aria-busy="true"></section>
|
|
15
15
|
</main>
|
|
16
16
|
<dialog id="echo-note" class="echo-note-dlg">
|
|
17
17
|
<button class="nclose" aria-label="Close">×</button>
|