@echomem/mcp 1.4.47 → 1.4.49
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 +22 -26
- package/dist/context-analysis/claude-native-canonical.js +2 -2
- package/dist/context-analysis/vendored-canonical.js +2 -2
- package/dist/context-analysis/workspace-report.js +3 -3
- package/dist/index.js +5 -8
- package/dist/local-data-paths.js +68 -29
- package/dist/local-jsonl.js +87 -0
- package/dist/migrate.js +8 -9
- package/dist/onboarding-stats.js +16 -0
- package/dist/save-checkpoint-hook.js +1 -1
- package/dist/setup-page/client-core.js +18 -372
- package/dist/setup-page/client-extraction.js +14 -129
- package/dist/setup-page/client-lifecycle.js +28 -101
- package/dist/setup-page/client.js +0 -2
- package/dist/setup-page/styles-extraction.js +1 -31
- package/dist/setup-page/styles-foundation.js +0 -89
- package/dist/setup-page/styles-mvp.js +10 -155
- package/dist/setup-page/styles-website-alignment.js +0 -204
- package/dist/setup-page/styles.js +0 -4
- package/dist/setup-page.js +4 -4
- package/dist/setup-preview.js +4 -212
- package/dist/setup.js +119 -583
- package/dist/v1-contract.js +0 -8
- package/package.json +5 -7
- package/dist/city/README.md +0 -9
- package/dist/city/echo-ai-city-only.html +0 -2232
- package/dist/city/echo-extraction-plate.html +0 -330
- package/dist/city/echo-face-cutout.png +0 -0
- package/dist/city/personality_stickers/bossy.png +0 -0
- package/dist/city/personality_stickers/ghosty.png +0 -0
- package/dist/city/personality_stickers/loopy.png +0 -0
- package/dist/city/personality_stickers/lusty.png +0 -0
- package/dist/city/personality_stickers/maxxy.png +0 -0
- package/dist/city/personality_stickers/tabby.png +0 -0
- package/dist/city/vendor/OrbitControls.js +0 -1417
- package/dist/city/vendor/RoundedBoxGeometry.js +0 -155
- package/dist/city/vendor/echo_general-file-21.riv +0 -0
- package/dist/city/vendor/rive.js +0 -8139
- package/dist/city/vendor/rive.wasm +0 -0
- package/dist/city/vendor/three.module.min.js +0 -6
- package/dist/forensics.js +0 -1531
- package/dist/report.js +0 -721
- package/dist/setup-page/client-report-audit.js +0 -819
- package/dist/setup-page/client-report-city.js +0 -356
- package/dist/setup-page/client-report.js +0 -6
- package/dist/setup-page/styles-city-report.js +0 -880
- package/dist/setup-page/styles-context-audit.js +0 -470
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
// Generated from the prior inline setup page. This content is emitted into one browser IIFE/style tag.
|
|
2
|
-
export const SETUP_PAGE_CLIENT_REPORT_CITY = String.raw ` /* ---------- fullscreen city modal: 80% viewport, dirty/clean, legend, stats ---------- */
|
|
3
|
-
function cityComparisonTo(mode) {
|
|
4
|
-
var frame = document.getElementById("city-report-frame");
|
|
5
|
-
if (!frame || !frame.contentWindow) return;
|
|
6
|
-
try { frame.contentWindow.postMessage({ type: "echomem:city-comparison", mode: mode }, location.origin); } catch (_) {}
|
|
7
|
-
}
|
|
8
|
-
function fillCityFullData() {
|
|
9
|
-
var legend = document.getElementById("cfc-legend");
|
|
10
|
-
var stats = document.getElementById("cfc-stats");
|
|
11
|
-
var r = report || {};
|
|
12
|
-
var gs = gsClean(r.canonicalGoldenStandard);
|
|
13
|
-
var s = (gs && gs.summary) || {};
|
|
14
|
-
var projection = gsBillingProjection(r, gs);
|
|
15
|
-
var cov = r.activeSessionCoverage || {};
|
|
16
|
-
var sr = (gs && gs.sourceReports) || {};
|
|
17
|
-
var codexShare = Number(sr.codex && sr.codex.summary && sr.codex.summary.officialInputTokens || 0);
|
|
18
|
-
var claudeShare = Number(sr.claudeCode && sr.claudeCode.summary && sr.claudeCode.summary.officialInputTokens || 0);
|
|
19
|
-
var basis = "of input tokens";
|
|
20
|
-
if (!codexShare && !claudeShare) {
|
|
21
|
-
codexShare = Number(cov.codex || 0);
|
|
22
|
-
claudeShare = Number(cov.claudeCode || 0);
|
|
23
|
-
basis = "of sessions";
|
|
24
|
-
}
|
|
25
|
-
var totalShare = codexShare + claudeShare;
|
|
26
|
-
var codexPct = totalShare ? Math.round((codexShare / totalShare) * 100) : 0;
|
|
27
|
-
var claudePct = totalShare ? 100 - codexPct : 0;
|
|
28
|
-
if (legend) legend.innerHTML =
|
|
29
|
-
'<span class="cfc-side"><i class="cfc-swatch" style="background:#10a37f"></i><img src="/hud-assets/codex.svg" alt="" />Codex <b>' + codexPct + '%</b></span>' +
|
|
30
|
-
'<span class="cfc-side"><i class="cfc-swatch" style="background:#d97757"></i><img src="/hud-assets/claude.svg" alt="" />Claude Code <b>' + claudePct + '%</b></span>' +
|
|
31
|
-
'<span style="color:var(--echo-ink-faint)">' + basis + '</span>';
|
|
32
|
-
var wh = r.userWorkingHours || {};
|
|
33
|
-
var items = [
|
|
34
|
-
["Sessions", number(Number(s.sessionsAnalyzed || 0) || (Number(cov.codex || 0) + Number(cov.claudeCode || 0)))],
|
|
35
|
-
["Repos analyzed", number(Number(s.reposAnalyzed || 0) || Number(r.scale && r.scale.repoCount || 0))],
|
|
36
|
-
["Turns analyzed", number(s.turnsAnalyzed)],
|
|
37
|
-
["Provider input", big(projection.billedInputTokens)],
|
|
38
|
-
["Projected noise", Math.round(gs ? gsDisplayWastePct(gs) : 0) + "% · " + big(projection.projectedWasteTokens)],
|
|
39
|
-
["Attention hours", number(Math.round(Number(wh.userAttentionHours || 0))) + "h"]
|
|
40
|
-
];
|
|
41
|
-
if (stats) stats.innerHTML = items.map(function (it) {
|
|
42
|
-
return '<div class="cfc-stat"><span>' + it[0] + '</span><strong>' + it[1] + '</strong></div>';
|
|
43
|
-
}).join("");
|
|
44
|
-
}
|
|
45
|
-
function bindCityFullscreen() {
|
|
46
|
-
var btn = document.getElementById("city-full-btn");
|
|
47
|
-
var chrome = document.getElementById("city-full-chrome");
|
|
48
|
-
var backdrop = document.getElementById("city-full-backdrop");
|
|
49
|
-
if (!btn || !chrome || !backdrop) return;
|
|
50
|
-
function setState(mode) {
|
|
51
|
-
cityComparisonTo(mode);
|
|
52
|
-
Array.prototype.forEach.call(chrome.querySelectorAll("[data-city-state]"), function (b) {
|
|
53
|
-
b.classList.toggle("on", b.getAttribute("data-city-state") === mode);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
function open() {
|
|
57
|
-
fillCityFullData();
|
|
58
|
-
document.body.classList.add("cityFull");
|
|
59
|
-
chrome.hidden = false;
|
|
60
|
-
backdrop.hidden = false;
|
|
61
|
-
}
|
|
62
|
-
function close() {
|
|
63
|
-
document.body.classList.remove("cityFull");
|
|
64
|
-
chrome.hidden = true;
|
|
65
|
-
backdrop.hidden = true;
|
|
66
|
-
setState("without");
|
|
67
|
-
}
|
|
68
|
-
btn.onclick = open;
|
|
69
|
-
backdrop.onclick = close;
|
|
70
|
-
chrome.querySelector(".cfc-close").onclick = close;
|
|
71
|
-
Array.prototype.forEach.call(chrome.querySelectorAll("[data-city-state]"), function (b) {
|
|
72
|
-
b.onclick = function () { setState(b.getAttribute("data-city-state")); };
|
|
73
|
-
});
|
|
74
|
-
Array.prototype.forEach.call(chrome.querySelectorAll("[data-city-metric]"), function (b) {
|
|
75
|
-
b.onclick = function () {
|
|
76
|
-
var frame = document.getElementById("city-report-frame");
|
|
77
|
-
if (frame && frame.contentWindow) {
|
|
78
|
-
try { frame.contentWindow.postMessage({ type: "echomem:city-metric", metric: b.getAttribute("data-city-metric") }, location.origin); } catch (_) {}
|
|
79
|
-
}
|
|
80
|
-
Array.prototype.forEach.call(chrome.querySelectorAll("[data-city-metric]"), function (x) {
|
|
81
|
-
x.classList.toggle("on", x === b);
|
|
82
|
-
});
|
|
83
|
-
};
|
|
84
|
-
});
|
|
85
|
-
document.addEventListener("keydown", function (e) {
|
|
86
|
-
if (e.key === "Escape" && document.body.classList.contains("cityFull")) close();
|
|
87
|
-
});
|
|
88
|
-
if (params.get("cityfull") === "1") open();
|
|
89
|
-
}
|
|
90
|
-
function sendReportToCity() {
|
|
91
|
-
if (!reportEnvelope) return;
|
|
92
|
-
var frame = document.getElementById("city-report-frame");
|
|
93
|
-
if (!frame || !frame.contentWindow) return;
|
|
94
|
-
try {
|
|
95
|
-
frame.contentWindow.postMessage({ type: "echomem:setup-report", nonce: nonce, envelope: reportEnvelope }, location.origin);
|
|
96
|
-
} catch (_) {}
|
|
97
|
-
}
|
|
98
|
-
function scheduleReportToCity() {
|
|
99
|
-
sendReportToCity();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/* ---------- report shell (parent owns report state; city renders it) ---------- */
|
|
103
|
-
// The report page (full-width city hero + detail sections below) is mounted ONCE. The city iframe
|
|
104
|
-
// shows its OWN in-canvas loading state while it scans, then fades into the rendered report — one
|
|
105
|
-
// surface, no separate loading page, no reload. The parent only fills the detail sections on /report.
|
|
106
|
-
function mountReportShell() {
|
|
107
|
-
setCityMode(true);
|
|
108
|
-
app.className = "";
|
|
109
|
-
app.innerHTML =
|
|
110
|
-
'<header class="reportTop">' +
|
|
111
|
-
'<span class="yeahLogo"><i>Yeah!</i><b>Echo</b></span>' +
|
|
112
|
-
'<nav class="navCenter">' +
|
|
113
|
-
'<span class="navPill">' +
|
|
114
|
-
'<span class="navTitle"><img class="navTitleFace" src="/hud-assets/echo-face-cutout.png" alt="" />Agent Doctor</span>' +
|
|
115
|
-
'<span class="navDates" id="report-period"></span>' +
|
|
116
|
-
'</span>' +
|
|
117
|
-
'<span class="navLocal">' +
|
|
118
|
-
'<svg viewBox="0 0 12 12" fill="none" aria-hidden="true"><rect x="2" y="5" width="8" height="5.5" rx="1.2" stroke="currentColor" stroke-width="1.3"/><path d="M4 5V3.8a2 2 0 0 1 4 0V5" stroke="currentColor" stroke-width="1.3"/></svg>' +
|
|
119
|
-
'Local Only' +
|
|
120
|
-
'</span>' +
|
|
121
|
-
'</nav>' +
|
|
122
|
-
'<button class="navConnect" data-connect-echo><span class="navDot"></span>Build my first memories' +
|
|
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
|
-
'</button>' +
|
|
125
|
-
'</header>' +
|
|
126
|
-
setupJourney(2) +
|
|
127
|
-
'<section class="cityHero"><div class="cityFigureRow">' +
|
|
128
|
-
'<figure class="cityFig">' +
|
|
129
|
-
'<div class="cityShell" id="city-shell">' +
|
|
130
|
-
'<iframe id="city-report-frame" title="AI Coding City" src="/city/echo-ai-city-only.html?setup=1&figure=1&nonce=' + encodeURIComponent(nonce) + (previewState ? '&preview=1' : '') + '"></iframe>' +
|
|
131
|
-
'</div>' +
|
|
132
|
-
'<button class="cityFullBtn" id="city-full-btn" type="button">' +
|
|
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>' +
|
|
134
|
-
'Explore the memory city' +
|
|
135
|
-
'</button>' +
|
|
136
|
-
'</figure>' +
|
|
137
|
-
'<div class="cityNote" id="city-fieldnote"></div>' +
|
|
138
|
-
'</div></section>' +
|
|
139
|
-
'<div class="cityFullBackdrop" id="city-full-backdrop" hidden></div>' +
|
|
140
|
-
'<div class="cityFullChrome" id="city-full-chrome" hidden>' +
|
|
141
|
-
'<div class="cfc-bar">' +
|
|
142
|
-
'<div class="cfc-left">' +
|
|
143
|
-
'<div class="cfc-toggle" role="group" aria-label="City state">' +
|
|
144
|
-
'<button type="button" data-city-state="without" class="on"><i class="cfc-dot"></i>Dirty — today</button>' +
|
|
145
|
-
'<button type="button" data-city-state="with"><img class="cfc-face" src="/hud-assets/echo-face-cutout.png" alt="" />Clean — with Echo</button>' +
|
|
146
|
-
'</div>' +
|
|
147
|
-
'<div class="cfc-toggle" role="group" aria-label="City metric">' +
|
|
148
|
-
'<button type="button" data-city-metric="time" class="on">Time</button>' +
|
|
149
|
-
'<button type="button" data-city-metric="tokens">Tokens</button>' +
|
|
150
|
-
'<button type="button" data-city-metric="cost">API $</button>' +
|
|
151
|
-
'</div>' +
|
|
152
|
-
'</div>' +
|
|
153
|
-
'<div class="cfc-legend" id="cfc-legend"></div>' +
|
|
154
|
-
'<button class="cfc-close" type="button" aria-label="Exit fullscreen">×</button>' +
|
|
155
|
-
'</div>' +
|
|
156
|
-
'<div class="cfc-stats" id="cfc-stats"></div>' +
|
|
157
|
-
'</div>' +
|
|
158
|
-
'<div id="setup-details" class="detailsWrap"></div>';
|
|
159
|
-
bindCityFieldnote();
|
|
160
|
-
bindConnect();
|
|
161
|
-
bindCityFullscreen();
|
|
162
|
-
var cityFrame = document.getElementById("city-report-frame");
|
|
163
|
-
if (cityFrame) cityFrame.addEventListener("load", sendReportToCity);
|
|
164
|
-
reportMounted = true;
|
|
165
|
-
}
|
|
166
|
-
function resetReportSurface() {
|
|
167
|
-
reportMounted = false;
|
|
168
|
-
document.body.classList.remove("cityFull");
|
|
169
|
-
setScanMode(false);
|
|
170
|
-
setCityMode(false);
|
|
171
|
-
}
|
|
172
|
-
function formatReportEta(seconds) {
|
|
173
|
-
seconds = Math.max(1, Math.round(seconds));
|
|
174
|
-
if (seconds >= 3600) {
|
|
175
|
-
var hours = Math.floor(seconds / 3600);
|
|
176
|
-
var minutesAfterHours = Math.ceil((seconds % 3600) / 60);
|
|
177
|
-
return "About " + hours + "h" + (minutesAfterHours ? " " + minutesAfterHours + "m" : "") + " remaining";
|
|
178
|
-
}
|
|
179
|
-
if (seconds >= 60) {
|
|
180
|
-
var minutes = Math.floor(seconds / 60);
|
|
181
|
-
var secondsAfterMinutes = seconds % 60;
|
|
182
|
-
return "About " + minutes + "m " + secondsAfterMinutes + "s remaining";
|
|
183
|
-
}
|
|
184
|
-
return "About " + seconds + "s remaining";
|
|
185
|
-
}
|
|
186
|
-
function estimateReportRemaining(progress, overall, stage) {
|
|
187
|
-
void overall;
|
|
188
|
-
var now = Date.now();
|
|
189
|
-
var stageElapsed = Math.max(0, Number(progress.stageElapsedMs || 0) / 1000);
|
|
190
|
-
var stageDone = Math.max(0, Number(progress.stageDone || 0));
|
|
191
|
-
var stageTotal = Math.max(0, Number(progress.stageTotal || 0));
|
|
192
|
-
function tickExistingEstimate() {
|
|
193
|
-
if (reportEtaDisplaySeconds <= 0) {
|
|
194
|
-
return { seconds: 0, overdue: false, calibrating: true };
|
|
195
|
-
}
|
|
196
|
-
var sinceLast = reportEtaUpdatedAt ? Math.max(0, (now - reportEtaUpdatedAt) / 1000) : 0;
|
|
197
|
-
reportEtaDisplaySeconds = Math.max(0, reportEtaDisplaySeconds - sinceLast);
|
|
198
|
-
reportEtaUpdatedAt = now;
|
|
199
|
-
return {
|
|
200
|
-
seconds: reportEtaDisplaySeconds,
|
|
201
|
-
overdue: now >= reportEtaDeadline || reportEtaDisplaySeconds <= 0,
|
|
202
|
-
calibrating: false,
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// The visual progress bands describe work completed, not wall-clock cost. In particular,
|
|
207
|
-
// reaching the 75% classification band does NOT mean only 25% of the time remains.
|
|
208
|
-
// Calibrate only from movement inside the expensive classification stage.
|
|
209
|
-
if (stage !== "classifying-repeated-context") {
|
|
210
|
-
return tickExistingEstimate();
|
|
211
|
-
}
|
|
212
|
-
if (reportEtaStage !== stage) {
|
|
213
|
-
reportEtaStage = stage;
|
|
214
|
-
reportEtaStageDone = stageDone;
|
|
215
|
-
reportEtaStageElapsed = stageElapsed;
|
|
216
|
-
reportEtaObservedRate = 0;
|
|
217
|
-
return { seconds: 0, overdue: false, calibrating: true };
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// The first canonical completions can be cache hits and arrive almost instantly. Treat the
|
|
221
|
-
// first observation as a baseline, then measure only later movement over real elapsed time.
|
|
222
|
-
if (stageDone > reportEtaStageDone && stageElapsed > reportEtaStageElapsed) {
|
|
223
|
-
var sampleElapsed = stageElapsed - reportEtaStageElapsed;
|
|
224
|
-
var sampleDone = stageDone - reportEtaStageDone;
|
|
225
|
-
if (sampleElapsed >= 2 && sampleDone > 0) {
|
|
226
|
-
var sampleRate = sampleDone / sampleElapsed;
|
|
227
|
-
reportEtaObservedRate = reportEtaObservedRate > 0
|
|
228
|
-
? reportEtaObservedRate * 0.65 + sampleRate * 0.35
|
|
229
|
-
: sampleRate;
|
|
230
|
-
reportEtaStageDone = stageDone;
|
|
231
|
-
reportEtaStageElapsed = stageElapsed;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
if (
|
|
235
|
-
reportEtaObservedRate <= 0 ||
|
|
236
|
-
!isFinite(reportEtaObservedRate)
|
|
237
|
-
) {
|
|
238
|
-
return { seconds: 0, overdue: false, calibrating: true };
|
|
239
|
-
}
|
|
240
|
-
if (stageTotal <= stageDone) return tickExistingEstimate();
|
|
241
|
-
|
|
242
|
-
// Add a safety margin for the tail of slower sessions plus final report reconciliation.
|
|
243
|
-
// This intentionally prefers a slightly early completion over a fake three-second promise.
|
|
244
|
-
var observedRemaining = ((stageTotal - stageDone) / reportEtaObservedRate) * 1.35 + 5;
|
|
245
|
-
observedRemaining = Math.min(15 * 60, Math.max(8, observedRemaining));
|
|
246
|
-
|
|
247
|
-
if (!reportEtaDeadline) {
|
|
248
|
-
reportEtaDeadline = now + observedRemaining * 1000;
|
|
249
|
-
reportEtaDisplaySeconds = observedRemaining;
|
|
250
|
-
} else {
|
|
251
|
-
var sinceLast = reportEtaUpdatedAt ? Math.max(0, (now - reportEtaUpdatedAt) / 1000) : 0;
|
|
252
|
-
var clockRemaining = Math.max(0, reportEtaDisplaySeconds - sinceLast);
|
|
253
|
-
// A faster observed rate may shorten the estimate. A slower sample never pushes the
|
|
254
|
-
// countdown back upward; passing the first deadline changes the copy to "Finishing up".
|
|
255
|
-
reportEtaDisplaySeconds = Math.min(clockRemaining, observedRemaining);
|
|
256
|
-
}
|
|
257
|
-
reportEtaUpdatedAt = now;
|
|
258
|
-
return {
|
|
259
|
-
seconds: Math.max(0, reportEtaDisplaySeconds),
|
|
260
|
-
overdue: now >= reportEtaDeadline || reportEtaDisplaySeconds <= 0,
|
|
261
|
-
calibrating: false,
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
function renderLoading() {
|
|
265
|
-
var progress = reportEnvelope && reportEnvelope.kind === "scanning" ? (reportEnvelope.progress || {}) : {};
|
|
266
|
-
var scanId = String(reportEnvelope && reportEnvelope.scanId || "");
|
|
267
|
-
if (scanId !== reportEtaScanId) {
|
|
268
|
-
reportEtaScanId = scanId;
|
|
269
|
-
reportEtaDeadline = 0;
|
|
270
|
-
reportEtaDisplaySeconds = 0;
|
|
271
|
-
reportEtaUpdatedAt = 0;
|
|
272
|
-
reportEtaStage = "";
|
|
273
|
-
reportEtaStageDone = 0;
|
|
274
|
-
reportEtaStageElapsed = 0;
|
|
275
|
-
reportEtaObservedRate = 0;
|
|
276
|
-
}
|
|
277
|
-
var scannedValue = Number(progress.scanned);
|
|
278
|
-
var totalValue = Number(progress.total);
|
|
279
|
-
var scanned = isFinite(scannedValue) ? Math.max(0, scannedValue) : 0;
|
|
280
|
-
var total = isFinite(totalValue) ? Math.max(0, totalValue) : 0;
|
|
281
|
-
var visibleScanned = total > 0 ? Math.min(scanned, total) : scanned;
|
|
282
|
-
// The bar tracks the whole scan (reading → summary → classifying → finalizing), which the
|
|
283
|
-
// file counters alone cannot express: they hit their maximum while analysis is still running.
|
|
284
|
-
var overallValue = Number(progress.overall);
|
|
285
|
-
var overall = isFinite(overallValue) ? Math.min(1, Math.max(0, overallValue)) : 0;
|
|
286
|
-
var pct = Math.round(overall * 100);
|
|
287
|
-
var stage = String(progress.stage || "starting");
|
|
288
|
-
var stageDone = Math.max(0, Number(progress.stageDone || 0));
|
|
289
|
-
var stageTotal = Math.max(0, Number(progress.stageTotal || 0));
|
|
290
|
-
var stageElapsed = Math.max(0, Number(progress.stageElapsedMs || 0));
|
|
291
|
-
var beat = Math.floor(stageElapsed / 4500);
|
|
292
|
-
var progressText = "";
|
|
293
|
-
if (total > 0 && stage === "reading-transcripts") {
|
|
294
|
-
progressText = "Reading " + number(visibleScanned) + " of " + number(total) + " sessions…";
|
|
295
|
-
} else if (stage === "building-summary") {
|
|
296
|
-
var summaryBeats = [
|
|
297
|
-
"Organizing what Echo found…",
|
|
298
|
-
"Building the report summary…"
|
|
299
|
-
];
|
|
300
|
-
progressText = summaryBeats[beat % summaryBeats.length];
|
|
301
|
-
} else if (stage === "classifying-repeated-context") {
|
|
302
|
-
var analysisCount = stageTotal > 0
|
|
303
|
-
? " · " + number(Math.min(stageDone, stageTotal)) + " of " + number(stageTotal)
|
|
304
|
-
: "";
|
|
305
|
-
var analysisBeats = [
|
|
306
|
-
"Comparing context across sessions" + analysisCount + "…",
|
|
307
|
-
"Finding repeated context" + analysisCount + "…",
|
|
308
|
-
"Separating useful context from noise" + analysisCount + "…"
|
|
309
|
-
];
|
|
310
|
-
progressText = analysisBeats[beat % analysisBeats.length];
|
|
311
|
-
} else if (stage === "finalizing-report") {
|
|
312
|
-
progressText = beat % 2 === 0 ? "Checking the report totals…" : "Preparing your report…";
|
|
313
|
-
}
|
|
314
|
-
var etaState = estimateReportRemaining(progress, overall, stage);
|
|
315
|
-
var etaText = etaState.overdue
|
|
316
|
-
? "Taking a little longer than estimated…"
|
|
317
|
-
: (etaState.seconds > 0 ? formatReportEta(etaState.seconds) : "Estimating time remaining…");
|
|
318
|
-
var fill = document.getElementById("scan-load-fill");
|
|
319
|
-
var caption = document.getElementById("scan-load-caption");
|
|
320
|
-
var eta = document.getElementById("scan-load-eta");
|
|
321
|
-
if (app.className === "scanLoading" && fill) {
|
|
322
|
-
fill.style.width = pct + "%";
|
|
323
|
-
fill.parentElement.setAttribute("aria-valuenow", String(pct));
|
|
324
|
-
fill.parentElement.setAttribute("aria-valuetext", (progressText || "Preparing session count") + " " + etaText);
|
|
325
|
-
if (caption) {
|
|
326
|
-
caption.textContent = progressText;
|
|
327
|
-
caption.hidden = !progressText;
|
|
328
|
-
}
|
|
329
|
-
if (eta) eta.textContent = etaText;
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
setScanMode(true);
|
|
333
|
-
setHead("Building your report", "Local scan");
|
|
334
|
-
app.className = "scanLoading";
|
|
335
|
-
app.innerHTML =
|
|
336
|
-
setupJourney(1) +
|
|
337
|
-
'<section class="mvpReading" aria-labelledby="scanLoadingTitle">' +
|
|
338
|
-
'<span class="mvpReadingMascot scanMascotFrames" aria-hidden="true">' +
|
|
339
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-01-ready.png" alt="" />' +
|
|
340
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-02-open.png" alt="" />' +
|
|
341
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-03-pull.png" alt="" />' +
|
|
342
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-04-read.png" alt="" />' +
|
|
343
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-04-read.png" alt="" />' +
|
|
344
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-05-file.png" alt="" />' +
|
|
345
|
-
'<img class="scanMascotFrame" src="/hud-assets/scan-loop/frame-06-close.png" alt="" />' +
|
|
346
|
-
'</span>' +
|
|
347
|
-
'<h2 id="scanLoadingTitle">Building your report…</h2>' +
|
|
348
|
-
'<p class="mvpReadingCount" id="scan-load-caption" aria-live="polite"' + (progressText ? "" : " hidden") + '>' + esc(progressText) + '</p>' +
|
|
349
|
-
'<p class="mvpReadingEta" id="scan-load-eta">' + esc(etaText) + '</p>' +
|
|
350
|
-
'<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") + " " + etaText) + '">' +
|
|
351
|
-
'<i id="scan-load-fill" class="scanProgressFill" style="width:' + pct + '%"></i>' +
|
|
352
|
-
'</div>' +
|
|
353
|
-
'</section>';
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
`;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { SETUP_PAGE_CLIENT_REPORT_CITY } from "./client-report-city.js";
|
|
2
|
-
import { SETUP_PAGE_CLIENT_REPORT_AUDIT } from "./client-report-audit.js";
|
|
3
|
-
export const SETUP_PAGE_CLIENT_REPORT = [
|
|
4
|
-
SETUP_PAGE_CLIENT_REPORT_CITY,
|
|
5
|
-
SETUP_PAGE_CLIENT_REPORT_AUDIT,
|
|
6
|
-
].join("\n");
|