webMcpChatTemplates.ts 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { getWebMcpTool } from './webMcpService';
  2. export interface WebMcpChatTemplate {
  3. toolName?: string;
  4. label: string;
  5. pattern: RegExp;
  6. examples: string[];
  7. requiresConfirmation: boolean;
  8. parse: (match: RegExpMatchArray) => Record<string, unknown>;
  9. }
  10. const template = (
  11. toolName: string | undefined,
  12. label: string,
  13. pattern: RegExp,
  14. examples: string[],
  15. parse: (match: RegExpMatchArray) => Record<string, unknown>
  16. ): WebMcpChatTemplate => ({
  17. toolName,
  18. label,
  19. pattern,
  20. examples,
  21. parse,
  22. requiresConfirmation: toolName ? Boolean(getWebMcpTool(toolName)?.requiresConfirmation) : false,
  23. });
  24. export const webMcpChatTemplates: ReadonlyArray<WebMcpChatTemplate> = [
  25. template('list_documents', '列出我的文档', /^列出(?:我的|当前用户的)?文档$/, ['列出我的文档'], () => ({})),
  26. template('open_document', '打开文档', /^(?:打开|查看)\s+(.+?)\s+文档$/, ['查看 doc-abc123 文档'], (match) => ({ documentId: match[1] })),
  27. template('get_document', '读取文档', /^读取文档\s+(\S+)$/, ['读取文档 doc-abc123'], (match) => ({ documentId: match[1] })),
  28. template('search_document', '搜索文档', /^搜索文档\s+(\S+)\s+(.+)$/, ['搜索文档 doc-abc123 WebMCP'], (match) => ({ documentId: match[1], query: match[2] })),
  29. template('get_block', '读取文档块', /^读取文档块\s+(\S+)\s+(\S+)$/, ['读取文档块 doc-abc123 block-p-50'], (match) => ({ documentId: match[1], blockId: match[2] })),
  30. template('get_document_toc', '查看文档目录', /^查看文档目录\s+(\S+)$/, ['查看文档目录 doc-abc123'], (match) => ({ documentId: match[1] })),
  31. template('get_document_stats', '查看文档统计', /^查看文档统计\s+(\S+)$/, ['查看文档统计 doc-abc123'], (match) => ({ documentId: match[1] })),
  32. template('list_export_records', '查看我的导出记录', /^查看我的导出记录$/, ['查看我的导出记录'], () => ({})),
  33. template('insert_block', '向文档插入段落', /^向文档\s+(\S+)\s+插入段落:(.+)$/, ['向文档 doc-abc123 插入段落:新增内容'], (match) => ({ documentId: match[1], type: 'paragraph', content: match[2] })),
  34. template('update_block', '更新文档块', /^更新文档块\s+(\S+)\s+(\S+)\s+为:(.+)$/, ['更新文档块 doc-abc123 block-p-50 为:新内容'], (match) => ({ documentId: match[1], blockId: match[2], content: match[3] })),
  35. template('delete_block', '删除文档块', /^删除文档块\s+(\S+)\s+(\S+)$/, ['删除文档块 doc-abc123 block-p-50'], (match) => ({ documentId: match[1], blockId: match[2] })),
  36. template('export_document', '导出文档', /^导出文档\s+(\S+)\s+为\s*Word$/i, ['导出文档 doc-abc123 为 Word'], (match) => ({ documentId: match[1] })),
  37. template('download_export_record', '下载导出记录', /^下载导出记录\s+(\S+)$/, ['下载导出记录 export-abc123'], (match) => ({ recordId: match[1] })),
  38. ];
  39. export const webMcpTemplateHelp = (): string =>
  40. webMcpChatTemplates
  41. .map((item) => `${item.label}:${item.examples.join(';')}${item.requiresConfirmation ? '(需要确认)' : ''}`)
  42. .join('\n');
  43. export const matchWebMcpChatTemplate = (content: string): { template: WebMcpChatTemplate; input: Record<string, unknown> } | null => {
  44. const normalized = content.trim().replace(/^调用\s*WebMCP\s*/i, '');
  45. for (const item of webMcpChatTemplates) {
  46. const match = normalized.match(item.pattern);
  47. if (match) return { template: item, input: item.parse(match) };
  48. }
  49. return null;
  50. };
  51. export const getWebMcpChatTemplates = (): ReadonlyArray<WebMcpChatTemplate> => webMcpChatTemplates;