subconscious-cli 6.0.0 → 6.1.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.
Files changed (76) hide show
  1. package/README.md +135 -2
  2. package/bin/agent-data.js +242 -0
  3. package/bin/agent-help.js +106 -0
  4. package/bin/agent-install.js +354 -0
  5. package/bin/agent-launch.js +199 -0
  6. package/bin/agent-spawn.js +137 -0
  7. package/bin/agents.js +284 -840
  8. package/bin/auth.js +89 -33
  9. package/bin/branding.js +3 -1
  10. package/bin/claude-picker.js +143 -0
  11. package/bin/cli.js +87 -20
  12. package/bin/clipboard-image.js +24 -5
  13. package/bin/colors.js +1 -1
  14. package/bin/feedback.js +71 -21
  15. package/bin/harness-manifest.js +286 -0
  16. package/bin/headless-args.js +35 -0
  17. package/bin/launch-values.js +25 -0
  18. package/bin/model-capabilities.js +12 -8
  19. package/bin/models.js +35 -19
  20. package/bin/native/subc-tui-darwin-amd64 +0 -0
  21. package/bin/native/subc-tui-darwin-arm64 +0 -0
  22. package/bin/native/subc-tui-linux-amd64 +0 -0
  23. package/bin/native/subc-tui-linux-arm64 +0 -0
  24. package/bin/native/subc-tui-windows-amd64.exe +0 -0
  25. package/bin/native/subc-tui-windows-arm64.exe +0 -0
  26. package/bin/opencode-provider.js +48 -5
  27. package/bin/profile-settings.js +129 -0
  28. package/bin/profiles.js +136 -449
  29. package/bin/runbook/README.md +66 -23
  30. package/bin/runbook/claude-code/agent.json +300 -0
  31. package/bin/runbook/claude-code/install.sh +9 -252
  32. package/bin/runbook/codex/agent.json +461 -0
  33. package/bin/runbook/codex/hooks-lib.sh +17 -4
  34. package/bin/runbook/codex/install.sh +0 -4
  35. package/bin/runbook/codex/run.sh +16 -235
  36. package/bin/runbook/copilot/agent.json +185 -0
  37. package/bin/runbook/copilot/install.sh +45 -63
  38. package/bin/runbook/cursor/agent.json +137 -0
  39. package/bin/runbook/cursor/install.sh +8 -35
  40. package/bin/runbook/deepseek-harness/agent.json +163 -0
  41. package/bin/runbook/deepseek-harness/run.sh +20 -59
  42. package/bin/runbook/image-window/index.ts +14 -0
  43. package/bin/runbook/image-window/window.d.ts +19 -0
  44. package/bin/runbook/image-window/window.js +140 -0
  45. package/bin/runbook/lib.sh +41 -0
  46. package/bin/runbook/opencode/agent.json +158 -0
  47. package/bin/runbook/opencode/install.sh +9 -183
  48. package/bin/runbook/opencode/opencode-plugin.d.ts +16 -0
  49. package/bin/runbook/opencode/subconscious-image-window.ts +24 -0
  50. package/bin/runbook/pi/agent.json +216 -0
  51. package/bin/runbook/pi/install.sh +18 -44
  52. package/bin/runbook/pi/run.sh +6 -18
  53. package/bin/runbook/pi/subconscious-compaction.ts +71 -49
  54. package/bin/runbook/shared.json +58 -0
  55. package/bin/runbook/subconscious-code/agent.json +156 -0
  56. package/bin/sessions.js +173 -58
  57. package/bin/tui.js +104 -32
  58. package/bin/update-check.js +54 -21
  59. package/bin/upgrade.js +67 -43
  60. package/bin/usage.js +47 -24
  61. package/bin/windows/agents.js +141 -37
  62. package/bin/windows/common.js +36 -25
  63. package/bin/windows/install.js +116 -34
  64. package/bin/windows/launch.js +260 -77
  65. package/bin/windows/pi-compaction.ts +68 -13
  66. package/bin/windows/process.js +210 -57
  67. package/bin/windows/setup.js +251 -56
  68. package/package.json +9 -4
  69. package/bin/registry.generated.json +0 -406
  70. package/bin/runbook/claude-code/run.sh +0 -254
  71. package/bin/runbook/model-capabilities.generated.sh +0 -9
  72. package/bin/runbook/opencode/provider.sh +0 -93
  73. package/bin/runbook/opencode/run.sh +0 -99
  74. package/bin/runbook/opencode/subconscious-compaction.ts +0 -100
  75. package/bin/runbook/subconscious-code/run.sh +0 -21
  76. package/bin/windows/claude.js +0 -71
@@ -1,10 +1,10 @@
1
- import fs from 'node:fs/promises';
2
1
  import { spawn } from 'node:child_process';
3
- import { spawnWindows } from './windows/process.js';
2
+ import fs from 'node:fs/promises';
4
3
  import readline from 'node:readline';
5
4
  import { fileURLToPath } from 'node:url';
6
5
  import { LOGO_ART_SMALL_LINES } from './branding.js';
7
6
  import { c, colorEnabled } from './colors.js';
7
+ import { spawnWindows } from './windows/process.js';
8
8
 
9
9
  export const PACKAGE_NAME = 'subconscious-cli';
10
10
  export const UPDATE_CHECK_TIMEOUT_MS = 1500;
@@ -46,7 +46,9 @@ export function detectInstallTarget(
46
46
  }
47
47
 
48
48
  const marker = `/lib/node_modules/${PACKAGE_NAME}/`;
49
- let prefix = normalized.includes(marker) ? normalized.slice(0, normalized.indexOf(marker)) : '';
49
+ let prefix = normalized.includes(marker)
50
+ ? normalized.slice(0, normalized.indexOf(marker))
51
+ : '';
50
52
  if (!prefix && platform === 'win32') {
51
53
  const windowsMarker = `/node_modules/${PACKAGE_NAME}/`;
52
54
  if (normalized.includes(windowsMarker)) {
@@ -59,7 +61,14 @@ export function detectInstallTarget(
59
61
  return {
60
62
  command: 'npm',
61
63
  args,
62
- display: ['npm', ...args].map(platform === 'win32' ? value => /^[-/@A-Za-z0-9._:]+$/.test(value) ? value : `"${value}"` : shellQuote).join(' '),
64
+ display: ['npm', ...args]
65
+ .map(
66
+ platform === 'win32'
67
+ ? (value) =>
68
+ /^[-/@A-Za-z0-9._:]+$/.test(value) ? value : `"${value}"`
69
+ : shellQuote,
70
+ )
71
+ .join(' '),
63
72
  prefix,
64
73
  };
65
74
  }
@@ -67,7 +76,9 @@ export function detectInstallTarget(
67
76
  function parseVersion(version) {
68
77
  const match = String(version)
69
78
  .trim()
70
- .match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/);
79
+ .match(
80
+ /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/,
81
+ );
71
82
  if (!match) return null;
72
83
  return {
73
84
  core: match.slice(1, 4).map(Number),
@@ -75,6 +86,10 @@ function parseVersion(version) {
75
86
  };
76
87
  }
77
88
 
89
+ export function isVersion(version) {
90
+ return parseVersion(version) !== null;
91
+ }
92
+
78
93
  function comparePrerelease(a, b) {
79
94
  if (!a.length && !b.length) return 0;
80
95
  if (!a.length) return 1;
@@ -87,10 +102,11 @@ function comparePrerelease(a, b) {
87
102
 
88
103
  const aNumber = /^\d+$/.test(a[index]) ? Number(a[index]) : null;
89
104
  const bNumber = /^\d+$/.test(b[index]) ? Number(b[index]) : null;
90
- if (aNumber !== null && bNumber !== null) return Math.sign(aNumber - bNumber);
105
+ if (aNumber !== null && bNumber !== null)
106
+ return Math.sign(aNumber - bNumber);
91
107
  if (aNumber !== null) return -1;
92
108
  if (bNumber !== null) return 1;
93
- return a[index].localeCompare(b[index]);
109
+ return a[index] < b[index] ? -1 : 1;
94
110
  }
95
111
  return 0;
96
112
  }
@@ -109,7 +125,9 @@ export function compareVersions(a, b) {
109
125
  }
110
126
 
111
127
  export async function currentVersion() {
112
- const pkg = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url), 'utf-8'));
128
+ const pkg = JSON.parse(
129
+ await fs.readFile(new URL('../package.json', import.meta.url), 'utf-8'),
130
+ );
113
131
  return pkg.version;
114
132
  }
115
133
 
@@ -134,7 +152,11 @@ export async function fetchLatestVersion(options = {}) {
134
152
  try {
135
153
  const aborted = new Promise((_, reject) => {
136
154
  const fail = () => {
137
- const error = new Error(signal?.aborted ? 'Update check was cancelled' : 'Update check timed out');
155
+ const error = new Error(
156
+ signal?.aborted
157
+ ? 'Update check was cancelled'
158
+ : 'Update check timed out',
159
+ );
138
160
  error.name = 'AbortError';
139
161
  reject(error);
140
162
  };
@@ -154,7 +176,8 @@ export async function fetchLatestVersion(options = {}) {
154
176
  ]);
155
177
  if (!response.ok) throw new Error(`npm returned HTTP ${response.status}`);
156
178
  const payload = await response.json();
157
- if (!parseVersion(payload?.version)) throw new Error('npm returned an invalid version');
179
+ if (!parseVersion(payload?.version))
180
+ throw new Error('npm returned an invalid version');
158
181
  return payload.version;
159
182
  } finally {
160
183
  signal?.removeEventListener('abort', onAbort);
@@ -175,7 +198,10 @@ export function renderUpdateNotice(installedVersion, latestVersion) {
175
198
  { raw: '', value: '' },
176
199
  { raw: '', value: '' },
177
200
  { raw: '', value: '' },
178
- { raw: 'Subconscious CLI', value: `${c.orange}${c.bold}Subconscious CLI${c.reset}` },
201
+ {
202
+ raw: 'Subconscious CLI',
203
+ value: `${c.orange}${c.bold}Subconscious CLI${c.reset}`,
204
+ },
179
205
  { raw: 'Update available', value: `${c.bold}Update available${c.reset}` },
180
206
  { raw: '', value: '' },
181
207
  {
@@ -198,7 +224,8 @@ export function renderUpdateNotice(installedVersion, latestVersion) {
198
224
  }
199
225
 
200
226
  export function renderUpdateOptions(selectedIndex = 0, versions = {}) {
201
- const installCommand = versions.installCommand || detectInstallTarget().display;
227
+ const installCommand =
228
+ versions.installCommand || detectInstallTarget().display;
202
229
  const descriptions = [
203
230
  `Runs \`${installCommand}\``,
204
231
  versions.installedVersion
@@ -209,9 +236,7 @@ export function renderUpdateOptions(selectedIndex = 0, versions = {}) {
209
236
  return UPDATE_ACTIONS.map((label, index) => {
210
237
  const active = index === selectedIndex;
211
238
  const pointer = active ? `${c.orange}›${c.reset}` : ' ';
212
- const activeStyle = colorEnabled
213
- ? `${c.bgOrange}${c.black}`
214
- : c.inverse;
239
+ const activeStyle = colorEnabled ? `${c.bgOrange}${c.black}` : c.inverse;
215
240
  const option = active
216
241
  ? `${activeStyle}${c.bold} ${label} ${c.reset}`
217
242
  : ` ${label} `;
@@ -278,7 +303,8 @@ export async function selectUpdateAction(options = {}) {
278
303
  }
279
304
 
280
305
  export async function installLatest(options = {}) {
281
- const spawnImpl = options.spawnImpl || (process.platform === 'win32' ? spawnWindows : spawn);
306
+ const spawnImpl =
307
+ options.spawnImpl || (process.platform === 'win32' ? spawnWindows : spawn);
282
308
  const target = options.target || detectInstallTarget();
283
309
  return new Promise((resolve) => {
284
310
  const child = spawnImpl(target.command, target.args, {
@@ -325,8 +351,10 @@ export async function showUpdateNotice(options = {}) {
325
351
  write(`\n${notice}\n\n`);
326
352
 
327
353
  const interactive =
328
- options.interactive ?? (process.stdin.isTTY === true && process.stderr.isTTY === true);
329
- if (!interactive) return { installedVersion, latestVersion, action: 'skip' };
354
+ options.interactive ??
355
+ (process.stdin.isTTY === true && process.stderr.isTTY === true);
356
+ if (!interactive)
357
+ return { installedVersion, latestVersion, action: 'skip' };
330
358
 
331
359
  const select = options.select || selectUpdateAction;
332
360
  const installTarget = options.installTarget || detectInstallTarget();
@@ -341,10 +369,13 @@ export async function showUpdateNotice(options = {}) {
341
369
  return { installedVersion, latestVersion, action };
342
370
  }
343
371
 
344
- write(`\n ${c.cyan}Updating ${PACKAGE_NAME} to ${latestVersion}...${c.reset}\n\n`);
372
+ write(
373
+ `\n ${c.cyan}Updating ${PACKAGE_NAME} to ${latestVersion}...${c.reset}\n\n`,
374
+ );
345
375
  const install =
346
376
  options.install ||
347
- ((expectedVersion) => installLatest({ expectedVersion, target: installTarget }));
377
+ ((expectedVersion) =>
378
+ installLatest({ expectedVersion, target: installTarget }));
348
379
  const installed = await install(latestVersion);
349
380
  if (installed) {
350
381
  write(
@@ -353,7 +384,9 @@ export async function showUpdateNotice(options = {}) {
353
384
  return { installedVersion, latestVersion, action: 'updated' };
354
385
  }
355
386
 
356
- write(`\n ${c.red}Update failed or the running installation stayed unchanged.${c.reset}\n`);
387
+ write(
388
+ `\n ${c.red}Update failed or the running installation stayed unchanged.${c.reset}\n`,
389
+ );
357
390
  write(` Try the exact detected install target manually:\n\n`);
358
391
  write(` ${c.cyan}${installTarget.display}${c.reset}\n\n`);
359
392
  return { installedVersion, latestVersion, action: 'failed' };
package/bin/upgrade.js CHANGED
@@ -6,12 +6,16 @@
6
6
  */
7
7
 
8
8
  import { spawn } from 'node:child_process';
9
- import { runWindows } from './windows/process.js';
10
9
  import fs from 'node:fs/promises';
11
10
  import readline from 'node:readline';
12
11
  import { fileURLToPath } from 'node:url';
13
12
  import { c } from './colors.js';
14
- import { detectInstallTarget } from './update-check.js';
13
+ import {
14
+ compareVersions,
15
+ detectInstallTarget,
16
+ isVersion,
17
+ } from './update-check.js';
18
+ import { runWindows } from './windows/process.js';
15
19
 
16
20
  export const PACKAGE_NAME = 'subconscious-cli';
17
21
  export const MIN_LOGIN_VERSION = '4.0';
@@ -20,7 +24,9 @@ export function parseUpgradeArgs(argv = []) {
20
24
  const latest = argv.includes('--latest');
21
25
  const unknown = argv.filter((arg) => arg !== '--latest');
22
26
  if (unknown.length) {
23
- throw new Error(`Unknown argument: ${unknown[0]}\nUsage: subc upgrade [--latest]`);
27
+ throw new Error(
28
+ `Unknown argument: ${unknown[0]}\nUsage: subc upgrade [--latest]`,
29
+ );
24
30
  }
25
31
  return { latest };
26
32
  }
@@ -30,32 +36,27 @@ export function detectInstallCommand(here = fileURLToPath(import.meta.url)) {
30
36
  }
31
37
 
32
38
  export async function currentCliVersion() {
33
- const pkg = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url), 'utf-8'));
39
+ const pkg = JSON.parse(
40
+ await fs.readFile(new URL('../package.json', import.meta.url), 'utf-8'),
41
+ );
34
42
  return pkg.version;
35
43
  }
36
44
 
37
- export function compareVersions(a, b) {
38
- const pa = String(a).split('.').map((part) => Number.parseInt(part, 10) || 0);
39
- const pb = String(b).split('.').map((part) => Number.parseInt(part, 10) || 0);
40
- const n = Math.max(pa.length, pb.length);
41
- for (let i = 0; i < n; i++) {
42
- const da = pa[i] || 0;
43
- const db = pb[i] || 0;
44
- if (da > db) return 1;
45
- if (da < db) return -1;
46
- }
47
- return 0;
48
- }
49
-
50
45
  export async function fetchLatestVersion(fetchImpl = fetch) {
51
- const res = await fetchImpl(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
52
- signal: AbortSignal.timeout(10000),
53
- });
46
+ const res = await fetchImpl(
47
+ `https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
48
+ {
49
+ signal: AbortSignal.timeout(10000),
50
+ },
51
+ );
54
52
  if (!res.ok) {
55
- throw new Error(`Could not look up ${PACKAGE_NAME} on npm (${res.status}).`);
53
+ throw new Error(
54
+ `Could not look up ${PACKAGE_NAME} on npm (${res.status}).`,
55
+ );
56
56
  }
57
57
  const data = await res.json();
58
- if (!data?.version) throw new Error(`npm did not return a version for ${PACKAGE_NAME}.`);
58
+ if (!data?.version)
59
+ throw new Error(`npm did not return a version for ${PACKAGE_NAME}.`);
59
60
  return data.version;
60
61
  }
61
62
 
@@ -72,7 +73,10 @@ export function printLoginUpgradeWarning() {
72
73
 
73
74
  function askYesNo(question) {
74
75
  return new Promise((resolve) => {
75
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
76
+ const rl = readline.createInterface({
77
+ input: process.stdin,
78
+ output: process.stdout,
79
+ });
76
80
  rl.question(question, (answer) => {
77
81
  rl.close();
78
82
  const a = answer.trim().toLowerCase();
@@ -84,7 +88,10 @@ function askYesNo(question) {
84
88
  function runInstall(command) {
85
89
  if (process.platform === 'win32') {
86
90
  const target = detectInstallTarget();
87
- return runWindows(target.command, target.args).then(code => code === 0, () => false);
91
+ return runWindows(target.command, target.args).then(
92
+ (code) => code === 0,
93
+ () => false,
94
+ );
88
95
  }
89
96
  return new Promise((resolve) => {
90
97
  const child = spawn(command, { shell: true, stdio: 'inherit' });
@@ -101,14 +108,20 @@ export async function installLatest(options = {}) {
101
108
 
102
109
  let latest;
103
110
  try {
104
- latest = await fetchLatest();
111
+ const version = await fetchLatest();
112
+ if (!isVersion(version)) {
113
+ throw new Error(`npm returned an invalid version (${version}).`);
114
+ }
115
+ latest = version;
105
116
  } catch (error) {
106
117
  console.error(` ${c.yellow}${error.message}${c.reset}`);
107
118
  console.error(` ${c.dim}Installing @latest anyway.${c.reset}\n`);
108
119
  }
109
120
 
110
- if (latest && compareVersions(current, latest) >= 0) {
111
- console.log(`\n ${c.green}Already up to date${c.reset} ${c.dim}(${current}).${c.reset}\n`);
121
+ if (latest && isVersion(current) && compareVersions(current, latest) >= 0) {
122
+ console.log(
123
+ `\n ${c.green}Already up to date${c.reset} ${c.dim}(${current}).${c.reset}\n`,
124
+ );
112
125
  return true;
113
126
  }
114
127
 
@@ -117,7 +130,9 @@ export async function installLatest(options = {}) {
117
130
  `\n Upgrading ${c.cyan}${PACKAGE_NAME}${c.reset} ${c.dim}${current}${c.reset} → ${c.cyan}${latest}${c.reset}`,
118
131
  );
119
132
  } else {
120
- console.log(`\n Upgrading ${c.cyan}${PACKAGE_NAME}${c.reset} ${c.dim}${current}${c.reset} → latest`);
133
+ console.log(
134
+ `\n Upgrading ${c.cyan}${PACKAGE_NAME}${c.reset} ${c.dim}${current}${c.reset} → latest`,
135
+ );
121
136
  }
122
137
  console.log(` ${c.dim}Running${c.reset} ${c.cyan}${command}${c.reset}\n`);
123
138
 
@@ -129,32 +144,39 @@ export async function installLatest(options = {}) {
129
144
  }
130
145
 
131
146
  if (latest) {
147
+ const readVersion = options.readVersion || currentCliVersion;
148
+ let installedVersion;
132
149
  try {
133
- const readVersion = options.readVersion || currentCliVersion;
134
- const installedVersion = await readVersion();
135
- if (compareVersions(installedVersion, latest) < 0) {
136
- console.error(
137
- `\n ${c.red}Upgrade command completed, but this installation is still ${installedVersion}.${c.reset}`,
138
- );
139
- console.error(` Run the exact detected command manually:\n`);
140
- console.error(` ${c.cyan}${command}${c.reset}\n`);
141
- return false;
142
- }
143
- } catch {
144
- console.error(`\n ${c.red}Could not verify the updated CLI installation.${c.reset}`);
150
+ installedVersion = await readVersion();
151
+ } catch {}
152
+ if (!isVersion(installedVersion)) {
153
+ console.error(
154
+ `\n ${c.red}Could not verify the updated CLI installation.${c.reset}`,
155
+ );
156
+ console.error(` Run the exact detected command manually:\n`);
157
+ console.error(` ${c.cyan}${command}${c.reset}\n`);
158
+ return false;
159
+ }
160
+ if (compareVersions(installedVersion, latest) < 0) {
161
+ console.error(
162
+ `\n ${c.red}Upgrade command completed, but this installation is still ${installedVersion}.${c.reset}`,
163
+ );
145
164
  console.error(` Run the exact detected command manually:\n`);
146
165
  console.error(` ${c.cyan}${command}${c.reset}\n`);
147
166
  return false;
148
167
  }
149
168
  }
150
169
 
151
- console.log(`\n ${c.green}${c.bold}✓ Upgraded.${c.reset} Re-run ${c.cyan}subc login${c.reset} if you were signing in.\n`);
170
+ console.log(
171
+ `\n ${c.green}${c.bold}✓ Upgraded.${c.reset} Re-run ${c.cyan}subc login${c.reset} if you were signing in.\n`,
172
+ );
152
173
  return true;
153
174
  }
154
175
 
155
176
  export async function upgradeCommand(argv = [], options = {}) {
156
177
  const { latest } = parseUpgradeArgs(argv);
157
- const interactive = options.interactive ?? (process.stdin.isTTY && process.stdout.isTTY);
178
+ const interactive =
179
+ options.interactive ?? (process.stdin.isTTY && process.stdout.isTTY);
158
180
  const ask = options.ask || askYesNo;
159
181
  const installLatestFn = options.installLatest || installLatest;
160
182
 
@@ -163,7 +185,9 @@ export async function upgradeCommand(argv = [], options = {}) {
163
185
  console.error(
164
186
  `\n ${c.yellow}Do you want to upgrade?${c.reset} requires a TTY.`,
165
187
  );
166
- console.error(` Run ${c.cyan}subc upgrade --latest${c.reset} instead.\n`);
188
+ console.error(
189
+ ` Run ${c.cyan}subc upgrade --latest${c.reset} instead.\n`,
190
+ );
167
191
  process.exitCode = 1;
168
192
  return;
169
193
  }
package/bin/usage.js CHANGED
@@ -2,26 +2,37 @@
2
2
  * Usage display for `subc usage` — fetches billing/quota from the platform API.
3
3
  */
4
4
 
5
- import { c } from './colors.js';
6
5
  import { getApiKey, getPlatformUrl } from './auth.js';
6
+ import { c } from './colors.js';
7
7
  import { DEFAULT_PROFILE } from './profiles.js';
8
8
  import { printLoginUpgradeWarning } from './upgrade.js';
9
9
 
10
10
  export const USAGE_API_PATH = '/api/v1/usage';
11
11
 
12
- export function formatTokens(value) {
12
+ // Largest first: [size, suffix].
13
+ const TOKEN_UNITS = [
14
+ [1_000_000_000, 'B'],
15
+ [1_000_000, 'M'],
16
+ [1_000, 'K'],
17
+ ];
18
+
19
+ export function formatTokens(value, { sigFigs = 3 } = {}) {
13
20
  const n = Number(value);
21
+
14
22
  if (!Number.isFinite(n) || n < 0) return '0';
15
- if (n >= 1_000_000_000) {
16
- const scaled = n / 1_000_000_000;
17
- return `${scaled.toFixed(n % 1_000_000_000 ? 1 : 0)}B`;
18
- }
19
- if (n >= 1_000_000) {
20
- const scaled = n / 1_000_000;
21
- return `${scaled.toFixed(n % 1_000_000 ? 1 : 0)}M`;
23
+
24
+ let index = TOKEN_UNITS.findIndex(([size]) => n >= size);
25
+ if (index === -1) return n.toLocaleString('en-US');
26
+
27
+ // Number() also turns toPrecision's exponent form ("1.00e+3") back into 1000.
28
+
29
+ let scaled = Number((n / TOKEN_UNITS[index][0]).toPrecision(sigFigs));
30
+ // Rounding can reach the next unit: 999_500 is 1M, not 1000K.
31
+ if (scaled >= 1_000 && index > 0) {
32
+ index -= 1;
33
+ scaled = Number((n / TOKEN_UNITS[index][0]).toPrecision(sigFigs));
22
34
  }
23
- if (n >= 1_000) return `${Math.round(n / 1_000)}K`;
24
- return n.toLocaleString('en-US');
35
+ return `${scaled}${TOKEN_UNITS[index][1]}`;
25
36
  }
26
37
 
27
38
  export function formatCurrency(value) {
@@ -33,13 +44,18 @@ export function formatCurrency(value) {
33
44
 
34
45
  export function shortModelSlug(slug) {
35
46
  const text = String(slug ?? '').trim();
36
- return text.startsWith('subconscious/') ? text.slice('subconscious/'.length) : text;
47
+ return text.startsWith('subconscious/')
48
+ ? text.slice('subconscious/'.length)
49
+ : text;
37
50
  }
38
51
 
39
52
  export function isLegacyUsagePayload(data) {
40
53
  if (!data || typeof data !== 'object') return true;
41
- if ('credits' in data && data.plan && typeof data.plan === 'object') return false;
42
- return 'dailyTokenCeiling' in data || 'consumedToday' in data || !('plan' in data);
54
+ if ('credits' in data && data.plan && typeof data.plan === 'object')
55
+ return false;
56
+ return (
57
+ 'dailyTokenCeiling' in data || 'consumedToday' in data || !('plan' in data)
58
+ );
43
59
  }
44
60
 
45
61
  export function meterColor(percentage) {
@@ -120,7 +136,9 @@ export function formatUsageDisplay(data) {
120
136
  );
121
137
  } else {
122
138
  const label =
123
- described.kind === 'credit' ? 'of daily credit used' : 'of daily tokens used';
139
+ described.kind === 'credit'
140
+ ? 'of daily credit used'
141
+ : 'of daily tokens used';
124
142
  lines.push(
125
143
  ` ${renderProgressBar(described.percent)} ${formatAllowancePercent(described.percent)} ${label}`,
126
144
  );
@@ -155,9 +173,7 @@ export function formatUsageDisplay(data) {
155
173
  );
156
174
  for (const model of models) {
157
175
  const label = shortModelSlug(model.slug).padEnd(slugWidth);
158
- lines.push(
159
- ` ${label} ${formatTokens(model.consumedToday ?? 0)}`,
160
- );
176
+ lines.push(` ${label} ${formatTokens(model.consumedToday ?? 0)}`);
161
177
  }
162
178
  }
163
179
 
@@ -166,10 +182,13 @@ export function formatUsageDisplay(data) {
166
182
  }
167
183
 
168
184
  export async function fetchUsage(apiKey, platformUrl, fetchImpl = fetch) {
169
- const res = await fetchImpl(`${platformUrl.replace(/\/$/, '')}${USAGE_API_PATH}`, {
170
- headers: { Authorization: `Bearer ${apiKey}` },
171
- signal: AbortSignal.timeout(5000),
172
- });
185
+ const res = await fetchImpl(
186
+ `${platformUrl.replace(/\/$/, '')}${USAGE_API_PATH}`,
187
+ {
188
+ headers: { Authorization: `Bearer ${apiKey}` },
189
+ signal: AbortSignal.timeout(5000),
190
+ },
191
+ );
173
192
  return res;
174
193
  }
175
194
 
@@ -183,7 +202,9 @@ export async function usageCommand(argv = [], options = {}) {
183
202
  const auth = await getApiKey(options.profile);
184
203
  if (!auth) {
185
204
  console.log(`\n ${c.dim}Not logged in.${c.reset}`);
186
- console.log(` Run ${c.cyan}subc ${profileFlag}login${c.reset} to get started.\n`);
205
+ console.log(
206
+ ` Run ${c.cyan}subc ${profileFlag}login${c.reset} to get started.\n`,
207
+ );
187
208
  return;
188
209
  }
189
210
 
@@ -236,7 +257,9 @@ export async function usageCommand(argv = [], options = {}) {
236
257
  console.log(formatUsageDisplay(data));
237
258
  } catch (error) {
238
259
  if (error.name === 'TimeoutError' || error.name === 'AbortError') {
239
- console.log(`\n ${c.yellow}Could not reach the platform (timed out).${c.reset}`);
260
+ console.log(
261
+ `\n ${c.yellow}Could not reach the platform (timed out).${c.reset}`,
262
+ );
240
263
  console.log(` ${c.dim}Host: ${platformUrl}${c.reset}\n`);
241
264
  return;
242
265
  }