| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- 'use strict';
- const assert = require('assert');
- const fs = require('fs');
- const os = require('os');
- const path = require('path');
- const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'qiwei-inbound-media-'));
- process.env.QIWEI_OUTPUTS_DIR = path.join(tempRoot, 'outputs');
- const { AgentWorkbenchDb } = require('../mcp/src/core/agent-workbench-db');
- const { AgentWorkbenchService } = require('../mcp/src/core/agent-workbench-service');
- const { evaluatePolledMessage } = require('../mcp/src/core/agent-poller-policy');
- const { InboundMediaService, mediaMessageDescriptor, sniffMedia } = require('../mcp/src/core/inbound-media');
- async function main() {
- const imageMessage = {
- msgType: 14,
- senderId: 'contact-1',
- timestamp: 1785920000,
- msgData: { fileId: 'file-1', fileAesKey: 'key-1', fileSize: 68, width: 1, height: 1 },
- };
- const imageCandidate = evaluatePolledMessage(imageMessage, { allowedSenders: ['contact-1'] });
- assert.equal(imageCandidate.eligible, true);
- assert.equal(imageCandidate.content, '[图片]');
- assert.equal(imageCandidate.media.kind, 'image');
- assert.equal(imageCandidate.generateReply, false);
- const voiceCandidate = evaluatePolledMessage({
- msgType: 16,
- senderId: 'contact-1',
- timestamp: 1785920001,
- msgData: { fileId: 'voice-1', fileAesKey: 'key-2', voiceTime: 6 },
- }, { allowedSenders: ['contact-1'] });
- assert.equal(voiceCandidate.eligible, true);
- assert.equal(voiceCandidate.content, '[语音]');
- assert.equal(voiceCandidate.generateReply, false);
- const analyzedVoice = mediaMessageDescriptor({
- msgType: 16,
- msgData: { transcript: '我明天下午有时间' },
- });
- assert.equal(analyzedVoice.mediaOnly, false);
- assert.equal(analyzedVoice.content, '[语音] 我明天下午有时间');
- const groupCandidate = evaluatePolledMessage({ ...imageMessage, fromRoomId: 'room-1' }, { allowedSenders: ['contact-1'] });
- assert.equal(groupCandidate.eligible, false);
- assert.equal(groupCandidate.reason, 'group_message');
- const db = new AgentWorkbenchDb(path.join(tempRoot, 'workbench.db'));
- let agentCalls = 0;
- const service = new AgentWorkbenchService({
- db,
- agent: { run: async () => { agentCalls += 1; throw new Error('agent must not run'); } },
- qiwei: {},
- config: { qiwei: { allowedSenders: ['contact-1'] }, agent: {} },
- });
- const stored = await service.ingestInbound({
- externalId: 'image-message-1',
- contactId: 'contact-1',
- contactName: '测试联系人',
- content: imageCandidate.content,
- timestamp: new Date(1785920000 * 1000).toISOString(),
- raw: imageMessage,
- contentType: imageCandidate.media.contentType,
- payload: imageCandidate.media.payload,
- }, { generateReply: false });
- assert.equal(stored.status, 'media_received');
- assert.equal(agentCalls, 0);
- const second = await service.ingestInbound({
- externalId: 'image-message-2',
- contactId: 'contact-1',
- contactName: '测试联系人',
- content: imageCandidate.content,
- timestamp: new Date((1785920000 + 1) * 1000).toISOString(),
- raw: { ...imageMessage, msgServerId: 'image-message-2' },
- contentType: imageCandidate.media.contentType,
- payload: imageCandidate.media.payload,
- }, { generateReply: false });
- assert.equal(second.status, 'media_received');
- const rows = db.listMessages(stored.conversation.id);
- assert.equal(rows.length, 2);
- assert.equal(rows[0].content_type, 'image');
- assert.equal(JSON.parse(rows[0].raw_json).msgData.fileId, 'file-1');
- if (typeof service.stopBackgroundWorkers === 'function') service.stopBackgroundWorkers();
- db.close();
- const png = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=', 'base64');
- assert.equal(sniffMedia(png, 'application/octet-stream').contentType, 'image/png');
- let downloadCalls = 0;
- const resolver = new InboundMediaService({
- qiwei: {
- call: async (method, params, options) => {
- assert.equal(method, '/cloud/wxWorkDownload');
- assert.equal(params.fileType, 1);
- assert.equal(options.sanitizeResponse, false);
- return { cloudUrl: 'https://media.example.test/image.png' };
- },
- },
- fetchImpl: async url => {
- downloadCalls += 1;
- assert.equal(url, 'https://media.example.test/image.png');
- return new Response(png, { status: 200, headers: { 'content-type': 'image/png' } });
- },
- });
- const resolved = await resolver.resolve('message-1', imageMessage);
- assert.equal(downloadCalls, 1);
- assert.equal(resolved.contentType, 'image/png');
- assert.equal(fs.readFileSync(resolved.filePath).equals(png), true);
- const dashboardApp = fs.readFileSync(path.join(__dirname, '..', 'mcp', 'src', 'dashboard', 'app.js'), 'utf8');
- const dashboardServer = fs.readFileSync(path.join(__dirname, '..', 'mcp', 'src', 'dashboard', 'server.js'), 'utf8');
- const agentService = fs.readFileSync(path.join(__dirname, '..', 'mcp', 'src', 'dashboard', 'agent-service.js'), 'utf8');
- const workbenchService = fs.readFileSync(path.join(__dirname, '..', 'mcp', 'src', 'core', 'agent-workbench-service.js'), 'utf8');
- assert.match(dashboardApp, /data-media-retry/);
- assert.match(dashboardApp, /\/api\/agent\/messages\/\$\{encodeURIComponent\(message\.id\)\}\/media/);
- assert.match(dashboardServer, /\/api\\\/agent\\\/messages\\\/\(\[\^\/\]\+\)\\\/media/);
- assert.match(agentService, /function publicMessageRaw/);
- assert.match(workbenchService, /media_received_without_auto_reply/);
- fs.rmSync(tempRoot, { recursive: true, force: true });
- console.log('agent inbound media smoke: passed');
- }
- main().catch(error => {
- try { fs.rmSync(tempRoot, { recursive: true, force: true }); } catch {}
- console.error(error);
- process.exit(1);
- });
|