claudemon 0.3.3 → 0.4.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.
@@ -9,66 +9,16 @@
9
9
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
10
10
  import { Type } from "@sinclair/typebox";
11
11
  import { matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
12
- import { execFileSync } from "node:child_process";
13
- import { existsSync, readFileSync } from "node:fs";
14
- import { homedir, platform } from "node:os";
15
- import { join } from "node:path";
16
12
 
17
13
  // ---------------------------------------------------------------------------
18
- // Token resolution (same logic as claudemon's auth.ts)
14
+ // Token resolution uses pi's native auth via modelRegistry
19
15
  // ---------------------------------------------------------------------------
20
16
 
21
- function readKeychainCredentials(): Record<string, unknown> | null {
22
- if (platform() !== "darwin") return null;
23
- try {
24
- const raw = execFileSync(
25
- "/usr/bin/security",
26
- ["find-generic-password", "-s", "Claude Code-credentials", "-w"],
27
- { timeout: 5000, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] },
28
- );
29
- if (!raw.trim()) return null;
30
- return JSON.parse(raw.trim()) as Record<string, unknown>;
31
- } catch {
32
- return null;
33
- }
34
- }
35
-
36
- function readFileCredentials(): Record<string, unknown> | null {
37
- const credFile = join(homedir(), ".claude", ".credentials.json");
38
- if (!existsSync(credFile)) return null;
39
- try {
40
- return JSON.parse(readFileSync(credFile, "utf-8")) as Record<string, unknown>;
41
- } catch {
42
- return null;
43
- }
44
- }
17
+ type ModelRegistryCtx = { modelRegistry: { getApiKeyForProvider(p: string): Promise<string | undefined> } };
45
18
 
46
- function readClaudemonToken(): string | null {
47
- const tokenFile = join(homedir(), ".config", "claudemon", "token.json");
48
- if (!existsSync(tokenFile)) return null;
49
- try {
50
- const data = JSON.parse(readFileSync(tokenFile, "utf-8"));
51
- if (data.expires_at && data.expires_at < Date.now()) return null;
52
- return data.oauth_token ?? null;
53
- } catch {
54
- return null;
55
- }
56
- }
57
-
58
- function getOAuthToken(): string | null {
59
- // Prefer Claude Code's live credentials
60
- for (const reader of [readKeychainCredentials, readFileCredentials]) {
61
- const data = reader();
62
- if (data) {
63
- const oauth = data["claudeAiOauth"] as { accessToken?: string; expiresAt?: number } | undefined;
64
- if (oauth?.accessToken) {
65
- if (oauth.expiresAt && oauth.expiresAt < Date.now()) continue;
66
- return oauth.accessToken;
67
- }
68
- }
69
- }
70
- // Fallback to claudemon's own stored token
71
- return readClaudemonToken();
19
+ async function getOAuthTokenFromCtx(ctx: ModelRegistryCtx): Promise<string | null> {
20
+ const apiKey = await ctx.modelRegistry.getApiKeyForProvider("anthropic");
21
+ return apiKey ?? null;
72
22
  }
73
23
 
74
24
  // ---------------------------------------------------------------------------
@@ -99,7 +49,7 @@ async function fetchQuota(token: string): Promise<QuotaData> {
99
49
  });
100
50
 
101
51
  if (resp.status === 401 || resp.status === 403) {
102
- throw new Error("OAuth token expired. Run `claudemon setup` to re-authenticate.");
52
+ throw new Error("OAuth token expired or invalid. Try `/login` to re-authenticate.");
103
53
  }
104
54
  if (resp.status === 429) {
105
55
  const retryAfter = resp.headers.get("retry-after");
@@ -521,10 +471,10 @@ export default function (pi: ExtensionAPI) {
521
471
 
522
472
  // --tui flag: launch the native pi TUI dashboard
523
473
  if (trimmed === "--tui" || trimmed === "-t") {
524
- const token = getOAuthToken();
474
+ const token = await getOAuthTokenFromCtx(ctx);
525
475
  if (!token) {
526
476
  ctx.ui.notify(
527
- "Not authenticated. Run `claudemon setup` or `npx claudemon setup` first.",
477
+ "Not authenticated. Make sure you're logged in (`/login`).",
528
478
  "error",
529
479
  );
530
480
  return;
@@ -543,10 +493,10 @@ export default function (pi: ExtensionAPI) {
543
493
  }
544
494
 
545
495
  // Default: fetch and display inline
546
- const token = getOAuthToken();
496
+ const token = await getOAuthTokenFromCtx(ctx);
547
497
  if (!token) {
548
498
  ctx.ui.notify(
549
- "Not authenticated. Run `claudemon setup` or `npx claudemon setup` first.",
499
+ "Not authenticated. Make sure you're logged in (`/login`).",
550
500
  "error",
551
501
  );
552
502
  return;
@@ -571,14 +521,14 @@ export default function (pi: ExtensionAPI) {
571
521
  description:
572
522
  "Check the user's Claude Pro/Max plan quota usage including 5-hour and 7-day windows and per-model breakdown. Use when the user asks about their Claude usage, quota, or remaining capacity.",
573
523
  parameters: Type.Object({}),
574
- async execute(_toolCallId, _params, signal) {
575
- const token = getOAuthToken();
524
+ async execute(_toolCallId, _params, signal, _onUpdate, ctx) {
525
+ const token = await getOAuthTokenFromCtx(ctx as ModelRegistryCtx);
576
526
  if (!token) {
577
527
  return {
578
528
  content: [
579
529
  {
580
530
  type: "text" as const,
581
- text: "Not authenticated. The user needs to run `claudemon setup` or `npx claudemon setup` to authenticate first.",
531
+ text: "Not authenticated. The user needs to log in first (`/login`).",
582
532
  },
583
533
  ],
584
534
  isError: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemon",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "Claude Usage Monitor TUI - monitor your Claude usage in real-time",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",