@slkiser/opencode-quota 1.0.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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -0
  3. package/dist/data/modelsdev-pricing.min.json +504 -0
  4. package/dist/index.d.ts +10 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +15 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/lib/cache.d.ts +49 -0
  9. package/dist/lib/cache.d.ts.map +1 -0
  10. package/dist/lib/cache.js +127 -0
  11. package/dist/lib/cache.js.map +1 -0
  12. package/dist/lib/config.d.ts +30 -0
  13. package/dist/lib/config.d.ts.map +1 -0
  14. package/dist/lib/config.js +154 -0
  15. package/dist/lib/config.js.map +1 -0
  16. package/dist/lib/copilot.d.ts +25 -0
  17. package/dist/lib/copilot.d.ts.map +1 -0
  18. package/dist/lib/copilot.js +306 -0
  19. package/dist/lib/copilot.js.map +1 -0
  20. package/dist/lib/entries.d.ts +60 -0
  21. package/dist/lib/entries.d.ts.map +1 -0
  22. package/dist/lib/entries.js +8 -0
  23. package/dist/lib/entries.js.map +1 -0
  24. package/dist/lib/firmware.d.ts +15 -0
  25. package/dist/lib/firmware.d.ts.map +1 -0
  26. package/dist/lib/firmware.js +79 -0
  27. package/dist/lib/firmware.js.map +1 -0
  28. package/dist/lib/format.d.ts +16 -0
  29. package/dist/lib/format.d.ts.map +1 -0
  30. package/dist/lib/format.js +99 -0
  31. package/dist/lib/format.js.map +1 -0
  32. package/dist/lib/google-token-cache.d.ts +30 -0
  33. package/dist/lib/google-token-cache.d.ts.map +1 -0
  34. package/dist/lib/google-token-cache.js +100 -0
  35. package/dist/lib/google-token-cache.js.map +1 -0
  36. package/dist/lib/google.d.ts +43 -0
  37. package/dist/lib/google.d.ts.map +1 -0
  38. package/dist/lib/google.js +399 -0
  39. package/dist/lib/google.js.map +1 -0
  40. package/dist/lib/markdown-table.d.ts +8 -0
  41. package/dist/lib/markdown-table.d.ts.map +1 -0
  42. package/dist/lib/markdown-table.js +56 -0
  43. package/dist/lib/markdown-table.js.map +1 -0
  44. package/dist/lib/modelsdev-pricing.d.ts +23 -0
  45. package/dist/lib/modelsdev-pricing.d.ts.map +1 -0
  46. package/dist/lib/modelsdev-pricing.js +32 -0
  47. package/dist/lib/modelsdev-pricing.js.map +1 -0
  48. package/dist/lib/openai.d.ts +33 -0
  49. package/dist/lib/openai.d.ts.map +1 -0
  50. package/dist/lib/openai.js +162 -0
  51. package/dist/lib/openai.js.map +1 -0
  52. package/dist/lib/opencode-auth.d.ts +11 -0
  53. package/dist/lib/opencode-auth.d.ts.map +1 -0
  54. package/dist/lib/opencode-auth.js +27 -0
  55. package/dist/lib/opencode-auth.js.map +1 -0
  56. package/dist/lib/opencode-storage.d.ts +45 -0
  57. package/dist/lib/opencode-storage.d.ts.map +1 -0
  58. package/dist/lib/opencode-storage.js +120 -0
  59. package/dist/lib/opencode-storage.js.map +1 -0
  60. package/dist/lib/quota-command-format.d.ts +14 -0
  61. package/dist/lib/quota-command-format.d.ts.map +1 -0
  62. package/dist/lib/quota-command-format.js +122 -0
  63. package/dist/lib/quota-command-format.js.map +1 -0
  64. package/dist/lib/quota-stats-format.d.ts +9 -0
  65. package/dist/lib/quota-stats-format.d.ts.map +1 -0
  66. package/dist/lib/quota-stats-format.js +244 -0
  67. package/dist/lib/quota-stats-format.js.map +1 -0
  68. package/dist/lib/quota-stats.d.ts +71 -0
  69. package/dist/lib/quota-stats.d.ts.map +1 -0
  70. package/dist/lib/quota-stats.js +270 -0
  71. package/dist/lib/quota-stats.js.map +1 -0
  72. package/dist/lib/quota-status.d.ts +23 -0
  73. package/dist/lib/quota-status.d.ts.map +1 -0
  74. package/dist/lib/quota-status.js +112 -0
  75. package/dist/lib/quota-status.js.map +1 -0
  76. package/dist/lib/toast-format-grouped.d.ts +25 -0
  77. package/dist/lib/toast-format-grouped.d.ts.map +1 -0
  78. package/dist/lib/toast-format-grouped.js +123 -0
  79. package/dist/lib/toast-format-grouped.js.map +1 -0
  80. package/dist/lib/types.d.ts +218 -0
  81. package/dist/lib/types.d.ts.map +1 -0
  82. package/dist/lib/types.js +39 -0
  83. package/dist/lib/types.js.map +1 -0
  84. package/dist/plugin.d.ts +13 -0
  85. package/dist/plugin.d.ts.map +1 -0
  86. package/dist/plugin.js +633 -0
  87. package/dist/plugin.js.map +1 -0
  88. package/dist/providers/copilot.d.ts +8 -0
  89. package/dist/providers/copilot.d.ts.map +1 -0
  90. package/dist/providers/copilot.js +50 -0
  91. package/dist/providers/copilot.js.map +1 -0
  92. package/dist/providers/firmware.d.ts +6 -0
  93. package/dist/providers/firmware.d.ts.map +1 -0
  94. package/dist/providers/firmware.js +52 -0
  95. package/dist/providers/firmware.js.map +1 -0
  96. package/dist/providers/google-antigravity.d.ts +6 -0
  97. package/dist/providers/google-antigravity.d.ts.map +1 -0
  98. package/dist/providers/google-antigravity.js +77 -0
  99. package/dist/providers/google-antigravity.js.map +1 -0
  100. package/dist/providers/openai.d.ts +6 -0
  101. package/dist/providers/openai.d.ts.map +1 -0
  102. package/dist/providers/openai.js +106 -0
  103. package/dist/providers/openai.js.map +1 -0
  104. package/dist/providers/registry.d.ts +8 -0
  105. package/dist/providers/registry.d.ts.map +1 -0
  106. package/dist/providers/registry.js +14 -0
  107. package/dist/providers/registry.js.map +1 -0
  108. package/package.json +71 -0
@@ -0,0 +1,23 @@
1
+ export type CostBuckets = {
2
+ input?: number;
3
+ output?: number;
4
+ cache_read?: number;
5
+ cache_write?: number;
6
+ reasoning?: number;
7
+ };
8
+ type Snapshot = {
9
+ _meta: {
10
+ source: string;
11
+ generatedAt: number;
12
+ providers: string[];
13
+ units: string;
14
+ };
15
+ providers: Record<string, Record<string, CostBuckets>>;
16
+ };
17
+ export declare function getPricingSnapshotMeta(): Snapshot["_meta"];
18
+ export declare function hasProvider(providerId: string): boolean;
19
+ export declare function getProviderModelCount(providerId: string): number;
20
+ export declare function listProviders(): string[];
21
+ export declare function lookupCost(providerId: string, modelId: string): CostBuckets | null;
22
+ export {};
23
+ //# sourceMappingURL=modelsdev-pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelsdev-pricing.d.ts","sourceRoot":"","sources":["../../src/lib/modelsdev-pricing.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CACxD,CAAC;AAYF,wBAAgB,sBAAsB,IAAI,QAAQ,CAAC,OAAO,CAAC,CAE1D;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAMlF"}
@@ -0,0 +1,32 @@
1
+ import { readFileSync } from "fs";
2
+ let SNAPSHOT = null;
3
+ function ensureLoaded() {
4
+ if (SNAPSHOT)
5
+ return SNAPSHOT;
6
+ const url = new URL("../data/modelsdev-pricing.min.json", import.meta.url);
7
+ const raw = readFileSync(url, "utf-8");
8
+ SNAPSHOT = JSON.parse(raw);
9
+ return SNAPSHOT;
10
+ }
11
+ export function getPricingSnapshotMeta() {
12
+ return ensureLoaded()._meta;
13
+ }
14
+ export function hasProvider(providerId) {
15
+ return !!ensureLoaded().providers[providerId];
16
+ }
17
+ export function getProviderModelCount(providerId) {
18
+ return Object.keys(ensureLoaded().providers[providerId] || {}).length;
19
+ }
20
+ export function listProviders() {
21
+ return Object.keys(ensureLoaded().providers);
22
+ }
23
+ export function lookupCost(providerId, modelId) {
24
+ const p = ensureLoaded().providers[providerId];
25
+ if (!p)
26
+ return null;
27
+ const c = p[modelId];
28
+ if (!c)
29
+ return null;
30
+ return c;
31
+ }
32
+ //# sourceMappingURL=modelsdev-pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelsdev-pricing.js","sourceRoot":"","sources":["../../src/lib/modelsdev-pricing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAoBlC,IAAI,QAAQ,GAAoB,IAAI,CAAC;AAErC,SAAS,YAAY;IACnB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,oCAAoC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3E,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;IACvC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,YAAY,EAAE,CAAC,KAAK,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,UAAkB;IAC5C,OAAO,CAAC,CAAC,YAAY,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACtD,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,SAAS,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,UAAkB,EAAE,OAAe;IAC5D,MAAM,CAAC,GAAG,YAAY,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IACrB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * OpenAI (ChatGPT) quota fetcher
3
+ *
4
+ * Uses OpenCode's auth.json (openai oauth) and queries:
5
+ * https://chatgpt.com/backend-api/wham/usage
6
+ */
7
+ import type { QuotaError } from "./types.js";
8
+ export type OpenAIResult = {
9
+ success: true;
10
+ label: string;
11
+ email?: string;
12
+ windows: {
13
+ hourly?: {
14
+ percentRemaining: number;
15
+ resetTimeIso?: string;
16
+ };
17
+ weekly?: {
18
+ percentRemaining: number;
19
+ resetTimeIso?: string;
20
+ };
21
+ codeReview?: {
22
+ percentRemaining: number;
23
+ resetTimeIso?: string;
24
+ };
25
+ };
26
+ credits?: {
27
+ hasCredits: boolean;
28
+ unlimited: boolean;
29
+ balance: string | null;
30
+ };
31
+ } | QuotaError | null;
32
+ export declare function queryOpenAIQuota(): Promise<OpenAIResult>;
33
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/lib/openai.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,YAAY,CAAC;AA6GvD,MAAM,MAAM,YAAY,GACpB;IACE,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QACP,MAAM,CAAC,EAAE;YAAE,gBAAgB,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7D,MAAM,CAAC,EAAE;YAAE,gBAAgB,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7D,UAAU,CAAC,EAAE;YAAE,gBAAgB,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAClE,CAAC;IACF,OAAO,CAAC,EAAE;QACR,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;CACH,GACD,UAAU,GACV,IAAI,CAAC;AAgBT,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC,CAmF9D"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * OpenAI (ChatGPT) quota fetcher
3
+ *
4
+ * Uses OpenCode's auth.json (openai oauth) and queries:
5
+ * https://chatgpt.com/backend-api/wham/usage
6
+ */
7
+ import { REQUEST_TIMEOUT_MS } from "./types.js";
8
+ import { readAuthFile } from "./opencode-auth.js";
9
+ function base64UrlDecode(input) {
10
+ const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
11
+ const padLen = (4 - (base64.length % 4)) % 4;
12
+ const padded = base64 + "=".repeat(padLen);
13
+ return Buffer.from(padded, "base64").toString("utf8");
14
+ }
15
+ function parseJwt(token) {
16
+ try {
17
+ const parts = token.split(".");
18
+ if (parts.length !== 3)
19
+ return null;
20
+ return JSON.parse(base64UrlDecode(parts[1]));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ function getEmailFromJwt(token) {
27
+ return parseJwt(token)?.["https://api.openai.com/profile"]?.email ?? null;
28
+ }
29
+ function getAccountIdFromJwt(token) {
30
+ return parseJwt(token)?.["https://api.openai.com/auth"]?.chatgpt_account_id ?? null;
31
+ }
32
+ function clampPercent(n) {
33
+ if (!Number.isFinite(n))
34
+ return 0;
35
+ return Math.max(0, Math.min(100, Math.round(n)));
36
+ }
37
+ function remainingPercent(window) {
38
+ return clampPercent(100 - window.used_percent);
39
+ }
40
+ function resetIsoFromNowSeconds(seconds) {
41
+ if (!Number.isFinite(seconds) || seconds <= 0)
42
+ return undefined;
43
+ return new Date(Date.now() + Math.round(seconds * 1000)).toISOString();
44
+ }
45
+ function resetIsoFromResetAt(resetAt) {
46
+ if (!Number.isFinite(resetAt) || !resetAt)
47
+ return undefined;
48
+ const ms = Math.round(resetAt * 1000);
49
+ if (!Number.isFinite(ms) || ms <= 0)
50
+ return undefined;
51
+ return new Date(ms).toISOString();
52
+ }
53
+ function derivePlanLabel(planType) {
54
+ const raw = (planType ?? "").toLowerCase();
55
+ if (raw.includes("pro"))
56
+ return "OpenAI (Pro)";
57
+ if (raw.includes("plus"))
58
+ return "OpenAI (Plus)";
59
+ if (planType)
60
+ return `OpenAI (${planType})`;
61
+ return "OpenAI";
62
+ }
63
+ async function fetchWithTimeout(url, options) {
64
+ const controller = new AbortController();
65
+ const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
66
+ try {
67
+ return await fetch(url, { ...options, signal: controller.signal });
68
+ }
69
+ catch (err) {
70
+ if (err instanceof Error && err.name === "AbortError") {
71
+ throw new Error(`Request timeout after ${Math.round(REQUEST_TIMEOUT_MS / 1000)}s`);
72
+ }
73
+ throw err;
74
+ }
75
+ finally {
76
+ clearTimeout(timeoutId);
77
+ }
78
+ }
79
+ const OPENAI_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
80
+ async function readOpenAIAuth() {
81
+ const auth = await readAuthFile();
82
+ const openai = auth?.codex ?? auth?.openai;
83
+ if (!openai || openai.type !== "oauth" || !openai.access)
84
+ return null;
85
+ return openai;
86
+ }
87
+ export async function queryOpenAIQuota() {
88
+ const auth = await readOpenAIAuth();
89
+ if (!auth)
90
+ return null;
91
+ if (auth.expires && auth.expires < Date.now()) {
92
+ return { success: false, error: "Token expired" };
93
+ }
94
+ try {
95
+ const headers = {
96
+ Authorization: `Bearer ${auth.access}`,
97
+ "User-Agent": "OpenCode-Quota-Toast/1.0",
98
+ };
99
+ const accountId = getAccountIdFromJwt(auth.access);
100
+ if (accountId) {
101
+ headers["ChatGPT-Account-Id"] = accountId;
102
+ }
103
+ const resp = await fetchWithTimeout(OPENAI_USAGE_URL, { headers });
104
+ if (!resp.ok) {
105
+ const text = await resp.text();
106
+ return {
107
+ success: false,
108
+ error: `OpenAI API error ${resp.status}: ${text.slice(0, 120)}`,
109
+ };
110
+ }
111
+ const data = (await resp.json());
112
+ const primary = data.rate_limit?.primary_window;
113
+ const secondary = data.rate_limit?.secondary_window ?? null;
114
+ const codeReview = data.code_review_rate_limit?.primary_window ?? null;
115
+ const credits = data.credits ?? null;
116
+ if (!primary)
117
+ return { success: false, error: "No quota data" };
118
+ const hourlyRemain = remainingPercent(primary);
119
+ const weeklyRemain = secondary ? remainingPercent(secondary) : undefined;
120
+ const codeReviewRemain = codeReview ? remainingPercent(codeReview) : undefined;
121
+ const hourlyResetIso = resetIsoFromResetAt(primary.reset_at) ?? resetIsoFromNowSeconds(primary.reset_after_seconds);
122
+ const weeklyResetIso = secondary
123
+ ? (resetIsoFromResetAt(secondary.reset_at) ??
124
+ resetIsoFromNowSeconds(secondary.reset_after_seconds))
125
+ : undefined;
126
+ const codeReviewResetIso = codeReview
127
+ ? (resetIsoFromResetAt(codeReview.reset_at) ??
128
+ resetIsoFromNowSeconds(codeReview.reset_after_seconds))
129
+ : undefined;
130
+ return {
131
+ success: true,
132
+ label: derivePlanLabel(data.plan_type),
133
+ email: getEmailFromJwt(auth.access) ?? undefined,
134
+ windows: {
135
+ hourly: { percentRemaining: clampPercent(hourlyRemain), resetTimeIso: hourlyResetIso },
136
+ weekly: weeklyRemain === undefined
137
+ ? undefined
138
+ : { percentRemaining: clampPercent(weeklyRemain), resetTimeIso: weeklyResetIso },
139
+ codeReview: codeReviewRemain === undefined
140
+ ? undefined
141
+ : {
142
+ percentRemaining: clampPercent(codeReviewRemain),
143
+ resetTimeIso: codeReviewResetIso,
144
+ },
145
+ },
146
+ credits: credits
147
+ ? {
148
+ hasCredits: Boolean(credits.has_credits),
149
+ unlimited: Boolean(credits.unlimited),
150
+ balance: credits.balance ?? null,
151
+ }
152
+ : undefined,
153
+ };
154
+ }
155
+ catch (err) {
156
+ return {
157
+ success: false,
158
+ error: err instanceof Error ? err.message : String(err),
159
+ };
160
+ }
161
+ }
162
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/lib/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * OpenCode auth.json reader
3
+ *
4
+ * Shared helper to read auth from ~/.local/share/opencode/auth.json
5
+ * (or platform equivalent). Providers should prefer this to duplicating
6
+ * file/path parsing.
7
+ */
8
+ import type { AuthData } from "./types.js";
9
+ export declare function getAuthPath(): string;
10
+ export declare function readAuthFile(): Promise<AuthData | null>;
11
+ //# sourceMappingURL=opencode-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-auth.d.ts","sourceRoot":"","sources":["../../src/lib/opencode-auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAO7D"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * OpenCode auth.json reader
3
+ *
4
+ * Shared helper to read auth from ~/.local/share/opencode/auth.json
5
+ * (or platform equivalent). Providers should prefer this to duplicating
6
+ * file/path parsing.
7
+ */
8
+ import { readFile } from "fs/promises";
9
+ import { homedir } from "os";
10
+ import { join } from "path";
11
+ export function getAuthPath() {
12
+ const home = homedir();
13
+ const dataDir = process.platform === "win32"
14
+ ? process.env.LOCALAPPDATA || join(home, "AppData", "Local")
15
+ : join(home, ".local", "share");
16
+ return join(dataDir, "opencode", "auth.json");
17
+ }
18
+ export async function readAuthFile() {
19
+ try {
20
+ const content = await readFile(getAuthPath(), "utf-8");
21
+ return JSON.parse(content);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ //# sourceMappingURL=opencode-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-auth.js","sourceRoot":"","sources":["../../src/lib/opencode-auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,OAAO,GACX,OAAO,CAAC,QAAQ,KAAK,OAAO;QAC1B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC;QAC5D,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAa,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,45 @@
1
+ export interface OpenCodeTokenCache {
2
+ read: number;
3
+ write: number;
4
+ }
5
+ export interface OpenCodeTokens {
6
+ input: number;
7
+ output: number;
8
+ reasoning?: number;
9
+ cache: OpenCodeTokenCache;
10
+ }
11
+ export interface OpenCodeMessage {
12
+ id: string;
13
+ sessionID: string;
14
+ role: "user" | "assistant" | string;
15
+ providerID?: string;
16
+ modelID?: string;
17
+ tokens?: OpenCodeTokens;
18
+ cost?: number;
19
+ time?: {
20
+ created?: number;
21
+ completed?: number;
22
+ };
23
+ agent?: string;
24
+ mode?: string;
25
+ }
26
+ export interface OpenCodeSessionInfo {
27
+ id: string;
28
+ title?: string;
29
+ parentID?: string;
30
+ time?: {
31
+ created?: number;
32
+ updated?: number;
33
+ };
34
+ }
35
+ export declare function getOpenCodeDataDir(): string;
36
+ export declare function getOpenCodeStorageDir(): string;
37
+ export declare function getOpenCodeMessageDir(): string;
38
+ export declare function getOpenCodeSessionDir(): string;
39
+ export declare function listSessionIDsFromMessageStorage(): Promise<string[]>;
40
+ export declare function iterAssistantMessages(params: {
41
+ sinceMs?: number;
42
+ untilMs?: number;
43
+ }): Promise<OpenCodeMessage[]>;
44
+ export declare function readAllSessionsIndex(): Promise<Record<string, OpenCodeSessionInfo>>;
45
+ //# sourceMappingURL=opencode-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-storage.d.ts","sourceRoot":"","sources":["../../src/lib/opencode-storage.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,kBAAkB,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAWD,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAY1E;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA+B7B;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAoCzF"}
@@ -0,0 +1,120 @@
1
+ import { readdir, readFile } from "fs/promises";
2
+ import { homedir } from "os";
3
+ import { join } from "path";
4
+ import { existsSync } from "fs";
5
+ export function getOpenCodeDataDir() {
6
+ const home = homedir();
7
+ if (process.platform === "win32") {
8
+ return process.env.LOCALAPPDATA || join(home, "AppData", "Local");
9
+ }
10
+ return join(home, ".local", "share");
11
+ }
12
+ export function getOpenCodeStorageDir() {
13
+ return join(getOpenCodeDataDir(), "opencode", "storage");
14
+ }
15
+ export function getOpenCodeMessageDir() {
16
+ return join(getOpenCodeStorageDir(), "message");
17
+ }
18
+ export function getOpenCodeSessionDir() {
19
+ return join(getOpenCodeStorageDir(), "session");
20
+ }
21
+ async function safeReadJson(path) {
22
+ try {
23
+ const raw = await readFile(path, "utf-8");
24
+ return JSON.parse(raw);
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ export async function listSessionIDsFromMessageStorage() {
31
+ const base = getOpenCodeMessageDir();
32
+ if (!existsSync(base))
33
+ return [];
34
+ try {
35
+ const entries = await readdir(base, { withFileTypes: true });
36
+ return entries
37
+ .filter((e) => e.isDirectory() && e.name.startsWith("ses_"))
38
+ .map((e) => e.name)
39
+ .sort();
40
+ }
41
+ catch {
42
+ return [];
43
+ }
44
+ }
45
+ export async function iterAssistantMessages(params) {
46
+ const base = getOpenCodeMessageDir();
47
+ if (!existsSync(base))
48
+ return [];
49
+ const sessionIDs = await listSessionIDsFromMessageStorage();
50
+ const out = [];
51
+ for (const sessionID of sessionIDs) {
52
+ const dir = join(base, sessionID);
53
+ let files;
54
+ try {
55
+ files = (await readdir(dir)).filter((f) => f.endsWith(".json"));
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ for (const f of files) {
61
+ const p = join(dir, f);
62
+ const msg = (await safeReadJson(p));
63
+ if (!msg)
64
+ continue;
65
+ if (msg.role !== "assistant")
66
+ continue;
67
+ const created = msg.time?.created;
68
+ if (typeof created !== "number")
69
+ continue;
70
+ if (typeof params.sinceMs === "number" && created < params.sinceMs)
71
+ continue;
72
+ if (typeof params.untilMs === "number" && created > params.untilMs)
73
+ continue;
74
+ out.push(msg);
75
+ }
76
+ }
77
+ out.sort((a, b) => (a.time?.created ?? 0) - (b.time?.created ?? 0));
78
+ return out;
79
+ }
80
+ export async function readAllSessionsIndex() {
81
+ const base = getOpenCodeSessionDir();
82
+ const idx = {};
83
+ if (!existsSync(base))
84
+ return idx;
85
+ async function visit(dir) {
86
+ let entries;
87
+ try {
88
+ entries = await readdir(dir, { withFileTypes: true });
89
+ }
90
+ catch {
91
+ return;
92
+ }
93
+ for (const e of entries) {
94
+ const p = join(dir, e.name);
95
+ if (e.isDirectory()) {
96
+ await visit(p);
97
+ }
98
+ else if (e.isFile() && e.name.startsWith("ses_") && e.name.endsWith(".json")) {
99
+ const data = await safeReadJson(p);
100
+ if (!data || typeof data !== "object")
101
+ continue;
102
+ const id = data.id;
103
+ if (typeof id !== "string" || !id.startsWith("ses_"))
104
+ continue;
105
+ idx[id] = {
106
+ id,
107
+ title: typeof data.title === "string" ? data.title : undefined,
108
+ parentID: typeof data.parentID === "string" ? data.parentID : undefined,
109
+ time: {
110
+ created: typeof data.time?.created === "number" ? data.time.created : undefined,
111
+ updated: typeof data.time?.updated === "number" ? data.time.updated : undefined,
112
+ },
113
+ };
114
+ }
115
+ }
116
+ }
117
+ await visit(base);
118
+ return idx;
119
+ }
120
+ //# sourceMappingURL=opencode-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-storage.js","sourceRoot":"","sources":["../../src/lib/opencode-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Verbose quota status formatter for /quota.
3
+ *
4
+ * This is intentionally more verbose than the toast:
5
+ * - Always shows reset countdown when available
6
+ * - Uses one line per limit, grouped under provider headers
7
+ */
8
+ import type { QuotaToastError } from "./entries.js";
9
+ import type { ToastGroupEntry } from "./toast-format-grouped.js";
10
+ export declare function formatQuotaCommand(params: {
11
+ entries: ToastGroupEntry[];
12
+ errors: QuotaToastError[];
13
+ }): string;
14
+ //# sourceMappingURL=quota-command-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-command-format.d.ts","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAuEjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,GAAG,MAAM,CAqDT"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Verbose quota status formatter for /quota.
3
+ *
4
+ * This is intentionally more verbose than the toast:
5
+ * - Always shows reset countdown when available
6
+ * - Uses one line per limit, grouped under provider headers
7
+ */
8
+ function clampInt(n, min, max) {
9
+ return Math.max(min, Math.min(max, Math.trunc(n)));
10
+ }
11
+ function formatResetTimeSeconds(diffSeconds) {
12
+ if (!Number.isFinite(diffSeconds) || diffSeconds <= 0)
13
+ return "now";
14
+ if (diffSeconds < 60)
15
+ return `${Math.ceil(diffSeconds)}s`;
16
+ if (diffSeconds < 3600)
17
+ return `${Math.ceil(diffSeconds / 60)}m`;
18
+ if (diffSeconds < 86400)
19
+ return `${Math.round(diffSeconds / 3600)}h`;
20
+ return `${Math.round(diffSeconds / 86400)}d`;
21
+ }
22
+ function formatResetsIn(iso) {
23
+ if (!iso)
24
+ return "";
25
+ const t = new Date(iso).getTime();
26
+ if (!Number.isFinite(t))
27
+ return "";
28
+ const diffSeconds = (t - Date.now()) / 1000;
29
+ return ` (resets in ${formatResetTimeSeconds(diffSeconds)})`;
30
+ }
31
+ function bar(percentRemaining, width) {
32
+ const p = clampInt(percentRemaining, 0, 100);
33
+ const filled = Math.round((p / 100) * width);
34
+ const empty = width - filled;
35
+ return "█".repeat(filled) + "░".repeat(empty);
36
+ }
37
+ function padRight(str, width) {
38
+ if (str.length >= width)
39
+ return str.slice(0, width);
40
+ return str + " ".repeat(width - str.length);
41
+ }
42
+ function normalizeGroupHeader(group) {
43
+ // Convert "OpenAI (Pro)" -> "[OpenAI] (Pro)" for competitor-like headers.
44
+ const m = group.match(/^([^()]+?)\s*(\(.*\))\s*$/);
45
+ if (m)
46
+ return `[${m[1].trim()}] ${m[2].trim()}`;
47
+ return `[${group.trim()}]`;
48
+ }
49
+ function looksLikeGoogleModel(label) {
50
+ const x = label.toLowerCase();
51
+ return x === "claude" || x === "g3pro" || x === "g3flash" || x === "g3image";
52
+ }
53
+ function coerceGrouped(entries) {
54
+ const out = [];
55
+ for (const e of entries) {
56
+ if (e.group) {
57
+ out.push(e);
58
+ continue;
59
+ }
60
+ // Heuristic for Google entries currently named like "Claude (abc..gmail)".
61
+ const m = e.name.match(/^(.+?)\s*\((.+)\)\s*$/);
62
+ if (m && looksLikeGoogleModel(m[1].trim())) {
63
+ out.push({
64
+ ...e,
65
+ group: `Google Antigravity (${m[2].trim()})`,
66
+ label: `${m[1].trim()}:`,
67
+ });
68
+ continue;
69
+ }
70
+ // Default: treat the whole name as one grouped row.
71
+ out.push({ ...e, group: e.name, label: "Status:" });
72
+ }
73
+ return out;
74
+ }
75
+ export function formatQuotaCommand(params) {
76
+ const entries = coerceGrouped(params.entries);
77
+ const groupOrder = [];
78
+ const groups = new Map();
79
+ for (const e of entries) {
80
+ const g = (e.group ?? "").trim();
81
+ if (!g)
82
+ continue;
83
+ const list = groups.get(g);
84
+ if (list)
85
+ list.push(e);
86
+ else {
87
+ groupOrder.push(g);
88
+ groups.set(g, [e]);
89
+ }
90
+ }
91
+ const lines = [];
92
+ lines.push("▣ Quota");
93
+ const barWidth = 18;
94
+ const leftCol = 12;
95
+ for (let i = 0; i < groupOrder.length; i++) {
96
+ const g = groupOrder[i];
97
+ const list = groups.get(g) ?? [];
98
+ lines.push("");
99
+ lines.push(`→ ${normalizeGroupHeader(g)}`);
100
+ for (const row of list) {
101
+ const label = (row.label ?? row.name).trim();
102
+ const labelCol = padRight(label, leftCol);
103
+ const pct = clampInt(row.percentRemaining, 0, 100);
104
+ const suffix = formatResetsIn(row.resetTimeIso);
105
+ lines.push(` ${labelCol} ${bar(pct, barWidth)} ${pct}% left${suffix}`);
106
+ }
107
+ if (i < groupOrder.length - 1) {
108
+ lines.push("");
109
+ lines.push("---");
110
+ }
111
+ }
112
+ if (params.errors.length > 0) {
113
+ lines.push("");
114
+ lines.push("---");
115
+ lines.push("");
116
+ for (const err of params.errors) {
117
+ lines.push(`${err.label}: ${err.message}`);
118
+ }
119
+ }
120
+ return lines.join("\n");
121
+ }
122
+ //# sourceMappingURL=quota-command-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-command-format.js","sourceRoot":"","sources":["../../src/lib/quota-command-format.ts"],"names":[],"mappings":"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"}