diff --git a/web/package.json b/web/package.json index 7d348ed..2fc76b6 100644 --- a/web/package.json +++ b/web/package.json @@ -25,7 +25,7 @@ "@astrojs/vue": "^5.1.3", "@kevisual/cache": "^0.0.5", "@kevisual/context": "^0.0.4", - "@kevisual/query": "^0.0.33", + "@kevisual/query": "^0.0.34", "@kevisual/query-login": "^0.0.7", "@kevisual/registry": "^0.0.1", "@kevisual/router": "^0.0.52", @@ -34,6 +34,7 @@ "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-slot": "^1.2.4", "@tailwindcss/vite": "^4.1.18", + "@tanstack/react-table": "^8.21.3", "@uiw/react-md-editor": "^4.0.11", "antd": "^6.1.3", "astro": "^5.16.6", @@ -53,7 +54,7 @@ "react": "^19.2.3", "react-dom": "^19.2.3", "react-hook-form": "^7.69.0", - "react-resizable-panels": "^4.1.0", + "react-resizable-panels": "^4.2.0", "react-toastify": "^11.0.5", "tailwind-merge": "^3.4.0", "vue": "^3.5.26", @@ -63,10 +64,11 @@ "access": "public" }, "devDependencies": { - "@kevisual/api": "^0.0.14", + "@kevisual/api": "^0.0.16", "@kevisual/types": "^0.0.10", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", + "baseline-browser-mapping": "^2.9.11", "dotenv": "^17.2.3", "tailwindcss": "^4.1.18", "tw-animate-css": "^1.4.0" diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index dffb1ba..a7cc38c 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -27,11 +27,11 @@ importers: specifier: ^0.0.4 version: 0.0.4 '@kevisual/query': - specifier: ^0.0.33 - version: 0.0.33 + specifier: ^0.0.34 + version: 0.0.34 '@kevisual/query-login': specifier: ^0.0.7 - version: 0.0.7(@kevisual/query@0.0.33) + version: 0.0.7(@kevisual/query@0.0.34) '@kevisual/registry': specifier: ^0.0.1 version: 0.0.1(typescript@5.9.3) @@ -53,6 +53,9 @@ importers: '@tailwindcss/vite': specifier: ^4.1.18 version: 4.1.18(vite@6.4.1(@types/node@24.7.2)(jiti@2.6.1)(lightningcss@1.30.2)) + '@tanstack/react-table': + specifier: ^8.21.3 + version: 8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@uiw/react-md-editor': specifier: ^4.0.11 version: 4.0.11(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -111,8 +114,8 @@ importers: specifier: ^7.69.0 version: 7.69.0(react@19.2.3) react-resizable-panels: - specifier: ^4.1.0 - version: 4.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: ^4.2.0 + version: 4.2.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react-toastify: specifier: ^11.0.5 version: 11.0.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -127,8 +130,8 @@ importers: version: 5.0.9(@types/react@19.2.7)(react@19.2.3) devDependencies: '@kevisual/api': - specifier: ^0.0.14 - version: 0.0.14 + specifier: ^0.0.16 + version: 0.0.16 '@kevisual/types': specifier: ^0.0.10 version: 0.0.10 @@ -138,6 +141,9 @@ importers: '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) + baseline-browser-mapping: + specifier: ^2.9.11 + version: 2.9.11 dotenv: specifier: ^17.2.3 version: 17.2.3 @@ -723,8 +729,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@kevisual/api@0.0.14': - resolution: {integrity: sha512-GOs61Jvjxs+7PB8+iSPko9/RGeWENxltHueV75M6W0psRsnx/J+06I48/cO413FwCoqSOqpOoivdRgSENdHM9g==} + '@kevisual/api@0.0.16': + resolution: {integrity: sha512-JInnqWHjUxos1oWHe8dmwxWOMCRgv5nI/7HbSrzvHDQxHE6Egc3xA5iALUcRDdkNOnPz98ErZnLmSgHHJDOwYQ==} '@kevisual/cache@0.0.3': resolution: {integrity: sha512-BWEck69KYL96/ywjYVkML974RHjDJTj2ITQND1zFPR+hlBV1H1p55QZgSYRJCObg3EAV1S9Zic/fR2T4pfe8yg==} @@ -746,8 +752,8 @@ packages: peerDependencies: '@kevisual/query': ^0 - '@kevisual/query@0.0.33': - resolution: {integrity: sha512-3w74bcLpwV3z483eg8n0DgkftfjWC6iLONXBvfyjW6IZf6jMOuouFaM4Rk+uEsTgElU6XGMKseNTp6dlQdWYkg==} + '@kevisual/query@0.0.34': + resolution: {integrity: sha512-UHA0qEJYzU76pffUx0OhcOL5zKuxR/Kg269OHjrFm7+7RO85Qzv4ON1vUJDFp61hRuRVwiwOEKucQLHLE6UpMg==} '@kevisual/registry@0.0.1': resolution: {integrity: sha512-//OHu9m4JDrMjgP8o8dcjZd3D3IAUkRVlkTSviouZEH7r5m7mccA3Hvzw0XJ/lelx6exC6LWsyv6c4uV0Dp+gw==} @@ -1667,6 +1673,17 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 + '@tanstack/react-table@8.21.3': + resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + + '@tanstack/table-core@8.21.3': + resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} + engines: {node: '>=12'} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1925,8 +1942,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.16: - resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==} + baseline-browser-mapping@2.9.11: + resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} hasBin: true bcp-47-match@2.0.3: @@ -3101,8 +3118,8 @@ packages: '@types/react': optional: true - react-resizable-panels@4.1.0: - resolution: {integrity: sha512-8ZpOwdKQz6bCs2LGnfS6HuBITxkOLelSMzBX4DrWsgHaU3ukTPxmBNAeK8Bsp3LAEdtXeG6ll6UPN7OJNua4sw==} + react-resizable-panels@4.2.0: + resolution: {integrity: sha512-X/WbnyT/bgx09KEGvtJvaTr3axRrcBGcJdELIoGXZipCxc2hPwFsH/pfpVgwNVq5LpQxF/E5pPXGTQdjBnidPw==} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 @@ -4404,7 +4421,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@kevisual/api@0.0.14': + '@kevisual/api@0.0.16': dependencies: '@kevisual/js-filter': 0.0.3 '@kevisual/load': 0.0.6 @@ -4430,13 +4447,15 @@ snapshots: dependencies: eventemitter3: 5.0.1 - '@kevisual/query-login@0.0.7(@kevisual/query@0.0.33)': + '@kevisual/query-login@0.0.7(@kevisual/query@0.0.34)': dependencies: '@kevisual/cache': 0.0.3 - '@kevisual/query': 0.0.33 + '@kevisual/query': 0.0.34 dotenv: 17.2.3 - '@kevisual/query@0.0.33': {} + '@kevisual/query@0.0.34': + dependencies: + tslib: 2.8.1 '@kevisual/registry@0.0.1(typescript@5.9.3)': dependencies: @@ -5434,6 +5453,14 @@ snapshots: tailwindcss: 4.1.18 vite: 6.4.1(@types/node@24.7.2)(jiti@2.6.1)(lightningcss@1.30.2) + '@tanstack/react-table@8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@tanstack/table-core': 8.21.3 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + + '@tanstack/table-core@8.21.3': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.5 @@ -5930,7 +5957,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.8.16: {} + baseline-browser-mapping@2.9.11: {} bcp-47-match@2.0.3: {} @@ -5957,7 +5984,7 @@ snapshots: browserslist@4.26.3: dependencies: - baseline-browser-mapping: 2.8.16 + baseline-browser-mapping: 2.9.11 caniuse-lite: 1.0.30001750 electron-to-chromium: 1.5.235 node-releases: 2.0.23 @@ -7424,7 +7451,7 @@ snapshots: optionalDependencies: '@types/react': 19.2.7 - react-resizable-panels@4.1.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + react-resizable-panels@4.2.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) diff --git a/web/src/apps/chat/index.tsx b/web/src/apps/chat/index.tsx new file mode 100644 index 0000000..c2fc3a9 --- /dev/null +++ b/web/src/apps/chat/index.tsx @@ -0,0 +1,103 @@ +import { app } from '@/index.ts' +import { useStudioStore } from '../studio/store'; +import { useShallow } from 'zustand/shallow'; +import { useState } from 'react'; +import { query } from '@/modules/query.ts' +export const Chat = () => { + const studioStore = useStudioStore(useShallow((state) => ({ + routes: state.routes, + }))); + const [text, setText] = useState(''); + const onSend = async () => { + const { routes } = studioStore; + let callPrompts = ''; + const toolsList = routes.map((r, index) => + `${index + 1}. 工具名称: ${r.id}\n 描述: ${r.description}` + ).join('\n\n'); + + callPrompts = `你是一个 AI 助手,你可以使用以下工具来帮助用户完成任务: + +${toolsList} + +## 回复规则 +1. 如果用户的请求可以使用上述工具完成,请返回 JSON 格式数据 +2. 如果没有合适的工具,请直接分析并回答用户问题 + +## JSON 数据格式 +\`\`\`json +{ + "id": "工具的id", + "payload": { + // 工具所需的参数(如果需要) + // 例如: "id": "xxx", "name": "xxx" + } +} +\`\`\` + +注意: +- payload 中包含工具执行所需的所有参数 +- 如果工具不需要参数,payload 可以为空对象 {} +- 确保返回的 id 与上述工具列表中的工具名称完全匹配` + + const res = await query.post({ + path: 'ai', + payload: { + messages: [ + { + role: 'system', + content: callPrompts + }, + { + role: 'user', + content: text + } + ], + isJson: true + } + }) + console.log('发送消息', text, res); + if (res.code === 200) { + // 处理返回结果 + const payload = res.data?.action; + if (payload) { + const route = routes.find(r => r.id === payload.id); + console.log('找到工具', route); + const { path, key } = route || {}; + const { id, ...otherParams } = payload.payload || {}; + if (route) { + const r = await app.run({ path, key, ...otherParams }); + console.log('工具调用结果', r); + } else { + console.error('未找到对应工具', payload.id); + } + } + } + } + return
| + {flexRender( + header.column.columnDef.header, + header.getContext() + )} + | + ))} +
|---|
| + {flexRender(cell.column.columnDef.cell, cell.getContext())} + | + ))} +
diff --git a/web/src/apps/studio/store.ts b/web/src/apps/studio/store.ts
index 3a5f92d..e646378 100644
--- a/web/src/apps/studio/store.ts
+++ b/web/src/apps/studio/store.ts
@@ -5,7 +5,7 @@ import { toast } from 'react-toastify';
import { use } from '@kevisual/context'
import { MyCache } from '@kevisual/cache'
import { persist } from 'zustand/middleware';
-
+import { app } from '@/index.ts'
const historyReplace = (url: string) => {
if (window.history.replaceState) {
window.history.replaceState(null, '', url);
@@ -21,16 +21,17 @@ type RouteItem = {
type RouteViewList = Array