@myassis/gateway 1.0.21 → 1.0.22
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/config/index.js +13 -1
- package/dist/routes/agent.js +2 -2
- package/dist/services/llm/LLMClient.js +1 -1
- package/dist/services/session/Session.js +29 -3
- package/dist/services/session/SessionStore.js +13 -0
- package/dist/services/tools/search.js +5 -7
- package/dist/services/tools/webFetch.js +5 -7
- package/package.json +13 -10
- package/scripts/pkg-build-win.js +50 -0
package/dist/config/index.js
CHANGED
|
@@ -34,6 +34,9 @@ const fs = __importStar(require("fs"));
|
|
|
34
34
|
* dist/config/index.js → 上三级 = 包根目录
|
|
35
35
|
*/
|
|
36
36
|
function getPackageRootDir() {
|
|
37
|
+
if (process.pkg) {
|
|
38
|
+
return path.dirname(process.execPath);
|
|
39
|
+
}
|
|
37
40
|
return path.resolve(__dirname, '..', '..');
|
|
38
41
|
}
|
|
39
42
|
const getEnvPath = () => {
|
|
@@ -42,7 +45,16 @@ const getEnvPath = () => {
|
|
|
42
45
|
if (fs.existsSync(cwdEnvPath)) {
|
|
43
46
|
return cwdEnvPath;
|
|
44
47
|
}
|
|
45
|
-
// 2.
|
|
48
|
+
// 2. pkg 环境:从 snapshot 虚拟路径读取打包的 .env
|
|
49
|
+
if (process.pkg) {
|
|
50
|
+
// __dirname 在 pkg 中指向 /snapshot/pocketclaw/gateway/dist/config
|
|
51
|
+
// 打包的 .env 在 /snapshot/pocketclaw/gateway/dist/.env
|
|
52
|
+
const snapshotEnvPath = path.resolve(__dirname, '..', '.env');
|
|
53
|
+
if (fs.existsSync(snapshotEnvPath)) {
|
|
54
|
+
return snapshotEnvPath;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 3. 包安装目录(随包发布的默认 .env)
|
|
46
58
|
const pkgEnvPath = path.join(getPackageRootDir(), 'dist', '.env');
|
|
47
59
|
if (fs.existsSync(pkgEnvPath)) {
|
|
48
60
|
return pkgEnvPath;
|
package/dist/routes/agent.js
CHANGED
|
@@ -433,8 +433,8 @@ router.post('/sessions/:sessionId/stream', ensureAgentManager, async (req, res)
|
|
|
433
433
|
const userId = req.userId;
|
|
434
434
|
const { sessionId } = req.params;
|
|
435
435
|
const { content, attachments, userMessageId, assistantMessageId } = req.body;
|
|
436
|
-
if (!content) {
|
|
437
|
-
return res.status(400).json({ success: false, error: 'Content
|
|
436
|
+
if (!content && attachments.length === 0) {
|
|
437
|
+
return res.status(400).json({ success: false, error: 'Content or attachments are required' });
|
|
438
438
|
}
|
|
439
439
|
// Find session directly
|
|
440
440
|
const session = (0, index_js_2.getSessionManager)(userId).getSession(sessionId);
|
|
@@ -400,7 +400,7 @@ class LLMClient {
|
|
|
400
400
|
}
|
|
401
401
|
const tokens = JSON.stringify(body).length;
|
|
402
402
|
logger.debug('tokens', tokens);
|
|
403
|
-
if (tokens > 200000) {
|
|
403
|
+
if (tokens > 200000 && !existAttachments) {
|
|
404
404
|
logger.warn('message is too large and has writen to the file debug.json');
|
|
405
405
|
await promises_1.default.writeFile('debug.json', JSON.stringify(body.messages), 'utf-8');
|
|
406
406
|
throw Error('exceed max message tokens');
|
|
@@ -110,8 +110,22 @@ class Session {
|
|
|
110
110
|
// 将附件统一为 Attachment 对象格式
|
|
111
111
|
const normalizedAttachments = (attachments || []).map((att) => {
|
|
112
112
|
if (typeof att === 'string') {
|
|
113
|
-
// URL
|
|
113
|
+
// 可能是 base64 data URL 或普通 URL
|
|
114
114
|
const url = att;
|
|
115
|
+
const mimeMatch = url.match(/^data:([^;]+)/);
|
|
116
|
+
if (mimeMatch) {
|
|
117
|
+
// base64 data URL: 从 MIME 识别类型
|
|
118
|
+
const mime = mimeMatch[1];
|
|
119
|
+
let type = 'file';
|
|
120
|
+
if (mime.startsWith('image/'))
|
|
121
|
+
type = 'image';
|
|
122
|
+
else if (mime.startsWith('video/'))
|
|
123
|
+
type = 'video';
|
|
124
|
+
else if (mime.startsWith('audio/'))
|
|
125
|
+
type = 'audio';
|
|
126
|
+
return { type, name: 'attachment', url };
|
|
127
|
+
}
|
|
128
|
+
// 普通 URL: 从后缀识别类型
|
|
115
129
|
const name = url.split('/').pop().split('?')[0] || 'attachment';
|
|
116
130
|
const ext = name.split('.').pop()?.toLowerCase() || '';
|
|
117
131
|
const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'];
|
|
@@ -127,10 +141,22 @@ class Session {
|
|
|
127
141
|
return { type, name, url };
|
|
128
142
|
}
|
|
129
143
|
// 已经是对象格式,确保有必要字段
|
|
144
|
+
const url = att.url || att.uri || '';
|
|
145
|
+
const mimeMatch = url.match(/^data:([^;]+)/);
|
|
146
|
+
let type = att.type || 'file';
|
|
147
|
+
if (!att.type && mimeMatch) {
|
|
148
|
+
const mime = mimeMatch[1];
|
|
149
|
+
if (mime.startsWith('image/'))
|
|
150
|
+
type = 'image';
|
|
151
|
+
else if (mime.startsWith('video/'))
|
|
152
|
+
type = 'video';
|
|
153
|
+
else if (mime.startsWith('audio/'))
|
|
154
|
+
type = 'audio';
|
|
155
|
+
}
|
|
130
156
|
return {
|
|
131
|
-
type
|
|
157
|
+
type,
|
|
132
158
|
name: att.name || 'attachment',
|
|
133
|
-
url
|
|
159
|
+
url,
|
|
134
160
|
size: att.size,
|
|
135
161
|
mimeType: att.mimeType,
|
|
136
162
|
};
|
|
@@ -15,6 +15,12 @@ const logger = (0, shared_1.getLogger)('SessionStore');
|
|
|
15
15
|
* 用 __dirname 定位,比 process.execPath 可靠
|
|
16
16
|
*/
|
|
17
17
|
function getPackageRootDir() {
|
|
18
|
+
// pkg 打包后 __dirname 是 /snapshot/... 虚拟路径,无法写文件
|
|
19
|
+
// 用 process.pkg 判断是否在 pkg 环境中
|
|
20
|
+
if (process.pkg) {
|
|
21
|
+
// process.execPath 指向二进制文件本身,取其所在目录
|
|
22
|
+
return path_1.default.dirname(process.execPath);
|
|
23
|
+
}
|
|
18
24
|
// dist/services/session/SessionStore.js → 包根目录
|
|
19
25
|
return path_1.default.resolve(__dirname, '..', '..', '..');
|
|
20
26
|
}
|
|
@@ -33,6 +39,13 @@ function getDbPath() {
|
|
|
33
39
|
}
|
|
34
40
|
exports.getDbPath = getDbPath;
|
|
35
41
|
function getMigrationsDir() {
|
|
42
|
+
// pkg 环境:从 snapshot 虚拟路径读取打包的 migrations
|
|
43
|
+
if (process.pkg) {
|
|
44
|
+
const snapshotMigrations = path_1.default.resolve(__dirname, '..', '..', '..', 'migrations');
|
|
45
|
+
if (fs_1.default.existsSync(snapshotMigrations)) {
|
|
46
|
+
return snapshotMigrations;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
36
49
|
// migrations 随包发布,从包安装目录读取
|
|
37
50
|
const pkgMigrations = path_1.default.join(getPackageRootDir(), 'migrations');
|
|
38
51
|
if (fs_1.default.existsSync(pkgMigrations)) {
|
|
@@ -22,13 +22,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
26
|
exports.searchTool = void 0;
|
|
30
27
|
// @ts-ignore
|
|
31
|
-
const
|
|
28
|
+
const undici_1 = require("undici");
|
|
32
29
|
const cheerio = __importStar(require("cheerio"));
|
|
33
30
|
exports.searchTool = {
|
|
34
31
|
name: 'search',
|
|
@@ -44,14 +41,15 @@ exports.searchTool = {
|
|
|
44
41
|
handler: async (args) => {
|
|
45
42
|
try {
|
|
46
43
|
const { query, limit = 5 } = args;
|
|
47
|
-
const response = await (0,
|
|
44
|
+
const response = await (0, undici_1.fetch)(`https://cn.bing.com/search?q=${encodeURIComponent(query)}`, {
|
|
48
45
|
headers: {
|
|
49
46
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
50
47
|
'Accept-Language': 'zh-CN,zh;q=0.9',
|
|
51
48
|
},
|
|
52
|
-
|
|
49
|
+
signal: AbortSignal.timeout(10000),
|
|
53
50
|
});
|
|
54
|
-
const
|
|
51
|
+
const body = await response.text();
|
|
52
|
+
const $ = cheerio.load(body);
|
|
55
53
|
const results = [];
|
|
56
54
|
$('li.b_algo').each((_, el) => {
|
|
57
55
|
if (results.length >= limit)
|
|
@@ -22,13 +22,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
26
|
exports.webFetchTool = void 0;
|
|
30
27
|
// @ts-ignore
|
|
31
|
-
const
|
|
28
|
+
const undici_1 = require("undici");
|
|
32
29
|
const cheerio = __importStar(require("cheerio"));
|
|
33
30
|
exports.webFetchTool = {
|
|
34
31
|
name: 'webFetch',
|
|
@@ -44,13 +41,14 @@ exports.webFetchTool = {
|
|
|
44
41
|
handler: async (args) => {
|
|
45
42
|
try {
|
|
46
43
|
const { url, query } = args;
|
|
47
|
-
const response = await (0,
|
|
44
|
+
const response = await (0, undici_1.fetch)(url, {
|
|
48
45
|
headers: {
|
|
49
46
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
50
47
|
},
|
|
51
|
-
|
|
48
|
+
signal: AbortSignal.timeout(15000),
|
|
52
49
|
});
|
|
53
|
-
const
|
|
50
|
+
const body = await response.text();
|
|
51
|
+
const $ = cheerio.load(body);
|
|
54
52
|
let content = $.html();
|
|
55
53
|
if (query) {
|
|
56
54
|
content = $(query).text().trim() || `选择器 ${query} 未找到匹配内容`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myassis/gateway",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "我的助手 Gateway Service - 本地 AI 网关服务,支持认证、WebSocket 实时通信和任务调度",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -24,9 +24,10 @@
|
|
|
24
24
|
"start": "node dist/index.js",
|
|
25
25
|
"build": "tsc --skipLibCheck",
|
|
26
26
|
"postbuild": "node scripts/add-shebang.js && npx tsc-alias",
|
|
27
|
-
"pkg:win": "
|
|
28
|
-
"pkg:linux": "npx @yao-pkg/pkg . --targets
|
|
27
|
+
"pkg:win": "node scripts/pkg-build-win.js node24-win-x64 myassis-gateway-win.exe",
|
|
28
|
+
"pkg:linux": "npx @yao-pkg/pkg . --targets node24-linux-x64 --output myassis-gateway-linux",
|
|
29
29
|
"pkg:all": "npm run pkg:win && npm run pkg:linux",
|
|
30
|
+
"pkg:linux-analyze": "npx @yao-pkg/pkg . --targets node24-linux-x64 --output myassis-gateway-linux --public-packages got --debug",
|
|
30
31
|
"test": "jest"
|
|
31
32
|
},
|
|
32
33
|
"keywords": [
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
],
|
|
40
41
|
"author": "duzhengjie",
|
|
41
42
|
"dependencies": {
|
|
42
|
-
"@myassis/shared": "
|
|
43
|
+
"@myassis/shared": "workspace:*",
|
|
43
44
|
"@nut-tree/nut-js": "^4.2.0",
|
|
44
45
|
"axios": "^1.15.2",
|
|
45
46
|
"bcryptjs": "^2.4.3",
|
|
@@ -49,7 +50,6 @@
|
|
|
49
50
|
"cors": "^2.8.5",
|
|
50
51
|
"dotenv": "^16.3.1",
|
|
51
52
|
"express": "^4.18.2",
|
|
52
|
-
"got": "^15.0.3",
|
|
53
53
|
"helmet": "^7.1.0",
|
|
54
54
|
"https-proxy-agent": "^9.0.0",
|
|
55
55
|
"jsonwebtoken": "^9.0.2",
|
|
@@ -61,7 +61,6 @@
|
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/bcryptjs": "^2.4.6",
|
|
64
|
-
"@types/compression": "^1.7.5",
|
|
65
64
|
"@types/cors": "^2.8.17",
|
|
66
65
|
"@types/express": "^4.17.21",
|
|
67
66
|
"@types/jsonwebtoken": "^9.0.6",
|
|
@@ -72,7 +71,8 @@
|
|
|
72
71
|
"@yao-pkg/pkg": "^6.20.0",
|
|
73
72
|
"tsc-alias": "^1.8.10",
|
|
74
73
|
"tsx": "^4.7.0",
|
|
75
|
-
"typescript": "^5.3.3"
|
|
74
|
+
"typescript": "^5.3.3",
|
|
75
|
+
"@yao-pkg/pkg-fetch": "3.6.3"
|
|
76
76
|
},
|
|
77
77
|
"pkg": {
|
|
78
78
|
"scripts": [
|
|
@@ -81,11 +81,14 @@
|
|
|
81
81
|
"assets": [
|
|
82
82
|
"dist/**/*",
|
|
83
83
|
"migrations/**/*",
|
|
84
|
-
"README*"
|
|
84
|
+
"README*",
|
|
85
|
+
"node_modules/better-sqlite3/build/Release/better_sqlite3.node",
|
|
86
|
+
"node_modules/.pnpm/@nut-tree+libnut-linux@2.7.1/node_modules/@nut-tree/libnut-linux/build/Release/libnut.node",
|
|
87
|
+
"node_modules/.pnpm/@nut-tree+libnut-win32@2.7.1/node_modules/@nut-tree/libnut-win32/build/Release/libnut.node"
|
|
85
88
|
],
|
|
86
89
|
"targets": [
|
|
87
|
-
"
|
|
88
|
-
"
|
|
90
|
+
"node24-win-x64",
|
|
91
|
+
"node24-linux-x64"
|
|
89
92
|
]
|
|
90
93
|
}
|
|
91
94
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// pkg-build-win.js - Windows pkg build using PKG_CACHE_PATH
|
|
3
|
+
// Points to ~/.pkg-cache which contains the correct v3.6 patched binary (40.6 MB, hash matches)
|
|
4
|
+
'use strict';
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
const TARGET = process.argv[2] || 'node18-win-x64';
|
|
11
|
+
const OUTPUT = process.argv[3] || 'myassis-gateway-win.exe';
|
|
12
|
+
|
|
13
|
+
const CACHE_DIR = path.join(os.homedir(), '.pkg-cache');
|
|
14
|
+
const V36_BINARY = path.join(CACHE_DIR, 'v3.6', 'fetched-v18.20.8-win-x64');
|
|
15
|
+
const PKG_BIN = path.resolve(__dirname, '../node_modules/@yao-pkg/pkg/lib-es5/bin.js');
|
|
16
|
+
|
|
17
|
+
function log(msg) { console.error('[pkg-build] ' + msg); }
|
|
18
|
+
|
|
19
|
+
async function main() {
|
|
20
|
+
log(`Building for ${TARGET}`);
|
|
21
|
+
log(`Output: ${OUTPUT}`);
|
|
22
|
+
|
|
23
|
+
// Verify v3.6 binary exists
|
|
24
|
+
if (!fs.existsSync(V36_BINARY)) {
|
|
25
|
+
log(`ERROR: Patched binary not found at ${V36_BINARY}`);
|
|
26
|
+
log('Please run: node node_modules/@yao-pkg/pkg/lib-es5/bin.js --targets node18-win-x64 first');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const size = (fs.statSync(V36_BINARY).size / 1024 / 1024).toFixed(1);
|
|
30
|
+
log(`Using patched binary: ${V36_BINARY} (${size} MB)`);
|
|
31
|
+
|
|
32
|
+
// Use PKG_CACHE_PATH so pkg-fetch finds the correct v3.6 binary by hash
|
|
33
|
+
const env = { ...process.env };
|
|
34
|
+
delete env.PKG_NODE_PATH; // MUST NOT use PKG_NODE_PATH - it bypasses placeholders check
|
|
35
|
+
env.PKG_CACHE_PATH = CACHE_DIR;
|
|
36
|
+
log(`PKG_CACHE_PATH=${CACHE_DIR}`);
|
|
37
|
+
|
|
38
|
+
log('Starting pkg...');
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
const child = spawn(process.execPath, [PKG_BIN, '.', '--targets', TARGET, '--output', OUTPUT], {
|
|
41
|
+
cwd: path.resolve(__dirname, '..'),
|
|
42
|
+
env,
|
|
43
|
+
stdio: 'inherit'
|
|
44
|
+
});
|
|
45
|
+
child.on('exit', (code) => process.exit(code || 0));
|
|
46
|
+
child.on('error', (e) => { log('Spawn error: ' + e.message); process.exit(1); });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
main().catch(e => { console.error('[pkg-build] Fatal:', e.message); process.exit(1); });
|