codex-team 0.0.2 → 0.0.3

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 CHANGED
@@ -20,6 +20,7 @@ codexm list [name]
20
20
  codexm save <name>
21
21
  codexm update
22
22
  codexm switch <name>
23
+ codexm switch --auto --dry-run
23
24
  codexm remove <name> --yes
24
25
  codexm rename <old> <new>
25
26
  codexm quota refresh [name]
@@ -33,7 +34,7 @@ Use `--json` on query and mutation commands when you need machine-readable outpu
33
34
  1. Log into a target account with the native Codex CLI.
34
35
  2. Save the current auth snapshot with `codexm save <name>`.
35
36
  3. Repeat for other accounts.
36
- 4. Switch between saved accounts with `codexm switch <name>`.
37
+ 4. Switch between saved accounts with `codexm switch <name>` or let the tool choose with `codexm switch --auto`.
37
38
  5. Refresh and inspect quota usage with `codexm list` or `codexm quota refresh`.
38
39
 
39
40
  ## Development
package/dist/cli.cjs CHANGED
@@ -910,6 +910,7 @@ Usage:
910
910
  codexm update [--json]
911
911
  codexm quota refresh [name] [--json]
912
912
  codexm switch <name> [--json]
913
+ codexm switch --auto [--dry-run] [--json]
913
914
  codexm remove <name> [--yes] [--json]
914
915
  codexm rename <old> <new> [--json]
915
916
  codexm doctor [--json]
@@ -973,6 +974,69 @@ Account names must match /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.
973
974
  failures: result.failures
974
975
  };
975
976
  }
977
+ function computeRemainingPercent(usedPercent) {
978
+ if ("number" != typeof usedPercent) return null;
979
+ return Math.max(0, 100 - usedPercent);
980
+ }
981
+ function toAutoSwitchCandidate(account) {
982
+ if ("ok" !== account.status) return null;
983
+ const remain5h = computeRemainingPercent(account.five_hour?.used_percent);
984
+ const remain1w = computeRemainingPercent(account.one_week?.used_percent);
985
+ if (null === remain5h || null === remain1w) return null;
986
+ return {
987
+ name: account.name,
988
+ account_id: account.account_id,
989
+ plan_type: account.plan_type,
990
+ available: computeAvailability(account),
991
+ refresh_status: "ok",
992
+ effective_score: Math.min(remain5h, 3 * remain1w),
993
+ remain_5h: remain5h,
994
+ remain_1w_eq_5h: 3 * remain1w,
995
+ five_hour_used: account.five_hour?.used_percent ?? 0,
996
+ one_week_used: account.one_week?.used_percent ?? 0,
997
+ five_hour_reset_at: account.five_hour?.reset_at ?? null,
998
+ one_week_reset_at: account.one_week?.reset_at ?? null
999
+ };
1000
+ }
1001
+ function compareNullableDateAscending(left, right) {
1002
+ if (left === right) return 0;
1003
+ if (null === left) return 1;
1004
+ if (null === right) return -1;
1005
+ return left.localeCompare(right);
1006
+ }
1007
+ function rankAutoSwitchCandidates(accounts) {
1008
+ return accounts.map(toAutoSwitchCandidate).filter((candidate)=>null !== candidate).sort((left, right)=>{
1009
+ if (right.effective_score !== left.effective_score) return right.effective_score - left.effective_score;
1010
+ if (right.remain_5h !== left.remain_5h) return right.remain_5h - left.remain_5h;
1011
+ if (right.remain_1w_eq_5h !== left.remain_1w_eq_5h) return right.remain_1w_eq_5h - left.remain_1w_eq_5h;
1012
+ const fiveHourResetOrder = compareNullableDateAscending(left.five_hour_reset_at, right.five_hour_reset_at);
1013
+ if (0 !== fiveHourResetOrder) return fiveHourResetOrder;
1014
+ const oneWeekResetOrder = compareNullableDateAscending(left.one_week_reset_at, right.one_week_reset_at);
1015
+ if (0 !== oneWeekResetOrder) return oneWeekResetOrder;
1016
+ return left.name.localeCompare(right.name);
1017
+ });
1018
+ }
1019
+ function describeAutoSwitchSelection(candidate, dryRun, backupPath, warnings) {
1020
+ const lines = [
1021
+ dryRun ? `Best account: "${candidate.name}" (${maskAccountId(candidate.account_id)}).` : `Auto-switched to "${candidate.name}" (${maskAccountId(candidate.account_id)}).`,
1022
+ `Score: ${candidate.effective_score}`,
1023
+ `5H remaining: ${candidate.remain_5h}%`,
1024
+ `1W remaining (5H-equivalent): ${candidate.remain_1w_eq_5h}%`
1025
+ ];
1026
+ if (backupPath) lines.push(`Backup: ${backupPath}`);
1027
+ for (const warning of warnings)lines.push(`Warning: ${warning}`);
1028
+ return lines.join("\n");
1029
+ }
1030
+ function describeAutoSwitchNoop(candidate, warnings) {
1031
+ const lines = [
1032
+ `Current account "${candidate.name}" (${maskAccountId(candidate.account_id)}) is already the best available account.`,
1033
+ `Score: ${candidate.effective_score}`,
1034
+ `5H remaining: ${candidate.remain_5h}%`,
1035
+ `1W remaining (5H-equivalent): ${candidate.remain_1w_eq_5h}%`
1036
+ ];
1037
+ for (const warning of warnings)lines.push(`Warning: ${warning}`);
1038
+ return lines.join("\n");
1039
+ }
976
1040
  function describeQuotaAccounts(accounts, warnings) {
977
1041
  if (0 === accounts.length) return 0 === warnings.length ? "No saved accounts." : warnings.map((warning)=>`Warning: ${warning}`).join("\n");
978
1042
  const table = formatTable(accounts.map((account)=>({
@@ -1145,7 +1209,74 @@ Account names must match /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.
1145
1209
  }
1146
1210
  case "switch":
1147
1211
  {
1212
+ const auto = parsed.flags.has("--auto");
1213
+ const dryRun = parsed.flags.has("--dry-run");
1148
1214
  const name = parsed.positionals[0];
1215
+ if (dryRun && !auto) throw new Error("Usage: codexm switch --auto [--dry-run] [--json]");
1216
+ if (auto) {
1217
+ if (name) throw new Error("Usage: codexm switch --auto [--dry-run] [--json]");
1218
+ const refreshResult = await store.refreshAllQuotas();
1219
+ const candidates = rankAutoSwitchCandidates(refreshResult.successes);
1220
+ if (0 === candidates.length) throw new Error("No auto-switch candidate has both 5H and 1W quota data available.");
1221
+ const selected = candidates[0];
1222
+ const selectedQuota = refreshResult.successes.find((account)=>account.name === selected.name) ?? null;
1223
+ const warnings = refreshResult.failures.map((failure)=>`${failure.name}: ${failure.error}`);
1224
+ if (dryRun) {
1225
+ const payload = {
1226
+ ok: true,
1227
+ action: "switch",
1228
+ mode: "auto",
1229
+ dry_run: true,
1230
+ selected,
1231
+ candidates,
1232
+ warnings
1233
+ };
1234
+ if (json) writeJson(streams.stdout, payload);
1235
+ else streams.stdout.write(`${describeAutoSwitchSelection(selected, true, null, warnings)}\n`);
1236
+ return 0 === refreshResult.failures.length ? 0 : 1;
1237
+ }
1238
+ const currentStatus = await store.getCurrentStatus();
1239
+ if ("available" === selected.available && currentStatus.matched_accounts.includes(selected.name)) {
1240
+ const payload = {
1241
+ ok: true,
1242
+ action: "switch",
1243
+ mode: "auto",
1244
+ skipped: true,
1245
+ reason: "already_current_best",
1246
+ account: {
1247
+ name: selected.name,
1248
+ account_id: selected.account_id
1249
+ },
1250
+ selected,
1251
+ candidates,
1252
+ quota: selectedQuota ? toCliQuotaSummary(selectedQuota) : null,
1253
+ warnings
1254
+ };
1255
+ if (json) writeJson(streams.stdout, payload);
1256
+ else streams.stdout.write(`${describeAutoSwitchNoop(selected, warnings)}\n`);
1257
+ return 0 === refreshResult.failures.length ? 0 : 1;
1258
+ }
1259
+ const result = await store.switchAccount(selected.name);
1260
+ for (const warning of warnings)result.warnings.push(warning);
1261
+ const payload = {
1262
+ ok: true,
1263
+ action: "switch",
1264
+ mode: "auto",
1265
+ account: {
1266
+ name: result.account.name,
1267
+ account_id: result.account.account_id,
1268
+ auth_mode: result.account.auth_mode
1269
+ },
1270
+ selected,
1271
+ candidates,
1272
+ quota: selectedQuota ? toCliQuotaSummary(selectedQuota) : null,
1273
+ backup_path: result.backup_path,
1274
+ warnings: result.warnings
1275
+ };
1276
+ if (json) writeJson(streams.stdout, payload);
1277
+ else streams.stdout.write(`${describeAutoSwitchSelection(selected, false, result.backup_path, result.warnings)}\n`);
1278
+ return 0 === refreshResult.failures.length ? 0 : 1;
1279
+ }
1149
1280
  if (!name) throw new Error("Usage: codexm switch <name>");
1150
1281
  const result = await store.switchAccount(name);
1151
1282
  let quota = null;
package/dist/main.cjs CHANGED
@@ -940,6 +940,7 @@ Usage:
940
940
  codexm update [--json]
941
941
  codexm quota refresh [name] [--json]
942
942
  codexm switch <name> [--json]
943
+ codexm switch --auto [--dry-run] [--json]
943
944
  codexm remove <name> [--yes] [--json]
944
945
  codexm rename <old> <new> [--json]
945
946
  codexm doctor [--json]
@@ -1003,6 +1004,69 @@ function toCliQuotaRefreshResult(result) {
1003
1004
  failures: result.failures
1004
1005
  };
1005
1006
  }
1007
+ function computeRemainingPercent(usedPercent) {
1008
+ if ("number" != typeof usedPercent) return null;
1009
+ return Math.max(0, 100 - usedPercent);
1010
+ }
1011
+ function toAutoSwitchCandidate(account) {
1012
+ if ("ok" !== account.status) return null;
1013
+ const remain5h = computeRemainingPercent(account.five_hour?.used_percent);
1014
+ const remain1w = computeRemainingPercent(account.one_week?.used_percent);
1015
+ if (null === remain5h || null === remain1w) return null;
1016
+ return {
1017
+ name: account.name,
1018
+ account_id: account.account_id,
1019
+ plan_type: account.plan_type,
1020
+ available: computeAvailability(account),
1021
+ refresh_status: "ok",
1022
+ effective_score: Math.min(remain5h, 3 * remain1w),
1023
+ remain_5h: remain5h,
1024
+ remain_1w_eq_5h: 3 * remain1w,
1025
+ five_hour_used: account.five_hour?.used_percent ?? 0,
1026
+ one_week_used: account.one_week?.used_percent ?? 0,
1027
+ five_hour_reset_at: account.five_hour?.reset_at ?? null,
1028
+ one_week_reset_at: account.one_week?.reset_at ?? null
1029
+ };
1030
+ }
1031
+ function compareNullableDateAscending(left, right) {
1032
+ if (left === right) return 0;
1033
+ if (null === left) return 1;
1034
+ if (null === right) return -1;
1035
+ return left.localeCompare(right);
1036
+ }
1037
+ function rankAutoSwitchCandidates(accounts) {
1038
+ return accounts.map(toAutoSwitchCandidate).filter((candidate)=>null !== candidate).sort((left, right)=>{
1039
+ if (right.effective_score !== left.effective_score) return right.effective_score - left.effective_score;
1040
+ if (right.remain_5h !== left.remain_5h) return right.remain_5h - left.remain_5h;
1041
+ if (right.remain_1w_eq_5h !== left.remain_1w_eq_5h) return right.remain_1w_eq_5h - left.remain_1w_eq_5h;
1042
+ const fiveHourResetOrder = compareNullableDateAscending(left.five_hour_reset_at, right.five_hour_reset_at);
1043
+ if (0 !== fiveHourResetOrder) return fiveHourResetOrder;
1044
+ const oneWeekResetOrder = compareNullableDateAscending(left.one_week_reset_at, right.one_week_reset_at);
1045
+ if (0 !== oneWeekResetOrder) return oneWeekResetOrder;
1046
+ return left.name.localeCompare(right.name);
1047
+ });
1048
+ }
1049
+ function describeAutoSwitchSelection(candidate, dryRun, backupPath, warnings) {
1050
+ const lines = [
1051
+ dryRun ? `Best account: "${candidate.name}" (${maskAccountId(candidate.account_id)}).` : `Auto-switched to "${candidate.name}" (${maskAccountId(candidate.account_id)}).`,
1052
+ `Score: ${candidate.effective_score}`,
1053
+ `5H remaining: ${candidate.remain_5h}%`,
1054
+ `1W remaining (5H-equivalent): ${candidate.remain_1w_eq_5h}%`
1055
+ ];
1056
+ if (backupPath) lines.push(`Backup: ${backupPath}`);
1057
+ for (const warning of warnings)lines.push(`Warning: ${warning}`);
1058
+ return lines.join("\n");
1059
+ }
1060
+ function describeAutoSwitchNoop(candidate, warnings) {
1061
+ const lines = [
1062
+ `Current account "${candidate.name}" (${maskAccountId(candidate.account_id)}) is already the best available account.`,
1063
+ `Score: ${candidate.effective_score}`,
1064
+ `5H remaining: ${candidate.remain_5h}%`,
1065
+ `1W remaining (5H-equivalent): ${candidate.remain_1w_eq_5h}%`
1066
+ ];
1067
+ for (const warning of warnings)lines.push(`Warning: ${warning}`);
1068
+ return lines.join("\n");
1069
+ }
1006
1070
  function describeQuotaAccounts(accounts, warnings) {
1007
1071
  if (0 === accounts.length) return 0 === warnings.length ? "No saved accounts." : warnings.map((warning)=>`Warning: ${warning}`).join("\n");
1008
1072
  const table = formatTable(accounts.map((account)=>({
@@ -1175,7 +1239,74 @@ async function runCli(argv, options = {}) {
1175
1239
  }
1176
1240
  case "switch":
1177
1241
  {
1242
+ const auto = parsed.flags.has("--auto");
1243
+ const dryRun = parsed.flags.has("--dry-run");
1178
1244
  const name = parsed.positionals[0];
1245
+ if (dryRun && !auto) throw new Error("Usage: codexm switch --auto [--dry-run] [--json]");
1246
+ if (auto) {
1247
+ if (name) throw new Error("Usage: codexm switch --auto [--dry-run] [--json]");
1248
+ const refreshResult = await store.refreshAllQuotas();
1249
+ const candidates = rankAutoSwitchCandidates(refreshResult.successes);
1250
+ if (0 === candidates.length) throw new Error("No auto-switch candidate has both 5H and 1W quota data available.");
1251
+ const selected = candidates[0];
1252
+ const selectedQuota = refreshResult.successes.find((account)=>account.name === selected.name) ?? null;
1253
+ const warnings = refreshResult.failures.map((failure)=>`${failure.name}: ${failure.error}`);
1254
+ if (dryRun) {
1255
+ const payload = {
1256
+ ok: true,
1257
+ action: "switch",
1258
+ mode: "auto",
1259
+ dry_run: true,
1260
+ selected,
1261
+ candidates,
1262
+ warnings
1263
+ };
1264
+ if (json) writeJson(streams.stdout, payload);
1265
+ else streams.stdout.write(`${describeAutoSwitchSelection(selected, true, null, warnings)}\n`);
1266
+ return 0 === refreshResult.failures.length ? 0 : 1;
1267
+ }
1268
+ const currentStatus = await store.getCurrentStatus();
1269
+ if ("available" === selected.available && currentStatus.matched_accounts.includes(selected.name)) {
1270
+ const payload = {
1271
+ ok: true,
1272
+ action: "switch",
1273
+ mode: "auto",
1274
+ skipped: true,
1275
+ reason: "already_current_best",
1276
+ account: {
1277
+ name: selected.name,
1278
+ account_id: selected.account_id
1279
+ },
1280
+ selected,
1281
+ candidates,
1282
+ quota: selectedQuota ? toCliQuotaSummary(selectedQuota) : null,
1283
+ warnings
1284
+ };
1285
+ if (json) writeJson(streams.stdout, payload);
1286
+ else streams.stdout.write(`${describeAutoSwitchNoop(selected, warnings)}\n`);
1287
+ return 0 === refreshResult.failures.length ? 0 : 1;
1288
+ }
1289
+ const result = await store.switchAccount(selected.name);
1290
+ for (const warning of warnings)result.warnings.push(warning);
1291
+ const payload = {
1292
+ ok: true,
1293
+ action: "switch",
1294
+ mode: "auto",
1295
+ account: {
1296
+ name: result.account.name,
1297
+ account_id: result.account.account_id,
1298
+ auth_mode: result.account.auth_mode
1299
+ },
1300
+ selected,
1301
+ candidates,
1302
+ quota: selectedQuota ? toCliQuotaSummary(selectedQuota) : null,
1303
+ backup_path: result.backup_path,
1304
+ warnings: result.warnings
1305
+ };
1306
+ if (json) writeJson(streams.stdout, payload);
1307
+ else streams.stdout.write(`${describeAutoSwitchSelection(selected, false, result.backup_path, result.warnings)}\n`);
1308
+ return 0 === refreshResult.failures.length ? 0 : 1;
1309
+ }
1179
1310
  if (!name) throw new Error("Usage: codexm switch <name>");
1180
1311
  const result = await store.switchAccount(name);
1181
1312
  let quota = null;
package/dist/main.js CHANGED
@@ -900,6 +900,7 @@ Usage:
900
900
  codexm update [--json]
901
901
  codexm quota refresh [name] [--json]
902
902
  codexm switch <name> [--json]
903
+ codexm switch --auto [--dry-run] [--json]
903
904
  codexm remove <name> [--yes] [--json]
904
905
  codexm rename <old> <new> [--json]
905
906
  codexm doctor [--json]
@@ -963,6 +964,69 @@ function toCliQuotaRefreshResult(result) {
963
964
  failures: result.failures
964
965
  };
965
966
  }
967
+ function computeRemainingPercent(usedPercent) {
968
+ if ("number" != typeof usedPercent) return null;
969
+ return Math.max(0, 100 - usedPercent);
970
+ }
971
+ function toAutoSwitchCandidate(account) {
972
+ if ("ok" !== account.status) return null;
973
+ const remain5h = computeRemainingPercent(account.five_hour?.used_percent);
974
+ const remain1w = computeRemainingPercent(account.one_week?.used_percent);
975
+ if (null === remain5h || null === remain1w) return null;
976
+ return {
977
+ name: account.name,
978
+ account_id: account.account_id,
979
+ plan_type: account.plan_type,
980
+ available: computeAvailability(account),
981
+ refresh_status: "ok",
982
+ effective_score: Math.min(remain5h, 3 * remain1w),
983
+ remain_5h: remain5h,
984
+ remain_1w_eq_5h: 3 * remain1w,
985
+ five_hour_used: account.five_hour?.used_percent ?? 0,
986
+ one_week_used: account.one_week?.used_percent ?? 0,
987
+ five_hour_reset_at: account.five_hour?.reset_at ?? null,
988
+ one_week_reset_at: account.one_week?.reset_at ?? null
989
+ };
990
+ }
991
+ function compareNullableDateAscending(left, right) {
992
+ if (left === right) return 0;
993
+ if (null === left) return 1;
994
+ if (null === right) return -1;
995
+ return left.localeCompare(right);
996
+ }
997
+ function rankAutoSwitchCandidates(accounts) {
998
+ return accounts.map(toAutoSwitchCandidate).filter((candidate)=>null !== candidate).sort((left, right)=>{
999
+ if (right.effective_score !== left.effective_score) return right.effective_score - left.effective_score;
1000
+ if (right.remain_5h !== left.remain_5h) return right.remain_5h - left.remain_5h;
1001
+ if (right.remain_1w_eq_5h !== left.remain_1w_eq_5h) return right.remain_1w_eq_5h - left.remain_1w_eq_5h;
1002
+ const fiveHourResetOrder = compareNullableDateAscending(left.five_hour_reset_at, right.five_hour_reset_at);
1003
+ if (0 !== fiveHourResetOrder) return fiveHourResetOrder;
1004
+ const oneWeekResetOrder = compareNullableDateAscending(left.one_week_reset_at, right.one_week_reset_at);
1005
+ if (0 !== oneWeekResetOrder) return oneWeekResetOrder;
1006
+ return left.name.localeCompare(right.name);
1007
+ });
1008
+ }
1009
+ function describeAutoSwitchSelection(candidate, dryRun, backupPath, warnings) {
1010
+ const lines = [
1011
+ dryRun ? `Best account: "${candidate.name}" (${maskAccountId(candidate.account_id)}).` : `Auto-switched to "${candidate.name}" (${maskAccountId(candidate.account_id)}).`,
1012
+ `Score: ${candidate.effective_score}`,
1013
+ `5H remaining: ${candidate.remain_5h}%`,
1014
+ `1W remaining (5H-equivalent): ${candidate.remain_1w_eq_5h}%`
1015
+ ];
1016
+ if (backupPath) lines.push(`Backup: ${backupPath}`);
1017
+ for (const warning of warnings)lines.push(`Warning: ${warning}`);
1018
+ return lines.join("\n");
1019
+ }
1020
+ function describeAutoSwitchNoop(candidate, warnings) {
1021
+ const lines = [
1022
+ `Current account "${candidate.name}" (${maskAccountId(candidate.account_id)}) is already the best available account.`,
1023
+ `Score: ${candidate.effective_score}`,
1024
+ `5H remaining: ${candidate.remain_5h}%`,
1025
+ `1W remaining (5H-equivalent): ${candidate.remain_1w_eq_5h}%`
1026
+ ];
1027
+ for (const warning of warnings)lines.push(`Warning: ${warning}`);
1028
+ return lines.join("\n");
1029
+ }
966
1030
  function describeQuotaAccounts(accounts, warnings) {
967
1031
  if (0 === accounts.length) return 0 === warnings.length ? "No saved accounts." : warnings.map((warning)=>`Warning: ${warning}`).join("\n");
968
1032
  const table = formatTable(accounts.map((account)=>({
@@ -1135,7 +1199,74 @@ async function runCli(argv, options = {}) {
1135
1199
  }
1136
1200
  case "switch":
1137
1201
  {
1202
+ const auto = parsed.flags.has("--auto");
1203
+ const dryRun = parsed.flags.has("--dry-run");
1138
1204
  const name = parsed.positionals[0];
1205
+ if (dryRun && !auto) throw new Error("Usage: codexm switch --auto [--dry-run] [--json]");
1206
+ if (auto) {
1207
+ if (name) throw new Error("Usage: codexm switch --auto [--dry-run] [--json]");
1208
+ const refreshResult = await store.refreshAllQuotas();
1209
+ const candidates = rankAutoSwitchCandidates(refreshResult.successes);
1210
+ if (0 === candidates.length) throw new Error("No auto-switch candidate has both 5H and 1W quota data available.");
1211
+ const selected = candidates[0];
1212
+ const selectedQuota = refreshResult.successes.find((account)=>account.name === selected.name) ?? null;
1213
+ const warnings = refreshResult.failures.map((failure)=>`${failure.name}: ${failure.error}`);
1214
+ if (dryRun) {
1215
+ const payload = {
1216
+ ok: true,
1217
+ action: "switch",
1218
+ mode: "auto",
1219
+ dry_run: true,
1220
+ selected,
1221
+ candidates,
1222
+ warnings
1223
+ };
1224
+ if (json) writeJson(streams.stdout, payload);
1225
+ else streams.stdout.write(`${describeAutoSwitchSelection(selected, true, null, warnings)}\n`);
1226
+ return 0 === refreshResult.failures.length ? 0 : 1;
1227
+ }
1228
+ const currentStatus = await store.getCurrentStatus();
1229
+ if ("available" === selected.available && currentStatus.matched_accounts.includes(selected.name)) {
1230
+ const payload = {
1231
+ ok: true,
1232
+ action: "switch",
1233
+ mode: "auto",
1234
+ skipped: true,
1235
+ reason: "already_current_best",
1236
+ account: {
1237
+ name: selected.name,
1238
+ account_id: selected.account_id
1239
+ },
1240
+ selected,
1241
+ candidates,
1242
+ quota: selectedQuota ? toCliQuotaSummary(selectedQuota) : null,
1243
+ warnings
1244
+ };
1245
+ if (json) writeJson(streams.stdout, payload);
1246
+ else streams.stdout.write(`${describeAutoSwitchNoop(selected, warnings)}\n`);
1247
+ return 0 === refreshResult.failures.length ? 0 : 1;
1248
+ }
1249
+ const result = await store.switchAccount(selected.name);
1250
+ for (const warning of warnings)result.warnings.push(warning);
1251
+ const payload = {
1252
+ ok: true,
1253
+ action: "switch",
1254
+ mode: "auto",
1255
+ account: {
1256
+ name: result.account.name,
1257
+ account_id: result.account.account_id,
1258
+ auth_mode: result.account.auth_mode
1259
+ },
1260
+ selected,
1261
+ candidates,
1262
+ quota: selectedQuota ? toCliQuotaSummary(selectedQuota) : null,
1263
+ backup_path: result.backup_path,
1264
+ warnings: result.warnings
1265
+ };
1266
+ if (json) writeJson(streams.stdout, payload);
1267
+ else streams.stdout.write(`${describeAutoSwitchSelection(selected, false, result.backup_path, result.warnings)}\n`);
1268
+ return 0 === refreshResult.failures.length ? 0 : 1;
1269
+ }
1139
1270
  if (!name) throw new Error("Usage: codexm switch <name>");
1140
1271
  const result = await store.switchAccount(name);
1141
1272
  let quota = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-team",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Manage multiple Codex ChatGPT auth snapshots and quota usage from the command line.",
5
5
  "license": "MIT",
6
6
  "type": "module",