@victor-software-house/pi-multicodex 2.1.4 → 2.2.0
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/account-manager.ts +60 -27
- package/commands.ts +256 -58
- package/package.json +1 -1
package/account-manager.ts
CHANGED
|
@@ -313,6 +313,42 @@ export class AccountManager {
|
|
|
313
313
|
);
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
+
private getLinkedImportedAccount(): Account | undefined {
|
|
317
|
+
return this.data.accounts.find(
|
|
318
|
+
(account) =>
|
|
319
|
+
account.importSource === "pi-openai-codex" &&
|
|
320
|
+
account.importMode !== "synthetic",
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private getSyntheticImportedAccount(): Account | undefined {
|
|
325
|
+
return this.data.accounts.find(
|
|
326
|
+
(account) =>
|
|
327
|
+
account.importSource === "pi-openai-codex" &&
|
|
328
|
+
account.importMode === "synthetic",
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private findManagedImportedTarget(imported: {
|
|
333
|
+
identifier: string;
|
|
334
|
+
credentials: OAuthCredentials;
|
|
335
|
+
}): Account | undefined {
|
|
336
|
+
const byRefreshToken = this.data.accounts.find(
|
|
337
|
+
(account) =>
|
|
338
|
+
account.importMode !== "synthetic" &&
|
|
339
|
+
account.refreshToken === imported.credentials.refresh,
|
|
340
|
+
);
|
|
341
|
+
if (byRefreshToken) {
|
|
342
|
+
return byRefreshToken;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return this.data.accounts.find(
|
|
346
|
+
(account) =>
|
|
347
|
+
account.importMode !== "synthetic" &&
|
|
348
|
+
account.email === imported.identifier,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
316
352
|
private clearImportedLink(account: Account): boolean {
|
|
317
353
|
let changed = false;
|
|
318
354
|
if (account.importSource) {
|
|
@@ -334,19 +370,18 @@ export class AccountManager {
|
|
|
334
370
|
const imported = await loadImportedOpenAICodexAuth();
|
|
335
371
|
if (!imported) return false;
|
|
336
372
|
|
|
337
|
-
const
|
|
373
|
+
const linkedImported = this.getLinkedImportedAccount();
|
|
374
|
+
const syntheticImported = this.getSyntheticImportedAccount();
|
|
375
|
+
const currentImported = linkedImported ?? syntheticImported;
|
|
338
376
|
if (
|
|
339
|
-
|
|
340
|
-
(
|
|
341
|
-
|
|
377
|
+
currentImported?.importFingerprint === imported.fingerprint &&
|
|
378
|
+
(currentImported.importMode !== "synthetic" ||
|
|
379
|
+
currentImported.email === imported.identifier)
|
|
342
380
|
) {
|
|
343
381
|
return false;
|
|
344
382
|
}
|
|
345
383
|
|
|
346
|
-
const matchingAccount = this.
|
|
347
|
-
imported.credentials.refresh,
|
|
348
|
-
existingImported?.email,
|
|
349
|
-
);
|
|
384
|
+
const matchingAccount = this.findManagedImportedTarget(imported);
|
|
350
385
|
if (matchingAccount) {
|
|
351
386
|
let changed = this.applyCredentials(
|
|
352
387
|
matchingAccount,
|
|
@@ -357,12 +392,11 @@ export class AccountManager {
|
|
|
357
392
|
importFingerprint: imported.fingerprint,
|
|
358
393
|
},
|
|
359
394
|
);
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
395
|
+
if (linkedImported && linkedImported !== matchingAccount) {
|
|
396
|
+
changed = this.clearImportedLink(linkedImported) || changed;
|
|
397
|
+
}
|
|
398
|
+
if (syntheticImported) {
|
|
399
|
+
changed = this.removeAccountRecord(syntheticImported) || changed;
|
|
366
400
|
}
|
|
367
401
|
if (changed) {
|
|
368
402
|
this.save();
|
|
@@ -371,17 +405,24 @@ export class AccountManager {
|
|
|
371
405
|
return changed;
|
|
372
406
|
}
|
|
373
407
|
|
|
374
|
-
if (
|
|
375
|
-
const
|
|
408
|
+
if (linkedImported) {
|
|
409
|
+
const changed = this.clearImportedLink(linkedImported);
|
|
410
|
+
if (changed) {
|
|
411
|
+
this.save();
|
|
412
|
+
this.notifyStateChanged();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (syntheticImported) {
|
|
376
417
|
let changed = false;
|
|
377
|
-
if (
|
|
418
|
+
if (syntheticImported.email !== imported.identifier) {
|
|
378
419
|
changed = this.updateAccountEmail(
|
|
379
|
-
|
|
420
|
+
syntheticImported,
|
|
380
421
|
imported.identifier,
|
|
381
422
|
);
|
|
382
423
|
}
|
|
383
424
|
changed =
|
|
384
|
-
this.applyCredentials(
|
|
425
|
+
this.applyCredentials(syntheticImported, imported.credentials, {
|
|
385
426
|
importSource: "pi-openai-codex",
|
|
386
427
|
importMode: "synthetic",
|
|
387
428
|
importFingerprint: imported.fingerprint,
|
|
@@ -393,14 +434,6 @@ export class AccountManager {
|
|
|
393
434
|
return changed;
|
|
394
435
|
}
|
|
395
436
|
|
|
396
|
-
if (existingImported) {
|
|
397
|
-
const changed = this.clearImportedLink(existingImported);
|
|
398
|
-
if (changed) {
|
|
399
|
-
this.save();
|
|
400
|
-
this.notifyStateChanged();
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
437
|
this.addOrUpdateAccount(imported.identifier, imported.credentials, {
|
|
405
438
|
importSource: "pi-openai-codex",
|
|
406
439
|
importMode: "synthetic",
|
package/commands.ts
CHANGED
|
@@ -5,14 +5,15 @@ import type {
|
|
|
5
5
|
ExtensionAPI,
|
|
6
6
|
ExtensionCommandContext,
|
|
7
7
|
} from "@mariozechner/pi-coding-agent";
|
|
8
|
-
import {
|
|
8
|
+
import { DynamicBorder, rawKeyHint } from "@mariozechner/pi-coding-agent";
|
|
9
9
|
import {
|
|
10
10
|
type AutocompleteItem,
|
|
11
11
|
Container,
|
|
12
|
-
|
|
12
|
+
getKeybindings,
|
|
13
13
|
matchesKey,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Spacer,
|
|
15
|
+
truncateToWidth,
|
|
16
|
+
visibleWidth,
|
|
16
17
|
} from "@mariozechner/pi-tui";
|
|
17
18
|
import { getAgentSettingsPath } from "pi-provider-utils/agent-paths";
|
|
18
19
|
import { normalizeUnknownError } from "pi-provider-utils/streams";
|
|
@@ -20,7 +21,7 @@ import type { AccountManager } from "./account-manager";
|
|
|
20
21
|
import { writeActiveTokenToAuthJson } from "./auth";
|
|
21
22
|
import { openLoginInBrowser } from "./browser";
|
|
22
23
|
import type { createUsageStatusController } from "./status";
|
|
23
|
-
import { STORAGE_FILE } from "./storage";
|
|
24
|
+
import { type Account, STORAGE_FILE } from "./storage";
|
|
24
25
|
import { formatResetAt, isUsageUntouched } from "./usage";
|
|
25
26
|
|
|
26
27
|
const SETTINGS_FILE = getAgentSettingsPath();
|
|
@@ -87,31 +88,42 @@ function parseResetTarget(value: string): ResetTarget | undefined {
|
|
|
87
88
|
return undefined;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
function
|
|
91
|
+
function isPlaceholderAccount(account: Account): boolean {
|
|
92
|
+
return (
|
|
93
|
+
!account.accessToken || !account.refreshToken || account.expiresAt <= 0
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function getAccountTags(
|
|
91
98
|
accountManager: AccountManager,
|
|
92
|
-
|
|
93
|
-
): string {
|
|
94
|
-
const account = accountManager.getAccount(email);
|
|
95
|
-
if (!account) return email;
|
|
99
|
+
account: Account,
|
|
100
|
+
): string[] {
|
|
96
101
|
const usage = accountManager.getCachedUsage(account.email);
|
|
97
102
|
const active = accountManager.getActiveAccount();
|
|
98
103
|
const manual = accountManager.getManualAccount();
|
|
99
104
|
const quotaHit =
|
|
100
105
|
account.quotaExhaustedUntil && account.quotaExhaustedUntil > Date.now();
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
const imported = account.importSource
|
|
107
|
+
? account.importMode === "synthetic"
|
|
108
|
+
? "pi auth only"
|
|
109
|
+
: "pi auth"
|
|
110
|
+
: null;
|
|
111
|
+
return [
|
|
105
112
|
active?.email === account.email ? "active" : null,
|
|
106
113
|
manual?.email === account.email ? "manual" : null,
|
|
107
|
-
reauth,
|
|
114
|
+
account.needsReauth ? "needs reauth" : null,
|
|
115
|
+
isPlaceholderAccount(account) ? "placeholder" : null,
|
|
108
116
|
quotaHit ? "quota" : null,
|
|
109
|
-
untouched,
|
|
117
|
+
isUsageUntouched(usage) ? "untouched" : null,
|
|
110
118
|
imported,
|
|
111
|
-
]
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
].filter((value): value is string => Boolean(value));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function formatUsageSummary(
|
|
123
|
+
accountManager: AccountManager,
|
|
124
|
+
account: Account,
|
|
125
|
+
): string {
|
|
126
|
+
const usage = accountManager.getCachedUsage(account.email);
|
|
115
127
|
const primaryUsed = usage?.primary?.usedPercent;
|
|
116
128
|
const secondaryUsed = usage?.secondary?.usedPercent;
|
|
117
129
|
const primaryReset = usage?.primary?.resetAt;
|
|
@@ -120,8 +132,18 @@ function formatAccountStatusLine(
|
|
|
120
132
|
primaryUsed === undefined ? "unknown" : `${Math.round(primaryUsed)}%`;
|
|
121
133
|
const secondaryLabel =
|
|
122
134
|
secondaryUsed === undefined ? "unknown" : `${Math.round(secondaryUsed)}%`;
|
|
123
|
-
|
|
124
|
-
|
|
135
|
+
return `5h ${primaryLabel} reset:${formatResetAt(primaryReset)} | weekly ${secondaryLabel} reset:${formatResetAt(secondaryReset)}`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function formatAccountStatusLine(
|
|
139
|
+
accountManager: AccountManager,
|
|
140
|
+
email: string,
|
|
141
|
+
): string {
|
|
142
|
+
const account = accountManager.getAccount(email);
|
|
143
|
+
if (!account) return email;
|
|
144
|
+
const tags = getAccountTags(accountManager, account).join(", ");
|
|
145
|
+
const suffix = tags ? ` (${tags})` : "";
|
|
146
|
+
return `${account.email}${suffix} - ${formatUsageSummary(accountManager, account)}`;
|
|
125
147
|
}
|
|
126
148
|
|
|
127
149
|
function getSubcommandCompletions(prefix: string): AutocompleteItem[] | null {
|
|
@@ -340,58 +362,234 @@ async function openAccountManagementPanel(
|
|
|
340
362
|
accountManager: AccountManager,
|
|
341
363
|
): Promise<AccountPanelResult> {
|
|
342
364
|
const accounts = accountManager.getAccounts();
|
|
343
|
-
const items = accounts.map((account) => ({
|
|
344
|
-
value: account.email,
|
|
345
|
-
label: formatAccountStatusLine(accountManager, account.email),
|
|
346
|
-
}));
|
|
347
365
|
|
|
348
|
-
return ctx.ui.custom<AccountPanelResult>((
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
)
|
|
366
|
+
return ctx.ui.custom<AccountPanelResult>((tui, theme, _kb, done) => {
|
|
367
|
+
const kb = getKeybindings();
|
|
368
|
+
let selectedIndex = 0;
|
|
369
|
+
const maxVisible = 12;
|
|
370
|
+
|
|
371
|
+
function getSelectedAccount(): Account | undefined {
|
|
372
|
+
return accounts[selectedIndex];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function findNextIndex(from: number, direction: number): number {
|
|
376
|
+
if (accounts.length === 0) return 0;
|
|
377
|
+
return Math.max(0, Math.min(accounts.length - 1, from + direction));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function renderTag(text: string): string {
|
|
381
|
+
if (text === "active") {
|
|
382
|
+
return theme.fg("accent", `[${text}]`);
|
|
383
|
+
}
|
|
384
|
+
if (text === "manual") {
|
|
385
|
+
return theme.fg("warning", `[${text}]`);
|
|
386
|
+
}
|
|
387
|
+
if (text === "needs reauth") {
|
|
388
|
+
return theme.fg("error", `[${text}]`);
|
|
389
|
+
}
|
|
390
|
+
if (text === "placeholder") {
|
|
391
|
+
return theme.fg("warning", `[${text}]`);
|
|
392
|
+
}
|
|
393
|
+
if (text === "quota") {
|
|
394
|
+
return theme.fg("warning", `[${text}]`);
|
|
395
|
+
}
|
|
396
|
+
if (text === "pi auth" || text === "pi auth only") {
|
|
397
|
+
return theme.fg("success", `[${text}]`);
|
|
398
|
+
}
|
|
399
|
+
return theme.fg("muted", `[${text}]`);
|
|
400
|
+
}
|
|
363
401
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
402
|
+
function renderRow(
|
|
403
|
+
account: Account,
|
|
404
|
+
selected: boolean,
|
|
405
|
+
width: number,
|
|
406
|
+
): string[] {
|
|
407
|
+
const cursor = selected ? theme.fg("accent", ">") : theme.fg("dim", " ");
|
|
408
|
+
const name = selected ? theme.bold(account.email) : account.email;
|
|
409
|
+
const tags = getAccountTags(accountManager, account)
|
|
410
|
+
.map((tag) => renderTag(tag))
|
|
411
|
+
.join(" ");
|
|
412
|
+
const primary = truncateToWidth(
|
|
413
|
+
`${cursor} ${name}${tags ? ` ${tags}` : ""}`,
|
|
414
|
+
width,
|
|
415
|
+
"",
|
|
416
|
+
);
|
|
417
|
+
const summaryColor = account.needsReauth
|
|
418
|
+
? "warning"
|
|
419
|
+
: isPlaceholderAccount(account)
|
|
420
|
+
? "muted"
|
|
421
|
+
: "dim";
|
|
422
|
+
const secondary = theme.fg(
|
|
423
|
+
summaryColor,
|
|
424
|
+
formatUsageSummary(accountManager, account),
|
|
425
|
+
);
|
|
426
|
+
return [primary, truncateToWidth(` ${secondary}`, width, "")];
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const header = {
|
|
430
|
+
invalidate() {},
|
|
431
|
+
render(width: number): string[] {
|
|
432
|
+
const title = theme.bold("MultiCodex Accounts");
|
|
433
|
+
const sep = theme.fg("muted", " · ");
|
|
434
|
+
const hints = [
|
|
435
|
+
rawKeyHint("enter", "use"),
|
|
436
|
+
rawKeyHint("u", "refresh"),
|
|
437
|
+
rawKeyHint("r", "reauth"),
|
|
438
|
+
rawKeyHint("n", "add"),
|
|
439
|
+
rawKeyHint("backspace", "remove"),
|
|
440
|
+
rawKeyHint("esc", "close"),
|
|
441
|
+
].join(sep);
|
|
442
|
+
const spacing = Math.max(
|
|
443
|
+
1,
|
|
444
|
+
width - visibleWidth(title) - visibleWidth(hints),
|
|
445
|
+
);
|
|
446
|
+
const reauthCount = accountManager.getAccountsNeedingReauth().length;
|
|
447
|
+
const placeholderCount = accounts.filter((account) =>
|
|
448
|
+
isPlaceholderAccount(account),
|
|
449
|
+
).length;
|
|
450
|
+
const status = [
|
|
451
|
+
`${accounts.length} account${accounts.length === 1 ? "" : "s"}`,
|
|
452
|
+
reauthCount > 0 ? `${reauthCount} need reauth` : undefined,
|
|
453
|
+
placeholderCount > 0
|
|
454
|
+
? `${placeholderCount} placeholder${placeholderCount === 1 ? "" : "s"}`
|
|
455
|
+
: undefined,
|
|
456
|
+
]
|
|
457
|
+
.filter(Boolean)
|
|
458
|
+
.join(" · ");
|
|
459
|
+
return [
|
|
460
|
+
truncateToWidth(`${title}${" ".repeat(spacing)}${hints}`, width, ""),
|
|
461
|
+
theme.fg("muted", status),
|
|
462
|
+
];
|
|
463
|
+
},
|
|
367
464
|
};
|
|
368
|
-
|
|
369
|
-
|
|
465
|
+
|
|
466
|
+
const list = {
|
|
467
|
+
invalidate() {},
|
|
468
|
+
render(width: number): string[] {
|
|
469
|
+
const lines: string[] = [];
|
|
470
|
+
if (accounts.length === 0) {
|
|
471
|
+
return [theme.fg("muted", " No managed accounts")];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const visibleRows = Math.max(1, Math.floor(maxVisible / 2));
|
|
475
|
+
const startIndex = Math.max(
|
|
476
|
+
0,
|
|
477
|
+
Math.min(
|
|
478
|
+
selectedIndex - Math.floor(visibleRows / 2),
|
|
479
|
+
Math.max(0, accounts.length - visibleRows),
|
|
480
|
+
),
|
|
481
|
+
);
|
|
482
|
+
const endIndex = Math.min(accounts.length, startIndex + visibleRows);
|
|
483
|
+
|
|
484
|
+
for (let index = startIndex; index < endIndex; index++) {
|
|
485
|
+
const account = accounts[index];
|
|
486
|
+
if (!account) continue;
|
|
487
|
+
lines.push(...renderRow(account, index === selectedIndex, width));
|
|
488
|
+
if (index < endIndex - 1) {
|
|
489
|
+
lines.push("");
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const selected = getSelectedAccount();
|
|
494
|
+
if (selected) {
|
|
495
|
+
lines.push("");
|
|
496
|
+
const detail = isPlaceholderAccount(selected)
|
|
497
|
+
? `selected: ${selected.email} · restored placeholder, re-auth required`
|
|
498
|
+
: `selected: ${selected.email}`;
|
|
499
|
+
lines.push(truncateToWidth(theme.fg("dim", detail), width, ""));
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const current = selectedIndex + 1;
|
|
503
|
+
lines.push(
|
|
504
|
+
theme.fg(
|
|
505
|
+
"dim",
|
|
506
|
+
` ${current}/${accounts.length} visible account rows`,
|
|
507
|
+
),
|
|
508
|
+
);
|
|
509
|
+
return lines;
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
const container = new Container();
|
|
514
|
+
container.addChild(new Spacer(1));
|
|
515
|
+
container.addChild(new DynamicBorder());
|
|
516
|
+
container.addChild(new Spacer(1));
|
|
517
|
+
container.addChild(header);
|
|
518
|
+
container.addChild(new Spacer(1));
|
|
519
|
+
container.addChild(list);
|
|
520
|
+
container.addChild(new Spacer(1));
|
|
521
|
+
container.addChild(new DynamicBorder());
|
|
370
522
|
|
|
371
523
|
return {
|
|
372
|
-
render
|
|
373
|
-
|
|
374
|
-
|
|
524
|
+
render(width: number) {
|
|
525
|
+
return container.render(width);
|
|
526
|
+
},
|
|
527
|
+
invalidate() {
|
|
528
|
+
container.invalidate();
|
|
529
|
+
},
|
|
530
|
+
handleInput(data: string) {
|
|
531
|
+
if (kb.matches(data, "tui.select.up")) {
|
|
532
|
+
selectedIndex = findNextIndex(selectedIndex, -1);
|
|
533
|
+
tui.requestRender();
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (kb.matches(data, "tui.select.down")) {
|
|
537
|
+
selectedIndex = findNextIndex(selectedIndex, 1);
|
|
538
|
+
tui.requestRender();
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
if (kb.matches(data, "tui.select.pageUp")) {
|
|
542
|
+
selectedIndex = findNextIndex(selectedIndex, -5);
|
|
543
|
+
tui.requestRender();
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
if (kb.matches(data, "tui.select.pageDown")) {
|
|
547
|
+
selectedIndex = findNextIndex(selectedIndex, 5);
|
|
548
|
+
tui.requestRender();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (
|
|
552
|
+
kb.matches(data, "tui.select.cancel") ||
|
|
553
|
+
matchesKey(data, "ctrl+c")
|
|
554
|
+
) {
|
|
555
|
+
done(undefined);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (
|
|
559
|
+
data === "\r" ||
|
|
560
|
+
data === "\n" ||
|
|
561
|
+
kb.matches(data, "tui.select.confirm")
|
|
562
|
+
) {
|
|
563
|
+
const selected = getSelectedAccount();
|
|
564
|
+
if (selected) {
|
|
565
|
+
done({ action: "select", email: selected.email });
|
|
566
|
+
}
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
375
569
|
if (data.toLowerCase() === "n") {
|
|
376
570
|
done({ action: "add" });
|
|
377
571
|
return;
|
|
378
572
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
573
|
+
if (data.toLowerCase() === "u") {
|
|
574
|
+
const selected = getSelectedAccount();
|
|
575
|
+
if (selected) {
|
|
576
|
+
done({ action: "refresh", email: selected.email });
|
|
577
|
+
}
|
|
382
578
|
return;
|
|
383
579
|
}
|
|
384
|
-
if (
|
|
385
|
-
|
|
580
|
+
if (data.toLowerCase() === "r") {
|
|
581
|
+
const selected = getSelectedAccount();
|
|
582
|
+
if (selected) {
|
|
583
|
+
done({ action: "reauth", email: selected.email });
|
|
584
|
+
}
|
|
386
585
|
return;
|
|
387
586
|
}
|
|
388
|
-
if (matchesKey(data,
|
|
587
|
+
if (matchesKey(data, "backspace")) {
|
|
588
|
+
const selected = getSelectedAccount();
|
|
389
589
|
if (selected) {
|
|
390
|
-
done({ action: "remove", email: selected.
|
|
590
|
+
done({ action: "remove", email: selected.email });
|
|
391
591
|
}
|
|
392
|
-
return;
|
|
393
592
|
}
|
|
394
|
-
selectList.handleInput(data);
|
|
395
593
|
},
|
|
396
594
|
};
|
|
397
595
|
});
|