codeql-development-mcp-server 2.24.3-rc2 → 2.25.0-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codeql-development-mcp-server.js +798 -360
- package/dist/codeql-development-mcp-server.js.map +4 -4
- package/package.json +8 -8
- package/ql/actions/tools/src/codeql-pack.lock.yml +14 -14
- package/ql/actions/tools/src/codeql-pack.yml +2 -2
- package/ql/cpp/tools/src/codeql-pack.yml +1 -1
- package/ql/csharp/tools/src/codeql-pack.yml +1 -1
- package/ql/go/tools/src/codeql-pack.yml +1 -1
- package/ql/java/tools/src/codeql-pack.yml +1 -1
- package/ql/javascript/tools/src/codeql-pack.yml +1 -1
- package/ql/python/tools/src/codeql-pack.yml +1 -1
- package/ql/ruby/tools/src/codeql-pack.yml +1 -1
- package/ql/swift/tools/src/codeql-pack.yml +1 -1
|
@@ -2242,8 +2242,8 @@ var require_resolve = __commonJS({
|
|
|
2242
2242
|
}
|
|
2243
2243
|
return count;
|
|
2244
2244
|
}
|
|
2245
|
-
function getFullPath(resolver, id = "",
|
|
2246
|
-
if (
|
|
2245
|
+
function getFullPath(resolver, id = "", normalize2) {
|
|
2246
|
+
if (normalize2 !== false)
|
|
2247
2247
|
id = normalizeId(id);
|
|
2248
2248
|
const p = resolver.parse(id);
|
|
2249
2249
|
return _getFullPath(resolver, p);
|
|
@@ -2991,7 +2991,7 @@ var require_compile = __commonJS({
|
|
|
2991
2991
|
const schOrFunc = root.refs[ref];
|
|
2992
2992
|
if (schOrFunc)
|
|
2993
2993
|
return schOrFunc;
|
|
2994
|
-
let _sch =
|
|
2994
|
+
let _sch = resolve15.call(this, root, ref);
|
|
2995
2995
|
if (_sch === void 0) {
|
|
2996
2996
|
const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2997
2997
|
const { schemaId } = this.opts;
|
|
@@ -3018,7 +3018,7 @@ var require_compile = __commonJS({
|
|
|
3018
3018
|
function sameSchemaEnv(s1, s2) {
|
|
3019
3019
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3020
3020
|
}
|
|
3021
|
-
function
|
|
3021
|
+
function resolve15(root, ref) {
|
|
3022
3022
|
let sch;
|
|
3023
3023
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3024
3024
|
ref = sch;
|
|
@@ -3583,7 +3583,7 @@ var require_fast_uri = __commonJS({
|
|
|
3583
3583
|
"use strict";
|
|
3584
3584
|
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
|
|
3585
3585
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3586
|
-
function
|
|
3586
|
+
function normalize2(uri, options) {
|
|
3587
3587
|
if (typeof uri === "string") {
|
|
3588
3588
|
uri = /** @type {T} */
|
|
3589
3589
|
serialize(parse4(uri, options), options);
|
|
@@ -3593,55 +3593,55 @@ var require_fast_uri = __commonJS({
|
|
|
3593
3593
|
}
|
|
3594
3594
|
return uri;
|
|
3595
3595
|
}
|
|
3596
|
-
function
|
|
3596
|
+
function resolve15(baseURI, relativeURI, options) {
|
|
3597
3597
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3598
3598
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3599
3599
|
schemelessOptions.skipEscape = true;
|
|
3600
3600
|
return serialize(resolved, schemelessOptions);
|
|
3601
3601
|
}
|
|
3602
|
-
function resolveComponent(base,
|
|
3602
|
+
function resolveComponent(base, relative2, options, skipNormalization) {
|
|
3603
3603
|
const target = {};
|
|
3604
3604
|
if (!skipNormalization) {
|
|
3605
3605
|
base = parse4(serialize(base, options), options);
|
|
3606
|
-
|
|
3606
|
+
relative2 = parse4(serialize(relative2, options), options);
|
|
3607
3607
|
}
|
|
3608
3608
|
options = options || {};
|
|
3609
|
-
if (!options.tolerant &&
|
|
3610
|
-
target.scheme =
|
|
3611
|
-
target.userinfo =
|
|
3612
|
-
target.host =
|
|
3613
|
-
target.port =
|
|
3614
|
-
target.path = removeDotSegments(
|
|
3615
|
-
target.query =
|
|
3609
|
+
if (!options.tolerant && relative2.scheme) {
|
|
3610
|
+
target.scheme = relative2.scheme;
|
|
3611
|
+
target.userinfo = relative2.userinfo;
|
|
3612
|
+
target.host = relative2.host;
|
|
3613
|
+
target.port = relative2.port;
|
|
3614
|
+
target.path = removeDotSegments(relative2.path || "");
|
|
3615
|
+
target.query = relative2.query;
|
|
3616
3616
|
} else {
|
|
3617
|
-
if (
|
|
3618
|
-
target.userinfo =
|
|
3619
|
-
target.host =
|
|
3620
|
-
target.port =
|
|
3621
|
-
target.path = removeDotSegments(
|
|
3622
|
-
target.query =
|
|
3617
|
+
if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
|
|
3618
|
+
target.userinfo = relative2.userinfo;
|
|
3619
|
+
target.host = relative2.host;
|
|
3620
|
+
target.port = relative2.port;
|
|
3621
|
+
target.path = removeDotSegments(relative2.path || "");
|
|
3622
|
+
target.query = relative2.query;
|
|
3623
3623
|
} else {
|
|
3624
|
-
if (!
|
|
3624
|
+
if (!relative2.path) {
|
|
3625
3625
|
target.path = base.path;
|
|
3626
|
-
if (
|
|
3627
|
-
target.query =
|
|
3626
|
+
if (relative2.query !== void 0) {
|
|
3627
|
+
target.query = relative2.query;
|
|
3628
3628
|
} else {
|
|
3629
3629
|
target.query = base.query;
|
|
3630
3630
|
}
|
|
3631
3631
|
} else {
|
|
3632
|
-
if (
|
|
3633
|
-
target.path = removeDotSegments(
|
|
3632
|
+
if (relative2.path[0] === "/") {
|
|
3633
|
+
target.path = removeDotSegments(relative2.path);
|
|
3634
3634
|
} else {
|
|
3635
3635
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3636
|
-
target.path = "/" +
|
|
3636
|
+
target.path = "/" + relative2.path;
|
|
3637
3637
|
} else if (!base.path) {
|
|
3638
|
-
target.path =
|
|
3638
|
+
target.path = relative2.path;
|
|
3639
3639
|
} else {
|
|
3640
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3640
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
|
|
3641
3641
|
}
|
|
3642
3642
|
target.path = removeDotSegments(target.path);
|
|
3643
3643
|
}
|
|
3644
|
-
target.query =
|
|
3644
|
+
target.query = relative2.query;
|
|
3645
3645
|
}
|
|
3646
3646
|
target.userinfo = base.userinfo;
|
|
3647
3647
|
target.host = base.host;
|
|
@@ -3649,7 +3649,7 @@ var require_fast_uri = __commonJS({
|
|
|
3649
3649
|
}
|
|
3650
3650
|
target.scheme = base.scheme;
|
|
3651
3651
|
}
|
|
3652
|
-
target.fragment =
|
|
3652
|
+
target.fragment = relative2.fragment;
|
|
3653
3653
|
return target;
|
|
3654
3654
|
}
|
|
3655
3655
|
function equal(uriA, uriB, options) {
|
|
@@ -3819,8 +3819,8 @@ var require_fast_uri = __commonJS({
|
|
|
3819
3819
|
}
|
|
3820
3820
|
var fastUri = {
|
|
3821
3821
|
SCHEMES,
|
|
3822
|
-
normalize,
|
|
3823
|
-
resolve:
|
|
3822
|
+
normalize: normalize2,
|
|
3823
|
+
resolve: resolve15,
|
|
3824
3824
|
resolveComponent,
|
|
3825
3825
|
equal,
|
|
3826
3826
|
serialize,
|
|
@@ -8862,8 +8862,8 @@ var require_resolve2 = __commonJS({
|
|
|
8862
8862
|
}
|
|
8863
8863
|
return count;
|
|
8864
8864
|
}
|
|
8865
|
-
function getFullPath(resolver, id = "",
|
|
8866
|
-
if (
|
|
8865
|
+
function getFullPath(resolver, id = "", normalize2) {
|
|
8866
|
+
if (normalize2 !== false)
|
|
8867
8867
|
id = normalizeId(id);
|
|
8868
8868
|
const p = resolver.parse(id);
|
|
8869
8869
|
return _getFullPath(resolver, p);
|
|
@@ -9611,7 +9611,7 @@ var require_compile2 = __commonJS({
|
|
|
9611
9611
|
const schOrFunc = root.refs[ref];
|
|
9612
9612
|
if (schOrFunc)
|
|
9613
9613
|
return schOrFunc;
|
|
9614
|
-
let _sch =
|
|
9614
|
+
let _sch = resolve15.call(this, root, ref);
|
|
9615
9615
|
if (_sch === void 0) {
|
|
9616
9616
|
const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
9617
9617
|
const { schemaId } = this.opts;
|
|
@@ -9638,7 +9638,7 @@ var require_compile2 = __commonJS({
|
|
|
9638
9638
|
function sameSchemaEnv(s1, s2) {
|
|
9639
9639
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
9640
9640
|
}
|
|
9641
|
-
function
|
|
9641
|
+
function resolve15(root, ref) {
|
|
9642
9642
|
let sch;
|
|
9643
9643
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
9644
9644
|
ref = sch;
|
|
@@ -13270,7 +13270,7 @@ var require_src = __commonJS({
|
|
|
13270
13270
|
// ../node_modules/depd/index.js
|
|
13271
13271
|
var require_depd = __commonJS({
|
|
13272
13272
|
"../node_modules/depd/index.js"(exports, module) {
|
|
13273
|
-
var
|
|
13273
|
+
var relative2 = __require("path").relative;
|
|
13274
13274
|
module.exports = depd;
|
|
13275
13275
|
var basePath = process.cwd();
|
|
13276
13276
|
function containsNamespace(str2, namespace) {
|
|
@@ -13462,7 +13462,7 @@ var require_depd = __commonJS({
|
|
|
13462
13462
|
return formatted;
|
|
13463
13463
|
}
|
|
13464
13464
|
function formatLocation(callSite) {
|
|
13465
|
-
return
|
|
13465
|
+
return relative2(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
|
|
13466
13466
|
}
|
|
13467
13467
|
function getStack() {
|
|
13468
13468
|
var limit = Error.stackTraceLimit;
|
|
@@ -17919,10 +17919,10 @@ var require_raw_body = __commonJS({
|
|
|
17919
17919
|
if (done) {
|
|
17920
17920
|
return readStream(stream, encoding, length, limit, wrap(done));
|
|
17921
17921
|
}
|
|
17922
|
-
return new Promise(function executor(
|
|
17922
|
+
return new Promise(function executor(resolve15, reject) {
|
|
17923
17923
|
readStream(stream, encoding, length, limit, function onRead(err, buf) {
|
|
17924
17924
|
if (err) return reject(err);
|
|
17925
|
-
|
|
17925
|
+
resolve15(buf);
|
|
17926
17926
|
});
|
|
17927
17927
|
});
|
|
17928
17928
|
}
|
|
@@ -27905,7 +27905,7 @@ var require_type_is = __commonJS({
|
|
|
27905
27905
|
module.exports = typeofrequest;
|
|
27906
27906
|
module.exports.is = typeis;
|
|
27907
27907
|
module.exports.hasBody = hasbody;
|
|
27908
|
-
module.exports.normalize =
|
|
27908
|
+
module.exports.normalize = normalize2;
|
|
27909
27909
|
module.exports.match = mimeMatch;
|
|
27910
27910
|
function typeis(value, types_) {
|
|
27911
27911
|
var i;
|
|
@@ -27925,7 +27925,7 @@ var require_type_is = __commonJS({
|
|
|
27925
27925
|
}
|
|
27926
27926
|
var type2;
|
|
27927
27927
|
for (i = 0; i < types.length; i++) {
|
|
27928
|
-
if (mimeMatch(
|
|
27928
|
+
if (mimeMatch(normalize2(type2 = types[i]), val)) {
|
|
27929
27929
|
return type2[0] === "+" || type2.indexOf("*") !== -1 ? val : type2;
|
|
27930
27930
|
}
|
|
27931
27931
|
}
|
|
@@ -27940,7 +27940,7 @@ var require_type_is = __commonJS({
|
|
|
27940
27940
|
var value = req.headers["content-type"];
|
|
27941
27941
|
return typeis(value, types);
|
|
27942
27942
|
}
|
|
27943
|
-
function
|
|
27943
|
+
function normalize2(type2) {
|
|
27944
27944
|
if (typeof type2 !== "string") {
|
|
27945
27945
|
return false;
|
|
27946
27946
|
}
|
|
@@ -31258,7 +31258,7 @@ var require_view = __commonJS({
|
|
|
31258
31258
|
var basename8 = path4.basename;
|
|
31259
31259
|
var extname3 = path4.extname;
|
|
31260
31260
|
var join19 = path4.join;
|
|
31261
|
-
var
|
|
31261
|
+
var resolve15 = path4.resolve;
|
|
31262
31262
|
module.exports = View;
|
|
31263
31263
|
function View(name, options) {
|
|
31264
31264
|
var opts = options || {};
|
|
@@ -31292,7 +31292,7 @@ var require_view = __commonJS({
|
|
|
31292
31292
|
debug('lookup "%s"', name);
|
|
31293
31293
|
for (var i = 0; i < roots.length && !path5; i++) {
|
|
31294
31294
|
var root = roots[i];
|
|
31295
|
-
var loc =
|
|
31295
|
+
var loc = resolve15(root, name);
|
|
31296
31296
|
var dir = dirname8(loc);
|
|
31297
31297
|
var file = basename8(loc);
|
|
31298
31298
|
path5 = this.resolve(dir, file);
|
|
@@ -31317,7 +31317,7 @@ var require_view = __commonJS({
|
|
|
31317
31317
|
});
|
|
31318
31318
|
sync = false;
|
|
31319
31319
|
};
|
|
31320
|
-
View.prototype.resolve = function
|
|
31320
|
+
View.prototype.resolve = function resolve16(dir, file) {
|
|
31321
31321
|
var ext = this.ext;
|
|
31322
31322
|
var path5 = join19(dir, file);
|
|
31323
31323
|
var stat = tryStat(path5);
|
|
@@ -33458,7 +33458,7 @@ var require_application = __commonJS({
|
|
|
33458
33458
|
var compileETag = require_utils4().compileETag;
|
|
33459
33459
|
var compileQueryParser = require_utils4().compileQueryParser;
|
|
33460
33460
|
var compileTrust = require_utils4().compileTrust;
|
|
33461
|
-
var
|
|
33461
|
+
var resolve15 = __require("node:path").resolve;
|
|
33462
33462
|
var once = require_once();
|
|
33463
33463
|
var Router = require_router();
|
|
33464
33464
|
var slice = Array.prototype.slice;
|
|
@@ -33512,7 +33512,7 @@ var require_application = __commonJS({
|
|
|
33512
33512
|
this.mountpath = "/";
|
|
33513
33513
|
this.locals.settings = this.settings;
|
|
33514
33514
|
this.set("view", View);
|
|
33515
|
-
this.set("views",
|
|
33515
|
+
this.set("views", resolve15("views"));
|
|
33516
33516
|
this.set("jsonp callback name", "callback");
|
|
33517
33517
|
if (env === "production") {
|
|
33518
33518
|
this.enable("view cache");
|
|
@@ -34970,9 +34970,9 @@ var require_send = __commonJS({
|
|
|
34970
34970
|
var util2 = __require("util");
|
|
34971
34971
|
var extname3 = path4.extname;
|
|
34972
34972
|
var join19 = path4.join;
|
|
34973
|
-
var
|
|
34974
|
-
var
|
|
34975
|
-
var
|
|
34973
|
+
var normalize2 = path4.normalize;
|
|
34974
|
+
var resolve15 = path4.resolve;
|
|
34975
|
+
var sep3 = path4.sep;
|
|
34976
34976
|
var BYTES_RANGE_REGEXP = /^ *bytes=/;
|
|
34977
34977
|
var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
|
|
34978
34978
|
var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
|
|
@@ -35000,7 +35000,7 @@ var require_send = __commonJS({
|
|
|
35000
35000
|
this._maxage = opts.maxAge || opts.maxage;
|
|
35001
35001
|
this._maxage = typeof this._maxage === "string" ? ms(this._maxage) : Number(this._maxage);
|
|
35002
35002
|
this._maxage = !isNaN(this._maxage) ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) : 0;
|
|
35003
|
-
this._root = opts.root ?
|
|
35003
|
+
this._root = opts.root ? resolve15(opts.root) : null;
|
|
35004
35004
|
}
|
|
35005
35005
|
util2.inherits(SendStream, Stream);
|
|
35006
35006
|
SendStream.prototype.error = function error2(status, err) {
|
|
@@ -35133,23 +35133,23 @@ var require_send = __commonJS({
|
|
|
35133
35133
|
var parts;
|
|
35134
35134
|
if (root !== null) {
|
|
35135
35135
|
if (path5) {
|
|
35136
|
-
path5 =
|
|
35136
|
+
path5 = normalize2("." + sep3 + path5);
|
|
35137
35137
|
}
|
|
35138
35138
|
if (UP_PATH_REGEXP.test(path5)) {
|
|
35139
35139
|
debug('malicious path "%s"', path5);
|
|
35140
35140
|
this.error(403);
|
|
35141
35141
|
return res;
|
|
35142
35142
|
}
|
|
35143
|
-
parts = path5.split(
|
|
35144
|
-
path5 =
|
|
35143
|
+
parts = path5.split(sep3);
|
|
35144
|
+
path5 = normalize2(join19(root, path5));
|
|
35145
35145
|
} else {
|
|
35146
35146
|
if (UP_PATH_REGEXP.test(path5)) {
|
|
35147
35147
|
debug('malicious path "%s"', path5);
|
|
35148
35148
|
this.error(403);
|
|
35149
35149
|
return res;
|
|
35150
35150
|
}
|
|
35151
|
-
parts =
|
|
35152
|
-
path5 =
|
|
35151
|
+
parts = normalize2(path5).split(sep3);
|
|
35152
|
+
path5 = resolve15(path5);
|
|
35153
35153
|
}
|
|
35154
35154
|
if (containsDotFile(parts)) {
|
|
35155
35155
|
debug('%s dotfile "%s"', this._dotfiles, path5);
|
|
@@ -35242,7 +35242,7 @@ var require_send = __commonJS({
|
|
|
35242
35242
|
var self = this;
|
|
35243
35243
|
debug('stat "%s"', path5);
|
|
35244
35244
|
fs3.stat(path5, function onstat(err, stat) {
|
|
35245
|
-
var pathEndsWithSep = path5[path5.length - 1] ===
|
|
35245
|
+
var pathEndsWithSep = path5[path5.length - 1] === sep3;
|
|
35246
35246
|
if (err && err.code === "ENOENT" && !extname3(path5) && !pathEndsWithSep) {
|
|
35247
35247
|
return next(err);
|
|
35248
35248
|
}
|
|
@@ -35527,7 +35527,7 @@ var require_response = __commonJS({
|
|
|
35527
35527
|
var cookie = require_cookie();
|
|
35528
35528
|
var send = require_send();
|
|
35529
35529
|
var extname3 = path4.extname;
|
|
35530
|
-
var
|
|
35530
|
+
var resolve15 = path4.resolve;
|
|
35531
35531
|
var vary = require_vary();
|
|
35532
35532
|
var { Buffer: Buffer2 } = __require("node:buffer");
|
|
35533
35533
|
var res = Object.create(http.ServerResponse.prototype);
|
|
@@ -35733,7 +35733,7 @@ var require_response = __commonJS({
|
|
|
35733
35733
|
}
|
|
35734
35734
|
opts = Object.create(opts);
|
|
35735
35735
|
opts.headers = headers;
|
|
35736
|
-
var fullPath = !opts.root ?
|
|
35736
|
+
var fullPath = !opts.root ? resolve15(path5) : path5;
|
|
35737
35737
|
return this.sendFile(fullPath, opts, done);
|
|
35738
35738
|
};
|
|
35739
35739
|
res.contentType = res.type = function contentType(type2) {
|
|
@@ -35982,7 +35982,7 @@ var require_serve_static = __commonJS({
|
|
|
35982
35982
|
var encodeUrl = require_encodeurl();
|
|
35983
35983
|
var escapeHtml = require_escape_html();
|
|
35984
35984
|
var parseUrl = require_parseurl();
|
|
35985
|
-
var
|
|
35985
|
+
var resolve15 = __require("path").resolve;
|
|
35986
35986
|
var send = require_send();
|
|
35987
35987
|
var url = __require("url");
|
|
35988
35988
|
module.exports = serveStatic;
|
|
@@ -36001,7 +36001,7 @@ var require_serve_static = __commonJS({
|
|
|
36001
36001
|
throw new TypeError("option setHeaders must be function");
|
|
36002
36002
|
}
|
|
36003
36003
|
opts.maxage = opts.maxage || opts.maxAge || 0;
|
|
36004
|
-
opts.root =
|
|
36004
|
+
opts.root = resolve15(root);
|
|
36005
36005
|
var onDirectory = redirect ? createRedirectDirectoryListener() : createNotFoundDirectoryListener();
|
|
36006
36006
|
return function serveStatic2(req, res, next) {
|
|
36007
36007
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
@@ -36695,8 +36695,8 @@ var require_main = __commonJS({
|
|
|
36695
36695
|
const shortPaths = [];
|
|
36696
36696
|
for (const filePath of optionPaths) {
|
|
36697
36697
|
try {
|
|
36698
|
-
const
|
|
36699
|
-
shortPaths.push(
|
|
36698
|
+
const relative2 = path4.relative(process.cwd(), filePath);
|
|
36699
|
+
shortPaths.push(relative2);
|
|
36700
36700
|
} catch (e) {
|
|
36701
36701
|
if (debug) {
|
|
36702
36702
|
_debug(`Failed to load ${filePath} ${e.message}`);
|
|
@@ -36992,7 +36992,7 @@ var init_temp_dir = __esm({
|
|
|
36992
36992
|
import { clearTimeout as clearTimeout2, setTimeout as setTimeout2 } from "timers";
|
|
36993
36993
|
function waitForProcessReady(child, name, opts) {
|
|
36994
36994
|
const timeoutMs = opts?.timeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
|
|
36995
|
-
return new Promise((
|
|
36995
|
+
return new Promise((resolve15, reject) => {
|
|
36996
36996
|
let settled = false;
|
|
36997
36997
|
const cleanup = () => {
|
|
36998
36998
|
settled = true;
|
|
@@ -37006,13 +37006,13 @@ function waitForProcessReady(child, name, opts) {
|
|
|
37006
37006
|
if (settled) return;
|
|
37007
37007
|
logger.debug(`${name}: ready (stderr output detected)`);
|
|
37008
37008
|
cleanup();
|
|
37009
|
-
|
|
37009
|
+
resolve15();
|
|
37010
37010
|
};
|
|
37011
37011
|
const onStdout = () => {
|
|
37012
37012
|
if (settled) return;
|
|
37013
37013
|
logger.debug(`${name}: ready (stdout output detected)`);
|
|
37014
37014
|
cleanup();
|
|
37015
|
-
|
|
37015
|
+
resolve15();
|
|
37016
37016
|
};
|
|
37017
37017
|
const onError = (error2) => {
|
|
37018
37018
|
if (settled) return;
|
|
@@ -37028,7 +37028,7 @@ function waitForProcessReady(child, name, opts) {
|
|
|
37028
37028
|
if (settled) return;
|
|
37029
37029
|
logger.warn(`${name}: readiness timeout (${timeoutMs} ms) \u2014 proceeding anyway`);
|
|
37030
37030
|
cleanup();
|
|
37031
|
-
|
|
37031
|
+
resolve15();
|
|
37032
37032
|
}, timeoutMs);
|
|
37033
37033
|
child.stderr?.on("data", onStderr);
|
|
37034
37034
|
child.stdout?.on("data", onStdout);
|
|
@@ -37196,7 +37196,7 @@ var init_language_server = __esm({
|
|
|
37196
37196
|
method,
|
|
37197
37197
|
params
|
|
37198
37198
|
};
|
|
37199
|
-
return new Promise((
|
|
37199
|
+
return new Promise((resolve15, reject) => {
|
|
37200
37200
|
const timer = setTimeout3(() => {
|
|
37201
37201
|
if (this.pendingResponses.has(id)) {
|
|
37202
37202
|
this.pendingResponses.delete(id);
|
|
@@ -37210,7 +37210,7 @@ var init_language_server = __esm({
|
|
|
37210
37210
|
},
|
|
37211
37211
|
resolve: (val) => {
|
|
37212
37212
|
clearTimeout3(timer);
|
|
37213
|
-
|
|
37213
|
+
resolve15(val);
|
|
37214
37214
|
}
|
|
37215
37215
|
});
|
|
37216
37216
|
this.sendMessage(message);
|
|
@@ -37299,7 +37299,7 @@ var init_language_server = __esm({
|
|
|
37299
37299
|
throw new Error("Language server is not initialized");
|
|
37300
37300
|
}
|
|
37301
37301
|
const documentUri = uri || pathToFileURL(join2(getProjectTmpDir("lsp-eval"), "eval.ql")).href;
|
|
37302
|
-
return new Promise((
|
|
37302
|
+
return new Promise((resolve15, reject) => {
|
|
37303
37303
|
let diagnosticsReceived = false;
|
|
37304
37304
|
const timeout = setTimeout3(() => {
|
|
37305
37305
|
if (!diagnosticsReceived) {
|
|
@@ -37315,7 +37315,7 @@ var init_language_server = __esm({
|
|
|
37315
37315
|
this.sendNotification("textDocument/didClose", {
|
|
37316
37316
|
textDocument: { uri: documentUri }
|
|
37317
37317
|
});
|
|
37318
|
-
|
|
37318
|
+
resolve15(params.diagnostics);
|
|
37319
37319
|
}
|
|
37320
37320
|
};
|
|
37321
37321
|
this.on("diagnostics", diagnosticsHandler);
|
|
@@ -37375,6 +37375,28 @@ var init_language_server = __esm({
|
|
|
37375
37375
|
});
|
|
37376
37376
|
return this.normalizeLocations(result);
|
|
37377
37377
|
}
|
|
37378
|
+
/**
|
|
37379
|
+
* Get document symbols (i.e. top-level declarations) for a file.
|
|
37380
|
+
* Returns a hierarchical DocumentSymbol[] when the server supports it, or a
|
|
37381
|
+
* flat SymbolInformation[] otherwise. Top-level symbols are the root nodes
|
|
37382
|
+
* of the returned array.
|
|
37383
|
+
*/
|
|
37384
|
+
async getDocumentSymbols(params) {
|
|
37385
|
+
if (!this.isInitialized) {
|
|
37386
|
+
throw new Error("Language server is not initialized");
|
|
37387
|
+
}
|
|
37388
|
+
if (!this.isRunning()) {
|
|
37389
|
+
throw new Error("Language server process is not running");
|
|
37390
|
+
}
|
|
37391
|
+
const result = await this.sendRequest("textDocument/documentSymbol", params);
|
|
37392
|
+
if (!result || !Array.isArray(result) || result.length === 0) {
|
|
37393
|
+
return [];
|
|
37394
|
+
}
|
|
37395
|
+
if ("selectionRange" in result[0]) {
|
|
37396
|
+
return result;
|
|
37397
|
+
}
|
|
37398
|
+
return result;
|
|
37399
|
+
}
|
|
37378
37400
|
/**
|
|
37379
37401
|
* Open a text document in the language server.
|
|
37380
37402
|
* The document must be opened before requesting completions, definitions, etc.
|
|
@@ -37430,22 +37452,22 @@ var init_language_server = __esm({
|
|
|
37430
37452
|
} catch (error2) {
|
|
37431
37453
|
logger.warn("Error during graceful shutdown:", error2);
|
|
37432
37454
|
}
|
|
37433
|
-
await new Promise((
|
|
37455
|
+
await new Promise((resolve15) => {
|
|
37434
37456
|
const timer = setTimeout3(() => {
|
|
37435
37457
|
if (this.server) {
|
|
37436
37458
|
this.server.kill("SIGTERM");
|
|
37437
37459
|
}
|
|
37438
|
-
|
|
37460
|
+
resolve15();
|
|
37439
37461
|
}, 1e3);
|
|
37440
37462
|
if (this.server) {
|
|
37441
37463
|
this.server.once("exit", () => {
|
|
37442
37464
|
clearTimeout3(timer);
|
|
37443
37465
|
this.server = null;
|
|
37444
|
-
|
|
37466
|
+
resolve15();
|
|
37445
37467
|
});
|
|
37446
37468
|
} else {
|
|
37447
37469
|
clearTimeout3(timer);
|
|
37448
|
-
|
|
37470
|
+
resolve15();
|
|
37449
37471
|
}
|
|
37450
37472
|
});
|
|
37451
37473
|
this.isInitialized = false;
|
|
@@ -37535,8 +37557,8 @@ var init_query_server = __esm({
|
|
|
37535
37557
|
method,
|
|
37536
37558
|
params
|
|
37537
37559
|
};
|
|
37538
|
-
return new Promise((
|
|
37539
|
-
this.pendingRequests.set(id, { reject, resolve:
|
|
37560
|
+
return new Promise((resolve15, reject) => {
|
|
37561
|
+
this.pendingRequests.set(id, { reject, resolve: resolve15 });
|
|
37540
37562
|
try {
|
|
37541
37563
|
this.sendRaw(message);
|
|
37542
37564
|
} catch (error2) {
|
|
@@ -37550,7 +37572,7 @@ var init_query_server = __esm({
|
|
|
37550
37572
|
reject(new Error(`Query server request timeout for method: ${method}`));
|
|
37551
37573
|
}
|
|
37552
37574
|
}, timeoutMs);
|
|
37553
|
-
const originalResolve =
|
|
37575
|
+
const originalResolve = resolve15;
|
|
37554
37576
|
const originalReject = reject;
|
|
37555
37577
|
const wrapped = {
|
|
37556
37578
|
reject: (err) => {
|
|
@@ -37578,23 +37600,23 @@ var init_query_server = __esm({
|
|
|
37578
37600
|
} catch (error2) {
|
|
37579
37601
|
logger.warn("Error during query server graceful shutdown:", error2);
|
|
37580
37602
|
}
|
|
37581
|
-
await new Promise((
|
|
37603
|
+
await new Promise((resolve15) => {
|
|
37582
37604
|
const timer = setTimeout4(() => {
|
|
37583
37605
|
if (this.process) {
|
|
37584
37606
|
this.process.kill("SIGTERM");
|
|
37585
37607
|
this.process = null;
|
|
37586
37608
|
}
|
|
37587
|
-
|
|
37609
|
+
resolve15();
|
|
37588
37610
|
}, 2e3);
|
|
37589
37611
|
if (this.process) {
|
|
37590
37612
|
this.process.once("exit", () => {
|
|
37591
37613
|
clearTimeout4(timer);
|
|
37592
37614
|
this.process = null;
|
|
37593
|
-
|
|
37615
|
+
resolve15();
|
|
37594
37616
|
});
|
|
37595
37617
|
} else {
|
|
37596
37618
|
clearTimeout4(timer);
|
|
37597
|
-
|
|
37619
|
+
resolve15();
|
|
37598
37620
|
}
|
|
37599
37621
|
});
|
|
37600
37622
|
}
|
|
@@ -37755,9 +37777,9 @@ var init_cli_server = __esm({
|
|
|
37755
37777
|
* @returns The stdout output from the command.
|
|
37756
37778
|
*/
|
|
37757
37779
|
runCommand(args) {
|
|
37758
|
-
return new Promise((
|
|
37780
|
+
return new Promise((resolve15, reject) => {
|
|
37759
37781
|
const execute = () => {
|
|
37760
|
-
this.executeCommand({ args, reject, resolve:
|
|
37782
|
+
this.executeCommand({ args, reject, resolve: resolve15 });
|
|
37761
37783
|
};
|
|
37762
37784
|
if (this.commandInProgress) {
|
|
37763
37785
|
this.commandQueue.push(execute);
|
|
@@ -37780,23 +37802,23 @@ var init_cli_server = __esm({
|
|
|
37780
37802
|
} catch (error2) {
|
|
37781
37803
|
logger.warn("Error during CLI server shutdown request:", error2);
|
|
37782
37804
|
}
|
|
37783
|
-
await new Promise((
|
|
37805
|
+
await new Promise((resolve15) => {
|
|
37784
37806
|
const timer = setTimeout5(() => {
|
|
37785
37807
|
if (this.process) {
|
|
37786
37808
|
this.process.kill("SIGTERM");
|
|
37787
37809
|
this.process = null;
|
|
37788
37810
|
}
|
|
37789
|
-
|
|
37811
|
+
resolve15();
|
|
37790
37812
|
}, 2e3);
|
|
37791
37813
|
if (this.process) {
|
|
37792
37814
|
this.process.once("exit", () => {
|
|
37793
37815
|
clearTimeout5(timer);
|
|
37794
37816
|
this.process = null;
|
|
37795
|
-
|
|
37817
|
+
resolve15();
|
|
37796
37818
|
});
|
|
37797
37819
|
} else {
|
|
37798
37820
|
clearTimeout5(timer);
|
|
37799
|
-
|
|
37821
|
+
resolve15();
|
|
37800
37822
|
}
|
|
37801
37823
|
});
|
|
37802
37824
|
this.commandInProgress = false;
|
|
@@ -38041,11 +38063,11 @@ var init_server_manager = __esm({
|
|
|
38041
38063
|
async warmUpLanguageServer() {
|
|
38042
38064
|
try {
|
|
38043
38065
|
const { packageRootDir: packageRootDir2 } = await Promise.resolve().then(() => (init_package_paths(), package_paths_exports));
|
|
38044
|
-
const { resolve:
|
|
38066
|
+
const { resolve: resolve15 } = await import("path");
|
|
38045
38067
|
const config2 = {
|
|
38046
38068
|
checkErrors: "ON_CHANGE",
|
|
38047
38069
|
loglevel: "WARN",
|
|
38048
|
-
searchPath:
|
|
38070
|
+
searchPath: resolve15(packageRootDir2, "ql")
|
|
38049
38071
|
};
|
|
38050
38072
|
logger.info("Warming up language server (background JVM start)...");
|
|
38051
38073
|
await this.getLanguageServer(config2);
|
|
@@ -40527,8 +40549,8 @@ var require_adm_zip = __commonJS({
|
|
|
40527
40549
|
return null;
|
|
40528
40550
|
}
|
|
40529
40551
|
function fixPath(zipPath) {
|
|
40530
|
-
const { join: join19, normalize, sep:
|
|
40531
|
-
return join19(".",
|
|
40552
|
+
const { join: join19, normalize: normalize2, sep: sep3 } = pth.posix;
|
|
40553
|
+
return join19(".", normalize2(sep3 + zipPath.split("\\").join(sep3) + sep3));
|
|
40532
40554
|
}
|
|
40533
40555
|
function filenameFilter(filterfn) {
|
|
40534
40556
|
if (filterfn instanceof RegExp) {
|
|
@@ -40923,10 +40945,10 @@ var require_adm_zip = __commonJS({
|
|
|
40923
40945
|
* @param {function|string} [props.namefix] - optional function to help fix filename
|
|
40924
40946
|
*/
|
|
40925
40947
|
addLocalFolderPromise: function(localPath2, props) {
|
|
40926
|
-
return new Promise((
|
|
40948
|
+
return new Promise((resolve15, reject) => {
|
|
40927
40949
|
this.addLocalFolderAsync2(Object.assign({ localPath: localPath2 }, props), (err, done) => {
|
|
40928
40950
|
if (err) reject(err);
|
|
40929
|
-
if (done)
|
|
40951
|
+
if (done) resolve15(this);
|
|
40930
40952
|
});
|
|
40931
40953
|
});
|
|
40932
40954
|
},
|
|
@@ -41113,12 +41135,12 @@ var require_adm_zip = __commonJS({
|
|
|
41113
41135
|
keepOriginalPermission = get_Bool(false, keepOriginalPermission);
|
|
41114
41136
|
overwrite = get_Bool(false, overwrite);
|
|
41115
41137
|
if (!callback) {
|
|
41116
|
-
return new Promise((
|
|
41138
|
+
return new Promise((resolve15, reject) => {
|
|
41117
41139
|
this.extractAllToAsync(targetPath, overwrite, keepOriginalPermission, function(err) {
|
|
41118
41140
|
if (err) {
|
|
41119
41141
|
reject(err);
|
|
41120
41142
|
} else {
|
|
41121
|
-
|
|
41143
|
+
resolve15(this);
|
|
41122
41144
|
}
|
|
41123
41145
|
});
|
|
41124
41146
|
});
|
|
@@ -41216,11 +41238,11 @@ var require_adm_zip = __commonJS({
|
|
|
41216
41238
|
*/
|
|
41217
41239
|
writeZipPromise: function(targetFileName, props) {
|
|
41218
41240
|
const { overwrite, perm } = Object.assign({ overwrite: true }, props);
|
|
41219
|
-
return new Promise((
|
|
41241
|
+
return new Promise((resolve15, reject) => {
|
|
41220
41242
|
if (!targetFileName && opts.filename) targetFileName = opts.filename;
|
|
41221
41243
|
if (!targetFileName) reject("ADM-ZIP: ZIP File Name Missing");
|
|
41222
41244
|
this.toBufferPromise().then((zipData) => {
|
|
41223
|
-
const ret = (done) => done ?
|
|
41245
|
+
const ret = (done) => done ? resolve15(done) : reject("ADM-ZIP: Wasn't able to write zip file");
|
|
41224
41246
|
filetools.writeFileToAsync(targetFileName, zipData, overwrite, perm, ret);
|
|
41225
41247
|
}, reject);
|
|
41226
41248
|
});
|
|
@@ -41229,8 +41251,8 @@ var require_adm_zip = __commonJS({
|
|
|
41229
41251
|
* @returns {Promise<Buffer>} A promise to the Buffer.
|
|
41230
41252
|
*/
|
|
41231
41253
|
toBufferPromise: function() {
|
|
41232
|
-
return new Promise((
|
|
41233
|
-
_zip.toAsyncBuffer(
|
|
41254
|
+
return new Promise((resolve15, reject) => {
|
|
41255
|
+
_zip.toAsyncBuffer(resolve15, reject);
|
|
41234
41256
|
});
|
|
41235
41257
|
},
|
|
41236
41258
|
/**
|
|
@@ -53328,7 +53350,7 @@ var Protocol = class {
|
|
|
53328
53350
|
return;
|
|
53329
53351
|
}
|
|
53330
53352
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
53331
|
-
await new Promise((
|
|
53353
|
+
await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
|
|
53332
53354
|
options?.signal?.throwIfAborted();
|
|
53333
53355
|
}
|
|
53334
53356
|
} catch (error2) {
|
|
@@ -53345,7 +53367,7 @@ var Protocol = class {
|
|
|
53345
53367
|
*/
|
|
53346
53368
|
request(request, resultSchema, options) {
|
|
53347
53369
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
53348
|
-
return new Promise((
|
|
53370
|
+
return new Promise((resolve15, reject) => {
|
|
53349
53371
|
const earlyReject = (error2) => {
|
|
53350
53372
|
reject(error2);
|
|
53351
53373
|
};
|
|
@@ -53423,7 +53445,7 @@ var Protocol = class {
|
|
|
53423
53445
|
if (!parseResult.success) {
|
|
53424
53446
|
reject(parseResult.error);
|
|
53425
53447
|
} else {
|
|
53426
|
-
|
|
53448
|
+
resolve15(parseResult.data);
|
|
53427
53449
|
}
|
|
53428
53450
|
} catch (error2) {
|
|
53429
53451
|
reject(error2);
|
|
@@ -53684,12 +53706,12 @@ var Protocol = class {
|
|
|
53684
53706
|
}
|
|
53685
53707
|
} catch {
|
|
53686
53708
|
}
|
|
53687
|
-
return new Promise((
|
|
53709
|
+
return new Promise((resolve15, reject) => {
|
|
53688
53710
|
if (signal.aborted) {
|
|
53689
53711
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
53690
53712
|
return;
|
|
53691
53713
|
}
|
|
53692
|
-
const timeoutId = setTimeout(
|
|
53714
|
+
const timeoutId = setTimeout(resolve15, interval);
|
|
53693
53715
|
signal.addEventListener("abort", () => {
|
|
53694
53716
|
clearTimeout(timeoutId);
|
|
53695
53717
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -54789,7 +54811,7 @@ var McpServer = class {
|
|
|
54789
54811
|
let task = createTaskResult.task;
|
|
54790
54812
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
54791
54813
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
54792
|
-
await new Promise((
|
|
54814
|
+
await new Promise((resolve15) => setTimeout(resolve15, pollInterval));
|
|
54793
54815
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
54794
54816
|
if (!updatedTask) {
|
|
54795
54817
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -55432,12 +55454,12 @@ var StdioServerTransport = class {
|
|
|
55432
55454
|
this.onclose?.();
|
|
55433
55455
|
}
|
|
55434
55456
|
send(message) {
|
|
55435
|
-
return new Promise((
|
|
55457
|
+
return new Promise((resolve15) => {
|
|
55436
55458
|
const json2 = serializeMessage(message);
|
|
55437
55459
|
if (this._stdout.write(json2)) {
|
|
55438
|
-
|
|
55460
|
+
resolve15();
|
|
55439
55461
|
} else {
|
|
55440
|
-
this._stdout.once("drain",
|
|
55462
|
+
this._stdout.once("drain", resolve15);
|
|
55441
55463
|
}
|
|
55442
55464
|
});
|
|
55443
55465
|
}
|
|
@@ -55870,7 +55892,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
55870
55892
|
});
|
|
55871
55893
|
if (!chunk) {
|
|
55872
55894
|
if (i === 1) {
|
|
55873
|
-
await new Promise((
|
|
55895
|
+
await new Promise((resolve15) => setTimeout(resolve15));
|
|
55874
55896
|
maxReadCount = 3;
|
|
55875
55897
|
continue;
|
|
55876
55898
|
}
|
|
@@ -56366,9 +56388,9 @@ data:
|
|
|
56366
56388
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
56367
56389
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
56368
56390
|
if (this._enableJsonResponse) {
|
|
56369
|
-
return new Promise((
|
|
56391
|
+
return new Promise((resolve15) => {
|
|
56370
56392
|
this._streamMapping.set(streamId, {
|
|
56371
|
-
resolveJson:
|
|
56393
|
+
resolveJson: resolve15,
|
|
56372
56394
|
cleanup: () => {
|
|
56373
56395
|
this._streamMapping.delete(streamId);
|
|
56374
56396
|
}
|
|
@@ -56703,7 +56725,7 @@ var import_express = __toESM(require_express2(), 1);
|
|
|
56703
56725
|
var import_cors = __toESM(require_lib3(), 1);
|
|
56704
56726
|
var import_dotenv = __toESM(require_main(), 1);
|
|
56705
56727
|
import { realpathSync as realpathSync2 } from "fs";
|
|
56706
|
-
import { resolve as
|
|
56728
|
+
import { resolve as resolve14 } from "path";
|
|
56707
56729
|
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
56708
56730
|
|
|
56709
56731
|
// src/lib/cli-tool-registry.ts
|
|
@@ -57272,6 +57294,11 @@ function registerCLITool(server, definition) {
|
|
|
57272
57294
|
positionalArgs = [...positionalArgs, query];
|
|
57273
57295
|
}
|
|
57274
57296
|
break;
|
|
57297
|
+
case "codeql_resolve_library-path":
|
|
57298
|
+
if (query) {
|
|
57299
|
+
options.query = query;
|
|
57300
|
+
}
|
|
57301
|
+
break;
|
|
57275
57302
|
case "codeql_resolve_queries":
|
|
57276
57303
|
if (directory) {
|
|
57277
57304
|
positionalArgs = [...positionalArgs, directory];
|
|
@@ -62790,19 +62817,19 @@ var codeqlResolveLanguagesTool = {
|
|
|
62790
62817
|
// src/tools/codeql/resolve-library-path.ts
|
|
62791
62818
|
var codeqlResolveLibraryPathTool = {
|
|
62792
62819
|
name: "codeql_resolve_library-path",
|
|
62793
|
-
description: "Resolve
|
|
62820
|
+
description: "Resolve paths to source code for all libraries used by, or available to, the given CodeQL query or qll file.",
|
|
62794
62821
|
command: "codeql",
|
|
62795
62822
|
subcommand: "resolve library-path",
|
|
62796
62823
|
inputSchema: {
|
|
62797
|
-
|
|
62824
|
+
query: external_exports.string().describe("Path to a .ql or .qll file for the context to perform resolution for."),
|
|
62798
62825
|
format: external_exports.enum(["text", "json", "betterjson"]).optional().describe("Output format for library path information"),
|
|
62799
62826
|
verbose: external_exports.boolean().optional().describe("Enable verbose output"),
|
|
62800
62827
|
additionalArgs: external_exports.array(external_exports.string()).optional().describe("Additional command-line arguments")
|
|
62801
62828
|
},
|
|
62802
62829
|
examples: [
|
|
62803
|
-
"codeql resolve library-path --
|
|
62804
|
-
"codeql resolve library-path --format=json --
|
|
62805
|
-
"codeql resolve library-path --format=betterjson"
|
|
62830
|
+
"codeql resolve library-path --query=/path/to/query.ql",
|
|
62831
|
+
"codeql resolve library-path --format=json --query=/path/to/query.ql",
|
|
62832
|
+
"codeql resolve library-path --format=betterjson --query=/path/to/query.ql"
|
|
62806
62833
|
],
|
|
62807
62834
|
resultProcessor: defaultCLIResultProcessor
|
|
62808
62835
|
};
|
|
@@ -62826,6 +62853,24 @@ var codeqlResolveMetadataTool = {
|
|
|
62826
62853
|
resultProcessor: defaultCLIResultProcessor
|
|
62827
62854
|
};
|
|
62828
62855
|
|
|
62856
|
+
// src/tools/codeql/resolve-packs.ts
|
|
62857
|
+
var codeqlResolvePacksTool = {
|
|
62858
|
+
name: "codeql_resolve_packs",
|
|
62859
|
+
description: "Resolve packs available within a project directory, provided as a search path, and the source roots of those available packs.",
|
|
62860
|
+
command: "codeql",
|
|
62861
|
+
subcommand: "resolve packs",
|
|
62862
|
+
inputSchema: {
|
|
62863
|
+
"search-path": external_exports.string().describe('The project root, to search packs available in the project. Typically the ".", or the current working directory.'),
|
|
62864
|
+
format: external_exports.enum(["text", "json", "betterjson"]).optional().describe("Output format for qlref resolution"),
|
|
62865
|
+
verbose: createCodeQLSchemas.verbose(),
|
|
62866
|
+
additionalArgs: createCodeQLSchemas.additionalArgs()
|
|
62867
|
+
},
|
|
62868
|
+
examples: [
|
|
62869
|
+
"codeql resolve packs --search-path=."
|
|
62870
|
+
],
|
|
62871
|
+
resultProcessor: defaultCLIResultProcessor
|
|
62872
|
+
};
|
|
62873
|
+
|
|
62829
62874
|
// src/tools/codeql/resolve-qlref.ts
|
|
62830
62875
|
var codeqlResolveQlrefTool = {
|
|
62831
62876
|
name: "codeql_resolve_qlref",
|
|
@@ -63435,6 +63480,7 @@ function registerCodeQLTools(server) {
|
|
|
63435
63480
|
registerCLITool(server, codeqlResolveLanguagesTool);
|
|
63436
63481
|
registerCLITool(server, codeqlResolveLibraryPathTool);
|
|
63437
63482
|
registerCLITool(server, codeqlResolveMetadataTool);
|
|
63483
|
+
registerCLITool(server, codeqlResolvePacksTool);
|
|
63438
63484
|
registerCLITool(server, codeqlResolveQlrefTool);
|
|
63439
63485
|
registerCLITool(server, codeqlResolveQueriesTool);
|
|
63440
63486
|
registerCLITool(server, codeqlResolveTestsTool);
|
|
@@ -63967,6 +64013,39 @@ async function lspReferences(params) {
|
|
|
63967
64013
|
server.closeDocument(docUri);
|
|
63968
64014
|
}
|
|
63969
64015
|
}
|
|
64016
|
+
async function lspDocumentSymbols(params) {
|
|
64017
|
+
logger.info(`LSP documentSymbol for ${params.filePath}`);
|
|
64018
|
+
const server = await getInitializedLanguageServer({
|
|
64019
|
+
serverOptions: { searchPath: params.searchPath },
|
|
64020
|
+
workspaceUri: params.workspaceUri
|
|
64021
|
+
});
|
|
64022
|
+
const paramsWithPosition = {
|
|
64023
|
+
character: 0,
|
|
64024
|
+
line: 0,
|
|
64025
|
+
...params
|
|
64026
|
+
};
|
|
64027
|
+
const { absPath, docUri } = prepareDocumentPosition(paramsWithPosition);
|
|
64028
|
+
await openDocumentForPosition(server, paramsWithPosition, absPath, docUri);
|
|
64029
|
+
try {
|
|
64030
|
+
return await server.getDocumentSymbols({ textDocument: { uri: docUri } });
|
|
64031
|
+
} finally {
|
|
64032
|
+
server.closeDocument(docUri);
|
|
64033
|
+
}
|
|
64034
|
+
}
|
|
64035
|
+
function extractNamesFromDocumentSymbols(symbols) {
|
|
64036
|
+
let symbolNames = [];
|
|
64037
|
+
function collectSymbolNames(symbols2) {
|
|
64038
|
+
symbols2.forEach((s) => {
|
|
64039
|
+
const sym = s;
|
|
64040
|
+
symbolNames.push(sym.name ?? "(unknown)");
|
|
64041
|
+
if ("children" in sym && Array.isArray(sym.children)) {
|
|
64042
|
+
collectSymbolNames(sym.children);
|
|
64043
|
+
}
|
|
64044
|
+
});
|
|
64045
|
+
}
|
|
64046
|
+
collectSymbolNames(symbols);
|
|
64047
|
+
return symbolNames;
|
|
64048
|
+
}
|
|
63970
64049
|
|
|
63971
64050
|
// src/tools/lsp/lsp-tools.ts
|
|
63972
64051
|
init_logger();
|
|
@@ -63988,6 +64067,12 @@ function toHandlerParams(input) {
|
|
|
63988
64067
|
workspaceUri: input.workspace_uri
|
|
63989
64068
|
};
|
|
63990
64069
|
}
|
|
64070
|
+
var lspFileParamsSchema = {
|
|
64071
|
+
file_content: external_exports.string().optional().describe("Optional file content override (reads from disk if omitted)"),
|
|
64072
|
+
file_path: external_exports.string().describe("Path to the CodeQL (.ql/.qll) file. Relative paths are resolved against the user workspace directory (see CODEQL_MCP_WORKSPACE)."),
|
|
64073
|
+
search_path: external_exports.string().optional().describe("Optional search path for CodeQL libraries"),
|
|
64074
|
+
workspace_uri: external_exports.string().optional().describe("Optional workspace URI for context (defaults to ./ql directory)")
|
|
64075
|
+
};
|
|
63991
64076
|
function registerLSPTools(server) {
|
|
63992
64077
|
registerLspDiagnosticsTool(server);
|
|
63993
64078
|
server.tool(
|
|
@@ -64083,6 +64168,42 @@ function registerLSPTools(server) {
|
|
|
64083
64168
|
}
|
|
64084
64169
|
}
|
|
64085
64170
|
);
|
|
64171
|
+
server.tool(
|
|
64172
|
+
"codeql_lsp_document_symbols",
|
|
64173
|
+
"List all top-level definitions (classes, predicates, modules) in a CodeQL file. Response contains location and type information unless names_only is set to true.",
|
|
64174
|
+
{
|
|
64175
|
+
names_only: external_exports.boolean().optional().describe("If true, returns only symbol names as a compact string array instead of full symbol objects. Use this when you only need to know what names a file defines."),
|
|
64176
|
+
...lspFileParamsSchema
|
|
64177
|
+
},
|
|
64178
|
+
async (input) => {
|
|
64179
|
+
try {
|
|
64180
|
+
const symbols = await lspDocumentSymbols({
|
|
64181
|
+
fileContent: input.file_content,
|
|
64182
|
+
filePath: input.file_path,
|
|
64183
|
+
searchPath: input.search_path,
|
|
64184
|
+
workspaceUri: input.workspace_uri
|
|
64185
|
+
});
|
|
64186
|
+
let result;
|
|
64187
|
+
if (input.names_only) {
|
|
64188
|
+
result = extractNamesFromDocumentSymbols(symbols);
|
|
64189
|
+
} else {
|
|
64190
|
+
result = symbols;
|
|
64191
|
+
}
|
|
64192
|
+
return {
|
|
64193
|
+
content: [{
|
|
64194
|
+
text: JSON.stringify({ symbolCount: result.length, symbols: result }, null, 2),
|
|
64195
|
+
type: "text"
|
|
64196
|
+
}]
|
|
64197
|
+
};
|
|
64198
|
+
} catch (error2) {
|
|
64199
|
+
logger.error("codeql_lsp_document_symbols error:", error2);
|
|
64200
|
+
return {
|
|
64201
|
+
content: [{ text: `Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`, type: "text" }],
|
|
64202
|
+
isError: true
|
|
64203
|
+
};
|
|
64204
|
+
}
|
|
64205
|
+
}
|
|
64206
|
+
);
|
|
64086
64207
|
}
|
|
64087
64208
|
|
|
64088
64209
|
// src/resources/languages/actions_ast.md
|
|
@@ -64257,7 +64378,12 @@ function registerLanguageResources(server) {
|
|
|
64257
64378
|
}
|
|
64258
64379
|
|
|
64259
64380
|
// src/prompts/workflow-prompts.ts
|
|
64260
|
-
import {
|
|
64381
|
+
import { access as access2 } from "fs/promises";
|
|
64382
|
+
import { basename as basename7, isAbsolute as isAbsolute7, normalize, relative, resolve as resolve13, sep as sep2 } from "path";
|
|
64383
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
64384
|
+
|
|
64385
|
+
// src/prompts/check-for-duplicated-code.prompt.md
|
|
64386
|
+
var check_for_duplicated_code_prompt_default = '---\nagent: agent\n---\n\n# Check for Duplicated Code\n\nUse the MCP server tools to identify classes, modules, and predicates defined in a\n`.ql` or `.qll` file and check for possible "duplicated code," where duplicated code\nis defined to be:\n\n- Reimplementing functionality that already exists in the standard library, or shared project `.qll` files, and\n- The local definition is identical, or semantically equivalent, or superior to the library definition, or\n- The local definition could be simplified by reusing the existing definition (e.g. a base class already exists that captures some of the shared logic)\n\nHere are some examples:\n\n```ql\nimport cpp\n\n// Duplicated: `StandardNamespace` already exists in the standard library and is identical\nclass NamespaceStd extends Namespace {\n NamespaceStd() { this.getName() = "std" }\n}\n\n// Duplicated: class should extend `Operator`, not `Function`\nclass ThrowingOperator extends Function {\n ThrowingOperator() {\n // Duplicated: this check is implied by using base class `Operator`\n this.getName().matches("%operator%") and\n and exists(ThrowExpr te |\n // Duplicated: this is equivalent to `te.getEnclosingFunction() = this`\n te.getParent*() = this.getAChild()\n )\n }\n\n // Duplicated: member predicate `getDeclaringType()` already does this.\n Class getDefiningClass() { ... }\n}\n\n// Duplicated: `ControlFlowNode.getASuccessor()` already exists in `cpp` and is superior\npredicate getASuccessor(Stmt a, Stmt b) {\n exists(Block b, int i | a = b.getChild(i) and b = b.getChild(i + 1))\n}\n\n// Duplicated: prefer to import `semmle.code.cpp.controlflow.Dominance`, defined in dependency pack `cpp-all`\npredicate dominates(Block a, Block b) { ... }\n```\n\nDuplicate code removal isn\'t done arbitrarily, but for several key reasons:\n\n- **Maintainability**: Duplicated code must be maintained separately, may diverge and have different bugs\n- **Simplicity**: Relying on existing definitions reduces the amount of code to read and understand\n- **Readability**: Existing definitions map wrap complex ideas into readable names\n- **Consistency**: A single source of truth makes for a more consistent user experience across queries\n- **Completeness/Correctness**: Recreating an already-existing definition can miss edge cases, resulting in false positives or false negatives\n\n## Use This Prompt When\n\n- A query file defines a class or predicate whose name sounds generic (e.g.\n `StandardNamespace`, `Callable`, `SecurityFeature`)\n- Refactoring a query that was written before a relevant library predicate existed\n- Reviewing a shared `.qll` file to check whether its helpers have been upstreamed\n into the standard library in a newer CodeQL version\n- Performing a code-quality audit across a suite of custom queries\n\n## Prerequisites\n\n1. The file path of the `.ql` or `.qll` file to audit for code duplication\n2. Understand which packs are imported by `qlpack.yml`\n3. Understand where the relevant language library packs are located (e.g. `~/.codeql`)\n4. Understand where project-specific library packs are located (e.g. `$LANGUAGE/lib` or `$LANGUAGE/common`)\n5. Understand where pack-specific shared `.qll` files are located (e.g. `$PACKROOT/common/*.qll`)\n\n## Overview of the Approach\n\nThe core idea is to enumerate every top-level name defined in the file under review.\nThen, find candidate `.qll` files, based on file name and path, that are available to\nthat `.ql` file in review. Then, enumerate the top-level names in each candidate\n`.qll` file, to find potential duplicates, dive further if necessary, and then report\nthe findings as code improvement recommendations to the user.\n\n1. **Read the file** to see its imports and top-level structure\n2. **Enumerate top-level definitions** with `codeql_lsp_document_symbols`\n3. **Find available .qll files** in the `.ql` file\'s pack, and its dependencies, including the standard library\n4. **Identify promising .qll file candidates** based on their file name and path\n5. **Enumerate top-level definitions in candidate `.qll` files** with `codeql_lsp_document_symbols`\n6. **Detect overlap, comparing definitions if unclear** (e.g. by using `find_predicate_position` and `find_class_position` tools)\n7. **Report findings** as a set of recommendations to the user about which definitions could be improved, by reusing which existing definitions\n\n## Step 1: Read the File and Note Its Imports\n\n```text\nTool: read_file\nParameters:\n file_path: /path/to/query.ql\n start_line: 1\n end_line: 60 # enough to see all imports\n```\n\nRecord every `import` statement. These are the namespaces the standard library\nexposes; duplication is only meaningful for libraries that are already imported (or\neasily importable).\n\n## Step 2: Enumerate Top-Level Definitions\n\nUse `codeql_lsp_document_symbols` to retrieve every class, predicate, and module\ndefined at the top level of the file in a single call:\n\n```text\nTool: codeql_lsp_document_symbols\nParameters:\n file_path: /path/to/query.ql\n names_only: true # provides significantly smaller response payload\n workspace_uri: /path/to/pack-root # directory containing codeql-pack.yml\n```\n\nThe response contains a `symbols` array. Each entry has:\n\n- `name` \u2014 the identifier as written in source\n- `kind` \u2014 numeric SymbolKind (5 = Class, 12 = Function/predicate, 2 = Module, etc.)\n- `range` \u2014 the full definition range (0-based lines)\n- `selectionRange` \u2014 the range of just the name token\n- `children` \u2014 nested members (for classes and modules)\n\nTop-level symbols are the root nodes of the array; `children` hold member\npredicates and fields.\n\n## Step 3. Read the filesystem to find candidate library `.qll` files\n\nRun the tool `codeql_resolve_library-path` with the given ql query file to find where\nthe available library sources live.\n\nFor each source root, run `find $ROOT -name "*.qll"` to find all `.qll` files\navailable in that pack. Do not preemptively filter this list of qll files. The names\nof the files may be broad or nondescriptive. Read all file names for each project to\nunderstand its structure and responsibilities before proceeding to step 3d.\n\nChoose promising candidate `.qll` files you found in the previous step. Pick\ncandidates that may potentially define behavior relevant to the current query and its\nenumerated definitions, based on the candidate filename, path, and priority.\n\nPrioritize as follows:\n\n- `.qll` files in the same directory as the query file have the absolute highest priority\n- `.qll` files in the same pack have the next extremely high priority\n- `.qll` files in project-specific library packs have the very high priority\n- `.qll` files in downloaded direct dependencies have standard priority\n- `.qll` files in transitive dependencies have the least priority.\n\n## Step 4: Identify candidate terms in the candidate library `.qll` files\n\nEnumerate the top-level definitions for each candidate `.qll` file using the tool\n`codeql_lsp_document_symbols` again. Some top levels may clearly match the name or\npurpose of a definition in the query file, while others may only appear as possibly\nrelated.\n\n```text\nTool: codeql_lsp_document_symbols\nParameters:\n file_path: /path/to/library/file.qll\n workspace_uri: /path/to/pack-root\n```\n\n## Step 5: Perform final overlap analysis\n\nFor each promising candidate, identify the predicate or class definitions that may overlap. One definition will be in the query file (`.ql`) and the other will be in the library file (`.qll`).\n\nUsing the tools `find_predicate_position` and `find_class_position`, you can retrieve the full definition of each predicate or class, and compare them to determine whether they are identical, equivalent, overlapping, or if one is a superior implementation that could be reused by the query file.\n\nDutifully analyze whether the shared library file definition would reduce code duplication in the categories identified before: maintenance, simplicity, readability, consistency, and completeness/correctness. Consider contextual factors such as comments explaining why the local definition differs from the library one, or whether the local definition is a thin wrapper around the library definition that adds value (e.g. by improving naming or adding extra checks).\n\nDo not go on a wild goose chase trying to find every possible overlap. Consider the likelihood of overlap based on the broadness of functionality, and the value that would be brought be reuse. Do not waste significant time on unimportant or unlikely overlaps.\n\n## Step 6: Report Findings\n\nFor each duplicate found, report:\n\n| Local name | Local file | import path | Notes |\n| ------------------- | ------------- | -------------------------------- | ---------- |\n| `StandardNamespace` | `query.ql:42` | already imported in `import cpp` | Identical |\n| `myHelper` | `query.ql:80` | `import myproject.Helpers` | Equivalent |\n| `myHelper` | `query.ql:80` | `import myproject.Helpers` | Equivalent |\n\nRecommend one of:\n\n- **Replace**: remove the local definition and use the standard definition directly instead\n- **Integrate**: refactor and simplify the local definition by making use of the standard definition\n- **Annotate**: add comments to the local definition to explain how it differs from the standard definition and why the duplication is necessary\n\nAdditionally, report if any issues came up in using the tools, or finding the qll files.\n\nFor each concept for which no duplicate was found, provide at most a **brief** description of what the concept is. Do not provide a long detailed explanation of a non-finding.\n\n# Conclusion\n\nDo **not** perform any updates to any code during this analysis.\n\nAs you work through completing this task, ask yourself:\n\n- Have I changed any code, even though that was not my task, or am I about to? Stop, do not change any code!\n- Did I sufficiently analyze the definitions such that I likely found most overlapping definitions?\n- Will my suggestions improve the maintainability, simplicity, readability, consistency, or completeness/correctness of the codebase?\n- Did I report my findings clearly?\n- Did I use the suggested LLM tools to their fullest extent?\n- Did I follow the steps in the recommended order, and not skip any steps?\n- Did I report any issues I had in finding the relevant `.qll` files, or using the tools to analyze definitions?\n';
|
|
64261
64387
|
|
|
64262
64388
|
// src/prompts/document-codeql-query.prompt.md
|
|
64263
64389
|
var document_codeql_query_prompt_default = '---\nagent: agent\n---\n\n# Document a CodeQL Query\n\nThis prompt guides you through creating or updating documentation for a CodeQL query file. The documentation is stored as a sibling file to the query with a standardized markdown format.\n\n## Purpose\n\nThe `document_codeql_query` prompt creates/updates **query documentation files** for a specific version of a CodeQL query. Documentation files are stored alongside the query file and provide concise yet comprehensive information about what the query does.\n\nFor creating **workshop learning content** with detailed explanations and visual diagrams, use the `explain_codeql_query` prompt instead.\n\n## Required Inputs\n\n- **queryPath**: Path to the CodeQL query file (`.ql` or `.qlref`)\n- **language**: Target programming language (actions, cpp, csharp, go, java, javascript, python, ruby, swift)\n\n## Documentation File Conventions\n\n### File Location and Naming\n\nFor a query file `QueryFileBaseName.ql`, the documentation file should be:\n\n- **Primary**: `QueryFileBaseName.md` (markdown format, preferred)\n- **Legacy**: `QueryFileBaseName.qhelp` (XML-based query help format)\n\nDocumentation files are **siblings** to the query file (same directory).\n\n### Handling Existing Documentation\n\n1. **No documentation exists**: Create new `QueryFileBaseName.md` file\n2. **`.md` file exists**: Update the existing markdown file\n3. **`.qhelp` file exists**: Use #codeql_generate_query-help tool to convert to markdown, then update\n\n## Workflow Checklist\n\nUse the following MCP server tools to gather context before creating documentation:\n\n### Phase 1: Query Discovery\n\n- [ ] **Step 1: Locate query files**\n - Tool: #find_codeql_query_files\n - Parameters: `queryPath` = provided query path\n - Gather: Query source file path, existing documentation files, test files\n - Check: Does `QueryFileBaseName.md` or `QueryFileBaseName.qhelp` exist?\n\n- [ ] **Step 2: Read query metadata**\n - Tool: #codeql_resolve_metadata\n - Parameters: `query` = query file path\n - Gather: @name, @description, @kind, @id, @tags, @precision, @severity\n\n### Phase 2: Convert Existing qhelp (if needed)\n\n- [ ] **Step 3: Convert qhelp to markdown** (only if `.qhelp` exists)\n - Tool: #codeql_generate_query-help\n - Parameters: `query` = query file path, `format` = "markdown"\n - Use output as starting point for updated documentation\n\n### Phase 3: Gather Query Context\n\n- [ ] **Step 4: Validate query structure**\n - Tool: #validate_codeql_query\n - Parameters: `query` = query source code\n - Gather: Structural validation, suggestions\n - Note: This is a heuristic check only \u2014 for full validation, use #codeql_query_compile\n\n- [ ] **Step 5: Explore query types** (if deeper understanding needed)\n - Tool: #codeql_lsp_definition \u2014 navigate to class/predicate definitions\n - Tool: #codeql_lsp_completion \u2014 explore member predicates on types used in the query\n - Parameters: `file_path`, `line` (0-based), `character` (0-based), `workspace_uri` (pack root)\n - Run #codeql_pack_install first \u2014 LSP tools require resolved dependencies\n\n- [ ] **Step 6: Run tests** (if tests exist from Step 1)\n - Tool: #codeql_test_run\n - Parameters: `tests` = test directories\n - Gather: Pass/fail status, confirms query behavior\n\n### Phase 4: Create/Update Documentation\n\nBased on gathered context, create or update the documentation file.\n\n## Documentation Format\n\nThe documentation file (`QueryFileBaseName.md`) should follow this standardized format with these sections:\n\n### Section 1: Title and Description\n\n- H1 heading with the query name from @name metadata\n- One paragraph description from @description, expanded if needed\n\n### Section 2: Metadata Table\n\nA table with these rows:\n\n- ID: The @id value in backticks\n- Kind: The @kind value (problem, path-problem, etc.)\n- Severity: The @severity value\n- Precision: The @precision value\n- Tags: The @tags values\n\n### Section 3: Overview\n\nConcise explanation of what vulnerability/issue this query detects and why it matters. 2-4 sentences.\n\n### Section 4: Recommendation\n\nBrief guidance on how developers should fix issues flagged by this query. Include code patterns to use or avoid.\n\n### Section 5: Example\n\nTwo subsections:\n\n- **Vulnerable Code**: A code block showing a pattern that would be flagged by this query\n- **Fixed Code**: A code block showing the corrected version of the code\n\nUse the appropriate language identifier for the code blocks (e.g., `javascript`, `python`, `java`).\n\n### Section 6: References\n\nA list of links to:\n\n- Relevant CWE if security query\n- Relevant documentation or standards\n- CodeQL documentation for related concepts\n\n## Output Actions\n\nAfter generating documentation content:\n\n1. **For new documentation**: Create the file at `[QueryDirectory]/QueryFileBaseName.md`\n2. **For existing `.md` file**: Update the file with new content, preserving any custom sections\n3. **For existing `.qhelp` file**: Create new `.md` file (keeping `.qhelp` for backward compatibility)\n\n## Important Notes\n\n- **Be concise**: Documentation should be brief but complete. This is reference documentation, not tutorial content.\n- **Keep it current**: Documentation should reflect the current behavior of the query.\n- **Use examples from tests**: If unit tests exist, use those code patterns as examples.\n- **Standard format**: Always use the format above for consistency across all query documentation.\n- **Metadata accuracy**: Ensure documented metadata matches actual query metadata.\n- **For workshops**: Use `explain_codeql_query` prompt when creating workshop content that requires deeper explanations and visual diagrams.\n';
|
|
@@ -64265,6 +64391,9 @@ var document_codeql_query_prompt_default = '---\nagent: agent\n---\n\n# Document
|
|
|
64265
64391
|
// src/prompts/explain-codeql-query.prompt.md
|
|
64266
64392
|
var explain_codeql_query_prompt_default = '---\nagent: agent\n---\n\n# Explain a CodeQL Query (Workshop Learning Content)\n\nThis prompt guides you through gathering comprehensive context about a CodeQL query using MCP server tools, then generating detailed explanations suitable for CodeQL workshop learning content.\n\n## Purpose\n\nThe `explain_codeql_query` prompt is designed for creating **learning content** for CodeQL workshops and workshop improvements. It produces in-depth, educational explanations of how a query works, including visual diagrams.\n\nFor creating/updating **query documentation files** (`.md` or `.qhelp`), use the `document_codeql_query` prompt instead.\n\n## Required Inputs\n\n- **queryPath**: Path to the CodeQL query file (`.ql` or `.qlref`)\n- **language**: Target programming language (actions, cpp, csharp, go, java, javascript, python, ruby, swift)\n- **databasePath** (optional): Path to a real CodeQL database for profiling\n\n## Agent AI Instructions\n\n**Critical**: The evaluator logs and profiler outputs from CodeQL can be very large files. Use the MCP server tools to analyze them efficiently:\n\n- Use #profile_codeql_query_from_logs to extract pipeline timing, predicate evaluation order, tuple count progressions, RA operations, and dependencies from evaluator logs \u2014 this single tool provides all evaluator log analysis\n- Use #search_ql_code to find predicates, classes, or patterns across QL library files\n\n## Choosing a Database\n\nSeveral steps below require a CodeQL database. Determine which database to use:\n\n1. **User-provided `databasePath`** \u2014 use this if provided and valid (check with #codeql_resolve_database).\n2. **Test database** \u2014 if Step 1 finds tests, run them in Step 3 to create a `.testproj` database.\n3. **No database available** \u2014 skip Steps 4-6, and base the explanation on source code analysis only.\n\nStore the chosen database path as `$DB` for use in Steps 4-6.\n\n## Workflow Checklist\n\nYou MUST use the following MCP server tools in sequence to gather context before generating your explanation:\n\n### Phase 1: Query Discovery and Validation\n\n- [ ] **Step 1: Locate query files**\n - Tool: #find_codeql_query_files\n - Parameters: `queryPath` = provided query path\n - Gather: Query source file, test files, expected results, metadata location\n - Note: If tests exist, record the test directory path for later steps\n\n- [ ] **Step 2: Validate query structure**\n - Tool: #validate_codeql_query\n - Parameters: `query` = contents of the query file\n - Gather: Structural validation results, heuristic warnings/suggestions\n\n### Phase 2: Test Execution and Database Creation\n\n- [ ] **Step 3: Run existing tests** (if tests exist from Step 1)\n - Tool: #codeql_test_run\n - Parameters: `tests` = array of test directories from Step 1\n - Purpose: Ensures test database is created and current with test code\n - Gather: Test pass/fail status, test database path (`.testproj` directory)\n - **If no tests exist**: Skip this step. Use user-provided `databasePath` as `$DB`.\n\n### Phase 3: Code Structure Analysis (requires `$DB`)\n\nSkip this phase entirely if no database is available.\n\n- [ ] **Step 4: Generate PrintAST output**\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintAST"`\n - `queryLanguage`: provided language\n - `database`: `$DB`\n - `sourceFiles`: test source file names (or representative source files from the database)\n - `format`: `"graphtext"`\n - Gather: AST hierarchy showing code structure representation\n\n- [ ] **Step 5: Generate PrintCFG output** (for key functions)\n - Tool: #codeql_query_run\n - Parameters:\n - `queryName`: `"PrintCFG"`\n - `queryLanguage`: provided language\n - `database`: `$DB`\n - `sourceFunction`: key function name(s) from test code or query source\n - `format`: `"graphtext"`\n - Gather: Control flow graph showing execution paths\n\n### Phase 4: Query Profiling and Evaluation Order (requires `$DB`)\n\nSkip this phase entirely if no database is available.\n\n- [ ] **Step 6a: Run the query with evaluator logging**\n - Tool: #codeql_query_run (or #codeql_database_analyze)\n - Run the query against `$DB` with evaluator logging enabled\n - The tool returns the path to the evaluator log file (`.jsonl`)\n\n- [ ] **Step 6b: Profile from evaluator logs**\n - Tool: #profile_codeql_query_from_logs\n - Parameters:\n - `evaluatorLog`: path to the evaluator log file from Step 6a\n - Gather: Pipeline execution order, predicate timing data, tuple counts\n - **Critical**: This reveals the actual bottom-up evaluation order of predicates\n\n- [ ] **Step 7: Quick evaluate specific predicates** (as needed)\n - First, locate the predicate: Tool: #find_predicate_position with `file` and `name`\n - Then evaluate: Tool: #quick_evaluate with `file`, `db`, and `symbol`\n - Use when: You need more context on how a specific predicate or class behaves\n - Note: #find_class_position finds `class` definitions only, not `module` definitions\n - Note: #find_predicate_position returns 1-based positions; LSP tools use 0-based\n\n### Phase 5: Generate Explanation\n\nBased on all gathered context, generate your explanation with both **verbal** and **visual** components.\n\n## Key Aspects to Analyze in Profiler Output\n\nUnderstanding the query profiler output is critical for explaining how the query actually works. Look for:\n\n1. **Evaluation Order**: Which predicates are evaluated first (base predicates) vs last (dependent predicates)\n2. **Pipeline Timing**: Time taken for each pipeline stage - indicates complexity\n3. **Tuple Counts**: Number of results at each stage - shows data flow volume\n4. **RA Operations**: The relational algebra operations (SCAN, JOIN, AGGREGATE) reveal query execution strategy\n5. **Dependencies**: Which predicates depend on others (shown by evaluation order)\n\n## Output Format\n\n### Verbal Explanation Structure\n\nGenerate a single markdown document with these sections in order:\n\n1. **Query Overview** \u2014 2-3 sentence summary of what the query detects and why it matters.\n2. **Query Metadata** \u2014 Table with: Name, Description, Kind, ID, Tags, Precision, Severity (from `@` annotations).\n3. **What This Query Detects** \u2014 Security implications (CWE/OWASP if applicable), why the pattern is problematic, real-world attack scenarios.\n4. **How the Query Works** \u2014 Two subsections:\n - **Bottom-Up Evaluation Order**: Evaluation timeline table (Order, Predicate/Pipeline, Time ms, Tuples) derived from profiler data. Explain that CodeQL evaluates bottom-up.\n - **Key Components**: Imports, classes and characteristic predicates, helper predicates, data flow configuration (sources, sinks, sanitizers, additional flow steps), main query `from`/`where`/`select`.\n5. **Test Code Analysis** (if database was available) \u2014 AST structure insights from PrintAST, control flow insights from PrintCFG.\n6. **Example Patterns** \u2014 Positive test cases (should match) and negative test cases (should not match) with explanations.\n7. **Performance Characteristics** (if profiler data available) \u2014 Most expensive predicates, highest tuple counts, optimization opportunities.\n8. **Limitations and Edge Cases** \u2014 Patterns the query might miss, known false positive scenarios.\n\n### Visual Explanation: Mermaid Evaluation Diagram\n\nGenerate a `mermaid` `flowchart BU` (bottom-up) diagram showing the evaluation order derived from profiler data. Guidelines:\n\n- Use subgraphs to group predicates by evaluation phase (base, intermediate, flow analysis, final select)\n- Label nodes with actual predicate/class names from the query\n- Show dependency edges between predicates\n- Annotate expensive operations with timing (e.g., `[500ms]`)\n- Direction must be `BU` to reflect bottom-up evaluation\n\n## Important Notes\n\n- **Always use tools first**: Do not generate explanations based only on query source code. Use the MCP tools to gather actual runtime data.\n- **Use the profiler tool for evaluator logs**: Evaluator logs can be huge. Use #profile_codeql_query_from_logs which returns compact JSON with per-predicate metrics and a line-indexed detail file. Use `read_file` with the `detailLines` ranges from the response to access full RA operations and tuple progressions for any predicate \u2014 do not use CLI grep or read log files directly.\n- **Evaluation order matters**: CodeQL evaluates bottom-up, not top-down. The profiler output reveals the true execution order.\n- **Focus on learning**: This is for workshop content, so include educational context and explanations suitable for CodeQL learners.\n- **Visual diagrams**: Always include a mermaid diagram showing evaluation order.\n- **Reference documentation**: For actual QL evaluation semantics, see [Evaluation of QL programs](https://codeql.github.com/docs/ql-language-reference/evaluation-of-ql-programs/)\n';
|
|
64267
64393
|
|
|
64394
|
+
// src/prompts/find-overlapping-queries.prompt.md
|
|
64395
|
+
var find_overlapping_queries_prompt_default = '---\nagent: agent\n---\n\n# Find Overlapping Queries and Libraries\n\nUse the MCP server tools to discover existing `.ql` query files and `.qll` library\nfiles whose content may overlap with a new query design \u2014 **before** writing any new\ncode \u2014 so that reusable building blocks can be identified and incorporated rather than\nreimplemented from scratch.\n\n"Overlap" here includes:\n\n- A shared library (`.qll`) that already models a concept central to the new query\n (e.g. a class representing placement-new expressions, or a predicate identifying\n types with non-trivial destructors)\n- An existing query (`.ql`) whose logic intersects the new query\'s domain (e.g. an\n existing query that already detects misuse of placement-new, or already reasons\n about destructor triviality)\n- Utility predicates or classes in either file type that could be imported and reused\n directly, reducing the amount of new code needed\n\n## Use This Prompt When\n\n- Starting a new query and wanting to know what library support already exists for\n the concepts it must model\n- Unsure whether a query (or a close variant) already exists in the codebase\n- Looking for concrete QL code examples of how to model a particular language\n construct or pattern in the target language\n- Performing an audit of a query suite to identify potential consolidation\n opportunities\n\n## Prerequisites\n\n1. A clear description of the new query\'s **purpose and target constructs** (e.g.\n "detect placement-new calls on objects whose type has a non-trivial destructor")\n2. The **target language** (e.g. `cpp`, `java`, `python`)\n3. Optionally, the **pack root** \u2014 the directory containing `codeql-pack.yml` for the\n pack that will own the new query; this is used to locate project-specific libraries\n and existing queries in the same suite\n\n## Overview of the Approach\n\nThe core idea is to decompose the new query\'s description into a set of **key\nconcepts**, then search the available `.qll` library files and existing `.ql` query\nfiles for content that relates to those concepts. Finally, report which files contain\nrelevant material and highlight the specific classes, predicates, or modules that\ncould be reused.\n\n1. **Extract key concepts** from the query description\n2. **Resolve available library sources** for the target language and pack\n3. **Find candidate `.qll` files** \u2014 ranked by naming proximity to the key concepts\n4. **Enumerate symbols in candidate `.qll` files** to identify reusable definitions\n5. **Find candidate `.ql` query files** in the same pack and its dependencies\n6. **Inspect overlapping queries** to understand their scope and find reusable logic\n7. **Report findings** \u2014 which files and which specific definitions are most relevant\n\n## Step 1: Extract Key Concepts\n\nBefore touching any tools, decompose the query description into a set of\n**searchable key concepts**: concrete noun phrases (AST node types, predicates,\nlanguage-specific constructs) that are likely to appear in file names or class/\npredicate names.\n\nFor example, "placement-new calls on objects whose type has a non-trivial destructor"\ndecomposes into:\n\n- `PlacementNew` / `placement_new` / `NewExpr`\n- `NonTrivial` / `non_trivial` / `Trivial`\n- `Destructor` / `destructor` / `Dtor`\n\nRecord these key concept terms \u2014 they drive every subsequent search.\n\n## Step 2: Resolve Available Library Sources\n\nUse `codeql_resolve_library-path` to find every source root visible to the target\npack. If no pack root is known yet, use either a representative existing `.ql` file\nin the same language, or the language\'s default library root (typically\n`~/.codeql/packages`).\n\n```text\nTool: codeql_resolve_library-path\nParameters:\n query: /path/to/any-existing-query.ql # or use --additional-packs\n format: json\n```\n\nRead the returned list of source roots. For each root, list the directory tree to\nunderstand the overall structure before narrowing your search:\n\n```text\nTool: list_directory\nParameters:\n path: /returned/source/root\n```\n\nDo **not** preemptively discard any source root based on its name alone. The\nstructure of each root must be understood before filtering.\n\n## Step 3: Find Candidate `.qll` Files\n\nFor each source root, gather all `.qll` file paths:\n\n```text\nShell: find /source/root -name "*.qll" | sort\n```\n\nScan every path using the key concept terms from Step 1. A file is a **candidate**\nif its path or filename contains one or more of those terms, or if it lives in a\ndirectory whose name suggests domain relevance (e.g. `memory/`, `destructors/`,\n`initialization/`).\n\nPrioritize candidates as follows:\n\n- `.qll` files in the same directory as the planned new query \u2014 **highest priority**\n- `.qll` files elsewhere in the same pack \u2014 **very high priority**\n- `.qll` files in project-specific library packs \u2014 **high priority**\n- `.qll` files in downloaded direct dependencies \u2014 **standard priority**\n- `.qll` files in transitive dependencies \u2014 **lower priority**\n\nAim to identify the **top 5\u201310 most promising candidate `.qll` files** before\nproceeding. Breadth is important here: a small `.qll` file named `Destructor.qll`\nis more immediately useful than a 5000-line `Types.qll`, but both should be noted if\nrelevant.\n\n## Step 4: Enumerate Symbols in Candidate `.qll` Files\n\nFor each shortlisted candidate `.qll` file, retrieve its top-level definitions:\n\n```text\nTool: codeql_lsp_document_symbols\nParameters:\n file_path: /path/to/Candidate.qll\n names_only: true\n workspace_uri: /path/to/pack-root # plain directory containing codeql-pack.yml\n```\n\nNote: `workspace_uri` must be a **plain directory path**, not a `file://` URI. All\nline/character positions returned by LSP tools are **0-based**.\n\nScan the returned `symbols` array for classes, predicates, and modules whose names\ncontain or are closely related to the key concept terms. For any promising symbol,\nexpand its definition using `find_predicate_position` or `find_class_position` and\nthen `read_file` to inspect the actual implementation.\n\nNote: `find_predicate_position` and `find_class_position` use **1-based** line\nnumbers.\n\nRecord each relevant symbol as:\n\n```\nFile: /path/to/Candidate.qll\nSymbol: ClassName / predicateName\nRelevance: <which key concept it addresses>\nSummary: <one-sentence description of what it does>\n```\n\n## Step 5: Find Candidate Existing `.ql` Query Files\n\nExisting queries are an equally important source of reusable logic.\n\nFirst, list all `.ql` files in the target pack (and any closely related packs) using\nthe MCP tool `codeql_resolve_queries` or a recursive directory listing:\n\n```text\nTool: codeql_resolve_queries\nParameters:\n directory: /path/to/pack-root\n format: json\n```\n\nOr equivalently:\n\n```text\nShell: find /pack-root -name "*.ql" | sort\n```\n\nScan every file name using the key concept terms from Step 1. A query file is a\n**candidate** if:\n\n- Its file name contains one or more key concept terms, or\n- It lives in a subdirectory whose name suggests domain overlap, or\n- Its containing rule directory (e.g. `RULE-X-Y-Z/`) has a description that overlaps\n with the new query\'s domain (check `qlpack.yml` query metadata or directory names\n if available)\n\n## Step 6: Inspect Overlapping Query Files\n\nFor each candidate `.ql` file identified in Step 5:\n\n1. Read the file header (first 60 lines) to understand what the query detects:\n\n ```text\n Tool: read_file\n Parameters:\n file_path: /path/to/ExistingQuery.ql\n start_line: 1\n end_line: 60\n ```\n\n2. Use `codeql_lsp_document_symbols` to enumerate its own top-level definitions:\n\n ```text\n Tool: codeql_lsp_document_symbols\n Parameters:\n file_path: /path/to/ExistingQuery.ql\n names_only: true\n workspace_uri: /path/to/pack-root\n ```\n\n3. For any symbol whose name or kind maps to a key concept, retrieve its full\n definition using `find_predicate_position` / `find_class_position` and `read_file`\n to determine whether the logic could be reused by the new query.\n\n4. Note the import statements in the existing query. Any shared `.qll` imported\n there is a strong signal that the same import could benefit the new query.\n\nAim to identify **which specific lines or definitions** are most relevant \u2014 not just\nwhich file \u2014 so that the report gives actionable guidance.\n\n## Step 7: Report Findings\n\n### Relevant Library Definitions (`.qll` files)\n\nPresent a table of reusable definitions found in library files:\n\n| Symbol | File | Kind | Key Concept | Notes |\n| ---------------------- | ---------------------------------------------------------- | --------- | ------------ | ------------------------------------------------ |\n| `PlacementNewExpr` | `semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll:12` | class | PlacementNew | Models placement-new allocation sites |\n| `hasTrivialDestructor` | `semmle/code/cpp/Type.qll:340` | predicate | Destructor | Returns true if the type\'s destructor is trivial |\n\nFor each entry, state:\n\n- **How to import it**: the `import` statement needed to access the symbol\n- **How it maps**: which part of the new query could use this definition\n- **Limitation** (if any): cases where the existing definition does not fully cover\n the new query\'s needs\n\n### Overlapping Existing Queries (`.ql` files)\n\nPresent a table of existing queries whose logic intersects:\n\n| Query file | Rule | What it detects | Overlap area |\n| ---------------------------- | -------------------- | ---------------------------------------------- | ---------------------------------------- |\n| `RULE-7-5-3/PlacementNew.ql` | MISRA C++ Rule 7.5.3 | Placement-new calls without matching destroy \u2014 | Placement-new enumeration, type analysis |\n\nFor each overlapping query, state:\n\n- **Shared logic**: the specific class or predicate definitions that could be lifted\n into a shared `.qll` or imported directly\n- **Divergence**: how the existing query\'s intent differs from the new query\'s intent,\n so the developer understands what cannot be reused directly\n\n### Summary Recommendation\n\nEnd with a short paragraph (3\u20135 sentences) summarising:\n\n1. Which existing definitions provide the **strongest starting points** for the new\n query\n2. Whether a **shared `.qll`** should be created to house logic that would otherwise\n be duplicated\n3. Which aspects of the new query appear to have **no existing foundation** and will\n require original implementation\n\n## Worked Example\n\n> **Query description**: Detect placement-new calls in C++ involving object types\n> that have a non-trivial destructor, because the caller is responsible for manually\n> invoking the destructor and may forget to do so.\n>\n> **Language**: `cpp`\n>\n> **Pack root**: `/workspace/cpp/misra/src`\n\n**Key concepts extracted**: `PlacementNew`, `NewExpr`, `NonTrivial`, `Trivial`,\n`Destructor`, `Dtor`\n\n**Step 2** \u2014 resolve library paths for a representative query:\n\n```text\nTool: codeql_resolve_library-path\nParameters:\n query: /workspace/cpp/misra/src/rules/RULE-7-5-1/SomeQuery.ql\n```\n\nReturns roots such as:\n\n- `/workspace/cpp/common/src` (project library)\n- `/workspace/cpp/misra/src` (pack being worked on)\n- `~/.codeql/packages/codeql/cpp-all/1.4.0` (standard library)\n\n**Step 3** \u2014 scanning `~/.codeql/packages/codeql/cpp-all/1.4.0` for `*.qll`:\n\nCandidates matching key concepts:\n\n- `semmle/code/cpp/exprs/New.qll` \u2014 contains `NewExpr`, likely covers placement-new\n- `semmle/code/cpp/Type.qll` \u2014 may contain destructor triviality predicates\n- `semmle/code/cpp/Destructor.qll` (if it exists) \u2014 direct match on `Destructor`\n\n**Step 4** \u2014 `codeql_lsp_document_symbols` on `New.qll`:\n\n```json\n{ "name": "NewExpr", "kind": 5 }\n{ "name": "NewArrayExpr", "kind": 5 }\n{ "name": "PlacementNewExpr","kind": 5 } \u2190 highly relevant\n```\n\n`PlacementNewExpr` in `New.qll` exactly models placement-new allocations \u2014\nthis class should be imported and used directly in the new query rather than\nreimplementing it.\n\n**Step 5** \u2014 scanning `/workspace/cpp/misra/src` for `*.ql`:\n\nCandidates matching key concepts:\n\n- `rules/RULE-12-2-1/DestructorMustBeCalledExplicitly.ql` \u2014 destructor relevance\n- `rules/RULE-6-2-2/PlacementNewLifetime.ql` \u2014 placement-new relevance\n\n**Step 6** \u2014 reading `PlacementNewLifetime.ql` header:\n\nThe file imports `semmle.code.cpp.exprs.New` and defines a local predicate\n`placementNewTarget()` that wraps `PlacementNewExpr.getAllocatedType()`.\nThis predicate and the surrounding type-resolution logic can serve as a template.\n\n# Conclusion\n\nDo **not** write or modify any code during this analysis.\n\nAs you work through this task, ask yourself:\n\n- Have I changed any code, even though that was not my task, or am I about to?\n Stop, do not change any code!\n- Did I extract enough key concepts to drive a thorough file-name search?\n- Did I inspect both library `.qll` files **and** existing `.ql` query files?\n- Did I identify specific symbols (not just files) that are relevant?\n- Did I report the import path needed to access each reusable symbol?\n- Did I summarise which parts of the new query still require original implementation?\n- Did I use the suggested tools to their fullest extent before concluding?\n- Did I report any difficulties encountered while resolving library paths or reading\n files?\n';
|
|
64396
|
+
|
|
64268
64397
|
// src/prompts/ql-lsp-iterative-development.prompt.md
|
|
64269
64398
|
var ql_lsp_iterative_development_prompt_default = '---\nagent: agent\n---\n\n# Iterative CodeQL Development with LSP Tools\n\nUse the MCP server tools from this prompt to iteratively develop and refine CodeQL queries using the LSP-powered tools.\nThese "iterative" tools work entirely through file paths and numeric positions.\nEvery operation is expressible as a tool call with explicit `file_path`, `line`, and `character` parameters.\nThus, this prompt can be used in any environment where the query files are on disk, and it does not require any special editor integration.\n\n## Use This Prompt When\n\n- Exploring unfamiliar CodeQL libraries to discover available classes and predicates\n- Incrementally building a query clause-by-clause with real-time feedback\n- Navigating from a type usage to its definition to understand its API\n- Finding all usages of a predicate to learn patterns from existing queries\n- Validating query fragments before assembling a complete query\n- Debugging individual predicates by evaluating them in isolation against a database\n\n## Prerequisites\n\n1. A CodeQL pack with `codeql-pack.yml` on disk\n2. Dependencies installed via #codeql_pack_install (pointing at the pack directory)\n3. Query files saved to disk (LSP tools operate on files, not inline strings)\n\n## Key Concept: Positions Are File Path + Line + Character\n\nAll LSP tools identify locations using three values:\n\n- `file_path`: absolute path to a `.ql` or `.qll` file\n- `line`: **0-based** line number (line 1 in the file = `line: 0`)\n- `character`: **0-based** column offset within that line\n\nThe `workspace_uri` parameter must point to the **pack root directory** (the folder\ncontaining `codeql-pack.yml`) for import resolution to work. Without it, completions\nand definitions for imported libraries will be empty.\n\n> **Critical**: LSP line/character positions are 0-based, but `read_file`,\n> #find_predicate_position, and #find_class_position return 1-based positions.\n> Always subtract 1 when passing their output to LSP tools.\n\n## Step 1: Discover Available Types with Completions\n\nUse #codeql_lsp_completion to explore what types and predicates are available at any\nposition in a query file. This replaces manual documentation browsing.\n\n**Example**: To see what classes are available in a `from` clause after `import javascript`:\n\n```text\nTool: codeql_lsp_completion\nParameters:\n file_path: /path/to/your/query.ql\n line: 9 # 0-based line of the `from` clause\n character: 5 # position after `from ` where you want completions\n workspace_uri: /path/to/pack-root # directory containing codeql-pack.yml\n```\n\nCompletions include class names with full documentation. For example, requesting\ncompletions in a JavaScript query\'s `from` clause returns 150+ types like\n`CallNode`, `PropWrite`, `RemoteFlowSource`, etc., each with docstrings.\n\n**Exploring member predicates**: To see what methods a variable offers, request\ncompletions after the dot. For example, if `pw` is typed as `DataFlow::PropWrite`,\nrequesting completions at the position after `pw.` returns all member predicates\nlike `getPropertyName()`, `getRhs()`, `getBase()`, `writes(base, prop, rhs)`,\neach with full signature and documentation.\n\n## Step 2: Navigate to Definitions\n\nUse #codeql_lsp_definition to find where a class, predicate, or module is defined.\nThis returns the file URI and line range of the definition \u2014 even into library pack\nfiles you haven\'t opened.\n\n```text\nTool: codeql_lsp_definition\nParameters:\n file_path: /path/to/your/query.ql\n line: 11 # 0-based line containing the symbol\n character: 30 # 0-based column within the symbol name\n workspace_uri: /path/to/pack-root\n```\n\n**Example**: Navigating to `RemoteFlowSource` at line 12, character 30 returns:\n\n```text\nuri: file:///.../.codeql/packages/codeql/javascript-all/2.6.19/\n semmle/javascript/security/dataflow/RemoteFlowSources.qll\nstartLine: 14, startCharacter: 17\n```\n\nYou can then read that file to understand the class\'s API. This is how you discover\nwhat predicates a type offers without documentation \u2014 go to the definition and read\nthe source.\n\n## Step 3: Find All References\n\nUse #codeql_lsp_references to find how a symbol is used across the workspace.\n\n```text\nTool: codeql_lsp_references\nParameters:\n file_path: /path/to/your/query.ql\n line: 11 # 0-based line\n character: 30 # 0-based column within the symbol\n workspace_uri: /path/to/pack-root\n```\n\n> **Scope note**: References are scoped to the pack identified by `workspace_uri`.\n> To find usages in library code, point `workspace_uri` to the library pack root.\n> For usages within your own pack only, point it to your pack root.\n\nThis is invaluable for learning how experienced query authors use a predicate \u2014\nfind real usage examples instead of guessing from documentation.\n\n## Step 4: Locate Symbols with Position Finders\n\nUse #find_predicate_position and #find_class_position to locate where a specific\nsymbol is defined in a file. These return **1-based** line/column positions.\n\n```text\nTool: find_predicate_position\nParameters:\n file: /path/to/your/query.ql\n name: isSource\nReturns: { start_line: 12, start_col: 13, end_line: 12, end_col: 20 }\n```\n\n> **Note**: #find_class_position finds `class` definitions only \u2014 it does not find\n> `module` definitions. Use #find_predicate_position for predicates inside modules,\n> or use #search_ql_code to search across QL files by text or regex pattern.\n\n**Combining with LSP tools**: To navigate to a predicate\'s definition in library code:\n\n1. Use #find_predicate_position to get its 1-based position\n2. Subtract 1 from line/col to convert to 0-based\n3. Pass to #codeql_lsp_definition to jump to the underlying type\n\n## Step 5: Quick-Evaluate Individual Predicates\n\nUse #quick_evaluate to evaluate a single predicate or class against a database\nwithout running the full query. This is the fastest way to debug whether a predicate\nmatches what you expect.\n\n```text\nTool: quick_evaluate\nParameters:\n file: /path/to/your/query.ql\n db: /path/to/test-database.testproj\n symbol: isSink\n output_path: /tmp/quickeval-results # optional, for inspecting bqrs output\n```\n\nThe tool evaluates just that symbol (predicate or class) and returns the result path.\nUse #codeql_bqrs_decode on the output to inspect results in CSV or JSON format.\n\n## Step 6: Validate at Multiple Levels\n\nUse the right validation tool for each situation:\n\n| Tool | Use When | Input | Resolves Imports? |\n| ----------------------- | --------------------------------------- | ------------------ | ------------------- |\n| #validate_codeql_query | Quick structural check | Inline QL string | No (heuristic only) |\n| #codeql_lsp_diagnostics | Syntax/semantic validation of fragments | Inline QL string | No |\n| #codeql_query_compile | Full compilation check | On-disk `.ql` file | Yes |\n| #codeql_test_run | End-to-end result validation | Test directory | Yes |\n\n**#codeql_lsp_diagnostics** validates QL syntax and semantics for inline code snippets,\nbut **cannot resolve `import` statements** (like `import javascript`). Use it for:\n\n- Checking predicate signatures and QL syntax\n- Verifying `from`/`where`/`select` clause structure\n- Catching type errors in import-free QL fragments\n\nFor queries with imports, always use #codeql_query_compile on the saved file.\n\n## Iterative Development Loop\n\n```text\n1. Write/modify a clause in the query file (save to disk)\n \u2193\n2. codeql_lsp_completion \u2192 verify context is valid (non-empty = good)\n \u2193\n3. codeql_query_compile \u2192 check for compilation errors\n \u2193\n4. codeql_test_run \u2192 validate against expected results\n \u2193\n5. If unexpected results: quick_evaluate on individual predicates\n \u2193\n6. If predicate is wrong: codeql_lsp_completion to explore the API\n \u2193\n7. If types are unclear: codeql_lsp_definition to read the source\n \u2193\n8. If stuck: codeql_lsp_references to find usage examples\n \u2193\n9. Repeat from step 1\n```\n\n## Worked Example: Building a Taint-Tracking Query\n\nThis example shows the tools in action for building a JavaScript XSS query.\n\n### 1. Create the query file and install dependencies\n\nWrite a `.ql` file with `import javascript` and a skeleton `from`/`where`/`select`.\nRun #codeql_pack_install on the pack directory.\n\n### 2. Explore sink types\n\nRequest completions in the `from` clause to discover `DataFlow::PropWrite`:\n\n```text\ncodeql_lsp_completion(file_path=..., line=9, character=5, workspace_uri=pack_root)\n\u2192 155 completions including PropWrite, CallNode, MethodCallNode, ...\n```\n\n### 3. Explore `PropWrite` member predicates\n\nAfter typing `pw.` in the `where` clause, request completions:\n\n```text\ncodeql_lsp_completion(file_path=..., line=12, character=9, workspace_uri=pack_root)\n\u2192 43 predicates: getPropertyName(), getRhs(), getBase(), writes(), ...\n```\n\n### 4. Navigate to `RemoteFlowSource` definition\n\n```text\ncodeql_lsp_definition(file_path=..., line=11, character=30, workspace_uri=pack_root)\n\u2192 RemoteFlowSources.qll line 14 in codeql/javascript-all\n```\n\n### 5. Compile and test incrementally\n\n```text\ncodeql_query_compile(query=file_path) \u2192 check for errors\ncodeql_test_run(tests=[test_dir], learn=true) \u2192 populate .expected files\n```\n\n### 6. Debug a predicate in isolation\n\n```text\nfind_predicate_position(file=..., name="isSink") \u2192 line 16, col 13\nquick_evaluate(file=..., db=test.testproj, symbol="isSink") \u2192 inspect results\n```\n\n## Important Notes\n\n- **All LSP tools use 0-based positions**. #find_class_position and\n #find_predicate_position return 1-based positions. Convert before combining.\n- **`workspace_uri` must be the pack root** (the directory containing\n `codeql-pack.yml`). Without it, completions and definitions will be empty.\n- **Run #codeql_pack_install first**. LSP tools require resolved dependencies.\n- **#codeql_lsp_diagnostics cannot resolve imports**. For `import javascript`\n and similar, use #codeql_query_compile on the on-disk file instead.\n- **#find_class_position finds `class` only**, not `module` definitions.\n Use #search_ql_code or #find_predicate_position for predicates inside modules.\n- **#codeql_lsp_references scope** depends on `workspace_uri`. Point it at\n a library pack root to find usages across library code.\n';
|
|
64270
64399
|
|
|
@@ -64291,8 +64420,10 @@ var workshop_creation_workflow_prompt_default = '---\nagent: agent\n---\n\n# Cre
|
|
|
64291
64420
|
|
|
64292
64421
|
// src/prompts/prompt-loader.ts
|
|
64293
64422
|
var PROMPT_TEMPLATES = {
|
|
64423
|
+
"check-for-duplicated-code.prompt.md": check_for_duplicated_code_prompt_default,
|
|
64294
64424
|
"document-codeql-query.prompt.md": document_codeql_query_prompt_default,
|
|
64295
64425
|
"explain-codeql-query.prompt.md": explain_codeql_query_prompt_default,
|
|
64426
|
+
"find-overlapping-queries.prompt.md": find_overlapping_queries_prompt_default,
|
|
64296
64427
|
"ql-lsp-iterative-development.prompt.md": ql_lsp_iterative_development_prompt_default,
|
|
64297
64428
|
"ql-tdd-advanced.prompt.md": ql_tdd_advanced_prompt_default,
|
|
64298
64429
|
"ql-tdd-basic.prompt.md": ql_tdd_basic_prompt_default,
|
|
@@ -64324,6 +64455,7 @@ function processPromptTemplate(template, variables) {
|
|
|
64324
64455
|
}
|
|
64325
64456
|
|
|
64326
64457
|
// src/prompts/workflow-prompts.ts
|
|
64458
|
+
init_package_paths();
|
|
64327
64459
|
init_logger();
|
|
64328
64460
|
var SUPPORTED_LANGUAGES = [
|
|
64329
64461
|
"actions",
|
|
@@ -64336,6 +64468,82 @@ var SUPPORTED_LANGUAGES = [
|
|
|
64336
64468
|
"ruby",
|
|
64337
64469
|
"swift"
|
|
64338
64470
|
];
|
|
64471
|
+
function markdownInlineCode(value) {
|
|
64472
|
+
const normalized = value.replace(/\r\n|\r|\n/g, " ");
|
|
64473
|
+
let maxRun = 0;
|
|
64474
|
+
let currentRun = 0;
|
|
64475
|
+
for (const ch of normalized) {
|
|
64476
|
+
if (ch === "`") {
|
|
64477
|
+
currentRun += 1;
|
|
64478
|
+
if (currentRun > maxRun) {
|
|
64479
|
+
maxRun = currentRun;
|
|
64480
|
+
}
|
|
64481
|
+
} else {
|
|
64482
|
+
currentRun = 0;
|
|
64483
|
+
}
|
|
64484
|
+
}
|
|
64485
|
+
const fence = "`".repeat(maxRun + 1);
|
|
64486
|
+
return `${fence}${normalized}${fence}`;
|
|
64487
|
+
}
|
|
64488
|
+
function blockedPathError(result, paramName) {
|
|
64489
|
+
const message = result.warning ?? `The provided ${paramName} could not be resolved safely and cannot be used.`;
|
|
64490
|
+
return {
|
|
64491
|
+
messages: [
|
|
64492
|
+
{
|
|
64493
|
+
role: "user",
|
|
64494
|
+
content: {
|
|
64495
|
+
type: "text",
|
|
64496
|
+
text: `${message}
|
|
64497
|
+
|
|
64498
|
+
The workflow cannot proceed because the ${paramName} is not allowed.`
|
|
64499
|
+
}
|
|
64500
|
+
}
|
|
64501
|
+
]
|
|
64502
|
+
};
|
|
64503
|
+
}
|
|
64504
|
+
async function resolvePromptFilePath(filePath, workspaceRoot) {
|
|
64505
|
+
if (!filePath || filePath.trim() === "") {
|
|
64506
|
+
return {
|
|
64507
|
+
resolvedPath: filePath ?? "",
|
|
64508
|
+
warning: "\u26A0 **File path is empty.** Please provide a valid file path."
|
|
64509
|
+
};
|
|
64510
|
+
}
|
|
64511
|
+
let effectivePath = filePath;
|
|
64512
|
+
if (/^file:\/\//i.test(filePath.trim())) {
|
|
64513
|
+
try {
|
|
64514
|
+
effectivePath = fileURLToPath3(filePath.trim());
|
|
64515
|
+
} catch {
|
|
64516
|
+
return {
|
|
64517
|
+
resolvedPath: "",
|
|
64518
|
+
blocked: true,
|
|
64519
|
+
warning: `\u26A0 **File path** \`${filePath}\` **is not a valid file URI.**`
|
|
64520
|
+
};
|
|
64521
|
+
}
|
|
64522
|
+
}
|
|
64523
|
+
const effectiveRoot = workspaceRoot ?? getUserWorkspaceDir();
|
|
64524
|
+
const normalizedPath = normalize(effectivePath);
|
|
64525
|
+
const inputWasAbsolute = isAbsolute7(normalizedPath);
|
|
64526
|
+
const absolutePath = inputWasAbsolute ? normalizedPath : resolve13(effectiveRoot, normalizedPath);
|
|
64527
|
+
if (!inputWasAbsolute) {
|
|
64528
|
+
const rel = relative(effectiveRoot, absolutePath);
|
|
64529
|
+
if (rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute7(rel)) {
|
|
64530
|
+
return {
|
|
64531
|
+
blocked: true,
|
|
64532
|
+
resolvedPath: "",
|
|
64533
|
+
warning: "\u26A0 **File path resolves outside the workspace root.** The path has been blocked for security."
|
|
64534
|
+
};
|
|
64535
|
+
}
|
|
64536
|
+
}
|
|
64537
|
+
try {
|
|
64538
|
+
await access2(absolutePath);
|
|
64539
|
+
} catch {
|
|
64540
|
+
return {
|
|
64541
|
+
resolvedPath: absolutePath,
|
|
64542
|
+
warning: `\u26A0 **File path** ${markdownInlineCode(filePath)} **does not exist.**`
|
|
64543
|
+
};
|
|
64544
|
+
}
|
|
64545
|
+
return { resolvedPath: absolutePath };
|
|
64546
|
+
}
|
|
64339
64547
|
var testDrivenDevelopmentSchema = external_exports.object({
|
|
64340
64548
|
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
|
|
64341
64549
|
queryName: external_exports.string().optional().describe("Name of the query to develop")
|
|
@@ -64354,23 +64562,23 @@ var workshopCreationWorkflowSchema = external_exports.object({
|
|
|
64354
64562
|
numStages: external_exports.coerce.number().optional().describe("Number of incremental stages (default: 4-8)")
|
|
64355
64563
|
});
|
|
64356
64564
|
var qlTddBasicSchema = external_exports.object({
|
|
64357
|
-
language: external_exports.enum(SUPPORTED_LANGUAGES).
|
|
64565
|
+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
|
|
64358
64566
|
queryName: external_exports.string().optional().describe("Name of the query to develop")
|
|
64359
64567
|
});
|
|
64360
64568
|
var qlTddAdvancedSchema = external_exports.object({
|
|
64361
64569
|
database: external_exports.string().optional().describe("Path to the CodeQL database for analysis"),
|
|
64362
|
-
language: external_exports.enum(SUPPORTED_LANGUAGES).
|
|
64570
|
+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
|
|
64363
64571
|
queryName: external_exports.string().optional().describe("Name of the query to develop")
|
|
64364
64572
|
});
|
|
64365
64573
|
var sarifRankSchema = external_exports.object({
|
|
64366
64574
|
queryId: external_exports.string().optional().describe("CodeQL query/rule identifier"),
|
|
64367
|
-
sarifPath: external_exports.string().
|
|
64575
|
+
sarifPath: external_exports.string().describe("Path to the SARIF file to analyze")
|
|
64368
64576
|
});
|
|
64369
64577
|
var describeFalsePositivesSchema = external_exports.object({
|
|
64370
|
-
queryPath: external_exports.string().
|
|
64578
|
+
queryPath: external_exports.string().describe("Path to the CodeQL query file")
|
|
64371
64579
|
});
|
|
64372
64580
|
var explainCodeqlQuerySchema = external_exports.object({
|
|
64373
|
-
databasePath: external_exports.string().optional().describe("
|
|
64581
|
+
databasePath: external_exports.string().optional().describe("Path to a CodeQL database for profiling"),
|
|
64374
64582
|
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language of the query"),
|
|
64375
64583
|
queryPath: external_exports.string().describe("Path to the CodeQL query file (.ql or .qlref)")
|
|
64376
64584
|
});
|
|
@@ -64378,14 +64586,108 @@ var documentCodeqlQuerySchema = external_exports.object({
|
|
|
64378
64586
|
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language of the query"),
|
|
64379
64587
|
queryPath: external_exports.string().describe("Path to the CodeQL query file (.ql or .qlref)")
|
|
64380
64588
|
});
|
|
64589
|
+
var checkForDuplicatedCodeSchema = external_exports.object({
|
|
64590
|
+
queryPath: external_exports.string().describe("Path to the .ql or .qll file to audit for duplicated definitions"),
|
|
64591
|
+
workspaceUri: external_exports.string().optional().describe("Pack root directory containing codeql-pack.yml (for LSP resolution)")
|
|
64592
|
+
});
|
|
64593
|
+
var findOverlappingQueriesSchema = external_exports.object({
|
|
64594
|
+
queryDescription: external_exports.string().describe(
|
|
64595
|
+
`Description of the new query's purpose and target constructs (e.g. "detect placement-new on types with non-trivial destructors")`
|
|
64596
|
+
),
|
|
64597
|
+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Target language for the new query (e.g. cpp, java, python)"),
|
|
64598
|
+
packRoot: external_exports.string().optional().describe("Directory containing codeql-pack.yml for the pack that will own the new query")
|
|
64599
|
+
});
|
|
64381
64600
|
var qlLspIterativeDevelopmentSchema = external_exports.object({
|
|
64382
|
-
language: external_exports.enum(SUPPORTED_LANGUAGES).
|
|
64383
|
-
queryPath: external_exports.string().
|
|
64601
|
+
language: external_exports.enum(SUPPORTED_LANGUAGES).describe("Programming language for the query"),
|
|
64602
|
+
queryPath: external_exports.string().describe("Path to the query file being developed"),
|
|
64384
64603
|
workspaceUri: external_exports.string().optional().describe("Workspace URI for LSP dependency resolution")
|
|
64385
64604
|
});
|
|
64605
|
+
function toPermissiveShape(shape) {
|
|
64606
|
+
const permissive = {};
|
|
64607
|
+
for (const [key, zodType] of Object.entries(shape)) {
|
|
64608
|
+
permissive[key] = widenZodType(zodType);
|
|
64609
|
+
}
|
|
64610
|
+
return permissive;
|
|
64611
|
+
}
|
|
64612
|
+
function widenZodType(zodType) {
|
|
64613
|
+
if (zodType instanceof external_exports.ZodOptional) {
|
|
64614
|
+
const inner = zodType.unwrap();
|
|
64615
|
+
const widenedInner = widenZodType(inner);
|
|
64616
|
+
if (widenedInner === inner) return zodType;
|
|
64617
|
+
const result = widenedInner.optional();
|
|
64618
|
+
const desc = zodType.description;
|
|
64619
|
+
return desc ? result.describe(desc) : result;
|
|
64620
|
+
}
|
|
64621
|
+
if (zodType instanceof external_exports.ZodEnum) {
|
|
64622
|
+
const desc = zodType.description;
|
|
64623
|
+
const replacement = external_exports.string();
|
|
64624
|
+
return desc ? replacement.describe(desc) : replacement;
|
|
64625
|
+
}
|
|
64626
|
+
return zodType;
|
|
64627
|
+
}
|
|
64628
|
+
function formatValidationError(promptName, error2) {
|
|
64629
|
+
const lines = [
|
|
64630
|
+
`\u26A0 **Invalid input for \`${promptName}\`**`,
|
|
64631
|
+
""
|
|
64632
|
+
];
|
|
64633
|
+
for (const issue2 of error2.issues) {
|
|
64634
|
+
const field = issue2.path.length > 0 ? issue2.path.join(".") : "input";
|
|
64635
|
+
if (issue2.code === "invalid_enum_value" && "options" in issue2) {
|
|
64636
|
+
const opts = issue2.options.join(", ");
|
|
64637
|
+
lines.push(
|
|
64638
|
+
`- **\`${field}\`**: received ${markdownInlineCode(String(issue2.received))} \u2014 must be one of: ${opts}`
|
|
64639
|
+
);
|
|
64640
|
+
} else if (issue2.code === "invalid_type") {
|
|
64641
|
+
lines.push(
|
|
64642
|
+
`- **\`${field}\`**: expected ${issue2.expected}, received ${issue2.received}`
|
|
64643
|
+
);
|
|
64644
|
+
} else {
|
|
64645
|
+
lines.push(`- **\`${field}\`**: ${issue2.message}`);
|
|
64646
|
+
}
|
|
64647
|
+
}
|
|
64648
|
+
lines.push(
|
|
64649
|
+
"",
|
|
64650
|
+
"Please correct the input and try again."
|
|
64651
|
+
);
|
|
64652
|
+
return lines.join("\n");
|
|
64653
|
+
}
|
|
64654
|
+
function createSafePromptHandler(promptName, strictSchema, handler) {
|
|
64655
|
+
return async (rawArgs) => {
|
|
64656
|
+
const parseResult = strictSchema.safeParse(rawArgs);
|
|
64657
|
+
if (!parseResult.success) {
|
|
64658
|
+
const errorText = formatValidationError(promptName, parseResult.error);
|
|
64659
|
+
logger.warn(`Prompt ${promptName} validation failed: ${parseResult.error.message}`);
|
|
64660
|
+
return {
|
|
64661
|
+
messages: [{
|
|
64662
|
+
role: "user",
|
|
64663
|
+
content: { type: "text", text: errorText }
|
|
64664
|
+
}]
|
|
64665
|
+
};
|
|
64666
|
+
}
|
|
64667
|
+
try {
|
|
64668
|
+
return await handler(parseResult.data);
|
|
64669
|
+
} catch (err) {
|
|
64670
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
64671
|
+
logger.error(`Prompt ${promptName} handler error: ${msg}`);
|
|
64672
|
+
return {
|
|
64673
|
+
messages: [{
|
|
64674
|
+
role: "user",
|
|
64675
|
+
content: {
|
|
64676
|
+
type: "text",
|
|
64677
|
+
text: `\u26A0 **Error in \`${promptName}\`**: ${msg}
|
|
64678
|
+
|
|
64679
|
+
Please check your inputs and try again.`
|
|
64680
|
+
}
|
|
64681
|
+
}]
|
|
64682
|
+
};
|
|
64683
|
+
}
|
|
64684
|
+
};
|
|
64685
|
+
}
|
|
64386
64686
|
var WORKFLOW_PROMPT_NAMES = [
|
|
64687
|
+
"check_for_duplicated_code",
|
|
64387
64688
|
"document_codeql_query",
|
|
64388
64689
|
"explain_codeql_query",
|
|
64690
|
+
"find_overlapping_queries",
|
|
64389
64691
|
"ql_lsp_iterative_development",
|
|
64390
64692
|
"ql_tdd_advanced",
|
|
64391
64693
|
"ql_tdd_basic",
|
|
@@ -64400,262 +64702,387 @@ function registerWorkflowPrompts(server) {
|
|
|
64400
64702
|
server.prompt(
|
|
64401
64703
|
"test_driven_development",
|
|
64402
64704
|
"Test-driven development workflow for CodeQL queries using MCP tools",
|
|
64403
|
-
testDrivenDevelopmentSchema.shape,
|
|
64404
|
-
|
|
64405
|
-
|
|
64406
|
-
|
|
64407
|
-
|
|
64408
|
-
|
|
64409
|
-
|
|
64410
|
-
|
|
64411
|
-
|
|
64412
|
-
|
|
64413
|
-
|
|
64414
|
-
|
|
64415
|
-
|
|
64416
|
-
|
|
64705
|
+
toPermissiveShape(testDrivenDevelopmentSchema.shape),
|
|
64706
|
+
createSafePromptHandler(
|
|
64707
|
+
"test_driven_development",
|
|
64708
|
+
testDrivenDevelopmentSchema,
|
|
64709
|
+
async ({ language, queryName }) => {
|
|
64710
|
+
const template = loadPromptTemplate("ql-tdd-basic.prompt.md");
|
|
64711
|
+
const content = processPromptTemplate(template, {
|
|
64712
|
+
language,
|
|
64713
|
+
queryName: queryName || "[QueryName]"
|
|
64714
|
+
});
|
|
64715
|
+
return {
|
|
64716
|
+
messages: [
|
|
64717
|
+
{
|
|
64718
|
+
role: "user",
|
|
64719
|
+
content: {
|
|
64720
|
+
type: "text",
|
|
64721
|
+
text: `## Context
|
|
64417
64722
|
|
|
64418
64723
|
- **Language**: ${language}
|
|
64419
64724
|
${queryName ? `- **Query Name**: ${queryName}
|
|
64420
64725
|
` : ""}
|
|
64421
64726
|
${content}`
|
|
64727
|
+
}
|
|
64422
64728
|
}
|
|
64423
|
-
|
|
64424
|
-
|
|
64425
|
-
}
|
|
64426
|
-
|
|
64729
|
+
]
|
|
64730
|
+
};
|
|
64731
|
+
}
|
|
64732
|
+
)
|
|
64427
64733
|
);
|
|
64428
64734
|
server.prompt(
|
|
64429
64735
|
"tools_query_workflow",
|
|
64430
64736
|
"Guide for using built-in tools queries (PrintAST, PrintCFG, CallGraphFrom, CallGraphTo) to understand code structure",
|
|
64431
|
-
toolsQueryWorkflowSchema.shape,
|
|
64432
|
-
|
|
64433
|
-
|
|
64434
|
-
|
|
64435
|
-
sourceFiles,
|
|
64436
|
-
|
|
64437
|
-
|
|
64438
|
-
|
|
64439
|
-
|
|
64440
|
-
|
|
64441
|
-
|
|
64442
|
-
|
|
64443
|
-
|
|
64444
|
-
|
|
64445
|
-
|
|
64446
|
-
|
|
64447
|
-
|
|
64448
|
-
|
|
64449
|
-
|
|
64450
|
-
|
|
64451
|
-
|
|
64452
|
-
|
|
64453
|
-
|
|
64454
|
-
|
|
64455
|
-
|
|
64456
|
-
|
|
64457
|
-
|
|
64737
|
+
toPermissiveShape(toolsQueryWorkflowSchema.shape),
|
|
64738
|
+
createSafePromptHandler(
|
|
64739
|
+
"tools_query_workflow",
|
|
64740
|
+
toolsQueryWorkflowSchema,
|
|
64741
|
+
async ({ language, database, sourceFiles, sourceFunction, targetFunction }) => {
|
|
64742
|
+
const template = loadPromptTemplate("tools-query-workflow.prompt.md");
|
|
64743
|
+
const warnings = [];
|
|
64744
|
+
const dbResult = await resolvePromptFilePath(database);
|
|
64745
|
+
if (dbResult.blocked) return blockedPathError(dbResult, "database path");
|
|
64746
|
+
const resolvedDatabase = dbResult.resolvedPath;
|
|
64747
|
+
if (dbResult.warning) warnings.push(dbResult.warning);
|
|
64748
|
+
const content = processPromptTemplate(template, {
|
|
64749
|
+
language,
|
|
64750
|
+
database: resolvedDatabase
|
|
64751
|
+
});
|
|
64752
|
+
const contextSection = buildToolsQueryContext(
|
|
64753
|
+
language,
|
|
64754
|
+
resolvedDatabase,
|
|
64755
|
+
sourceFiles,
|
|
64756
|
+
sourceFunction,
|
|
64757
|
+
targetFunction
|
|
64758
|
+
);
|
|
64759
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
64760
|
+
return {
|
|
64761
|
+
messages: [
|
|
64762
|
+
{
|
|
64763
|
+
role: "user",
|
|
64764
|
+
content: {
|
|
64765
|
+
type: "text",
|
|
64766
|
+
text: warningSection + contextSection + content
|
|
64767
|
+
}
|
|
64458
64768
|
}
|
|
64459
|
-
|
|
64460
|
-
|
|
64461
|
-
}
|
|
64462
|
-
|
|
64769
|
+
]
|
|
64770
|
+
};
|
|
64771
|
+
}
|
|
64772
|
+
)
|
|
64463
64773
|
);
|
|
64464
64774
|
server.prompt(
|
|
64465
64775
|
"workshop_creation_workflow",
|
|
64466
64776
|
"Guide for creating CodeQL query development workshops from production-grade queries",
|
|
64467
|
-
workshopCreationWorkflowSchema.shape,
|
|
64468
|
-
|
|
64469
|
-
|
|
64470
|
-
|
|
64471
|
-
|
|
64472
|
-
|
|
64473
|
-
|
|
64474
|
-
|
|
64475
|
-
|
|
64476
|
-
|
|
64477
|
-
|
|
64478
|
-
|
|
64479
|
-
|
|
64480
|
-
|
|
64481
|
-
|
|
64482
|
-
|
|
64483
|
-
|
|
64777
|
+
toPermissiveShape(workshopCreationWorkflowSchema.shape),
|
|
64778
|
+
createSafePromptHandler(
|
|
64779
|
+
"workshop_creation_workflow",
|
|
64780
|
+
workshopCreationWorkflowSchema,
|
|
64781
|
+
async ({ queryPath, language, workshopName, numStages }) => {
|
|
64782
|
+
const template = loadPromptTemplate("workshop-creation-workflow.prompt.md");
|
|
64783
|
+
const warnings = [];
|
|
64784
|
+
const qpResult = await resolvePromptFilePath(queryPath);
|
|
64785
|
+
if (qpResult.blocked) return blockedPathError(qpResult, "query path");
|
|
64786
|
+
const resolvedQueryPath = qpResult.resolvedPath;
|
|
64787
|
+
if (qpResult.warning) warnings.push(qpResult.warning);
|
|
64788
|
+
const derivedName = workshopName || basename7(resolvedQueryPath).replace(/\.(ql|qlref)$/, "").toLowerCase().replace(/[^a-z0-9]+/g, "-") || "codeql-workshop";
|
|
64789
|
+
const contextSection = buildWorkshopContext(
|
|
64790
|
+
resolvedQueryPath,
|
|
64791
|
+
language,
|
|
64792
|
+
derivedName,
|
|
64793
|
+
numStages
|
|
64794
|
+
);
|
|
64795
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
64796
|
+
return {
|
|
64797
|
+
messages: [
|
|
64798
|
+
{
|
|
64799
|
+
role: "user",
|
|
64800
|
+
content: {
|
|
64801
|
+
type: "text",
|
|
64802
|
+
text: warningSection + contextSection + template
|
|
64803
|
+
}
|
|
64484
64804
|
}
|
|
64485
|
-
|
|
64486
|
-
|
|
64487
|
-
}
|
|
64488
|
-
|
|
64805
|
+
]
|
|
64806
|
+
};
|
|
64807
|
+
}
|
|
64808
|
+
)
|
|
64489
64809
|
);
|
|
64490
64810
|
server.prompt(
|
|
64491
64811
|
"ql_tdd_basic",
|
|
64492
64812
|
"Test-driven CodeQL query development checklist - write tests first, implement query, iterate until tests pass",
|
|
64493
|
-
qlTddBasicSchema.shape,
|
|
64494
|
-
|
|
64495
|
-
|
|
64496
|
-
|
|
64497
|
-
|
|
64813
|
+
toPermissiveShape(qlTddBasicSchema.shape),
|
|
64814
|
+
createSafePromptHandler(
|
|
64815
|
+
"ql_tdd_basic",
|
|
64816
|
+
qlTddBasicSchema,
|
|
64817
|
+
async ({ language, queryName }) => {
|
|
64818
|
+
const template = loadPromptTemplate("ql-tdd-basic.prompt.md");
|
|
64819
|
+
let contextSection = "## Your Development Context\n\n";
|
|
64498
64820
|
contextSection += `- **Language**: ${language}
|
|
64499
64821
|
`;
|
|
64500
|
-
|
|
64501
|
-
|
|
64502
|
-
contextSection += `- **Query Name**: ${queryName}
|
|
64822
|
+
if (queryName) {
|
|
64823
|
+
contextSection += `- **Query Name**: ${queryName}
|
|
64503
64824
|
`;
|
|
64504
|
-
|
|
64505
|
-
if (language || queryName) {
|
|
64825
|
+
}
|
|
64506
64826
|
contextSection += "\n";
|
|
64507
|
-
|
|
64508
|
-
|
|
64509
|
-
|
|
64510
|
-
|
|
64511
|
-
|
|
64512
|
-
|
|
64513
|
-
|
|
64514
|
-
|
|
64827
|
+
return {
|
|
64828
|
+
messages: [
|
|
64829
|
+
{
|
|
64830
|
+
role: "user",
|
|
64831
|
+
content: {
|
|
64832
|
+
type: "text",
|
|
64833
|
+
text: contextSection + template
|
|
64834
|
+
}
|
|
64515
64835
|
}
|
|
64516
|
-
|
|
64517
|
-
|
|
64518
|
-
}
|
|
64519
|
-
|
|
64836
|
+
]
|
|
64837
|
+
};
|
|
64838
|
+
}
|
|
64839
|
+
)
|
|
64520
64840
|
);
|
|
64521
64841
|
server.prompt(
|
|
64522
64842
|
"ql_tdd_advanced",
|
|
64523
64843
|
"Advanced test-driven CodeQL development with AST visualization, control flow, and call graph analysis",
|
|
64524
|
-
qlTddAdvancedSchema.shape,
|
|
64525
|
-
|
|
64526
|
-
|
|
64527
|
-
|
|
64528
|
-
|
|
64844
|
+
toPermissiveShape(qlTddAdvancedSchema.shape),
|
|
64845
|
+
createSafePromptHandler(
|
|
64846
|
+
"ql_tdd_advanced",
|
|
64847
|
+
qlTddAdvancedSchema,
|
|
64848
|
+
async ({ language, queryName, database }) => {
|
|
64849
|
+
const template = loadPromptTemplate("ql-tdd-advanced.prompt.md");
|
|
64850
|
+
const warnings = [];
|
|
64851
|
+
let resolvedDatabase = database;
|
|
64852
|
+
if (database) {
|
|
64853
|
+
const dbResult = await resolvePromptFilePath(database);
|
|
64854
|
+
if (dbResult.blocked) return blockedPathError(dbResult, "database path");
|
|
64855
|
+
resolvedDatabase = dbResult.resolvedPath;
|
|
64856
|
+
if (dbResult.warning) warnings.push(dbResult.warning);
|
|
64857
|
+
}
|
|
64858
|
+
let contextSection = "## Your Development Context\n\n";
|
|
64529
64859
|
contextSection += `- **Language**: ${language}
|
|
64530
64860
|
`;
|
|
64531
|
-
|
|
64532
|
-
|
|
64533
|
-
contextSection += `- **Query Name**: ${queryName}
|
|
64861
|
+
if (queryName) {
|
|
64862
|
+
contextSection += `- **Query Name**: ${queryName}
|
|
64534
64863
|
`;
|
|
64535
|
-
|
|
64536
|
-
|
|
64537
|
-
|
|
64864
|
+
}
|
|
64865
|
+
if (resolvedDatabase) {
|
|
64866
|
+
contextSection += `- **Database**: ${resolvedDatabase}
|
|
64538
64867
|
`;
|
|
64539
|
-
|
|
64540
|
-
if (language || queryName || database) {
|
|
64868
|
+
}
|
|
64541
64869
|
contextSection += "\n";
|
|
64542
|
-
|
|
64543
|
-
|
|
64544
|
-
|
|
64545
|
-
|
|
64546
|
-
|
|
64547
|
-
|
|
64548
|
-
|
|
64549
|
-
|
|
64870
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
64871
|
+
return {
|
|
64872
|
+
messages: [
|
|
64873
|
+
{
|
|
64874
|
+
role: "user",
|
|
64875
|
+
content: {
|
|
64876
|
+
type: "text",
|
|
64877
|
+
text: warningSection + contextSection + template
|
|
64878
|
+
}
|
|
64550
64879
|
}
|
|
64551
|
-
|
|
64552
|
-
|
|
64553
|
-
}
|
|
64554
|
-
|
|
64880
|
+
]
|
|
64881
|
+
};
|
|
64882
|
+
}
|
|
64883
|
+
)
|
|
64555
64884
|
);
|
|
64556
64885
|
server.prompt(
|
|
64557
64886
|
"sarif_rank_false_positives",
|
|
64558
64887
|
"Analyze SARIF results to identify likely false positives in CodeQL query results",
|
|
64559
|
-
sarifRankSchema.shape,
|
|
64560
|
-
|
|
64561
|
-
|
|
64562
|
-
|
|
64563
|
-
|
|
64564
|
-
|
|
64888
|
+
toPermissiveShape(sarifRankSchema.shape),
|
|
64889
|
+
createSafePromptHandler(
|
|
64890
|
+
"sarif_rank_false_positives",
|
|
64891
|
+
sarifRankSchema,
|
|
64892
|
+
async ({ queryId, sarifPath }) => {
|
|
64893
|
+
const template = loadPromptTemplate("sarif-rank-false-positives.prompt.md");
|
|
64894
|
+
const warnings = [];
|
|
64895
|
+
const spResult = await resolvePromptFilePath(sarifPath);
|
|
64896
|
+
if (spResult.blocked) return blockedPathError(spResult, "SARIF path");
|
|
64897
|
+
const resolvedSarifPath = spResult.resolvedPath;
|
|
64898
|
+
if (spResult.warning) warnings.push(spResult.warning);
|
|
64899
|
+
let contextSection = "## Analysis Context\n\n";
|
|
64900
|
+
if (queryId) {
|
|
64901
|
+
contextSection += `- **Query ID**: ${queryId}
|
|
64565
64902
|
`;
|
|
64566
|
-
|
|
64567
|
-
|
|
64568
|
-
contextSection += `- **SARIF File**: ${sarifPath}
|
|
64903
|
+
}
|
|
64904
|
+
contextSection += `- **SARIF File**: ${resolvedSarifPath}
|
|
64569
64905
|
`;
|
|
64570
|
-
}
|
|
64571
|
-
if (queryId || sarifPath) {
|
|
64572
64906
|
contextSection += "\n";
|
|
64573
|
-
|
|
64574
|
-
|
|
64575
|
-
|
|
64576
|
-
|
|
64577
|
-
|
|
64578
|
-
|
|
64579
|
-
|
|
64580
|
-
|
|
64907
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
64908
|
+
return {
|
|
64909
|
+
messages: [
|
|
64910
|
+
{
|
|
64911
|
+
role: "user",
|
|
64912
|
+
content: {
|
|
64913
|
+
type: "text",
|
|
64914
|
+
text: warningSection + contextSection + template
|
|
64915
|
+
}
|
|
64581
64916
|
}
|
|
64582
|
-
|
|
64583
|
-
|
|
64584
|
-
}
|
|
64585
|
-
|
|
64917
|
+
]
|
|
64918
|
+
};
|
|
64919
|
+
}
|
|
64920
|
+
)
|
|
64586
64921
|
);
|
|
64587
64922
|
server.prompt(
|
|
64588
64923
|
"sarif_rank_true_positives",
|
|
64589
64924
|
"Analyze SARIF results to identify likely true positives in CodeQL query results",
|
|
64590
|
-
sarifRankSchema.shape,
|
|
64591
|
-
|
|
64592
|
-
|
|
64593
|
-
|
|
64594
|
-
|
|
64595
|
-
|
|
64925
|
+
toPermissiveShape(sarifRankSchema.shape),
|
|
64926
|
+
createSafePromptHandler(
|
|
64927
|
+
"sarif_rank_true_positives",
|
|
64928
|
+
sarifRankSchema,
|
|
64929
|
+
async ({ queryId, sarifPath }) => {
|
|
64930
|
+
const template = loadPromptTemplate("sarif-rank-true-positives.prompt.md");
|
|
64931
|
+
const warnings = [];
|
|
64932
|
+
const spResult = await resolvePromptFilePath(sarifPath);
|
|
64933
|
+
if (spResult.blocked) return blockedPathError(spResult, "SARIF path");
|
|
64934
|
+
const resolvedSarifPath = spResult.resolvedPath;
|
|
64935
|
+
if (spResult.warning) warnings.push(spResult.warning);
|
|
64936
|
+
let contextSection = "## Analysis Context\n\n";
|
|
64937
|
+
if (queryId) {
|
|
64938
|
+
contextSection += `- **Query ID**: ${queryId}
|
|
64596
64939
|
`;
|
|
64597
|
-
|
|
64598
|
-
|
|
64599
|
-
contextSection += `- **SARIF File**: ${sarifPath}
|
|
64940
|
+
}
|
|
64941
|
+
contextSection += `- **SARIF File**: ${resolvedSarifPath}
|
|
64600
64942
|
`;
|
|
64601
|
-
}
|
|
64602
|
-
if (queryId || sarifPath) {
|
|
64603
64943
|
contextSection += "\n";
|
|
64604
|
-
|
|
64605
|
-
|
|
64606
|
-
|
|
64607
|
-
|
|
64608
|
-
|
|
64609
|
-
|
|
64610
|
-
|
|
64611
|
-
|
|
64944
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
64945
|
+
return {
|
|
64946
|
+
messages: [
|
|
64947
|
+
{
|
|
64948
|
+
role: "user",
|
|
64949
|
+
content: {
|
|
64950
|
+
type: "text",
|
|
64951
|
+
text: warningSection + contextSection + template
|
|
64952
|
+
}
|
|
64612
64953
|
}
|
|
64613
|
-
|
|
64614
|
-
|
|
64615
|
-
}
|
|
64616
|
-
|
|
64954
|
+
]
|
|
64955
|
+
};
|
|
64956
|
+
}
|
|
64957
|
+
)
|
|
64617
64958
|
);
|
|
64618
64959
|
server.prompt(
|
|
64619
64960
|
"run_query_and_summarize_false_positives",
|
|
64620
64961
|
"Help a user figure out where their query may need improvement to have a lower false positive rate",
|
|
64621
|
-
describeFalsePositivesSchema.shape,
|
|
64622
|
-
|
|
64623
|
-
|
|
64624
|
-
|
|
64625
|
-
|
|
64626
|
-
|
|
64962
|
+
toPermissiveShape(describeFalsePositivesSchema.shape),
|
|
64963
|
+
createSafePromptHandler(
|
|
64964
|
+
"run_query_and_summarize_false_positives",
|
|
64965
|
+
describeFalsePositivesSchema,
|
|
64966
|
+
async ({ queryPath }) => {
|
|
64967
|
+
const template = loadPromptTemplate("run-query-and-summarize-false-positives.prompt.md");
|
|
64968
|
+
const warnings = [];
|
|
64969
|
+
const qpResult = await resolvePromptFilePath(queryPath);
|
|
64970
|
+
if (qpResult.blocked) return blockedPathError(qpResult, "query path");
|
|
64971
|
+
const resolvedQueryPath = qpResult.resolvedPath;
|
|
64972
|
+
if (qpResult.warning) warnings.push(qpResult.warning);
|
|
64973
|
+
const contextSection = `## Analysis Context
|
|
64974
|
+
|
|
64975
|
+
- **Query Path**: ${resolvedQueryPath}
|
|
64976
|
+
|
|
64627
64977
|
`;
|
|
64628
|
-
|
|
64629
|
-
|
|
64630
|
-
|
|
64631
|
-
|
|
64632
|
-
|
|
64633
|
-
|
|
64634
|
-
|
|
64635
|
-
|
|
64636
|
-
|
|
64978
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
64979
|
+
return {
|
|
64980
|
+
messages: [
|
|
64981
|
+
{
|
|
64982
|
+
role: "user",
|
|
64983
|
+
content: {
|
|
64984
|
+
type: "text",
|
|
64985
|
+
text: warningSection + contextSection + template
|
|
64986
|
+
}
|
|
64637
64987
|
}
|
|
64638
|
-
|
|
64639
|
-
|
|
64640
|
-
}
|
|
64641
|
-
|
|
64988
|
+
]
|
|
64989
|
+
};
|
|
64990
|
+
}
|
|
64991
|
+
)
|
|
64642
64992
|
);
|
|
64643
64993
|
server.prompt(
|
|
64644
64994
|
"explain_codeql_query",
|
|
64645
64995
|
"Generate detailed explanation of a CodeQL query for workshop learning content - uses MCP tools to gather context and produces both verbal explanations and mermaid evaluation diagrams",
|
|
64646
|
-
explainCodeqlQuerySchema.shape,
|
|
64647
|
-
|
|
64648
|
-
|
|
64649
|
-
|
|
64650
|
-
|
|
64996
|
+
toPermissiveShape(explainCodeqlQuerySchema.shape),
|
|
64997
|
+
createSafePromptHandler(
|
|
64998
|
+
"explain_codeql_query",
|
|
64999
|
+
explainCodeqlQuerySchema,
|
|
65000
|
+
async ({ queryPath, language, databasePath }) => {
|
|
65001
|
+
const template = loadPromptTemplate("explain-codeql-query.prompt.md");
|
|
65002
|
+
const warnings = [];
|
|
65003
|
+
const qpResult = await resolvePromptFilePath(queryPath);
|
|
65004
|
+
if (qpResult.blocked) return blockedPathError(qpResult, "query path");
|
|
65005
|
+
const resolvedQueryPath = qpResult.resolvedPath;
|
|
65006
|
+
if (qpResult.warning) warnings.push(qpResult.warning);
|
|
65007
|
+
let resolvedDatabasePath = databasePath;
|
|
65008
|
+
if (databasePath) {
|
|
65009
|
+
const dbResult = await resolvePromptFilePath(databasePath);
|
|
65010
|
+
if (dbResult.blocked) return blockedPathError(dbResult, "database path");
|
|
65011
|
+
resolvedDatabasePath = dbResult.resolvedPath;
|
|
65012
|
+
if (dbResult.warning) warnings.push(dbResult.warning);
|
|
65013
|
+
}
|
|
65014
|
+
let contextSection = "## Query to Explain\n\n";
|
|
65015
|
+
contextSection += `- **Query Path**: ${resolvedQueryPath}
|
|
64651
65016
|
`;
|
|
64652
|
-
|
|
65017
|
+
contextSection += `- **Language**: ${language}
|
|
64653
65018
|
`;
|
|
64654
|
-
|
|
64655
|
-
|
|
65019
|
+
if (resolvedDatabasePath) {
|
|
65020
|
+
contextSection += `- **Database Path**: ${resolvedDatabasePath}
|
|
64656
65021
|
`;
|
|
65022
|
+
}
|
|
65023
|
+
contextSection += "\n";
|
|
65024
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
65025
|
+
return {
|
|
65026
|
+
messages: [
|
|
65027
|
+
{
|
|
65028
|
+
role: "user",
|
|
65029
|
+
content: {
|
|
65030
|
+
type: "text",
|
|
65031
|
+
text: warningSection + contextSection + template
|
|
65032
|
+
}
|
|
65033
|
+
}
|
|
65034
|
+
]
|
|
65035
|
+
};
|
|
64657
65036
|
}
|
|
64658
|
-
|
|
65037
|
+
)
|
|
65038
|
+
);
|
|
65039
|
+
server.prompt(
|
|
65040
|
+
"document_codeql_query",
|
|
65041
|
+
"Create or update documentation for a CodeQL query - generates standardized markdown documentation as a sibling file to the query",
|
|
65042
|
+
toPermissiveShape(documentCodeqlQuerySchema.shape),
|
|
65043
|
+
createSafePromptHandler(
|
|
65044
|
+
"document_codeql_query",
|
|
65045
|
+
documentCodeqlQuerySchema,
|
|
65046
|
+
async ({ queryPath, language }) => {
|
|
65047
|
+
const template = loadPromptTemplate("document-codeql-query.prompt.md");
|
|
65048
|
+
const warnings = [];
|
|
65049
|
+
const qpResult = await resolvePromptFilePath(queryPath);
|
|
65050
|
+
if (qpResult.blocked) return blockedPathError(qpResult, "query path");
|
|
65051
|
+
const resolvedQueryPath = qpResult.resolvedPath;
|
|
65052
|
+
if (qpResult.warning) warnings.push(qpResult.warning);
|
|
65053
|
+
const contextSection = `## Query to Document
|
|
65054
|
+
|
|
65055
|
+
- **Query Path**: ${resolvedQueryPath}
|
|
65056
|
+
- **Language**: ${language}
|
|
65057
|
+
|
|
65058
|
+
`;
|
|
65059
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
65060
|
+
return {
|
|
65061
|
+
messages: [
|
|
65062
|
+
{
|
|
65063
|
+
role: "user",
|
|
65064
|
+
content: {
|
|
65065
|
+
type: "text",
|
|
65066
|
+
text: warningSection + contextSection + template
|
|
65067
|
+
}
|
|
65068
|
+
}
|
|
65069
|
+
]
|
|
65070
|
+
};
|
|
65071
|
+
}
|
|
65072
|
+
)
|
|
65073
|
+
);
|
|
65074
|
+
server.prompt(
|
|
65075
|
+
"check_for_duplicated_code",
|
|
65076
|
+
"Check a .ql or .qll file for classes, predicates, and modules that duplicate definitions already available in the standard CodeQL libraries or shared project .qll files",
|
|
65077
|
+
checkForDuplicatedCodeSchema.shape,
|
|
65078
|
+
async ({ queryPath, workspaceUri }) => {
|
|
65079
|
+
const template = loadPromptTemplate("check-for-duplicated-code.prompt.md");
|
|
65080
|
+
const contextSection = `## File to Audit
|
|
65081
|
+
|
|
65082
|
+
- **Query Path**: ${queryPath}
|
|
65083
|
+
${workspaceUri ? `- **Workspace URI**: ${workspaceUri}
|
|
65084
|
+
` : ""}
|
|
65085
|
+
`;
|
|
64659
65086
|
return {
|
|
64660
65087
|
messages: [
|
|
64661
65088
|
{
|
|
@@ -64670,24 +65097,24 @@ ${content}`
|
|
|
64670
65097
|
}
|
|
64671
65098
|
);
|
|
64672
65099
|
server.prompt(
|
|
64673
|
-
"
|
|
64674
|
-
"
|
|
64675
|
-
|
|
64676
|
-
async ({
|
|
64677
|
-
const template = loadPromptTemplate("
|
|
64678
|
-
const contextSection = `## Query
|
|
64679
|
-
|
|
64680
|
-
- **Query
|
|
65100
|
+
"find_overlapping_queries",
|
|
65101
|
+
"Discover existing .ql query files and .qll library files whose content may overlap with a new query design, identifying reusable classes, predicates, and modules",
|
|
65102
|
+
findOverlappingQueriesSchema.shape,
|
|
65103
|
+
async ({ queryDescription, language, packRoot }) => {
|
|
65104
|
+
const template = loadPromptTemplate("find-overlapping-queries.prompt.md");
|
|
65105
|
+
const contextSection = `## New Query Context
|
|
65106
|
+
|
|
65107
|
+
- **Query Description**: ${queryDescription}
|
|
64681
65108
|
- **Language**: ${language}
|
|
64682
|
-
|
|
64683
|
-
|
|
65109
|
+
` + (packRoot ? `- **Pack Root**: ${packRoot}
|
|
65110
|
+
` : "");
|
|
64684
65111
|
return {
|
|
64685
65112
|
messages: [
|
|
64686
65113
|
{
|
|
64687
65114
|
role: "user",
|
|
64688
65115
|
content: {
|
|
64689
65116
|
type: "text",
|
|
64690
|
-
text: contextSection + template
|
|
65117
|
+
text: contextSection + "\n" + template
|
|
64691
65118
|
}
|
|
64692
65119
|
}
|
|
64693
65120
|
]
|
|
@@ -64697,37 +65124,48 @@ ${content}`
|
|
|
64697
65124
|
server.prompt(
|
|
64698
65125
|
"ql_lsp_iterative_development",
|
|
64699
65126
|
"Iterative CodeQL query development using LSP tools for completion, navigation, and validation",
|
|
64700
|
-
qlLspIterativeDevelopmentSchema.shape,
|
|
64701
|
-
|
|
64702
|
-
|
|
64703
|
-
|
|
64704
|
-
|
|
65127
|
+
toPermissiveShape(qlLspIterativeDevelopmentSchema.shape),
|
|
65128
|
+
createSafePromptHandler(
|
|
65129
|
+
"ql_lsp_iterative_development",
|
|
65130
|
+
qlLspIterativeDevelopmentSchema,
|
|
65131
|
+
async ({ language, queryPath, workspaceUri }) => {
|
|
65132
|
+
const template = loadPromptTemplate("ql-lsp-iterative-development.prompt.md");
|
|
65133
|
+
const warnings = [];
|
|
65134
|
+
const qpResult = await resolvePromptFilePath(queryPath);
|
|
65135
|
+
if (qpResult.blocked) return blockedPathError(qpResult, "query path");
|
|
65136
|
+
const resolvedQueryPath = qpResult.resolvedPath;
|
|
65137
|
+
if (qpResult.warning) warnings.push(qpResult.warning);
|
|
65138
|
+
let resolvedWorkspaceUri = workspaceUri;
|
|
65139
|
+
if (workspaceUri) {
|
|
65140
|
+
const wsResult = await resolvePromptFilePath(workspaceUri);
|
|
65141
|
+
if (wsResult.blocked) return blockedPathError(wsResult, "workspace URI");
|
|
65142
|
+
resolvedWorkspaceUri = wsResult.resolvedPath;
|
|
65143
|
+
if (wsResult.warning) warnings.push(wsResult.warning);
|
|
65144
|
+
}
|
|
65145
|
+
let contextSection = "## Your Development Context\n\n";
|
|
64705
65146
|
contextSection += `- **Language**: ${language}
|
|
64706
65147
|
`;
|
|
64707
|
-
|
|
64708
|
-
if (queryPath) {
|
|
64709
|
-
contextSection += `- **Query Path**: ${queryPath}
|
|
65148
|
+
contextSection += `- **Query Path**: ${resolvedQueryPath}
|
|
64710
65149
|
`;
|
|
64711
|
-
|
|
64712
|
-
|
|
64713
|
-
contextSection += `- **Workspace URI**: ${workspaceUri}
|
|
65150
|
+
if (resolvedWorkspaceUri) {
|
|
65151
|
+
contextSection += `- **Workspace URI**: ${resolvedWorkspaceUri}
|
|
64714
65152
|
`;
|
|
64715
|
-
|
|
64716
|
-
if (language || queryPath || workspaceUri) {
|
|
65153
|
+
}
|
|
64717
65154
|
contextSection += "\n";
|
|
64718
|
-
|
|
64719
|
-
|
|
64720
|
-
|
|
64721
|
-
|
|
64722
|
-
|
|
64723
|
-
|
|
64724
|
-
|
|
64725
|
-
|
|
65155
|
+
const warningSection = warnings.length > 0 ? warnings.join("\n") + "\n\n" : "";
|
|
65156
|
+
return {
|
|
65157
|
+
messages: [
|
|
65158
|
+
{
|
|
65159
|
+
role: "user",
|
|
65160
|
+
content: {
|
|
65161
|
+
type: "text",
|
|
65162
|
+
text: warningSection + contextSection + template
|
|
65163
|
+
}
|
|
64726
65164
|
}
|
|
64727
|
-
|
|
64728
|
-
|
|
64729
|
-
}
|
|
64730
|
-
|
|
65165
|
+
]
|
|
65166
|
+
};
|
|
65167
|
+
}
|
|
65168
|
+
)
|
|
64731
65169
|
);
|
|
64732
65170
|
logger.info(`Registered ${WORKFLOW_PROMPT_NAMES.length} workflow prompts`);
|
|
64733
65171
|
}
|
|
@@ -66186,9 +66624,9 @@ init_cli_executor();
|
|
|
66186
66624
|
init_server_manager();
|
|
66187
66625
|
init_package_paths();
|
|
66188
66626
|
init_logger();
|
|
66189
|
-
import_dotenv.default.config({ path:
|
|
66627
|
+
import_dotenv.default.config({ path: resolve14(packageRootDir, ".env"), quiet: true });
|
|
66190
66628
|
var PACKAGE_NAME = "codeql-development-mcp-server";
|
|
66191
|
-
var VERSION = "2.
|
|
66629
|
+
var VERSION = "2.25.0-rc1";
|
|
66192
66630
|
async function startServer(mode = "stdio") {
|
|
66193
66631
|
logger.info(`Starting CodeQL Development MCP McpServer v${VERSION} in ${mode} mode`);
|
|
66194
66632
|
const codeqlBinary = resolveCodeQLBinary();
|
|
@@ -66242,10 +66680,10 @@ async function startServer(mode = "stdio") {
|
|
|
66242
66680
|
});
|
|
66243
66681
|
const host = process.env.HTTP_HOST || "localhost";
|
|
66244
66682
|
const port = Number(process.env.HTTP_PORT || process.env.PORT) || 3e3;
|
|
66245
|
-
return new Promise((
|
|
66683
|
+
return new Promise((resolve15, reject) => {
|
|
66246
66684
|
const httpServer = app.listen(port, host, () => {
|
|
66247
66685
|
logger.info(`HTTP server listening on http://${host}:${port}/mcp`);
|
|
66248
|
-
|
|
66686
|
+
resolve15();
|
|
66249
66687
|
});
|
|
66250
66688
|
httpServer.on("error", (error2) => {
|
|
66251
66689
|
logger.error("HTTP server error:", error2);
|
|
@@ -66282,7 +66720,7 @@ async function main() {
|
|
|
66282
66720
|
process.exit(1);
|
|
66283
66721
|
}
|
|
66284
66722
|
}
|
|
66285
|
-
var scriptPath = process.argv[1] ? realpathSync2(
|
|
66723
|
+
var scriptPath = process.argv[1] ? realpathSync2(resolve14(process.argv[1])) : void 0;
|
|
66286
66724
|
if (scriptPath && import.meta.url === pathToFileURL5(scriptPath).href) {
|
|
66287
66725
|
main();
|
|
66288
66726
|
}
|