diff --git a/modules/tool/packages/linkMemo/config.ts b/modules/tool/packages/linkMemo/config.ts deleted file mode 100644 index c3646820..00000000 --- a/modules/tool/packages/linkMemo/config.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { defineTool } from '@tool/type'; -import { - FlowNodeInputTypeEnum, - FlowNodeOutputTypeEnum, - WorkflowIOValueTypeEnum -} from '@tool/type/fastgpt'; -import { ToolTypeEnum } from '@tool/type/tool'; - -export default defineTool({ - name: { - 'zh-CN': '钉钉 Memo', - en: 'Template tool' - }, - type: ToolTypeEnum.tools, - description: { - 'zh-CN': '钉钉Memo工具', - en: 'DingTalk Memo Tool' - }, - secretInputConfig: [ - { - key: 'dingdingUrl', - label: '钉钉Memo服务根地址', - description: '根地址,例如:http://example.com', - required: true, - inputType: 'secret' - }, - { - key: 'sysAccessKey', - label: '钉钉Memo系统AccessKey', - description: '系统AccessKey', - required: true, - inputType: 'secret' - }, - { - key: 'corpId', - label: '钉钉Memo企业ID', - description: '企业ID', - required: true, - inputType: 'secret' - } - ], - versionList: [ - { - value: '0.1.0', - description: 'Default version', - inputs: [ - { - key: 'query', - label: '用户提问内容', - renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference], - valueType: WorkflowIOValueTypeEnum.string, - required: true - }, - { - key: 'appId', - label: '钉钉Memo应用ID', - renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference], - valueType: WorkflowIOValueTypeEnum.string, - required: true - }, - { - key: 'appAccessKey', - label: '钉钉Memo应用AccessKey', - renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference], - valueType: WorkflowIOValueTypeEnum.string, - required: true - }, - { - key: 'iscontact', - label: '是否使用职级', - renderTypeList: [FlowNodeInputTypeEnum.switch, FlowNodeInputTypeEnum.reference], - valueType: WorkflowIOValueTypeEnum.boolean, - required: false - } - ], - outputs: [ - { - valueType: WorkflowIOValueTypeEnum.string, - key: 'content', - label: '答案内容', - description: '工具返回的完整答案' - }, - { - valueType: WorkflowIOValueTypeEnum.arrayObject, - key: 'citeLinks', - label: '参考文档', - description: '相关的参考文档链接列表' - } - ] - } - ] -}); diff --git a/modules/tool/packages/linkMemo/index.ts b/modules/tool/packages/linkMemo/index.ts deleted file mode 100644 index d698ed48..00000000 --- a/modules/tool/packages/linkMemo/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import config from './config'; -import { InputType, OutputType, tool as toolCb } from './src'; -import { exportTool } from '@tool/utils/tool'; - -export default exportTool({ - toolCb, - InputType, - OutputType, - config -}); diff --git a/modules/tool/packages/linkMemo/logo.svg b/modules/tool/packages/linkMemo/logo.svg deleted file mode 100644 index ca10cec3..00000000 --- a/modules/tool/packages/linkMemo/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/modules/tool/packages/linkMemo/package.json b/modules/tool/packages/linkMemo/package.json deleted file mode 100644 index d7e33192..00000000 --- a/modules/tool/packages/linkMemo/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@fastgpt-plugins/tool-link-memo", - "module": "index.ts", - "type": "module", - "scripts": { - "build": "bun ../../../../scripts/build.ts" - }, - "devDependencies": { - "@types/bun": "latest" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "dependencies": { - "zod": "^3.24.2" - } -} diff --git a/modules/tool/packages/linkMemo/src/index.ts b/modules/tool/packages/linkMemo/src/index.ts deleted file mode 100644 index 5a1fc5fb..00000000 --- a/modules/tool/packages/linkMemo/src/index.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { z } from 'zod'; -import type { RunToolSecondParamsType } from '@tool/type/tool'; -import { StreamDataAnswerTypeEnum } from '@tool/type/tool'; -import { getErrText } from '@tool/utils/err'; - -export const InputType = z.object({ - query: z.string().describe('用户提问内容'), - dingdingUrl: z.string().describe('钉钉Memo服务根地址'), - sysAccessKey: z.string().describe('钉钉Memo系统AccessKey'), - corpId: z.string().describe('钉钉Memo企业ID'), - appId: z.string().describe('钉钉Memo应用ID'), - appAccessKey: z.string().describe('钉钉Memo应用AccessKey'), - iscontact: z.boolean().optional().describe('是否使用职级') -}); - -export const OutputType = z.object({ - content: z.string().describe('完整答案'), - citeLinks: z - .array( - z.object({ - name: z.string().describe('知识参考文档显示名称'), - url: z.string().describe('文档链接') - }) - ) - .optional() - .describe('参考文档列表') -}); - -type ReferenceDocument = { - name: string; - webUrl: string; - dingUrl: string; -}; - -type StreamData = { - streamData?: string; - isFinished?: boolean; - customMessage?: { - memoChainData?: { - referenceDocuments?: ReferenceDocument[]; - }; - completedContent?: string; - }; -}; - -function buildQueryString(query: string, iscontact: boolean, userContact?: string): string { - const userParts: string[] = []; - - if (iscontact && userContact) { - userParts.push(`我的职级是${userContact}`); - } - - return userParts.length > 0 ? userParts.join(',') + ',' + query : query; -} - -function extractCiteLinks(docs: ReferenceDocument[]) { - const citeLinks: Array<{ name: string; url: string }> = []; - - docs.forEach((doc) => { - citeLinks.push({ - name: `${doc.name}`, - url: doc.webUrl - }); - }); - - return citeLinks; -} - -function parseDataString( - line: string, - lines: string[], - index: number -): { dataStr: string; nextIndex: number } { - let dataStr = ''; - let nextIndex = index; - - if (line.startsWith('data: ')) { - dataStr = line.slice(6); - } else if (line === 'data:' && index + 1 < lines.length) { - dataStr = lines[index + 1]; - nextIndex = index + 1; - } else if (line.startsWith('data:') && line.length > 5) { - dataStr = line.slice(5); - } - - return { dataStr, nextIndex }; -} - -export async function tool( - { - query, - dingdingUrl, - sysAccessKey, - corpId, - appId, - appAccessKey, - iscontact - }: z.infer, - { systemVar, streamResponse }: RunToolSecondParamsType -): Promise> { - try { - const url = new URL('/v2/open/api/onpremise/memo/stream/query', dingdingUrl); - - url.searchParams.append('userId', systemVar.user.username); - url.searchParams.append('sysAccessKey', sysAccessKey); - url.searchParams.append('corpId', corpId); - url.searchParams.append('appId', appId.toString()); - url.searchParams.append('appAccessKey', appAccessKey); - - const queryString = buildQueryString(query, iscontact || false, systemVar.user.contact); - - url.searchParams.append('query', queryString); - - const response = await fetch(url.toString(), { - method: 'GET', - headers: { - Accept: 'text/event-stream', - 'Cache-Control': 'no-cache' - } - }); - - if (!response.ok) { - return Promise.reject(`HTTP ${response.status}: ${response.statusText}`); - } - - const reader = response.body?.getReader(); - if (!reader) { - return Promise.reject('无法获取响应流'); - } - - const decoder = new TextDecoder(); - let buffer = ''; - let completedContent = ''; - let accumulatedContent = ''; - let citeLinks: Array<{ name: string; url: string }> = []; - let isFinished = false; - - while (!isFinished) { - const { done, value } = await reader.read(); - - if (done) break; - - const chunk = decoder.decode(value, { stream: true }); - buffer += chunk; - - const lines = buffer.split('\n'); - buffer = lines.pop() || ''; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const { dataStr, nextIndex } = parseDataString(line, lines, i); - i = nextIndex; - - if (!dataStr.trim()) continue; - - try { - const data: StreamData = JSON.parse(dataStr); - - if (data.streamData && !data.isFinished) { - await streamResponse({ - type: StreamDataAnswerTypeEnum.answer, - content: data.streamData - }); - accumulatedContent += data.streamData; - } - - if (data.customMessage?.memoChainData?.referenceDocuments) { - citeLinks = extractCiteLinks(data.customMessage.memoChainData.referenceDocuments); - } - - if (data.customMessage?.completedContent) { - completedContent = data.customMessage.completedContent; - } - - if (data.isFinished === true) { - isFinished = true; - break; - } - } catch { - // Ignore parse errors for malformed SSE data - continue; - } - } - } - - reader.releaseLock(); - - return { - content: completedContent || accumulatedContent, - citeLinks: citeLinks.length > 0 ? citeLinks : undefined - }; - } catch (error) { - return Promise.reject(getErrText(error)); - } -} diff --git a/modules/tool/packages/linkMemo/test/index.test.ts b/modules/tool/packages/linkMemo/test/index.test.ts deleted file mode 100644 index b70e289f..00000000 --- a/modules/tool/packages/linkMemo/test/index.test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { expect, test } from 'vitest'; -import tool from '..'; - -test(async () => { - expect(tool.name).toBeDefined(); - expect(tool.description).toBeDefined(); - expect(tool.cb).toBeDefined(); -});