ocr-chat.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /**
  2. * Func 标签:ocr-chat
  3. *
  4. * 约定:src/pages/processing/func/ 目录下每个文件名就是一个"可用标签/能力"。
  5. * 本文件用于声明该标签存在(供文档/提示词/后续动态加载使用)。
  6. *
  7. * 运行时真实执行逻辑由 ActionParser + electronAPI.extractChatHistory + main-js/func/ocr-chat.js 实现。
  8. */
  9. const electronAPI = require('../../node-api.js')
  10. const tagName = 'ocr-chat'
  11. const schema = {
  12. description: '根据图片识别对话内容,区分好友和自己的对话,输出JSON字符串格式的消息记录。',
  13. inputs: {
  14. // 按用户要求:抽象为 avatar1/avatar2,不绑定 friend/me 语义
  15. avatar1: '参与者1的头像/标识图片路径(相对于工作流目录)',
  16. avatar2: '参与者2的头像/标识图片路径(相对于工作流目录)',
  17. variable: '输出变量名(保存JSON字符串格式的消息记录)',
  18. },
  19. outputs: {
  20. variable: 'JSON字符串格式的消息记录(数组,每个元素包含 sender 和 text 字段)',
  21. },
  22. };
  23. /**
  24. * 执行 ocr-chat 功能
  25. * 这个函数会被 ActionParser 调用
  26. *
  27. * @param {Object} params - 参数对象
  28. * @param {string} params.device - 设备 ID/IP:Port
  29. * @param {string} params.avatar1 - 参与者1的头像路径
  30. * @param {string} params.avatar2 - 参与者2的头像路径
  31. * @param {string} params.folderPath - 工作流文件夹路径
  32. * @param {Object} params.region - 识别区域(可选,包含四个顶点坐标的 corners 对象)
  33. * @param {string} params.friendRgb - 好友对话框RGB颜色(格式:"(r,g,b)")
  34. * @param {string} params.myRgb - 我的对话框RGB颜色(格式:"(r,g,b)")
  35. * @returns {Promise<{success: boolean, messagesJson?: string, messages?: Array, error?: string}>}
  36. */
  37. async function executeOcrChat({ device, avatar1, avatar2, folderPath, region = null, friendRgb = null, myRgb = null }) {
  38. try {
  39. if (!electronAPI.extractChatHistory) {
  40. return {
  41. success: false,
  42. error: 'extractChatHistory API 不可用'
  43. };
  44. }
  45. // 调用主进程的 extractChatHistory 函数
  46. const result = await electronAPI.extractChatHistory(
  47. device,
  48. avatar1,
  49. avatar2,
  50. folderPath,
  51. region, // 传递区域参数
  52. friendRgb, // 传递好友RGB
  53. myRgb // 传递我的RGB
  54. );
  55. if (!result.success) {
  56. return { success: false, error: result.error };
  57. }
  58. // 获取消息数组
  59. let messages = [];
  60. if (result.messages && Array.isArray(result.messages)) {
  61. messages = result.messages;
  62. } else if (result.messagesText) {
  63. // 如果只有文本,尝试解析(向后兼容)
  64. const lines = result.messagesText.split('\n').filter(line => line.trim());
  65. for (const line of lines) {
  66. const match = line.match(/^(对方|好友|我):\s*(.+)$/);
  67. if (match) {
  68. const senderLabel = match[1];
  69. const sender = (senderLabel === '对方' || senderLabel === '好友') ? 'friend' : 'me';
  70. const text = match[2].trim();
  71. messages.push({ sender, text });
  72. }
  73. }
  74. }
  75. // 将消息数组转换为 chat-history.txt 格式的字符串
  76. // 格式:{"data":"时间戳","friend":"消息","me":"消息"}
  77. // 每个消息前都有一个时间戳(同一时间识别的消息使用相同时间戳)
  78. const formattedLines = [];
  79. formattedLines.push('{');
  80. // 获取当前时间戳(格式:昨天 HH:MM 或 今天 HH:MM)
  81. const now = new Date();
  82. const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  83. const yesterday = new Date(today);
  84. yesterday.setDate(yesterday.getDate() - 1);
  85. let timeLabel = '';
  86. const hour = now.getHours();
  87. const minute = now.getMinutes();
  88. if (now >= today) {
  89. timeLabel = `今天 ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  90. } else if (now >= yesterday) {
  91. timeLabel = `昨天 ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  92. } else {
  93. timeLabel = `${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()} ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
  94. }
  95. // 添加消息(按顺序),每个消息前添加时间戳
  96. let entryIndex = 0;
  97. for (let i = 0; i < messages.length; i++) {
  98. const msg = messages[i];
  99. const sender = msg.sender || msg.role || '';
  100. const text = (msg.text || msg.message || '').trim();
  101. if (text && (sender === 'friend' || sender === 'me')) {
  102. // 每个消息前添加时间戳
  103. formattedLines.push(`\t"data":${JSON.stringify(timeLabel)},`);
  104. formattedLines.push(`\t"${sender}":${JSON.stringify(text)}`);
  105. // 如果不是最后一条消息,添加逗号
  106. const hasMoreMessages = messages.slice(i + 1).some(m => {
  107. const s = m.sender || m.role || '';
  108. const t = (m.text || m.message || '').trim();
  109. return t && (s === 'friend' || s === 'me');
  110. });
  111. if (hasMoreMessages) {
  112. formattedLines[formattedLines.length - 1] += ',';
  113. }
  114. }
  115. }
  116. formattedLines.push('}');
  117. const chatHistoryFormat = formattedLines.join('\n');
  118. return {
  119. success: true,
  120. messagesJson: chatHistoryFormat, // 返回 chat-history.txt 格式的字符串
  121. messages: messages // 保留原始消息数组(向后兼容)
  122. };
  123. } catch (error) {
  124. return {
  125. success: false,
  126. error: error.message || '提取聊天记录失败'
  127. };
  128. }
  129. }
  130. module.exports = { tagName, schema, executeOcrChat }