@echomem/mcp 1.4.6 → 1.4.8
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 +14 -8
- package/assets/hud/claude.svg +1 -0
- package/assets/hud/codex.svg +1 -0
- package/assets/hud/session-viewer.html +1734 -0
- package/dist/city/10-problems-report.html +649 -0
- package/dist/city/echo-ai-city-only.html +63 -653
- package/dist/city/echo-ai-city-only.template.html +35 -17
- package/dist/city/echo-face-cutout.png +0 -0
- package/dist/forensics-10-problems.js +632 -0
- package/dist/hud/autostart.js +66 -0
- package/dist/hud/cli.js +31 -0
- package/dist/hud/electron-main.js +229 -22
- package/dist/hud/monitor.js +36 -68
- package/dist/hud/preload.cjs +12 -0
- package/dist/hud/server.js +413 -3
- package/dist/hud/web.js +713 -74
- package/dist/index.js +355 -28
- package/dist/migrate.js +18 -0
- package/dist/setup-page.js +978 -60
- package/dist/setup.js +353 -40
- package/dist/v1-contract.js +154 -5
- package/package.json +3 -2
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
--ink:#1b1c1f; --muted:#8b8d94; --line:#ececef;
|
|
9
9
|
--mono:"IBM Plex Mono","SFMono-Regular",ui-monospace,Menlo,monospace;
|
|
10
10
|
--sans:"Avenir Next","Helvetica Neue","Segoe UI",system-ui,-apple-system,sans-serif;
|
|
11
|
-
--blue:#
|
|
11
|
+
--blue:#1a3a8f; --red:#C7372F; --amber:#f0a83f;
|
|
12
12
|
}
|
|
13
13
|
*{margin:0;padding:0;box-sizing:border-box;}
|
|
14
|
-
html,body{background:#
|
|
14
|
+
html,body{background:#FAF7F0;}
|
|
15
15
|
body{display:flex;justify-content:center;align-items:center;height:100vh;overflow:hidden;
|
|
16
16
|
font-family:var(--sans);color:var(--ink);}
|
|
17
17
|
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
.v7-head{right:56px;top:48px;width:410px;text-align:right;}
|
|
39
39
|
.v7-eyebrow{font-family:var(--mono);font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:#9aa0aa;}
|
|
40
40
|
.v7-title{font-size:34px;font-weight:800;letter-spacing:-.02em;line-height:1.05;margin-top:8px;}
|
|
41
|
-
|
|
41
|
+
/* Persona is identity flavor (a badge), not the page headline — one display-size element per
|
|
42
|
+
screen, and that's "Here's what you built." */
|
|
43
|
+
.v7-personaName{font-size:46px;font-weight:800;letter-spacing:-.03em;line-height:.92;margin-top:8px;text-transform:lowercase;}
|
|
42
44
|
.v7-rank{margin-top:12px;font-family:var(--mono);font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:#8d929c;}
|
|
43
45
|
.v7-combo{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px;}
|
|
44
46
|
.v7-combo .ct{font-family:var(--mono);font-size:11px;letter-spacing:.02em;color:#3a3c43;border:1px solid var(--line);
|
|
@@ -59,6 +61,9 @@
|
|
|
59
61
|
.v7-stat .v{font-size:23px;font-weight:800;letter-spacing:-.01em;line-height:1;}
|
|
60
62
|
.v7-stat .k{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#9296a0;margin-top:4px;}
|
|
61
63
|
.v7-band{left:90px;right:90px;bottom:250px;text-align:center;}
|
|
64
|
+
/* Echo delivers the verdict: the mascot makes the band a character speaking, not a floating stat. */
|
|
65
|
+
.v7-echo{width:56px;height:56px;object-fit:contain;margin:10px auto 2px;display:block;
|
|
66
|
+
filter:drop-shadow(0 12px 20px rgba(26,58,143,.22));}
|
|
62
67
|
.v7-band .eyebrow{font-family:var(--mono);font-size:12px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;color:#a4a7af;}
|
|
63
68
|
.v7-band .bignum{font-size:64px;font-weight:800;letter-spacing:-.03em;line-height:.9;margin-top:10px;color:var(--red);
|
|
64
69
|
min-height:64px;transition:opacity .52s ease,transform .52s ease;}
|
|
@@ -75,7 +80,7 @@
|
|
|
75
80
|
.v7-band .say b{color:var(--ink);font-weight:700;}
|
|
76
81
|
.v7-ctaWrap{left:0;right:0;bottom:112px;text-align:center;}
|
|
77
82
|
.v7-ctaWrap .pre{font-family:var(--mono);font-size:12px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#9296a0;margin-bottom:15px;}
|
|
78
|
-
.v7-cta{display:inline-flex;align-items:center;gap:11px;background:#1a3a8f;color:#fff;border:0;border-radius:
|
|
83
|
+
.v7-cta{display:inline-flex;align-items:center;gap:11px;background:#1a3a8f;color:#fff;border:0;border-radius:999px;
|
|
79
84
|
font-family:var(--mono);font-size:17px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:21px 48px;
|
|
80
85
|
box-shadow:0 20px 46px rgba(26,58,143,.32);cursor:pointer;transition:background .18s ease,transform .18s ease;}
|
|
81
86
|
.v7-cta:hover,.v7-cta:focus-visible{background:#223f9b;transform:translateY(-2px);outline:none;}
|
|
@@ -155,7 +160,7 @@
|
|
|
155
160
|
|
|
156
161
|
/* setup flow CTA: hidden in share-card export, visible only in ?setup=1 mode */
|
|
157
162
|
.setup-connect{display:none;position:absolute;z-index:20;right:46px;top:930px;width:238px;min-height:58px;
|
|
158
|
-
border:1px solid #1a3a8f;border-radius:
|
|
163
|
+
border:1px solid #1a3a8f;border-radius:999px;background:#1a3a8f;color:#fff;align-items:center;justify-content:center;
|
|
159
164
|
font-family:var(--mono);font-size:13px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
|
|
160
165
|
box-shadow:0 16px 36px rgba(20,24,40,.18);cursor:pointer;}
|
|
161
166
|
.setup-connect:hover{background:#223f9b;}
|
|
@@ -227,7 +232,7 @@
|
|
|
227
232
|
body.setup-mode .counterfactual,
|
|
228
233
|
body.setup-mode .setup-connect{display:none;}
|
|
229
234
|
body.setup-mode .v7-persona{left:clamp(48px,5vw,86px);top:clamp(42px,5vh,72px);width:min(360px,32vw);}
|
|
230
|
-
body.setup-mode .v7-personaName{font-size:clamp(
|
|
235
|
+
body.setup-mode .v7-personaName{font-size:clamp(38px,3.4vw,54px);}
|
|
231
236
|
body.setup-mode .v7-head{right:clamp(48px,5vw,86px);top:clamp(42px,5vh,72px);width:min(520px,38vw);}
|
|
232
237
|
body.setup-mode .v7-head .v7-eyebrow{font-size:clamp(10px,.72vw,12px);}
|
|
233
238
|
body.setup-mode .v7-title{font-size:clamp(28px,2.1vw,40px);}
|
|
@@ -235,7 +240,10 @@
|
|
|
235
240
|
body.setup-mode .v7-stat .v{font-size:clamp(20px,1.45vw,28px);}
|
|
236
241
|
body.setup-mode .v7-stat .k{font-size:clamp(9px,.72vw,11px);}
|
|
237
242
|
body.setup-mode .v7-band{left:clamp(48px,5vw,86px);right:auto;bottom:clamp(82px,8vh,130px);
|
|
238
|
-
width:min(
|
|
243
|
+
width:min(640px,42vw);text-align:left;display:grid;grid-template-columns:72px minmax(0,1fr);
|
|
244
|
+
column-gap:16px;align-items:start;}
|
|
245
|
+
body.setup-mode .v7-echo{width:72px;height:72px;margin:2px 0 0;}
|
|
246
|
+
body.setup-mode .v7-bandCopy{min-width:0;}
|
|
239
247
|
body.setup-mode .v7-band .eyebrow{display:none;}
|
|
240
248
|
body.setup-mode .v7-band .bignum{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
|
|
241
249
|
margin-top:0;min-height:0;line-height:.96;}
|
|
@@ -250,7 +258,7 @@
|
|
|
250
258
|
body.setup-mode .v7-ctaWrap .micro{max-width:430px;margin-left:auto;}
|
|
251
259
|
body.setup-mode .v7-foot{left:clamp(48px,5vw,86px);right:clamp(48px,5vw,86px);}
|
|
252
260
|
@media (max-height:820px){
|
|
253
|
-
body.setup-mode .v7-personaName{font-size:clamp(
|
|
261
|
+
body.setup-mode .v7-personaName{font-size:clamp(32px,4.4vh,46px);}
|
|
254
262
|
body.setup-mode .v7-title{font-size:clamp(30px,5vh,44px);}
|
|
255
263
|
body.setup-mode .v7-band{bottom:58px;width:min(500px,40vw);}
|
|
256
264
|
body.setup-mode .v7-ctaWrap{bottom:58px;width:min(390px,32vw);}
|
|
@@ -323,8 +331,11 @@
|
|
|
323
331
|
</div>
|
|
324
332
|
<div class="v7-z v7-band">
|
|
325
333
|
<div class="eyebrow">What we found</div>
|
|
334
|
+
<img class="v7-echo" src="echo-face-cutout.png" alt="" />
|
|
335
|
+
<div class="v7-bandCopy">
|
|
326
336
|
<div class="bignum" id="v7-metric"><span id="v7-metric-value">{{dirtyPct}}%</span><span id="v7-metric-label">repeated reads</span><button class="v7-infoBtn" id="v7-info-btn" type="button" aria-label="How we read your city" aria-expanded="false" aria-controls="v7-info-sheet">i</button></div>
|
|
327
337
|
<div class="say" id="v7-metric-say">Your agents re-load context they've already seen — unchanged files, the same rules, stale maps — every session. That's context rot. It's <b>how coding agents work today</b>, and it's the haze on your city.</div>
|
|
338
|
+
</div>
|
|
328
339
|
</div>
|
|
329
340
|
<div class="v7-z v7-ctaWrap">
|
|
330
341
|
<div class="pre">Ready when you are</div>
|
|
@@ -896,17 +907,19 @@ function addCube(o){
|
|
|
896
907
|
}
|
|
897
908
|
// repo summary as an upright billboard above each bar — white text, ALWAYS faces the camera (never skewed).
|
|
898
909
|
// name = small tag just above the bar top; tokens + $ fly higher above it, clear of the cube.
|
|
899
|
-
function addTopLabel(o){
|
|
910
|
+
function addTopLabel(o, numbers=true, lift=0){
|
|
900
911
|
const PW=320, PH=280;
|
|
901
912
|
const cv=document.createElement('canvas'); cv.width=PW; cv.height=PH;
|
|
902
913
|
const g=cv.getContext('2d'); g.textAlign='center';
|
|
903
914
|
g.shadowColor='rgba(0,0,0,0.34)'; g.shadowBlur=9; g.shadowOffsetY=1; // subtle contrast over light areas
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
915
|
+
if(numbers){
|
|
916
|
+
// tokens — the headline, flies highest
|
|
917
|
+
g.fillStyle='#ffffff'; g.font=`800 ${Math.round(PW*0.19)}px "IBM Plex Mono", monospace`;
|
|
918
|
+
g.fillText(fmtTok(o.tokens), PW/2, PH*0.18);
|
|
919
|
+
// dollars — just under the tokens, also up high
|
|
920
|
+
g.fillStyle='rgba(255,255,255,0.92)'; g.font=`700 ${Math.round(PW*0.11)}px "IBM Plex Mono", monospace`;
|
|
921
|
+
g.fillText('$'+Math.round(o.cost*(setupMode?1:COST_SCALE)).toLocaleString('en-US'), PW/2, PH*0.40);
|
|
922
|
+
}
|
|
910
923
|
// name — small tag sitting just above the bar top
|
|
911
924
|
g.fillStyle='rgba(255,255,255,0.95)'; g.font=`600 ${Math.round(PW*0.075)}px "IBM Plex Mono", monospace`;
|
|
912
925
|
const fw=g.measureText(o.name).width, maxw=PW*0.94;
|
|
@@ -915,7 +928,7 @@ function addTopLabel(o){
|
|
|
915
928
|
const sprite=new THREE.Sprite(new THREE.SpriteMaterial({map:tex, transparent:true, toneMapped:false, depthWrite:false}));
|
|
916
929
|
const wWorld=Math.min(Math.max(o.w*0.95, 42), 128), hWorld=wWorld*PH/PW; // scales with bar size, clamped legible
|
|
917
930
|
sprite.scale.set(wWorld, hWorld, 1);
|
|
918
|
-
sprite.position.set(o.x, TRAY_TOP + o.h - 3 + 6 + 0.36*hWorld, o.z); // name tags the top; tokens/$ fly higher
|
|
931
|
+
sprite.position.set(o.x, TRAY_TOP + o.h - 3 + 6 + 0.36*hWorld + lift, o.z); // name tags the top; tokens/$ fly higher; lift staggers neighbors
|
|
919
932
|
scene.add(sprite);
|
|
920
933
|
}
|
|
921
934
|
// fine ivory grain — textures EVERY face (incl. the curved side walls), so the tray isn't flat plastic
|
|
@@ -962,7 +975,12 @@ tray.position.set(CX, TRAY_TOP/2, CZ); tray.castShadow=true; tray.receiveShadow=
|
|
|
962
975
|
plane.rotation.x=-Math.PI/2; plane.position.set(CX, TRAY_TOP+0.6, CZ); scene.add(plane);
|
|
963
976
|
})();
|
|
964
977
|
|
|
965
|
-
|
|
978
|
+
// De-crowd the skyline: only the top token movers fly their numbers; every other building keeps just
|
|
979
|
+
// its name tag (hover still shows the full repo detail card). Kills the mid-air label collisions.
|
|
980
|
+
const NUMBERED_LABELS=4;
|
|
981
|
+
const numberedOrder=all.slice().sort((a,b)=>(b.tokens||0)-(a.tokens||0)).slice(0,NUMBERED_LABELS);
|
|
982
|
+
const numberedLift=new Map(numberedOrder.map((o,i)=>[o.name, (i%2)*16])); // alternate heights so neighbors' numbers never collide
|
|
983
|
+
all.forEach(o=>{ o.mesh=addCube(o); o.mesh.userData=o; if(o.w>=LABEL_MIN_BASE) addTopLabel(o, numberedLift.has(o.name), numberedLift.get(o.name)||0); });
|
|
966
984
|
|
|
967
985
|
// bottom-right standing "signpost": tray summary — total tokens + how much is input
|
|
968
986
|
let signpostCanvas=null, signpostTexture=null;
|
|
Binary file
|