@bacnh85/pi-sub 0.1.8 → 0.1.10

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
@@ -15,13 +15,9 @@ pi install npm:@bacnh85/pi-sub
15
15
  From this repository checkout:
16
16
 
17
17
  ```bash
18
- cd extensions/pi-sub
19
- npm install
20
- cd ../..
21
-
22
- pi install ./extensions/pi-sub
18
+ pi install ./pi-sub
23
19
  # or test directly
24
- pi -e ./extensions/pi-sub
20
+ pi -e ./pi-sub
25
21
  ```
26
22
 
27
23
  ## What it shows
@@ -30,32 +26,31 @@ pi -e ./extensions/pi-sub
30
26
 
31
27
  The footer status appears after Pi's built-in status/token usage line and includes:
32
28
 
33
- - active account email;
34
- - subscription plan, such as `Plus`;
35
- - 5-hour usage percentage and reset time;
36
- - weekly usage percentage and reset time/date;
37
- - active Codex model id.
29
+ - active account email/account label;
30
+ - subscription plan, such as `Plus` in `/sub` details;
31
+ - 5-hour remaining quota and reset countdown;
32
+ - weekly remaining quota and reset countdown.
38
33
 
39
34
  Example subscription line:
40
35
 
41
36
  ```text
42
- Sub · Plus · user@example.com · 5H 85% (18:12) · W 80% (08:00 on 2 Jul) · gpt-5-codex
37
+ (user@example.com) R:15%/2H W:20%/3D
43
38
  ```
44
39
 
45
40
  ### OpenCode Go
46
41
 
47
- OpenCode Go does not expose usage windows, so the footer shows only the accumulated session cost:
42
+ OpenCode Go does not expose a public usage-window API, so the footer shows the active account/key label and accumulated session cost:
48
43
 
49
44
  ```text
50
- OpenCode Go $0.23
45
+ OpenCode Go (OpenCode Go key#1a2b3c4d) $0.23
51
46
  ```
52
47
 
53
48
  ### Z.ai
54
49
 
55
- Z.ai (GLM Coding Plan) shows 5-hour rolling and weekly quota percentages with reset times:
50
+ Z.ai (GLM Coding Plan) shows the active account/key label plus 5-hour rolling and weekly remaining quota with reset countdowns:
56
51
 
57
52
  ```text
58
- R:55%(18:12) W:80%(08:00 on 2 Jul)
53
+ (Z.ai key#1a2b3c4d) R:55%/2H W:80%/3D
59
54
  ```
60
55
 
61
56
  When the current model provider is not supported, `pi-sub` clears its subscription line and does not refresh subscription data.
@@ -71,16 +66,21 @@ When the current model provider is not supported, `pi-sub` clears its subscripti
71
66
  When Pi OpenAI Codex auth is available, `/sub` shows the active account usage:
72
67
 
73
68
  ```text
74
- ACCOUNT PLAN 5H USAGE WEEKLY USAGE LAST ACTIVITY
75
- * user@example.com Plus 85% (18:12) 80% (08:00 on 2 Jul) Now
69
+ ACCOUNT PLAN ROLLING WEEKLY LAST ACTIVITY
70
+ * user@example.com Plus 15%/2H 20%/3D Now
76
71
  ```
77
72
 
78
- For OpenCode Go, `/sub` shows the provider/model and session cost:
73
+ For OpenCode Go, `/sub` shows the provider/model, active account/key label, and session cost:
79
74
 
80
75
  ```text
81
76
  Provider: OpenCode Go · Model: kimi-k2.6 · Fetched: 14:23
82
- OpenCode Go does not expose usage windows.
83
77
  Session cost: $0.23
78
+
79
+ ACCOUNT PLAN LAST ACTIVITY
80
+ ------------------------------------------------------
81
+ * OpenCode Go key#1a2b3c4d Go Now
82
+
83
+ OpenCode Go does not expose usage windows.
84
84
  ```
85
85
 
86
86
  For Z.ai, `/sub` shows the rolling and weekly quota windows:
@@ -90,7 +90,7 @@ Provider: Z.ai · Model: glm-5.2 · Fetched: 14:23
90
90
 
91
91
  ACCOUNT PLAN ROLLING WEEKLY LAST ACTIVITY
92
92
  ------------------------------------------------------------------------
93
- * Z.ai subscription ? 55%/18:12 80%/08:00 on 2 Jul Now
93
+ * Z.ai key#1a2b3c4d Pro 55%/2H 80%/3D Now
94
94
  ```
95
95
 
96
96
  ## Refresh behavior
@@ -110,8 +110,9 @@ Refreshes are cached briefly to avoid excessive usage endpoint calls.
110
110
  ## Requirements and troubleshooting
111
111
 
112
112
  - **OpenAI Codex**: Pi auth must contain an `openai-codex` OAuth entry in `~/.pi/agent/auth.json` or `$PI_CODING_AGENT_DIR/auth.json`. The entry must include `access` and `accountId` fields.
113
- - **OpenCode Go**: Pi auth must contain an `opencode-go` API key entry (via `/login` or env var). The entry must have a `key` field or an `accountId` field.
113
+ - **OpenCode Go**: Pi auth must contain an `opencode-go` API key entry (via `/login` or env var). The entry must have a `key` field or an `accountId` field. OpenCode Go/Zen usage windows and Zen balance are not shown because no public API is currently documented for those values.
114
114
  - **Z.ai**: Pi auth must contain a `zai` entry in `auth.json` with a `key` field (the same API key used for Z.ai model access via `@czottmann/pi-zai-api`). The Z.ai provider must be registered (e.g., `pi install npm:@czottmann/pi-zai-api`).
115
+ - For API-key-only providers, account labels come from stored auth metadata (`email`, `label`, `name`, or `accountId`) when available; otherwise `pi-sub` displays a non-secret SHA-256 key fingerprint such as `Z.ai key#1a2b3c4d`.
115
116
  - `pi-sub` redacts auth/token-related errors and never prints credentials.
116
117
 
117
118
  ## Design notes
@@ -1,5 +1,6 @@
1
1
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { Box, Text } from "@earendil-works/pi-tui";
3
+ import { createHash } from "node:crypto";
3
4
  import fs from "node:fs/promises";
4
5
  import os from "node:os";
5
6
  import path from "node:path";
@@ -19,7 +20,6 @@ type ModelLike = { provider?: string; id?: string } | undefined;
19
20
 
20
21
  type UsageApiWindow = {
21
22
  used_percent?: number;
22
- limit_window_seconds?: number;
23
23
  reset_at?: number;
24
24
  };
25
25
 
@@ -38,17 +38,17 @@ type PiAuthEntry = {
38
38
  expires?: number;
39
39
  accountId?: string;
40
40
  key?: string;
41
+ email?: string;
42
+ label?: string;
43
+ name?: string;
44
+ env?: Record<string, string>;
41
45
  };
42
46
 
43
47
  interface UsageWindow {
44
- used?: number;
45
- limit?: number;
46
48
  percent?: number;
47
49
  remaining?: number;
48
50
  remainingLabel?: string;
49
51
  resetLabel?: string;
50
- resetsAt?: string | number | Date;
51
- label?: string;
52
52
  }
53
53
 
54
54
  interface SubscriptionAccountSnapshot {
@@ -58,12 +58,10 @@ interface SubscriptionAccountSnapshot {
58
58
  plan?: string;
59
59
  fiveHour?: UsageWindow;
60
60
  weekly?: UsageWindow;
61
- monthly?: UsageWindow;
62
61
  lastActivity?: string;
63
62
  }
64
63
 
65
64
  interface SubscriptionUsageSnapshot {
66
- providerId: string;
67
65
  providerDisplayName: string;
68
66
  accounts: SubscriptionAccountSnapshot[];
69
67
  activeAccount?: SubscriptionAccountSnapshot;
@@ -72,12 +70,11 @@ interface SubscriptionUsageSnapshot {
72
70
  cost?: number;
73
71
  }
74
72
 
75
- interface SubscriptionProviderAdapter {
73
+ type SubscriptionProviderAdapter = {
76
74
  id: string;
77
75
  displayName: string;
78
- isModelSupported(model: ModelLike): boolean;
79
76
  fetchUsage(signal?: AbortSignal): Promise<SubscriptionUsageSnapshot>;
80
- }
77
+ };
81
78
 
82
79
  interface State {
83
80
  model?: ModelLike;
@@ -140,6 +137,46 @@ function accountFromPiAuth(entry: PiAuthEntry): SubscriptionAccountSnapshot {
140
137
  };
141
138
  }
142
139
 
140
+ function firstString(...values: unknown[]): string | undefined {
141
+ for (const value of values) {
142
+ if (typeof value !== "string") continue;
143
+ const trimmed = value.trim();
144
+ if (trimmed.length > 0) return trimmed;
145
+ }
146
+ return undefined;
147
+ }
148
+
149
+ function authEntryLabel(entry: PiAuthEntry | undefined): string | undefined {
150
+ return firstString(entry?.email, entry?.label, entry?.name, entry?.accountId);
151
+ }
152
+
153
+ function keyFingerprint(key: string | undefined): string | undefined {
154
+ if (!key) return undefined;
155
+ return createHash("sha256").update(key).digest("hex").slice(0, 8);
156
+ }
157
+
158
+ function authAccountLabel(providerLabel: string, entry: PiAuthEntry | undefined): string {
159
+ const label = authEntryLabel(entry);
160
+ if (label) return label;
161
+ const fingerprint = keyFingerprint(entry?.key);
162
+ return fingerprint ? `${providerLabel} key#${fingerprint}` : `${providerLabel} account`;
163
+ }
164
+
165
+ function authAccountSnapshot(providerLabel: string, entry: PiAuthEntry | undefined, defaults: Partial<SubscriptionAccountSnapshot> = {}): SubscriptionAccountSnapshot {
166
+ return {
167
+ id: firstString(entry?.accountId),
168
+ isActive: true,
169
+ accountLabel: authAccountLabel(providerLabel, entry),
170
+ lastActivity: "Now",
171
+ ...defaults,
172
+ };
173
+ }
174
+
175
+ function formatFooterAccount(account: SubscriptionAccountSnapshot | undefined): string | undefined {
176
+ const label = firstString(account?.accountLabel);
177
+ return label ? `(${label})` : undefined;
178
+ }
179
+
143
180
  function getCodexAccountId(entry: PiAuthEntry | undefined): string | undefined {
144
181
  if (!entry) return undefined;
145
182
  if (typeof entry.accountId === "string" && entry.accountId.length > 0) return entry.accountId;
@@ -201,8 +238,6 @@ function usageWindowFromApi(window: UsageApiWindow | undefined): UsageWindow | u
201
238
  remaining,
202
239
  remainingLabel,
203
240
  resetLabel,
204
- resetsAt: window.reset_at,
205
- label: remainingLabel ? `${remaining}% (${remainingLabel})` : `${remaining}%`,
206
241
  };
207
242
  }
208
243
 
@@ -225,7 +260,6 @@ function parseUsageResponse(body: unknown): UsageApiSnapshot | undefined {
225
260
  if (!window || typeof window !== "object" || typeof window.used_percent !== "number") return undefined;
226
261
  return {
227
262
  used_percent: window.used_percent,
228
- limit_window_seconds: typeof window.limit_window_seconds === "number" ? window.limit_window_seconds : undefined,
229
263
  reset_at: typeof window.reset_at === "number" ? window.reset_at : undefined,
230
264
  };
231
265
  };
@@ -244,29 +278,30 @@ async function readPiCodexAuth(): Promise<PiAuthEntry & { accountId: string }> {
244
278
  return { ...entry, accountId };
245
279
  }
246
280
 
247
- async function readOpenCodeGoAuth(): Promise<{ key?: string; accountId?: string }> {
281
+ async function readOpenCodeGoAuth(): Promise<SubscriptionAccountSnapshot> {
248
282
  const auth = await readJsonFile<PiAuthFile>(piAuthPath());
249
283
  const entry = auth[OPC_PROVIDER];
250
284
  if (!entry?.key && !entry?.accountId) throw new Error("Missing opencode-go API key or accountId in Pi auth");
251
- if (typeof entry.key === "string") return { key: entry.key };
252
- return { accountId: typeof entry.accountId === "string" ? entry.accountId : undefined };
285
+ return authAccountSnapshot("OpenCode Go", entry, { plan: "Go" });
253
286
  }
254
287
 
255
- async function readZaiAuth(): Promise<string> {
288
+ async function readZaiAuth(): Promise<{ key: string; account: SubscriptionAccountSnapshot }> {
256
289
  const auth = await readJsonFile<PiAuthFile>(piAuthPath());
257
290
  const entry = auth[ZAI_PROVIDER];
258
291
  if (!entry?.key) throw new Error("Missing zai API key in Pi auth");
259
- return entry.key;
292
+ return { key: entry.key, account: authAccountSnapshot("Z.ai", entry) };
260
293
  }
261
294
 
262
295
  async function fetchUsageFromPiAuth(entry: PiAuthEntry, signal?: AbortSignal): Promise<UsageApiSnapshot | undefined> {
296
+ const accountId = getCodexAccountId(entry) ?? entry.accountId;
297
+ if (!accountId) throw new Error("Missing openai-codex OAuth entry in Pi auth");
263
298
  const timeoutSignal = AbortSignal.timeout(7_000);
264
299
  const combinedSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
265
300
  const response = await fetch(USAGE_ENDPOINT, {
266
301
  headers: {
267
302
  Accept: "application/json",
268
303
  Authorization: `Bearer ${entry.access}`,
269
- "ChatGPT-Account-Id": getCodexAccountId(entry) ?? entry.accountId,
304
+ "ChatGPT-Account-Id": accountId,
270
305
  "User-Agent": "pi-sub/0.1.0",
271
306
  },
272
307
  signal: combinedSignal,
@@ -293,7 +328,6 @@ async function fetchCodexUsage(signal?: AbortSignal): Promise<SubscriptionUsageS
293
328
  const usage = await fetchUsageFromPiAuth(entry, signal);
294
329
  activeAccount = mergeUsageIntoAccount(activeAccount, usage);
295
330
  return {
296
- providerId: CODEX_PROVIDER,
297
331
  providerDisplayName: "Codex",
298
332
  accounts: [activeAccount],
299
333
  activeAccount,
@@ -301,7 +335,6 @@ async function fetchCodexUsage(signal?: AbortSignal): Promise<SubscriptionUsageS
301
335
  };
302
336
  } catch (error) {
303
337
  return {
304
- providerId: CODEX_PROVIDER,
305
338
  providerDisplayName: "Codex",
306
339
  accounts: [],
307
340
  fetchedAt: Date.now(),
@@ -312,16 +345,15 @@ async function fetchCodexUsage(signal?: AbortSignal): Promise<SubscriptionUsageS
312
345
 
313
346
  async function fetchOpenCodeGoUsage(_signal?: AbortSignal): Promise<SubscriptionUsageSnapshot> {
314
347
  try {
315
- await readOpenCodeGoAuth();
348
+ const account = await readOpenCodeGoAuth();
316
349
  return {
317
- providerId: OPC_PROVIDER,
318
350
  providerDisplayName: "OpenCode Go",
319
- accounts: [],
351
+ accounts: [account],
352
+ activeAccount: account,
320
353
  fetchedAt: Date.now(),
321
354
  };
322
355
  } catch (error) {
323
356
  return {
324
- providerId: OPC_PROVIDER,
325
357
  providerDisplayName: "OpenCode Go",
326
358
  accounts: [],
327
359
  fetchedAt: Date.now(),
@@ -343,6 +375,10 @@ interface ZaiLimitEntry {
343
375
  interface ZaiUsageApiResponse {
344
376
  data?: {
345
377
  limits?: ZaiLimitEntry[];
378
+ planName?: string;
379
+ plan?: string;
380
+ plan_type?: string;
381
+ packageName?: string;
346
382
  };
347
383
  }
348
384
 
@@ -365,14 +401,17 @@ function zaiLimitToUsageWindow(limit: ZaiLimitEntry): UsageWindow | undefined {
365
401
  remaining,
366
402
  remainingLabel,
367
403
  resetLabel,
368
- resetsAt: limit.nextResetTime,
369
- label: remainingLabel ? `${remaining}% (${remainingLabel})` : `${remaining}%`,
370
404
  };
371
405
  }
372
406
 
407
+ function zaiPlanLabel(response: ZaiUsageApiResponse): string | undefined {
408
+ const data = response.data;
409
+ return planLabel(firstString(data?.planName, data?.plan, data?.plan_type, data?.packageName));
410
+ }
411
+
373
412
  async function fetchZaiUsage(signal?: AbortSignal): Promise<SubscriptionUsageSnapshot> {
374
413
  try {
375
- const apiKey = await readZaiAuth();
414
+ const { key: apiKey, account: authAccount } = await readZaiAuth();
376
415
  const timeoutSignal = AbortSignal.timeout(7_000);
377
416
  const combinedSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
378
417
 
@@ -408,15 +447,13 @@ async function fetchZaiUsage(signal?: AbortSignal): Promise<SubscriptionUsageSna
408
447
  const weekly = tokenLimits.length >= 2 ? zaiLimitToUsageWindow(tokenLimits[1]) : undefined;
409
448
 
410
449
  const account: SubscriptionAccountSnapshot = {
411
- isActive: true,
412
- accountLabel: "Z.ai subscription",
450
+ ...authAccount,
451
+ plan: zaiPlanLabel(parsed) ?? authAccount.plan,
413
452
  fiveHour,
414
453
  weekly,
415
- lastActivity: "Now",
416
454
  };
417
455
 
418
456
  return {
419
- providerId: ZAI_PROVIDER,
420
457
  providerDisplayName: "Z.ai",
421
458
  accounts: [account],
422
459
  activeAccount: account,
@@ -424,7 +461,6 @@ async function fetchZaiUsage(signal?: AbortSignal): Promise<SubscriptionUsageSna
424
461
  };
425
462
  } catch (error) {
426
463
  return {
427
- providerId: ZAI_PROVIDER,
428
464
  providerDisplayName: "Z.ai",
429
465
  accounts: [],
430
466
  fetchedAt: Date.now(),
@@ -433,31 +469,11 @@ async function fetchZaiUsage(signal?: AbortSignal): Promise<SubscriptionUsageSna
433
469
  }
434
470
  }
435
471
 
436
- const codexAdapter: SubscriptionProviderAdapter = {
437
- id: CODEX_PROVIDER,
438
- displayName: "Codex",
439
- isModelSupported: isCodexModel,
440
- fetchUsage: fetchCodexUsage,
441
- };
442
-
443
- const openCodeGoAdapter: SubscriptionProviderAdapter = {
444
- id: OPC_PROVIDER,
445
- displayName: "OpenCode Go",
446
- isModelSupported: isOpenCodeGoModel,
447
- fetchUsage: fetchOpenCodeGoUsage,
448
- };
449
-
450
- const zaiAdapter: SubscriptionProviderAdapter = {
451
- id: ZAI_PROVIDER,
452
- displayName: "Z.ai",
453
- isModelSupported: isZaiModel,
454
- fetchUsage: fetchZaiUsage,
455
- };
456
-
457
- const adapters = [codexAdapter, openCodeGoAdapter, zaiAdapter];
458
-
459
472
  function supportedAdapter(model: ModelLike): SubscriptionProviderAdapter | undefined {
460
- return adapters.find((adapter) => adapter.isModelSupported(model));
473
+ if (isCodexModel(model)) return { id: CODEX_PROVIDER, displayName: "Codex", fetchUsage: fetchCodexUsage };
474
+ if (isOpenCodeGoModel(model)) return { id: OPC_PROVIDER, displayName: "OpenCode Go", fetchUsage: fetchOpenCodeGoUsage };
475
+ if (isZaiModel(model)) return { id: ZAI_PROVIDER, displayName: "Z.ai", fetchUsage: fetchZaiUsage };
476
+ return undefined;
461
477
  }
462
478
 
463
479
  function formatRemaining(window: UsageWindow | undefined): string {
@@ -468,20 +484,10 @@ function formatRemaining(window: UsageWindow | undefined): string {
468
484
  return "?";
469
485
  }
470
486
 
471
- function formatWindow(window: UsageWindow | undefined, _compact = true): string {
472
- if (!window) return "?";
473
- if (window.percent !== undefined && window.resetLabel) return `${window.percent}% (${window.resetLabel})`;
474
- if (window.label) return window.label;
475
- if (window.percent !== undefined) return `${window.percent}%`;
476
- if (window.used !== undefined && window.limit !== undefined) return `${window.used}/${window.limit}`;
477
- return "?";
478
- }
479
-
480
487
  function minRemaining(account: SubscriptionAccountSnapshot | undefined): number {
481
488
  const values: number[] = [];
482
489
  if (account?.fiveHour?.remaining !== undefined) values.push(account.fiveHour.remaining);
483
490
  if (account?.weekly?.remaining !== undefined) values.push(account.weekly.remaining);
484
- if (account?.monthly?.remaining !== undefined) values.push(account.monthly.remaining);
485
491
  if (values.length === 0) return 100;
486
492
  return Math.min(...values);
487
493
  }
@@ -491,7 +497,6 @@ function windowSegments(account: SubscriptionAccountSnapshot | undefined): strin
491
497
  const segments: string[] = [];
492
498
  if (account.fiveHour) segments.push(`R:${formatRemaining(account.fiveHour)}`);
493
499
  if (account.weekly) segments.push(`W:${formatRemaining(account.weekly)}`);
494
- if (account.monthly) segments.push(`M:${formatRemaining(account.monthly)}`);
495
500
  return segments;
496
501
  }
497
502
 
@@ -521,9 +526,11 @@ function renderSubscriptionLine(ctx: ExtensionContext, state: State): void {
521
526
  color = "warning";
522
527
  } else {
523
528
  const account = snapshot.activeAccount;
524
- const segments = windowSegments(account);
529
+ const windowParts = windowSegments(account);
530
+ const accountPart = formatFooterAccount(account);
531
+ const segments = accountPart ? [accountPart, ...windowParts] : [...windowParts];
525
532
  const cost = snapshot.cost;
526
- const hasWindows = segments.length > 0;
533
+ const hasWindows = windowParts.length > 0;
527
534
  if (cost !== undefined && cost > 0) segments.push(`$${cost.toFixed(2)}`);
528
535
  if (segments.length === 0) {
529
536
  line = `Sub ${state.adapter.displayName}`;
@@ -629,12 +636,8 @@ function buildDetails(snapshot: SubscriptionUsageSnapshot | undefined, state: St
629
636
 
630
637
  const hasFiveHour = snapshot.accounts.some((a) => a.fiveHour);
631
638
  const hasWeekly = snapshot.accounts.some((a) => a.weekly);
632
- const hasMonthly = snapshot.accounts.some((a) => a.monthly);
633
-
634
639
  if (hasFiveHour) columns.push({ key: "five", label: "ROLLING", get: (a) => formatRemaining(a.fiveHour) });
635
640
  if (hasWeekly) columns.push({ key: "weekly", label: "WEEKLY", get: (a) => formatRemaining(a.weekly) });
636
- if (hasMonthly) columns.push({ key: "monthly", label: "MONTHLY", get: (a) => formatRemaining(a.monthly) });
637
-
638
641
  const rows = snapshot.accounts.map((account) => ({
639
642
  active: account.isActive ? "*" : " ",
640
643
  snapshot: account,
@@ -654,7 +657,11 @@ function buildDetails(snapshot: SubscriptionUsageSnapshot | undefined, state: St
654
657
  });
655
658
 
656
659
  const costLine = snapshot.cost !== undefined ? `\nSession cost: $${snapshot.cost.toFixed(2)}` : "";
657
- return [`Provider: ${snapshot.providerDisplayName} · Model: ${state.model?.id ?? "unknown-model"} · Fetched: ${new Date(snapshot.fetchedAt).toLocaleTimeString()}${costLine}`, "", header, sep, ...body].join("\n");
660
+ const lines = [`Provider: ${snapshot.providerDisplayName} · Model: ${state.model?.id ?? "unknown-model"} · Fetched: ${new Date(snapshot.fetchedAt).toLocaleTimeString()}${costLine}`, "", header, sep, ...body];
661
+ if (!hasFiveHour && !hasWeekly) {
662
+ lines.push("", `${snapshot.providerDisplayName} does not expose usage windows.`);
663
+ }
664
+ return lines.join("\n");
658
665
  }
659
666
 
660
667
  export default function (pi: ExtensionAPI) {
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@bacnh85/pi-sub",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Pi extension showing subscription usage for supported model providers.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
10
- "homepage": "https://github.com/bacnh85/skills#readme",
10
+ "homepage": "https://github.com/bacnh85/pi-extensions#readme",
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/bacnh85/skills.git",
14
- "directory": "extensions/pi-sub"
13
+ "url": "git+https://github.com/bacnh85/pi-extensions.git",
14
+ "directory": "pi-sub"
15
15
  },
16
16
  "bugs": {
17
- "url": "https://github.com/bacnh85/skills/issues"
17
+ "url": "https://github.com/bacnh85/pi-extensions/issues"
18
18
  },
19
19
  "keywords": [
20
20
  "pi-package",
@@ -26,14 +26,16 @@
26
26
  ],
27
27
  "files": [
28
28
  "README.md",
29
- "index.ts"
29
+ "extensions/"
30
30
  ],
31
31
  "pi": {
32
32
  "extensions": [
33
- "./index.ts"
33
+ "./extensions/index.ts"
34
34
  ]
35
35
  },
36
- "engines": { "node": ">=20.3.0" },
36
+ "engines": {
37
+ "node": ">=20.3.0"
38
+ },
37
39
  "peerDependencies": {
38
40
  "@earendil-works/pi-coding-agent": "*",
39
41
  "@earendil-works/pi-tui": "*"