feat: 从JWT解析userId并添加资源点余额提醒
- 新增 jwtUtils.ts 解析JWT token获取user_id - dialogService 从登录session获取真实userId - 添加 credit_update 事件处理 - 余额低于5点时弹窗提醒用户充值 - settings.ts 登录URL改为可配置
This commit is contained in:
@ -12,6 +12,7 @@ import { getConfig } from '../config/settings';
|
||||
import type { DialogRequest, ToolCallRequest, AskUserEvent, RunMode, ServiceTier, ToolConfirmEvent, PlanConfirmEvent } from '../types/api';
|
||||
import { submitToolConfirm, submitAnswer, stopDialog } from './apiClient';
|
||||
import { ChatHistoryManager } from '../utils/chatHistoryManager';
|
||||
import { getUserIdFromToken } from '../utils/jwtUtils';
|
||||
|
||||
/**
|
||||
* 消息段落类型
|
||||
@ -331,6 +332,27 @@ export class DialogSession {
|
||||
|
||||
const config = getConfig();
|
||||
|
||||
// 从登录 session 获取真实 userId
|
||||
let userId = config.userId; // 默认值
|
||||
try {
|
||||
console.log('[DialogSession] 尝试获取登录 session...');
|
||||
const session = await vscode.authentication.getSession('iccoder', [], { silent: true });
|
||||
console.log('[DialogSession] session 结果:', session ? '已获取' : 'null/undefined');
|
||||
if (session?.accessToken) {
|
||||
console.log('[DialogSession] accessToken 长度:', session.accessToken.length);
|
||||
const parsedUserId = getUserIdFromToken(session.accessToken);
|
||||
console.log('[DialogSession] 解析的 userId:', parsedUserId);
|
||||
if (parsedUserId) {
|
||||
userId = parsedUserId;
|
||||
console.log('[DialogSession] 使用真实 userId:', userId);
|
||||
}
|
||||
} else {
|
||||
console.log('[DialogSession] 未获取到 accessToken,使用默认 userId:', userId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[DialogSession] 获取登录 session 失败:', error);
|
||||
}
|
||||
|
||||
// 获取压缩数据和新消息(用于后端重启后恢复)
|
||||
const historyManager = ChatHistoryManager.getInstance();
|
||||
const compactedData = await historyManager.loadCompactedData(this.taskId);
|
||||
@ -343,7 +365,7 @@ export class DialogSession {
|
||||
const request: DialogRequest = {
|
||||
taskId: this.taskId,
|
||||
message,
|
||||
userId: config.userId,
|
||||
userId,
|
||||
mode: mode || 'agent',
|
||||
serviceTier: serviceTier || config.serviceTier, // 优先使用传入的参数
|
||||
compactedData: compactedData || undefined,
|
||||
@ -654,6 +676,23 @@ export class DialogSession {
|
||||
callbacks.onContextUsage?.(data);
|
||||
},
|
||||
|
||||
onCreditUpdate: (data) => {
|
||||
console.log('[DialogSession] onCreditUpdate: 扣除', data.deductedCredits, '剩余', data.remainingCredits);
|
||||
// 资源点余额低于阈值时弹窗提醒
|
||||
const LOW_CREDIT_THRESHOLD = 5;
|
||||
if (data.remainingCredits < LOW_CREDIT_THRESHOLD) {
|
||||
vscode.window.showWarningMessage(
|
||||
`资源点余额不足!当前剩余 ${data.remainingCredits.toFixed(2)} 点,请及时充值。`,
|
||||
'去充值'
|
||||
).then(selection => {
|
||||
if (selection === '去充值') {
|
||||
// 打开充值页面
|
||||
vscode.env.openExternal(vscode.Uri.parse('https://iccoder.com/recharge'));
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onOpen: () => {
|
||||
console.log('[DialogSession] SSE 连接已建立');
|
||||
},
|
||||
|
||||
@ -2,6 +2,7 @@ import * as vscode from "vscode";
|
||||
import * as http from "http";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import { getConfig } from "../config/settings";
|
||||
|
||||
/**
|
||||
* IC Coder Authentication Provider
|
||||
@ -12,7 +13,6 @@ export class ICCoderAuthenticationProvider
|
||||
{
|
||||
private static readonly AUTH_TYPE = "iccoder";
|
||||
private static readonly AUTH_NAME = "IC Coder";
|
||||
private static readonly LOGIN_URL = "http://192.168.1.108:2005/login";
|
||||
private static loginServer: http.Server | null = null;
|
||||
private static currentPort: number | null = null;
|
||||
|
||||
@ -149,9 +149,8 @@ export class ICCoderAuthenticationProvider
|
||||
|
||||
// 构建登录 URL
|
||||
const callbackUrl = `http://localhost:${port}/callback`;
|
||||
const loginUrl = `${
|
||||
ICCoderAuthenticationProvider.LOGIN_URL
|
||||
}?redirect_uri=${encodeURIComponent(callbackUrl)}`;
|
||||
const config = getConfig();
|
||||
const loginUrl = `${config.loginUrl}?redirect_uri=${encodeURIComponent(callbackUrl)}`;
|
||||
|
||||
console.log("🔐 登录服务器已启动,监听端口:", port);
|
||||
console.log("🌐 登录 URL:", loginUrl);
|
||||
|
||||
@ -28,7 +28,8 @@ import type {
|
||||
AgentProgressEvent,
|
||||
AgentCompleteEvent,
|
||||
AgentErrorEvent,
|
||||
ContextUsageEvent
|
||||
ContextUsageEvent,
|
||||
CreditUpdateEvent
|
||||
} from '../types/api';
|
||||
import type { MemoryCompactedEvent } from '../types/memory';
|
||||
|
||||
@ -74,6 +75,8 @@ export interface SSECallbacks {
|
||||
onMemoryCompacted?: (data: MemoryCompactedEvent) => void;
|
||||
/** 上下文使用量更新 */
|
||||
onContextUsage?: (data: ContextUsageEvent) => void;
|
||||
/** 资源点余额更新 */
|
||||
onCreditUpdate?: (data: CreditUpdateEvent) => void;
|
||||
/** 连接打开 */
|
||||
onOpen?: () => void;
|
||||
/** 连接关闭 */
|
||||
@ -331,6 +334,9 @@ function dispatchEvent(
|
||||
case 'context_usage':
|
||||
callbacks.onContextUsage?.(data as ContextUsageEvent);
|
||||
break;
|
||||
case 'credit_update':
|
||||
callbacks.onCreditUpdate?.(data as CreditUpdateEvent);
|
||||
break;
|
||||
case 'heartbeat':
|
||||
// 心跳事件:仅用于保持连接,不需要特殊处理
|
||||
// Node.js req.setTimeout 会在收到数据时自动重置计时器
|
||||
|
||||
Reference in New Issue
Block a user