const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'qiwei-unified-task-')); process.env.QIWEI_OUTPUTS_DIR = tempDir; process.env.QIWEI_AGENT_DB_PATH = path.join(tempDir, 'messages', 'agent-workbench.db'); function write(relativePath, value) { const filePath = path.join(tempDir, relativePath); fs.mkdirSync(path.dirname(filePath), { recursive: true }); fs.writeFileSync(filePath, JSON.stringify(value, null, 2), 'utf8'); } async function main() { write(path.join('knowledge', 'todos', 'index.json'), { todos: [ { id: 'official-linked', content: '已绑定客户任务', status: 1 }, { id: 'official-only', content: '独立官方待办', status: 1, endTime: '2027-01-02 10:00:00' }, ], }); write(path.join('goals', 'plans.json'), { plans: [{ id: 'goal-1', title: '演示计划', milestones: [{ id: 'm1', title: '准备阶段', tasks: [{ id: 'goal-task-1', title: '完成演示彩排', status: 'in_progress', owner: '测试成员' }] }] }], }); write(path.join('knowledge', 'docs', 'index.json'), { documents: [{ id: 'doc-1', title: '客户方案', analysis: { analyzedAt: '2026-07-17T00:00:00Z', actionItems: [{ title: '确认方案版本', owner: '', dueDate: '', evidence: '原文要求确认版本', confidence: 0.92 }] } }], }); write(path.join('knowledge', 'meetings', 'index.json'), { meetings: [{ id: 'meeting-1', title: '项目会', analysis: { analyzedAt: '2026-07-17T01:00:00Z', actionItems: [{ title: '整理会议结论', owner: '记录人', dueDate: '', priority: 'high', evidence: '会议描述中明确要求', confidence: 0.88 }] } }], }); const { createUnifiedTaskService } = require('../mcp/src/dashboard/unified-task-service'); const service = createUnifiedTaskService({ outputsDir: tempDir, getConversations: () => ({ data: { conversations: [{ id: 'conversation-1', displayName: '白名单客户', customerIntelligence: { tasks: [{ id: 'customer-task-1', title: '确认客户用途', status: 'open', priority: 'high', evidence: '客户尚未说明用途', officialTodoId: 'official-linked', officialSyncStatus: 'synced' }] }, }] } }), updateCustomerTask: async () => ({ status: 'ok' }), completeTodoKnowledge: async () => ({ status: 'ok' }), qiweiGoalUpdateTask: async () => ({ status: 'ok' }), }); const first = service.hub(); assert.equal(first.status, 'ok'); assert.equal(first.summary.total, 3); assert.equal(first.summary.candidates, 2); assert.equal(first.summary.deduplicatedOfficialCount, 1); assert(first.data.tasks.some(task => task.source === 'customer' && task.actions.openConversation)); assert(!first.data.tasks.some(task => task.source === 'official' && task.id === 'official-linked')); const candidate = first.data.tasks.find(task => task.source === 'document-candidate'); const promoted = service.createLocalTask({ title: candidate.title, evidence: candidate.evidence, source: candidate.source, sourceKey: candidate.id, sourceTitle: candidate.sourceTitle }); assert.equal(promoted.status, 'ok'); assert.equal(promoted.summary.created, true); const second = service.hub(); assert.equal(second.summary.total, 4); assert.equal(second.summary.candidates, 1); assert.equal(second.summary.promotedCandidates, 1); const local = second.data.tasks.find(task => task.source === 'local'); const updated = await service.update({ source: 'local', taskId: local.id, status: 'done' }); assert.equal(updated.status, 'ok'); assert.equal(service.hub().data.tasks.find(task => task.id === local.id).status, 'done'); process.stdout.write(`${JSON.stringify({ status: 'ok', checks: 12, formalTasks: second.summary.total, candidates: second.summary.candidates }, null, 2)}\n`); } main().catch(error => { process.stderr.write(`${error.stack || error.message}\n`); process.exitCode = 1; }).finally(() => { try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch {} });