unified-task-smoke-test.js 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. const assert = require('assert');
  2. const fs = require('fs');
  3. const os = require('os');
  4. const path = require('path');
  5. const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'qiwei-unified-task-'));
  6. process.env.QIWEI_OUTPUTS_DIR = tempDir;
  7. process.env.QIWEI_AGENT_DB_PATH = path.join(tempDir, 'messages', 'agent-workbench.db');
  8. function write(relativePath, value) {
  9. const filePath = path.join(tempDir, relativePath);
  10. fs.mkdirSync(path.dirname(filePath), { recursive: true });
  11. fs.writeFileSync(filePath, JSON.stringify(value, null, 2), 'utf8');
  12. }
  13. async function main() {
  14. write(path.join('knowledge', 'todos', 'index.json'), {
  15. todos: [
  16. { id: 'official-linked', content: '已绑定客户任务', status: 1 },
  17. { id: 'official-only', content: '独立官方待办', status: 1, endTime: '2027-01-02 10:00:00' },
  18. ],
  19. });
  20. write(path.join('goals', 'plans.json'), {
  21. plans: [{ id: 'goal-1', title: '演示计划', milestones: [{ id: 'm1', title: '准备阶段', tasks: [{ id: 'goal-task-1', title: '完成演示彩排', status: 'in_progress', owner: '测试成员' }] }] }],
  22. });
  23. write(path.join('knowledge', 'docs', 'index.json'), {
  24. documents: [{ id: 'doc-1', title: '客户方案', analysis: { analyzedAt: '2026-07-17T00:00:00Z', actionItems: [{ title: '确认方案版本', owner: '', dueDate: '', evidence: '原文要求确认版本', confidence: 0.92 }] } }],
  25. });
  26. write(path.join('knowledge', 'meetings', 'index.json'), {
  27. meetings: [{ id: 'meeting-1', title: '项目会', analysis: { analyzedAt: '2026-07-17T01:00:00Z', actionItems: [{ title: '整理会议结论', owner: '记录人', dueDate: '', priority: 'high', evidence: '会议描述中明确要求', confidence: 0.88 }] } }],
  28. });
  29. const { createUnifiedTaskService } = require('../mcp/src/dashboard/unified-task-service');
  30. const service = createUnifiedTaskService({
  31. outputsDir: tempDir,
  32. getConversations: () => ({ data: { conversations: [{
  33. id: 'conversation-1',
  34. displayName: '白名单客户',
  35. customerIntelligence: { tasks: [{ id: 'customer-task-1', title: '确认客户用途', status: 'open', priority: 'high', evidence: '客户尚未说明用途', officialTodoId: 'official-linked', officialSyncStatus: 'synced' }] },
  36. }] } }),
  37. updateCustomerTask: async () => ({ status: 'ok' }),
  38. completeTodoKnowledge: async () => ({ status: 'ok' }),
  39. qiweiGoalUpdateTask: async () => ({ status: 'ok' }),
  40. });
  41. const first = service.hub();
  42. assert.equal(first.status, 'ok');
  43. assert.equal(first.summary.total, 3);
  44. assert.equal(first.summary.candidates, 2);
  45. assert.equal(first.summary.deduplicatedOfficialCount, 1);
  46. assert(first.data.tasks.some(task => task.source === 'customer' && task.actions.openConversation));
  47. assert(!first.data.tasks.some(task => task.source === 'official' && task.id === 'official-linked'));
  48. const candidate = first.data.tasks.find(task => task.source === 'document-candidate');
  49. const promoted = service.createLocalTask({ title: candidate.title, evidence: candidate.evidence, source: candidate.source, sourceKey: candidate.id, sourceTitle: candidate.sourceTitle });
  50. assert.equal(promoted.status, 'ok');
  51. assert.equal(promoted.summary.created, true);
  52. const second = service.hub();
  53. assert.equal(second.summary.total, 4);
  54. assert.equal(second.summary.candidates, 1);
  55. assert.equal(second.summary.promotedCandidates, 1);
  56. const local = second.data.tasks.find(task => task.source === 'local');
  57. const updated = await service.update({ source: 'local', taskId: local.id, status: 'done' });
  58. assert.equal(updated.status, 'ok');
  59. assert.equal(service.hub().data.tasks.find(task => task.id === local.id).status, 'done');
  60. process.stdout.write(`${JSON.stringify({ status: 'ok', checks: 12, formalTasks: second.summary.total, candidates: second.summary.candidates }, null, 2)}\n`);
  61. }
  62. main().catch(error => {
  63. process.stderr.write(`${error.stack || error.message}\n`);
  64. process.exitCode = 1;
  65. }).finally(() => {
  66. try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch {}
  67. });