refactor: 全面清理死代码 — 删除 348 行无用代码

删除文件:
- training-export.ts: 训练数据导出(零引用,UI 已移除)

删除函数:
- workspace.ts: isProcessAlive, getActiveProcessCount, execWorkspaceCommand, terminateWorkspaceCommand
- sqlite.ts: deleteMessagesBySession, getSkill, closeDatabase
- tool-registry.ts: isToolEnabled
- cron-manager.ts: clearAllTimers
- workspace-panel.ts: setOnToolTerminated, setWorkspaceDirPath

删除 UI:
- index.html: 训练数据导出按钮及说明
- settings-modal.ts: 训练数据导出事件绑定
This commit is contained in:
thzxx
2026-04-18 10:08:01 +08:00
parent 6c9ffa5135
commit d2468cd6fc
8 changed files with 0 additions and 348 deletions
@@ -151,15 +151,6 @@ export function initSettingsModal(): void {
logSetting('检查间隔', `${ms / 60000} 分钟`);
});
// ── v5.0 训练数据导出 ──
document.querySelector('#btnExportTraining')!.addEventListener('click', async () => {
const { saveTrainingData } = await import('../services/training-export.js');
showToast('正在导出训练数据...', 'info');
const ok = await saveTrainingData();
if (ok) showToast('训练数据导出成功', 'success');
else showToast('导出取消或无数据', 'warning');
});
// ── v5.0 Cron 定时任务 ──
document.querySelector('#btnAddCronTask')!.addEventListener('click', async () => {
const name = (document.querySelector('#inputCronName') as HTMLInputElement).value.trim();
@@ -44,10 +44,6 @@ let currentAiCommand: string | null = null;
/** 终止通知回调(由外部设置) */
let onToolTerminated: ((command: string) => void) | null = null;
/** 设置终止通知回调 */
export function setOnToolTerminated(cb: (command: string) => void): void {
onToolTerminated = cb;
}
function genId(): string {
return `ws_${Date.now()}_${++_counter}`;
@@ -628,17 +624,3 @@ export function getWorkspaceDirPath(): string {
return workspaceDir;
}
/** 设置工作空间目录 */
export async function setWorkspaceDirPath(dir: string): Promise<boolean> {
const bridge = window.metonaDesktop;
if (!bridge?.isDesktop) return false;
const result = await bridge.workspace.setDir(dir);
if (result.success && result.dir) {
workspaceDir = result.dir;
currentFileDir = workspaceDir;
logInfo('工作空间目录已更新', workspaceDir);
return true;
}
return false;
}
-5
View File
@@ -347,11 +347,6 @@
<button class="btn btn-outline" id="btnDoctor" style="margin-bottom:8px;">🩺 一键诊断</button>
<div id="doctorResults" style="display:none;margin-top:8px;padding:10px;background:var(--bg-layer);border-radius:var(--radius-control);font-size:12px;max-height:200px;overflow-y:auto;"></div>
</div>
<div class="setting-group">
<label class="setting-label">📚 训练数据导出</label>
<button class="btn btn-outline" id="btnExportTraining" style="margin-bottom:4px;">📥 导出训练数据 (JSONL)</button>
<p class="text-muted" style="margin-top:4px;font-size:11px;">将 Agent 执行轨迹导出为 SFT 格式,可用于模型微调训练。包含成功的工具调用链和对话记录。</p>
</div>
<div class="setting-group">
<label class="setting-label">⏰ 定时任务 (Cron)</label>
<div style="display:flex;gap:8px;margin-bottom:8px;">
-9
View File
@@ -183,12 +183,3 @@ export async function restoreCronTasks(): Promise<void> {
logInfo(`定时任务已恢复: ${scheduled} 个任务`);
}
}
/**
* 清理所有定时器(应用退出时调用)
*/
export function clearAllTimers(): void {
for (const [id] of activeTimers) {
clearTimer(id);
}
}
-3
View File
@@ -572,9 +572,6 @@ export function setToolEnabled(toolName: string, enabled: boolean): void {
else enabledTools.delete(toolName);
}
export function isToolEnabled(toolName: string): boolean {
return enabledTools.has(toolName);
}
export function getEnabledToolDefinitions(): ToolDefinition[] {
const builtIn = TOOL_DEFINITIONS.filter(def => enabledTools.has(def.function.name));
-130
View File
@@ -1,130 +0,0 @@
/**
* TrainingExport - 训练数据导出 (v5.0)
* 将 Agent 执行轨迹转换为 SFT 训练数据格式
*/
import { state, KEYS } from '../state/state.js';
import { logInfo, logSuccess, logError } from './log-service.js';
interface SFTRecord {
instruction: string;
input: string;
output: string;
tools?: Array<{ name: string; arguments: Record<string, unknown> }>;
observations?: string[];
metadata?: {
session_id: string;
session_title: string;
timestamp: number;
model: string;
eval_count?: number;
total_duration?: number;
};
}
/**
* 导出所有会话的训练数据
* 从 traces + messages 中提取成功的工具调用链
*/
export async function exportTrainingData(): Promise<string | null> {
const bridge = (window as any).metonaDesktop;
if (!bridge?.db) return null;
try {
const sessions = await bridge.db.getAllSessions();
const records: SFTRecord[] = [];
for (const session of sessions) {
const messages = await bridge.db.getMessages(session.id);
const traces = await bridge.db.getTraces(session.id);
// 遍历消息对(user → assistant
for (let i = 0; i < messages.length - 1; i++) {
const userMsg = messages[i];
const asstMsg = messages[i + 1];
if (userMsg.role !== 'user' || asstMsg.role !== 'assistant') continue;
if (!userMsg.content || !asstMsg.content) continue;
// 解析工具调用
let tools: Array<{ name: string; arguments: Record<string, unknown> }> | undefined;
let observations: string[] | undefined;
if (asstMsg.tool_calls) {
try {
const toolCalls = JSON.parse(asstMsg.tool_calls);
if (Array.isArray(toolCalls) && toolCalls.length > 0) {
tools = toolCalls.map((tc: any) => ({
name: tc.name || tc.function?.name || 'unknown',
arguments: tc.arguments || tc.function?.arguments || {}
}));
}
} catch { /* ignore */ }
}
// 从 traces 中提取 observation
const sessionTraces = traces.filter(t =>
t.created_at >= userMsg.created_at && t.created_at <= asstMsg.created_at
);
if (sessionTraces.length > 0) {
observations = sessionTraces.map(t => t.observation || '').filter(Boolean);
}
records.push({
instruction: userMsg.content,
input: '',
output: asstMsg.content,
...(tools && { tools }),
...(observations?.length && { observations }),
metadata: {
session_id: session.id,
session_title: session.title,
timestamp: userMsg.created_at,
model: session.model,
...(asstMsg.eval_count && { eval_count: asstMsg.eval_count }),
...(asstMsg.total_duration && { total_duration: asstMsg.total_duration })
}
});
i++; // 跳过 assistant 消息
}
}
if (records.length === 0) {
logInfo('训练数据导出: 无可导出数据');
return null;
}
logSuccess(`训练数据导出完成: ${records.length} 条记录`);
return records.map(r => JSON.stringify(r)).join('\n');
} catch (err) {
logError('训练数据导出失败', (err as Error).message);
return null;
}
}
/**
* 保存训练数据到文件
*/
export async function saveTrainingData(): Promise<boolean> {
const bridge = (window as any).metonaDesktop;
if (!bridge?.dialog?.saveFile) return false;
const data = await exportTrainingData();
if (!data) return false;
try {
const filePath = await bridge.dialog.saveFile({
defaultPath: `metona-training-data-${new Date().toISOString().slice(0, 10)}.jsonl`,
filters: [{ name: 'JSONL', extensions: ['jsonl'] }, { name: 'JSON', extensions: ['json'] }]
});
if (!filePath) return false;
await bridge.fs.writeFile(filePath, data);
logSuccess(`训练数据已保存: ${filePath}`);
return true;
} catch (err) {
logError('保存训练数据失败', (err as Error).message);
return false;
}
}