const assert = require('assert/strict'); const fs = require('fs'); const os = require('os'); const path = require('path'); const { createDocumentKnowledgeService, createTodoKnowledgeService, unwrapOfficialResponse, } = require('../mcp/src/dashboard/official-office-knowledge-service'); function rpc(payload) { return { status: 'ok', data: { response: { jsonrpc: '2.0', id: 1, result: { isError: false, content: [{ type: 'text', text: JSON.stringify(payload) }] }, }, }, }; } async function main() { const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'qiwei-office-knowledge-')); const readyStatus = async () => ({ installed: true, valid: true, authorized: true, ready: true, installedVersion: '0.1.9' }); const available = async () => ({ available: true, reason: 'available', message: '官方能力可用' }); let docPolls = 0; const docCalls = []; const docOfficialCall = async request => { docCalls.push(request); if (request.method === 'create_doc') return rpc({ errcode: 0, docid: 'doc-live-1', url: 'https://doc.weixin.qq.com/doc/demo' }); if (request.method === 'edit_doc_content') return rpc({ errcode: 0 }); if (request.method === 'get_doc_content') { docPolls += 1; if (docPolls % 2 === 1) return rpc({ errcode: 0, task_id: 'task-1', task_done: false }); return rpc({ errcode: 0, task_id: 'task-1', task_done: true, docid: 'doc-live-1', url: 'https://doc.weixin.qq.com/doc/demo', doc_name: '客户演示方案', content: '# 客户演示方案\n\n王刚负责在 7 月 20 日前整理演示清单。' }); } throw new Error(`unexpected doc method ${request.method}`); }; const analyzer = async () => ({ status: 'completed', summary: '文档明确了客户演示准备任务。', keyPoints: ['准备客户演示'], decisions: [], actionItems: [{ title: '整理演示清单', owner: '王刚', dueDate: '2026-07-20', evidence: '文档原文明确说明', confidence: 0.98 }], risks: [], knowledgeTags: ['客户演示'], analysisBasis: '仅基于企微文档原文。', requiresReview: true, analyzedAt: new Date().toISOString(), error: null, }); try { const docs = createDocumentKnowledgeService({ storeDir: path.join(tempRoot, 'docs'), officialStatus: readyStatus, officialCall: docOfficialCall, capability: available, analyzer, wait: async () => {} }); const created = await docs.createDocument({ title: '客户演示方案', content: '# 客户演示方案\n\n正文' }); assert.equal(created.status, 'ok'); assert.equal(created.summary.live, true); assert.equal(created.data.document.sourceKind, 'official-cli-live'); assert.match(created.data.document.markdown, /王刚负责/); assert.ok(fs.existsSync(created.data.document.files.json)); assert.ok(fs.existsSync(created.data.document.files.markdown)); assert.deepEqual(docCalls.slice(0, 2).map(item => item.method), ['create_doc', 'edit_doc_content']); assert.ok(docCalls.filter(item => item.method === 'get_doc_content').length >= 2); const analyzed = await docs.analyze('doc-live-1'); assert.equal(analyzed.status, 'ok'); assert.equal(analyzed.data.document.analysis.actionItems[0].owner, '王刚'); assert.match(fs.readFileSync(analyzed.data.document.files.markdown, 'utf8'), /整理演示清单/); const docHub = await docs.hub(); assert.equal(docHub.summary.docReady, true); assert.equal(docHub.summary.documentCount, 1); const permissionDocs = createDocumentKnowledgeService({ storeDir: path.join(tempRoot, 'permission-docs'), officialStatus: readyStatus, capability: available, wait: async () => {}, officialCall: async request => { if (request.method === 'create_doc') return rpc({ errcode: 0, docid: 'doc-permission-1', url: 'https://doc.weixin.qq.com/doc/permission' }); if (request.method === 'edit_doc_content') return rpc({ errcode: 0 }); return rpc({ errcode: 851008, errmsg: 'partial no authorization' }); }, }); const permissionCreated = await permissionDocs.createDocument({ title: '待读权限文档', content: '# 已成功写入' }); assert.equal(permissionCreated.status, 'ok'); assert.equal(permissionCreated.summary.readbackPending, true); assert.equal(permissionCreated.data.document.readbackStatus, 'pending-permission'); assert.equal(permissionCreated.data.document.sourceKind, 'official-cli-live-created'); const todoCalls = []; let todoListEmpty = false; const todoOfficialCall = async request => { todoCalls.push(request); if (request.method === 'search_todo_userid') return rpc({ errcode: 0, user_list: [{ userid: 'wanggang', name: '王刚', alias: '刚sir' }] }); if (request.method === 'get_todo_list') return rpc({ errcode: 0, todo_list: todoListEmpty ? [] : [ { todo_id: 'todo-live-1', content: '整理客户资料', todo_status: 1, end_time: '2026-07-20 18:00:00', follower_list: { followers: [{ follower_id: 'wanggang' }] } }, { todo_id: 'todo-live-2', content: '确认演示时间', todo_status: 0, follower_list: { followers: [{ follower_id: 'wanggang' }] } }, ] }); if (request.method === 'get_todo_detail') return rpc({ errcode: 0, data_list: [ { todo_id: 'todo-live-3', content: '制作客户演示截图', todo_status: 1, end_time: '2026-07-21 18:00:00', follower_list: { followers: [{ follower_id: 'wanggang' }] } }, ] }); if (request.method === 'create_todo') return rpc({ errcode: 0, todo_id: 'todo-live-3' }); if (request.method === 'update_todo') return rpc({ errcode: 0 }); throw new Error(`unexpected todo method ${request.method}`); }; const todos = createTodoKnowledgeService({ storeDir: path.join(tempRoot, 'todos'), officialStatus: readyStatus, officialCall: todoOfficialCall, capability: available }); const users = await todos.searchUsers({ keyword: '王刚' }); assert.equal(users.data.users[0].id, 'wanggang'); const synced = await todos.sync({ followerId: 'wanggang' }); assert.equal(synced.status, 'ok'); assert.equal(synced.summary.syncedCount, 2); const todoCreated = await todos.create({ content: '制作客户演示截图', followerIds: ['wanggang'], endTime: '2026-07-21T18:00', remindType: 3 }); assert.equal(todoCreated.status, 'ok'); assert.equal(todoCreated.data.todo.id, 'todo-live-3'); const refreshed = await todos.refreshDetails({ todoIds: ['todo-live-3'] }); assert.equal(refreshed.summary.refreshedCount, 1); todoListEmpty = true; const preserved = await todos.sync({ followerId: 'wanggang' }); assert.equal(preserved.summary.preservedCount, 3); const completed = await todos.complete('todo-live-3'); assert.equal(completed.status, 'ok'); assert.equal(todos.readIndex().todos.find(item => item.id === 'todo-live-3').status, 0); assert.ok(fs.existsSync(path.join(tempRoot, 'todos', 'todos.md'))); const unwrapped = unwrapOfficialResponse(rpc({ errcode: 0, value: 'real' })); assert.equal(unwrapped.value, 'real'); let blockedCalls = 0; const blockedDocs = createDocumentKnowledgeService({ storeDir: path.join(tempRoot, 'blocked'), officialStatus: readyStatus, officialCall: async () => { blockedCalls += 1; throw new Error('blocked capability must not call live API'); }, capability: async () => ({ available: false, reason: 'enterprise-policy', message: '文档能力未开放' }), }); const blocked = await blockedDocs.importDocument({ docid: 'x' }); assert.equal(blocked.status, 'error'); assert.equal(blockedCalls, 0); process.stdout.write(`${JSON.stringify({ status: 'ok', officialEnvelopeUnwrapped: true, documentCreateReadAnalyze: true, documentReadPermissionFallback: true, todoSearchSyncCreateComplete: true, blockedPathMakesNoLiveCall: true }, null, 2)}\n`); } finally { fs.rmSync(tempRoot, { recursive: true, force: true }); } } main().catch(error => { process.stderr.write(`${error.stack || error.message}\n`); process.exitCode = 1; });