@echomem/mcp 1.4.39 → 1.4.40
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.
|
@@ -1285,10 +1285,12 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
1285
1285
|
var slot = document.getElementById("setupPlan");
|
|
1286
1286
|
if (!slot) return;
|
|
1287
1287
|
var readySettings = slot.closest ? slot.closest(".readySettings") : null;
|
|
1288
|
+
var planGateDecision = slot.closest ? slot.closest(".planGateDecision") : null;
|
|
1288
1289
|
if (!canExtract) {
|
|
1289
1290
|
slot.innerHTML = "";
|
|
1290
1291
|
slot.classList.add("is-hidden");
|
|
1291
1292
|
if (readySettings) readySettings.classList.remove("is-plan-open", "is-checkout-pending");
|
|
1293
|
+
if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
|
|
1292
1294
|
renderBillingCommitment("");
|
|
1293
1295
|
return;
|
|
1294
1296
|
}
|
|
@@ -1303,6 +1305,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
1303
1305
|
return;
|
|
1304
1306
|
}
|
|
1305
1307
|
if (readySettings) readySettings.classList.remove("is-plan-open", "is-checkout-pending");
|
|
1308
|
+
if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
|
|
1306
1309
|
rememberSetupPlanChoice("");
|
|
1307
1310
|
setupPlanChoice = "paid";
|
|
1308
1311
|
var planLabel = plan.charAt(0).toUpperCase() + plan.slice(1);
|
|
@@ -1329,6 +1332,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
1329
1332
|
}
|
|
1330
1333
|
if (setupPlanChoice === "free") {
|
|
1331
1334
|
if (readySettings) readySettings.classList.remove("is-plan-open", "is-checkout-pending");
|
|
1335
|
+
if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
|
|
1332
1336
|
slot.innerHTML = '<div class="setupPlanConfirmed"><span class="setupPlanConfirmedIcon" aria-hidden="true">' + setupIcon("check") + '</span><span class="setupPlanConfirmedCopy"><strong>Original Echo</strong><span>100 coding sessions and 100 memory recalls each week.</span></span><button type="button" class="textButton" id="changeSetupPlan">Change</button></div>';
|
|
1333
1337
|
renderBillingCommitment("");
|
|
1334
1338
|
var changeBtn = document.getElementById("changeSetupPlan");
|
|
@@ -1352,6 +1356,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
1352
1356
|
readySettings.classList.remove("is-plan-open");
|
|
1353
1357
|
readySettings.classList.add("is-checkout-pending");
|
|
1354
1358
|
}
|
|
1359
|
+
if (planGateDecision) planGateDecision.classList.add("is-checkout-pending");
|
|
1355
1360
|
var selectedPaidPlan = pendingPaidPlan === "power" ? "Power" : "Pro";
|
|
1356
1361
|
var pendingHasTrial = !billingStatus || billingStatus.trialAvailable !== false;
|
|
1357
1362
|
var pendingPrice = pendingPaidPlan === "power" ? "$100" : "$20";
|
|
@@ -1361,15 +1366,15 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
1361
1366
|
: "Checking automatically every few seconds");
|
|
1362
1367
|
slot.innerHTML =
|
|
1363
1368
|
'<section class="setupPlanChoice setupPlanCheckout" aria-labelledby="setupPlanHeading">' +
|
|
1364
|
-
'<div class="setupPlanIntro"><h3 id="setupPlanHeading">' + esc(pendingHasTrial ? selectedPaidPlan + " trial — $0 today" : selectedPaidPlan + " subscription") + '</h3><p>
|
|
1369
|
+
'<div class="setupPlanIntro"><h3 id="setupPlanHeading">' + esc(pendingHasTrial ? selectedPaidPlan + " trial — $0 today" : selectedPaidPlan + " subscription") + '</h3><p>Complete checkout in Stripe, then return here. This page updates automatically.</p></div>' +
|
|
1365
1370
|
'<dl class="checkoutCommitment">' +
|
|
1366
1371
|
'<div><dt>Today</dt><dd>' + esc(pendingHasTrial ? "$0" : pendingPrice) + '</dd></div>' +
|
|
1367
1372
|
'<div><dt>History import</dt><dd>' + esc(pendingLimit) + ' sessions</dd></div>' +
|
|
1368
1373
|
'<div><dt>' + esc(pendingHasTrial ? "First charge" : "Billing") + '</dt><dd>' + esc(pendingHasTrial ? pendingPrice + " on " + trialChargeDateText() : pendingPrice + "/month now") + '</dd></div>' +
|
|
1369
1374
|
'</dl>' +
|
|
1370
|
-
'<div class="checkoutActions"><button type="button" class="primary" id="continueSelectedPaidPlan">Reopen Stripe checkout</button
|
|
1375
|
+
'<div class="checkoutActions"><button type="button" class="primary" id="continueSelectedPaidPlan">Reopen Stripe checkout</button></div>' +
|
|
1371
1376
|
'<p class="checkoutPollStatus" id="setupPlanStatus" role="status" aria-live="polite">' + esc(pendingStatus) + '</p>' +
|
|
1372
|
-
'<div class="setupPlanFoot"><button type="button" class="textButton" id="changeSelectedPaidPlan">Choose another plan</button></div>' +
|
|
1377
|
+
'<div class="setupPlanFoot"><button type="button" class="textButton" id="checkPaymentStatus">Check payment status</button><button type="button" class="textButton" id="changeSelectedPaidPlan">Choose another plan</button></div>' +
|
|
1373
1378
|
'</section>';
|
|
1374
1379
|
var checkPaid = document.getElementById("checkPaymentStatus");
|
|
1375
1380
|
if (checkPaid) checkPaid.onclick = function () {
|
|
@@ -1395,6 +1400,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
|
|
|
1395
1400
|
readySettings.classList.remove("is-checkout-pending");
|
|
1396
1401
|
readySettings.classList.add("is-plan-open");
|
|
1397
1402
|
}
|
|
1403
|
+
if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
|
|
1398
1404
|
slot.innerHTML = renderPlanHabitat();
|
|
1399
1405
|
renderBillingCommitment("");
|
|
1400
1406
|
bindPlanHabitat();
|
|
@@ -667,6 +667,52 @@ export const SETUP_PAGE_STYLES_MVP = String.raw `
|
|
|
667
667
|
color: var(--echo-ink-text);
|
|
668
668
|
text-align: left;
|
|
669
669
|
}
|
|
670
|
+
.planGateDecision.is-checkout-pending {
|
|
671
|
+
width: min(680px, 100%);
|
|
672
|
+
}
|
|
673
|
+
.planGateDecision.is-checkout-pending .setupPlanSlot {
|
|
674
|
+
margin-top: 8px;
|
|
675
|
+
}
|
|
676
|
+
.planGateDecision.is-checkout-pending .setupPlanCheckout {
|
|
677
|
+
display: grid;
|
|
678
|
+
gap: 16px;
|
|
679
|
+
margin: 0 auto;
|
|
680
|
+
overflow: visible;
|
|
681
|
+
border: 1px solid rgba(26,58,143,0.11);
|
|
682
|
+
border-radius: 20px;
|
|
683
|
+
background: rgba(255,255,255,0.78);
|
|
684
|
+
padding: clamp(22px, 4vw, 34px);
|
|
685
|
+
box-shadow: 0 22px 55px -42px rgba(20,36,84,0.5);
|
|
686
|
+
backdrop-filter: blur(10px);
|
|
687
|
+
}
|
|
688
|
+
.planGateDecision.is-checkout-pending .setupPlanIntro {
|
|
689
|
+
padding: 0;
|
|
690
|
+
}
|
|
691
|
+
.planGateDecision.is-checkout-pending .setupPlanIntro h3 {
|
|
692
|
+
font-size: clamp(25px, 3vw, 32px);
|
|
693
|
+
line-height: 1.2;
|
|
694
|
+
}
|
|
695
|
+
.planGateDecision.is-checkout-pending .setupPlanIntro p {
|
|
696
|
+
max-width: 620px;
|
|
697
|
+
margin-top: 7px;
|
|
698
|
+
font-size: 14px;
|
|
699
|
+
line-height: 1.5;
|
|
700
|
+
}
|
|
701
|
+
.planGateDecision.is-checkout-pending .checkoutActions {
|
|
702
|
+
grid-template-columns: 1fr;
|
|
703
|
+
}
|
|
704
|
+
.planGateDecision.is-checkout-pending .setupPlanFoot {
|
|
705
|
+
justify-content: flex-start;
|
|
706
|
+
gap: 18px;
|
|
707
|
+
margin-top: 0;
|
|
708
|
+
}
|
|
709
|
+
.planGateDecision.is-checkout-pending .setupPlanFoot .textButton {
|
|
710
|
+
min-height: 0;
|
|
711
|
+
padding: 2px 0;
|
|
712
|
+
color: var(--echo-ink-mute);
|
|
713
|
+
font-size: 11px;
|
|
714
|
+
font-weight: 700;
|
|
715
|
+
}
|
|
670
716
|
.mvpPricing {
|
|
671
717
|
width: 100%;
|
|
672
718
|
}
|
package/dist/setup.js
CHANGED
|
@@ -416,7 +416,26 @@ export function writeJsonClientConfig(configPath, entry) {
|
|
|
416
416
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
417
417
|
}
|
|
418
418
|
export function writeClaudeCodeConfig(entry) {
|
|
419
|
-
|
|
419
|
+
// EchoMem is a memory server that should load in EVERY Claude Code project, so it belongs at
|
|
420
|
+
// `user` scope (~/.claude.json, all projects) rather than `local` scope (the current project only).
|
|
421
|
+
const addArguments = ["mcp", "add-json", "-s", "user", "echomem", JSON.stringify(entry)];
|
|
422
|
+
const removeFromScope = (scope) => {
|
|
423
|
+
try {
|
|
424
|
+
execFileSync("claude", ["mcp", "remove", "echomem", "-s", scope], {
|
|
425
|
+
encoding: "utf8",
|
|
426
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
427
|
+
timeout: 10000,
|
|
428
|
+
});
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
// Older builds installed EchoMem at `local` scope. Left in place it would shadow the user-scoped
|
|
436
|
+
// entry and keep launching the stale command, so drop it first. Best-effort: `local` is per-project,
|
|
437
|
+
// so this only clears the directory setup runs from — a no-op (ignored) when nothing is there.
|
|
438
|
+
removeFromScope("local");
|
|
420
439
|
try {
|
|
421
440
|
execFileSync("claude", addArguments, {
|
|
422
441
|
encoding: "utf8",
|
|
@@ -431,14 +450,11 @@ export function writeClaudeCodeConfig(entry) {
|
|
|
431
450
|
if (!detail.includes("already exists"))
|
|
432
451
|
return "unavailable";
|
|
433
452
|
}
|
|
434
|
-
// Claude Code's CLI will not replace a same-name
|
|
435
|
-
//
|
|
453
|
+
// Claude Code's CLI will not replace a same-name server. Once the replacement entry is fully
|
|
454
|
+
// constructed, remove only EchoMem and immediately re-add it; sibling MCP servers remain.
|
|
436
455
|
try {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
440
|
-
timeout: 10000,
|
|
441
|
-
});
|
|
456
|
+
if (!removeFromScope("user"))
|
|
457
|
+
return "unavailable";
|
|
442
458
|
execFileSync("claude", addArguments, {
|
|
443
459
|
encoding: "utf8",
|
|
444
460
|
stdio: ["ignore", "pipe", "pipe"],
|
package/package.json
CHANGED