axusage 3.2.0 → 3.3.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/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ import { usageCommand } from "./commands/usage-command.js";
7
7
  import { getCredentialSourcesPath } from "./config/credential-sources.js";
8
8
  import { getAvailableServices } from "./services/service-adapter-registry.js";
9
9
  import { configureColor } from "./utils/color.js";
10
+ import { formatRequiresHelpText } from "./utils/format-requires-help-text.js";
10
11
  import { getRootOptionsError, } from "./utils/validate-root-options.js";
11
12
  // Parse --no-color early so help/error output is consistently uncolored.
12
13
  const shouldDisableColor = process.argv.includes("--no-color");
@@ -25,7 +26,7 @@ const program = new Command()
25
26
  .default("text"))
26
27
  .option("--auth-setup <service>", "set up authentication for a service (directs to appropriate CLI)")
27
28
  .option("--auth-status [service]", "check authentication status for services")
28
- .addHelpText("after", () => `\nExamples:\n # Fetch usage for all services\n ${packageJson.name}\n\n # JSON output for a single service\n ${packageJson.name} --service claude --format json\n\n # TSV output for piping to cut, awk, sort\n ${packageJson.name} --format tsv | tail -n +2 | awk -F'\\t' '{print $1, $4"%"}'\n\n # Filter Prometheus metrics with standard tools\n ${packageJson.name} --format prometheus | grep axusage_utilization_percent\n\n # Check authentication status for all services\n ${packageJson.name} --auth-status\n\nSources config file: ${getCredentialSourcesPath()}\n(or set AXUSAGE_SOURCES to JSON to bypass file)\n\nRequires: claude, codex (ChatGPT), gemini, gh (Copilot) CLIs for auth\nOverride CLI paths: AXUSAGE_CLAUDE_PATH, AXUSAGE_CODEX_PATH, AXUSAGE_GEMINI_PATH, AXUSAGE_GH_PATH\n`);
29
+ .addHelpText("after", () => `\nExamples:\n # Fetch usage for all services\n ${packageJson.name}\n\n # JSON output for a single service\n ${packageJson.name} --service claude --format json\n\n # TSV output for piping to cut, awk, sort\n ${packageJson.name} --format tsv | tail -n +2 | awk -F'\\t' '{print $1, $4"%"}'\n\n # Filter Prometheus metrics with standard tools\n ${packageJson.name} --format prometheus | grep axusage_utilization_percent\n\n # Check authentication status for all services\n ${packageJson.name} --auth-status\n\nSources config file: ${getCredentialSourcesPath()}\n(or set AXUSAGE_SOURCES to JSON to bypass file)\n\n${formatRequiresHelpText()}\nOverride CLI paths: AXUSAGE_CLAUDE_PATH, AXUSAGE_CODEX_PATH, AXUSAGE_GEMINI_PATH, AXUSAGE_GH_PATH\n`);
29
30
  function fail(message) {
30
31
  console.error(`Error: ${message}`);
31
32
  console.error("Try 'axusage --help' for details.");
@@ -1,6 +1,5 @@
1
- import { checkAuth } from "axauth";
1
+ import { getServiceDiagnostic } from "../services/service-diagnostics.js";
2
2
  import { SUPPORTED_SERVICES, validateService, } from "../services/supported-service.js";
3
- import { getCopilotTokenFromCustomGhPath } from "../utils/copilot-gh-token.js";
4
3
  import { chalk } from "../utils/color.js";
5
4
  export function authStatusCommand(options) {
6
5
  const servicesToCheck = options.service
@@ -9,26 +8,16 @@ export function authStatusCommand(options) {
9
8
  let hasFailures = false;
10
9
  console.log(chalk.blue("\nAuthentication Status:\n"));
11
10
  for (const service of servicesToCheck) {
12
- let result = checkAuth(service);
13
- if (service === "copilot" && !result.authenticated) {
14
- const tokenFromOverride = getCopilotTokenFromCustomGhPath();
15
- if (tokenFromOverride) {
16
- result = {
17
- ...result,
18
- authenticated: true,
19
- method: "GitHub CLI (AXUSAGE_GH_PATH)",
20
- };
21
- }
22
- }
23
- const status = result.authenticated
11
+ const diagnostic = getServiceDiagnostic(service);
12
+ const status = diagnostic.authenticated
24
13
  ? chalk.green("✓ authenticated")
25
14
  : chalk.red("✗ not authenticated");
26
- if (!result.authenticated) {
15
+ if (!diagnostic.authenticated) {
27
16
  hasFailures = true;
28
17
  }
29
18
  console.log(`${chalk.bold(service)}: ${status}`);
30
- if (result.method) {
31
- console.log(` ${chalk.dim("Method:")} ${chalk.dim(result.method)}`);
19
+ if (diagnostic.authMethod) {
20
+ console.log(` ${chalk.dim("Method:")} ${chalk.dim(diagnostic.authMethod)}`);
32
21
  }
33
22
  }
34
23
  if (hasFailures) {
@@ -0,0 +1,11 @@
1
+ import type { SupportedService } from "./supported-service.js";
2
+ type ServiceDiagnostic = {
3
+ readonly service: SupportedService;
4
+ readonly cliAvailable: boolean;
5
+ readonly cliPath: string;
6
+ readonly authenticated: boolean;
7
+ readonly authMethod: string | undefined;
8
+ };
9
+ export type { ServiceDiagnostic };
10
+ export declare function getServiceDiagnostic(service: SupportedService): ServiceDiagnostic;
11
+ export declare function getAllServiceDiagnostics(): ServiceDiagnostic[];
@@ -0,0 +1,29 @@
1
+ import { checkAuth } from "axauth";
2
+ import { checkCliDependency, getAuthCliDependency, } from "../utils/check-cli-dependency.js";
3
+ import { getCopilotTokenFromCustomGhPath } from "../utils/copilot-gh-token.js";
4
+ import { SUPPORTED_SERVICES } from "./supported-service.js";
5
+ export function getServiceDiagnostic(service) {
6
+ const dependency = getAuthCliDependency(service);
7
+ const cliResult = checkCliDependency(dependency);
8
+ let authResult = checkAuth(service);
9
+ if (service === "copilot" && !authResult.authenticated) {
10
+ const tokenFromOverride = getCopilotTokenFromCustomGhPath();
11
+ if (tokenFromOverride) {
12
+ authResult = {
13
+ ...authResult,
14
+ authenticated: true,
15
+ method: "GitHub CLI (AXUSAGE_GH_PATH)",
16
+ };
17
+ }
18
+ }
19
+ return {
20
+ service,
21
+ cliAvailable: cliResult.ok,
22
+ cliPath: cliResult.path,
23
+ authenticated: authResult.authenticated,
24
+ authMethod: authResult.method,
25
+ };
26
+ }
27
+ export function getAllServiceDiagnostics() {
28
+ return SUPPORTED_SERVICES.map((service) => getServiceDiagnostic(service));
29
+ }
@@ -0,0 +1,17 @@
1
+ type RuntimeRequirement = {
2
+ readonly label: string;
3
+ readonly status: "ok";
4
+ } | {
5
+ readonly label: string;
6
+ readonly status: "missing" | "not-authorized";
7
+ readonly fix: string;
8
+ };
9
+ export type { RuntimeRequirement };
10
+ /**
11
+ * Formats a list of runtime requirements into a compact or detailed string.
12
+ *
13
+ * All-ok → single line: `Requires: claude, codex (ChatGPT), gemini, gh (Copilot)`
14
+ * Any non-ok → multi-line with inline remediation per requirement.
15
+ */
16
+ export declare function formatRequiresSection(requirements: readonly RuntimeRequirement[]): string;
17
+ export declare function formatRequiresHelpText(): string;
@@ -0,0 +1,62 @@
1
+ import { getAllServiceDiagnostics } from "../services/service-diagnostics.js";
2
+ import { getAuthCliDependency } from "./check-cli-dependency.js";
3
+ const SERVICE_LABELS = {
4
+ claude: "claude",
5
+ codex: "codex (ChatGPT)",
6
+ gemini: "gemini",
7
+ copilot: "gh (Copilot)",
8
+ };
9
+ const AUTH_FIX_COMMANDS = {
10
+ claude: "Run: claude",
11
+ codex: "Run: codex",
12
+ gemini: "Run: gemini",
13
+ copilot: "Run: gh auth login",
14
+ };
15
+ function diagnosticToRequirement(diagnostic) {
16
+ const label = SERVICE_LABELS[diagnostic.service];
17
+ if (!diagnostic.cliAvailable) {
18
+ const dependency = getAuthCliDependency(diagnostic.service);
19
+ return {
20
+ label,
21
+ status: "missing",
22
+ fix: `Install: ${dependency.installHint}. ` +
23
+ `Or set ${dependency.envVar}=/path/to/${dependency.command}`,
24
+ };
25
+ }
26
+ if (!diagnostic.authenticated) {
27
+ return {
28
+ label,
29
+ status: "not-authorized",
30
+ fix: AUTH_FIX_COMMANDS[diagnostic.service],
31
+ };
32
+ }
33
+ return { label, status: "ok" };
34
+ }
35
+ let cachedRequirements;
36
+ function getRuntimeRequirementsStatus() {
37
+ if (cachedRequirements)
38
+ return cachedRequirements;
39
+ cachedRequirements = getAllServiceDiagnostics().map((d) => diagnosticToRequirement(d));
40
+ return cachedRequirements;
41
+ }
42
+ /**
43
+ * Formats a list of runtime requirements into a compact or detailed string.
44
+ *
45
+ * All-ok → single line: `Requires: claude, codex (ChatGPT), gemini, gh (Copilot)`
46
+ * Any non-ok → multi-line with inline remediation per requirement.
47
+ */
48
+ export function formatRequiresSection(requirements) {
49
+ if (requirements.every((r) => r.status === "ok")) {
50
+ return `Requires: ${requirements.map((r) => r.label).join(", ")}`;
51
+ }
52
+ const lines = requirements.map((r) => {
53
+ if (r.status === "ok")
54
+ return ` - ${r.label}`;
55
+ const tag = r.status === "missing" ? "MISSING" : "NOT AUTHORIZED";
56
+ return ` - ${r.label} - ${tag}! ${r.fix}`;
57
+ });
58
+ return `Requires:\n${lines.join("\n")}`;
59
+ }
60
+ export function formatRequiresHelpText() {
61
+ return formatRequiresSection(getRuntimeRequirementsStatus());
62
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "axusage",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "3.2.0",
5
+ "version": "3.3.0",
6
6
  "description": "Monitor API usage across Claude, ChatGPT, GitHub Copilot, and Gemini from a single CLI",
7
7
  "repository": {
8
8
  "type": "git",