hvip-mcp-server 0.2.49 → 0.2.50

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.
Files changed (2) hide show
  1. package/dist/index.js +1065 -396
  2. package/package.json +65 -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 fs2 = require("fs");
105
+ var path2 = 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 (fs2.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 = path2.resolve(process.cwd(), ".env.vault");
222
+ }
223
+ if (fs2.existsSync(possibleVaultPath)) {
224
+ return possibleVaultPath;
225
+ }
226
+ return null;
227
+ }
228
+ function _resolveHome(envPath) {
229
+ return envPath[0] === "~" ? path2.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 = path2.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 path3 of optionPaths) {
271
+ try {
272
+ const parsed = DotenvModule.parse(fs2.readFileSync(path3, { encoding }));
273
+ DotenvModule.populate(parsedAll, parsed, options);
274
+ } catch (e) {
275
+ if (debug) {
276
+ _debug(`Failed to load ${path3} ${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 = path2.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) {
@@ -2984,7 +3385,7 @@ var require_compile = __commonJS({
2984
3385
  const schOrFunc = root.refs[ref];
2985
3386
  if (schOrFunc)
2986
3387
  return schOrFunc;
2987
- let _sch = resolve2.call(this, root, ref);
3388
+ let _sch = resolve.call(this, root, ref);
2988
3389
  if (_sch === void 0) {
2989
3390
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
2990
3391
  const { schemaId } = this.opts;
@@ -3011,7 +3412,7 @@ var require_compile = __commonJS({
3011
3412
  function sameSchemaEnv(s1, s2) {
3012
3413
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3013
3414
  }
3014
- function resolve2(root, ref) {
3415
+ function resolve(root, ref) {
3015
3416
  let sch;
3016
3417
  while (typeof (sch = this.refs[ref]) == "string")
3017
3418
  ref = sch;
@@ -3229,8 +3630,8 @@ var require_utils = __commonJS({
3229
3630
  }
3230
3631
  return ind;
3231
3632
  }
3232
- function removeDotSegments(path3) {
3233
- let input = path3;
3633
+ function removeDotSegments(path2) {
3634
+ let input = path2;
3234
3635
  const output = [];
3235
3636
  let nextSlash = -1;
3236
3637
  let len = 0;
@@ -3482,8 +3883,8 @@ var require_schemes = __commonJS({
3482
3883
  wsComponent.secure = void 0;
3483
3884
  }
3484
3885
  if (wsComponent.resourceName) {
3485
- const [path3, query] = wsComponent.resourceName.split("?");
3486
- wsComponent.path = path3 && path3 !== "/" ? path3 : void 0;
3886
+ const [path2, query] = wsComponent.resourceName.split("?");
3887
+ wsComponent.path = path2 && path2 !== "/" ? path2 : void 0;
3487
3888
  wsComponent.query = query;
3488
3889
  wsComponent.resourceName = void 0;
3489
3890
  }
@@ -3642,7 +4043,7 @@ var require_fast_uri = __commonJS({
3642
4043
  }
3643
4044
  return uri;
3644
4045
  }
3645
- function resolve2(baseURI, relativeURI, options) {
4046
+ function resolve(baseURI, relativeURI, options) {
3646
4047
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3647
4048
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
3648
4049
  schemelessOptions.skipEscape = true;
@@ -3900,7 +4301,7 @@ var require_fast_uri = __commonJS({
3900
4301
  var fastUri = {
3901
4302
  SCHEMES,
3902
4303
  normalize,
3903
- resolve: resolve2,
4304
+ resolve,
3904
4305
  resolveComponent,
3905
4306
  equal,
3906
4307
  serialize,
@@ -6876,12 +7277,12 @@ var require_dist = __commonJS({
6876
7277
  throw new Error(`Unknown format "${name}"`);
6877
7278
  return f;
6878
7279
  };
6879
- function addFormats(ajv, list, fs3, exportName) {
7280
+ function addFormats(ajv, list, fs2, exportName) {
6880
7281
  var _a;
6881
7282
  var _b;
6882
7283
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
6883
7284
  for (const f of list)
6884
- ajv.addFormat(f, fs3[f]);
7285
+ ajv.addFormat(f, fs2[f]);
6885
7286
  }
6886
7287
  module2.exports = exports2 = formatsPlugin;
6887
7288
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -10568,34 +10969,51 @@ var require_websocket_server = __commonJS({
10568
10969
  }
10569
10970
  });
10570
10971
 
10571
- // node_modules/ws/wrapper.mjs
10572
- var wrapper_exports = {};
10573
- __export(wrapper_exports, {
10574
- PerMessageDeflate: () => import_permessage_deflate.default,
10575
- Receiver: () => import_receiver.default,
10576
- Sender: () => import_sender.default,
10577
- WebSocket: () => import_websocket.default,
10578
- WebSocketServer: () => import_websocket_server.default,
10579
- createWebSocketStream: () => import_stream2.default,
10580
- default: () => wrapper_default,
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;
10972
+ // node_modules/@colbymchenry/codegraph/npm-sdk.js
10973
+ var require_npm_sdk = __commonJS({
10974
+ "node_modules/@colbymchenry/codegraph/npm-sdk.js"(exports2, module2) {
10975
+ "use strict";
10976
+ var path2 = require("path");
10977
+ var os2 = require("os");
10978
+ var fs2 = require("fs");
10979
+ var target = process.platform + "-" + process.arch;
10980
+ var pkg = "@colbymchenry/codegraph-" + target;
10981
+ module2.exports = require(resolveLibrary());
10982
+ function resolveLibrary() {
10983
+ try {
10984
+ return require.resolve(pkg + "/lib/dist/index.js");
10985
+ } catch (e) {
10986
+ }
10987
+ var cached2 = cachedLibrary();
10988
+ if (cached2) return cached2;
10989
+ throw new Error(
10990
+ "codegraph: the programmatic API is unavailable because the platform bundle\n(" + pkg + ") is not installed.\nThe compiled library ships inside that per-platform optional dependency.\nFixes:\n - install from the official npm registry so the matching bundle is fetched:\n npm i @colbymchenry/codegraph --registry=https://registry.npmjs.org\n - or run the CLI once (e.g. `npx @colbymchenry/codegraph status`) to\n self-heal the bundle into ~/.codegraph, then require() will find it."
10991
+ );
10992
+ }
10993
+ function cachedLibrary() {
10994
+ try {
10995
+ var version2 = require(path2.join(__dirname, "package.json")).version;
10996
+ var base = process.env.CODEGRAPH_INSTALL_DIR || path2.join(os2.homedir(), ".codegraph");
10997
+ var lib = path2.join(base, "bundles", target + "-" + version2, "lib", "dist", "index.js");
10998
+ if (fs2.existsSync(lib)) return lib;
10999
+ } catch (e) {
11000
+ }
11001
+ return null;
11002
+ }
10596
11003
  }
10597
11004
  });
10598
11005
 
11006
+ // node_modules/dotenv/config.js
11007
+ (function() {
11008
+ require_main().config(
11009
+ Object.assign(
11010
+ {},
11011
+ require_env_options(),
11012
+ require_cli_options()(process.argv)
11013
+ )
11014
+ );
11015
+ })();
11016
+
10599
11017
  // src/index.ts
10600
11018
  var import_node_http = require("node:http");
10601
11019
 
@@ -11077,8 +11495,8 @@ function getErrorMap() {
11077
11495
 
11078
11496
  // node_modules/zod/v3/helpers/parseUtil.js
11079
11497
  var makeIssue = (params) => {
11080
- const { data, path: path3, errorMaps, issueData } = params;
11081
- const fullPath = [...path3, ...issueData.path || []];
11498
+ const { data, path: path2, errorMaps, issueData } = params;
11499
+ const fullPath = [...path2, ...issueData.path || []];
11082
11500
  const fullIssue = {
11083
11501
  ...issueData,
11084
11502
  path: fullPath
@@ -11194,11 +11612,11 @@ var errorUtil;
11194
11612
 
11195
11613
  // node_modules/zod/v3/types.js
11196
11614
  var ParseInputLazyPath = class {
11197
- constructor(parent, value, path3, key) {
11615
+ constructor(parent, value, path2, key) {
11198
11616
  this._cachedPath = [];
11199
11617
  this.parent = parent;
11200
11618
  this.data = value;
11201
- this._path = path3;
11619
+ this._path = path2;
11202
11620
  this._key = key;
11203
11621
  }
11204
11622
  get path() {
@@ -14835,10 +15253,10 @@ function assignProp(target, prop, value) {
14835
15253
  configurable: true
14836
15254
  });
14837
15255
  }
14838
- function getElementAtPath(obj, path3) {
14839
- if (!path3)
15256
+ function getElementAtPath(obj, path2) {
15257
+ if (!path2)
14840
15258
  return obj;
14841
- return path3.reduce((acc, key) => acc?.[key], obj);
15259
+ return path2.reduce((acc, key) => acc?.[key], obj);
14842
15260
  }
14843
15261
  function promiseAllObject(promisesObj) {
14844
15262
  const keys = Object.keys(promisesObj);
@@ -15158,11 +15576,11 @@ function aborted(x, startIndex = 0) {
15158
15576
  }
15159
15577
  return false;
15160
15578
  }
15161
- function prefixIssues(path3, issues) {
15579
+ function prefixIssues(path2, issues) {
15162
15580
  return issues.map((iss) => {
15163
15581
  var _a;
15164
15582
  (_a = iss).path ?? (_a.path = []);
15165
- iss.path.unshift(path3);
15583
+ iss.path.unshift(path2);
15166
15584
  return iss;
15167
15585
  });
15168
15586
  }
@@ -22692,7 +23110,7 @@ var Protocol = class {
22692
23110
  return;
22693
23111
  }
22694
23112
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
22695
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
23113
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
22696
23114
  options?.signal?.throwIfAborted();
22697
23115
  }
22698
23116
  } catch (error2) {
@@ -22709,7 +23127,7 @@ var Protocol = class {
22709
23127
  */
22710
23128
  request(request3, resultSchema, options) {
22711
23129
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
22712
- return new Promise((resolve2, reject) => {
23130
+ return new Promise((resolve, reject) => {
22713
23131
  const earlyReject = (error2) => {
22714
23132
  reject(error2);
22715
23133
  };
@@ -22787,7 +23205,7 @@ var Protocol = class {
22787
23205
  if (!parseResult.success) {
22788
23206
  reject(parseResult.error);
22789
23207
  } else {
22790
- resolve2(parseResult.data);
23208
+ resolve(parseResult.data);
22791
23209
  }
22792
23210
  } catch (error2) {
22793
23211
  reject(error2);
@@ -23048,12 +23466,12 @@ var Protocol = class {
23048
23466
  }
23049
23467
  } catch {
23050
23468
  }
23051
- return new Promise((resolve2, reject) => {
23469
+ return new Promise((resolve, reject) => {
23052
23470
  if (signal.aborted) {
23053
23471
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
23054
23472
  return;
23055
23473
  }
23056
- const timeoutId = setTimeout(resolve2, interval);
23474
+ const timeoutId = setTimeout(resolve, interval);
23057
23475
  signal.addEventListener("abort", () => {
23058
23476
  clearTimeout(timeoutId);
23059
23477
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -24153,7 +24571,7 @@ var McpServer = class {
24153
24571
  let task = createTaskResult.task;
24154
24572
  const pollInterval = task.pollInterval ?? 5e3;
24155
24573
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
24156
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
24574
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
24157
24575
  const updatedTask = await extra.taskStore.getTask(taskId);
24158
24576
  if (!updatedTask) {
24159
24577
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -24802,12 +25220,12 @@ var StdioServerTransport = class {
24802
25220
  this.onclose?.();
24803
25221
  }
24804
25222
  send(message) {
24805
- return new Promise((resolve2) => {
25223
+ return new Promise((resolve) => {
24806
25224
  const json = serializeMessage(message);
24807
25225
  if (this._stdout.write(json)) {
24808
- resolve2();
25226
+ resolve();
24809
25227
  } else {
24810
- this._stdout.once("drain", resolve2);
25228
+ this._stdout.once("drain", resolve);
24811
25229
  }
24812
25230
  });
24813
25231
  }
@@ -25306,7 +25724,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
25306
25724
  });
25307
25725
  if (!chunk) {
25308
25726
  if (i === 1) {
25309
- await new Promise((resolve2) => setTimeout(resolve2));
25727
+ await new Promise((resolve) => setTimeout(resolve));
25310
25728
  maxReadCount = 3;
25311
25729
  continue;
25312
25730
  }
@@ -25806,9 +26224,9 @@ data:
25806
26224
  const initRequest = messages.find((m) => isInitializeRequest(m));
25807
26225
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
25808
26226
  if (this._enableJsonResponse) {
25809
- return new Promise((resolve2) => {
26227
+ return new Promise((resolve) => {
25810
26228
  this._streamMapping.set(streamId, {
25811
- resolveJson: resolve2,
26229
+ resolveJson: resolve,
25812
26230
  cleanup: () => {
25813
26231
  this._streamMapping.delete(streamId);
25814
26232
  }
@@ -26141,8 +26559,8 @@ var StreamableHTTPServerTransport = class {
26141
26559
  // src/adapters/okx.ts
26142
26560
  var import_node_crypto = __toESM(require("node:crypto"));
26143
26561
  var BASE = "https://www.okx.com";
26144
- function sign(ts, method, path3, body, secret) {
26145
- const msg = ts + method + path3 + body;
26562
+ function sign(ts, method, path2, body, secret) {
26563
+ const msg = ts + method + path2 + body;
26146
26564
  return import_node_crypto.default.createHmac("sha256", secret).update(msg).digest("base64");
26147
26565
  }
26148
26566
  function timestamp() {
@@ -26155,9 +26573,9 @@ function buildQuery(params) {
26155
26573
  }
26156
26574
  return p.size ? "?" + p.toString() : "";
26157
26575
  }
26158
- async function request(method, path3, options = {}) {
26576
+ async function request(method, path2, options = {}) {
26159
26577
  const query = options.params ? buildQuery(options.params) : "";
26160
- const fullPath = path3 + query;
26578
+ const fullPath = path2 + query;
26161
26579
  const bodyStr = options.body ? JSON.stringify(options.body) : "";
26162
26580
  const headers = {
26163
26581
  "Content-Type": "application/json",
@@ -26546,12 +26964,12 @@ var privateApi = {
26546
26964
 
26547
26965
  // src/adapters/hrails.ts
26548
26966
  var DEFAULT_BASE = "https://api-staging.hwallet.vip";
26549
- async function request2(path3, params = {}, apiKey, base) {
26967
+ async function request2(path2, params = {}, apiKey, base) {
26550
26968
  const filtered = Object.entries(params).filter(([, v]) => v !== void 0 && v !== "");
26551
26969
  const p = new URLSearchParams();
26552
26970
  for (const [k, v] of filtered) p.append(k, String(v));
26553
26971
  const query = p.size ? "?" + p.toString() : "";
26554
- const res = await fetch(base + path3 + query, {
26972
+ const res = await fetch(base + path2 + query, {
26555
26973
  headers: {
26556
26974
  "Accept": "application/json",
26557
26975
  "Authorization": `Bearer ${apiKey}`
@@ -26563,7 +26981,7 @@ async function request2(path3, params = {}, apiKey, base) {
26563
26981
  return json.data ?? json;
26564
26982
  }
26565
26983
  function createHRailsClient(apiKey, baseUrl = DEFAULT_BASE) {
26566
- const get = (path3, params) => request2(path3, params, apiKey, baseUrl);
26984
+ const get = (path2, params) => request2(path2, params, apiKey, baseUrl);
26567
26985
  return {
26568
26986
  health: () => fetch(baseUrl + "/health").then((r) => r.json()),
26569
26987
  listEvents: (params) => {
@@ -26665,24 +27083,181 @@ function toResult(data) {
26665
27083
  }
26666
27084
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
26667
27085
  }
27086
+ var OKX_ERROR_MESSAGES = {
27087
+ // 公共 / 系统
27088
+ 5e4: "\u7CFB\u7EDF\u5185\u90E8\u9519\u8BEF",
27089
+ 50001: "\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
27090
+ 50002: "\u7CFB\u7EDF\u5347\u7EA7\u7EF4\u62A4\u4E2D",
27091
+ 50004: "\u8BF7\u6C42\u8D85\u65F6",
27092
+ 50005: "\u63A5\u53E3\u5DF2\u88AB\u51BB\u7ED3\uFF0C\u8BF7\u8054\u7CFB\u5BA2\u670D",
27093
+ 50006: "OK-ACCESS-KEY \u65E0\u6548",
27094
+ 50007: "OK-ACCESS-SIGN \u7B7E\u540D\u9519\u8BEF",
27095
+ 50008: "OK-ACCESS-TIMESTAMP \u65F6\u95F4\u6233\u65E0\u6548",
27096
+ 50009: "OK-ACCESS-PASSPHRASE \u5BC6\u7801\u77ED\u8BED\u9519\u8BEF",
27097
+ 50010: "\u5F53\u524D IP \u4E0D\u5728 API Key \u767D\u540D\u5355\u4E2D",
27098
+ 50011: "\u8BF7\u6C42\u9891\u7387\u8FC7\u5FEB\uFF0C\u5DF2\u89E6\u53D1\u9650\u6D41\u3002\u8BF7\u964D\u4F4E\u8BF7\u6C42\u901F\u7387",
27099
+ 50012: "\u7CFB\u7EDF\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
27100
+ 50013: "\u7CFB\u7EDF\u9519\u8BEF",
27101
+ 50014: "\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5FC5\u586B\u5B57\u6BB5\u548C\u683C\u5F0F",
27102
+ 50015: "\u4ED3\u4F4D\u5DF2\u88AB\u51BB\u7ED3",
27103
+ 50016: "\u8D26\u6237\u5DF2\u88AB\u51BB\u7ED3",
27104
+ 50017: "\u8D26\u6237\u5DF2\u88AB\u6682\u505C",
27105
+ 50018: "\u8D26\u6237\u7B49\u7EA7\u4E0D\u8DB3",
27106
+ 50019: "\u5408\u7EA6\u5DF2\u5230\u671F",
27107
+ 50020: "\u4F59\u989D\u4E0D\u8DB3",
27108
+ 50021: "\u4FDD\u8BC1\u91D1\u4E0D\u8DB3",
27109
+ 50022: "\u4E0B\u5355\u6570\u91CF\u5C0F\u4E8E\u6700\u5C0F\u9650\u5236",
27110
+ 50023: "\u4E0B\u5355\u6570\u91CF\u8D85\u8FC7\u6700\u5927\u9650\u5236",
27111
+ 50024: "\u6301\u4ED3\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650",
27112
+ 50025: "\u6302\u5355\u6570\u91CF\u5DF2\u8FBE\u4E0A\u9650",
27113
+ 50026: "\u4E0B\u5355\u4EF7\u683C\u8D85\u51FA\u9650\u4EF7\u8303\u56F4",
27114
+ 50027: "\u4EF7\u683C\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
27115
+ 50028: "\u6570\u91CF\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
27116
+ 50029: "\u8BE5\u5408\u7EA6\u6682\u4E0D\u53EF\u7528",
27117
+ 50030: "API Key \u65E0\u6B64\u64CD\u4F5C\u6743\u9650",
27118
+ 50031: "API Key \u5DF2\u8FC7\u671F",
27119
+ 50032: "API Key \u672A\u627E\u5230",
27120
+ 50033: "API Key \u672A\u6FC0\u6D3B",
27121
+ 50035: "\u89E6\u53D1\u98CE\u63A7\u89C4\u5219\uFF0C\u4EA4\u6613\u88AB\u62D2\u7EDD",
27122
+ 50036: "\u65E0\u4EA4\u6613\u6743\u9650",
27123
+ 50044: "\u8BA2\u5355\u4E0D\u5B58\u5728",
27124
+ 50045: "\u8BE5\u8BA2\u5355\u4E0D\u53EF\u64A4\u9500",
27125
+ 50046: "\u8BA2\u5355\u5DF2\u5168\u90E8\u6210\u4EA4",
27126
+ 50047: "\u8BA2\u5355\u5DF2\u88AB\u64A4\u9500",
27127
+ 50050: "\u6301\u4ED3\u4E0D\u5B58\u5728",
27128
+ 50051: "\u4ED3\u4F4D\u5DF2\u5E73\u4ED3",
27129
+ 50053: "\u4ED3\u4F4D\u4FDD\u8BC1\u91D1\u4E0D\u8DB3",
27130
+ 50056: "\u4E0B\u5355\u8FC7\u4E8E\u9891\u7E41",
27131
+ 50058: "\u8BE5\u5E01\u79CD\u6682\u4E0D\u652F\u6301",
27132
+ 50059: "\u53C2\u6570\u89E3\u6790\u5931\u8D25",
27133
+ 50060: "\u8D26\u6237\u6A21\u5F0F\u4E0D\u652F\u6301\u6B64\u64CD\u4F5C",
27134
+ 50061: "\u5B50\u8D26\u6237\u8BF7\u6C42\u9891\u7387\u8D85\u9650",
27135
+ 50064: "\u8BE5\u5408\u7EA6\u4E0D\u652F\u6301\u6B64\u64CD\u4F5C",
27136
+ 50068: "\u7CFB\u7EDF\u5347\u7EA7\u4E2D\uFF0C\u6682\u4E0D\u53EF\u7528",
27137
+ 50070: "\u6301\u4ED3\u6A21\u5F0F\u4E0D\u5339\u914D",
27138
+ 50071: "\u4FDD\u8BC1\u91D1\u6A21\u5F0F\u4E0D\u5339\u914D",
27139
+ 50072: "\u6760\u6746\u500D\u6570\u8D85\u51FA\u5141\u8BB8\u8303\u56F4",
27140
+ 50074: "\u89E6\u53D1\u4EF7\u683C\u65E0\u6548",
27141
+ 50080: "\u4E0B\u5355\u4EF7\u683C\u504F\u79BB\u5E02\u573A\u4EF7\u8FC7\u5927",
27142
+ 50082: "\u8D26\u6237\u6743\u76CA\u4E0D\u8DB3",
27143
+ // API Key 相关
27144
+ 50100: "API Key \u5DF2\u88AB\u51BB\u7ED3",
27145
+ 50101: "API Key \u5DF2\u8FC7\u671F",
27146
+ 50102: "\u8BF7\u6C42\u65F6\u95F4\u6233\u4E0E\u670D\u52A1\u5668\u65F6\u95F4\u504F\u5DEE\u8D85\u8FC7 30 \u79D2",
27147
+ 50103: "\u8BF7\u6C42\u5934 OK-ACCESS-KEY \u4E0D\u80FD\u4E3A\u7A7A",
27148
+ 50104: "\u8BF7\u6C42\u5934 OK-ACCESS-SIGN \u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A",
27149
+ 50105: "\u8BF7\u6C42\u5934 OK-ACCESS-TIMESTAMP \u4E0D\u80FD\u4E3A\u7A7A",
27150
+ 50106: "\u8BF7\u6C42\u5934 OK-ACCESS-PASSPHRASE \u4E0D\u80FD\u4E3A\u7A7A",
27151
+ 50107: "API Key \u5BF9\u5E94\u7684\u8D26\u6237\u4E0D\u5B58\u5728",
27152
+ 50108: "\u8D26\u6237\u4F59\u989D\u4E0D\u8DB3",
27153
+ 50109: "\u5212\u8F6C\u91D1\u989D\u8D85\u8FC7\u9650\u989D",
27154
+ 50110: "\u5212\u8F6C\u5E01\u79CD\u4E0D\u652F\u6301",
27155
+ 50111: "\u5212\u8F6C\u5931\u8D25",
27156
+ 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",
27157
+ 50121: "API Key \u5DF2\u8FC7\u671F",
27158
+ 50122: "API Key \u672A\u627E\u5230",
27159
+ 50123: "API Key \u672A\u6FC0\u6D3B",
27160
+ 50124: "API Key \u5DF2\u88AB\u5220\u9664",
27161
+ 50125: "API Key \u5DF2\u88AB\u51BB\u7ED3",
27162
+ 50126: "API Key \u5DF2\u88AB\u7981\u7528",
27163
+ // 交易
27164
+ 51e3: "\u53C2\u6570\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u5FC5\u586B\u53C2\u6570",
27165
+ 51001: "\u8BA2\u5355\u7C7B\u578B\u4E0D\u652F\u6301",
27166
+ 51002: "\u8BA2\u5355\u65B9\u5411\u4E0D\u652F\u6301",
27167
+ 51003: "\u8BA2\u5355\u6570\u91CF\u4E0D\u80FD\u4E3A 0 \u6216\u8D1F\u6570",
27168
+ 51004: "\u8BA2\u5355\u4EF7\u683C\u4E0D\u80FD\u4E3A 0 \u6216\u8D1F\u6570",
27169
+ 51005: "\u4FDD\u8BC1\u91D1\u6A21\u5F0F\u4E0D\u652F\u6301",
27170
+ 51006: "\u8BA2\u5355\u4EF7\u683C\u8D85\u51FA\u9650\u4EF7\u8303\u56F4",
27171
+ 51007: "\u8BA2\u5355\u6570\u91CF\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
27172
+ 51008: "\u8BA2\u5355\u4EF7\u683C\u7CBE\u5EA6\u4E0D\u7B26\u5408\u8981\u6C42",
27173
+ 51009: "\u8BA2\u5355\u6570\u91CF\u8D85\u51FA\u6700\u5927\u9650\u5236",
27174
+ 51010: "\u8BA2\u5355\u6570\u91CF\u4F4E\u4E8E\u6700\u5C0F\u9650\u5236",
27175
+ 51011: "\u8BE5\u4EA7\u54C1\u4E0D\u652F\u6301\u6B64\u8BA2\u5355\u7C7B\u578B",
27176
+ 51012: "\u8BE5\u4EA7\u54C1\u4E0D\u652F\u6301\u6B64\u4FDD\u8BC1\u91D1\u6A21\u5F0F",
27177
+ 51013: "\u8BE5\u4EA7\u54C1\u4E0D\u652F\u6301\u6B64\u6301\u4ED3\u6A21\u5F0F",
27178
+ 51014: "\u5F53\u524D\u6301\u4ED3\u6A21\u5F0F\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C",
27179
+ 51015: "\u5F53\u524D\u8D26\u6237\u6A21\u5F0F\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C",
27180
+ 51020: "\u6279\u91CF\u4E0B\u5355\u6570\u91CF\u8D85\u8FC7\u4E0A\u9650",
27181
+ 51021: "\u6279\u91CF\u64CD\u4F5C\u4E2D\u5305\u542B\u91CD\u590D\u8BA2\u5355",
27182
+ 51026: "\u8BA2\u5355\u4EF7\u683C\u8D85\u51FA\u6ED1\u70B9\u4FDD\u62A4\u8303\u56F4",
27183
+ 51027: "\u8BA2\u5355\u5DF2\u8FC7\u671F",
27184
+ 51100: "\u8BE5\u4EA7\u54C1\u4E0D\u5728\u53EF\u4EA4\u6613\u5217\u8868",
27185
+ 51102: "\u6301\u4ED3\u6A21\u5F0F\u4E0D\u5339\u914D\uFF0C\u65E0\u6CD5\u5E73\u4ED3",
27186
+ 51103: "\u4FDD\u8BC1\u91D1\u6A21\u5F0F\u4E0D\u5339\u914D\uFF0C\u65E0\u6CD5\u5E73\u4ED3",
27187
+ 51104: "\u6760\u6746\u500D\u6570\u4E0D\u5339\u914D",
27188
+ 51107: "\u5E02\u4EF7\u5355\u5F53\u524D\u4E0D\u53EF\u7528",
27189
+ 51108: "\u6B62\u635F\u5355\u5F53\u524D\u4E0D\u53EF\u7528",
27190
+ // 资金
27191
+ 52e3: "\u5212\u8F6C\u5931\u8D25",
27192
+ 52001: "\u63D0\u73B0\u91D1\u989D\u8D85\u8FC7\u9650\u989D",
27193
+ 52002: "\u63D0\u73B0\u5730\u5740\u65E0\u6548",
27194
+ 52003: "\u63D0\u73B0\u94FE\u4E0D\u652F\u6301",
27195
+ 52004: "\u63D0\u73B0\u7F51\u7EDC\u8D39\u4E0D\u8DB3",
27196
+ 52005: "\u63D0\u73B0\u5DF2\u51BB\u7ED3",
27197
+ 52006: "\u5145\u503C\u5730\u5740\u751F\u6210\u5931\u8D25",
27198
+ 52007: "\u8BE5\u5E01\u79CD\u4E0D\u652F\u6301\u5145\u503C",
27199
+ 52008: "\u8BE5\u5E01\u79CD\u4E0D\u652F\u6301\u63D0\u73B0",
27200
+ // 跟单交易
27201
+ 52100: "\u4EA4\u6613\u5458\u4E0D\u5B58\u5728",
27202
+ 52101: "\u4EA4\u6613\u5458\u4E0D\u5BF9\u5916\u516C\u5F00",
27203
+ 52102: "\u8DDF\u5355\u91D1\u989D\u8D85\u51FA\u9650\u5236",
27204
+ 52103: "\u8DDF\u5355\u4EBA\u6570\u5DF2\u8FBE\u4E0A\u9650",
27205
+ 52104: "\u5F53\u524D\u4E0D\u652F\u6301\u8DDF\u5355\u8BE5\u4EA4\u6613\u5458",
27206
+ 52105: "\u8BE5\u4EA4\u6613\u5458\u5DF2\u505C\u6B62\u5E26\u5355",
27207
+ // 策略 / 网格
27208
+ 53e3: "\u7B56\u7565\u59D4\u6258\u521B\u5EFA\u5931\u8D25",
27209
+ 53001: "\u7B56\u7565\u59D4\u6258\u4FEE\u6539\u5931\u8D25",
27210
+ 53002: "\u7B56\u7565\u59D4\u6258\u64A4\u9500\u5931\u8D25",
27211
+ 53003: "\u7B56\u7565\u59D4\u6258\u4E0D\u5B58\u5728",
27212
+ 53004: "\u7B56\u7565\u59D4\u6258\u5DF2\u89E6\u53D1",
27213
+ 53005: "\u7F51\u683C\u7B56\u7565\u521B\u5EFA\u5931\u8D25",
27214
+ 53006: "\u7F51\u683C\u7B56\u7565\u4E0D\u5B58\u5728",
27215
+ 53007: "\u7F51\u683C\u7B56\u7565\u5DF2\u505C\u6B62",
27216
+ 53008: "\u7F51\u683C\u53C2\u6570\u65E0\u6548",
27217
+ // WebSocket
27218
+ 60001: "\u8BA2\u9605\u9891\u9053\u4E0D\u5B58\u5728\u6216\u53C2\u6570\u9519\u8BEF",
27219
+ 60002: "WebSocket \u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 API Key",
27220
+ 60003: "WebSocket \u8BA2\u9605\u53C2\u6570\u65E0\u6548",
27221
+ 60004: "WebSocket \u8BF7\u6C42\u9891\u7387\u8FC7\u9AD8",
27222
+ 60005: "WebSocket \u8FDE\u63A5\u6570\u5DF2\u8FBE\u4E0A\u9650",
27223
+ 60006: "WebSocket \u8FDE\u63A5\u88AB\u670D\u52A1\u7AEF\u5173\u95ED",
27224
+ 60007: "WebSocket \u8BE5\u9891\u9053\u9700\u8981\u767B\u5F55",
27225
+ 60008: "WebSocket \u8BE5\u9891\u9053\u4E0D\u9700\u8981\u767B\u5F55",
27226
+ 60009: "WebSocket \u767B\u5F55\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55",
27227
+ 64008: "\u670D\u52A1\u5347\u7EA7\u4E2D\uFF0C\u8FDE\u63A5\u5373\u5C06\u5173\u95ED\uFF0C\u8BF7\u91CD\u8FDE"
27228
+ };
27229
+ function translateError(code, rawMsg) {
27230
+ const translated = OKX_ERROR_MESSAGES[code];
27231
+ if (translated) return translated;
27232
+ if (code >= 5e4 && code < 50100) return `\u7CFB\u7EDF/\u8BA4\u8BC1\u9519\u8BEF (${code}): ${rawMsg}`;
27233
+ if (code >= 50100 && code < 50200) return `API Key \u9519\u8BEF (${code}): ${rawMsg}`;
27234
+ if (code >= 51e3 && code < 51200) return `\u4EA4\u6613\u53C2\u6570\u9519\u8BEF (${code}): ${rawMsg}`;
27235
+ if (code >= 52e3 && code < 52200) return `\u8D44\u91D1/\u8DDF\u5355\u9519\u8BEF (${code}): ${rawMsg}`;
27236
+ if (code >= 53e3 && code < 54e3) return `\u7B56\u7565\u59D4\u6258\u9519\u8BEF (${code}): ${rawMsg}`;
27237
+ if (code >= 6e4 && code < 65e3) return `WebSocket \u9519\u8BEF (${code}): ${rawMsg}`;
27238
+ return rawMsg;
27239
+ }
26668
27240
  function classifyError(msg) {
26669
27241
  const okxMatch = msg.match(/OKX (\d+):/);
26670
27242
  if (okxMatch && okxMatch[1]) {
26671
27243
  const code = parseInt(okxMatch[1]);
26672
- if (code >= 5e4 && code < 50100) return { errorCode: `OKX_${code}`, errorCategory: "AUTH" };
26673
- if (code >= 51e3) return { errorCode: `OKX_${code}`, errorCategory: "BUSINESS" };
26674
- if (code >= 50004 && code <= 50014) return { errorCode: `OKX_${code}`, errorCategory: "VALIDATION" };
26675
- return { errorCode: `OKX_${code}`, errorCategory: "BUSINESS" };
27244
+ const rawMsg = msg.replace(/^OKX \d+: /, "");
27245
+ const translated = translateError(code, rawMsg);
27246
+ if (code >= 5e4 && code < 50100) return { errorCode: `OKX_${code}`, errorCategory: "AUTH", errorMessage: translated };
27247
+ if (code === 50100 || code === 50101 || code === 50120) return { errorCode: `OKX_${code}`, errorCategory: "AUTH", errorMessage: translated };
27248
+ if (code >= 50004 && code <= 50014) return { errorCode: `OKX_${code}`, errorCategory: "VALIDATION", errorMessage: translated };
27249
+ if (code >= 51e3 && code < 51200) return { errorCode: `OKX_${code}`, errorCategory: "VALIDATION", errorMessage: translated };
27250
+ return { errorCode: `OKX_${code}`, errorCategory: "BUSINESS", errorMessage: translated };
26676
27251
  }
26677
27252
  if (msg.startsWith("HTTP ")) {
26678
27253
  const httpMatch = msg.match(/HTTP (\d+)/);
26679
27254
  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" };
27255
+ 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" };
27256
+ 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" };
27257
+ return { errorCode: "NETWORK_ERROR", errorCategory: "NETWORK", errorMessage: `\u7F51\u7EDC\u9519\u8BEF HTTP ${status}` };
26683
27258
  }
26684
- if (msg.includes("API Key")) return { errorCode: "AUTH_REQUIRED", errorCategory: "AUTH" };
26685
- return { errorCode: "UNKNOWN_ERROR", errorCategory: "BUSINESS" };
27259
+ if (msg.includes("API Key")) return { errorCode: "AUTH_REQUIRED", errorCategory: "AUTH", errorMessage: msg };
27260
+ return { errorCode: "UNKNOWN_ERROR", errorCategory: "BUSINESS", errorMessage: msg };
26686
27261
  }
26687
27262
  function classifyRisk(toolName) {
26688
27263
  const admin = ["okx_set_account_mode", "okx_set_position_mode", "okx_set_settle_currency"];
@@ -26737,12 +27312,13 @@ function classifyRisk(toolName) {
26737
27312
  }
26738
27313
  function toError(e) {
26739
27314
  const msg = e instanceof Error ? e.message : String(e);
26740
- const { errorCode, errorCategory } = classifyError(msg);
27315
+ const { errorCode, errorCategory, errorMessage } = classifyError(msg);
26741
27316
  return {
26742
- content: [{ type: "text", text: msg }],
27317
+ content: [{ type: "text", text: errorMessage }],
26743
27318
  isError: true,
26744
27319
  errorCode,
26745
- errorCategory
27320
+ errorCategory,
27321
+ errorMessage
26746
27322
  };
26747
27323
  }
26748
27324
 
@@ -33757,12 +34333,13 @@ function registerAgentUtils(server, auth) {
33757
34333
  },
33758
34334
  {
33759
34335
  domain: "WebSocket \u5B9E\u65F6",
33760
- what: "\u5B9E\u65F6\u884C\u60C5\u63A8\u9001\u3001\u6210\u4EA4\u63A8\u9001",
33761
- when: ["\u5B9E\u65F6", "\u8BA2\u9605", "\u63A8\u9001", "websocket", "ws", "\u76D1\u542C"],
34336
+ 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",
34337
+ when: ["\u5B9E\u65F6", "\u8BA2\u9605", "\u63A8\u9001", "websocket", "ws", "\u76D1\u542C", "\u7206\u4ED3", "\u5B9E\u65F6\u8BA2\u5355"],
33762
34338
  go_to: "okx_ws_subscribe",
33763
34339
  also: [
33764
- "okx_ws_events \u2014 \u83B7\u53D6\u63A8\u9001\u4E8B\u4EF6",
33765
- "okx_ws_status \u2014 \u8BA2\u9605\u72B6\u6001",
34340
+ "okx_ws_subscribe_private \u2014 \u79C1\u6709\u9891\u9053\uFF08\u8D26\u6237/\u6301\u4ED3/\u8BA2\u5355\uFF0C\u9700Key\uFF09",
34341
+ "okx_ws_events \u2014 \u62C9\u53D6\u7F13\u51B2\u4E8B\u4EF6",
34342
+ "okx_ws_status \u2014 \u67E5\u770B\u8BA2\u9605\u72B6\u6001",
33766
34343
  "okx_ws_close \u2014 \u5173\u95ED\u8BA2\u9605"
33767
34344
  ],
33768
34345
  risk: "READ"
@@ -33854,7 +34431,8 @@ function registerAgentUtils(server, auth) {
33854
34431
  "agent_get_preference": "key? (\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8)",
33855
34432
  "agent_set_preference": "key, value",
33856
34433
  "okx_event_instruments": "eventType? (\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8)",
33857
- "okx_ws_subscribe": "channels (JSON\u6570\u7EC4)",
34434
+ "okx_ws_subscribe": "instId (\u4EA7\u54C1ID), channel (33\u4E2A\u516C\u5F00\u9891\u9053)",
34435
+ "okx_ws_subscribe_private": "instId? (\u4EA7\u54C1ID), channel (22\u4E2A\u79C1\u6709\u9891\u9053\uFF0C\u9700Key)",
33858
34436
  "okx_get_grid_ai_param": "instType, algoOrdType"
33859
34437
  };
33860
34438
  const enrichedDomains = CATALOG.domains.map((d) => ({
@@ -34055,12 +34633,13 @@ function registerAgentUtils(server, auth) {
34055
34633
  ]
34056
34634
  },
34057
34635
  "WebSocket \u5B9E\u65F6": {
34058
- workflow: "okx_ws_subscribe \u8BA2\u9605\u9891\u9053 \u2192 okx_ws_events \u62C9\u53D6\u4E8B\u4EF6",
34636
+ 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
34637
  tools: [
34060
- { name: "okx_ws_subscribe", auth: "\u516C\u5F00", params: "channels[]", what: "\u8BA2\u9605\u5B9E\u65F6\u9891\u9053\uFF08tickers/trades/books/candles/fundingRate \u7B49\uFF09" },
34061
- { name: "okx_ws_events", auth: "\u516C\u5F00", params: "channel?", what: "\u6536\u53D6\u8BA2\u9605\u7684\u5B9E\u65F6\u63A8\u9001\u4E8B\u4EF6" },
34062
- { name: "okx_ws_status", auth: "\u516C\u5F00", params: "\u65E0", what: "\u5F53\u524D\u8BA2\u9605\u72B6\u6001" },
34063
- { name: "okx_ws_close", auth: "\u516C\u5F00", params: "channel?", what: "\u53D6\u6D88\u8BA2\u9605" }
34638
+ { 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" },
34639
+ { 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" },
34640
+ { name: "okx_ws_events", auth: "\u516C\u5F00", params: "subscriptionId?, limit?, filter?", what: "\u62C9\u53D6\u7F13\u51B2\u7684\u5B9E\u65F6\u4E8B\u4EF6" },
34641
+ { name: "okx_ws_status", auth: "\u516C\u5F00", params: "\u65E0", what: "\u5F53\u524D\u6240\u6709\u8BA2\u9605+\u7F13\u51B2\u79EF\u538B" },
34642
+ { name: "okx_ws_close", auth: "\u516C\u5F00", params: "subscriptionId?", what: "\u5173\u95ED\u8BA2\u9605" }
34064
34643
  ]
34065
34644
  },
34066
34645
  "\u6A21\u62DF\u4F30\u7B97": {
@@ -35009,8 +35588,18 @@ function registerSmartMoneyTools(server, auth) {
35009
35588
  );
35010
35589
  }
35011
35590
 
35591
+ // node_modules/ws/wrapper.mjs
35592
+ var import_stream2 = __toESM(require_stream(), 1);
35593
+ var import_extension = __toESM(require_extension(), 1);
35594
+ var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
35595
+ var import_receiver = __toESM(require_receiver(), 1);
35596
+ var import_sender = __toESM(require_sender(), 1);
35597
+ var import_subprotocol = __toESM(require_subprotocol(), 1);
35598
+ var import_websocket = __toESM(require_websocket(), 1);
35599
+ var import_websocket_server = __toESM(require_websocket_server(), 1);
35600
+ var wrapper_default = import_websocket.default;
35601
+
35012
35602
  // src/adapters/xlayer-ws.ts
35013
- init_wrapper();
35014
35603
  var WS_URL = process.env.XLAYER_WS_URL || "wss://xlayerws.okx.com";
35015
35604
  var MAX_EVENTS = 500;
35016
35605
  var XLayerWSManager = class {
@@ -35024,7 +35613,7 @@ var XLayerWSManager = class {
35024
35613
  async connect() {
35025
35614
  if (this.ws?.readyState === wrapper_default.OPEN) return;
35026
35615
  if (this.connectPromise) return this.connectPromise;
35027
- this.connectPromise = new Promise((resolve2, reject) => {
35616
+ this.connectPromise = new Promise((resolve, reject) => {
35028
35617
  const ws = new wrapper_default(WS_URL);
35029
35618
  ws.on("open", () => {
35030
35619
  this.ws = ws;
@@ -35032,7 +35621,7 @@ var XLayerWSManager = class {
35032
35621
  this.pingTimer = setInterval(() => {
35033
35622
  if (ws.readyState === wrapper_default.OPEN) ws.ping();
35034
35623
  }, 3e4);
35035
- resolve2();
35624
+ resolve();
35036
35625
  });
35037
35626
  ws.on("message", (raw) => {
35038
35627
  try {
@@ -35085,12 +35674,12 @@ var XLayerWSManager = class {
35085
35674
  await this.connect();
35086
35675
  const ws = this.ws;
35087
35676
  const id = ++this.idCounter;
35088
- return new Promise((resolve2, reject) => {
35677
+ return new Promise((resolve, reject) => {
35089
35678
  const timer = setTimeout(() => {
35090
35679
  this.pending.delete(id);
35091
35680
  reject(new Error(`RPC \u8C03\u7528\u8D85\u65F6: ${method}`));
35092
35681
  }, 3e4);
35093
- this.pending.set(id, { resolve: resolve2, reject, timer });
35682
+ this.pending.set(id, { resolve, reject, timer });
35094
35683
  ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
35095
35684
  });
35096
35685
  }
@@ -35280,25 +35869,47 @@ var subCounter = 0;
35280
35869
  var WsManager = class {
35281
35870
  subscriptions = /* @__PURE__ */ new Map();
35282
35871
  events = [];
35283
- ws = null;
35284
- pingTimer = null;
35285
- channelArgs = /* @__PURE__ */ new Map();
35286
- // channel -> instIds
35872
+ wsPub = null;
35873
+ wsPriv = null;
35874
+ pingPub = null;
35875
+ pingPriv = null;
35876
+ // Fix #1: 按 type 拆分 channelArgs,重连时只遍历同类型
35877
+ channelArgsPub = /* @__PURE__ */ new Map();
35878
+ channelArgsPriv = /* @__PURE__ */ new Map();
35879
+ getWs(type) {
35880
+ return type === "public" ? this.wsPub : this.wsPriv;
35881
+ }
35882
+ setWs(type, ws) {
35883
+ if (type === "public") this.wsPub = ws;
35884
+ else this.wsPriv = ws;
35885
+ }
35886
+ getPing(type) {
35887
+ return type === "public" ? this.pingPub : this.pingPriv;
35888
+ }
35889
+ setPing(type, timer) {
35890
+ if (type === "public") this.pingPub = timer;
35891
+ else this.pingPriv = timer;
35892
+ }
35893
+ getChannelArgs(type) {
35894
+ return type === "public" ? this.channelArgsPub : this.channelArgsPriv;
35895
+ }
35287
35896
  async subscribe(opts) {
35288
- const wsModule = await Promise.resolve().then(() => (init_wrapper(), wrapper_exports));
35289
35897
  const id = `sub_${++subCounter}`;
35290
- this.subscriptions.set(id, { id, channel: opts.channel, instId: opts.instId });
35898
+ const type = opts.type || "public";
35899
+ this.subscriptions.set(id, { id, channel: opts.channel, instId: opts.instId, type });
35291
35900
  const arg = { channel: opts.channel, instId: opts.instId };
35292
- if (!this.ws || this.ws.readyState !== wsModule.WebSocket.OPEN) {
35293
- const url = opts.type === "private" ? WS_PRIVATE : WS_PUBLIC;
35294
- await this.connect(wsModule, url, opts.auth);
35295
- }
35296
- if (this.ws?.readyState === wsModule.WebSocket.OPEN) {
35297
- this.ws.send(JSON.stringify({ op: "subscribe", args: [arg] }));
35298
- }
35299
- const ck = opts.channel;
35300
- if (!this.channelArgs.has(ck)) this.channelArgs.set(ck, /* @__PURE__ */ new Set());
35301
- this.channelArgs.get(ck).add(opts.instId);
35901
+ const currentWs = this.getWs(type);
35902
+ if (!currentWs || currentWs.readyState !== wrapper_default.OPEN) {
35903
+ const url = type === "private" ? WS_PRIVATE : WS_PUBLIC;
35904
+ await this.connect(url, opts.auth, type);
35905
+ }
35906
+ const targetWs = this.getWs(type);
35907
+ if (targetWs?.readyState === wrapper_default.OPEN) {
35908
+ targetWs.send(JSON.stringify({ op: "subscribe", args: [arg] }));
35909
+ }
35910
+ const chanArgs = this.getChannelArgs(type);
35911
+ if (!chanArgs.has(opts.channel)) chanArgs.set(opts.channel, /* @__PURE__ */ new Set());
35912
+ chanArgs.get(opts.channel).add(opts.instId);
35302
35913
  return id;
35303
35914
  }
35304
35915
  drain(subId, limit = 20) {
@@ -35329,37 +35940,60 @@ var WsManager = class {
35329
35940
  }
35330
35941
  close(subId) {
35331
35942
  if (subId) {
35943
+ const sub = this.subscriptions.get(subId);
35944
+ if (sub) {
35945
+ const chanArgs = this.getChannelArgs(sub.type);
35946
+ const instIds = chanArgs.get(sub.channel);
35947
+ if (instIds) {
35948
+ instIds.delete(sub.instId);
35949
+ if (instIds.size === 0) chanArgs.delete(sub.channel);
35950
+ }
35951
+ const ws = this.getWs(sub.type);
35952
+ if (ws?.readyState === wrapper_default.OPEN) {
35953
+ try {
35954
+ ws.send(JSON.stringify({ op: "unsubscribe", args: [{ channel: sub.channel, instId: sub.instId }] }));
35955
+ } catch {
35956
+ }
35957
+ }
35958
+ }
35332
35959
  this.subscriptions.delete(subId);
35333
35960
  this.events = this.events.filter((e) => e.subId !== subId);
35334
35961
  return 1;
35335
35962
  }
35336
35963
  const count = this.subscriptions.size;
35337
35964
  this.subscriptions.clear();
35965
+ this.channelArgsPub.clear();
35966
+ this.channelArgsPriv.clear();
35338
35967
  this.events = [];
35339
- if (this.ws) {
35340
- try {
35341
- this.ws.close();
35342
- } catch {
35968
+ for (const ws of [this.wsPub, this.wsPriv]) {
35969
+ if (ws) {
35970
+ try {
35971
+ ws.close();
35972
+ } catch {
35973
+ }
35343
35974
  }
35344
- ;
35345
- this.ws = null;
35346
35975
  }
35347
- if (this.pingTimer) {
35348
- clearInterval(this.pingTimer);
35349
- this.pingTimer = null;
35976
+ this.wsPub = null;
35977
+ this.wsPriv = null;
35978
+ for (const t of [this.pingPub, this.pingPriv]) {
35979
+ if (t) {
35980
+ clearInterval(t);
35981
+ }
35350
35982
  }
35983
+ this.pingPub = null;
35984
+ this.pingPriv = null;
35351
35985
  return count;
35352
35986
  }
35353
- connect(wsModule, url, auth) {
35354
- return new Promise((resolve2, reject) => {
35355
- const ws = new wsModule.WebSocket(url);
35987
+ connect(url, auth, type) {
35988
+ return new Promise((resolve, reject) => {
35989
+ const ws = new wrapper_default(url);
35356
35990
  const timeout = setTimeout(() => {
35357
35991
  ws.close();
35358
35992
  reject(new Error("WS \u8FDE\u63A5\u8D85\u65F6(10s)"));
35359
35993
  }, 1e4);
35360
35994
  ws.on("open", () => {
35361
35995
  clearTimeout(timeout);
35362
- if (auth && url.includes("private")) {
35996
+ if (auth && type === "private") {
35363
35997
  const ts = Math.floor(Date.now() / 1e3).toString();
35364
35998
  const sign2 = import_node_crypto2.default.createHmac("sha256", auth.secret).update(ts + "GET/users/self/verify").digest("base64");
35365
35999
  ws.send(JSON.stringify({
@@ -35367,22 +36001,40 @@ var WsManager = class {
35367
36001
  args: [{ apiKey: auth.apiKey, passphrase: auth.passphrase, timestamp: ts, sign: sign2 }]
35368
36002
  }));
35369
36003
  }
35370
- for (const [channel, instIds] of this.channelArgs) {
36004
+ const chanArgs = this.getChannelArgs(type);
36005
+ for (const [channel, instIds] of chanArgs) {
35371
36006
  for (const instId of instIds) {
35372
36007
  ws.send(JSON.stringify({ op: "subscribe", args: [{ channel, instId }] }));
35373
36008
  }
35374
36009
  }
35375
- this.pingTimer = setInterval(() => {
35376
- if (ws.readyState === wsModule.WebSocket.OPEN) ws.send("ping");
36010
+ const timer = setInterval(() => {
36011
+ if (ws.readyState === wrapper_default.OPEN) ws.send("ping");
35377
36012
  }, 25e3);
35378
- this.ws = ws;
35379
- resolve2();
36013
+ this.setPing(type, timer);
36014
+ this.setWs(type, ws);
36015
+ resolve();
35380
36016
  });
35381
36017
  ws.on("message", (raw) => {
35382
36018
  try {
35383
36019
  const msg = raw.toString();
35384
36020
  if (msg === "pong") return;
35385
36021
  const parsed = JSON.parse(msg);
36022
+ if (parsed.event === "error" && parsed.code) {
36023
+ this.events.push({
36024
+ subId: "__error__",
36025
+ channel: parsed.arg?.channel || "unknown",
36026
+ instId: parsed.arg?.instId || "",
36027
+ ts: Date.now(),
36028
+ data: {
36029
+ error: true,
36030
+ code: parsed.code,
36031
+ message: parsed.msg || "WebSocket \u9519\u8BEF",
36032
+ 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}`
36033
+ }
36034
+ });
36035
+ if (this.events.length > 1e4) this.events = this.events.slice(-5e3);
36036
+ return;
36037
+ }
35386
36038
  if (parsed.arg && parsed.data) {
35387
36039
  for (const [id, sub] of this.subscriptions) {
35388
36040
  if (sub.channel === parsed.arg.channel && sub.instId === parsed.arg.instId) {
@@ -35406,11 +36058,12 @@ var WsManager = class {
35406
36058
  reject(err);
35407
36059
  });
35408
36060
  ws.on("close", () => {
35409
- if (this.pingTimer) {
35410
- clearInterval(this.pingTimer);
35411
- this.pingTimer = null;
36061
+ const t = this.getPing(type);
36062
+ if (t) {
36063
+ clearInterval(t);
36064
+ this.setPing(type, null);
35412
36065
  }
35413
- this.ws = null;
36066
+ this.setWs(type, null);
35414
36067
  });
35415
36068
  });
35416
36069
  }
@@ -35422,36 +36075,103 @@ function getOrCreateWs() {
35422
36075
  if (!wsManager) wsManager = new WsManager();
35423
36076
  return wsManager;
35424
36077
  }
35425
- var PUBLIC_CHANNELS = [
35426
- "tickers",
35427
- "trades",
35428
- "candle1m",
35429
- "candle5m",
35430
- "candle15m",
35431
- "candle1H",
35432
- "candle4H",
35433
- "candle1D",
35434
- "books5",
35435
- "books",
35436
- "mark-price",
35437
- "funding-rate",
35438
- "open-interest",
35439
- "price-limit",
35440
- "index-tickers"
35441
- ];
35442
- function registerWsTools(server) {
36078
+ var ALL_CHANNELS = {
36079
+ public: [
36080
+ // 行情类(10)
36081
+ "tickers",
36082
+ "trades",
36083
+ "all-trades",
36084
+ "option-trades",
36085
+ "candle1m",
36086
+ "candle5m",
36087
+ "candle15m",
36088
+ "candle1H",
36089
+ "candle4H",
36090
+ "candle1D",
36091
+ // 深度类(2)
36092
+ "books5",
36093
+ "books",
36094
+ // 市场细节(1)
36095
+ "call-auction-details",
36096
+ // 公共数据(10)
36097
+ "mark-price",
36098
+ "mark-price-candles",
36099
+ "index-tickers",
36100
+ "index-candles",
36101
+ "funding-rate",
36102
+ "open-interest",
36103
+ "price-limit",
36104
+ "instruments",
36105
+ "option-summary",
36106
+ "estimated-price",
36107
+ // 风险预警(3)
36108
+ "liquidation-orders",
36109
+ "adl-warning",
36110
+ "status",
36111
+ // 事件合约(1)
36112
+ "event-contract-markets",
36113
+ // 经济日历(1)
36114
+ "economic-calendar",
36115
+ // 价差公开(4)
36116
+ "sprd/tickers",
36117
+ "sprd/candles",
36118
+ "sprd/order-book",
36119
+ "sprd/public-trades",
36120
+ // 大宗公开(3)
36121
+ "public-structure-block-trades",
36122
+ "public-block-trades",
36123
+ "block-tickers"
36124
+ ],
36125
+ private: [
36126
+ // 账户(5)
36127
+ "account",
36128
+ "positions",
36129
+ "balance_and_position",
36130
+ "position-risk-warning",
36131
+ "account-greeks",
36132
+ // 交易(4)
36133
+ "orders",
36134
+ "fills",
36135
+ "algo-orders",
36136
+ "advance-algo-orders",
36137
+ // 网格(4)
36138
+ "spot-grid-algo-orders",
36139
+ "contract-grid-algo-orders",
36140
+ "grid-positions",
36141
+ "grid-sub-orders",
36142
+ // 定投(1)
36143
+ "recurring-buy-orders",
36144
+ // 跟单(1)
36145
+ "lead-trading-notification",
36146
+ // 资金(2)
36147
+ "deposit-info",
36148
+ "withdrawal-info",
36149
+ // 大宗私有(3)
36150
+ "rfqs",
36151
+ "quotes",
36152
+ "structure-block-trades",
36153
+ // 价差私有(2)
36154
+ "sprd/orders",
36155
+ "sprd/trades"
36156
+ ]
36157
+ };
36158
+ function registerWsTools(server, auth) {
35443
36159
  server.tool(
35444
36160
  "okx_ws_subscribe",
35445
- "CAT:[\u884C\u60C5-WS] | ## \u529F\u80FD\uFF1A\u8BA2\u9605OKX WebSocket\u5B9E\u65F6\u6570\u636E\uFF0C\u4E8B\u4EF6\u81EA\u52A8\u7F13\u51B2\u5728\u5185\u5B58\u4E2D\n## \u573A\u666F\uFF1AAgent \u9700\u8981\u5B9E\u65F6\u76D1\u63A7\u884C\u60C5\u53D8\u5316\u800C\u975E\u8F6E\u8BE2\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1AWebSocket, ws, \u5B9E\u65F6\u63A8\u9001, \u5B9E\u65F6\u884C\u60C5, \u8BA2\u9605, subscribe, \u6D41\u5F0F\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT\u3001ETH-USDT-SWAP\n## - channel: \u9891\u9053\u540D\u3002(tickers/trades/candle1m~1D/books5/books\u7B49)\n## - instType: SPOT/SWAP/FUTURES/OPTION\uFF08tickers/trades \u9891\u9053\u9700\u8981\uFF09\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u9891\u9053\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\u8BA2\u9605\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u8BA2\u9605 \u2192 okx_ws_events \u62C9\u53D6 \u2192 \u51B3\u7B56 \u2192 okx_ws_close \u5173\u95ED",
36161
+ "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
36162
  {
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("tickers/trades \u9700\u8981")
36163
+ 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"),
36164
+ 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"),
36165
+ instType: external_exports.enum(["SPOT", "SWAP", "FUTURES", "OPTION"]).optional().describe("\u90E8\u5206\u9891\u9053\u9700\u8981\u4EA7\u54C1\u7C7B\u578B")
35450
36166
  },
35451
36167
  async ({ instId, channel }) => {
35452
36168
  try {
35453
- if (!PUBLIC_CHANNELS.includes(channel)) {
35454
- return toError(new Error(`\u9891\u9053 "${channel}" \u4E0D\u652F\u6301\u3002\u652F\u6301: ${PUBLIC_CHANNELS.join(" ")}`));
36169
+ if (!ALL_CHANNELS.public.includes(channel)) {
36170
+ return toError(new Error(
36171
+ `\u9891\u9053 "${channel}" \u975E\u516C\u5F00\u9891\u9053\u3002
36172
+ \u516C\u5F00\u9891\u9053(${ALL_CHANNELS.public.length}\u4E2A): ${ALL_CHANNELS.public.join(" ")}
36173
+ \u79C1\u6709\u9891\u9053\u8BF7\u7528 okx_ws_subscribe_private\u3002`
36174
+ ));
35455
36175
  }
35456
36176
  const ws = getOrCreateWs();
35457
36177
  const subId = await ws.subscribe({ channel, instId: instId.toUpperCase(), type: "public" });
@@ -35460,8 +36180,48 @@ function registerWsTools(server) {
35460
36180
  subscriptionId: subId,
35461
36181
  channel,
35462
36182
  instId: instId.toUpperCase(),
36183
+ type: "public",
36184
+ buffered: ws.countBuffered(subId),
36185
+ hint: `\u5DF2\u8BA2\u9605 ${instId || "\u5168\u5C40"} ${channel}\u3002\u8C03\u7528 okx_ws_events \u62C9\u53D6\u4E8B\u4EF6\u3002`,
36186
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
36187
+ });
36188
+ } catch (e) {
36189
+ return toError(e);
36190
+ }
36191
+ }
36192
+ );
36193
+ server.tool(
36194
+ "okx_ws_subscribe_private",
36195
+ "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",
36196
+ {
36197
+ instId: external_exports.string().optional().describe("\u4EA7\u54C1ID\u3002\u8D26\u6237\u7EA7\u9891\u9053\u53EF\u4E0D\u4F20\uFF08\u5982 account/positions/balances\uFF09"),
36198
+ 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")
36199
+ },
36200
+ async ({ instId, channel }) => {
36201
+ if (!auth) return toError(AUTH_REQUIRED);
36202
+ try {
36203
+ if (!ALL_CHANNELS.private.includes(channel)) {
36204
+ return toError(new Error(
36205
+ `\u9891\u9053 "${channel}" \u975E\u79C1\u6709\u9891\u9053\u3002
36206
+ \u79C1\u6709\u9891\u9053(${ALL_CHANNELS.private.length}\u4E2A): ${ALL_CHANNELS.private.join(" ")}
36207
+ \u516C\u5F00\u9891\u9053\u8BF7\u7528 okx_ws_subscribe\u3002`
36208
+ ));
36209
+ }
36210
+ const ws = getOrCreateWs();
36211
+ const subId = await ws.subscribe({
36212
+ channel,
36213
+ instId: (instId || "").toUpperCase(),
36214
+ type: "private",
36215
+ auth
36216
+ });
36217
+ return toResult({
36218
+ subscribed: true,
36219
+ subscriptionId: subId,
36220
+ channel,
36221
+ instId: (instId || "\u5168\u5C40").toUpperCase(),
36222
+ type: "private",
35463
36223
  buffered: ws.countBuffered(subId),
35464
- hint: `\u5DF2\u8BA2\u9605 ${instId.toUpperCase()} ${channel}\u3002\u8C03\u7528 okx_ws_events \u62C9\u53D6\u4E8B\u4EF6\u3002`,
36224
+ hint: `\u5DF2\u8BA2\u9605\u79C1\u6709\u9891\u9053 ${channel}\u3002\u8C03\u7528 okx_ws_events \u62C9\u53D6\u5B9E\u65F6\u4E8B\u4EF6\u3002`,
35465
36225
  tsIso: (/* @__PURE__ */ new Date()).toISOString()
35466
36226
  });
35467
36227
  } catch (e) {
@@ -35536,7 +36296,6 @@ function registerWsTools(server) {
35536
36296
  }
35537
36297
 
35538
36298
  // src/adapters/agent-hub.ts
35539
- init_wrapper();
35540
36299
  var MAX_ROOM_MESSAGES = 200;
35541
36300
  var AgentHub = class {
35542
36301
  wss = null;
@@ -36086,98 +36845,73 @@ function registerAgentHubTools(server) {
36086
36845
  }
36087
36846
 
36088
36847
  // src/tools/codegraph.ts
36089
- var path2 = __toESM(require("node:path"));
36090
- var fs2 = __toESM(require("node:fs"));
36091
- var DatabaseSync = null;
36092
- function getDB() {
36093
- if (DatabaseSync === null) {
36094
- try {
36095
- const sqlite = require("node:sqlite");
36096
- DatabaseSync = sqlite.DatabaseSync;
36097
- } catch {
36098
- return null;
36099
- }
36100
- }
36101
- const dbPath = path2.resolve(".codegraph", "codegraph.db");
36102
- if (!fs2.existsSync(dbPath)) {
36103
- return null;
36104
- }
36848
+ var _cg = null;
36849
+ var _cgInitError = null;
36850
+ var _cgInitDone = false;
36851
+ async function getCodeGraph() {
36852
+ if (_cgInitDone) return _cg;
36105
36853
  try {
36106
- const db = new DatabaseSync(dbPath, { readonly: true });
36107
- db.prepare("SELECT 1").get();
36108
- return { db };
36854
+ const mod = await Promise.resolve().then(() => __toESM(require_npm_sdk()));
36855
+ const CodeGraph = mod.CodeGraph || mod.default?.CodeGraph;
36856
+ _cg = await CodeGraph.open(".");
36857
+ _cgInitDone = true;
36858
+ return _cg;
36109
36859
  } catch (e) {
36860
+ _cgInitError = e.message || String(e);
36861
+ _cgInitDone = true;
36110
36862
  return null;
36111
36863
  }
36112
36864
  }
36113
36865
  function registerCodeGraphTools(server) {
36114
36866
  server.tool(
36115
36867
  "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\u540E\u7D22\u5F15\u65F6\u95F4\n## \u573A\u666F\uFF1AAgent \u9996\u6B21\u8FDE\u63A5\u65F6\u8C03\u7528\uFF0C\u4E86\u89E3\u4EE3\u7801\u56FE\u8C31\u662F\u5426\u5C31\u7EEA\uFF1B\u6216\u7528\u6237\u95EE\u300C\u4EE3\u7801\u7ED3\u6784\u80FD\u67E5\u5417\u300D\u65F6\u786E\u8BA4\u72B6\u6001\n## \u5173\u952E\u8BCD\uFF1A\u4EE3\u7801\u56FE\u8C31, codegraph, \u77E5\u8BC6\u56FE\u8C31, \u4EE3\u7801\u7ED3\u6784, \u7D22\u5F15\u72B6\u6001\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u53EA\u8BFB\uFF0C\u4E0D\u67E5\u5916\u90E8 API\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\u672C\u5730\u6587\u4EF6\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u786E\u8BA4\u72B6\u6001 \u2192 codegraph_query \u67E5\u8BE2 \u2192 \u83B7\u53D6\u8C03\u7528\u94FE/\u4F9D\u8D56/\u7ED3\u6784",
36868
+ "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\u7528\u6700\u591A\u7684\u51FD\u6570\n## \u573A\u666F\uFF1AAgent \u9996\u6B21\u8FDE\u63A5\u65F6\u786E\u8BA4\u56FE\u8C31\u662F\u5426\u5C31\u7EEA\uFF0C\u6216\u7528\u6237\u95EE\u300Chvip \u4EE3\u7801\u7ED3\u6784\u80FD\u67E5\u5417\u300D\u65F6\u786E\u8BA4\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\u6570\u636E\u5E93\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~800B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u786E\u8BA4\u72B6\u6001 \u2192 codegraph_query \u8FFD\u8E2A\u8C03\u7528\u94FE/\u641C\u7D22\u7B26\u53F7",
36117
36869
  {},
36118
36870
  async () => {
36119
36871
  try {
36120
- const conn = getDB();
36121
- if (!conn) {
36122
- const nodeVersion = process.versions.node;
36123
- const nodeMajor = parseInt(nodeVersion.split(".")[0]);
36124
- const needsUpgrade = nodeMajor < 22 || nodeMajor === 22 && parseInt(nodeVersion.split(".")[1]) < 5;
36872
+ const cg = await getCodeGraph();
36873
+ if (!cg) {
36125
36874
  return toResult({
36126
36875
  status: "unavailable",
36127
- reason: needsUpgrade ? `Node.js ${nodeVersion} \u4E0D\u652F\u6301\u5185\u7F6E sqlite\uFF0C\u9700\u8981 Node >= 22.5.0` : "\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u6570\u636E\u5E93\u672A\u627E\u5230",
36128
- how_to_setup: [
36129
- "1. npm i -g @colbymchenry/codegraph",
36130
- "2. cd \u5230\u9879\u76EE\u6839\u76EE\u5F55",
36131
- "3. codegraph index # \u751F\u6210 .codegraph/codegraph.db",
36132
- "4. \u91CD\u542F MCP Server"
36133
- ].join("\n"),
36134
- nodeVersion,
36876
+ reason: _cgInitError || "CodeGraph \u5F15\u64CE\u52A0\u8F7D\u5931\u8D25",
36877
+ how_to_setup: "npm i @colbymchenry/codegraph && codegraph index",
36878
+ alternatives: "\u56FE\u8C31\u4E0D\u53EF\u7528\u65F6\uFF0C\u4ECD\u53EF\u7528\u672C\u5DE5\u5177\u8FD4\u56DE\u7684\u8282\u70B9\u6570\u548C\u8FB9\u6570\u4E86\u89E3\u4EE3\u7801\u89C4\u6A21",
36135
36879
  tsIso: (/* @__PURE__ */ new Date()).toISOString(),
36136
- _summary: needsUpgrade ? `\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\uFF1ANode ${nodeVersion} \u9700 >= 22.5.0` : "\u4EE3\u7801\u56FE\u8C31\u672A\u521D\u59CB\u5316\u3002\u8BF7\u8FD0\u884C codegraph index \u751F\u6210\u6570\u636E\u5E93\u3002"
36880
+ _summary: "\u4EE3\u7801\u56FE\u8C31\u672A\u5C31\u7EEA\u3002\u8BF7\u8FD0\u884C codegraph index \u751F\u6210\u6570\u636E\u5E93\u3002"
36137
36881
  });
36138
36882
  }
36139
- const { db } = conn;
36140
- const nodeCount = db.prepare("SELECT count(*) as n FROM nodes").get().n;
36141
- const edgeCount = db.prepare("SELECT count(*) as n FROM edges").get().n;
36142
- const fileCount = db.prepare("SELECT count(*) as n FROM files").get().n;
36143
- const langRows = db.prepare(
36144
- "SELECT language, count(*) as n FROM files GROUP BY language ORDER BY n DESC"
36145
- ).all();
36146
- const kindRows = db.prepare(
36147
- "SELECT kind, count(*) as n FROM nodes GROUP BY kind ORDER BY n DESC LIMIT 10"
36148
- ).all();
36149
- const lastIndexed = db.prepare(
36150
- "SELECT max(indexed_at) as ts FROM files"
36151
- ).get().ts;
36152
- const topCalled = db.prepare(`
36153
- SELECT n.name, n.kind, n.file_path, count(e.id) as caller_count
36154
- FROM edges e
36155
- JOIN nodes n ON e.target = n.id
36156
- WHERE e.kind = 'calls'
36157
- GROUP BY e.target
36158
- ORDER BY caller_count DESC
36159
- LIMIT 10
36160
- `).all();
36883
+ const stats = await cg.getStats();
36884
+ let topCalled = [];
36885
+ try {
36886
+ const allExported = await cg.getNodesByKind("function").then((nodes) => nodes.filter((n) => n.isExported)).catch(() => []);
36887
+ const sample = allExported.slice(0, 50);
36888
+ const withCounts = await Promise.all(
36889
+ sample.map(async (n) => {
36890
+ try {
36891
+ const callers = await cg.getCallers(n.id, 1);
36892
+ return { name: n.name, file: n.filePath, callers: callers?.length || 0 };
36893
+ } catch {
36894
+ return { name: n.name, file: n.filePath, callers: 0 };
36895
+ }
36896
+ })
36897
+ );
36898
+ topCalled = withCounts.sort((a, b) => b.callers - a.callers).slice(0, 5);
36899
+ } catch {
36900
+ }
36161
36901
  const status = {
36162
36902
  status: "ready",
36163
- database: {
36164
- path: ".codegraph/codegraph.db",
36165
- nodeCount,
36166
- edgeCount,
36167
- fileCount,
36168
- languages: langRows.reduce((acc, r) => ({ ...acc, [r.language]: r.n }), {})
36903
+ stats: {
36904
+ nodes: stats.nodeCount,
36905
+ edges: stats.edgeCount,
36906
+ files: stats.fileCount,
36907
+ byKind: stats.nodesByKind,
36908
+ byLanguage: stats.filesByLanguage,
36909
+ dbSize: stats.dbSizeBytes ? `${(stats.dbSizeBytes / 1024 / 1024).toFixed(1)} MB` : "unknown"
36169
36910
  },
36170
- nodesByKind: kindRows.reduce((acc, r) => ({ ...acc, [r.kind]: r.n }), {}),
36171
- lastIndexed: lastIndexed ? new Date(lastIndexed).toISOString() : "unknown",
36172
- topCalledFunctions: topCalled.map((r) => ({
36173
- name: r.name,
36174
- kind: r.kind,
36175
- file: r.file_path,
36176
- callers: r.caller_count
36177
- })).slice(0, 5),
36178
- queryHint: "\u7528 codegraph_query \u67E5\u8BE2\u5177\u4F53\u7B26\u53F7\u7684\u8C03\u7528\u94FE\u6216\u63A2\u7D22\u4EE3\u7801\u7ED3\u6784\u3002\u4F8B\u5982: codegraph_query({ mode: 'callers', symbol: 'toResult' })",
36911
+ topCalled,
36912
+ queryHint: "\u7528 codegraph_query \u67E5\u8C03\u7528\u94FE\u3002\u4F8B: codegraph_query({ mode: 'callers', symbol: 'toResult' })",
36179
36913
  tsIso: (/* @__PURE__ */ new Date()).toISOString(),
36180
- _summary: `\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u5C31\u7EEA\u3002${nodeCount} \u4E2A\u8282\u70B9\uFF0C${edgeCount} \u6761\u5173\u7CFB\uFF0C\u8986\u76D6 ${fileCount} \u4E2A\u6587\u4EF6\u3002\u88AB\u8C03\u7528\u6700\u591A\u7684\u51FD\u6570: ${topCalled.slice(0, 3).map((r) => r.name).join("\u3001") || "\u65E0"}\u3002`
36914
+ _summary: `\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u5C31\u7EEA\u3002${stats.nodeCount} \u4E2A\u8282\u70B9\uFF0C${stats.edgeCount} \u6761\u5173\u7CFB\uFF0C\u8986\u76D6 ${stats.fileCount} \u4E2A\u6587\u4EF6\u3002${topCalled.length ? `\u88AB\u8C03\u6700\u591A: ${topCalled.slice(0, 3).map((f) => f.name).join("\u3001")}` : ""}`
36181
36915
  };
36182
36916
  return toResult(status);
36183
36917
  } catch (e) {
@@ -36187,106 +36921,113 @@ function registerCodeGraphTools(server) {
36187
36921
  );
36188
36922
  server.tool(
36189
36923
  "codegraph_query",
36190
- "CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u67E5\u8BE2\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u2014\u2014\u8FFD\u8E2A\u51FD\u6570\u8C03\u7528\u94FE\uFF08\u8C01\u8C03\u4E86\u8C01/\u88AB\u8C01\u8C03\uFF09\u3001\u641C\u7D22\u7B26\u53F7\u3001\u63A2\u7D22\u6A21\u5757\u4F9D\u8D56\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300CtoResult \u88AB\u54EA\u4E9B\u5DE5\u5177\u8C03\u7528\u300D\u300CregisterMarketTools \u7684\u8C03\u7528\u94FE\u300D\u300Cindex.ts \u4F9D\u8D56\u54EA\u4E9B\u6A21\u5757\u300D\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1Acodegraph, \u8C03\u7528\u94FE, callers, callees, \u4F9D\u8D56, \u4EE3\u7801\u641C\u7D22, \u7B26\u53F7\u67E5\u8BE2, \u4E0A\u4E0B\u6E38\n## \u53C2\u6570\uFF1A\n## - mode: \u67E5\u8BE2\u6A21\u5F0F\u3002callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, explore=\u81EA\u7136\u8BED\u8A00\u641C\u7D22, files=\u6309\u6587\u4EF6\u67E5\u8BE2\n## - symbol: \u7B26\u53F7\u540D\uFF08mode=callers/callees \u65F6\u5FC5\u586B\uFF09\u6216\u6587\u4EF6\u540D\uFF08mode=files\uFF09\n## - question: \u81EA\u7136\u8BED\u8A00\u641C\u7D22\uFF08mode=explore \u65F6\u4F7F\u7528\uFF09\n## - limit: \u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA4 15\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u6570\u636E\u5E93\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1Acodegraph_status \u770B\u72B6\u6001 \u2192 \u672C\u5DE5\u5177\u67E5\u8BE2 \u2192 \u5B9A\u4F4D\u6E90\u7801 \u2192 Agent \u7528 Read \u67E5\u770B\u7EC6\u8282",
36924
+ "CAT:[\u4EE3\u7801\u667A\u80FD] | ## \u529F\u80FD\uFF1A\u67E5\u8BE2\u4EE3\u7801\u77E5\u8BC6\u56FE\u8C31\u2014\u2014\u8FFD\u8E2A\u8C03\u7528\u94FE\u3001\u641C\u7D22\u7B26\u53F7\u3001\u63A2\u7D22\u6A21\u5757\u4F9D\u8D56\u3001\u6309\u6587\u4EF6\u5217\u51FA\u7B26\u53F7\n## \u573A\u666F\uFF1AAgent \u56DE\u7B54\u300CtoResult \u88AB\u54EA\u4E9B\u5DE5\u5177\u8C03\u7528\u300D\u300CregisterMarketTools \u7684\u4E0A\u4E0B\u6E38\u300D\u300C\u4EE3\u7801\u91CC\u54EA\u91CC\u5904\u7406\u4E86 WebSocket\u300D\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1Acodegraph, \u8C03\u7528\u94FE, callers, callees, \u4F9D\u8D56, \u4EE3\u7801\u641C\u7D22, \u7B26\u53F7\u67E5\u8BE2, \u4E0A\u4E0B\u6E38, \u5F71\u54CD\u5206\u6790\n## \u53C2\u6570\uFF1A\n## - mode: \u67E5\u8BE2\u6A21\u5F0F\u3002callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, search=\u5168\u6587\u641C\u7D22, file=\u6309\u6587\u4EF6\u5217\u51FA\n## - symbol: \u7B26\u53F7\u540D/\u8282\u70B9ID (callers/callees/file \u6A21\u5F0F)\n## - query: \u641C\u7D22\u8BCD (search \u6A21\u5F0F)\n## - limit: \u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15\n## \u9274\u6743\uFF1APUBLIC \u2014 \u672C\u5730\u8BFB\u6570\u636E\u5E93\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1Acodegraph_status \u770B\u72B6\u6001 \u2192 \u672C\u5DE5\u5177\u67E5\u8BE2 \u2192 Agent \u5B9A\u4F4D\u6E90\u7801",
36191
36925
  {
36192
- mode: external_exports.enum(["callers", "callees", "explore", "files"]).describe("\u67E5\u8BE2\u6A21\u5F0F\u3002callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, explore=\u81EA\u7136\u8BED\u8A00\u641C\u7D22, files=\u6309\u6587\u4EF6\u67E5\u8282\u70B9"),
36193
- symbol: external_exports.string().optional().describe("\u7B26\u53F7\u540D\uFF08\u5982 toResult, registerMarketTools\uFF09\u6216\u6587\u4EF6\u540D\uFF08\u5982 agent-utils.ts\uFF09"),
36194
- question: external_exports.string().optional().describe("\u81EA\u7136\u8BED\u8A00\u641C\u7D22\uFF08mode=explore \u65F6\u4F7F\u7528\uFF09\uFF0C\u5982 'HTTP \u8BF7\u6C42\u7B7E\u540D' 'WebSocket \u8FDE\u63A5'"),
36195
- limit: external_exports.number().int().min(1).max(100).optional().describe("\u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA4 15")
36926
+ mode: external_exports.enum(["callers", "callees", "search", "file"]).describe("callers=\u8C01\u8C03\u7528\u5B83, callees=\u5B83\u8C03\u7528\u8C01, search=\u5168\u6587\u641C\u7D22, file=\u6309\u6587\u4EF6\u5217\u51FA\u7B26\u53F7"),
36927
+ symbol: external_exports.string().optional().describe("\u7B26\u53F7\u540D\uFF08\u5982 toResult\uFF09\u6216\u6587\u4EF6\u540D\uFF08\u5982 agent-utils.ts\uFF09"),
36928
+ query: external_exports.string().optional().describe("\u641C\u7D22\u8BCD\uFF08search \u6A21\u5F0F\uFF09\uFF0C\u5982 'websocket \u8FDE\u63A5'"),
36929
+ limit: external_exports.number().int().min(1).max(100).optional().describe("\u8FD4\u56DE\u6570\uFF0C\u9ED8\u8BA4 15")
36196
36930
  },
36197
- async ({ mode, symbol, question, limit }) => {
36931
+ async ({ mode, symbol, query, limit }) => {
36198
36932
  try {
36199
- const conn = getDB();
36200
- if (!conn) {
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;
36933
+ const cg = await getCodeGraph();
36934
+ if (!cg) return toError("\u4EE3\u7801\u56FE\u8C31\u4E0D\u53EF\u7528\u3002\u8BF7\u5148\u8C03 codegraph_status \u68C0\u67E5\u72B6\u6001\u3002");
36204
36935
  const n = limit || 15;
36205
- if (mode === "callers") {
36206
- if (!symbol) return toError("callers \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570\uFF0CAgent \u8BF7\u63D0\u4F9B\u51FD\u6570\u540D");
36207
- const nodes = db.prepare(
36208
- "SELECT id, name, kind, file_path, start_line, signature, qualified_name FROM nodes WHERE name = ? OR name LIKE ? LIMIT 5"
36209
- ).all(symbol, `%${symbol}%`);
36210
- if (nodes.length === 0) {
36936
+ if (mode === "search") {
36937
+ const q = query || symbol || "";
36938
+ if (!q) return toError("search \u6A21\u5F0F\u9700\u8981 query \u6216 symbol \u53C2\u6570");
36939
+ const results = await cg.searchNodes(q, { limit: n });
36940
+ if (!results?.length) {
36211
36941
  return toResult({
36212
- mode: "callers",
36213
- symbol,
36942
+ mode: "search",
36943
+ query: q,
36214
36944
  found: false,
36215
- hint: `\u672A\u627E\u5230\u7B26\u53F7 "${symbol}"\u3002\u8BD5\u8BD5 codegraph_query({ mode: 'explore', question: '${symbol}' }) \u5168\u6587\u641C\u7D22`,
36945
+ hint: `\u672A\u627E\u5230\u4E0E "${q}" \u76F8\u5173\u7684\u7B26\u53F7\u3002\u8BD5\u8BD5\u51FD\u6570\u540D\uFF08\u5982 registerTools\uFF09\u6216\u6587\u4EF6\u540D\u3002`,
36216
36946
  tsIso: (/* @__PURE__ */ new Date()).toISOString()
36217
36947
  });
36218
36948
  }
36219
- const results = [];
36220
- for (const node of nodes) {
36221
- const callers = db.prepare(`
36222
- SELECT n.name as caller_name, n.kind, n.file_path, e.line, e.kind as edge_kind
36223
- FROM edges e
36224
- JOIN nodes n ON e.source = n.id
36225
- WHERE e.target = ?
36226
- ORDER BY n.name
36227
- LIMIT ?
36228
- `).all(node.id, n);
36229
- results.push({
36230
- target: { name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
36231
- callers: callers.map((c) => ({
36232
- name: c.caller_name,
36949
+ const items = await Promise.all(results.slice(0, n).map(async (r) => {
36950
+ const node = r.node || r;
36951
+ let callerCount = 0, calleeCount = 0;
36952
+ try {
36953
+ callerCount = (await cg.getCallers(node.id, 1))?.length || 0;
36954
+ } catch {
36955
+ }
36956
+ try {
36957
+ calleeCount = (await cg.getCallees(node.id, 1))?.length || 0;
36958
+ } catch {
36959
+ }
36960
+ return {
36961
+ id: node.id,
36962
+ name: node.name,
36963
+ kind: node.kind,
36964
+ file: node.filePath,
36965
+ line: node.startLine,
36966
+ signature: node.signature?.slice(0, 120),
36967
+ stats: { callers: callerCount, callees: calleeCount }
36968
+ };
36969
+ }));
36970
+ return toResult({
36971
+ mode: "search",
36972
+ query: q,
36973
+ total: results.length,
36974
+ results: items,
36975
+ _summary: `\u641C\u7D22 "${q}" \u627E\u5230 ${results.length} \u4E2A\u7B26\u53F7\u3002${items.slice(0, 3).map((i) => `${i.name}(${i.kind})`).join(" | ")}`,
36976
+ hint: `\u627E\u5230\u5177\u4F53\u7B26\u53F7\u540E\uFF0C\u7528 codegraph_query({ mode: 'callers', symbol: '<id>' }) \u8FFD\u8E2A\u8C03\u7528\u94FE\u3002`,
36977
+ tsIso: (/* @__PURE__ */ new Date()).toISOString()
36978
+ });
36979
+ }
36980
+ if (mode === "callers") {
36981
+ if (!symbol) return toError("callers \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570");
36982
+ const nodes = await cg.getNodesByName(symbol);
36983
+ if (!nodes?.length) {
36984
+ return toResult({ mode: "callers", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
36985
+ }
36986
+ const results = await Promise.all(nodes.slice(0, 5).map(async (node) => {
36987
+ const callers = await cg.getCallers(node.id, 1);
36988
+ return {
36989
+ target: { id: node.id, name: node.name, kind: node.kind, file: node.filePath, line: node.startLine },
36990
+ callers: (callers || []).slice(0, n).map((c) => ({
36991
+ name: c.name,
36233
36992
  kind: c.kind,
36234
- file: c.file_path,
36235
- atLine: c.line,
36236
- relation: c.edge_kind
36993
+ file: c.filePath,
36994
+ line: c.line,
36995
+ relation: c.edgeKind
36237
36996
  })),
36238
- totalCallers: callers.length
36239
- });
36240
- }
36241
- const total = results.reduce((s, r) => s + r.totalCallers, 0);
36997
+ total: callers?.length || 0
36998
+ };
36999
+ }));
37000
+ const total = results.reduce((s, r) => s + r.total, 0);
36242
37001
  return toResult({
36243
37002
  mode: "callers",
36244
37003
  symbol,
36245
37004
  matched: nodes.length,
36246
37005
  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(" | ")}`,
37006
+ _summary: `"${symbol}" \u5339\u914D ${nodes.length} \u4E2A\u7B26\u53F7\uFF0C\u5171 ${total} \u4E2A\u8C03\u7528\u8005\u3002`,
36248
37007
  tsIso: (/* @__PURE__ */ new Date()).toISOString()
36249
37008
  });
36250
37009
  }
36251
37010
  if (mode === "callees") {
36252
37011
  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) {
36257
- return toResult({
36258
- mode: "callees",
36259
- symbol,
36260
- found: false,
36261
- hint: `\u672A\u627E\u5230 "${symbol}"\uFF0C\u8BD5\u8BD5 mode='explore' \u5168\u6587\u641C\u7D22`,
36262
- tsIso: (/* @__PURE__ */ new Date()).toISOString()
36263
- });
37012
+ const nodes = await cg.getNodesByName(symbol);
37013
+ if (!nodes?.length) {
37014
+ return toResult({ mode: "callees", symbol, found: false, tsIso: (/* @__PURE__ */ new Date()).toISOString() });
36264
37015
  }
36265
- const results = [];
36266
- for (const node of nodes) {
36267
- const callees = db.prepare(`
36268
- SELECT n.name as callee_name, n.kind, n.file_path, e.line
36269
- FROM edges e
36270
- JOIN nodes n ON e.target = n.id
36271
- WHERE e.source = ?
36272
- ORDER BY e.kind, n.name
36273
- LIMIT ?
36274
- `).all(node.id, n);
36275
- const byKind = {};
36276
- for (const c of callees) {
36277
- (byKind[c.kind] || (byKind[c.kind] = [])).push(c);
36278
- }
36279
- results.push({
36280
- source: { name: node.name, kind: node.kind, file: node.file_path, line: node.start_line },
36281
- callees: Object.entries(byKind).map(([kind, items]) => ({
36282
- relation: kind,
36283
- count: items.length,
36284
- top: items.slice(0, 10).map((c) => ({ name: c.callee_name, kind: c.kind, file: c.file_path, atLine: c.line }))
37016
+ const results = await Promise.all(nodes.slice(0, 5).map(async (node) => {
37017
+ const callees = await cg.getCallees(node.id, 1);
37018
+ return {
37019
+ source: { id: node.id, name: node.name, kind: node.kind, file: node.filePath, line: node.startLine },
37020
+ callees: (callees || []).slice(0, n).map((c) => ({
37021
+ name: c.name,
37022
+ kind: c.kind,
37023
+ file: c.filePath,
37024
+ line: c.line,
37025
+ relation: c.edgeKind
36285
37026
  })),
36286
- totalCallees: callees.length
36287
- });
36288
- }
36289
- const total = results.reduce((s, r) => s + r.totalCallees, 0);
37027
+ total: callees?.length || 0
37028
+ };
37029
+ }));
37030
+ const total = results.reduce((s, r) => s + r.total, 0);
36290
37031
  return toResult({
36291
37032
  mode: "callees",
36292
37033
  symbol,
@@ -36296,95 +37037,23 @@ function registerCodeGraphTools(server) {
36296
37037
  tsIso: (/* @__PURE__ */ new Date()).toISOString()
36297
37038
  });
36298
37039
  }
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) {
36320
- return toResult({
36321
- mode: "explore",
36322
- question: q,
36323
- found: false,
36324
- hint: `\u672A\u627E\u5230\u4E0E "${q}" \u76F8\u5173\u7684\u7B26\u53F7\u3002\u8BD5\u8BD5\u66F4\u77ED\u7684\u5173\u952E\u8BCD\u6216\u76F4\u63A5\u641C\u51FD\u6570\u540D\u3002`,
36325
- tsIso: (/* @__PURE__ */ new Date()).toISOString()
36326
- });
36327
- }
36328
- const top = rows.slice(0, 5);
36329
- const enriched = top.map((r) => {
36330
- const callers = db.prepare(
36331
- "SELECT count(*) as n FROM edges WHERE target = ? AND kind = 'calls'"
36332
- ).get(r.id).n;
36333
- const callees = db.prepare(
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);
37040
+ if (mode === "file") {
37041
+ if (!symbol) return toError("file \u6A21\u5F0F\u9700\u8981 symbol \u53C2\u6570\uFF08\u6587\u4EF6\u540D\uFF09");
37042
+ const files = await cg.getFiles({ pattern: symbol });
37043
+ const fileInfo = files?.[0];
37044
+ const symbols = fileInfo ? await cg.getNodesInFile(fileInfo.path) : [];
36370
37045
  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
37046
+ mode: "file",
37047
+ file: symbol,
37048
+ fileInfo: fileInfo ? { path: fileInfo.path, language: fileInfo.language, size: fileInfo.size } : null,
37049
+ symbols: (symbols || []).slice(0, n).map((s) => ({
37050
+ name: s.name,
37051
+ kind: s.kind,
37052
+ line: s.startLine,
37053
+ signature: s.signature?.slice(0, 120),
37054
+ exported: s.isExported
36386
37055
  })),
36387
- _summary: `\u6587\u4EF6 "${file}" \u5305\u542B ${nodes.length} \u4E2A\u7B26\u53F7\u3002${nodes.filter((r) => r.is_exported).length} \u4E2A\u5BFC\u51FA\u3002`,
37056
+ _summary: `\u6587\u4EF6 "${symbol}" \u5305\u542B ${symbols?.length || 0} \u4E2A\u7B26\u53F7\u3002`,
36388
37057
  tsIso: (/* @__PURE__ */ new Date()).toISOString()
36389
37058
  });
36390
37059
  }
@@ -36449,7 +37118,7 @@ function registerAllTools(server, auth, readOnly) {
36449
37118
  registerIndicatorTools(server);
36450
37119
  registerSmartMoneyTools(server, auth);
36451
37120
  registerXLayerWSTools(server);
36452
- registerWsTools(server);
37121
+ registerWsTools(server, auth);
36453
37122
  registerAgentHubTools(server);
36454
37123
  registerCodeGraphTools(server);
36455
37124
  return { skipped, skipLog };
@@ -36544,7 +37213,7 @@ async function startStdio(server, version2, auth, readOnly, skipped, skipLog) {
36544
37213
  await server.connect(transport);
36545
37214
  }
36546
37215
  async function main() {
36547
- const VERSION = "0.2.49";
37216
+ const VERSION = "0.2.50";
36548
37217
  const auth = getAuth();
36549
37218
  const mode = resolveTransportMode();
36550
37219
  const exec = resolveExecutionMode();
@@ -36552,7 +37221,7 @@ async function main() {
36552
37221
  const server = new McpServer({
36553
37222
  name: "hvip-mcp",
36554
37223
  version: VERSION,
36555
- description: "hvip MCP Server \u2014 364 \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\uFF08\u975E OKX \u5B98\u65B9\u4EA7\u54C1\uFF09\u3002\u4ED3\u5E93: https://github.com/okx-wallet-H/hvip-mcp"
37224
+ 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
37225
  });
36557
37226
  const { skipped, skipLog } = registerAllTools(server, auth, readOnly);
36558
37227
  if (mode === "http") {