fix: 修复 showPlan 工具交互逻辑和 JWT Token 问题

- 修复 pendingQuestions 缺失时无法提交回答的问题
- 添加 fallbackTaskId 参数支持直接发送到后端
- apiClient 自动获取 JWT Token
- 取消按钮改为中止对话而非发送消息
This commit is contained in:
XiaoFeng
2026-01-13 10:58:33 +08:00
parent 37a121c3de
commit 72a84ed9e2
10 changed files with 300 additions and 103 deletions

View File

@ -12,7 +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';
import { getUserIdFromToken, isTokenExpired } from '../utils/jwtUtils';
import { updateCachedBalance } from './creditsService';
/**
@ -342,14 +342,29 @@ export class DialogSession {
const config = getConfig();
// 从登录 session 获取真实 userId
// 从登录 session 获取真实 userId 和 token
let userId = config.userId; // 默认值
let token: string | undefined;
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);
// 检测 token 是否过期
const expired = isTokenExpired(session.accessToken);
if (expired === true) {
console.error('[DialogSession] token 已过期,需要重新登录');
vscode.window.showErrorMessage('登录已过期,请重新登录', '重新登录').then(selection => {
if (selection === '重新登录') {
vscode.commands.executeCommand('iccoder.login');
}
});
throw new Error('登录已过期,请重新登录');
}
token = session.accessToken; // 保存 token 用于扣费
const parsedUserId = getUserIdFromToken(session.accessToken);
console.log('[DialogSession] 解析的 userId:', parsedUserId);
if (parsedUserId) {
@ -380,6 +395,7 @@ export class DialogSession {
userId,
mode: mode || 'agent',
serviceTier: serviceTier || config.serviceTier, // 优先使用传入的参数
token, // JWT token 用于扣费
compactedData: compactedData || undefined,
newMessages: newMessages.length > 0 ? newMessages : undefined,
knowledgeData: knowledgeData || undefined
@ -711,6 +727,18 @@ export class DialogSession {
onError: (data) => {
this.isActive = false;
// 检测登录状态过期(只弹一次窗,不再传递错误)
if (data.message.includes('LOGIN_EXPIRED') || data.message.includes('登录状态已过期')) {
vscode.window.showErrorMessage('登录状态已过期,请重新登录', '重新登录').then(selection => {
if (selection === '重新登录') {
vscode.commands.executeCommand('ic-coder.login');
}
});
// 登录过期错误已处理,不再传递给外部
return;
}
callbacks.onError?.(data.message);
},
@ -895,7 +923,10 @@ export class DialogSession {
selected?: string[],
customInput?: string
): Promise<void> {
await userInteractionManager.receiveAnswer(askId, selected, customInput);
// 直接调用 receiveAnswer传递 taskId 作为 fallbackTaskId
// 如果 pendingQuestions 中有问题,走正常流程
// 如果没有receiveAnswer 会使用 fallbackTaskId 直接发送到后端
await userInteractionManager.receiveAnswer(askId, selected, customInput, this.taskId);
}
}