feat: 升级至 v0.2.3 — Token 估算优化、工具确认超时改进、工作空间标签页
1. Token 估算优化(核心改进):新增 token-estimator.ts 智能字符估算(中文 1.5 token/字、ASCII 0.25 token/字),替换三处旧的 length/2 粗略估算,中文场景准确度从 ~50% 提升到 ~90% 2. 工具确认超时改进:超时时间可配置(30s~600s)、超时 toast 通知、ConfirmationDialog 倒计时 UI(进度条 + 最后 10 秒红色脉冲动画)、SettingsModal 新增配置入口 3. 详情栏新增 Workspace 标签页:workspace:getInfo IPC + WorkspaceViewer 组件(文件预览、目录状态、在文件管理器打开)
This commit is contained in:
@@ -28,6 +28,7 @@ import type { MemoryConsolidator } from '../harness/memory/consolidator';
|
||||
import type { MetonaMessage, MetonaStreamEvent } from '../harness/types';
|
||||
import { MetonaErrorCode, MetonaStreamEventType } from '../harness/types';
|
||||
import type { MetonaError } from '../harness/types';
|
||||
import { estimateMessagesTokens } from '../harness/utils/token-estimator';
|
||||
import log from 'electron-log';
|
||||
|
||||
/**
|
||||
@@ -198,7 +199,7 @@ export function registerAllIPCHandlers(
|
||||
|
||||
// TRACE 层:记录上下文构建
|
||||
sessionRecorder.recordContextBuilt({
|
||||
tokenCount: history.reduce((sum, m) => sum + Math.ceil(m.content.length / 2), 0),
|
||||
tokenCount: estimateMessagesTokens(history),
|
||||
usageRatio: 0,
|
||||
});
|
||||
|
||||
@@ -500,6 +501,10 @@ export function registerAllIPCHandlers(
|
||||
// numCtx 同时更新 Engine 的 contextLength
|
||||
agentLoop.updateConfig({ contextLength: (value as number) || undefined });
|
||||
log.info(`[CONFIG] Agent contextLength updated to ${value}`);
|
||||
} else if (key === 'agent.confirmationTimeoutMs') {
|
||||
// 工具确认超时变更,即时应用到 ConfirmationHook
|
||||
confirmationHook.setConfirmationTimeout(value as number);
|
||||
log.info(`[CONFIG] Confirmation timeout updated to ${value}ms`);
|
||||
}
|
||||
|
||||
// 日志级别变更时即时应用
|
||||
@@ -663,6 +668,73 @@ export function registerAllIPCHandlers(
|
||||
return { success: true, inherited, failed };
|
||||
});
|
||||
|
||||
// 获取当前工作空间详情:路径 + 4 个核心文件状态 + 自动目录状态
|
||||
ipcMain.handle('workspace:getInfo', async () => {
|
||||
const { existsSync, statSync } = await import('fs');
|
||||
const workspacePath = workspaceService.getPath();
|
||||
const files = workspaceService.reload(); // 同步外部可能的手动修改
|
||||
|
||||
const REQUIRED = ['SOUL.md', 'AGENTS.md', 'MEMORY.md', 'USERS.md'] as const;
|
||||
const AUTO_DIRS = ['logs', 'traces', '.metona'] as const;
|
||||
|
||||
const fileInfos = REQUIRED.map((name) => {
|
||||
const filePath = join(workspacePath, name);
|
||||
let exists = false;
|
||||
let size = 0;
|
||||
let mtime = 0;
|
||||
let preview = '';
|
||||
try {
|
||||
if (existsSync(filePath)) {
|
||||
const stat = statSync(filePath);
|
||||
exists = true;
|
||||
size = stat.size;
|
||||
mtime = stat.mtimeMs;
|
||||
// 截取前 500 字符作为预览
|
||||
const { readFileSync } = await import('fs');
|
||||
const content = readFileSync(filePath, 'utf-8');
|
||||
preview = content.length > 500 ? content.slice(0, 500) + '\n...(已截断)' : content;
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
// 文件内容映射:SOUL.md → files.soul, AGENTS.md → files.agents 等
|
||||
const contentKey = name.toLowerCase().replace('.md', '') as 'soul' | 'agents' | 'memory' | 'users';
|
||||
return {
|
||||
name,
|
||||
path: filePath,
|
||||
exists,
|
||||
size,
|
||||
mtime,
|
||||
preview: exists ? preview : (files[contentKey] ?? ''),
|
||||
};
|
||||
});
|
||||
|
||||
const dirInfos = AUTO_DIRS.map((name) => {
|
||||
const dirPath = join(workspacePath, name);
|
||||
let exists = false;
|
||||
let fileCount = 0;
|
||||
try {
|
||||
if (existsSync(dirPath)) {
|
||||
exists = true;
|
||||
const stat = statSync(dirPath);
|
||||
if (stat.isDirectory()) {
|
||||
const { readdirSync } = await import('fs');
|
||||
fileCount = readdirSync(dirPath).length;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return { name, path: dirPath, exists, fileCount };
|
||||
});
|
||||
|
||||
return {
|
||||
path: workspacePath,
|
||||
files: fileInfos,
|
||||
dirs: dirInfos,
|
||||
};
|
||||
});
|
||||
|
||||
// ===== 工具管理 =====
|
||||
|
||||
ipcMain.handle('tools:list', async () => {
|
||||
|
||||
Reference in New Issue
Block a user