@myassis/gateway 1.0.18 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.js +27 -19
- package/dist/cli.js +18 -5
- package/dist/config/index.js +34 -11
- package/dist/index.js +1 -2
- package/dist/main.js +76 -71
- package/dist/middleware/auth.js +9 -5
- package/dist/middleware/errorHandler.js +9 -4
- package/dist/routes/agent.js +39 -37
- package/dist/routes/auth.js +32 -30
- package/dist/routes/chat.js +7 -5
- package/dist/routes/config.js +5 -3
- package/dist/routes/models.js +28 -23
- package/dist/routes/service.js +29 -24
- package/dist/routes/settings.js +26 -21
- package/dist/routes/skillHub.js +22 -17
- package/dist/routes/skills.js +25 -20
- package/dist/routes/tasks.js +24 -19
- package/dist/routes/upload.js +24 -17
- package/dist/routes/version.js +20 -19
- package/dist/services/HMSPushService.js +4 -1
- package/dist/services/LocalTaskService.js +12 -9
- package/dist/services/NotificationService.js +14 -11
- package/dist/services/ServiceManager.js +77 -65
- package/dist/services/TaskSchedulerService.js +33 -30
- package/dist/services/TaskService.js +27 -24
- package/dist/services/WebSocketService.js +14 -11
- package/dist/services/agent/Agent.js +13 -9
- package/dist/services/agent/AgentManager.js +32 -24
- package/dist/services/agent/AgentStore.js +7 -3
- package/dist/services/dataService.js +72 -69
- package/dist/services/index.js +25 -9
- package/dist/services/llm/LLMClient.js +17 -9
- package/dist/services/memory/MemoryManager.js +22 -18
- package/dist/services/model/ModelCapabilities.js +11 -7
- package/dist/services/model/index.js +17 -1
- package/dist/services/models.js +5 -1
- package/dist/services/session/MigrationManager.js +18 -11
- package/dist/services/session/Session.js +33 -29
- package/dist/services/session/SessionManager.js +26 -21
- package/dist/services/session/SessionStore.js +32 -25
- package/dist/services/session/index.js +8 -2
- package/dist/services/skills.js +4 -1
- package/dist/services/systemPrompt.js +23 -16
- package/dist/services/task/PushTokenStore.js +9 -5
- package/dist/services/task/TaskStore.js +10 -6
- package/dist/services/tools/calculator.js +4 -1
- package/dist/services/tools/edit.js +16 -10
- package/dist/services/tools/exec.js +25 -16
- package/dist/services/tools/fetch.js +30 -4
- package/dist/services/tools/file.js +41 -35
- package/dist/services/tools/index.js +44 -24
- package/dist/services/tools/keyboard.js +41 -38
- package/dist/services/tools/model.js +12 -9
- package/dist/services/tools/mouse.js +12 -9
- package/dist/services/tools/screenshot.js +9 -3
- package/dist/services/tools/search.js +34 -4
- package/dist/services/tools/sessionsSpawn.js +11 -8
- package/dist/services/tools/skill.js +19 -16
- package/dist/services/tools/task.js +12 -9
- package/dist/services/tools/types.js +2 -1
- package/dist/services/tools/webFetch.js +34 -4
- package/dist/stores/authStore.js +25 -19
- package/dist/stores/index.js +9 -3
- package/dist/stores/memoryStore.js +5 -2
- package/dist/stores/persistStore.js +20 -14
- package/package.json +11 -20
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.execTool = exports.clearSessionCwd = exports.setSessionCwd = exports.getSessionCwd = void 0;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const util_1 = require("util");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const shared_1 = require("@myassis/shared");
|
|
12
|
+
const logger = (0, shared_1.getLogger)('exec');
|
|
13
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
8
14
|
// 会话级工作目录状态:sessionId -> cwd
|
|
9
15
|
// 让 cd 命令能跨多次 exec 调用持久化工作目录
|
|
10
16
|
const sessionCwdMap = new Map();
|
|
@@ -12,15 +18,15 @@ const sessionCwdMap = new Map();
|
|
|
12
18
|
function resolveCdTarget(cdArg, currentCwd) {
|
|
13
19
|
const arg = cdArg.trim();
|
|
14
20
|
if (!arg)
|
|
15
|
-
return
|
|
21
|
+
return os_1.default.homedir(); // cd 无参数 → 回家目录
|
|
16
22
|
if (arg === '~' || arg.startsWith('~/')) {
|
|
17
|
-
return
|
|
23
|
+
return path_1.default.join(os_1.default.homedir(), arg.slice(1));
|
|
18
24
|
}
|
|
19
25
|
// Windows 盘符路径或 Unix 绝对路径
|
|
20
|
-
if (
|
|
21
|
-
return
|
|
26
|
+
if (path_1.default.isAbsolute(arg))
|
|
27
|
+
return path_1.default.resolve(arg);
|
|
22
28
|
// 相对路径:基于当前 cwd 解析
|
|
23
|
-
return
|
|
29
|
+
return path_1.default.resolve(currentCwd, arg);
|
|
24
30
|
}
|
|
25
31
|
/** 检查命令是否以 cd 开头,若是则提取目标路径(支持 cd /d D:\path 这种 Windows 写法)*/
|
|
26
32
|
function parseCdCommand(command) {
|
|
@@ -42,18 +48,21 @@ function parseCdCommand(command) {
|
|
|
42
48
|
return cut || '';
|
|
43
49
|
}
|
|
44
50
|
/** 获取某个 session 的当前工作目录 */
|
|
45
|
-
|
|
51
|
+
function getSessionCwd(sessionId) {
|
|
46
52
|
return sessionCwdMap.get(sessionId);
|
|
47
53
|
}
|
|
54
|
+
exports.getSessionCwd = getSessionCwd;
|
|
48
55
|
/** 设置某个 session 的工作目录 */
|
|
49
|
-
|
|
56
|
+
function setSessionCwd(sessionId, cwd) {
|
|
50
57
|
sessionCwdMap.set(sessionId, cwd);
|
|
51
58
|
}
|
|
59
|
+
exports.setSessionCwd = setSessionCwd;
|
|
52
60
|
/** 清除某个 session 的工作目录(可选,用于会话结束时清理) */
|
|
53
|
-
|
|
61
|
+
function clearSessionCwd(sessionId) {
|
|
54
62
|
sessionCwdMap.delete(sessionId);
|
|
55
63
|
}
|
|
56
|
-
|
|
64
|
+
exports.clearSessionCwd = clearSessionCwd;
|
|
65
|
+
exports.execTool = {
|
|
57
66
|
name: 'exec',
|
|
58
67
|
description: '在本地计算机上执行命令行命令。适用于运行系统命令、脚本、查看文件、执行程序等场景。',
|
|
59
68
|
parameters: {
|
|
@@ -1,11 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.fetchTool = void 0;
|
|
27
|
+
const shared_1 = require("@myassis/shared");
|
|
28
|
+
const logger = (0, shared_1.getLogger)('FetchTool');
|
|
3
29
|
let _undiciCache = null;
|
|
4
30
|
async function loadUndici() {
|
|
5
31
|
if (_undiciCache)
|
|
6
32
|
return _undiciCache;
|
|
7
33
|
try {
|
|
8
|
-
const undici = await
|
|
34
|
+
const undici = await Promise.resolve().then(() => __importStar(require('undici')));
|
|
9
35
|
_undiciCache = { ProxyAgent: undici.ProxyAgent, fetch: undici.fetch };
|
|
10
36
|
return _undiciCache;
|
|
11
37
|
}
|
|
@@ -84,7 +110,7 @@ function toTimeoutSignal(ms) {
|
|
|
84
110
|
const validMs = Number.isFinite(ms) && ms > 0 ? ms : 30000;
|
|
85
111
|
return AbortSignal.timeout(validMs);
|
|
86
112
|
}
|
|
87
|
-
|
|
113
|
+
exports.fetchTool = {
|
|
88
114
|
name: 'fetch',
|
|
89
115
|
description: '发送 HTTP 请求',
|
|
90
116
|
parameters: {
|
|
@@ -1,30 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fileTool = void 0;
|
|
1
7
|
/**
|
|
2
8
|
* 文件操作工具
|
|
3
9
|
* 提供文件和目录的基础操作:读取、写入、创建、删除、搜索等
|
|
4
10
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const logger = getLogger('FileTool');
|
|
12
|
-
const execAsync = promisify(exec);
|
|
11
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const os_1 = __importDefault(require("os"));
|
|
14
|
+
const child_process_1 = require("child_process");
|
|
15
|
+
const util_1 = require("util");
|
|
16
|
+
const shared_1 = require("@myassis/shared");
|
|
17
|
+
const logger = (0, shared_1.getLogger)('FileTool');
|
|
18
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
13
19
|
const DEFAULT_EXCLUDE_DIRS = [
|
|
14
20
|
'node_modules', '.git', '.svn', '.hg', 'dist', 'build', 'out', '.next', '.nuxt',
|
|
15
21
|
'.cache', '__pycache__', '.venv', '.env', '.idea', '.vscode', '.DS_Store',
|
|
16
22
|
'target', 'Pods', '.gradle', '.dart_tool',
|
|
17
23
|
];
|
|
18
24
|
const ALLOWED_DIRS = [
|
|
19
|
-
|
|
25
|
+
os_1.default.homedir(), '/tmp', process.env.GATEWAY_DIR || '/workspace/projects/gateway',
|
|
20
26
|
process.env.USER_HOME || '',
|
|
21
27
|
].filter(Boolean);
|
|
22
28
|
function isPathAllowed(_filePath) {
|
|
23
29
|
return true;
|
|
24
30
|
}
|
|
25
31
|
async function listDir(dirPath) {
|
|
26
|
-
const items = await
|
|
27
|
-
return items.map(item => ({ name: item.name, type: item.isDirectory() ? 'directory' : 'file', path:
|
|
32
|
+
const items = await promises_1.default.readdir(dirPath, { withFileTypes: true });
|
|
33
|
+
return items.map(item => ({ name: item.name, type: item.isDirectory() ? 'directory' : 'file', path: path_1.default.join(dirPath, item.name) }));
|
|
28
34
|
}
|
|
29
35
|
function isDirExcluded(dirName, excludeDirs) {
|
|
30
36
|
const lower = dirName.toLowerCase();
|
|
@@ -83,11 +89,11 @@ async function searchFiles(dirPath, query, maxResults = 50, excludeDirs = DEFAUL
|
|
|
83
89
|
if (results.length >= maxResults)
|
|
84
90
|
return;
|
|
85
91
|
try {
|
|
86
|
-
const items = await
|
|
92
|
+
const items = await promises_1.default.readdir(dir, { withFileTypes: true });
|
|
87
93
|
for (const item of items) {
|
|
88
94
|
if (results.length >= maxResults)
|
|
89
95
|
break;
|
|
90
|
-
const fullPath =
|
|
96
|
+
const fullPath = path_1.default.join(dir, item.name);
|
|
91
97
|
if (item.isDirectory() && !item.name.startsWith('.') && !isDirExcluded(item.name, excludeDirs)) {
|
|
92
98
|
await searchDir(fullPath);
|
|
93
99
|
}
|
|
@@ -104,7 +110,7 @@ async function searchFiles(dirPath, query, maxResults = 50, excludeDirs = DEFAUL
|
|
|
104
110
|
await searchDir(dirPath);
|
|
105
111
|
return results;
|
|
106
112
|
}
|
|
107
|
-
|
|
113
|
+
exports.fileTool = {
|
|
108
114
|
name: 'file',
|
|
109
115
|
description: '文件和目录操作工具',
|
|
110
116
|
parameters: {
|
|
@@ -138,12 +144,12 @@ export const fileTool = {
|
|
|
138
144
|
return { success: false, errorMessage: `路径不在允许范围内` };
|
|
139
145
|
switch (action) {
|
|
140
146
|
case 'read': {
|
|
141
|
-
const stats = await
|
|
147
|
+
const stats = await promises_1.default.stat(filePath);
|
|
142
148
|
if (stats.isDirectory()) {
|
|
143
149
|
const items = await listDir(filePath);
|
|
144
150
|
return { success: true, output: JSON.stringify({ type: 'directory', items }) };
|
|
145
151
|
}
|
|
146
|
-
const fileContent = await
|
|
152
|
+
const fileContent = await promises_1.default.readFile(filePath, 'utf-8');
|
|
147
153
|
// split('\n') 会保留末尾空行,用 filter(Boolean) 去掉末尾空元素
|
|
148
154
|
// 保持一致性:无论文件是否以 \n 结尾,行号都从 1 开始,终点为总行数
|
|
149
155
|
const allLines = fileContent.split('\n').filter((_, i, arr) => !(i === arr.length - 1 && _ === ''));
|
|
@@ -169,27 +175,27 @@ export const fileTool = {
|
|
|
169
175
|
case 'write': {
|
|
170
176
|
if (content === undefined)
|
|
171
177
|
return { success: false, errorMessage: 'write 操作需要提供 content' };
|
|
172
|
-
const dir =
|
|
173
|
-
await
|
|
174
|
-
await
|
|
178
|
+
const dir = path_1.default.dirname(filePath);
|
|
179
|
+
await promises_1.default.mkdir(dir, { recursive: true });
|
|
180
|
+
await promises_1.default.writeFile(filePath, content, 'utf-8');
|
|
175
181
|
return { success: true, output: JSON.stringify({ path: filePath, size: content.length }) };
|
|
176
182
|
}
|
|
177
183
|
case 'mkdir': {
|
|
178
|
-
await
|
|
184
|
+
await promises_1.default.mkdir(filePath, { recursive: true });
|
|
179
185
|
return { success: true, output: JSON.stringify({ path: filePath }) };
|
|
180
186
|
}
|
|
181
187
|
case 'delete': {
|
|
182
|
-
const stats = await
|
|
188
|
+
const stats = await promises_1.default.stat(filePath);
|
|
183
189
|
if (stats.isDirectory())
|
|
184
190
|
return { success: false, errorMessage: 'delete 用于删除文件,删除目录请使用 rmdir' };
|
|
185
|
-
await
|
|
191
|
+
await promises_1.default.unlink(filePath);
|
|
186
192
|
return { success: true, output: JSON.stringify({ path: filePath }) };
|
|
187
193
|
}
|
|
188
194
|
case 'rmdir': {
|
|
189
|
-
const rmdirStat = await
|
|
195
|
+
const rmdirStat = await promises_1.default.stat(filePath);
|
|
190
196
|
if (!rmdirStat.isDirectory())
|
|
191
197
|
return { success: false, errorMessage: 'rmdir 用于删除目录' };
|
|
192
|
-
await
|
|
198
|
+
await promises_1.default.rm(filePath, { recursive: true });
|
|
193
199
|
return { success: true, output: JSON.stringify({ path: filePath }) };
|
|
194
200
|
}
|
|
195
201
|
case 'list': {
|
|
@@ -197,10 +203,10 @@ export const fileTool = {
|
|
|
197
203
|
return { success: true, output: JSON.stringify({ total: items.length, items }) };
|
|
198
204
|
}
|
|
199
205
|
case 'open': {
|
|
200
|
-
const stats = await
|
|
201
|
-
const targetPath = stats.isFile() ?
|
|
206
|
+
const stats = await promises_1.default.stat(filePath);
|
|
207
|
+
const targetPath = stats.isFile() ? path_1.default.dirname(filePath) : filePath;
|
|
202
208
|
let command, ignoreExitCode = false;
|
|
203
|
-
switch (
|
|
209
|
+
switch (os_1.default.platform()) {
|
|
204
210
|
case 'darwin':
|
|
205
211
|
command = `open "${targetPath}"`;
|
|
206
212
|
break;
|
|
@@ -219,14 +225,14 @@ export const fileTool = {
|
|
|
219
225
|
if (!ignoreExitCode || error.code !== 1)
|
|
220
226
|
throw error;
|
|
221
227
|
}
|
|
222
|
-
return { success: true, output: JSON.stringify({ path: targetPath, platform:
|
|
228
|
+
return { success: true, output: JSON.stringify({ path: targetPath, platform: os_1.default.platform() }) };
|
|
223
229
|
}
|
|
224
230
|
case 'search': {
|
|
225
231
|
if (!searchQuery)
|
|
226
232
|
return { success: false, errorMessage: 'search 操作需要提供 searchQuery' };
|
|
227
|
-
let searchRoot = filePath ||
|
|
233
|
+
let searchRoot = filePath || os_1.default.homedir();
|
|
228
234
|
try {
|
|
229
|
-
const rootStat = await
|
|
235
|
+
const rootStat = await promises_1.default.stat(searchRoot);
|
|
230
236
|
if (!rootStat.isDirectory())
|
|
231
237
|
return { success: false, errorMessage: `path 必须是目录` };
|
|
232
238
|
}
|
|
@@ -239,7 +245,7 @@ export const fileTool = {
|
|
|
239
245
|
case 'searchContent': {
|
|
240
246
|
if (!searchQuery)
|
|
241
247
|
return { success: false, errorMessage: 'searchContent 操作需要提供 searchQuery' };
|
|
242
|
-
const stats = await
|
|
248
|
+
const stats = await promises_1.default.stat(filePath);
|
|
243
249
|
const isDir = stats.isDirectory();
|
|
244
250
|
const results = [];
|
|
245
251
|
const maxContent = args.maxContentResults || 20;
|
|
@@ -248,7 +254,7 @@ export const fileTool = {
|
|
|
248
254
|
const BINARY_EXTS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.webp', '.svg', '.mp3', '.mp4', '.avi', '.mov', '.wav', '.flac', '.zip', '.tar', '.gz', '.rar', '.7z', '.exe', '.dll', '.so', '.dylib', '.bin', '.dat', '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.sqlite', '.db', '.woff', '.woff2', '.ttf', '.eot', '.class', '.jar', '.pyc', '.o', '.obj']);
|
|
249
255
|
async function searchInFile(targetPath) {
|
|
250
256
|
try {
|
|
251
|
-
const fileContent = await
|
|
257
|
+
const fileContent = await promises_1.default.readFile(targetPath, 'utf-8');
|
|
252
258
|
const lines = fileContent.split('\n');
|
|
253
259
|
for (let i = 0; i < lines.length; i++) {
|
|
254
260
|
if (results.length >= maxContent)
|
|
@@ -273,16 +279,16 @@ export const fileTool = {
|
|
|
273
279
|
if (results.length >= maxContent)
|
|
274
280
|
return;
|
|
275
281
|
try {
|
|
276
|
-
const items = await
|
|
282
|
+
const items = await promises_1.default.readdir(dirPath, { withFileTypes: true });
|
|
277
283
|
for (const item of items) {
|
|
278
284
|
if (results.length >= maxContent)
|
|
279
285
|
break;
|
|
280
|
-
const fullPath =
|
|
286
|
+
const fullPath = path_1.default.join(dirPath, item.name);
|
|
281
287
|
if (item.isDirectory() && !item.name.startsWith('.') && !isDirExcluded(item.name, effectiveExcludeDirs)) {
|
|
282
288
|
await searchDirRecursive(fullPath);
|
|
283
289
|
}
|
|
284
290
|
else if (item.isFile()) {
|
|
285
|
-
const ext =
|
|
291
|
+
const ext = path_1.default.extname(item.name).toLowerCase();
|
|
286
292
|
if (!BINARY_EXTS.has(ext))
|
|
287
293
|
await searchInFile(fullPath);
|
|
288
294
|
}
|
|
@@ -1,40 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.getToolDefinitions = exports.executeTool = exports.getToolByName = exports.tools = void 0;
|
|
1
18
|
/**
|
|
2
19
|
* 工具定义集合
|
|
3
20
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
searchTool, calculatorTool, screenshotTool, keyboardTool, mouseTool,
|
|
21
|
-
skillTool, execTool, taskTool, modelTool, fetchTool,
|
|
22
|
-
editTool, webFetchTool, fileTool, sessionsSpawnTool
|
|
21
|
+
__exportStar(require("./types.js"), exports);
|
|
22
|
+
const search_js_1 = require("./search.js");
|
|
23
|
+
const calculator_js_1 = require("./calculator.js");
|
|
24
|
+
const screenshot_js_1 = require("./screenshot.js");
|
|
25
|
+
const keyboard_js_1 = require("./keyboard.js");
|
|
26
|
+
const mouse_js_1 = require("./mouse.js");
|
|
27
|
+
const fetch_js_1 = require("./fetch.js");
|
|
28
|
+
const skill_js_1 = require("./skill.js");
|
|
29
|
+
const exec_js_1 = require("./exec.js");
|
|
30
|
+
const file_js_1 = require("./file.js");
|
|
31
|
+
const task_js_1 = require("./task.js");
|
|
32
|
+
const model_js_1 = require("./model.js");
|
|
33
|
+
const edit_js_1 = require("./edit.js");
|
|
34
|
+
const webFetch_js_1 = require("./webFetch.js");
|
|
35
|
+
const sessionsSpawn_js_1 = require("./sessionsSpawn.js");
|
|
36
|
+
exports.tools = [
|
|
37
|
+
search_js_1.searchTool, calculator_js_1.calculatorTool, screenshot_js_1.screenshotTool, keyboard_js_1.keyboardTool, mouse_js_1.mouseTool,
|
|
38
|
+
skill_js_1.skillTool, exec_js_1.execTool, task_js_1.taskTool, model_js_1.modelTool, fetch_js_1.fetchTool,
|
|
39
|
+
edit_js_1.editTool, webFetch_js_1.webFetchTool, file_js_1.fileTool, sessionsSpawn_js_1.sessionsSpawnTool
|
|
23
40
|
];
|
|
24
|
-
|
|
25
|
-
return tools.find(tool => tool.name === name);
|
|
41
|
+
function getToolByName(name) {
|
|
42
|
+
return exports.tools.find(tool => tool.name === name);
|
|
26
43
|
}
|
|
44
|
+
exports.getToolByName = getToolByName;
|
|
27
45
|
/**
|
|
28
46
|
* 执行工具调用,返回 ToolResult(AI 可见格式)
|
|
29
47
|
*/
|
|
30
|
-
|
|
48
|
+
async function executeTool(name, args, sessionId, messageId, userId) {
|
|
31
49
|
const tool = getToolByName(name);
|
|
32
50
|
if (!tool)
|
|
33
51
|
throw new Error(`Tool not found: ${name}`);
|
|
34
52
|
return await tool.handler(args, sessionId, messageId, userId);
|
|
35
53
|
}
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
exports.executeTool = executeTool;
|
|
55
|
+
function getToolDefinitions() {
|
|
56
|
+
return exports.tools.map(tool => ({
|
|
38
57
|
type: 'function',
|
|
39
58
|
function: {
|
|
40
59
|
name: tool.name,
|
|
@@ -47,3 +66,4 @@ export function getToolDefinitions() {
|
|
|
47
66
|
},
|
|
48
67
|
}));
|
|
49
68
|
}
|
|
69
|
+
exports.getToolDefinitions = getToolDefinitions;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.keyboardTool = void 0;
|
|
4
|
+
const nut_js_1 = require("@nut-tree/nut-js");
|
|
2
5
|
// 可打印 ASCII 字符范围(空格到 ~)
|
|
3
6
|
const PRINTABLE_ASCII_START = 32;
|
|
4
7
|
const PRINTABLE_ASCII_END = 126;
|
|
@@ -16,42 +19,42 @@ function validateText(text) {
|
|
|
16
19
|
// 按键名称到 nut-js Key 的映射
|
|
17
20
|
const keyMap = {
|
|
18
21
|
// 常用键
|
|
19
|
-
enter: Key.Enter,
|
|
20
|
-
return: Key.Enter,
|
|
21
|
-
escape: Key.Escape,
|
|
22
|
-
esc: Key.Escape,
|
|
23
|
-
tab: Key.Tab,
|
|
24
|
-
space: Key.Space,
|
|
25
|
-
backspace: Key.Backspace,
|
|
26
|
-
delete: Key.Delete,
|
|
27
|
-
del: Key.Delete,
|
|
22
|
+
enter: nut_js_1.Key.Enter,
|
|
23
|
+
return: nut_js_1.Key.Enter,
|
|
24
|
+
escape: nut_js_1.Key.Escape,
|
|
25
|
+
esc: nut_js_1.Key.Escape,
|
|
26
|
+
tab: nut_js_1.Key.Tab,
|
|
27
|
+
space: nut_js_1.Key.Space,
|
|
28
|
+
backspace: nut_js_1.Key.Backspace,
|
|
29
|
+
delete: nut_js_1.Key.Delete,
|
|
30
|
+
del: nut_js_1.Key.Delete,
|
|
28
31
|
// 方向键
|
|
29
|
-
up: Key.Up,
|
|
30
|
-
down: Key.Down,
|
|
31
|
-
left: Key.Left,
|
|
32
|
-
right: Key.Right,
|
|
32
|
+
up: nut_js_1.Key.Up,
|
|
33
|
+
down: nut_js_1.Key.Down,
|
|
34
|
+
left: nut_js_1.Key.Left,
|
|
35
|
+
right: nut_js_1.Key.Right,
|
|
33
36
|
// 功能键
|
|
34
|
-
f1: Key.F1,
|
|
35
|
-
f2: Key.F2,
|
|
36
|
-
f3: Key.F3,
|
|
37
|
-
f4: Key.F4,
|
|
38
|
-
f5: Key.F5,
|
|
39
|
-
f6: Key.F6,
|
|
40
|
-
f7: Key.F7,
|
|
41
|
-
f8: Key.F8,
|
|
42
|
-
f9: Key.F9,
|
|
43
|
-
f10: Key.F10,
|
|
44
|
-
f11: Key.F11,
|
|
45
|
-
f12: Key.F12,
|
|
37
|
+
f1: nut_js_1.Key.F1,
|
|
38
|
+
f2: nut_js_1.Key.F2,
|
|
39
|
+
f3: nut_js_1.Key.F3,
|
|
40
|
+
f4: nut_js_1.Key.F4,
|
|
41
|
+
f5: nut_js_1.Key.F5,
|
|
42
|
+
f6: nut_js_1.Key.F6,
|
|
43
|
+
f7: nut_js_1.Key.F7,
|
|
44
|
+
f8: nut_js_1.Key.F8,
|
|
45
|
+
f9: nut_js_1.Key.F9,
|
|
46
|
+
f10: nut_js_1.Key.F10,
|
|
47
|
+
f11: nut_js_1.Key.F11,
|
|
48
|
+
f12: nut_js_1.Key.F12,
|
|
46
49
|
// 修饰键
|
|
47
|
-
ctrl: Key.LeftControl,
|
|
48
|
-
control: Key.LeftControl,
|
|
49
|
-
alt: Key.LeftAlt,
|
|
50
|
-
shift: Key.LeftShift,
|
|
51
|
-
meta: Key.LeftSuper,
|
|
52
|
-
win: Key.LeftSuper,
|
|
53
|
-
cmd: Key.LeftSuper,
|
|
54
|
-
command: Key.LeftSuper,
|
|
50
|
+
ctrl: nut_js_1.Key.LeftControl,
|
|
51
|
+
control: nut_js_1.Key.LeftControl,
|
|
52
|
+
alt: nut_js_1.Key.LeftAlt,
|
|
53
|
+
shift: nut_js_1.Key.LeftShift,
|
|
54
|
+
meta: nut_js_1.Key.LeftSuper,
|
|
55
|
+
win: nut_js_1.Key.LeftSuper,
|
|
56
|
+
cmd: nut_js_1.Key.LeftSuper,
|
|
57
|
+
command: nut_js_1.Key.LeftSuper,
|
|
55
58
|
};
|
|
56
59
|
// 解析组合键,如 "Ctrl+C" 或 "Alt+Shift+F4"
|
|
57
60
|
function parseHotkey(keysStr) {
|
|
@@ -83,7 +86,7 @@ function parseKey(keyStr) {
|
|
|
83
86
|
}
|
|
84
87
|
throw new Error(`未知按键: ${keyStr}`);
|
|
85
88
|
}
|
|
86
|
-
|
|
89
|
+
exports.keyboardTool = {
|
|
87
90
|
name: 'keyboard',
|
|
88
91
|
description: '控制键盘输入和按键操作',
|
|
89
92
|
parameters: {
|
|
@@ -115,14 +118,14 @@ export const keyboardTool = {
|
|
|
115
118
|
if (!validation.valid) {
|
|
116
119
|
return { success: false, errorMessage: `文本包含不可输入字符: "${validation.invalidChar}" (字符码: ${validation.charCode})` };
|
|
117
120
|
}
|
|
118
|
-
await keyboard.type(text);
|
|
121
|
+
await nut_js_1.keyboard.type(text);
|
|
119
122
|
return { success: true, output: `已输入文本: "${text}"` };
|
|
120
123
|
case 'press':
|
|
121
124
|
if (typeof key !== 'string') {
|
|
122
125
|
return { success: false, errorMessage: 'press 操作需要 key 参数' };
|
|
123
126
|
}
|
|
124
127
|
const parsedKey = parseKey(key);
|
|
125
|
-
await keyboard.pressKey(parsedKey);
|
|
128
|
+
await nut_js_1.keyboard.pressKey(parsedKey);
|
|
126
129
|
return { success: true, output: `已按下按键: ${key}` };
|
|
127
130
|
case 'hotkey':
|
|
128
131
|
if (typeof keys !== 'string') {
|
|
@@ -132,7 +135,7 @@ export const keyboardTool = {
|
|
|
132
135
|
if (hotkeys.length === 0) {
|
|
133
136
|
return { success: false, errorMessage: '无法解析组合键' };
|
|
134
137
|
}
|
|
135
|
-
await keyboard.pressKey(...hotkeys);
|
|
138
|
+
await nut_js_1.keyboard.pressKey(...hotkeys);
|
|
136
139
|
return { success: true, output: `已执行组合键: ${keys}` };
|
|
137
140
|
default:
|
|
138
141
|
return { success: false, errorMessage: `未知的键盘操作: ${action}` };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.modelTool = void 0;
|
|
4
|
+
const dataService_js_1 = require("../dataService.js");
|
|
5
|
+
const index_js_1 = require("../../stores/index.js");
|
|
6
|
+
exports.modelTool = {
|
|
4
7
|
name: 'model',
|
|
5
8
|
description: '模型管理工具',
|
|
6
9
|
parameters: {
|
|
@@ -25,10 +28,10 @@ export const modelTool = {
|
|
|
25
28
|
handler: async (args, sessionId, messageId, userId) => {
|
|
26
29
|
try {
|
|
27
30
|
const { action, modelId, modelName, modelIdName, baseUrl, apiKey, provider = 'doubao', isPrimary = false, supportsToolCall = true } = args;
|
|
28
|
-
const token = authStore.get(userId).accessToken;
|
|
31
|
+
const token = index_js_1.authStore.get(userId).accessToken;
|
|
29
32
|
switch (action) {
|
|
30
33
|
case 'list': {
|
|
31
|
-
const response = await modelsService.list(token);
|
|
34
|
+
const response = await dataService_js_1.modelsService.list(token);
|
|
32
35
|
if (!response.success)
|
|
33
36
|
return { success: false, errorMessage: response.error || '获取列表失败' };
|
|
34
37
|
const models = response.data || [];
|
|
@@ -37,7 +40,7 @@ export const modelTool = {
|
|
|
37
40
|
case 'add': {
|
|
38
41
|
if (!modelName || !baseUrl || !modelIdName)
|
|
39
42
|
return { success: false, errorMessage: '添加模型需要提供模型名称、模型 ID 和 API 地址' };
|
|
40
|
-
const response = await modelsService.create({ modelName, modelId: modelIdName, baseUrl, apiKey, provider, isPrimary, supportsToolCall }, token);
|
|
43
|
+
const response = await dataService_js_1.modelsService.create({ modelName, modelId: modelIdName, baseUrl, apiKey, provider, isPrimary, supportsToolCall }, token);
|
|
41
44
|
if (!response.success)
|
|
42
45
|
return { success: false, errorMessage: response.error || '添加失败' };
|
|
43
46
|
return { success: true, output: JSON.stringify({ model: response.data }) };
|
|
@@ -56,7 +59,7 @@ export const modelTool = {
|
|
|
56
59
|
updateData.isPrimary = isPrimary;
|
|
57
60
|
if (supportsToolCall !== undefined)
|
|
58
61
|
updateData.supportsToolCall = supportsToolCall;
|
|
59
|
-
const response = await modelsService.update(modelId, updateData, token);
|
|
62
|
+
const response = await dataService_js_1.modelsService.update(modelId, updateData, token);
|
|
60
63
|
if (!response.success)
|
|
61
64
|
return { success: false, errorMessage: response.error || '更新失败' };
|
|
62
65
|
return { success: true, output: JSON.stringify({ model: response.data }) };
|
|
@@ -64,7 +67,7 @@ export const modelTool = {
|
|
|
64
67
|
case 'delete': {
|
|
65
68
|
if (!modelId)
|
|
66
69
|
return { success: false, errorMessage: '删除模型需要提供模型 ID' };
|
|
67
|
-
const response = await modelsService.delete(modelId, token);
|
|
70
|
+
const response = await dataService_js_1.modelsService.delete(modelId, token);
|
|
68
71
|
if (!response.success)
|
|
69
72
|
return { success: false, errorMessage: response.error || '删除失败' };
|
|
70
73
|
return { success: true };
|
|
@@ -72,7 +75,7 @@ export const modelTool = {
|
|
|
72
75
|
case 'setPrimary': {
|
|
73
76
|
if (!modelId)
|
|
74
77
|
return { success: false, errorMessage: '设为默认需要提供模型 ID' };
|
|
75
|
-
const response = await modelsService.setPrimary(modelId, token);
|
|
78
|
+
const response = await dataService_js_1.modelsService.setPrimary(modelId, token);
|
|
76
79
|
if (!response.success)
|
|
77
80
|
return { success: false, errorMessage: response.error || '设置失败' };
|
|
78
81
|
return { success: true };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mouseTool = void 0;
|
|
4
|
+
const nut_js_1 = require("@nut-tree/nut-js");
|
|
5
|
+
exports.mouseTool = {
|
|
3
6
|
name: 'mouse',
|
|
4
7
|
description: '控制鼠标移动、点击和滚轮操作',
|
|
5
8
|
parameters: {
|
|
@@ -25,24 +28,24 @@ export const mouseTool = {
|
|
|
25
28
|
if (typeof x !== 'number' || typeof y !== 'number') {
|
|
26
29
|
return { success: false, errorMessage: 'move 操作需要 x 和 y 坐标' };
|
|
27
30
|
}
|
|
28
|
-
await mouse.setPosition({ x, y });
|
|
31
|
+
await nut_js_1.mouse.setPosition({ x, y });
|
|
29
32
|
return { success: true, output: `鼠标移动到 (${x}, ${y})` };
|
|
30
33
|
case 'click':
|
|
31
34
|
case 'rightClick':
|
|
32
35
|
case 'doubleClick':
|
|
33
36
|
if (action === 'doubleClick') {
|
|
34
|
-
await mouse.click(Button.LEFT);
|
|
37
|
+
await nut_js_1.mouse.click(nut_js_1.Button.LEFT);
|
|
35
38
|
await new Promise(r => setTimeout(r, 100));
|
|
36
39
|
}
|
|
37
|
-
const btn = button === 'right' ? Button.RIGHT : button === 'middle' ? Button.MIDDLE : Button.LEFT;
|
|
38
|
-
await mouse.click(btn);
|
|
40
|
+
const btn = button === 'right' ? nut_js_1.Button.RIGHT : button === 'middle' ? nut_js_1.Button.MIDDLE : nut_js_1.Button.LEFT;
|
|
41
|
+
await nut_js_1.mouse.click(btn);
|
|
39
42
|
return { success: true, output: `${button} 键${action === 'doubleClick' ? '双' : ''}击成功` };
|
|
40
43
|
case 'scroll':
|
|
41
|
-
await mouse.scrollDown(scrollY);
|
|
42
|
-
await mouse.scrollRight(scrollX);
|
|
44
|
+
await nut_js_1.mouse.scrollDown(scrollY);
|
|
45
|
+
await nut_js_1.mouse.scrollRight(scrollX);
|
|
43
46
|
return { success: true, output: `滚动 (${scrollX}, ${scrollY})` };
|
|
44
47
|
case 'position':
|
|
45
|
-
const pos = await mouse.getPosition();
|
|
48
|
+
const pos = await nut_js_1.mouse.getPosition();
|
|
46
49
|
return { success: true, output: `当前鼠标位置 (${pos.x}, ${pos.y})` };
|
|
47
50
|
default:
|
|
48
51
|
return { success: false, errorMessage: `未知的鼠标操作: ${action}` };
|