hvip-mcp-server 0.2.49 → 0.2.51
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/index.js +1180 -364
- package/package.json +64 -64
package/dist/index.js
CHANGED
|
@@ -6,9 +6,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __esm = (fn, res) => function __init() {
|
|
10
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
-
};
|
|
12
9
|
var __commonJS = (cb, mod) => function __require() {
|
|
13
10
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
14
11
|
};
|
|
@@ -33,6 +30,410 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
30
|
mod
|
|
34
31
|
));
|
|
35
32
|
|
|
33
|
+
// node_modules/dotenv/package.json
|
|
34
|
+
var require_package = __commonJS({
|
|
35
|
+
"node_modules/dotenv/package.json"(exports2, module2) {
|
|
36
|
+
module2.exports = {
|
|
37
|
+
name: "dotenv",
|
|
38
|
+
version: "16.6.1",
|
|
39
|
+
description: "Loads environment variables from .env file",
|
|
40
|
+
main: "lib/main.js",
|
|
41
|
+
types: "lib/main.d.ts",
|
|
42
|
+
exports: {
|
|
43
|
+
".": {
|
|
44
|
+
types: "./lib/main.d.ts",
|
|
45
|
+
require: "./lib/main.js",
|
|
46
|
+
default: "./lib/main.js"
|
|
47
|
+
},
|
|
48
|
+
"./config": "./config.js",
|
|
49
|
+
"./config.js": "./config.js",
|
|
50
|
+
"./lib/env-options": "./lib/env-options.js",
|
|
51
|
+
"./lib/env-options.js": "./lib/env-options.js",
|
|
52
|
+
"./lib/cli-options": "./lib/cli-options.js",
|
|
53
|
+
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
54
|
+
"./package.json": "./package.json"
|
|
55
|
+
},
|
|
56
|
+
scripts: {
|
|
57
|
+
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
58
|
+
lint: "standard",
|
|
59
|
+
pretest: "npm run lint && npm run dts-check",
|
|
60
|
+
test: "tap run --allow-empty-coverage --disable-coverage --timeout=60000",
|
|
61
|
+
"test:coverage": "tap run --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
|
|
62
|
+
prerelease: "npm test",
|
|
63
|
+
release: "standard-version"
|
|
64
|
+
},
|
|
65
|
+
repository: {
|
|
66
|
+
type: "git",
|
|
67
|
+
url: "git://github.com/motdotla/dotenv.git"
|
|
68
|
+
},
|
|
69
|
+
homepage: "https://github.com/motdotla/dotenv#readme",
|
|
70
|
+
funding: "https://dotenvx.com",
|
|
71
|
+
keywords: [
|
|
72
|
+
"dotenv",
|
|
73
|
+
"env",
|
|
74
|
+
".env",
|
|
75
|
+
"environment",
|
|
76
|
+
"variables",
|
|
77
|
+
"config",
|
|
78
|
+
"settings"
|
|
79
|
+
],
|
|
80
|
+
readmeFilename: "README.md",
|
|
81
|
+
license: "BSD-2-Clause",
|
|
82
|
+
devDependencies: {
|
|
83
|
+
"@types/node": "^18.11.3",
|
|
84
|
+
decache: "^4.6.2",
|
|
85
|
+
sinon: "^14.0.1",
|
|
86
|
+
standard: "^17.0.0",
|
|
87
|
+
"standard-version": "^9.5.0",
|
|
88
|
+
tap: "^19.2.0",
|
|
89
|
+
typescript: "^4.8.4"
|
|
90
|
+
},
|
|
91
|
+
engines: {
|
|
92
|
+
node: ">=12"
|
|
93
|
+
},
|
|
94
|
+
browser: {
|
|
95
|
+
fs: false
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// node_modules/dotenv/lib/main.js
|
|
102
|
+
var require_main = __commonJS({
|
|
103
|
+
"node_modules/dotenv/lib/main.js"(exports2, module2) {
|
|
104
|
+
var fs3 = require("fs");
|
|
105
|
+
var path3 = require("path");
|
|
106
|
+
var os2 = require("os");
|
|
107
|
+
var crypto5 = require("crypto");
|
|
108
|
+
var packageJson = require_package();
|
|
109
|
+
var version2 = packageJson.version;
|
|
110
|
+
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
111
|
+
function parse3(src) {
|
|
112
|
+
const obj = {};
|
|
113
|
+
let lines = src.toString();
|
|
114
|
+
lines = lines.replace(/\r\n?/mg, "\n");
|
|
115
|
+
let match;
|
|
116
|
+
while ((match = LINE.exec(lines)) != null) {
|
|
117
|
+
const key = match[1];
|
|
118
|
+
let value = match[2] || "";
|
|
119
|
+
value = value.trim();
|
|
120
|
+
const maybeQuote = value[0];
|
|
121
|
+
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
122
|
+
if (maybeQuote === '"') {
|
|
123
|
+
value = value.replace(/\\n/g, "\n");
|
|
124
|
+
value = value.replace(/\\r/g, "\r");
|
|
125
|
+
}
|
|
126
|
+
obj[key] = value;
|
|
127
|
+
}
|
|
128
|
+
return obj;
|
|
129
|
+
}
|
|
130
|
+
function _parseVault(options) {
|
|
131
|
+
options = options || {};
|
|
132
|
+
const vaultPath = _vaultPath(options);
|
|
133
|
+
options.path = vaultPath;
|
|
134
|
+
const result = DotenvModule.configDotenv(options);
|
|
135
|
+
if (!result.parsed) {
|
|
136
|
+
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
137
|
+
err.code = "MISSING_DATA";
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
const keys = _dotenvKey(options).split(",");
|
|
141
|
+
const length = keys.length;
|
|
142
|
+
let decrypted;
|
|
143
|
+
for (let i = 0; i < length; i++) {
|
|
144
|
+
try {
|
|
145
|
+
const key = keys[i].trim();
|
|
146
|
+
const attrs = _instructions(result, key);
|
|
147
|
+
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
148
|
+
break;
|
|
149
|
+
} catch (error2) {
|
|
150
|
+
if (i + 1 >= length) {
|
|
151
|
+
throw error2;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return DotenvModule.parse(decrypted);
|
|
156
|
+
}
|
|
157
|
+
function _warn(message) {
|
|
158
|
+
console.log(`[dotenv@${version2}][WARN] ${message}`);
|
|
159
|
+
}
|
|
160
|
+
function _debug(message) {
|
|
161
|
+
console.log(`[dotenv@${version2}][DEBUG] ${message}`);
|
|
162
|
+
}
|
|
163
|
+
function _log(message) {
|
|
164
|
+
console.log(`[dotenv@${version2}] ${message}`);
|
|
165
|
+
}
|
|
166
|
+
function _dotenvKey(options) {
|
|
167
|
+
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
168
|
+
return options.DOTENV_KEY;
|
|
169
|
+
}
|
|
170
|
+
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
171
|
+
return process.env.DOTENV_KEY;
|
|
172
|
+
}
|
|
173
|
+
return "";
|
|
174
|
+
}
|
|
175
|
+
function _instructions(result, dotenvKey) {
|
|
176
|
+
let uri;
|
|
177
|
+
try {
|
|
178
|
+
uri = new URL(dotenvKey);
|
|
179
|
+
} catch (error2) {
|
|
180
|
+
if (error2.code === "ERR_INVALID_URL") {
|
|
181
|
+
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
182
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
185
|
+
throw error2;
|
|
186
|
+
}
|
|
187
|
+
const key = uri.password;
|
|
188
|
+
if (!key) {
|
|
189
|
+
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
190
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
191
|
+
throw err;
|
|
192
|
+
}
|
|
193
|
+
const environment = uri.searchParams.get("environment");
|
|
194
|
+
if (!environment) {
|
|
195
|
+
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
196
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
197
|
+
throw err;
|
|
198
|
+
}
|
|
199
|
+
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
200
|
+
const ciphertext = result.parsed[environmentKey];
|
|
201
|
+
if (!ciphertext) {
|
|
202
|
+
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
203
|
+
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
return { ciphertext, key };
|
|
207
|
+
}
|
|
208
|
+
function _vaultPath(options) {
|
|
209
|
+
let possibleVaultPath = null;
|
|
210
|
+
if (options && options.path && options.path.length > 0) {
|
|
211
|
+
if (Array.isArray(options.path)) {
|
|
212
|
+
for (const filepath of options.path) {
|
|
213
|
+
if (fs3.existsSync(filepath)) {
|
|
214
|
+
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
possibleVaultPath = path3.resolve(process.cwd(), ".env.vault");
|
|
222
|
+
}
|
|
223
|
+
if (fs3.existsSync(possibleVaultPath)) {
|
|
224
|
+
return possibleVaultPath;
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
function _resolveHome(envPath) {
|
|
229
|
+
return envPath[0] === "~" ? path3.join(os2.homedir(), envPath.slice(1)) : envPath;
|
|
230
|
+
}
|
|
231
|
+
function _configVault(options) {
|
|
232
|
+
const debug = Boolean(options && options.debug);
|
|
233
|
+
const quiet = options && "quiet" in options ? options.quiet : true;
|
|
234
|
+
if (debug || !quiet) {
|
|
235
|
+
_log("Loading env from encrypted .env.vault");
|
|
236
|
+
}
|
|
237
|
+
const parsed = DotenvModule._parseVault(options);
|
|
238
|
+
let processEnv = process.env;
|
|
239
|
+
if (options && options.processEnv != null) {
|
|
240
|
+
processEnv = options.processEnv;
|
|
241
|
+
}
|
|
242
|
+
DotenvModule.populate(processEnv, parsed, options);
|
|
243
|
+
return { parsed };
|
|
244
|
+
}
|
|
245
|
+
function configDotenv(options) {
|
|
246
|
+
const dotenvPath = path3.resolve(process.cwd(), ".env");
|
|
247
|
+
let encoding = "utf8";
|
|
248
|
+
const debug = Boolean(options && options.debug);
|
|
249
|
+
const quiet = options && "quiet" in options ? options.quiet : true;
|
|
250
|
+
if (options && options.encoding) {
|
|
251
|
+
encoding = options.encoding;
|
|
252
|
+
} else {
|
|
253
|
+
if (debug) {
|
|
254
|
+
_debug("No encoding is specified. UTF-8 is used by default");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
let optionPaths = [dotenvPath];
|
|
258
|
+
if (options && options.path) {
|
|
259
|
+
if (!Array.isArray(options.path)) {
|
|
260
|
+
optionPaths = [_resolveHome(options.path)];
|
|
261
|
+
} else {
|
|
262
|
+
optionPaths = [];
|
|
263
|
+
for (const filepath of options.path) {
|
|
264
|
+
optionPaths.push(_resolveHome(filepath));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
let lastError;
|
|
269
|
+
const parsedAll = {};
|
|
270
|
+
for (const path4 of optionPaths) {
|
|
271
|
+
try {
|
|
272
|
+
const parsed = DotenvModule.parse(fs3.readFileSync(path4, { encoding }));
|
|
273
|
+
DotenvModule.populate(parsedAll, parsed, options);
|
|
274
|
+
} catch (e) {
|
|
275
|
+
if (debug) {
|
|
276
|
+
_debug(`Failed to load ${path4} ${e.message}`);
|
|
277
|
+
}
|
|
278
|
+
lastError = e;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
let processEnv = process.env;
|
|
282
|
+
if (options && options.processEnv != null) {
|
|
283
|
+
processEnv = options.processEnv;
|
|
284
|
+
}
|
|
285
|
+
DotenvModule.populate(processEnv, parsedAll, options);
|
|
286
|
+
if (debug || !quiet) {
|
|
287
|
+
const keysCount = Object.keys(parsedAll).length;
|
|
288
|
+
const shortPaths = [];
|
|
289
|
+
for (const filePath of optionPaths) {
|
|
290
|
+
try {
|
|
291
|
+
const relative = path3.relative(process.cwd(), filePath);
|
|
292
|
+
shortPaths.push(relative);
|
|
293
|
+
} catch (e) {
|
|
294
|
+
if (debug) {
|
|
295
|
+
_debug(`Failed to load ${filePath} ${e.message}`);
|
|
296
|
+
}
|
|
297
|
+
lastError = e;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")}`);
|
|
301
|
+
}
|
|
302
|
+
if (lastError) {
|
|
303
|
+
return { parsed: parsedAll, error: lastError };
|
|
304
|
+
} else {
|
|
305
|
+
return { parsed: parsedAll };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function config2(options) {
|
|
309
|
+
if (_dotenvKey(options).length === 0) {
|
|
310
|
+
return DotenvModule.configDotenv(options);
|
|
311
|
+
}
|
|
312
|
+
const vaultPath = _vaultPath(options);
|
|
313
|
+
if (!vaultPath) {
|
|
314
|
+
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
315
|
+
return DotenvModule.configDotenv(options);
|
|
316
|
+
}
|
|
317
|
+
return DotenvModule._configVault(options);
|
|
318
|
+
}
|
|
319
|
+
function decrypt(encrypted, keyStr) {
|
|
320
|
+
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
321
|
+
let ciphertext = Buffer.from(encrypted, "base64");
|
|
322
|
+
const nonce = ciphertext.subarray(0, 12);
|
|
323
|
+
const authTag = ciphertext.subarray(-16);
|
|
324
|
+
ciphertext = ciphertext.subarray(12, -16);
|
|
325
|
+
try {
|
|
326
|
+
const aesgcm = crypto5.createDecipheriv("aes-256-gcm", key, nonce);
|
|
327
|
+
aesgcm.setAuthTag(authTag);
|
|
328
|
+
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
329
|
+
} catch (error2) {
|
|
330
|
+
const isRange = error2 instanceof RangeError;
|
|
331
|
+
const invalidKeyLength = error2.message === "Invalid key length";
|
|
332
|
+
const decryptionFailed = error2.message === "Unsupported state or unable to authenticate data";
|
|
333
|
+
if (isRange || invalidKeyLength) {
|
|
334
|
+
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
335
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
336
|
+
throw err;
|
|
337
|
+
} else if (decryptionFailed) {
|
|
338
|
+
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
339
|
+
err.code = "DECRYPTION_FAILED";
|
|
340
|
+
throw err;
|
|
341
|
+
} else {
|
|
342
|
+
throw error2;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function populate(processEnv, parsed, options = {}) {
|
|
347
|
+
const debug = Boolean(options && options.debug);
|
|
348
|
+
const override = Boolean(options && options.override);
|
|
349
|
+
if (typeof parsed !== "object") {
|
|
350
|
+
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
351
|
+
err.code = "OBJECT_REQUIRED";
|
|
352
|
+
throw err;
|
|
353
|
+
}
|
|
354
|
+
for (const key of Object.keys(parsed)) {
|
|
355
|
+
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
356
|
+
if (override === true) {
|
|
357
|
+
processEnv[key] = parsed[key];
|
|
358
|
+
}
|
|
359
|
+
if (debug) {
|
|
360
|
+
if (override === true) {
|
|
361
|
+
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
362
|
+
} else {
|
|
363
|
+
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
processEnv[key] = parsed[key];
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
var DotenvModule = {
|
|
372
|
+
configDotenv,
|
|
373
|
+
_configVault,
|
|
374
|
+
_parseVault,
|
|
375
|
+
config: config2,
|
|
376
|
+
decrypt,
|
|
377
|
+
parse: parse3,
|
|
378
|
+
populate
|
|
379
|
+
};
|
|
380
|
+
module2.exports.configDotenv = DotenvModule.configDotenv;
|
|
381
|
+
module2.exports._configVault = DotenvModule._configVault;
|
|
382
|
+
module2.exports._parseVault = DotenvModule._parseVault;
|
|
383
|
+
module2.exports.config = DotenvModule.config;
|
|
384
|
+
module2.exports.decrypt = DotenvModule.decrypt;
|
|
385
|
+
module2.exports.parse = DotenvModule.parse;
|
|
386
|
+
module2.exports.populate = DotenvModule.populate;
|
|
387
|
+
module2.exports = DotenvModule;
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// node_modules/dotenv/lib/env-options.js
|
|
392
|
+
var require_env_options = __commonJS({
|
|
393
|
+
"node_modules/dotenv/lib/env-options.js"(exports2, module2) {
|
|
394
|
+
var options = {};
|
|
395
|
+
if (process.env.DOTENV_CONFIG_ENCODING != null) {
|
|
396
|
+
options.encoding = process.env.DOTENV_CONFIG_ENCODING;
|
|
397
|
+
}
|
|
398
|
+
if (process.env.DOTENV_CONFIG_PATH != null) {
|
|
399
|
+
options.path = process.env.DOTENV_CONFIG_PATH;
|
|
400
|
+
}
|
|
401
|
+
if (process.env.DOTENV_CONFIG_QUIET != null) {
|
|
402
|
+
options.quiet = process.env.DOTENV_CONFIG_QUIET;
|
|
403
|
+
}
|
|
404
|
+
if (process.env.DOTENV_CONFIG_DEBUG != null) {
|
|
405
|
+
options.debug = process.env.DOTENV_CONFIG_DEBUG;
|
|
406
|
+
}
|
|
407
|
+
if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
|
|
408
|
+
options.override = process.env.DOTENV_CONFIG_OVERRIDE;
|
|
409
|
+
}
|
|
410
|
+
if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
|
|
411
|
+
options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY;
|
|
412
|
+
}
|
|
413
|
+
module2.exports = options;
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// node_modules/dotenv/lib/cli-options.js
|
|
418
|
+
var require_cli_options = __commonJS({
|
|
419
|
+
"node_modules/dotenv/lib/cli-options.js"(exports2, module2) {
|
|
420
|
+
var re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/;
|
|
421
|
+
module2.exports = function optionMatcher(args) {
|
|
422
|
+
const options = args.reduce(function(acc, cur) {
|
|
423
|
+
const matches = cur.match(re);
|
|
424
|
+
if (matches) {
|
|
425
|
+
acc[matches[1]] = matches[2];
|
|
426
|
+
}
|
|
427
|
+
return acc;
|
|
428
|
+
}, {});
|
|
429
|
+
if (!("quiet" in options)) {
|
|
430
|
+
options.quiet = "true";
|
|
431
|
+
}
|
|
432
|
+
return options;
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
36
437
|
// node_modules/ajv/dist/compile/codegen/code.js
|
|
37
438
|
var require_code = __commonJS({
|
|
38
439
|
"node_modules/ajv/dist/compile/codegen/code.js"(exports2) {
|
|
@@ -10568,33 +10969,16 @@ var require_websocket_server = __commonJS({
|
|
|
10568
10969
|
}
|
|
10569
10970
|
});
|
|
10570
10971
|
|
|
10571
|
-
// node_modules/
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
|
|
10575
|
-
|
|
10576
|
-
|
|
10577
|
-
|
|
10578
|
-
|
|
10579
|
-
|
|
10580
|
-
|
|
10581
|
-
extension: () => import_extension.default,
|
|
10582
|
-
subprotocol: () => import_subprotocol.default
|
|
10583
|
-
});
|
|
10584
|
-
var import_stream2, import_extension, import_permessage_deflate, import_receiver, import_sender, import_subprotocol, import_websocket, import_websocket_server, wrapper_default;
|
|
10585
|
-
var init_wrapper = __esm({
|
|
10586
|
-
"node_modules/ws/wrapper.mjs"() {
|
|
10587
|
-
import_stream2 = __toESM(require_stream(), 1);
|
|
10588
|
-
import_extension = __toESM(require_extension(), 1);
|
|
10589
|
-
import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
10590
|
-
import_receiver = __toESM(require_receiver(), 1);
|
|
10591
|
-
import_sender = __toESM(require_sender(), 1);
|
|
10592
|
-
import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
10593
|
-
import_websocket = __toESM(require_websocket(), 1);
|
|
10594
|
-
import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
10595
|
-
wrapper_default = import_websocket.default;
|
|
10596
|
-
}
|
|
10597
|
-
});
|
|
10972
|
+
// node_modules/dotenv/config.js
|
|
10973
|
+
(function() {
|
|
10974
|
+
require_main().config(
|
|
10975
|
+
Object.assign(
|
|
10976
|
+
{},
|
|
10977
|
+
require_env_options(),
|
|
10978
|
+
require_cli_options()(process.argv)
|
|
10979
|
+
)
|
|
10980
|
+
);
|
|
10981
|
+
})();
|
|
10598
10982
|
|
|
10599
10983
|
// src/index.ts
|
|
10600
10984
|
var import_node_http = require("node:http");
|
|
@@ -26665,24 +27049,181 @@ function toResult(data) {
|
|
|
26665
27049
|
}
|
|
26666
27050
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
26667
27051
|
}
|
|
27052
|
+
var OKX_ERROR_MESSAGES = {
|
|
27053
|
+
// 公共 / 系统
|
|
27054
|
+
5e4: "\u7CFB\u7EDF\u5185\u90E8\u9519\u8BEF",
|
|
27055
|
+
50001: "\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
27056
|
+
50002: "\u7CFB\u7EDF\u5347\u7EA7\u7EF4\u62A4\u4E2D",
|
|
27057
|
+
50004: "\u8BF7\u6C42\u8D85\u65F6",
|
|
27058
|
+
50005: "\u63A5\u53E3\u5DF2\u88AB\u51BB\u7ED3\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D",
|
|
27059
|
+
50006: "OK-ACCESS-KEY \u65E0\u6548",
|
|
27060
|
+
50007: "OK-ACCESS-SIGN \u7B7E\u540D\u9519\u8BEF",
|
|
27061
|
+
50008: "OK-ACCESS-TIMESTAMP \u65F6\u95F4\u6233\u65E0\u6548",
|
|
27062
|
+
50009: "OK-ACCESS-PASSPHRASE \u5BC6\u7801\u77ED\u8BED\u9519\u8BEF",
|
|
27063
|
+
50010: "\u5F53\u524D IP \u4E0D\u5728 API Key \u767D\u540D\u5355\u4E2D",
|
|
27064
|
+
50011: "\u8BF7\u6C42\u9891\u7387\u8FC7\u5FEB\uFF0C\u5DF2\u89E6\u53D1\u9650\u6D41\u3002\u8BF7\u964D\u4F4E\u8BF7\u6C42\u901F\u7387",
|
|
27065
|
+
50012: "\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
27066
|
+
50013: "\u7CFB\u7EDF\u9519\u8BEF",
|
|
27067
|
+
50014: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5FC5\u586B\u5B57\u6BB5\u548C\u683C\u5F0F",
|
|
27068
|
+
50015: "\u4ED3\u4F4D\u5DF2\u88AB\u51BB\u7ED3",
|
|
27069
|
+
50016: "\u8D26\u6237\u5DF2\u88AB\u51BB\u7ED3",
|
|
27070
|
+
50017: "\u8D26\u6237\u5DF2\u88AB\u6682\u505C",
|
|
27071
|
+
50018: "\u8D26\u6237\u7B49\u7EA7\u4E0D\u8DB3",
|
|
27072
|
+
50019: "\u5408\u7EA6\u5DF2\u5230\u671F",
|
|
27073
|
+
50020: "\u4F59\u989D\u4E0D\u8DB3",
|
|
27074
|
+
50021: "\u4FDD\u8BC1\u91D1\u4E0D\u8DB3",
|
|
27075
|
+
50022: "\u4E0B\u5355\u6570\u91CF\u5C0F\u4E8E\u6700\u5C0F\u9650\u5236",
|
|
27076
|
+
50023: "\u4E0B\u5355\u6570\u91CF\u8D85\u8FC7\u6700\u5927\u9650\u5236",
|
|
27077
|
+
50024: "\u6301\u4ED3\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650",
|
|
27078
|
+
50025: "\u6302\u5355\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650",
|
|
27079
|
+
50026: "\u4E0B\u5355\u4EF7\u683C\u8D85\u51FA\u9650\u4EF7\u8303\u56F4",
|
|
27080
|
+
50027: "\u4EF7\u683C\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
|
|
27081
|
+
50028: "\u6570\u91CF\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
|
|
27082
|
+
50029: "\u8BE5\u5408\u7EA6\u6682\u4E0D\u53EF\u7528",
|
|
27083
|
+
50030: "API Key \u65E0\u6B64\u64CD\u4F5C\u6743\u9650",
|
|
27084
|
+
50031: "API Key \u5DF2\u8FC7\u671F",
|
|
27085
|
+
50032: "API Key \u672A\u627E\u5230",
|
|
27086
|
+
50033: "API Key \u672A\u6FC0\u6D3B",
|
|
27087
|
+
50035: "\u89E6\u53D1\u98CE\u63A7\u89C4\u5219\uFF0C\u4EA4\u6613\u88AB\u62D2\u7EDD",
|
|
27088
|
+
50036: "\u65E0\u4EA4\u6613\u6743\u9650",
|
|
27089
|
+
50044: "\u8BA2\u5355\u4E0D\u5B58\u5728",
|
|
27090
|
+
50045: "\u8BE5\u8BA2\u5355\u4E0D\u53EF\u64A4\u9500",
|
|
27091
|
+
50046: "\u8BA2\u5355\u5DF2\u5168\u90E8\u6210\u4EA4",
|
|
27092
|
+
50047: "\u8BA2\u5355\u5DF2\u88AB\u64A4\u9500",
|
|
27093
|
+
50050: "\u6301\u4ED3\u4E0D\u5B58\u5728",
|
|
27094
|
+
50051: "\u4ED3\u4F4D\u5DF2\u5E73\u4ED3",
|
|
27095
|
+
50053: "\u4ED3\u4F4D\u4FDD\u8BC1\u91D1\u4E0D\u8DB3",
|
|
27096
|
+
50056: "\u4E0B\u5355\u8FC7\u4E8E\u9891\u7E41",
|
|
27097
|
+
50058: "\u8BE5\u5E01\u79CD\u6682\u4E0D\u652F\u6301",
|
|
27098
|
+
50059: "\u53C2\u6570\u89E3\u6790\u5931\u8D25",
|
|
27099
|
+
50060: "\u8D26\u6237\u6A21\u5F0F\u4E0D\u652F\u6301\u6B64\u64CD\u4F5C",
|
|
27100
|
+
50061: "\u5B50\u8D26\u6237\u8BF7\u6C42\u9891\u7387\u8D85\u9650",
|
|
27101
|
+
50064: "\u8BE5\u5408\u7EA6\u4E0D\u652F\u6301\u6B64\u64CD\u4F5C",
|
|
27102
|
+
50068: "\u7CFB\u7EDF\u5347\u7EA7\u4E2D\uFF0C\u6682\u4E0D\u53EF\u7528",
|
|
27103
|
+
50070: "\u6301\u4ED3\u6A21\u5F0F\u4E0D\u5339\u914D",
|
|
27104
|
+
50071: "\u4FDD\u8BC1\u91D1\u6A21\u5F0F\u4E0D\u5339\u914D",
|
|
27105
|
+
50072: "\u6760\u6746\u500D\u6570\u8D85\u51FA\u5141\u8BB8\u8303\u56F4",
|
|
27106
|
+
50074: "\u89E6\u53D1\u4EF7\u683C\u65E0\u6548",
|
|
27107
|
+
50080: "\u4E0B\u5355\u4EF7\u683C\u504F\u79BB\u5E02\u573A\u4EF7\u8FC7\u5927",
|
|
27108
|
+
50082: "\u8D26\u6237\u6743\u76CA\u4E0D\u8DB3",
|
|
27109
|
+
// API Key 相关
|
|
27110
|
+
50100: "API Key \u5DF2\u88AB\u51BB\u7ED3",
|
|
27111
|
+
50101: "API Key \u5DF2\u8FC7\u671F",
|
|
27112
|
+
50102: "\u8BF7\u6C42\u65F6\u95F4\u6233\u4E0E\u670D\u52A1\u5668\u65F6\u95F4\u504F\u5DEE\u8D85\u8FC7 30 \u79D2",
|
|
27113
|
+
50103: "\u8BF7\u6C42\u5934 OK-ACCESS-KEY \u4E0D\u80FD\u4E3A\u7A7A",
|
|
27114
|
+
50104: "\u8BF7\u6C42\u5934 OK-ACCESS-SIGN \u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A",
|
|
27115
|
+
50105: "\u8BF7\u6C42\u5934 OK-ACCESS-TIMESTAMP \u4E0D\u80FD\u4E3A\u7A7A",
|
|
27116
|
+
50106: "\u8BF7\u6C42\u5934 OK-ACCESS-PASSPHRASE \u4E0D\u80FD\u4E3A\u7A7A",
|
|
27117
|
+
50107: "API Key \u5BF9\u5E94\u7684\u8D26\u6237\u4E0D\u5B58\u5728",
|
|
27118
|
+
50108: "\u8D26\u6237\u4F59\u989D\u4E0D\u8DB3",
|
|
27119
|
+
50109: "\u5212\u8F6C\u91D1\u989D\u8D85\u8FC7\u9650\u989D",
|
|
27120
|
+
50110: "\u5212\u8F6C\u5E01\u79CD\u4E0D\u652F\u6301",
|
|
27121
|
+
50111: "\u5212\u8F6C\u5931\u8D25",
|
|
27122
|
+
50120: "API Key \u6743\u9650\u4E0D\u8DB3\uFF0C\u8BF7\u68C0\u67E5\u662F\u5426\u5F00\u901A\u4E86\u6240\u9700\u6743\u9650\uFF08\u8BFB\u53D6/\u4EA4\u6613/\u63D0\u73B0\uFF09",
|
|
27123
|
+
50121: "API Key \u5DF2\u8FC7\u671F",
|
|
27124
|
+
50122: "API Key \u672A\u627E\u5230",
|
|
27125
|
+
50123: "API Key \u672A\u6FC0\u6D3B",
|
|
27126
|
+
50124: "API Key \u5DF2\u88AB\u5220\u9664",
|
|
27127
|
+
50125: "API Key \u5DF2\u88AB\u51BB\u7ED3",
|
|
27128
|
+
50126: "API Key \u5DF2\u88AB\u7981\u7528",
|
|
27129
|
+
// 交易
|
|
27130
|
+
51e3: "\u53C2\u6570\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u5FC5\u586B\u53C2\u6570",
|
|
27131
|
+
51001: "\u8BA2\u5355\u7C7B\u578B\u4E0D\u652F\u6301",
|
|
27132
|
+
51002: "\u8BA2\u5355\u65B9\u5411\u4E0D\u652F\u6301",
|
|
27133
|
+
51003: "\u8BA2\u5355\u6570\u91CF\u4E0D\u80FD\u4E3A 0 \u6216\u8D1F\u6570",
|
|
27134
|
+
51004: "\u8BA2\u5355\u4EF7\u683C\u4E0D\u80FD\u4E3A 0 \u6216\u8D1F\u6570",
|
|
27135
|
+
51005: "\u4FDD\u8BC1\u91D1\u6A21\u5F0F\u4E0D\u652F\u6301",
|
|
27136
|
+
51006: "\u8BA2\u5355\u4EF7\u683C\u8D85\u51FA\u9650\u4EF7\u8303\u56F4",
|
|
27137
|
+
51007: "\u8BA2\u5355\u6570\u91CF\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
|
|
27138
|
+
51008: "\u8BA2\u5355\u4EF7\u683C\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
|
|
27139
|
+
51009: "\u8BA2\u5355\u6570\u91CF\u8D85\u51FA\u6700\u5927\u9650\u5236",
|
|
27140
|
+
51010: "\u8BA2\u5355\u6570\u91CF\u4F4E\u4E8E\u6700\u5C0F\u9650\u5236",
|
|
27141
|
+
51011: "\u8BE5\u4EA7\u54C1\u4E0D\u652F\u6301\u6B64\u8BA2\u5355\u7C7B\u578B",
|
|
27142
|
+
51012: "\u8BE5\u4EA7\u54C1\u4E0D\u652F\u6301\u6B64\u4FDD\u8BC1\u91D1\u6A21\u5F0F",
|
|
27143
|
+
51013: "\u8BE5\u4EA7\u54C1\u4E0D\u652F\u6301\u6B64\u6301\u4ED3\u6A21\u5F0F",
|
|
27144
|
+
51014: "\u5F53\u524D\u6301\u4ED3\u6A21\u5F0F\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C",
|
|
27145
|
+
51015: "\u5F53\u524D\u8D26\u6237\u6A21\u5F0F\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C",
|
|
27146
|
+
51020: "\u6279\u91CF\u4E0B\u5355\u6570\u91CF\u8D85\u8FC7\u4E0A\u9650",
|
|
27147
|
+
51021: "\u6279\u91CF\u64CD\u4F5C\u4E2D\u5305\u542B\u91CD\u590D\u8BA2\u5355",
|
|
27148
|
+
51026: "\u8BA2\u5355\u4EF7\u683C\u8D85\u51FA\u6ED1\u70B9\u4FDD\u62A4\u8303\u56F4",
|
|
27149
|
+
51027: "\u8BA2\u5355\u5DF2\u8FC7\u671F",
|
|
27150
|
+
51100: "\u8BE5\u4EA7\u54C1\u4E0D\u5728\u53EF\u4EA4\u6613\u5217\u8868",
|
|
27151
|
+
51102: "\u6301\u4ED3\u6A21\u5F0F\u4E0D\u5339\u914D\uFF0C\u65E0\u6CD5\u5E73\u4ED3",
|
|
27152
|
+
51103: "\u4FDD\u8BC1\u91D1\u6A21\u5F0F\u4E0D\u5339\u914D\uFF0C\u65E0\u6CD5\u5E73\u4ED3",
|
|
27153
|
+
51104: "\u6760\u6746\u500D\u6570\u4E0D\u5339\u914D",
|
|
27154
|
+
51107: "\u5E02\u4EF7\u5355\u5F53\u524D\u4E0D\u53EF\u7528",
|
|
27155
|
+
51108: "\u6B62\u635F\u5355\u5F53\u524D\u4E0D\u53EF\u7528",
|
|
27156
|
+
// 资金
|
|
27157
|
+
52e3: "\u5212\u8F6C\u5931\u8D25",
|
|
27158
|
+
52001: "\u63D0\u73B0\u91D1\u989D\u8D85\u8FC7\u9650\u989D",
|
|
27159
|
+
52002: "\u63D0\u73B0\u5730\u5740\u65E0\u6548",
|
|
27160
|
+
52003: "\u63D0\u73B0\u94FE\u4E0D\u652F\u6301",
|
|
27161
|
+
52004: "\u63D0\u73B0\u7F51\u7EDC\u8D39\u4E0D\u8DB3",
|
|
27162
|
+
52005: "\u63D0\u73B0\u5DF2\u51BB\u7ED3",
|
|
27163
|
+
52006: "\u5145\u503C\u5730\u5740\u751F\u6210\u5931\u8D25",
|
|
27164
|
+
52007: "\u8BE5\u5E01\u79CD\u4E0D\u652F\u6301\u5145\u503C",
|
|
27165
|
+
52008: "\u8BE5\u5E01\u79CD\u4E0D\u652F\u6301\u63D0\u73B0",
|
|
27166
|
+
// 跟单交易
|
|
27167
|
+
52100: "\u4EA4\u6613\u5458\u4E0D\u5B58\u5728",
|
|
27168
|
+
52101: "\u4EA4\u6613\u5458\u4E0D\u5BF9\u5916\u516C\u5F00",
|
|
27169
|
+
52102: "\u8DDF\u5355\u91D1\u989D\u8D85\u51FA\u9650\u5236",
|
|
27170
|
+
52103: "\u8DDF\u5355\u4EBA\u6570\u5DF2\u8FBE\u4E0A\u9650",
|
|
27171
|
+
52104: "\u5F53\u524D\u4E0D\u652F\u6301\u8DDF\u5355\u8BE5\u4EA4\u6613\u5458",
|
|
27172
|
+
52105: "\u8BE5\u4EA4\u6613\u5458\u5DF2\u505C\u6B62\u5E26\u5355",
|
|
27173
|
+
// 策略 / 网格
|
|
27174
|
+
53e3: "\u7B56\u7565\u59D4\u6258\u521B\u5EFA\u5931\u8D25",
|
|
27175
|
+
53001: "\u7B56\u7565\u59D4\u6258\u4FEE\u6539\u5931\u8D25",
|
|
27176
|
+
53002: "\u7B56\u7565\u59D4\u6258\u64A4\u9500\u5931\u8D25",
|
|
27177
|
+
53003: "\u7B56\u7565\u59D4\u6258\u4E0D\u5B58\u5728",
|
|
27178
|
+
53004: "\u7B56\u7565\u59D4\u6258\u5DF2\u89E6\u53D1",
|
|
27179
|
+
53005: "\u7F51\u683C\u7B56\u7565\u521B\u5EFA\u5931\u8D25",
|
|
27180
|
+
53006: "\u7F51\u683C\u7B56\u7565\u4E0D\u5B58\u5728",
|
|
27181
|
+
53007: "\u7F51\u683C\u7B56\u7565\u5DF2\u505C\u6B62",
|
|
27182
|
+
53008: "\u7F51\u683C\u53C2\u6570\u65E0\u6548",
|
|
27183
|
+
// WebSocket
|
|
27184
|
+
60001: "\u8BA2\u9605\u9891\u9053\u4E0D\u5B58\u5728\u6216\u53C2\u6570\u9519\u8BEF",
|
|
27185
|
+
60002: "WebSocket \u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 API Key",
|
|
27186
|
+
60003: "WebSocket \u8BA2\u9605\u53C2\u6570\u65E0\u6548",
|
|
27187
|
+
60004: "WebSocket \u8BF7\u6C42\u9891\u7387\u8FC7\u9AD8",
|
|
27188
|
+
60005: "WebSocket \u8FDE\u63A5\u6570\u5DF2\u8FBE\u4E0A\u9650",
|
|
27189
|
+
60006: "WebSocket \u8FDE\u63A5\u88AB\u670D\u52A1\u7AEF\u5173\u95ED",
|
|
27190
|
+
60007: "WebSocket \u8BE5\u9891\u9053\u9700\u8981\u767B\u5F55",
|
|
27191
|
+
60008: "WebSocket \u8BE5\u9891\u9053\u4E0D\u9700\u8981\u767B\u5F55",
|
|
27192
|
+
60009: "WebSocket \u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55",
|
|
27193
|
+
64008: "\u670D\u52A1\u5347\u7EA7\u4E2D\uFF0C\u8FDE\u63A5\u5373\u5C06\u5173\u95ED\uFF0C\u8BF7\u91CD\u8FDE"
|
|
27194
|
+
};
|
|
27195
|
+
function translateError(code, rawMsg) {
|
|
27196
|
+
const translated = OKX_ERROR_MESSAGES[code];
|
|
27197
|
+
if (translated) return translated;
|
|
27198
|
+
if (code >= 5e4 && code < 50100) return `\u7CFB\u7EDF/\u8BA4\u8BC1\u9519\u8BEF (${code}): ${rawMsg}`;
|
|
27199
|
+
if (code >= 50100 && code < 50200) return `API Key \u9519\u8BEF (${code}): ${rawMsg}`;
|
|
27200
|
+
if (code >= 51e3 && code < 51200) return `\u4EA4\u6613\u53C2\u6570\u9519\u8BEF (${code}): ${rawMsg}`;
|
|
27201
|
+
if (code >= 52e3 && code < 52200) return `\u8D44\u91D1/\u8DDF\u5355\u9519\u8BEF (${code}): ${rawMsg}`;
|
|
27202
|
+
if (code >= 53e3 && code < 54e3) return `\u7B56\u7565\u59D4\u6258\u9519\u8BEF (${code}): ${rawMsg}`;
|
|
27203
|
+
if (code >= 6e4 && code < 65e3) return `WebSocket \u9519\u8BEF (${code}): ${rawMsg}`;
|
|
27204
|
+
return rawMsg;
|
|
27205
|
+
}
|
|
26668
27206
|
function classifyError(msg) {
|
|
26669
27207
|
const okxMatch = msg.match(/OKX (\d+):/);
|
|
26670
27208
|
if (okxMatch && okxMatch[1]) {
|
|
26671
27209
|
const code = parseInt(okxMatch[1]);
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
if (code >=
|
|
26675
|
-
return { errorCode: `OKX_${code}`, errorCategory: "
|
|
27210
|
+
const rawMsg = msg.replace(/^OKX \d+: /, "");
|
|
27211
|
+
const translated = translateError(code, rawMsg);
|
|
27212
|
+
if (code >= 5e4 && code < 50100) return { errorCode: `OKX_${code}`, errorCategory: "AUTH", errorMessage: translated };
|
|
27213
|
+
if (code === 50100 || code === 50101 || code === 50120) return { errorCode: `OKX_${code}`, errorCategory: "AUTH", errorMessage: translated };
|
|
27214
|
+
if (code >= 50004 && code <= 50014) return { errorCode: `OKX_${code}`, errorCategory: "VALIDATION", errorMessage: translated };
|
|
27215
|
+
if (code >= 51e3 && code < 51200) return { errorCode: `OKX_${code}`, errorCategory: "VALIDATION", errorMessage: translated };
|
|
27216
|
+
return { errorCode: `OKX_${code}`, errorCategory: "BUSINESS", errorMessage: translated };
|
|
26676
27217
|
}
|
|
26677
27218
|
if (msg.startsWith("HTTP ")) {
|
|
26678
27219
|
const httpMatch = msg.match(/HTTP (\d+)/);
|
|
26679
27220
|
const status = httpMatch && httpMatch[1] ? parseInt(httpMatch[1]) : 0;
|
|
26680
|
-
if (status === 401 || status === 403) return { errorCode: "HTTP_401", errorCategory: "AUTH" };
|
|
26681
|
-
if (status === 429) return { errorCode: "HTTP_429", errorCategory: "RATE_LIMIT" };
|
|
26682
|
-
return { errorCode: "NETWORK_ERROR", errorCategory: "NETWORK" };
|
|
27221
|
+
if (status === 401 || status === 403) return { errorCode: "HTTP_401", errorCategory: "AUTH", errorMessage: "API Key \u8BA4\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5BC6\u94A5\u662F\u5426\u6B63\u786E\u914D\u7F6E" };
|
|
27222
|
+
if (status === 429) return { errorCode: "HTTP_429", errorCategory: "RATE_LIMIT", errorMessage: "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u5DF2\u89E6\u53D1\u9650\u6D41\u3002\u8BF7\u7A0D\u7B49\u540E\u91CD\u8BD5" };
|
|
27223
|
+
return { errorCode: "NETWORK_ERROR", errorCategory: "NETWORK", errorMessage: `\u7F51\u7EDC\u9519\u8BEF HTTP ${status}` };
|
|
26683
27224
|
}
|
|
26684
|
-
if (msg.includes("API Key")) return { errorCode: "AUTH_REQUIRED", errorCategory: "AUTH" };
|
|
26685
|
-
return { errorCode: "UNKNOWN_ERROR", errorCategory: "BUSINESS" };
|
|
27225
|
+
if (msg.includes("API Key")) return { errorCode: "AUTH_REQUIRED", errorCategory: "AUTH", errorMessage: msg };
|
|
27226
|
+
return { errorCode: "UNKNOWN_ERROR", errorCategory: "BUSINESS", errorMessage: msg };
|
|
26686
27227
|
}
|
|
26687
27228
|
function classifyRisk(toolName) {
|
|
26688
27229
|
const admin = ["okx_set_account_mode", "okx_set_position_mode", "okx_set_settle_currency"];
|
|
@@ -26737,12 +27278,13 @@ function classifyRisk(toolName) {
|
|
|
26737
27278
|
}
|
|
26738
27279
|
function toError(e) {
|
|
26739
27280
|
const msg = e instanceof Error ? e.message : String(e);
|
|
26740
|
-
const { errorCode, errorCategory } = classifyError(msg);
|
|
27281
|
+
const { errorCode, errorCategory, errorMessage } = classifyError(msg);
|
|
26741
27282
|
return {
|
|
26742
|
-
content: [{ type: "text", text:
|
|
27283
|
+
content: [{ type: "text", text: errorMessage }],
|
|
26743
27284
|
isError: true,
|
|
26744
27285
|
errorCode,
|
|
26745
|
-
errorCategory
|
|
27286
|
+
errorCategory,
|
|
27287
|
+
errorMessage
|
|
26746
27288
|
};
|
|
26747
27289
|
}
|
|
26748
27290
|
|
|
@@ -33757,12 +34299,13 @@ function registerAgentUtils(server, auth) {
|
|
|
33757
34299
|
},
|
|
33758
34300
|
{
|
|
33759
34301
|
domain: "WebSocket \u5B9E\u65F6",
|
|
33760
|
-
what: "\u5B9E\u65F6\u884C\u60C5\
|
|
33761
|
-
when: ["\u5B9E\u65F6", "\u8BA2\u9605", "\u63A8\u9001", "websocket", "ws", "\u76D1\u542C"],
|
|
34302
|
+
what: "\u5B9E\u65F6\u884C\u60C5\u3001\u8D26\u6237\u3001\u8BA2\u5355\u3001\u7206\u4ED3\u3001\u4EF7\u5DEE\u3001\u5927\u5B97\u63A8\u9001\uFF0855 \u9891\u9053\uFF09",
|
|
34303
|
+
when: ["\u5B9E\u65F6", "\u8BA2\u9605", "\u63A8\u9001", "websocket", "ws", "\u76D1\u542C", "\u7206\u4ED3", "\u5B9E\u65F6\u8BA2\u5355"],
|
|
33762
34304
|
go_to: "okx_ws_subscribe",
|
|
33763
34305
|
also: [
|
|
33764
|
-
"
|
|
33765
|
-
"
|
|
34306
|
+
"okx_ws_subscribe_private \u2014 \u79C1\u6709\u9891\u9053\uFF08\u8D26\u6237/\u6301\u4ED3/\u8BA2\u5355\uFF0C\u9700Key\uFF09",
|
|
34307
|
+
"okx_ws_events \u2014 \u62C9\u53D6\u7F13\u51B2\u4E8B\u4EF6",
|
|
34308
|
+
"okx_ws_status \u2014 \u67E5\u770B\u8BA2\u9605\u72B6\u6001",
|
|
33766
34309
|
"okx_ws_close \u2014 \u5173\u95ED\u8BA2\u9605"
|
|
33767
34310
|
],
|
|
33768
34311
|
risk: "READ"
|
|
@@ -33854,7 +34397,8 @@ function registerAgentUtils(server, auth) {
|
|
|
33854
34397
|
"agent_get_preference": "key? (\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8)",
|
|
33855
34398
|
"agent_set_preference": "key, value",
|
|
33856
34399
|
"okx_event_instruments": "eventType? (\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8)",
|
|
33857
|
-
"okx_ws_subscribe": "
|
|
34400
|
+
"okx_ws_subscribe": "instId (\u4EA7\u54C1ID), channel (33\u4E2A\u516C\u5F00\u9891\u9053)",
|
|
34401
|
+
"okx_ws_subscribe_private": "instId? (\u4EA7\u54C1ID), channel (22\u4E2A\u79C1\u6709\u9891\u9053\uFF0C\u9700Key)",
|
|
33858
34402
|
"okx_get_grid_ai_param": "instType, algoOrdType"
|
|
33859
34403
|
};
|
|
33860
34404
|
const enrichedDomains = CATALOG.domains.map((d) => ({
|
|
@@ -34055,12 +34599,13 @@ function registerAgentUtils(server, auth) {
|
|
|
34055
34599
|
]
|
|
34056
34600
|
},
|
|
34057
34601
|
"WebSocket \u5B9E\u65F6": {
|
|
34058
|
-
workflow: "okx_ws_subscribe \
|
|
34602
|
+
workflow: "okx_ws_subscribe \u516C\u5F00\u9891\u9053 \u2192 okx_ws_subscribe_private \u79C1\u6709\u9891\u9053\uFF08\u9700Key\uFF09\u2192 okx_ws_events \u62C9\u53D6 \u2192 okx_ws_status \u7BA1\u7406",
|
|
34059
34603
|
tools: [
|
|
34060
|
-
{ name: "okx_ws_subscribe", auth: "\u516C\u5F00", params: "
|
|
34061
|
-
{ name: "
|
|
34062
|
-
{ name: "
|
|
34063
|
-
{ name: "
|
|
34604
|
+
{ name: "okx_ws_subscribe", auth: "\u516C\u5F00", params: "instId, channel (33\u516C\u5F00\u9891\u9053)", what: "\u8BA2\u9605\u516C\u5F00\u9891\u9053\uFF1A\u884C\u60C5/\u6DF1\u5EA6/\u7206\u4ED3/\u4EF7\u5DEE/\u5927\u5B97/\u8D44\u91D1\u8D39\u7387\u7B49" },
|
|
34605
|
+
{ name: "okx_ws_subscribe_private", auth: "API Key", params: "instId?, channel (22\u79C1\u6709\u9891\u9053)", what: "\u8BA2\u9605\u79C1\u6709\u9891\u9053\uFF1A\u8D26\u6237/\u6301\u4ED3/\u8BA2\u5355/\u7F51\u683C/\u8DDF\u5355\u7B49\u5B9E\u65F6\u63A8\u9001" },
|
|
34606
|
+
{ name: "okx_ws_events", auth: "\u516C\u5F00", params: "subscriptionId?, limit?, filter?", what: "\u62C9\u53D6\u7F13\u51B2\u7684\u5B9E\u65F6\u4E8B\u4EF6" },
|
|
34607
|
+
{ name: "okx_ws_status", auth: "\u516C\u5F00", params: "\u65E0", what: "\u5F53\u524D\u6240\u6709\u8BA2\u9605+\u7F13\u51B2\u79EF\u538B" },
|
|
34608
|
+
{ name: "okx_ws_close", auth: "\u516C\u5F00", params: "subscriptionId?", what: "\u5173\u95ED\u8BA2\u9605" }
|
|
34064
34609
|
]
|
|
34065
34610
|
},
|
|
34066
34611
|
"\u6A21\u62DF\u4F30\u7B97": {
|
|
@@ -35009,8 +35554,18 @@ function registerSmartMoneyTools(server, auth) {
|
|
|
35009
35554
|
);
|
|
35010
35555
|
}
|
|
35011
35556
|
|
|
35557
|
+
// node_modules/ws/wrapper.mjs
|
|
35558
|
+
var import_stream2 = __toESM(require_stream(), 1);
|
|
35559
|
+
var import_extension = __toESM(require_extension(), 1);
|
|
35560
|
+
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
35561
|
+
var import_receiver = __toESM(require_receiver(), 1);
|
|
35562
|
+
var import_sender = __toESM(require_sender(), 1);
|
|
35563
|
+
var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
35564
|
+
var import_websocket = __toESM(require_websocket(), 1);
|
|
35565
|
+
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
35566
|
+
var wrapper_default = import_websocket.default;
|
|
35567
|
+
|
|
35012
35568
|
// src/adapters/xlayer-ws.ts
|
|
35013
|
-
init_wrapper();
|
|
35014
35569
|
var WS_URL = process.env.XLAYER_WS_URL || "wss://xlayerws.okx.com";
|
|
35015
35570
|
var MAX_EVENTS = 500;
|
|
35016
35571
|
var XLayerWSManager = class {
|
|
@@ -35280,25 +35835,47 @@ var subCounter = 0;
|
|
|
35280
35835
|
var WsManager = class {
|
|
35281
35836
|
subscriptions = /* @__PURE__ */ new Map();
|
|
35282
35837
|
events = [];
|
|
35283
|
-
|
|
35284
|
-
|
|
35285
|
-
|
|
35286
|
-
|
|
35838
|
+
wsPub = null;
|
|
35839
|
+
wsPriv = null;
|
|
35840
|
+
pingPub = null;
|
|
35841
|
+
pingPriv = null;
|
|
35842
|
+
// Fix #1: 按 type 拆分 channelArgs,重连时只遍历同类型
|
|
35843
|
+
channelArgsPub = /* @__PURE__ */ new Map();
|
|
35844
|
+
channelArgsPriv = /* @__PURE__ */ new Map();
|
|
35845
|
+
getWs(type) {
|
|
35846
|
+
return type === "public" ? this.wsPub : this.wsPriv;
|
|
35847
|
+
}
|
|
35848
|
+
setWs(type, ws) {
|
|
35849
|
+
if (type === "public") this.wsPub = ws;
|
|
35850
|
+
else this.wsPriv = ws;
|
|
35851
|
+
}
|
|
35852
|
+
getPing(type) {
|
|
35853
|
+
return type === "public" ? this.pingPub : this.pingPriv;
|
|
35854
|
+
}
|
|
35855
|
+
setPing(type, timer) {
|
|
35856
|
+
if (type === "public") this.pingPub = timer;
|
|
35857
|
+
else this.pingPriv = timer;
|
|
35858
|
+
}
|
|
35859
|
+
getChannelArgs(type) {
|
|
35860
|
+
return type === "public" ? this.channelArgsPub : this.channelArgsPriv;
|
|
35861
|
+
}
|
|
35287
35862
|
async subscribe(opts) {
|
|
35288
|
-
const wsModule = await Promise.resolve().then(() => (init_wrapper(), wrapper_exports));
|
|
35289
35863
|
const id = `sub_${++subCounter}`;
|
|
35290
|
-
|
|
35864
|
+
const type = opts.type || "public";
|
|
35865
|
+
this.subscriptions.set(id, { id, channel: opts.channel, instId: opts.instId, type });
|
|
35291
35866
|
const arg = { channel: opts.channel, instId: opts.instId };
|
|
35292
|
-
|
|
35293
|
-
|
|
35294
|
-
|
|
35295
|
-
|
|
35296
|
-
|
|
35297
|
-
|
|
35298
|
-
|
|
35299
|
-
|
|
35300
|
-
|
|
35301
|
-
this.
|
|
35867
|
+
const currentWs = this.getWs(type);
|
|
35868
|
+
if (!currentWs || currentWs.readyState !== wrapper_default.OPEN) {
|
|
35869
|
+
const url = type === "private" ? WS_PRIVATE : WS_PUBLIC;
|
|
35870
|
+
await this.connect(url, opts.auth, type);
|
|
35871
|
+
}
|
|
35872
|
+
const targetWs = this.getWs(type);
|
|
35873
|
+
if (targetWs?.readyState === wrapper_default.OPEN) {
|
|
35874
|
+
targetWs.send(JSON.stringify({ op: "subscribe", args: [arg] }));
|
|
35875
|
+
}
|
|
35876
|
+
const chanArgs = this.getChannelArgs(type);
|
|
35877
|
+
if (!chanArgs.has(opts.channel)) chanArgs.set(opts.channel, /* @__PURE__ */ new Set());
|
|
35878
|
+
chanArgs.get(opts.channel).add(opts.instId);
|
|
35302
35879
|
return id;
|
|
35303
35880
|
}
|
|
35304
35881
|
drain(subId, limit = 20) {
|
|
@@ -35329,37 +35906,60 @@ var WsManager = class {
|
|
|
35329
35906
|
}
|
|
35330
35907
|
close(subId) {
|
|
35331
35908
|
if (subId) {
|
|
35909
|
+
const sub = this.subscriptions.get(subId);
|
|
35910
|
+
if (sub) {
|
|
35911
|
+
const chanArgs = this.getChannelArgs(sub.type);
|
|
35912
|
+
const instIds = chanArgs.get(sub.channel);
|
|
35913
|
+
if (instIds) {
|
|
35914
|
+
instIds.delete(sub.instId);
|
|
35915
|
+
if (instIds.size === 0) chanArgs.delete(sub.channel);
|
|
35916
|
+
}
|
|
35917
|
+
const ws = this.getWs(sub.type);
|
|
35918
|
+
if (ws?.readyState === wrapper_default.OPEN) {
|
|
35919
|
+
try {
|
|
35920
|
+
ws.send(JSON.stringify({ op: "unsubscribe", args: [{ channel: sub.channel, instId: sub.instId }] }));
|
|
35921
|
+
} catch {
|
|
35922
|
+
}
|
|
35923
|
+
}
|
|
35924
|
+
}
|
|
35332
35925
|
this.subscriptions.delete(subId);
|
|
35333
35926
|
this.events = this.events.filter((e) => e.subId !== subId);
|
|
35334
35927
|
return 1;
|
|
35335
35928
|
}
|
|
35336
35929
|
const count = this.subscriptions.size;
|
|
35337
35930
|
this.subscriptions.clear();
|
|
35931
|
+
this.channelArgsPub.clear();
|
|
35932
|
+
this.channelArgsPriv.clear();
|
|
35338
35933
|
this.events = [];
|
|
35339
|
-
|
|
35340
|
-
|
|
35341
|
-
|
|
35342
|
-
|
|
35934
|
+
for (const ws of [this.wsPub, this.wsPriv]) {
|
|
35935
|
+
if (ws) {
|
|
35936
|
+
try {
|
|
35937
|
+
ws.close();
|
|
35938
|
+
} catch {
|
|
35939
|
+
}
|
|
35343
35940
|
}
|
|
35344
|
-
;
|
|
35345
|
-
this.ws = null;
|
|
35346
35941
|
}
|
|
35347
|
-
|
|
35348
|
-
|
|
35349
|
-
|
|
35942
|
+
this.wsPub = null;
|
|
35943
|
+
this.wsPriv = null;
|
|
35944
|
+
for (const t of [this.pingPub, this.pingPriv]) {
|
|
35945
|
+
if (t) {
|
|
35946
|
+
clearInterval(t);
|
|
35947
|
+
}
|
|
35350
35948
|
}
|
|
35949
|
+
this.pingPub = null;
|
|
35950
|
+
this.pingPriv = null;
|
|
35351
35951
|
return count;
|
|
35352
35952
|
}
|
|
35353
|
-
connect(
|
|
35953
|
+
connect(url, auth, type) {
|
|
35354
35954
|
return new Promise((resolve2, reject) => {
|
|
35355
|
-
const ws = new
|
|
35955
|
+
const ws = new wrapper_default(url);
|
|
35356
35956
|
const timeout = setTimeout(() => {
|
|
35357
35957
|
ws.close();
|
|
35358
35958
|
reject(new Error("WS \u8FDE\u63A5\u8D85\u65F6(10s)"));
|
|
35359
35959
|
}, 1e4);
|
|
35360
35960
|
ws.on("open", () => {
|
|
35361
35961
|
clearTimeout(timeout);
|
|
35362
|
-
if (auth &&
|
|
35962
|
+
if (auth && type === "private") {
|
|
35363
35963
|
const ts = Math.floor(Date.now() / 1e3).toString();
|
|
35364
35964
|
const sign2 = import_node_crypto2.default.createHmac("sha256", auth.secret).update(ts + "GET/users/self/verify").digest("base64");
|
|
35365
35965
|
ws.send(JSON.stringify({
|
|
@@ -35367,15 +35967,17 @@ var WsManager = class {
|
|
|
35367
35967
|
args: [{ apiKey: auth.apiKey, passphrase: auth.passphrase, timestamp: ts, sign: sign2 }]
|
|
35368
35968
|
}));
|
|
35369
35969
|
}
|
|
35370
|
-
|
|
35970
|
+
const chanArgs = this.getChannelArgs(type);
|
|
35971
|
+
for (const [channel, instIds] of chanArgs) {
|
|
35371
35972
|
for (const instId of instIds) {
|
|
35372
35973
|
ws.send(JSON.stringify({ op: "subscribe", args: [{ channel, instId }] }));
|
|
35373
35974
|
}
|
|
35374
35975
|
}
|
|
35375
|
-
|
|
35376
|
-
if (ws.readyState ===
|
|
35976
|
+
const timer = setInterval(() => {
|
|
35977
|
+
if (ws.readyState === wrapper_default.OPEN) ws.send("ping");
|
|
35377
35978
|
}, 25e3);
|
|
35378
|
-
this.
|
|
35979
|
+
this.setPing(type, timer);
|
|
35980
|
+
this.setWs(type, ws);
|
|
35379
35981
|
resolve2();
|
|
35380
35982
|
});
|
|
35381
35983
|
ws.on("message", (raw) => {
|
|
@@ -35383,6 +35985,22 @@ var WsManager = class {
|
|
|
35383
35985
|
const msg = raw.toString();
|
|
35384
35986
|
if (msg === "pong") return;
|
|
35385
35987
|
const parsed = JSON.parse(msg);
|
|
35988
|
+
if (parsed.event === "error" && parsed.code) {
|
|
35989
|
+
this.events.push({
|
|
35990
|
+
subId: "__error__",
|
|
35991
|
+
channel: parsed.arg?.channel || "unknown",
|
|
35992
|
+
instId: parsed.arg?.instId || "",
|
|
35993
|
+
ts: Date.now(),
|
|
35994
|
+
data: {
|
|
35995
|
+
error: true,
|
|
35996
|
+
code: parsed.code,
|
|
35997
|
+
message: parsed.msg || "WebSocket \u9519\u8BEF",
|
|
35998
|
+
hint: parsed.code === "60001" ? "\u9891\u9053\u540D\u4E0D\u652F\u6301\u6216\u53C2\u6570\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5 channel \u503C" : parsed.code === "60003" ? "\u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u8FDE" : parsed.code === "60009" ? "\u79C1\u6709\u9891\u9053\u9700\u8981\u5148 login\uFF08API Key \u7B7E\u540D\uFF09" : `OKX WS \u9519\u8BEF ${parsed.code}`
|
|
35999
|
+
}
|
|
36000
|
+
});
|
|
36001
|
+
if (this.events.length > 1e4) this.events = this.events.slice(-5e3);
|
|
36002
|
+
return;
|
|
36003
|
+
}
|
|
35386
36004
|
if (parsed.arg && parsed.data) {
|
|
35387
36005
|
for (const [id, sub] of this.subscriptions) {
|
|
35388
36006
|
if (sub.channel === parsed.arg.channel && sub.instId === parsed.arg.instId) {
|
|
@@ -35406,11 +36024,12 @@ var WsManager = class {
|
|
|
35406
36024
|
reject(err);
|
|
35407
36025
|
});
|
|
35408
36026
|
ws.on("close", () => {
|
|
35409
|
-
|
|
35410
|
-
|
|
35411
|
-
|
|
36027
|
+
const t = this.getPing(type);
|
|
36028
|
+
if (t) {
|
|
36029
|
+
clearInterval(t);
|
|
36030
|
+
this.setPing(type, null);
|
|
35412
36031
|
}
|
|
35413
|
-
this.
|
|
36032
|
+
this.setWs(type, null);
|
|
35414
36033
|
});
|
|
35415
36034
|
});
|
|
35416
36035
|
}
|
|
@@ -35422,36 +36041,103 @@ function getOrCreateWs() {
|
|
|
35422
36041
|
if (!wsManager) wsManager = new WsManager();
|
|
35423
36042
|
return wsManager;
|
|
35424
36043
|
}
|
|
35425
|
-
var
|
|
35426
|
-
|
|
35427
|
-
|
|
35428
|
-
|
|
35429
|
-
|
|
35430
|
-
|
|
35431
|
-
|
|
35432
|
-
|
|
35433
|
-
|
|
35434
|
-
|
|
35435
|
-
|
|
35436
|
-
|
|
35437
|
-
|
|
35438
|
-
|
|
35439
|
-
|
|
35440
|
-
|
|
35441
|
-
|
|
35442
|
-
|
|
36044
|
+
var ALL_CHANNELS = {
|
|
36045
|
+
public: [
|
|
36046
|
+
// 行情类(10)
|
|
36047
|
+
"tickers",
|
|
36048
|
+
"trades",
|
|
36049
|
+
"all-trades",
|
|
36050
|
+
"option-trades",
|
|
36051
|
+
"candle1m",
|
|
36052
|
+
"candle5m",
|
|
36053
|
+
"candle15m",
|
|
36054
|
+
"candle1H",
|
|
36055
|
+
"candle4H",
|
|
36056
|
+
"candle1D",
|
|
36057
|
+
// 深度类(2)
|
|
36058
|
+
"books5",
|
|
36059
|
+
"books",
|
|
36060
|
+
// 市场细节(1)
|
|
36061
|
+
"call-auction-details",
|
|
36062
|
+
// 公共数据(10)
|
|
36063
|
+
"mark-price",
|
|
36064
|
+
"mark-price-candles",
|
|
36065
|
+
"index-tickers",
|
|
36066
|
+
"index-candles",
|
|
36067
|
+
"funding-rate",
|
|
36068
|
+
"open-interest",
|
|
36069
|
+
"price-limit",
|
|
36070
|
+
"instruments",
|
|
36071
|
+
"option-summary",
|
|
36072
|
+
"estimated-price",
|
|
36073
|
+
// 风险预警(3)
|
|
36074
|
+
"liquidation-orders",
|
|
36075
|
+
"adl-warning",
|
|
36076
|
+
"status",
|
|
36077
|
+
// 事件合约(1)
|
|
36078
|
+
"event-contract-markets",
|
|
36079
|
+
// 经济日历(1)
|
|
36080
|
+
"economic-calendar",
|
|
36081
|
+
// 价差公开(4)
|
|
36082
|
+
"sprd/tickers",
|
|
36083
|
+
"sprd/candles",
|
|
36084
|
+
"sprd/order-book",
|
|
36085
|
+
"sprd/public-trades",
|
|
36086
|
+
// 大宗公开(3)
|
|
36087
|
+
"public-structure-block-trades",
|
|
36088
|
+
"public-block-trades",
|
|
36089
|
+
"block-tickers"
|
|
36090
|
+
],
|
|
36091
|
+
private: [
|
|
36092
|
+
// 账户(5)
|
|
36093
|
+
"account",
|
|
36094
|
+
"positions",
|
|
36095
|
+
"balance_and_position",
|
|
36096
|
+
"position-risk-warning",
|
|
36097
|
+
"account-greeks",
|
|
36098
|
+
// 交易(4)
|
|
36099
|
+
"orders",
|
|
36100
|
+
"fills",
|
|
36101
|
+
"algo-orders",
|
|
36102
|
+
"advance-algo-orders",
|
|
36103
|
+
// 网格(4)
|
|
36104
|
+
"spot-grid-algo-orders",
|
|
36105
|
+
"contract-grid-algo-orders",
|
|
36106
|
+
"grid-positions",
|
|
36107
|
+
"grid-sub-orders",
|
|
36108
|
+
// 定投(1)
|
|
36109
|
+
"recurring-buy-orders",
|
|
36110
|
+
// 跟单(1)
|
|
36111
|
+
"lead-trading-notification",
|
|
36112
|
+
// 资金(2)
|
|
36113
|
+
"deposit-info",
|
|
36114
|
+
"withdrawal-info",
|
|
36115
|
+
// 大宗私有(3)
|
|
36116
|
+
"rfqs",
|
|
36117
|
+
"quotes",
|
|
36118
|
+
"structure-block-trades",
|
|
36119
|
+
// 价差私有(2)
|
|
36120
|
+
"sprd/orders",
|
|
36121
|
+
"sprd/trades"
|
|
36122
|
+
]
|
|
36123
|
+
};
|
|
36124
|
+
function registerWsTools(server, auth) {
|
|
35443
36125
|
server.tool(
|
|
35444
36126
|
"okx_ws_subscribe",
|
|
35445
|
-
"CAT:[\u884C\u60C5-WS] | ## \u529F\u80FD\uFF1A\u8BA2\
|
|
36127
|
+
"CAT:[\u884C\u60C5-WS] | ## \u529F\u80FD\uFF1A\u8BA2\u9605 OKX WebSocket \u5B9E\u65F6\u516C\u5F00\u9891\u9053\uFF0C\u4E8B\u4EF6\u81EA\u52A8\u7F13\u51B2\u5728\u5185\u5B58\u4E2D\n## \u573A\u666F\uFF1AAgent \u9700\u8981\u5B9E\u65F6\u76D1\u63A7\u884C\u60C5\u3001\u7206\u4ED3\u5355\u3001\u8D44\u91D1\u8D39\u7387\u3001\u4EF7\u5DEE/\u5927\u5B97\u5E02\u573A\u65F6\u8C03\u7528\uFF0C\u66FF\u4EE3 REST \u8F6E\u8BE2\n## \u5173\u952E\u8BCD\uFF1AWebSocket, ws, \u5B9E\u65F6\u63A8\u9001, \u5B9E\u65F6\u884C\u60C5, \u8BA2\u9605, subscribe, \u7206\u4ED3, \u8D44\u91D1\u8D39\u7387, \u4EF7\u5DEE, \u5927\u5B97\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT\u3001ETH-USDT-SWAP\u3002status/instruments/economic-calendar \u7B49\u5168\u5C40\u9891\u9053\u4E0D\u9700\u8981 instId\n## - channel: \u9891\u9053\u540D\u3002\u53EF\u9009: tickers / trades / all-trades / candle1m~1D / books5 / books / funding-rate / open-interest / price-limit / instruments / mark-price / mark-price-candles / index-tickers / index-candles / option-summary / estimated-price / liquidation-orders / adl-warning / event-contract-markets / economic-calendar / status / sprd/* / public-*-block-trades / block-tickers\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u9891\u9053\uFF0C\u65E0\u9700 API Key\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u8BA2\u9605 \u2192 okx_ws_events \u62C9\u53D6 \u2192 okx_ws_close \u5173\u95ED",
|
|
35446
36128
|
{
|
|
35447
|
-
instId: external_exports.string().describe("\u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT"),
|
|
35448
|
-
channel: external_exports.string().describe("\u9891\u9053\u540D"),
|
|
35449
|
-
instType: external_exports.enum(["SPOT", "SWAP", "FUTURES", "OPTION"]).optional().describe("
|
|
36129
|
+
instId: external_exports.string().describe("\u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT\u3001ETH-USDT-SWAP\u3002\u7EAF\u5168\u5C40\u9891\u9053\uFF08status/instruments/economic-calendar\uFF09\u53EF\u4F20\u7A7A\u5B57\u7B26\u4E32"),
|
|
36130
|
+
channel: external_exports.string().describe("\u9891\u9053\u540D\u3002\u516C\u5F00\u9891\u9053\u5171 33 \u4E2A\uFF0C\u652F\u6301 tickers/trades/candle1m~1D/books5/books/funding-rate/open-interest/price-limit/instruments/mark-price/mark-price-candles/index-tickers/index-candles/option-summary/estimated-price/liquidation-orders/adl-warning/event-contract-markets/economic-calendar/status/sprd\u7CFB\u5217/public-block-trades\u7CFB\u5217/block-tickers"),
|
|
36131
|
+
instType: external_exports.enum(["SPOT", "SWAP", "FUTURES", "OPTION"]).optional().describe("\u90E8\u5206\u9891\u9053\u9700\u8981\u4EA7\u54C1\u7C7B\u578B")
|
|
35450
36132
|
},
|
|
35451
36133
|
async ({ instId, channel }) => {
|
|
35452
36134
|
try {
|
|
35453
|
-
if (!
|
|
35454
|
-
return toError(new Error(
|
|
36135
|
+
if (!ALL_CHANNELS.public.includes(channel)) {
|
|
36136
|
+
return toError(new Error(
|
|
36137
|
+
`\u9891\u9053 "${channel}" \u975E\u516C\u5F00\u9891\u9053\u3002
|
|
36138
|
+
\u516C\u5F00\u9891\u9053(${ALL_CHANNELS.public.length}\u4E2A): ${ALL_CHANNELS.public.join(" ")}
|
|
36139
|
+
\u79C1\u6709\u9891\u9053\u8BF7\u7528 okx_ws_subscribe_private\u3002`
|
|
36140
|
+
));
|
|
35455
36141
|
}
|
|
35456
36142
|
const ws = getOrCreateWs();
|
|
35457
36143
|
const subId = await ws.subscribe({ channel, instId: instId.toUpperCase(), type: "public" });
|
|
@@ -35460,8 +36146,48 @@ function registerWsTools(server) {
|
|
|
35460
36146
|
subscriptionId: subId,
|
|
35461
36147
|
channel,
|
|
35462
36148
|
instId: instId.toUpperCase(),
|
|
36149
|
+
type: "public",
|
|
35463
36150
|
buffered: ws.countBuffered(subId),
|
|
35464
|
-
hint: `\u5DF2\u8BA2\u9605 ${instId
|
|
36151
|
+
hint: `\u5DF2\u8BA2\u9605 ${instId || "\u5168\u5C40"} ${channel}\u3002\u8C03\u7528 okx_ws_events \u62C9\u53D6\u4E8B\u4EF6\u3002`,
|
|
36152
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36153
|
+
});
|
|
36154
|
+
} catch (e) {
|
|
36155
|
+
return toError(e);
|
|
36156
|
+
}
|
|
36157
|
+
}
|
|
36158
|
+
);
|
|
36159
|
+
server.tool(
|
|
36160
|
+
"okx_ws_subscribe_private",
|
|
36161
|
+
"CAT:[\u884C\u60C5-WS] | ## \u529F\u80FD\uFF1A\u8BA2\u9605 OKX WebSocket \u79C1\u6709\u9891\u9053\u2014\u2014\u5B9E\u65F6\u63A8\u9001\u8D26\u6237\u4F59\u989D\u3001\u6301\u4ED3\u53D8\u52A8\u3001\u8BA2\u5355\u6210\u4EA4\u3001\u7F51\u683C/\u7B56\u7565/\u8DDF\u5355\u72B6\u6001\n## \u573A\u666F\uFF1AAgent \u9700\u8981\u5B9E\u65F6\u8DDF\u8E2A\u8D26\u6237\u53D8\u5316\uFF08\u975E\u8F6E\u8BE2 REST\uFF09\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1AWebSocket, ws, \u79C1\u6709\u9891\u9053, \u5B9E\u65F6\u8D26\u6237, \u8BA2\u5355\u63A8\u9001, positions, orders, \u7F51\u683C, \u8DDF\u5355\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\u3002account/positions/balance_and_position \u7B49\u8D26\u6237\u7EA7\u9891\u9053\u53EF\u4E0D\u4F20\n## - channel: \u79C1\u6709\u9891\u9053\u540D\u3002\u53EF\u9009: account / positions / balance_and_position / position-risk-warning / account-greeks / orders / fills / algo-orders / advance-algo-orders / spot-grid-algo-orders / contract-grid-algo-orders / grid-positions / grid-sub-orders / recurring-buy-orders / lead-trading-notification / deposit-info / withdrawal-info / rfqs / quotes / structure-block-trades / sprd/orders / sprd/trades\n## \u9274\u6743\uFF1A\u26A0\uFE0F \u9700\u8981 API Key\uFF08\u5FC5\u987B\u5F00\u901A\u8BFB\u53D6\u6743\u9650\uFF09\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\u8BA2\u9605\uFF0C\u4F46\u9700 API Key\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u8BA2\u9605 \u2192 okx_ws_events \u62C9\u53D6 \u2192 okx_ws_close \u5173\u95ED",
|
|
36162
|
+
{
|
|
36163
|
+
instId: external_exports.string().optional().describe("\u4EA7\u54C1ID\u3002\u8D26\u6237\u7EA7\u9891\u9053\u53EF\u4E0D\u4F20\uFF08\u5982 account/positions/balances\uFF09"),
|
|
36164
|
+
channel: external_exports.string().describe("\u79C1\u6709\u9891\u9053\u540D\u3002\u5171 22 \u4E2A: account / positions / balance_and_position / position-risk-warning / account-greeks / orders / fills / algo-orders / advance-algo-orders / spot-grid-algo-orders / contract-grid-algo-orders / grid-positions / grid-sub-orders / recurring-buy-orders / lead-trading-notification / deposit-info / withdrawal-info / rfqs / quotes / structure-block-trades / sprd/orders / sprd/trades")
|
|
36165
|
+
},
|
|
36166
|
+
async ({ instId, channel }) => {
|
|
36167
|
+
if (!auth) return toError(AUTH_REQUIRED);
|
|
36168
|
+
try {
|
|
36169
|
+
if (!ALL_CHANNELS.private.includes(channel)) {
|
|
36170
|
+
return toError(new Error(
|
|
36171
|
+
`\u9891\u9053 "${channel}" \u975E\u79C1\u6709\u9891\u9053\u3002
|
|
36172
|
+
\u79C1\u6709\u9891\u9053(${ALL_CHANNELS.private.length}\u4E2A): ${ALL_CHANNELS.private.join(" ")}
|
|
36173
|
+
\u516C\u5F00\u9891\u9053\u8BF7\u7528 okx_ws_subscribe\u3002`
|
|
36174
|
+
));
|
|
36175
|
+
}
|
|
36176
|
+
const ws = getOrCreateWs();
|
|
36177
|
+
const subId = await ws.subscribe({
|
|
36178
|
+
channel,
|
|
36179
|
+
instId: (instId || "").toUpperCase(),
|
|
36180
|
+
type: "private",
|
|
36181
|
+
auth
|
|
36182
|
+
});
|
|
36183
|
+
return toResult({
|
|
36184
|
+
subscribed: true,
|
|
36185
|
+
subscriptionId: subId,
|
|
36186
|
+
channel,
|
|
36187
|
+
instId: (instId || "\u5168\u5C40").toUpperCase(),
|
|
36188
|
+
type: "private",
|
|
36189
|
+
buffered: ws.countBuffered(subId),
|
|
36190
|
+
hint: `\u5DF2\u8BA2\u9605\u79C1\u6709\u9891\u9053 ${channel}\u3002\u8C03\u7528 okx_ws_events \u62C9\u53D6\u5B9E\u65F6\u4E8B\u4EF6\u3002`,
|
|
35465
36191
|
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
35466
36192
|
});
|
|
35467
36193
|
} catch (e) {
|
|
@@ -35536,7 +36262,6 @@ function registerWsTools(server) {
|
|
|
35536
36262
|
}
|
|
35537
36263
|
|
|
35538
36264
|
// src/adapters/agent-hub.ts
|
|
35539
|
-
init_wrapper();
|
|
35540
36265
|
var MAX_ROOM_MESSAGES = 200;
|
|
35541
36266
|
var AgentHub = class {
|
|
35542
36267
|
wss = null;
|
|
@@ -36089,97 +36814,210 @@ function registerAgentHubTools(server) {
|
|
|
36089
36814
|
var path2 = __toESM(require("node:path"));
|
|
36090
36815
|
var fs2 = __toESM(require("node:fs"));
|
|
36091
36816
|
var DatabaseSync = null;
|
|
36092
|
-
|
|
36093
|
-
|
|
36094
|
-
|
|
36095
|
-
|
|
36096
|
-
|
|
36097
|
-
|
|
36098
|
-
|
|
36099
|
-
|
|
36817
|
+
var _sqliteAvailable = null;
|
|
36818
|
+
function isSqliteAvailable() {
|
|
36819
|
+
if (_sqliteAvailable !== null) return _sqliteAvailable;
|
|
36820
|
+
try {
|
|
36821
|
+
const sqlite = require("node:sqlite");
|
|
36822
|
+
DatabaseSync = sqlite.DatabaseSync;
|
|
36823
|
+
_sqliteAvailable = true;
|
|
36824
|
+
return true;
|
|
36825
|
+
} catch {
|
|
36826
|
+
_sqliteAvailable = false;
|
|
36827
|
+
return false;
|
|
36100
36828
|
}
|
|
36101
|
-
|
|
36102
|
-
|
|
36829
|
+
}
|
|
36830
|
+
function getDBPath() {
|
|
36831
|
+
return path2.resolve(".codegraph", "codegraph.db");
|
|
36832
|
+
}
|
|
36833
|
+
function openDB() {
|
|
36834
|
+
if (!isSqliteAvailable()) return null;
|
|
36835
|
+
const dbPath = getDBPath();
|
|
36836
|
+
if (!fs2.existsSync(dbPath)) return null;
|
|
36837
|
+
try {
|
|
36838
|
+
return new DatabaseSync(dbPath, { readonly: true });
|
|
36839
|
+
} catch {
|
|
36103
36840
|
return null;
|
|
36104
36841
|
}
|
|
36842
|
+
}
|
|
36843
|
+
function safeGet(db, sql, ...params) {
|
|
36105
36844
|
try {
|
|
36106
|
-
const
|
|
36107
|
-
|
|
36108
|
-
|
|
36109
|
-
} catch (e) {
|
|
36845
|
+
const stmt = db.prepare(sql);
|
|
36846
|
+
return stmt.get(...params.length ? params : []);
|
|
36847
|
+
} catch {
|
|
36110
36848
|
return null;
|
|
36111
36849
|
}
|
|
36112
36850
|
}
|
|
36851
|
+
function safeAll(db, sql, limit, ...params) {
|
|
36852
|
+
try {
|
|
36853
|
+
const stmt = db.prepare(sql);
|
|
36854
|
+
const all = stmt.all(...params.length ? params : []);
|
|
36855
|
+
return (Array.isArray(all) ? all : []).slice(0, limit);
|
|
36856
|
+
} catch {
|
|
36857
|
+
return [];
|
|
36858
|
+
}
|
|
36859
|
+
}
|
|
36860
|
+
function findNodes(db, name, limit = 5) {
|
|
36861
|
+
const exact = safeAll(
|
|
36862
|
+
db,
|
|
36863
|
+
"SELECT * FROM nodes WHERE name = ? LIMIT ?",
|
|
36864
|
+
limit,
|
|
36865
|
+
name,
|
|
36866
|
+
limit
|
|
36867
|
+
);
|
|
36868
|
+
if (exact.length > 0) return exact;
|
|
36869
|
+
return safeAll(
|
|
36870
|
+
db,
|
|
36871
|
+
"SELECT * FROM nodes WHERE name LIKE ? LIMIT ?",
|
|
36872
|
+
limit,
|
|
36873
|
+
`%${name}%`,
|
|
36874
|
+
limit
|
|
36875
|
+
);
|
|
36876
|
+
}
|
|
36877
|
+
function getCallers(db, nodeId, limit = 50) {
|
|
36878
|
+
return safeAll(db, `
|
|
36879
|
+
SELECT n.name, n.kind, n.file_path, n.start_line, e.line, e.kind as edge_kind
|
|
36880
|
+
FROM edges e
|
|
36881
|
+
JOIN nodes n ON e.source = n.id
|
|
36882
|
+
WHERE e.target = ? AND e.kind = 'calls'
|
|
36883
|
+
ORDER BY n.file_path, n.start_line
|
|
36884
|
+
LIMIT ?
|
|
36885
|
+
`, limit, nodeId, limit);
|
|
36886
|
+
}
|
|
36887
|
+
function getCallees(db, nodeId, limit = 50) {
|
|
36888
|
+
return safeAll(db, `
|
|
36889
|
+
SELECT n.name, n.kind, n.file_path, n.start_line, e.line, e.kind as edge_kind
|
|
36890
|
+
FROM edges e
|
|
36891
|
+
JOIN nodes n ON e.target = n.id
|
|
36892
|
+
WHERE e.source = ? AND e.kind = 'calls'
|
|
36893
|
+
ORDER BY n.file_path, n.start_line
|
|
36894
|
+
LIMIT ?
|
|
36895
|
+
`, limit, nodeId, limit);
|
|
36896
|
+
}
|
|
36897
|
+
function getImpact(db, nodeId, maxDepth = 2, limit = 50) {
|
|
36898
|
+
const direct = getCallers(db, nodeId, limit);
|
|
36899
|
+
const indirectMap = /* @__PURE__ */ new Map();
|
|
36900
|
+
for (const d of direct.slice(0, 10)) {
|
|
36901
|
+
const node = safeGet(
|
|
36902
|
+
db,
|
|
36903
|
+
"SELECT id, name, kind, file_path FROM nodes WHERE name = ? AND file_path = ? LIMIT 1",
|
|
36904
|
+
d.name,
|
|
36905
|
+
d.file_path
|
|
36906
|
+
);
|
|
36907
|
+
if (node) {
|
|
36908
|
+
const indirect = safeAll(db, `
|
|
36909
|
+
SELECT n.name, n.kind, n.file_path, n.start_line
|
|
36910
|
+
FROM edges e JOIN nodes n ON e.source = n.id
|
|
36911
|
+
WHERE e.target = ? AND e.kind = 'calls'
|
|
36912
|
+
LIMIT 5
|
|
36913
|
+
`, 5, node.id);
|
|
36914
|
+
for (const idr of indirect) {
|
|
36915
|
+
const key = `${idr.name}@${idr.file_path}`;
|
|
36916
|
+
if (!indirectMap.has(key)) indirectMap.set(key, idr);
|
|
36917
|
+
}
|
|
36918
|
+
}
|
|
36919
|
+
}
|
|
36920
|
+
return { direct, indirect: [...indirectMap.values()].slice(0, limit) };
|
|
36921
|
+
}
|
|
36113
36922
|
function registerCodeGraphTools(server) {
|
|
36114
36923
|
server.tool(
|
|
36115
36924
|
"codegraph_status",
|
|
36116
|
-
"CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u68C0\u67E5\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u72B6\u6001\u2014\u2014\u8282\u70B9\u6570\u3001\u8FB9\u6570\u3001\u8986\u76D6\u6587\u4EF6\u3001\u6700\
|
|
36925
|
+
"CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u68C0\u67E5\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u72B6\u6001\u2014\u2014\u8282\u70B9\u6570\u3001\u8FB9\u6570\u3001\u8986\u76D6\u6587\u4EF6\u3001\u88AB\u8C03\u6700\u591A\u7684\u51FD\u6570\n## \u573A\u666F\uFF1AAgent \u9996\u6B21\u8FDE\u63A5\u65F6\u786E\u8BA4\u56FE\u8C31\u5C31\u7EEA\n## \u5173\u952E\u8BCD\uFF1A\u4EE3\u7801\u56FE\u8C31, codegraph, \u77E5\u8BC6\u56FE\u8C31, \u7D22\u5F15\u72B6\u6001, \u8C03\u7528\u6392\u884C\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB DB\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~1KB\n## \u5173\u8054\uFF1A\u786E\u8BA4\u72B6\u6001 \u2192 codegraph_query \u8FFD\u8E2A\u8C03\u7528\u94FE",
|
|
36117
36926
|
{},
|
|
36118
36927
|
async () => {
|
|
36119
36928
|
try {
|
|
36120
|
-
|
|
36121
|
-
if (!conn) {
|
|
36929
|
+
if (!isSqliteAvailable()) {
|
|
36122
36930
|
const nodeVersion = process.versions.node;
|
|
36123
|
-
const nodeMajor = parseInt(nodeVersion.split(".")[0]);
|
|
36124
|
-
const needsUpgrade = nodeMajor < 22 || nodeMajor === 22 && parseInt(nodeVersion.split(".")[1]) < 5;
|
|
36125
36931
|
return toResult({
|
|
36126
36932
|
status: "unavailable",
|
|
36127
|
-
reason:
|
|
36933
|
+
reason: `Node.js ${nodeVersion} \u4E0D\u652F\u6301\u5185\u7F6E sqlite\uFF0C\u9700\u8981 Node >= 22.5.0`,
|
|
36934
|
+
nodeVersion,
|
|
36935
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
36936
|
+
_summary: `\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\uFF1A\u9700 Node >= 22.5.0\uFF0C\u5F53\u524D ${nodeVersion}`
|
|
36937
|
+
});
|
|
36938
|
+
}
|
|
36939
|
+
const dbPath = getDBPath();
|
|
36940
|
+
if (!fs2.existsSync(dbPath)) {
|
|
36941
|
+
return toResult({
|
|
36942
|
+
status: "no_db",
|
|
36943
|
+
reason: `.codegraph/codegraph.db \u4E0D\u5B58\u5728`,
|
|
36128
36944
|
how_to_setup: [
|
|
36129
36945
|
"1. npm i -g @colbymchenry/codegraph",
|
|
36130
|
-
"2. cd \u5230\u9879\u76EE\u6839\u76EE\u5F55",
|
|
36131
|
-
"3.
|
|
36132
|
-
"
|
|
36946
|
+
"2. cd \u5230\u9879\u76EE\u6839\u76EE\u5F55\u8FD0\u884C codegraph index",
|
|
36947
|
+
"3. \u91CD\u542F MCP Server",
|
|
36948
|
+
"\uFF08Claude Code \u7528\u6237\uFF1A\u56FE\u8C31\u7531 CodeGraph \u529F\u80FD\u81EA\u52A8\u751F\u6210\uFF09"
|
|
36133
36949
|
].join("\n"),
|
|
36134
|
-
nodeVersion,
|
|
36135
36950
|
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
36136
|
-
_summary:
|
|
36951
|
+
_summary: "\u4EE3\u7801\u56FE\u8C31\u672A\u751F\u6210\u3002\u8FD0\u884C codegraph index \u540E\u53EF\u7528\u3002"
|
|
36137
36952
|
});
|
|
36138
36953
|
}
|
|
36139
|
-
const
|
|
36140
|
-
|
|
36141
|
-
|
|
36142
|
-
|
|
36143
|
-
|
|
36144
|
-
|
|
36145
|
-
|
|
36146
|
-
|
|
36147
|
-
|
|
36148
|
-
|
|
36149
|
-
|
|
36150
|
-
"SELECT
|
|
36151
|
-
|
|
36152
|
-
|
|
36153
|
-
|
|
36154
|
-
|
|
36155
|
-
|
|
36156
|
-
|
|
36157
|
-
|
|
36158
|
-
|
|
36159
|
-
|
|
36160
|
-
|
|
36161
|
-
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
|
|
36166
|
-
|
|
36167
|
-
|
|
36168
|
-
|
|
36169
|
-
|
|
36170
|
-
|
|
36171
|
-
|
|
36172
|
-
|
|
36173
|
-
|
|
36174
|
-
|
|
36175
|
-
|
|
36176
|
-
|
|
36177
|
-
|
|
36178
|
-
|
|
36179
|
-
|
|
36180
|
-
|
|
36181
|
-
|
|
36182
|
-
|
|
36954
|
+
const db = openDB();
|
|
36955
|
+
if (!db) {
|
|
36956
|
+
return toResult({
|
|
36957
|
+
status: "error",
|
|
36958
|
+
reason: "\u65E0\u6CD5\u6253\u5F00\u4EE3\u7801\u56FE\u8C31\u6570\u636E\u5E93\uFF08\u53EF\u80FD\u88AB\u9501\u5B9A\uFF09",
|
|
36959
|
+
dbPath,
|
|
36960
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
36961
|
+
_summary: "\u4EE3\u7801\u56FE\u8C31\u6570\u636E\u5E93\u6253\u5F00\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002"
|
|
36962
|
+
});
|
|
36963
|
+
}
|
|
36964
|
+
try {
|
|
36965
|
+
const nodeCount = safeGet(db, "SELECT count(*) as n FROM nodes")?.n || 0;
|
|
36966
|
+
const edgeCount = safeGet(db, "SELECT count(*) as n FROM edges")?.n || 0;
|
|
36967
|
+
const fileCount = safeGet(db, "SELECT count(*) as n FROM files")?.n || 0;
|
|
36968
|
+
const byLang = safeAll(
|
|
36969
|
+
db,
|
|
36970
|
+
"SELECT language, count(*) as n FROM files GROUP BY language ORDER BY n DESC",
|
|
36971
|
+
20
|
|
36972
|
+
);
|
|
36973
|
+
const byKind = safeAll(
|
|
36974
|
+
db,
|
|
36975
|
+
"SELECT kind, count(*) as n FROM nodes GROUP BY kind ORDER BY n DESC",
|
|
36976
|
+
20
|
|
36977
|
+
);
|
|
36978
|
+
let topCalled = [];
|
|
36979
|
+
try {
|
|
36980
|
+
topCalled = safeAll(db, `
|
|
36981
|
+
SELECT n.name, n.kind, n.file_path, count(e.id) as caller_count
|
|
36982
|
+
FROM edges e
|
|
36983
|
+
JOIN nodes n ON e.target = n.id
|
|
36984
|
+
WHERE e.kind = 'calls'
|
|
36985
|
+
GROUP BY e.target
|
|
36986
|
+
ORDER BY caller_count DESC
|
|
36987
|
+
LIMIT 5
|
|
36988
|
+
`, 5) || [];
|
|
36989
|
+
} catch {
|
|
36990
|
+
}
|
|
36991
|
+
const lastIndexed = safeGet(
|
|
36992
|
+
db,
|
|
36993
|
+
"SELECT max(indexed_at) as ts FROM files"
|
|
36994
|
+
)?.ts;
|
|
36995
|
+
db.close();
|
|
36996
|
+
const status = {
|
|
36997
|
+
status: "ready",
|
|
36998
|
+
dbPath,
|
|
36999
|
+
database: { nodeCount, edgeCount, fileCount },
|
|
37000
|
+
languages: byLang.reduce((acc, r) => ({ ...acc, [r.language]: r.n }), {}),
|
|
37001
|
+
nodesByKind: byKind.reduce((acc, r) => ({ ...acc, [r.kind]: r.n }), {}),
|
|
37002
|
+
lastIndexed: lastIndexed ? new Date(lastIndexed).toISOString() : "unknown",
|
|
37003
|
+
topCalledFunctions: topCalled.map((r) => ({
|
|
37004
|
+
name: r.name,
|
|
37005
|
+
kind: r.kind,
|
|
37006
|
+
file: r.file_path,
|
|
37007
|
+
callers: r.caller_count
|
|
37008
|
+
})),
|
|
37009
|
+
queryHint: "codegraph_query { mode: 'callers', symbol: 'toResult' }",
|
|
37010
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37011
|
+
_summary: `\u4EE3\u7801\u56FE\u8C31\u5C31\u7EEA\u3002${nodeCount} \u4E2A\u8282\u70B9\uFF0C${edgeCount} \u6761\u5173\u7CFB\uFF0C${fileCount} \u4E2A\u6587\u4EF6\u3002${topCalled.length ? `\u88AB\u8C03\u6700\u591A: ${topCalled.slice(0, 3).map((f) => f.name).join("\u3001")}` : ""}`
|
|
37012
|
+
};
|
|
37013
|
+
return toResult(status);
|
|
37014
|
+
} catch (e) {
|
|
37015
|
+
try {
|
|
37016
|
+
db.close();
|
|
37017
|
+
} catch {
|
|
37018
|
+
}
|
|
37019
|
+
throw e;
|
|
37020
|
+
}
|
|
36183
37021
|
} catch (e) {
|
|
36184
37022
|
return toError(e);
|
|
36185
37023
|
}
|
|
@@ -36187,208 +37025,186 @@ function registerCodeGraphTools(server) {
|
|
|
36187
37025
|
);
|
|
36188
37026
|
server.tool(
|
|
36189
37027
|
"codegraph_query",
|
|
36190
|
-
"CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u67E5\u8BE2\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u2014\u2014\u8FFD\u8E2A\
|
|
37028
|
+
"CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u67E5\u8BE2\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u2014\u2014\u8FFD\u8E2A\u8C03\u7528\u94FE\uFF08callers/callees\uFF09\u3001\u641C\u7D22\u7B26\u53F7\u3001\u6309\u6587\u4EF6\u5217\u7B26\u53F7\u3001\u5F71\u54CD\u5206\u6790\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300CtoResult \u88AB\u54EA\u4E9B\u5DE5\u5177\u8C03\u7528\u300D\u300C\u6539 shared.ts \u5F71\u54CD\u54EA\u4E9B\u6A21\u5757\u300D\u300CWebSocket \u5728\u54EA\u4E9B\u6587\u4EF6\u91CC\u300D\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1Acodegraph, \u8C03\u7528\u94FE, callers, callees, \u641C\u7D22, \u5F71\u54CD\u5206\u6790, \u4F9D\u8D56\n## \u53C2\u6570\uFF1A\n## - mode: \u67E5\u8BE2\u6A21\u5F0F\u3002callers / callees / search / file / impact\n## - symbol: \u7B26\u53F7\u540D\u6216\u6587\u4EF6\u540D\n## - limit: \u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB DB\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1Acodegraph_status \u2192 codegraph_query",
|
|
36191
37029
|
{
|
|
36192
|
-
mode: external_exports.enum(["callers", "callees", "
|
|
36193
|
-
symbol: external_exports.string().optional().describe("\u7B26\u53F7\u540D\uFF08\u5982 toResult
|
|
36194
|
-
|
|
36195
|
-
limit: external_exports.number().int().min(1).max(100).optional().describe("\u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA4 15")
|
|
37030
|
+
mode: external_exports.enum(["callers", "callees", "search", "file", "impact"]).describe("callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, search=\u641C\u7B26\u53F7, file=\u6309\u6587\u4EF6, impact=2\u8DF3\u5F71\u54CD\u5206\u6790"),
|
|
37031
|
+
symbol: external_exports.string().optional().describe("\u7B26\u53F7\u540D\uFF08\u5982 toResult\uFF09\u6216\u6587\u4EF6\u540D\uFF08\u5982 agent-utils.ts\uFF09\u6216\u641C\u7D22\u8BCD"),
|
|
37032
|
+
limit: external_exports.number().int().min(1).max(100).optional().describe("\u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15")
|
|
36196
37033
|
},
|
|
36197
|
-
async ({ mode, symbol,
|
|
37034
|
+
async ({ mode, symbol, limit }) => {
|
|
36198
37035
|
try {
|
|
36199
|
-
const
|
|
36200
|
-
if (!
|
|
36201
|
-
return toError("\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u4E0D\u53EF\u7528\u3002\u8BF7\u5148\u8C03 codegraph_status \u68C0\u67E5\u72B6\u6001\u3002");
|
|
36202
|
-
}
|
|
36203
|
-
const { db } = conn;
|
|
37036
|
+
const db = openDB();
|
|
37037
|
+
if (!db) return toError("\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\u3002\u8BF7\u8C03 codegraph_status \u68C0\u67E5\u72B6\u6001\u3002");
|
|
36204
37038
|
const n = limit || 15;
|
|
36205
|
-
|
|
36206
|
-
if (
|
|
36207
|
-
|
|
36208
|
-
|
|
36209
|
-
|
|
36210
|
-
|
|
37039
|
+
try {
|
|
37040
|
+
if (mode === "search") {
|
|
37041
|
+
if (!symbol) return toError("search \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570");
|
|
37042
|
+
const q = symbol;
|
|
37043
|
+
let rows = safeAll(db, `
|
|
37044
|
+
SELECT n.id, n.name, n.kind, n.file_path, n.start_line, n.signature,
|
|
37045
|
+
n.docstring, n.qualified_name
|
|
37046
|
+
FROM nodes_fts f
|
|
37047
|
+
JOIN nodes n ON f.id = n.id
|
|
37048
|
+
WHERE nodes_fts MATCH ?
|
|
37049
|
+
ORDER BY rank
|
|
37050
|
+
LIMIT ?
|
|
37051
|
+
`, n, q, n);
|
|
37052
|
+
if (!rows || rows.length === 0) {
|
|
37053
|
+
rows = safeAll(db, `
|
|
37054
|
+
SELECT id, name, kind, file_path, start_line, signature, docstring, qualified_name
|
|
37055
|
+
FROM nodes
|
|
37056
|
+
WHERE name LIKE ? OR qualified_name LIKE ?
|
|
37057
|
+
ORDER BY name
|
|
37058
|
+
LIMIT ?
|
|
37059
|
+
`, n, `%${q}%`, `%${q}%`, n);
|
|
37060
|
+
}
|
|
37061
|
+
if (!rows || rows.length === 0) {
|
|
37062
|
+
return toResult({
|
|
37063
|
+
mode: "search",
|
|
37064
|
+
query: q,
|
|
37065
|
+
found: false,
|
|
37066
|
+
hint: `\u672A\u627E\u5230 "${q}"\u3002\u8BD5\u8BD5\u51FD\u6570\u540D\uFF08\u5982 registerTools\uFF09\u6216\u6587\u4EF6\u540D\u7247\u6BB5\u3002`,
|
|
37067
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
37068
|
+
});
|
|
37069
|
+
}
|
|
37070
|
+
const items = rows.slice(0, n).map((r) => ({
|
|
37071
|
+
name: r.name,
|
|
37072
|
+
kind: r.kind,
|
|
37073
|
+
file: r.file_path,
|
|
37074
|
+
line: r.start_line,
|
|
37075
|
+
signature: r.signature?.slice(0, 120),
|
|
37076
|
+
docstring: r.docstring?.slice(0, 100)
|
|
37077
|
+
}));
|
|
37078
|
+
return toResult({
|
|
37079
|
+
mode: "search",
|
|
37080
|
+
query: q,
|
|
37081
|
+
total: rows.length,
|
|
37082
|
+
results: items,
|
|
37083
|
+
_summary: `\u641C\u7D22 "${q}" \u627E\u5230 ${rows.length} \u4E2A\u7B26\u53F7\u3002${items.slice(0, 3).map((i) => `${i.name}(${i.kind})`).join(" | ")}`,
|
|
37084
|
+
hint: `\u627E\u5230\u540E: codegraph_query({ mode: 'callers', symbol: '<name>' })`,
|
|
37085
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
37086
|
+
});
|
|
37087
|
+
}
|
|
37088
|
+
if (mode === "callers") {
|
|
37089
|
+
if (!symbol) return toError("callers \u6A21\u5F0F\u9700\u8981 symbol");
|
|
37090
|
+
const nodes = findNodes(db, symbol, 3);
|
|
37091
|
+
if (!nodes.length) {
|
|
37092
|
+
return toResult({ mode: "callers", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
|
|
37093
|
+
}
|
|
37094
|
+
const results = nodes.map((node) => {
|
|
37095
|
+
const callers = getCallers(db, node.id, n);
|
|
37096
|
+
return {
|
|
37097
|
+
target: { id: node.id, name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
|
|
37098
|
+
callers: callers.map((c) => ({
|
|
37099
|
+
name: c.name,
|
|
37100
|
+
kind: c.kind,
|
|
37101
|
+
file: c.file_path,
|
|
37102
|
+
line: c.start_line
|
|
37103
|
+
})),
|
|
37104
|
+
total: callers.length
|
|
37105
|
+
};
|
|
37106
|
+
});
|
|
37107
|
+
const total = results.reduce((s, r) => s + r.total, 0);
|
|
36211
37108
|
return toResult({
|
|
36212
37109
|
mode: "callers",
|
|
36213
37110
|
symbol,
|
|
36214
|
-
|
|
36215
|
-
|
|
37111
|
+
matched: nodes.length,
|
|
37112
|
+
results,
|
|
37113
|
+
_summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171 ${total} \u4E2A\u8C03\u7528\u8005\u3002`,
|
|
36216
37114
|
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36217
37115
|
});
|
|
36218
37116
|
}
|
|
36219
|
-
|
|
36220
|
-
|
|
36221
|
-
const
|
|
36222
|
-
|
|
36223
|
-
|
|
36224
|
-
|
|
36225
|
-
|
|
36226
|
-
|
|
36227
|
-
|
|
36228
|
-
|
|
36229
|
-
|
|
36230
|
-
|
|
36231
|
-
|
|
36232
|
-
|
|
36233
|
-
|
|
36234
|
-
|
|
36235
|
-
|
|
36236
|
-
|
|
36237
|
-
})),
|
|
36238
|
-
totalCallers: callers.length
|
|
37117
|
+
if (mode === "callees") {
|
|
37118
|
+
if (!symbol) return toError("callees \u6A21\u5F0F\u9700\u8981 symbol");
|
|
37119
|
+
const nodes = findNodes(db, symbol, 3);
|
|
37120
|
+
if (!nodes.length) {
|
|
37121
|
+
return toResult({ mode: "callees", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
|
|
37122
|
+
}
|
|
37123
|
+
const results = nodes.map((node) => {
|
|
37124
|
+
const callees = getCallees(db, node.id, n);
|
|
37125
|
+
return {
|
|
37126
|
+
source: { id: node.id, name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
|
|
37127
|
+
callees: callees.map((c) => ({
|
|
37128
|
+
name: c.name,
|
|
37129
|
+
kind: c.kind,
|
|
37130
|
+
file: c.file_path,
|
|
37131
|
+
line: c.start_line
|
|
37132
|
+
})),
|
|
37133
|
+
total: callees.length
|
|
37134
|
+
};
|
|
36239
37135
|
});
|
|
36240
|
-
|
|
36241
|
-
const total = results.reduce((s, r) => s + r.totalCallers, 0);
|
|
36242
|
-
return toResult({
|
|
36243
|
-
mode: "callers",
|
|
36244
|
-
symbol,
|
|
36245
|
-
matched: nodes.length,
|
|
36246
|
-
results,
|
|
36247
|
-
_summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171 ${total} \u4E2A\u8C03\u7528\u8005\u3002${results.slice(0, 3).map((r) => `${r.target.name}: ${r.callers.slice(0, 3).map((c) => c.name).join("\u3001")}`).join(" | ")}`,
|
|
36248
|
-
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36249
|
-
});
|
|
36250
|
-
}
|
|
36251
|
-
if (mode === "callees") {
|
|
36252
|
-
if (!symbol) return toError("callees \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570");
|
|
36253
|
-
const nodes = db.prepare(
|
|
36254
|
-
"SELECT id, name, kind, file_path, start_line FROM nodes WHERE name = ? OR name LIKE ? LIMIT 5"
|
|
36255
|
-
).all(symbol, `%${symbol}%`);
|
|
36256
|
-
if (nodes.length === 0) {
|
|
37136
|
+
const total = results.reduce((s, r) => s + r.total, 0);
|
|
36257
37137
|
return toResult({
|
|
36258
37138
|
mode: "callees",
|
|
36259
37139
|
symbol,
|
|
36260
|
-
|
|
36261
|
-
|
|
37140
|
+
matched: nodes.length,
|
|
37141
|
+
results,
|
|
37142
|
+
_summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171\u8C03\u7528 ${total} \u4E2A\u4E0B\u6E38\u3002`,
|
|
36262
37143
|
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36263
37144
|
});
|
|
36264
37145
|
}
|
|
36265
|
-
|
|
36266
|
-
|
|
36267
|
-
const
|
|
36268
|
-
|
|
36269
|
-
FROM
|
|
36270
|
-
|
|
36271
|
-
|
|
36272
|
-
|
|
36273
|
-
|
|
36274
|
-
|
|
36275
|
-
|
|
36276
|
-
|
|
36277
|
-
|
|
36278
|
-
|
|
36279
|
-
|
|
36280
|
-
|
|
36281
|
-
|
|
36282
|
-
|
|
36283
|
-
|
|
36284
|
-
|
|
37146
|
+
if (mode === "file") {
|
|
37147
|
+
if (!symbol) return toError("file \u6A21\u5F0F\u9700\u8981 symbol\uFF08\u6587\u4EF6\u540D\uFF09");
|
|
37148
|
+
const file = safeGet(
|
|
37149
|
+
db,
|
|
37150
|
+
"SELECT * FROM files WHERE path LIKE ? LIMIT 1",
|
|
37151
|
+
`%${symbol}%`
|
|
37152
|
+
);
|
|
37153
|
+
const nodes = safeAll(db, `
|
|
37154
|
+
SELECT name, kind, start_line, signature, is_exported
|
|
37155
|
+
FROM nodes WHERE file_path LIKE ?
|
|
37156
|
+
ORDER BY start_line LIMIT ?
|
|
37157
|
+
`, n, `%${symbol}%`, n);
|
|
37158
|
+
return toResult({
|
|
37159
|
+
mode: "file",
|
|
37160
|
+
file: symbol,
|
|
37161
|
+
fileInfo: file ? { path: file.path, language: file.language, size: file.size, nodeCount: file.node_count } : null,
|
|
37162
|
+
symbols: nodes.map((r) => ({
|
|
37163
|
+
name: r.name,
|
|
37164
|
+
kind: r.kind,
|
|
37165
|
+
line: r.start_line,
|
|
37166
|
+
signature: r.signature?.slice(0, 120),
|
|
37167
|
+
exported: r.is_exported === 1
|
|
36285
37168
|
})),
|
|
36286
|
-
|
|
37169
|
+
_summary: `\u6587\u4EF6 "${symbol}" \u5305\u542B ${nodes.length} \u4E2A\u7B26\u53F7\u3002`,
|
|
37170
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36287
37171
|
});
|
|
36288
37172
|
}
|
|
36289
|
-
|
|
36290
|
-
|
|
36291
|
-
|
|
36292
|
-
|
|
36293
|
-
|
|
36294
|
-
|
|
36295
|
-
|
|
36296
|
-
|
|
36297
|
-
});
|
|
36298
|
-
}
|
|
36299
|
-
if (mode === "explore") {
|
|
36300
|
-
const q = question || symbol || "";
|
|
36301
|
-
if (!q) return toError("explore \u6A21\u5F0F\u9700\u8981 question \u6216 symbol \u53C2\u6570");
|
|
36302
|
-
let rows = db.prepare(`
|
|
36303
|
-
SELECT n.id, n.name, n.kind, n.file_path, n.start_line, n.signature, n.docstring, n.qualified_name
|
|
36304
|
-
FROM nodes_fts f
|
|
36305
|
-
JOIN nodes n ON f.id = n.id
|
|
36306
|
-
WHERE nodes_fts MATCH ?
|
|
36307
|
-
ORDER BY rank
|
|
36308
|
-
LIMIT ?
|
|
36309
|
-
`).all(q, n);
|
|
36310
|
-
if (rows.length === 0) {
|
|
36311
|
-
rows = db.prepare(`
|
|
36312
|
-
SELECT id, name, kind, file_path, start_line, signature, docstring, qualified_name
|
|
36313
|
-
FROM nodes
|
|
36314
|
-
WHERE name LIKE ? OR qualified_name LIKE ? OR docstring LIKE ?
|
|
36315
|
-
ORDER BY name
|
|
36316
|
-
LIMIT ?
|
|
36317
|
-
`).all(`%${q}%`, `%${q}%`, `%${q}%`, n);
|
|
36318
|
-
}
|
|
36319
|
-
if (rows.length === 0) {
|
|
37173
|
+
if (mode === "impact") {
|
|
37174
|
+
if (!symbol) return toError("impact \u6A21\u5F0F\u9700\u8981 symbol");
|
|
37175
|
+
const nodes = findNodes(db, symbol, 1);
|
|
37176
|
+
if (!nodes.length) {
|
|
37177
|
+
return toResult({ mode: "impact", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
|
|
37178
|
+
}
|
|
37179
|
+
const node = nodes[0];
|
|
37180
|
+
const { direct, indirect } = getImpact(db, node.id, 2, n);
|
|
36320
37181
|
return toResult({
|
|
36321
|
-
mode: "
|
|
36322
|
-
|
|
36323
|
-
|
|
36324
|
-
|
|
37182
|
+
mode: "impact",
|
|
37183
|
+
symbol,
|
|
37184
|
+
node: { id: node.id, name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
|
|
37185
|
+
directlyAffected: direct.map((c) => ({
|
|
37186
|
+
name: c.name,
|
|
37187
|
+
kind: c.kind,
|
|
37188
|
+
file: c.file_path,
|
|
37189
|
+
line: c.start_line
|
|
37190
|
+
})),
|
|
37191
|
+
indirectlyAffected: indirect.map((c) => ({
|
|
37192
|
+
name: c.name,
|
|
37193
|
+
kind: c.kind,
|
|
37194
|
+
file: c.file_path,
|
|
37195
|
+
line: c.start_line
|
|
37196
|
+
})),
|
|
37197
|
+
_summary: `\u4FEE\u6539 "${symbol}" \u76F4\u63A5\u5F71\u54CD ${direct.length} \u4E2A\u8C03\u7528\u8005\uFF0C\u95F4\u63A5\u5F71\u54CD ${indirect.length} \u4E2A\u4E0B\u6E38\u3002`,
|
|
36325
37198
|
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36326
37199
|
});
|
|
36327
37200
|
}
|
|
36328
|
-
|
|
36329
|
-
|
|
36330
|
-
|
|
36331
|
-
|
|
36332
|
-
|
|
36333
|
-
|
|
36334
|
-
"SELECT count(*) as n FROM edges WHERE source = ? AND kind = 'calls'"
|
|
36335
|
-
).get(r.id).n;
|
|
36336
|
-
return {
|
|
36337
|
-
name: r.name,
|
|
36338
|
-
kind: r.kind,
|
|
36339
|
-
file: r.file_path,
|
|
36340
|
-
line: r.start_line,
|
|
36341
|
-
signature: r.signature,
|
|
36342
|
-
docstring: r.docstring?.slice(0, 120),
|
|
36343
|
-
stats: { callers, callees }
|
|
36344
|
-
};
|
|
36345
|
-
});
|
|
36346
|
-
return toResult({
|
|
36347
|
-
mode: "explore",
|
|
36348
|
-
question: q,
|
|
36349
|
-
found: true,
|
|
36350
|
-
total: rows.length,
|
|
36351
|
-
results: enriched,
|
|
36352
|
-
_summary: `\u641C\u7D22 "${q}" \u627E\u5230 ${rows.length} \u4E2A\u7B26\u53F7\u3002${enriched.slice(0, 3).map((r) => `${r.name}(${r.kind}) in ${r.file}`).join(" | ")}`,
|
|
36353
|
-
hint: `\u627E\u5230\u5177\u4F53\u7B26\u53F7\u540E\u7528 codegraph_query({ mode: 'callers', symbol: '<name>' }) \u770B\u5B8C\u6574\u8C03\u7528\u94FE\u3002`,
|
|
36354
|
-
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36355
|
-
});
|
|
36356
|
-
}
|
|
36357
|
-
if (mode === "files") {
|
|
36358
|
-
const file = symbol || "";
|
|
36359
|
-
if (!file) return toError("files \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570\uFF08\u6587\u4EF6\u540D\uFF09");
|
|
36360
|
-
const fileInfo = db.prepare(
|
|
36361
|
-
"SELECT * FROM files WHERE path LIKE ? LIMIT 1"
|
|
36362
|
-
).get(`%${file}%`);
|
|
36363
|
-
const nodes = db.prepare(`
|
|
36364
|
-
SELECT name, kind, start_line, signature, is_exported
|
|
36365
|
-
FROM nodes
|
|
36366
|
-
WHERE file_path LIKE ?
|
|
36367
|
-
ORDER BY start_line
|
|
36368
|
-
LIMIT ?
|
|
36369
|
-
`).all(`%${file}%`, n);
|
|
36370
|
-
return toResult({
|
|
36371
|
-
mode: "files",
|
|
36372
|
-
file,
|
|
36373
|
-
fileInfo: fileInfo ? {
|
|
36374
|
-
path: fileInfo.path,
|
|
36375
|
-
language: fileInfo.language,
|
|
36376
|
-
size: fileInfo.size,
|
|
36377
|
-
nodeCount: fileInfo.node_count,
|
|
36378
|
-
indexedAt: fileInfo.indexed_at ? new Date(fileInfo.indexed_at).toISOString() : void 0
|
|
36379
|
-
} : null,
|
|
36380
|
-
symbols: nodes.map((r) => ({
|
|
36381
|
-
name: r.name,
|
|
36382
|
-
kind: r.kind,
|
|
36383
|
-
line: r.start_line,
|
|
36384
|
-
signature: r.signature,
|
|
36385
|
-
exported: r.is_exported === 1
|
|
36386
|
-
})),
|
|
36387
|
-
_summary: `\u6587\u4EF6 "${file}" \u5305\u542B ${nodes.length} \u4E2A\u7B26\u53F7\u3002${nodes.filter((r) => r.is_exported).length} \u4E2A\u5BFC\u51FA\u3002`,
|
|
36388
|
-
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
36389
|
-
});
|
|
37201
|
+
return toError(`\u672A\u77E5\u6A21\u5F0F: ${mode}`);
|
|
37202
|
+
} finally {
|
|
37203
|
+
try {
|
|
37204
|
+
db.close();
|
|
37205
|
+
} catch {
|
|
37206
|
+
}
|
|
36390
37207
|
}
|
|
36391
|
-
return toError(`\u672A\u77E5\u6A21\u5F0F: ${mode}`);
|
|
36392
37208
|
} catch (e) {
|
|
36393
37209
|
return toError(e);
|
|
36394
37210
|
}
|
|
@@ -36449,7 +37265,7 @@ function registerAllTools(server, auth, readOnly) {
|
|
|
36449
37265
|
registerIndicatorTools(server);
|
|
36450
37266
|
registerSmartMoneyTools(server, auth);
|
|
36451
37267
|
registerXLayerWSTools(server);
|
|
36452
|
-
registerWsTools(server);
|
|
37268
|
+
registerWsTools(server, auth);
|
|
36453
37269
|
registerAgentHubTools(server);
|
|
36454
37270
|
registerCodeGraphTools(server);
|
|
36455
37271
|
return { skipped, skipLog };
|
|
@@ -36544,7 +37360,7 @@ async function startStdio(server, version2, auth, readOnly, skipped, skipLog) {
|
|
|
36544
37360
|
await server.connect(transport);
|
|
36545
37361
|
}
|
|
36546
37362
|
async function main() {
|
|
36547
|
-
const VERSION = "0.2.
|
|
37363
|
+
const VERSION = "0.2.51";
|
|
36548
37364
|
const auth = getAuth();
|
|
36549
37365
|
const mode = resolveTransportMode();
|
|
36550
37366
|
const exec = resolveExecutionMode();
|
|
@@ -36552,7 +37368,7 @@ async function main() {
|
|
|
36552
37368
|
const server = new McpServer({
|
|
36553
37369
|
name: "hvip-mcp",
|
|
36554
37370
|
version: VERSION,
|
|
36555
|
-
description: "hvip MCP Server \u2014
|
|
37371
|
+
description: "hvip MCP Server \u2014 365 \u5DE5\u5177\u8986\u76D6 97.7% OKX REST API\uFF0C\u542B\u4EA4\u6613/\u884C\u60C5/\u8D44\u91D1/\u7B56\u7565/\u9884\u6D4B\u5E02\u573A/\u6280\u672F\u6307\u6807/Smart Money/WebSocket/\u4EE3\u7801\u56FE\u8C31\uFF08\u975E OKX \u5B98\u65B9\u4EA7\u54C1\uFF09\u3002\u4ED3\u5E93: https://github.com/okx-wallet-H/hvip-mcp"
|
|
36556
37372
|
});
|
|
36557
37373
|
const { skipped, skipLog } = registerAllTools(server, auth, readOnly);
|
|
36558
37374
|
if (mode === "http") {
|