teamclaude-cloud 1.7.0 → 1.8.1
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/package.json +1 -1
- package/src/account-manager.js +7 -6
- package/src/cloud.js +12 -2
- package/src/index.js +14 -9
- package/src/tui.js +8 -4
package/package.json
CHANGED
package/src/account-manager.js
CHANGED
|
@@ -61,10 +61,11 @@ export class AccountManager {
|
|
|
61
61
|
// means "no preference" — selection then falls back to use-or-lose. So a
|
|
62
62
|
// config with no priorities behaves exactly as before.
|
|
63
63
|
priority: Number.isFinite(acct.priority) ? Math.floor(acct.priority) : null,
|
|
64
|
-
// Provenance: an account
|
|
65
|
-
//
|
|
66
|
-
// the dashboard/status can label it "
|
|
67
|
-
|
|
64
|
+
// Provenance: an account that belongs to a personal (private) cloud group
|
|
65
|
+
// carries cloudPrivate (set by mergePulledAccounts from the pull response's
|
|
66
|
+
// `personal` flag). Surfaced so the dashboard/status can label it "private"
|
|
67
|
+
// vs a shared/fleet account.
|
|
68
|
+
isPrivate: acct.cloudPrivate === true,
|
|
68
69
|
quota: emptyQuota(),
|
|
69
70
|
usage: {
|
|
70
71
|
totalInputTokens: 0,
|
|
@@ -1058,7 +1059,7 @@ export class AccountManager {
|
|
|
1058
1059
|
status: 'active',
|
|
1059
1060
|
enabled: acctData.enabled !== false,
|
|
1060
1061
|
priority: Number.isFinite(acctData.priority) ? Math.floor(acctData.priority) : null,
|
|
1061
|
-
|
|
1062
|
+
isPrivate: acctData.cloudPrivate === true,
|
|
1062
1063
|
quota: emptyQuota(),
|
|
1063
1064
|
usage: { totalInputTokens: 0, totalOutputTokens: 0, totalRequests: 0, lastUsed: null },
|
|
1064
1065
|
rateLimitedUntil: null,
|
|
@@ -1259,7 +1260,7 @@ export class AccountManager {
|
|
|
1259
1260
|
type: a.type,
|
|
1260
1261
|
status: a.status,
|
|
1261
1262
|
enabled: a.enabled !== false,
|
|
1262
|
-
|
|
1263
|
+
isPrivate: a.isPrivate === true,
|
|
1263
1264
|
priority: a.priority ?? null,
|
|
1264
1265
|
// Deep-copy the nested modelWeekly map — the shallow quota spread would
|
|
1265
1266
|
// otherwise hand callers a live reference into account state.
|
package/src/cloud.js
CHANGED
|
@@ -593,6 +593,14 @@ export function mergePulledAccounts(config, pulled, source = null, allowed = nul
|
|
|
593
593
|
if (Number.isInteger(incoming.priority)) target.priority = incoming.priority;
|
|
594
594
|
else delete target.priority; // null → automatic ordering
|
|
595
595
|
};
|
|
596
|
+
// Personal-group (private) display flag from the pull response. Authoritative when
|
|
597
|
+
// the server sends `personal` (a pull can move an account in/out of a personal
|
|
598
|
+
// group); left untouched on a pre-personal server response so it isn't wiped.
|
|
599
|
+
const applyPrivate = (target, incoming) => {
|
|
600
|
+
if (!('personal' in incoming)) return;
|
|
601
|
+
if (incoming.personal === true) target.cloudPrivate = true;
|
|
602
|
+
else delete target.cloudPrivate;
|
|
603
|
+
};
|
|
596
604
|
// Multi-source tagging: an account can be managed by several keys (a consumer
|
|
597
605
|
// using >1 key whose groups overlap). Each key adds its source; an account is
|
|
598
606
|
// only pruned once NO managing key still allows it (Codex round 4 R4-3).
|
|
@@ -624,6 +632,7 @@ export function mergePulledAccounts(config, pulled, source = null, allowed = nul
|
|
|
624
632
|
applyOverlay(fresh); // honor an offline local-disable that survived a prune+re-add
|
|
625
633
|
addSource(fresh);
|
|
626
634
|
applyPriority(fresh, a);
|
|
635
|
+
applyPrivate(fresh, a);
|
|
627
636
|
config.accounts.push(fresh);
|
|
628
637
|
summary.added++;
|
|
629
638
|
continue;
|
|
@@ -638,9 +647,9 @@ export function mergePulledAccounts(config, pulled, source = null, allowed = nul
|
|
|
638
647
|
addSource(cur); // now managed by this key (so this key can prune it later)
|
|
639
648
|
// A payload entry with no token at all (allowed-but-tokenless) must not clobber
|
|
640
649
|
// a valid local token — only apply priority/metadata, keep the local token.
|
|
641
|
-
if (!hasAnyToken(a)) { applyPriority(cur, a); summary.skipped++; continue; }
|
|
650
|
+
if (!hasAnyToken(a)) { applyPriority(cur, a); applyPrivate(cur, a); summary.skipped++; continue; }
|
|
642
651
|
const curExp = normalizeExpiresAt(cur.expiresAt) || 0;
|
|
643
|
-
if (curExp > incomingExp) { applyPriority(cur, a); summary.skipped++; continue; } // local token fresher — keep it
|
|
652
|
+
if (curExp > incomingExp) { applyPriority(cur, a); applyPrivate(cur, a); summary.skipped++; continue; } // local token fresher — keep it
|
|
644
653
|
config.accounts[idx] = {
|
|
645
654
|
...cur,
|
|
646
655
|
accountUuid: a.accountUuid || cur.accountUuid,
|
|
@@ -654,6 +663,7 @@ export function mergePulledAccounts(config, pulled, source = null, allowed = nul
|
|
|
654
663
|
};
|
|
655
664
|
applyOverlay(config.accounts[idx]); // re-assert overlay on the rebuilt row
|
|
656
665
|
applyPriority(config.accounts[idx], a);
|
|
666
|
+
applyPrivate(config.accounts[idx], a);
|
|
657
667
|
summary.updated++;
|
|
658
668
|
}
|
|
659
669
|
// Prune: only when the server sent an authoritative allow-set (`allowed`). Never
|
package/src/index.js
CHANGED
|
@@ -892,8 +892,8 @@ async function statusCommand() {
|
|
|
892
892
|
const current = acct.name === data.currentAccount ? ' *' : '';
|
|
893
893
|
|
|
894
894
|
const disabledTag = acct.enabled === false ? ' [disabled]' : '';
|
|
895
|
-
const
|
|
896
|
-
console.log(` ${maskIf(acct.name, config.maskMode)} (${acct.type})${current}${
|
|
895
|
+
const privateTag = acct.isPrivate ? ' [🔑 private]' : '';
|
|
896
|
+
console.log(` ${maskIf(acct.name, config.maskMode)} (${acct.type})${current}${privateTag}${disabledTag}`);
|
|
897
897
|
console.log(` Status: ${acct.status}${acct.enabled === false ? ' (disabled — out of rotation)' : ''}`);
|
|
898
898
|
if (acct.priority != null) console.log(` Priority: ${acct.priority} (lower = preferred)`);
|
|
899
899
|
if (acct.maxConcurrent != null) {
|
|
@@ -1347,9 +1347,9 @@ async function syncAccountsFromDisk(diskConfig, memConfig, accountManager) {
|
|
|
1347
1347
|
if (mgr.enabled !== wantEnabled) accountManager.setEnabled(mgr, wantEnabled);
|
|
1348
1348
|
const diskPriority = Number.isFinite(diskAcct.priority) ? Math.floor(diskAcct.priority) : null;
|
|
1349
1349
|
if (mgr.priority !== diskPriority) accountManager.setPriority(mgr, diskPriority);
|
|
1350
|
-
// Provenance can change while running (a cloud pull
|
|
1351
|
-
// so refresh the
|
|
1352
|
-
mgr.
|
|
1350
|
+
// Provenance can change while running (a cloud pull moves an account in/out of
|
|
1351
|
+
// a personal group), so refresh the private flag on reload too.
|
|
1352
|
+
mgr.isPrivate = diskAcct.cloudPrivate === true;
|
|
1353
1353
|
// Mirror the applied state into the in-memory config copy too. Otherwise a
|
|
1354
1354
|
// later TUI saveConfig (for any unrelated op) would spread the pre-sync
|
|
1355
1355
|
// enabled/priority over the disk value and silently revert a CLI change.
|
|
@@ -1357,15 +1357,20 @@ async function syncAccountsFromDisk(diskConfig, memConfig, accountManager) {
|
|
|
1357
1357
|
if (memAcct) {
|
|
1358
1358
|
if (wantEnabled) delete memAcct.enabled; else memAcct.enabled = false;
|
|
1359
1359
|
if (diskPriority === null) delete memAcct.priority; else memAcct.priority = diskPriority;
|
|
1360
|
-
// cloudSources
|
|
1361
|
-
//
|
|
1362
|
-
// would overlay the stale in-memory
|
|
1363
|
-
//
|
|
1360
|
+
// cloudSources (prune scoping) and cloudPrivate (personal-group display) are
|
|
1361
|
+
// both authoritative on disk — a cloud pull tags/untags them. Mirror both, or
|
|
1362
|
+
// a later TUI saveConfig would overlay the stale in-memory value onto disk
|
|
1363
|
+
// and resurrect a source tag / private flag a pull just changed.
|
|
1364
1364
|
if (Array.isArray(diskAcct.cloudSources) && diskAcct.cloudSources.length > 0) {
|
|
1365
1365
|
memAcct.cloudSources = diskAcct.cloudSources;
|
|
1366
1366
|
} else {
|
|
1367
1367
|
delete memAcct.cloudSources;
|
|
1368
1368
|
}
|
|
1369
|
+
if (diskAcct.cloudPrivate === true) {
|
|
1370
|
+
memAcct.cloudPrivate = true;
|
|
1371
|
+
} else {
|
|
1372
|
+
delete memAcct.cloudPrivate;
|
|
1373
|
+
}
|
|
1369
1374
|
}
|
|
1370
1375
|
}
|
|
1371
1376
|
|
package/src/tui.js
CHANGED
|
@@ -18,6 +18,9 @@ const yellow = s => fg(33, s);
|
|
|
18
18
|
const red = s => fg(31, s);
|
|
19
19
|
const cyan = s => fg(36, s);
|
|
20
20
|
const gray = s => fg(90, s);
|
|
21
|
+
// A pill-style badge: light-cyan text on a dark-teal background with padding, so it
|
|
22
|
+
// reads as a badge (like the web dashboard's) rather than plain colored text.
|
|
23
|
+
const badge = label => `${ESC}48;5;23m${ESC}38;5;159m ${label} ${RESET}`;
|
|
21
24
|
|
|
22
25
|
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
23
26
|
const strip = s => s.replace(ANSI_RE, '');
|
|
@@ -861,10 +864,11 @@ export class TUI {
|
|
|
861
864
|
// badges stay column-aligned across mixed account types.
|
|
862
865
|
line += l3 ? ` ${l3} ${bar(r3, bw, t3)}` : ' '.repeat(6 + bw);
|
|
863
866
|
}
|
|
864
|
-
// Provenance badge: an account
|
|
865
|
-
//
|
|
866
|
-
// the rank badge) so it never disrupts the
|
|
867
|
-
|
|
867
|
+
// Provenance badge: an account in a personal (private) cloud group gets a pill
|
|
868
|
+
// badge "🔑 private" (matching the web dashboard) so it's distinguishable from a
|
|
869
|
+
// shared/fleet account. Appended (like the rank badge) so it never disrupts the
|
|
870
|
+
// fixed-width columns / quota bars.
|
|
871
|
+
if (a.isPrivate) line += ` ${badge('🔑 private')}`;
|
|
868
872
|
// Order badge: ranked accounts show their 1-based position (#1 = most
|
|
869
873
|
// preferred). While ordering, unranked accounts are labelled "auto" so the
|
|
870
874
|
// two groups (pinned order vs use-or-lose) are visible. Appended last so it
|