mistagent 0.1.20 → 0.1.21
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/dist/src/api/quota.d.ts +13 -0
- package/dist/src/api/quota.js +7 -0
- package/dist/src/hooks/useChat.js +23 -2
- package/dist/src/hooks/useSlashCommand.js +45 -0
- package/dist/src/main.js +1 -0
- package/dist/src/utils/constants.d.ts +1 -1
- package/dist/src/utils/constants.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface QuotaBalance {
|
|
2
|
+
usd_balance: number;
|
|
3
|
+
usd_total_granted: number;
|
|
4
|
+
usd_total_consumed: number;
|
|
5
|
+
usage_today_tokens: number;
|
|
6
|
+
usage_this_month_tokens: number;
|
|
7
|
+
cost_today_usd: number;
|
|
8
|
+
cost_this_month_usd: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const quotaApi: {
|
|
11
|
+
balance(): Promise<QuotaBalance>;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=quota.d.ts.map
|
|
@@ -3,6 +3,7 @@ import { createParser } from 'eventsource-parser';
|
|
|
3
3
|
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { chatApi } from '../api/chat.js';
|
|
6
|
+
import { ApiError } from '../api/client.js';
|
|
6
7
|
import { submitTunnelResult } from '../api/tunnel.js';
|
|
7
8
|
import { processFileReferences } from '../utils/fileRef.js';
|
|
8
9
|
import { executeFileOperation, isSensitiveOperation, isAlwaysConfirmRequired } from '../utils/fileTunnel.js';
|
|
@@ -292,7 +293,17 @@ export function useChat() {
|
|
|
292
293
|
}
|
|
293
294
|
catch (err) {
|
|
294
295
|
tokenBuf.dispose();
|
|
295
|
-
|
|
296
|
+
let errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
297
|
+
if (err instanceof ApiError) {
|
|
298
|
+
try {
|
|
299
|
+
const parsed = JSON.parse(err.body);
|
|
300
|
+
if (parsed.detail?.message)
|
|
301
|
+
errorMessage = parsed.detail.message;
|
|
302
|
+
else if (typeof parsed.detail === 'string')
|
|
303
|
+
errorMessage = parsed.detail;
|
|
304
|
+
}
|
|
305
|
+
catch { /* use default */ }
|
|
306
|
+
}
|
|
296
307
|
dispatch({ type: 'STREAM_ERROR', error: errorMessage });
|
|
297
308
|
}
|
|
298
309
|
finally {
|
|
@@ -421,7 +432,17 @@ export function useChat() {
|
|
|
421
432
|
await processConfirmStream(reader);
|
|
422
433
|
}
|
|
423
434
|
catch (err) {
|
|
424
|
-
|
|
435
|
+
let errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
436
|
+
if (err instanceof ApiError) {
|
|
437
|
+
try {
|
|
438
|
+
const parsed = JSON.parse(err.body);
|
|
439
|
+
if (parsed.detail?.message)
|
|
440
|
+
errorMessage = parsed.detail.message;
|
|
441
|
+
else if (typeof parsed.detail === 'string')
|
|
442
|
+
errorMessage = parsed.detail;
|
|
443
|
+
}
|
|
444
|
+
catch { /* use default */ }
|
|
445
|
+
}
|
|
425
446
|
dispatch({ type: 'STREAM_ERROR', error: errorMessage });
|
|
426
447
|
}
|
|
427
448
|
}, [state.threadId, state.pendingPlan, dispatch, processConfirmStream]);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { sessionsApi } from '../api/sessions.js';
|
|
3
|
+
import { quotaApi } from '../api/quota.js';
|
|
3
4
|
import { useChatState, useChatDispatch } from '../contexts/ChatContext.js';
|
|
4
5
|
import { useAppState, useAppActions } from '../contexts/AppContext.js';
|
|
5
6
|
import { useUIActions } from '../contexts/UIContext.js';
|
|
@@ -104,6 +105,50 @@ export function useSlashCommand() {
|
|
|
104
105
|
});
|
|
105
106
|
return;
|
|
106
107
|
}
|
|
108
|
+
// /usage — show account balance and usage
|
|
109
|
+
if (trimmed === '/usage') {
|
|
110
|
+
dispatch({ type: 'SET_BUSY', busy: true });
|
|
111
|
+
try {
|
|
112
|
+
const b = await quotaApi.balance();
|
|
113
|
+
const fmt = (v) => `$${v.toFixed(4)}`;
|
|
114
|
+
const fmtTokens = (v) => v >= 1_000_000
|
|
115
|
+
? `${(v / 1_000_000).toFixed(1)}M`
|
|
116
|
+
: v >= 1_000
|
|
117
|
+
? `${(v / 1_000).toFixed(1)}K`
|
|
118
|
+
: String(v);
|
|
119
|
+
const lines = [
|
|
120
|
+
`**账户余额**`,
|
|
121
|
+
` 余额: ${fmt(b.usd_balance)}`,
|
|
122
|
+
` 总充值: ${fmt(b.usd_total_granted)}`,
|
|
123
|
+
` 总消耗: ${fmt(b.usd_total_consumed)}`,
|
|
124
|
+
``,
|
|
125
|
+
`**今日用量**`,
|
|
126
|
+
` Tokens: ${fmtTokens(b.usage_today_tokens)}`,
|
|
127
|
+
` 费用: ${fmt(b.cost_today_usd)}`,
|
|
128
|
+
``,
|
|
129
|
+
`**本月用量**`,
|
|
130
|
+
` Tokens: ${fmtTokens(b.usage_this_month_tokens)}`,
|
|
131
|
+
` 费用: ${fmt(b.cost_this_month_usd)}`,
|
|
132
|
+
];
|
|
133
|
+
dispatch({
|
|
134
|
+
type: 'ADD_ITEM',
|
|
135
|
+
item: { type: 'command', command: '/usage', result: lines.join('\n') },
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
dispatch({
|
|
140
|
+
type: 'ADD_ITEM',
|
|
141
|
+
item: {
|
|
142
|
+
type: 'error',
|
|
143
|
+
text: `查询用量失败: ${err instanceof Error ? err.message : String(err)}`,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
dispatch({ type: 'SET_BUSY', busy: false });
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
107
152
|
// /quit or /exit
|
|
108
153
|
if (trimmed === '/quit' || trimmed === '/exit') {
|
|
109
154
|
dispatch({
|
package/dist/src/main.js
CHANGED
|
@@ -197,6 +197,7 @@ export async function main() {
|
|
|
197
197
|
{ name: '/tools', description: '显示可用工具列表', usage: '/tools' },
|
|
198
198
|
{ name: '/theme', description: '切换显示主题', usage: '/theme' },
|
|
199
199
|
{ name: '/init', description: '分析当前目录代码并生成知识图谱', usage: '/init' },
|
|
200
|
+
{ name: '/usage', description: '查看账户使用量和余额', usage: '/usage' },
|
|
200
201
|
{ name: '/quit', description: '退出应用', usage: '/quit', aliases: ['/exit'] },
|
|
201
202
|
{ name: '/logout', description: '退出登录并返回登录界面', usage: '/logout' },
|
|
202
203
|
];
|