-
-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support query Aide key usage info when click vscode statusbar a…
…ide item
- Loading branch information
1 parent
43a8049
commit b580fcd
Showing
18 changed files
with
314 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
// this file is for Aide third-party API query | ||
type BaseRes<T = any> = { | ||
success: boolean | ||
data: T | ||
message: string | ||
} | ||
|
||
type AideKeyUsageSearchParams = { | ||
key: string | ||
p: number // page | ||
pageSize: number | ||
} | ||
|
||
type AideKeyUsageSearchResDataItem = { | ||
id: number | ||
request_id: string | ||
user_id: number | ||
created_at: number | ||
type: number | ||
content: string | ||
username: string | ||
token_name: string | ||
model_name: string | ||
channel_name: string | ||
quota: number | ||
prompt_tokens: number | ||
completion_tokens: number | ||
channel: number | ||
token_key: string | ||
request_duration: number | ||
response_first_byte_duration: number | ||
total_duration: number | ||
duration_for_view: number | ||
is_stream: boolean | ||
ip: string | ||
} | ||
|
||
type AideKeyUsageSearchRes = BaseRes<{ | ||
total: number | ||
data: AideKeyUsageSearchResDataItem[] | ||
}> | ||
|
||
export const aideKeyUsageSearch = (params: AideKeyUsageSearchParams) => | ||
fetch( | ||
`https://api.zyai.online/public/log/self/search?key=${params.key}&p=${params.p}&pageSize=${params.pageSize}`, | ||
{ | ||
method: 'GET' | ||
} | ||
).then(response => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! status: ${response.status}`) | ||
} | ||
return response.json() as Promise<AideKeyUsageSearchRes> | ||
}) | ||
|
||
type AideKeyUsageCountParams = { | ||
key: string | ||
} | ||
|
||
type AideKeyUsageCountResData = { | ||
count: number | ||
} | ||
|
||
type AideKeyUsageCountRes = BaseRes<AideKeyUsageCountResData> | ||
|
||
export const aideKeyUsageCount = (params: AideKeyUsageCountParams) => | ||
fetch(`https://api.zyai.online/public/log/self/count?key=${params.key}`, { | ||
method: 'GET' | ||
}).then(response => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! status: ${response.status}`) | ||
} | ||
return response.json() as Promise<AideKeyUsageCountRes> | ||
}) | ||
|
||
type AideKeyUsageStatParams = { | ||
key: string | ||
} | ||
|
||
type AideKeyUsageStatResData = { | ||
mpm: number | ||
quota: number | ||
rpm: number | ||
tpm: number | ||
} | ||
|
||
type AideKeyUsageStatRes = BaseRes<AideKeyUsageStatResData> | ||
|
||
export const aideKeyUsageStat = (params: AideKeyUsageStatParams) => | ||
fetch(`https://api.zyai.online/public/log/self/stat?key=${params.key}`, { | ||
method: 'GET' | ||
}).then(response => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! status: ${response.status}`) | ||
} | ||
return response.json() as Promise<AideKeyUsageStatRes> | ||
}) | ||
|
||
export type AideKeyUsageSubscriptionParams = { | ||
key: string | ||
} | ||
|
||
export type AideKeyUsageSubscriptionRes = { | ||
object: string | ||
has_payment_method: boolean | ||
soft_limit_usd: number | ||
hard_limit_usd: number | ||
system_hard_limit_usd: number | ||
access_until: number | ||
used_quota: number | ||
remain_quota: number | ||
used_count: number | ||
} | ||
|
||
export const aideKeyUsageSubscription = ( | ||
params: AideKeyUsageSubscriptionParams | ||
) => | ||
fetch(`https://api.zyai.online/public/dashboard/billing/subscription`, { | ||
method: 'GET', | ||
headers: { | ||
Authorization: `Bearer ${params.key}` | ||
} | ||
}).then(response => { | ||
if (!response.ok) { | ||
throw new Error(`HTTP error! status: ${response.status}`) | ||
} | ||
return response.json() as Promise<AideKeyUsageSubscriptionRes> | ||
}) | ||
|
||
type AideKeyUsageInfoParams = { | ||
key: string | ||
} | ||
|
||
type AideKeyUsageInfoResData = { | ||
count: AideKeyUsageCountResData | ||
subscription: AideKeyUsageSubscriptionRes | ||
} | ||
|
||
type AideKeyUsageInfoRes = BaseRes<AideKeyUsageInfoResData> | ||
|
||
export const aideKeyUsageInfo = ( | ||
params: AideKeyUsageInfoParams | ||
): Promise<AideKeyUsageInfoRes> => | ||
Promise.all([aideKeyUsageCount(params), aideKeyUsageSubscription(params)]) | ||
.then(([countRes, subscriptionRes]) => ({ | ||
success: countRes.success, | ||
data: { | ||
count: countRes.data, | ||
subscription: subscriptionRes | ||
}, | ||
message: 'Combined usage info retrieved successfully' | ||
})) | ||
.catch(error => ({ | ||
success: false, | ||
data: { | ||
count: { count: 0 }, | ||
subscription: { | ||
object: '', | ||
has_payment_method: false, | ||
soft_limit_usd: 0, | ||
hard_limit_usd: 0, | ||
system_hard_limit_usd: 0, | ||
access_until: 0, | ||
used_quota: 0, | ||
remain_quota: 0, | ||
used_count: 0 | ||
} | ||
}, | ||
message: `Error fetching usage info: ${error.message}` | ||
})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { aideKeyUsageInfo } from '@/ai/aide-key-request' | ||
import { getConfigKey } from '@/config' | ||
import { t } from '@/i18n' | ||
import { updateAideKeyUsageStatusBar } from '@/providers/aide-key-usage-statusbar' | ||
import { formatNumber } from '@/utils' | ||
import * as vscode from 'vscode' | ||
|
||
export const handleShowAideKeyUsageInfo = async () => { | ||
const openaiBaseUrl = await getConfigKey('openaiBaseUrl') | ||
const openaiKey = await getConfigKey('openaiKey') | ||
|
||
if (!openaiBaseUrl.includes('api.zyai.online')) | ||
throw new Error(t('error.aideKeyUsageInfoOnlySupportAideModels')) | ||
|
||
// show loading | ||
updateAideKeyUsageStatusBar(`$(sync~spin) ${t('info.loading')}`) | ||
|
||
try { | ||
const result = await aideKeyUsageInfo({ key: openaiKey }) | ||
|
||
if (result.success) { | ||
// create a nice message to show the result | ||
const { count, subscription } = result.data | ||
|
||
const totalUSD = subscription.hard_limit_usd | ||
const usedUSD = | ||
(subscription.used_quota / subscription.remain_quota) * totalUSD | ||
const remainUSD = totalUSD - usedUSD | ||
const formatUSD = (amount: number) => `$${formatNumber(amount, 2)}` | ||
const formatDate = (timestamp: number) => { | ||
if (timestamp === 0) return t('info.aideKey.neverExpires') | ||
return new Date(timestamp * 1000).toLocaleDateString() | ||
} | ||
|
||
const message = `${t('info.aideKey.usageInfo')}: | ||
${t('info.aideKey.total')}: ${formatUSD(totalUSD)} | ||
${t('info.aideKey.used')}: ${formatUSD(usedUSD)} | ||
${t('info.aideKey.remain')}: ${formatUSD(remainUSD)} | ||
${t('info.aideKey.callCount')}: ${count.count} | ||
${t('info.aideKey.validUntil')}: ${formatDate(subscription.access_until)}` | ||
|
||
vscode.window.showInformationMessage(message, { | ||
modal: true | ||
}) | ||
} else { | ||
throw new Error(`Failed to fetch usage info: ${result.message}`) | ||
} | ||
} finally { | ||
// restore the original text of the status bar item | ||
updateAideKeyUsageStatusBar( | ||
`$(info) ${t('info.aideKeyUsageStatusBar.text')}` | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { t } from '@/i18n' | ||
import * as vscode from 'vscode' | ||
|
||
let aideKeyUsageStatusBar: vscode.StatusBarItem | ||
|
||
export const initAideKeyUsageStatusBar = (context: vscode.ExtensionContext) => { | ||
aideKeyUsageStatusBar = vscode.window.createStatusBarItem( | ||
vscode.StatusBarAlignment.Right, | ||
100 | ||
) | ||
aideKeyUsageStatusBar.text = `$(info) ${t('info.aideKeyUsageStatusBar.text')}` | ||
aideKeyUsageStatusBar.tooltip = t('info.aideKeyUsageStatusBar.tooltip') | ||
aideKeyUsageStatusBar.command = 'aide.showAideKeyUsageInfo' | ||
aideKeyUsageStatusBar.show() | ||
|
||
context.subscriptions.push(aideKeyUsageStatusBar) | ||
} | ||
|
||
export const updateAideKeyUsageStatusBar = (text: string) => { | ||
aideKeyUsageStatusBar.text = text | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.