@echomem/mcp 1.4.21 → 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/setup-page/client-core.js +140 -47
- package/dist/setup-page/client-extraction.js +251 -68
- package/dist/setup-page/client-lifecycle.js +45 -39
- 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 +330 -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-preview.js +18 -2
- package/dist/setup.js +262 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ HUD; the granular commands below still work.
|
|
|
66
66
|
| `npx -y @echomem/mcp@latest setup` | One-off setup without keeping a global CLI command |
|
|
67
67
|
| `echomem-mcp setup [--client cursor\|windsurf\|claude-desktop\|claude-code\|codex]` | Write client config + log in |
|
|
68
68
|
| `echomem-mcp setup --skip-login [--client cursor\|windsurf\|claude-desktop\|claude-code\|codex]` | Write client config without opening the browser or changing credentials |
|
|
69
|
-
| `npx -y @echomem/mcp@latest update --all` | One-shot update: repoint detected client configs
|
|
69
|
+
| `npx -y @echomem/mcp@latest update --all` | One-shot update: install the latest bridge durably and repoint detected client configs, with no browser login |
|
|
70
70
|
| `npx -y @echomem/mcp@latest update --client codex` | Update one client only |
|
|
71
71
|
| `echomem-mcp setup --with-hud [--client codex]` | Write client config + log in + launch the EchoMem context HUD |
|
|
72
72
|
| `echomem-mcp login` | Approve device in browser (or use `--token` / `--passphrase`) |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -8,6 +8,9 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
8
8
|
var status = document.getElementById("status");
|
|
9
9
|
var report = null;
|
|
10
10
|
var reportEnvelope = null;
|
|
11
|
+
// The local bridge is authoritative. Login never gets access to scan/import routes;
|
|
12
|
+
// onboarding may request the separate local-history permission.
|
|
13
|
+
var setupFlow = "onboarding";
|
|
11
14
|
var activeScanId = "";
|
|
12
15
|
var stats = null;
|
|
13
16
|
var statsSlow = false;
|
|
@@ -27,6 +30,8 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
27
30
|
var billingStatus = null;
|
|
28
31
|
var billingStatusLoading = false;
|
|
29
32
|
var setupPlanChoice = "";
|
|
33
|
+
var setupPlanPreview = "free";
|
|
34
|
+
var billingActivationPendingPlan = "";
|
|
30
35
|
var selectedSessionKeys = Object.create(null);
|
|
31
36
|
var sessionSelectionTouched = false;
|
|
32
37
|
var sessionPickerQuery = "";
|
|
@@ -37,13 +42,30 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
37
42
|
var localAuthAgeConfirmed = false;
|
|
38
43
|
var statsPollStarted = false;
|
|
39
44
|
var reportPollStarted = false;
|
|
45
|
+
var reportEstimateDeadline = 0;
|
|
46
|
+
var reportEstimateTimer = null;
|
|
47
|
+
var readyStage = "";
|
|
40
48
|
var NIGHT_HOURS = { 22: 1, 23: 1, 0: 1, 1: 1, 2: 1, 3: 1 };
|
|
41
49
|
|
|
50
|
+
try {
|
|
51
|
+
var storedSetupPlanChoice = sessionStorage.getItem("echomem:setup-plan:" + nonce) || "";
|
|
52
|
+
if (storedSetupPlanChoice === "free" || storedSetupPlanChoice === "pro" || storedSetupPlanChoice === "power") {
|
|
53
|
+
setupPlanChoice = storedSetupPlanChoice;
|
|
54
|
+
}
|
|
55
|
+
} catch (_) {}
|
|
56
|
+
|
|
42
57
|
function esc(value) {
|
|
43
58
|
return String(value == null ? "" : value).replace(/[&<>"']/g, function (ch) {
|
|
44
59
|
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[ch];
|
|
45
60
|
});
|
|
46
61
|
}
|
|
62
|
+
function rememberSetupPlanChoice(choice) {
|
|
63
|
+
setupPlanChoice = choice === "free" || choice === "pro" || choice === "power" ? choice : "";
|
|
64
|
+
try {
|
|
65
|
+
if (setupPlanChoice) sessionStorage.setItem("echomem:setup-plan:" + nonce, setupPlanChoice);
|
|
66
|
+
else sessionStorage.removeItem("echomem:setup-plan:" + nonce);
|
|
67
|
+
} catch (_) {}
|
|
68
|
+
}
|
|
47
69
|
function setupIcon(name) {
|
|
48
70
|
var paths = {
|
|
49
71
|
"shield-check": '<path d="M12 3 5 6v5c0 4.6 2.9 8.1 7 10 4.1-1.9 7-5.4 7-10V6l-7-3Z"/><path d="m8.8 12.1 2 2 4.4-4.5"/>',
|
|
@@ -152,14 +174,18 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
152
174
|
return false;
|
|
153
175
|
}
|
|
154
176
|
function localAuthLegalHtml() {
|
|
155
|
-
return '<
|
|
156
|
-
'<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
'<span>I have read and agree to the Echo <a href="https://echoknows.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms of Use</a>, <a href="https://echoknows.com/memory-terms" target="_blank" rel="noopener noreferrer">Memory Usage Terms</a>, and <a href="https://echoknows.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>. I understand Echo uses subprocessors listed <a href="https://echoknows.com/subprocessor-list" target="_blank" rel="noopener noreferrer">here</a>.</span></label>' +
|
|
160
|
-
'</div>';
|
|
177
|
+
return '<label class="localAuthConsent">' +
|
|
178
|
+
'<input type="checkbox" id="localAuthConsent" ' + (localAuthAgeConfirmed && localAuthTermsAccepted ? "checked" : "") + ' />' +
|
|
179
|
+
'<span>I confirm that I am at least 18 years old and that I have read and agree to Echo\'s <a href="https://echoknows.com/terms-of-use" target="_blank" rel="noopener noreferrer">Terms of Use</a>, <a href="https://echoknows.com/memory-terms" target="_blank" rel="noopener noreferrer">Memory Usage Terms</a>, and <a href="https://echoknows.com/privacy-policy" target="_blank" rel="noopener noreferrer">Privacy Policy</a>. See our <a href="https://echoknows.com/subprocessor-list" target="_blank" rel="noopener noreferrer">Subprocessor List</a>.</span>' +
|
|
180
|
+
'</label>';
|
|
161
181
|
}
|
|
162
182
|
function captureLocalAuthConsents() {
|
|
183
|
+
var consent = document.getElementById("localAuthConsent");
|
|
184
|
+
if (consent) {
|
|
185
|
+
localAuthTermsAccepted = !!consent.checked;
|
|
186
|
+
localAuthAgeConfirmed = !!consent.checked;
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
163
189
|
var terms = document.getElementById("localAuthTerms");
|
|
164
190
|
var age = document.getElementById("localAuthAge");
|
|
165
191
|
localAuthTermsAccepted = !!(terms && terms.checked);
|
|
@@ -185,19 +211,21 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
185
211
|
setExtractMode(false);
|
|
186
212
|
setReadyMode(true);
|
|
187
213
|
setHead("Connect EchoMem", "Local login");
|
|
188
|
-
app.className = "localAuthStage";
|
|
214
|
+
app.className = "localAuthStage localAuthWelcomeStage";
|
|
189
215
|
app.innerHTML =
|
|
190
|
-
'<section class="
|
|
191
|
-
'<div class="
|
|
192
|
-
|
|
193
|
-
'<
|
|
194
|
-
'<
|
|
195
|
-
'<p>Echo sends a one-time code to your email. The browser stays on localhost; your device token and encryption key are stored only in the local EchoMem keystore.</p>' +
|
|
216
|
+
'<section class="localAuthWelcome" aria-labelledby="localAuthWelcomeTitle">' +
|
|
217
|
+
'<div class="localAuthOrbScene" aria-hidden="true"><span class="localAuthOrb"></span><span class="localAuthOrbShadow"></span></div>' +
|
|
218
|
+
'<div class="localAuthWelcomeCopy">' +
|
|
219
|
+
'<h2 id="localAuthWelcomeTitle">Welcome to Echo</h2>' +
|
|
220
|
+
'<p>Your memories, sovereign and shared.</p>' +
|
|
196
221
|
'</div>' +
|
|
197
|
-
'<form class="
|
|
198
|
-
'<
|
|
222
|
+
'<form class="localAuthWelcomeForm" id="localAuthEmailForm">' +
|
|
223
|
+
'<div class="localAuthEmailCapsule">' +
|
|
224
|
+
'<label class="srOnly" for="localAuthEmail">Email</label>' +
|
|
225
|
+
'<input id="localAuthEmail" type="email" autocomplete="email" placeholder="Enter your email" value="' + esc(localAuthEmail) + '" />' +
|
|
226
|
+
'<button id="localAuthSend" type="submit" aria-label="Send one-time code"><span aria-hidden="true">→</span></button>' +
|
|
227
|
+
'</div>' +
|
|
199
228
|
localAuthLegalHtml() +
|
|
200
|
-
'<button class="primary" id="localAuthSend" type="submit">Send code</button>' +
|
|
201
229
|
'<p class="localAuthStatus' + (message ? " is-error" : "") + '" id="localAuthStatus" role="status" aria-live="polite">' + esc(message || "") + '</p>' +
|
|
202
230
|
'</form>' +
|
|
203
231
|
'</section>';
|
|
@@ -208,12 +236,37 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
208
236
|
email.oninput = function () { localAuthEmail = String(email.value || ""); updateLocalAuthSendButton(); };
|
|
209
237
|
email.focus();
|
|
210
238
|
}
|
|
211
|
-
var
|
|
212
|
-
|
|
213
|
-
if (terms) terms.onchange = updateLocalAuthSendButton;
|
|
214
|
-
if (age) age.onchange = updateLocalAuthSendButton;
|
|
239
|
+
var consent = document.getElementById("localAuthConsent");
|
|
240
|
+
if (consent) consent.onchange = updateLocalAuthSendButton;
|
|
215
241
|
updateLocalAuthSendButton();
|
|
216
242
|
}
|
|
243
|
+
function renderLocalLoginComplete() {
|
|
244
|
+
setCityMode(false);
|
|
245
|
+
setScanMode(false);
|
|
246
|
+
setExtractMode(false);
|
|
247
|
+
setReadyMode(true);
|
|
248
|
+
setHead("EchoMem connected", "Done");
|
|
249
|
+
app.className = "notice";
|
|
250
|
+
app.innerHTML =
|
|
251
|
+
'<section class="localAuthCard localAuthComplete">' +
|
|
252
|
+
'<div class="localAuthLead">' +
|
|
253
|
+
'<img src="/hud-assets/echo-face-cutout.png" alt="" />' +
|
|
254
|
+
'<p class="consentEyebrow">This device is connected</p>' +
|
|
255
|
+
'<h2 class="siteHeadline">You\'re signed in.</h2>' +
|
|
256
|
+
'<p>Your local device token and encryption key are ready. Return to Terminal, or run <code>echomem-mcp init</code> when you want to start local-history onboarding.</p>' +
|
|
257
|
+
'</div>' +
|
|
258
|
+
'</section>';
|
|
259
|
+
}
|
|
260
|
+
async function finishLocalLogin() {
|
|
261
|
+
connected = true;
|
|
262
|
+
if (setupFlow === "login") {
|
|
263
|
+
renderLocalLoginComplete();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
rememberSetupPlanChoice("");
|
|
267
|
+
try { await refreshBillingStatus(); } catch (_) {}
|
|
268
|
+
await waitForStats();
|
|
269
|
+
}
|
|
217
270
|
async function sendLocalOtp() {
|
|
218
271
|
var email = document.getElementById("localAuthEmail");
|
|
219
272
|
localAuthEmail = email && email.value ? String(email.value).trim().toLowerCase() : "";
|
|
@@ -224,7 +277,7 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
224
277
|
return;
|
|
225
278
|
}
|
|
226
279
|
var button = document.getElementById("localAuthSend");
|
|
227
|
-
if (button) { button.disabled = true; button.
|
|
280
|
+
if (button) { button.disabled = true; button.innerHTML = '<span class="localAuthSpinner" aria-hidden="true"></span>'; }
|
|
228
281
|
setLocalAuthStatus("Sending verification code...");
|
|
229
282
|
try {
|
|
230
283
|
var data = await postJson("/local-auth/send-otp", {
|
|
@@ -235,7 +288,7 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
235
288
|
localAuthEmail = data.email || localAuthEmail;
|
|
236
289
|
renderLocalOtp("Code sent. Check your inbox.");
|
|
237
290
|
} catch (error) {
|
|
238
|
-
if (button) { button.disabled = false; button.
|
|
291
|
+
if (button) { button.disabled = false; button.innerHTML = '<span aria-hidden="true">→</span>'; }
|
|
239
292
|
setLocalAuthStatus(error && error.message ? error.message : "Could not send the code.", "error");
|
|
240
293
|
}
|
|
241
294
|
}
|
|
@@ -245,18 +298,26 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
245
298
|
setExtractMode(false);
|
|
246
299
|
setReadyMode(true);
|
|
247
300
|
setHead("Check your email", "Local login");
|
|
248
|
-
app.className = "localAuthStage";
|
|
301
|
+
app.className = "localAuthStage localAuthWelcomeStage localAuthOtpStage";
|
|
249
302
|
app.innerHTML =
|
|
250
|
-
'<section class="
|
|
251
|
-
'<div class="
|
|
252
|
-
|
|
253
|
-
'<
|
|
254
|
-
'<
|
|
255
|
-
'<p>This code signs in this local EchoMem bridge only. The next step asks for your encryption passphrase.</p>' +
|
|
303
|
+
'<section class="localAuthWelcome localAuthOtpWelcome" aria-labelledby="localAuthOtpTitle">' +
|
|
304
|
+
'<div class="localAuthOrbScene" aria-hidden="true"><span class="localAuthOrb"></span><span class="localAuthOrbShadow"></span></div>' +
|
|
305
|
+
'<div class="localAuthWelcomeCopy">' +
|
|
306
|
+
'<h2 id="localAuthOtpTitle">Check your inbox</h2>' +
|
|
307
|
+
'<p>We sent a 6-digit code to <strong>' + esc(localAuthEmail) + '</strong></p>' +
|
|
256
308
|
'</div>' +
|
|
257
|
-
'<form class="
|
|
258
|
-
'<label class="
|
|
259
|
-
'<div class="
|
|
309
|
+
'<form class="localAuthWelcomeForm localAuthOtpForm" id="localAuthOtpForm">' +
|
|
310
|
+
'<label class="srOnly" for="localAuthOtp0">6-digit code</label>' +
|
|
311
|
+
'<div class="localAuthOtpCells" aria-label="6-digit verification code">' +
|
|
312
|
+
'<input id="localAuthOtp0" data-otp-cell type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="1" />' +
|
|
313
|
+
'<input data-otp-cell type="text" inputmode="numeric" maxlength="1" />' +
|
|
314
|
+
'<input data-otp-cell type="text" inputmode="numeric" maxlength="1" />' +
|
|
315
|
+
'<input data-otp-cell type="text" inputmode="numeric" maxlength="1" />' +
|
|
316
|
+
'<input data-otp-cell type="text" inputmode="numeric" maxlength="1" />' +
|
|
317
|
+
'<input data-otp-cell type="text" inputmode="numeric" maxlength="1" />' +
|
|
318
|
+
'</div>' +
|
|
319
|
+
'<button class="primary localAuthVerifyWide" id="localAuthVerify" type="submit">Verify</button>' +
|
|
320
|
+
'<button class="secondary localAuthBackWide" id="localAuthBack" type="button">Use another email</button>' +
|
|
260
321
|
'<p class="localAuthStatus" id="localAuthStatus" role="status" aria-live="polite">' + esc(message || "") + '</p>' +
|
|
261
322
|
'</form>' +
|
|
262
323
|
'</section>';
|
|
@@ -264,12 +325,45 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
264
325
|
if (form) form.onsubmit = function (event) { event.preventDefault(); void verifyLocalOtp(); };
|
|
265
326
|
var back = document.getElementById("localAuthBack");
|
|
266
327
|
if (back) back.onclick = function () { renderLocalLogin(""); };
|
|
267
|
-
|
|
328
|
+
bindLocalOtpCells();
|
|
329
|
+
var otp = document.querySelector("[data-otp-cell]");
|
|
268
330
|
if (otp) otp.focus();
|
|
269
331
|
}
|
|
332
|
+
function localOtpCellValues() {
|
|
333
|
+
return Array.prototype.map.call(document.querySelectorAll("[data-otp-cell]"), function (node) {
|
|
334
|
+
return String(node.value || "").replace(/\\D/g, "").slice(0, 1);
|
|
335
|
+
}).join("");
|
|
336
|
+
}
|
|
337
|
+
function fillLocalOtpCells(value) {
|
|
338
|
+
var digits = String(value || "").replace(/\\D/g, "").slice(0, 6);
|
|
339
|
+
var cells = Array.prototype.slice.call(document.querySelectorAll("[data-otp-cell]"));
|
|
340
|
+
cells.forEach(function (cell, index) { cell.value = digits.charAt(index) || ""; });
|
|
341
|
+
var focusIndex = Math.min(digits.length, cells.length - 1);
|
|
342
|
+
if (cells[focusIndex]) cells[focusIndex].focus();
|
|
343
|
+
}
|
|
344
|
+
function bindLocalOtpCells() {
|
|
345
|
+
var cells = Array.prototype.slice.call(document.querySelectorAll("[data-otp-cell]"));
|
|
346
|
+
cells.forEach(function (cell, index) {
|
|
347
|
+
cell.oninput = function () {
|
|
348
|
+
var value = String(cell.value || "").replace(/\\D/g, "");
|
|
349
|
+
if (value.length > 1) { fillLocalOtpCells(value); return; }
|
|
350
|
+
cell.value = value;
|
|
351
|
+
if (value && cells[index + 1]) cells[index + 1].focus();
|
|
352
|
+
};
|
|
353
|
+
cell.onkeydown = function (event) {
|
|
354
|
+
if (event.key === "Backspace" && !cell.value && cells[index - 1]) cells[index - 1].focus();
|
|
355
|
+
};
|
|
356
|
+
cell.onpaste = function (event) {
|
|
357
|
+
var text = event.clipboardData && event.clipboardData.getData ? event.clipboardData.getData("text") : "";
|
|
358
|
+
if (text) {
|
|
359
|
+
event.preventDefault();
|
|
360
|
+
fillLocalOtpCells(text);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
});
|
|
364
|
+
}
|
|
270
365
|
async function verifyLocalOtp() {
|
|
271
|
-
var
|
|
272
|
-
var otp = otpInput && otpInput.value ? String(otpInput.value).replace(/\\D/g, "") : "";
|
|
366
|
+
var otp = localOtpCellValues();
|
|
273
367
|
if (otp.length !== 6) { setLocalAuthStatus("Enter the 6-digit code.", "error"); return; }
|
|
274
368
|
var button = document.getElementById("localAuthVerify");
|
|
275
369
|
if (button) { button.disabled = true; button.textContent = "Verifying..."; }
|
|
@@ -285,8 +379,7 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
285
379
|
renderLocalPassphrase(data.mode || "unlock", data.email || localAuthEmail);
|
|
286
380
|
return;
|
|
287
381
|
}
|
|
288
|
-
|
|
289
|
-
await waitForStats();
|
|
382
|
+
await finishLocalLogin();
|
|
290
383
|
} catch (error) {
|
|
291
384
|
if (button) { button.disabled = false; button.textContent = "Verify code"; }
|
|
292
385
|
setLocalAuthStatus(error && error.message ? error.message : "Could not verify the code.", "error");
|
|
@@ -300,19 +393,19 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
300
393
|
setExtractMode(false);
|
|
301
394
|
setReadyMode(true);
|
|
302
395
|
setHead(setupMode ? "Create encrypted vault" : "Unlock encrypted vault", "Local passphrase");
|
|
303
|
-
app.className = "localAuthStage";
|
|
396
|
+
app.className = "localAuthStage localAuthWelcomeStage localAuthPassphraseStage";
|
|
304
397
|
app.innerHTML =
|
|
305
|
-
'<section class="
|
|
306
|
-
'<div class="
|
|
307
|
-
|
|
308
|
-
'<
|
|
309
|
-
'<h2 class="siteHeadline">' + (setupMode ? 'Create your local vault passphrase.' : 'Enter your vault passphrase.') + '</h2>' +
|
|
398
|
+
'<section class="localAuthWelcome localAuthPassphraseWelcome">' +
|
|
399
|
+
'<div class="localAuthOrbScene" aria-hidden="true"><span class="localAuthOrb"></span><span class="localAuthOrbShadow"></span></div>' +
|
|
400
|
+
'<div class="localAuthWelcomeCopy">' +
|
|
401
|
+
'<h2>' + (setupMode ? 'Create your local vault passphrase.' : 'Enter your vault passphrase.') + '</h2>' +
|
|
310
402
|
'<p>' + (setupMode ? 'Echo derives your encryption key on this device. The passphrase and key are never sent to EchoMem. If you forget it, encrypted memories cannot be recovered.' : 'Echo verifies this passphrase locally against your account encryption token. The passphrase is never sent to EchoMem.') + '</p>' +
|
|
311
403
|
'</div>' +
|
|
312
|
-
'<form class="
|
|
404
|
+
'<form class="localAuthWelcomeForm localAuthPassphraseForm" id="localAuthPassphraseForm">' +
|
|
313
405
|
'<label class="localAuthField"><span>Passphrase</span><input id="localAuthPassphrase" type="password" autocomplete="' + (setupMode ? "new-password" : "current-password") + '" placeholder="Encryption passphrase" /></label>' +
|
|
314
406
|
(setupMode ? '<label class="localAuthField"><span>Confirm passphrase</span><input id="localAuthPassphraseConfirm" type="password" autocomplete="new-password" placeholder="Confirm passphrase" /></label>' : '') +
|
|
315
|
-
'<
|
|
407
|
+
'<button class="primary localAuthPassphraseSubmit" id="localAuthUnlock" type="submit">' + (setupMode ? "Create vault" : "Unlock") + '</button>' +
|
|
408
|
+
'<button class="secondary localAuthBackWide" id="localAuthRestart" type="button">Use a different email</button>' +
|
|
316
409
|
'<p class="localAuthStatus' + (message ? " is-error" : "") + '" id="localAuthStatus" role="status" aria-live="polite">' + esc(message || "") + '</p>' +
|
|
317
410
|
'</form>' +
|
|
318
411
|
'</section>';
|
|
@@ -335,8 +428,7 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
335
428
|
setLocalAuthStatus(setupMode ? "Creating encrypted vault..." : "Unlocking vault...");
|
|
336
429
|
try {
|
|
337
430
|
await postJson("/local-auth/passphrase", { passphrase: passphrase }, 30000);
|
|
338
|
-
|
|
339
|
-
await waitForStats();
|
|
431
|
+
await finishLocalLogin();
|
|
340
432
|
} catch (error) {
|
|
341
433
|
if (button) { button.disabled = false; button.textContent = setupMode ? "Create vault" : "Unlock"; }
|
|
342
434
|
var msg = error && error.message ? error.message : "Could not unlock encrypted memory.";
|
|
@@ -350,6 +442,7 @@ export const SETUP_PAGE_CLIENT_CORE = String.raw ` var params = new URLSear
|
|
|
350
442
|
return;
|
|
351
443
|
}
|
|
352
444
|
if (connected) { void waitForStats(); return; }
|
|
445
|
+
rememberSetupPlanChoice("");
|
|
353
446
|
renderLocalLogin("");
|
|
354
447
|
}
|
|
355
448
|
function bindConnect() {
|