@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,49 @@
1
+ /**
2
+ * Cache and throttling system for quota fetching
3
+ *
4
+ * Implements:
5
+ * - Throttling: Only fetch if minIntervalMs has passed since last fetch
6
+ * - Caching: Store last toast message for immediate display
7
+ * - Deduplication: Use inFlightPromise to prevent concurrent fetches
8
+ */
9
+ /**
10
+ * Get the cached toast message if still valid
11
+ *
12
+ * @param minIntervalMs - Minimum interval between fetches
13
+ * @returns Cached message or null if stale/missing
14
+ */
15
+ export declare function getCachedToast(minIntervalMs: number): string | null;
16
+ /**
17
+ * Check if a new fetch should be initiated
18
+ *
19
+ * @param minIntervalMs - Minimum interval between fetches
20
+ * @returns true if a fetch should be started
21
+ */
22
+ export declare function shouldFetch(minIntervalMs: number): boolean;
23
+ /**
24
+ * Get or start a fetch operation with deduplication
25
+ *
26
+ * @param fetchFn - Function that performs the actual fetch
27
+ * @param minIntervalMs - Minimum interval between fetches
28
+ * @returns Promise resolving to toast message or null
29
+ */
30
+ export declare function getOrFetch(fetchFn: () => Promise<string | null>, minIntervalMs: number): Promise<string | null>;
31
+ /**
32
+ * Get or start a fetch operation with deduplication and cache control.
33
+ *
34
+ * This is useful when some results should be displayed but not cached
35
+ * (e.g. transient "all providers failed" cases).
36
+ */
37
+ export declare function getOrFetchWithCacheControl(fetchFn: () => Promise<{
38
+ message: string | null;
39
+ cache?: boolean;
40
+ }>, minIntervalMs: number): Promise<string | null>;
41
+ /**
42
+ * Clear the cache (for testing or reset)
43
+ */
44
+ export declare function clearCache(): void;
45
+ /**
46
+ * Force update the cache with a new message
47
+ */
48
+ export declare function updateCache(message: string): void;
49
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcnE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EACrC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EACnE,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqDxB;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAIjC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKjD"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Cache and throttling system for quota fetching
3
+ *
4
+ * Implements:
5
+ * - Throttling: Only fetch if minIntervalMs has passed since last fetch
6
+ * - Caching: Store last toast message for immediate display
7
+ * - Deduplication: Use inFlightPromise to prevent concurrent fetches
8
+ */
9
+ /** Cached toast data */
10
+ let cachedToast = null;
11
+ /** In-flight promise for deduplication */
12
+ let inFlightPromise = null;
13
+ /** Timestamp of last fetch start */
14
+ let lastFetchTime = 0;
15
+ /**
16
+ * Get the cached toast message if still valid
17
+ *
18
+ * @param minIntervalMs - Minimum interval between fetches
19
+ * @returns Cached message or null if stale/missing
20
+ */
21
+ export function getCachedToast(minIntervalMs) {
22
+ if (!cachedToast) {
23
+ return null;
24
+ }
25
+ const now = Date.now();
26
+ const age = now - cachedToast.timestamp;
27
+ // Return cached value if within throttle window
28
+ if (age < minIntervalMs) {
29
+ return cachedToast.message;
30
+ }
31
+ return null;
32
+ }
33
+ /**
34
+ * Check if a new fetch should be initiated
35
+ *
36
+ * @param minIntervalMs - Minimum interval between fetches
37
+ * @returns true if a fetch should be started
38
+ */
39
+ export function shouldFetch(minIntervalMs) {
40
+ const now = Date.now();
41
+ return now - lastFetchTime >= minIntervalMs;
42
+ }
43
+ /**
44
+ * Get or start a fetch operation with deduplication
45
+ *
46
+ * @param fetchFn - Function that performs the actual fetch
47
+ * @param minIntervalMs - Minimum interval between fetches
48
+ * @returns Promise resolving to toast message or null
49
+ */
50
+ export async function getOrFetch(fetchFn, minIntervalMs) {
51
+ const wrapped = async () => {
52
+ const message = await fetchFn();
53
+ return { message, cache: true };
54
+ };
55
+ return getOrFetchWithCacheControl(wrapped, minIntervalMs);
56
+ }
57
+ /**
58
+ * Get or start a fetch operation with deduplication and cache control.
59
+ *
60
+ * This is useful when some results should be displayed but not cached
61
+ * (e.g. transient "all providers failed" cases).
62
+ */
63
+ export async function getOrFetchWithCacheControl(fetchFn, minIntervalMs) {
64
+ // Check cache first
65
+ const cached = getCachedToast(minIntervalMs);
66
+ if (cached !== null) {
67
+ return cached;
68
+ }
69
+ // If there's already a fetch in progress, wait for it
70
+ if (inFlightPromise) {
71
+ return inFlightPromise;
72
+ }
73
+ // Check if we should start a new fetch
74
+ if (!shouldFetch(minIntervalMs)) {
75
+ // Within throttle window but cache is empty/stale
76
+ // Return cached message anyway if available
77
+ return cachedToast?.message ?? null;
78
+ }
79
+ // Start a new fetch
80
+ lastFetchTime = Date.now();
81
+ inFlightPromise = (async () => {
82
+ try {
83
+ const out = await fetchFn();
84
+ const result = out.message;
85
+ const cache = out.cache ?? true;
86
+ // If there is no message, don't throttle future fetches.
87
+ // This is important when users enable providers or connect accounts and
88
+ // want the toast to appear on the next trigger.
89
+ if (result === null) {
90
+ lastFetchTime = 0;
91
+ return null;
92
+ }
93
+ if (!cache) {
94
+ // Display, but don't cache or throttle the next attempt.
95
+ lastFetchTime = 0;
96
+ return result;
97
+ }
98
+ cachedToast = {
99
+ message: result,
100
+ timestamp: Date.now(),
101
+ };
102
+ return result;
103
+ }
104
+ finally {
105
+ inFlightPromise = null;
106
+ }
107
+ })();
108
+ return inFlightPromise;
109
+ }
110
+ /**
111
+ * Clear the cache (for testing or reset)
112
+ */
113
+ export function clearCache() {
114
+ cachedToast = null;
115
+ inFlightPromise = null;
116
+ lastFetchTime = 0;
117
+ }
118
+ /**
119
+ * Force update the cache with a new message
120
+ */
121
+ export function updateCache(message) {
122
+ cachedToast = {
123
+ message,
124
+ timestamp: Date.now(),
125
+ };
126
+ }
127
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Configuration loader for opencode-quota plugin
3
+ *
4
+ * Primary: reads configuration from OpenCode's merged config via the SDK client.
5
+ * Fallback: reads local config files directly.
6
+ */
7
+ import type { QuotaToastConfig } from "./types.js";
8
+ export interface LoadConfigMeta {
9
+ source: "sdk" | "files" | "defaults";
10
+ paths: string[];
11
+ }
12
+ export declare function createLoadConfigMeta(): LoadConfigMeta;
13
+ /**
14
+ * Load plugin configuration from OpenCode config
15
+ *
16
+ * @param client - OpenCode SDK client
17
+ * @returns Merged configuration with defaults
18
+ */
19
+ export declare function loadConfig(client: {
20
+ config: {
21
+ get: () => Promise<{
22
+ data?: {
23
+ experimental?: {
24
+ quotaToast?: Partial<QuotaToastConfig>;
25
+ };
26
+ };
27
+ }>;
28
+ };
29
+ }, meta?: LoadConfigMeta): Promise<QuotaToastConfig>;
30
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,YAAY,CAAC;AAQlE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AASD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE;IACN,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,OAAO,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,YAAY,CAAC,EAAE;oBAAE,UAAU,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;iBAAE,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAC9F,CAAC;CACH,EACD,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAiK3B"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Configuration loader for opencode-quota plugin
3
+ *
4
+ * Primary: reads configuration from OpenCode's merged config via the SDK client.
5
+ * Fallback: reads local config files directly.
6
+ */
7
+ import { DEFAULT_CONFIG } from "./types.js";
8
+ import { existsSync } from "fs";
9
+ import { readFile } from "fs/promises";
10
+ import { homedir } from "os";
11
+ import { join } from "path";
12
+ export function createLoadConfigMeta() {
13
+ return { source: "defaults", paths: [] };
14
+ }
15
+ /**
16
+ * Validates and normalizes a Google model ID
17
+ */
18
+ function isValidGoogleModelId(id) {
19
+ return typeof id === "string" && ["G3PRO", "G3FLASH", "CLAUDE", "G3IMAGE"].includes(id);
20
+ }
21
+ /**
22
+ * Load plugin configuration from OpenCode config
23
+ *
24
+ * @param client - OpenCode SDK client
25
+ * @returns Merged configuration with defaults
26
+ */
27
+ export async function loadConfig(client, meta) {
28
+ function normalize(quotaToastConfig) {
29
+ if (!quotaToastConfig)
30
+ return DEFAULT_CONFIG;
31
+ const config = {
32
+ enabled: typeof quotaToastConfig.enabled === "boolean"
33
+ ? quotaToastConfig.enabled
34
+ : DEFAULT_CONFIG.enabled,
35
+ enableToast: typeof quotaToastConfig.enableToast === "boolean"
36
+ ? quotaToastConfig.enableToast
37
+ : DEFAULT_CONFIG.enableToast,
38
+ toastStyle: quotaToastConfig.toastStyle === "grouped" || quotaToastConfig.toastStyle === "classic"
39
+ ? quotaToastConfig.toastStyle
40
+ : DEFAULT_CONFIG.toastStyle,
41
+ minIntervalMs: typeof quotaToastConfig.minIntervalMs === "number" && quotaToastConfig.minIntervalMs > 0
42
+ ? quotaToastConfig.minIntervalMs
43
+ : DEFAULT_CONFIG.minIntervalMs,
44
+ debug: typeof quotaToastConfig.debug === "boolean" ? quotaToastConfig.debug : DEFAULT_CONFIG.debug,
45
+ enabledProviders: Array.isArray(quotaToastConfig.enabledProviders)
46
+ ? quotaToastConfig.enabledProviders.filter((p) => typeof p === "string")
47
+ : DEFAULT_CONFIG.enabledProviders,
48
+ googleModels: Array.isArray(quotaToastConfig.googleModels)
49
+ ? quotaToastConfig.googleModels.filter(isValidGoogleModelId)
50
+ : DEFAULT_CONFIG.googleModels,
51
+ showOnIdle: typeof quotaToastConfig.showOnIdle === "boolean"
52
+ ? quotaToastConfig.showOnIdle
53
+ : DEFAULT_CONFIG.showOnIdle,
54
+ showOnQuestion: typeof quotaToastConfig.showOnQuestion === "boolean"
55
+ ? quotaToastConfig.showOnQuestion
56
+ : DEFAULT_CONFIG.showOnQuestion,
57
+ showOnCompact: typeof quotaToastConfig.showOnCompact === "boolean"
58
+ ? quotaToastConfig.showOnCompact
59
+ : DEFAULT_CONFIG.showOnCompact,
60
+ showOnBothFail: typeof quotaToastConfig.showOnBothFail === "boolean"
61
+ ? quotaToastConfig.showOnBothFail
62
+ : DEFAULT_CONFIG.showOnBothFail,
63
+ toastDurationMs: typeof quotaToastConfig.toastDurationMs === "number" && quotaToastConfig.toastDurationMs > 0
64
+ ? quotaToastConfig.toastDurationMs
65
+ : DEFAULT_CONFIG.toastDurationMs,
66
+ onlyCurrentModel: typeof quotaToastConfig.onlyCurrentModel === "boolean"
67
+ ? quotaToastConfig.onlyCurrentModel
68
+ : DEFAULT_CONFIG.onlyCurrentModel,
69
+ layout: {
70
+ maxWidth: typeof quotaToastConfig.layout?.maxWidth === "number" &&
71
+ quotaToastConfig.layout.maxWidth > 0
72
+ ? quotaToastConfig.layout.maxWidth
73
+ : DEFAULT_CONFIG.layout.maxWidth,
74
+ narrowAt: typeof quotaToastConfig.layout?.narrowAt === "number" &&
75
+ quotaToastConfig.layout.narrowAt > 0
76
+ ? quotaToastConfig.layout.narrowAt
77
+ : DEFAULT_CONFIG.layout.narrowAt,
78
+ tinyAt: typeof quotaToastConfig.layout?.tinyAt === "number" && quotaToastConfig.layout.tinyAt > 0
79
+ ? quotaToastConfig.layout.tinyAt
80
+ : DEFAULT_CONFIG.layout.tinyAt,
81
+ },
82
+ };
83
+ // enabledProviders is intentionally allowed to be empty (providers OFF by default).
84
+ // Ensure at least one Google model is configured
85
+ if (config.googleModels.length === 0) {
86
+ config.googleModels = DEFAULT_CONFIG.googleModels;
87
+ }
88
+ return config;
89
+ }
90
+ async function readJson(path) {
91
+ try {
92
+ const content = await readFile(path, "utf-8");
93
+ return JSON.parse(content);
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ async function loadFromFiles() {
100
+ const cwd = process.cwd();
101
+ const configBaseDir = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
102
+ // Order: global first, then local overrides.
103
+ const candidates = [
104
+ join(configBaseDir, "opencode", "opencode.json"),
105
+ join(cwd, "opencode.json"),
106
+ ];
107
+ const quota = {};
108
+ const usedPaths = [];
109
+ for (const p of candidates) {
110
+ if (!existsSync(p))
111
+ continue;
112
+ const parsed = await readJson(p);
113
+ if (!parsed || typeof parsed !== "object")
114
+ continue;
115
+ const root = parsed;
116
+ const picks = [
117
+ { key: "experimental.quotaToast", value: root?.experimental?.quotaToast },
118
+ ];
119
+ const usedKeys = [];
120
+ for (const pick of picks) {
121
+ if (!pick.value || typeof pick.value !== "object")
122
+ continue;
123
+ Object.assign(quota, pick.value);
124
+ usedKeys.push(pick.key);
125
+ }
126
+ if (usedKeys.length > 0) {
127
+ usedPaths.push(`${p} (${usedKeys.join(", ")})`);
128
+ }
129
+ }
130
+ if (meta) {
131
+ meta.source = usedPaths.length > 0 ? "files" : "defaults";
132
+ meta.paths = usedPaths;
133
+ }
134
+ return normalize(Object.keys(quota).length > 0 ? quota : null);
135
+ }
136
+ try {
137
+ const response = await client.config.get();
138
+ // OpenCode config schema is strict; plugin-specific config must live under
139
+ // experimental.* to avoid "unrecognized key" validation errors.
140
+ const quotaToastConfig = response.data?.experimental?.quotaToast;
141
+ if (quotaToastConfig && typeof quotaToastConfig === "object") {
142
+ if (meta) {
143
+ meta.source = "sdk";
144
+ meta.paths = ["client.config.get"];
145
+ }
146
+ return normalize(quotaToastConfig);
147
+ }
148
+ return await loadFromFiles();
149
+ }
150
+ catch {
151
+ return await loadFromFiles();
152
+ }
153
+ }
154
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * GitHub Copilot quota fetcher
3
+ *
4
+ * Strategy (new Copilot API reality):
5
+ *
6
+ * 1) Preferred: GitHub public billing API using a fine-grained PAT
7
+ * configured in ~/.config/opencode/copilot-quota-token.json.
8
+ * 2) Best-effort: internal endpoint using OpenCode's stored OAuth token
9
+ * (legacy formats or via token exchange).
10
+ */
11
+ import type { CopilotResult } from "./types.js";
12
+ /**
13
+ * Query GitHub Copilot premium requests quota
14
+ *
15
+ * @returns Quota result, error, or null if not configured
16
+ */
17
+ export declare function queryCopilotQuota(): Promise<CopilotResult>;
18
+ /**
19
+ * Format Copilot quota for toast display
20
+ *
21
+ * @param result - Copilot quota result
22
+ * @returns Formatted string like "Copilot 229/300 (24%)" or null
23
+ */
24
+ export declare function formatCopilotQuota(result: CopilotResult): string | null;
25
+ //# sourceMappingURL=copilot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/lib/copilot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAOV,aAAa,EACd,MAAM,YAAY,CAAC;AAsSpB;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,CAAC,CA2DhE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAevE"}