@leo000001/opencode-quota-sidebar 3.0.1 → 3.0.3

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 (44) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/CONTRIBUTING.md +4 -1
  3. package/README.md +210 -514
  4. package/README.zh-CN.md +337 -0
  5. package/SECURITY.md +2 -2
  6. package/assets/OpenCode-Quota-Sidebar.png +0 -0
  7. package/dist/cost.d.ts +3 -3
  8. package/dist/cost.js +258 -169
  9. package/dist/format.js +10 -3
  10. package/dist/index.js +4 -3
  11. package/dist/providers/common.d.ts +6 -0
  12. package/dist/providers/common.js +32 -12
  13. package/dist/providers/core/anthropic.d.ts +1 -1
  14. package/dist/providers/core/anthropic.js +43 -39
  15. package/dist/providers/core/kimi_for_coding.d.ts +1 -1
  16. package/dist/providers/core/kimi_for_coding.js +44 -64
  17. package/dist/providers/core/minimax_cn_coding_plan.d.ts +2 -0
  18. package/dist/providers/core/minimax_cn_coding_plan.js +214 -0
  19. package/dist/providers/core/zhipu_coding_plan.d.ts +1 -1
  20. package/dist/providers/core/zhipu_coding_plan.js +41 -61
  21. package/dist/providers/index.d.ts +3 -3
  22. package/dist/providers/index.js +5 -5
  23. package/dist/providers/third_party/rightcode.d.ts +1 -1
  24. package/dist/providers/third_party/rightcode.js +41 -61
  25. package/dist/providers/third_party/xyai.d.ts +2 -0
  26. package/dist/providers/third_party/{xyai_vibe.js → xyai.js} +113 -79
  27. package/dist/quota.d.ts +2 -2
  28. package/dist/quota.js +24 -18
  29. package/dist/quota_render.d.ts +1 -1
  30. package/dist/quota_render.js +23 -17
  31. package/dist/storage_parse.js +1 -0
  32. package/dist/title.js +7 -7
  33. package/dist/title_apply.js +18 -1
  34. package/dist/tools.d.ts +13 -8
  35. package/dist/tools.js +4 -2
  36. package/dist/tui.tsx +2 -1
  37. package/dist/tui_helpers.d.ts +2 -1
  38. package/dist/tui_helpers.js +6 -1
  39. package/dist/types.d.ts +2 -0
  40. package/package.json +11 -3
  41. package/quota-sidebar.config.example.json +45 -45
  42. package/dist/providers/third_party/buzz.d.ts +0 -2
  43. package/dist/providers/third_party/buzz.js +0 -156
  44. package/dist/providers/third_party/xyai_vibe.d.ts +0 -2
@@ -1,156 +0,0 @@
1
- import { isRecord, swallow } from '../../helpers.js';
2
- import { asNumber, configuredProviderEnabled, fetchWithTimeout, sanitizeBaseURL, toIso, } from '../common.js';
3
- function isBuzzBaseURL(value) {
4
- const normalized = sanitizeBaseURL(value);
5
- if (!normalized)
6
- return false;
7
- try {
8
- const parsed = new URL(normalized);
9
- if (parsed.protocol !== 'https:')
10
- return false;
11
- return parsed.host === 'buzzai.cc' || parsed.host === 'www.buzzai.cc';
12
- }
13
- catch {
14
- return false;
15
- }
16
- }
17
- function resolveApiKey(auth, providerOptions) {
18
- const optionKey = providerOptions?.apiKey;
19
- if (typeof optionKey === 'string' && optionKey)
20
- return optionKey;
21
- if (!auth)
22
- return undefined;
23
- if (auth.type === 'api' && typeof auth.key === 'string' && auth.key) {
24
- return auth.key;
25
- }
26
- if (auth.type === 'wellknown') {
27
- if (typeof auth.key === 'string' && auth.key)
28
- return auth.key;
29
- if (typeof auth.token === 'string' && auth.token)
30
- return auth.token;
31
- }
32
- if (auth.type === 'oauth' && typeof auth.access === 'string' && auth.access) {
33
- return auth.access;
34
- }
35
- return undefined;
36
- }
37
- function dashboardUrl(baseURL, pathname) {
38
- const normalized = sanitizeBaseURL(baseURL);
39
- if (normalized) {
40
- try {
41
- return new URL(pathname, normalized).toString();
42
- }
43
- catch {
44
- // Fall through to the stable default host below.
45
- }
46
- }
47
- return `https://buzzai.cc${pathname}`;
48
- }
49
- async function fetchBuzzQuota({ sourceProviderID, providerID, providerOptions, auth, config, }) {
50
- const checkedAt = Date.now();
51
- const runtimeProviderID = typeof sourceProviderID === 'string' && sourceProviderID
52
- ? sourceProviderID
53
- : providerID;
54
- const base = {
55
- providerID: runtimeProviderID,
56
- adapterID: 'buzz',
57
- label: 'Buzz',
58
- shortLabel: 'Buzz',
59
- sortOrder: 6,
60
- };
61
- const apiKey = resolveApiKey(auth, providerOptions);
62
- if (!apiKey) {
63
- return {
64
- ...base,
65
- status: 'unavailable',
66
- checkedAt,
67
- note: 'missing api key',
68
- };
69
- }
70
- const subscriptionEndpoint = dashboardUrl(providerOptions?.baseURL, '/v1/dashboard/billing/subscription');
71
- const usageEndpoint = dashboardUrl(providerOptions?.baseURL, '/v1/dashboard/billing/usage');
72
- const requestInit = {
73
- headers: {
74
- Accept: 'application/json',
75
- Authorization: `Bearer ${apiKey}`,
76
- 'User-Agent': 'opencode-quota-sidebar',
77
- },
78
- };
79
- const [subscriptionResponse, usageResponse] = await Promise.all([
80
- fetchWithTimeout(subscriptionEndpoint, requestInit, config.quota.requestTimeoutMs).catch(swallow('fetchBuzzQuota:subscription')),
81
- fetchWithTimeout(usageEndpoint, requestInit, config.quota.requestTimeoutMs).catch(swallow('fetchBuzzQuota:usage')),
82
- ]);
83
- if (!subscriptionResponse || !usageResponse) {
84
- return {
85
- ...base,
86
- status: 'error',
87
- checkedAt,
88
- note: 'network request failed',
89
- };
90
- }
91
- if (!subscriptionResponse.ok || !usageResponse.ok) {
92
- const note = [
93
- !subscriptionResponse.ok
94
- ? `subscription http ${subscriptionResponse.status}`
95
- : undefined,
96
- !usageResponse.ok ? `usage http ${usageResponse.status}` : undefined,
97
- ]
98
- .filter((value) => Boolean(value))
99
- .join(', ');
100
- return {
101
- ...base,
102
- status: 'error',
103
- checkedAt,
104
- note,
105
- };
106
- }
107
- const [subscriptionPayload, usagePayload] = await Promise.all([
108
- subscriptionResponse
109
- .json()
110
- .catch(swallow('fetchBuzzQuota:subscriptionJson')),
111
- usageResponse.json().catch(swallow('fetchBuzzQuota:usageJson')),
112
- ]);
113
- if (!isRecord(subscriptionPayload) || !isRecord(usagePayload)) {
114
- return {
115
- ...base,
116
- status: 'error',
117
- checkedAt,
118
- note: 'invalid response',
119
- };
120
- }
121
- const totalQuota = asNumber(subscriptionPayload.soft_limit_usd);
122
- const totalUsage = asNumber(usagePayload.total_usage);
123
- if (totalQuota === undefined || totalUsage === undefined) {
124
- return {
125
- ...base,
126
- status: 'error',
127
- checkedAt,
128
- note: 'missing billing fields',
129
- };
130
- }
131
- const accessUntil = asNumber(subscriptionPayload.access_until);
132
- const resetAt = accessUntil !== undefined && accessUntil > 0
133
- ? toIso(accessUntil)
134
- : undefined;
135
- const balance = totalQuota - totalUsage / 100;
136
- return {
137
- ...base,
138
- status: 'ok',
139
- checkedAt,
140
- resetAt,
141
- balance: {
142
- amount: balance,
143
- currency: '¥',
144
- },
145
- note: 'remaining balance = soft_limit_usd - total_usage / 100',
146
- };
147
- }
148
- export const buzzAdapter = {
149
- id: 'buzz',
150
- label: 'Buzz',
151
- shortLabel: 'Buzz',
152
- sortOrder: 6,
153
- matchScore: ({ providerOptions }) => isBuzzBaseURL(providerOptions?.baseURL) ? 100 : 0,
154
- isEnabled: (config) => configuredProviderEnabled(config.quota, 'buzz', true),
155
- fetch: fetchBuzzQuota,
156
- };
@@ -1,2 +0,0 @@
1
- import type { QuotaProviderAdapter } from '../types.js';
2
- export declare const xyaiVibeAdapter: QuotaProviderAdapter;