lurqrun 0.1.7 → 0.1.8
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/README.md +312 -148
- package/dist/{auditHandler-JCOJSUYW.js → auditHandler-VWCXSDVO.js} +12 -11
- package/dist/autopilotInit-Q62MX5M6.js +178 -0
- package/dist/bin/lurq.js +235 -83
- package/dist/{browserAuth-B6G27USY.js → browserAuth-J7APSD4P.js} +4 -3
- package/dist/{cache-DKI34SVS.js → cache-AEAKCV4I.js} +2 -2
- package/dist/check-2JTQDQA6.js +2613 -0
- package/dist/{check-2FDGUOV7.js → check-PQSQ2MMA.js} +1 -1
- package/dist/checkUpgrade-5YW77OBL.js +24 -0
- package/dist/{chunk-BCANRN5B.js → chunk-2GAYNIHG.js} +8 -1
- package/dist/{chunk-EA3DP5HG.js → chunk-2O6Z37IT.js} +155 -25
- package/dist/{chunk-J5FZYN4A.js → chunk-2WD4QAH4.js} +1 -1
- package/dist/{chunk-CUP36ND3.js → chunk-3676XOBU.js} +145 -36
- package/dist/chunk-3D2MPGOQ.js +181 -0
- package/dist/{chunk-LYMPYETA.js → chunk-4JHDSVIN.js} +270 -6
- package/dist/chunk-53SG6XWA.js +141 -0
- package/dist/chunk-5ABNDB3I.js +37 -0
- package/dist/chunk-5ALIJFDA.js +114 -0
- package/dist/{chunk-BULZAX2U.js → chunk-64ZF7KO4.js} +55 -38
- package/dist/{chunk-2VMOWSRY.js → chunk-6DM6UQFD.js} +19 -1
- package/dist/{chunk-HWBBVLOT.js → chunk-6L67QMCP.js} +1 -1
- package/dist/{chunk-GPTKSNR6.js → chunk-72Y2FDVS.js} +2 -1
- package/dist/{chunk-B43LCXBM.js → chunk-A3TYI2TF.js} +81 -16
- package/dist/{chunk-IQ4SDKKY.js → chunk-B2UUYRBX.js} +31 -228
- package/dist/{chunk-DB2VF5UD.js → chunk-BJT2LHAR.js} +16 -11
- package/dist/chunk-BM3LF5T6.js +132 -0
- package/dist/{chunk-3N3Q3DSW.js → chunk-BN3NM47Q.js} +8 -8
- package/dist/chunk-D3K6IZVR.js +12845 -0
- package/dist/{chunk-AHBP533R.js → chunk-D3VTZS7V.js} +7 -5
- package/dist/{chunk-UDVNA7EA.js → chunk-DM37MTOO.js} +161 -8
- package/dist/chunk-DONTW3NE.js +171 -0
- package/dist/{chunk-M6NYEXCW.js → chunk-DSROTZ3Z.js} +1 -1
- package/dist/{chunk-4F7ZESPO.js → chunk-EQCXENKZ.js} +3 -5
- package/dist/{chunk-CW5HJ3LX.js → chunk-EYAKM6YN.js} +1 -1
- package/dist/{chunk-VL2E5T2A.js → chunk-FDFPMBCA.js} +6 -3
- package/dist/{chunk-BV32UNLL.js → chunk-FVYFV5HA.js} +2 -2
- package/dist/{chunk-DWAGCNEL.js → chunk-GM5Y555O.js} +36 -103
- package/dist/{chunk-PSX3GIAN.js → chunk-HWFX4BC4.js} +2 -1
- package/dist/chunk-IFNONGRQ.js +603 -0
- package/dist/chunk-J3U2CPSK.js +136 -0
- package/dist/{chunk-Y5GI7RL3.js → chunk-J6XQ7OPZ.js} +9 -1
- package/dist/{chunk-LBFGSSF2.js → chunk-KMV4Y6R3.js} +2 -1
- package/dist/{chunk-L6N4JFW2.js → chunk-KP5ZDDPE.js} +81 -4
- package/dist/{chunk-SJOVFF7B.js → chunk-KYKSZ3XZ.js} +3 -2
- package/dist/chunk-NEZNAPPN.js +41 -0
- package/dist/{chunk-NH5I4KHH.js → chunk-NPVN2THM.js} +1 -5
- package/dist/{chunk-6L3U7DZ5.js → chunk-NYZU5NCW.js} +1 -1
- package/dist/chunk-O4KHCV6I.js +320 -0
- package/dist/{chunk-LO35HLQZ.js → chunk-ONDVTXUO.js} +25 -4
- package/dist/{chunk-4ZYCIMY4.js → chunk-OTJFHESY.js} +25 -4
- package/dist/chunk-P6MIKSPY.js +243 -0
- package/dist/{checkUpgrade-F2WESBPM.js → chunk-QCRBX3LV.js} +72 -10
- package/dist/{chunk-LRD4GBYE.js → chunk-QUIMQ7YL.js} +1 -1
- package/dist/chunk-RG3YLU6E.js +49 -0
- package/dist/{chunk-ST2X2GYN.js → chunk-SHZFOSXC.js} +109 -20
- package/dist/{chunk-CIDWNUAP.js → chunk-SOXFMMXC.js} +8 -2
- package/dist/chunk-TDTYV6QI.js +119 -0
- package/dist/{chunk-FW6BD2NO.js → chunk-TUXQ32WE.js} +457 -121
- package/dist/{chunk-WQ23REYT.js → chunk-VGCDRK3S.js} +1 -1
- package/dist/{chunk-U5AT3TD4.js → chunk-X4W64MHU.js} +1735 -1858
- package/dist/chunk-XBQA4I36.js +92 -0
- package/dist/chunk-XGOV6KV4.js +413 -0
- package/dist/{chunk-OQS4GUSI.js → chunk-XIFQIFSZ.js} +210 -661
- package/dist/{chunk-XBIDMHSK.js → chunk-XLXPVN3Y.js} +2 -34
- package/dist/chunk-ZJMLQ37G.js +90 -0
- package/dist/{client-IRKAMDYZ.js → client-MU4EUDZV.js} +3 -3
- package/dist/{commands-FIL5ET6P.js → commands-UOOTMBKA.js} +145 -33
- package/dist/{compat-R3UTFQ5Q.js → compat-Q5DVPITN.js} +6 -6
- package/dist/constants-DJFOFZ44.js +24 -0
- package/dist/{dashboardIssue-WYYMBFIB.js → dashboardIssue-KBKLQMGC.js} +105 -23
- package/dist/{diff-GZA2774U.js → diff-I4SNUHU3.js} +1 -1
- package/dist/domains-VRT4BRVZ.js +14 -0
- package/dist/env-UN6KGZ7S.js +15 -0
- package/dist/envCheck-KUPTORFQ.js +71 -0
- package/dist/{extract-NKGKLIVT.js → extract-6WG265BL.js} +14 -3
- package/dist/{fetch-QYTUJVG2.js → fetch-PJ3SC32M.js} +4 -4
- package/dist/{firstTouch-QQTJH4QX.js → firstTouch-COJCMOB3.js} +1 -1
- package/dist/fix-3EDWNKW3.js +220 -0
- package/dist/{handlers-GEJAVZDK.js → handlers-4Q37WIFT.js} +19 -17
- package/dist/hook-NA66XJLC.js +412 -0
- package/dist/{http-ETPYMBGD.js → http-25GJ6SKK.js} +2078 -510
- package/dist/{ingestQueue-VKN4KBIF.js → ingestQueue-FSVJC3AA.js} +14 -12
- package/dist/{install-EK3W2COX.js → install-G2HHXYJ2.js} +6 -6
- package/dist/{installSkill-VQJWJVCL.js → installSkill-5TIMYIJZ.js} +21 -3
- package/dist/manifest-ENMIC54B.js +13 -0
- package/dist/{mcp-3JHD5SUZ.js → mcp-PENLL2PK.js} +60 -32
- package/dist/mcpConfig-3LYPRY5Q.js +80 -0
- package/dist/{mcpHandlers-QFN4MCFL.js → mcpHandlers-PO7GENA7.js} +7 -7
- package/dist/{mcpScan-QZHWENIP.js → mcpScan-ULP626TQ.js} +306 -442
- package/dist/{mcpScanWorkflow-JPYCBGC4.js → mcpScanWorkflow-27O44FOE.js} +29 -12
- package/dist/{mcpStack-BYJCZNIV.js → mcpStack-ZNYIFXZ5.js} +1 -1
- package/dist/model-ASMZWLM7.js +214 -0
- package/dist/{packages-THVFMWFP.js → packages-RWF2LXST.js} +3 -5
- package/dist/{plan-V4OEI3J4.js → plan-SDILIDZT.js} +23 -21
- package/dist/{planView-JRXGCG2N.js → planView-ZAKRTGVS.js} +4 -1
- package/dist/{policy-3P6BGRDN.js → policy-JAGNMQJI.js} +5 -5
- package/dist/probe-3IK646WN.js +610 -0
- package/dist/publicUpgrades-WTBGLDIK.js +42 -0
- package/dist/{references-6N7VEPHT.js → references-I6Y4BSRR.js} +3 -1
- package/dist/{release-4U4ABNSJ.js → release-7IU2R4YG.js} +5 -5
- package/dist/{remote-YGCXYI4V.js → remote-FN6225AH.js} +13 -3
- package/dist/rename-OS6JYBZQ.js +204 -0
- package/dist/{reportRuns-CKQQYLY4.js → reportRuns-O4X7ZFTX.js} +15 -2
- package/dist/safeFetch-COERXGFN.js +19 -0
- package/dist/{sandbox-MEZLAODF.js → sandbox-SAPSRKEI.js} +4 -4
- package/dist/sarif-WLVJFJ7U.js +125 -0
- package/dist/server-OLTY3NYT.js +59 -0
- package/dist/{surface-V62GE554.js → surface-7MHE3RL7.js} +18 -16
- package/dist/{surface-YL6O67W3.js → surface-JS2XU3U3.js} +5 -3
- package/dist/{surfaceHandlers-X2IZKA3E.js → surfaceHandlers-4B6TMZ34.js} +5 -5
- package/dist/{typecheck-X7U5ELMR.js → typecheck-NGOKNAJY.js} +23 -9
- package/dist/{uninstall-P7RGBX6G.js → uninstall-I2IJP5JZ.js} +30 -4
- package/dist/{upgrade-NQ5IWFZB.js → upgrade-FS26DJGG.js} +86 -32
- package/dist/{upgradePlan-A4LRKLEG.js → upgradePlan-ZS5IOVMZ.js} +46 -11
- package/dist/upkeepHandler-VFGYXJKB.js +13 -0
- package/dist/{userConfig-Z3GQE776.js → userConfig-ICASHI47.js} +1 -1
- package/dist/{watch-DGFMWUDL.js → watch-OCNEUXG6.js} +24 -34
- package/package.json +3 -2
- package/templates/skill-instructions.md +22 -3
- package/dist/chunk-6AAEVQ7I.js +0 -6336
- package/dist/chunk-I2JUKN6Z.js +0 -24
- package/dist/server-KFUD5X57.js +0 -55
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
SseError,
|
|
4
|
+
StreamableHTTPError,
|
|
5
|
+
UnauthorizedError
|
|
6
|
+
} from "./chunk-X4W64MHU.js";
|
|
7
|
+
import {
|
|
8
|
+
ErrorCode,
|
|
9
|
+
McpError
|
|
10
|
+
} from "./chunk-D3K6IZVR.js";
|
|
11
|
+
import {
|
|
12
|
+
init_esm_shims
|
|
13
|
+
} from "./chunk-I3M2KJXB.js";
|
|
14
|
+
|
|
15
|
+
// src/mcpScan/errors.ts
|
|
16
|
+
init_esm_shims();
|
|
17
|
+
var ENV_COMPLAINT = /\b([A-Z][A-Z0-9]{2,}(?:_[A-Z0-9]+)+)\b[^.\n]{0,60}?\b(required|must be set|not set|missing|is not defined)\b|\b(required|must be set|missing)\b[^.\n]{0,60}?\b([A-Z][A-Z0-9]{2,}(?:_[A-Z0-9]+)+)\b/;
|
|
18
|
+
function sniffMissingEnv(text) {
|
|
19
|
+
const m = ENV_COMPLAINT.exec(text);
|
|
20
|
+
return m ? m[1] ?? m[4] ?? null : null;
|
|
21
|
+
}
|
|
22
|
+
var NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
23
|
+
"ECONNREFUSED",
|
|
24
|
+
"ENOTFOUND",
|
|
25
|
+
"EAI_AGAIN",
|
|
26
|
+
"ECONNRESET",
|
|
27
|
+
"ETIMEDOUT",
|
|
28
|
+
"EHOSTUNREACH",
|
|
29
|
+
"ENETUNREACH",
|
|
30
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
31
|
+
"UND_ERR_SOCKET",
|
|
32
|
+
"CERT_HAS_EXPIRED",
|
|
33
|
+
"DEPTH_ZERO_SELF_SIGNED_CERT",
|
|
34
|
+
"SELF_SIGNED_CERT_IN_CHAIN",
|
|
35
|
+
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
36
|
+
"ERR_TLS_CERT_ALTNAME_INVALID"
|
|
37
|
+
]);
|
|
38
|
+
function causeCode(err) {
|
|
39
|
+
let cur = err;
|
|
40
|
+
for (let i = 0; i < 5 && cur; i++) {
|
|
41
|
+
const code = cur.code;
|
|
42
|
+
if (typeof code === "string") return code;
|
|
43
|
+
cur = cur.cause;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
var msg = (err) => err instanceof Error ? err.message : String(err);
|
|
48
|
+
function classifyError(err, ctx) {
|
|
49
|
+
const message = msg(err).slice(0, 500);
|
|
50
|
+
if (err instanceof UnauthorizedError) {
|
|
51
|
+
return {
|
|
52
|
+
status: "auth_required",
|
|
53
|
+
error: message || "the server requires authorization",
|
|
54
|
+
hint: "this server signs in with OAuth, and lurq cannot reuse the token your agent holds; ask your agent to pass its tool list to the mcp_stack tool instead"
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const httpCode = err instanceof StreamableHTTPError || err instanceof SseError ? err.code : void 0;
|
|
58
|
+
if (httpCode === 401 || httpCode === 403) {
|
|
59
|
+
return {
|
|
60
|
+
status: "auth_required",
|
|
61
|
+
error: `HTTP ${httpCode}`,
|
|
62
|
+
hint: "the server rejected the credentials in this config; check the Authorization header or token it is given"
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (typeof httpCode === "number" && httpCode > 0) {
|
|
66
|
+
return {
|
|
67
|
+
status: "unreachable",
|
|
68
|
+
error: `HTTP ${httpCode}: ${message}`,
|
|
69
|
+
hint: httpCode === 404 ? "nothing answers MCP at this url; check the path" : null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (err instanceof McpError && err.code === ErrorCode.RequestTimeout) {
|
|
73
|
+
return {
|
|
74
|
+
status: "timeout",
|
|
75
|
+
error: message,
|
|
76
|
+
hint: ctx.transport === "stdio" ? "the server did not answer in time; a first run of npx/uvx downloads the package, so try again with a longer --timeout" : null
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const code = causeCode(err);
|
|
80
|
+
if (code === "ENOENT" && ctx.transport === "stdio") {
|
|
81
|
+
return {
|
|
82
|
+
status: "spawn_failed",
|
|
83
|
+
error: `command not found: ${ctx.command ?? "(none)"}`,
|
|
84
|
+
hint: "install it, or use an absolute path in the config"
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (code && NETWORK_CODES.has(code)) {
|
|
88
|
+
return { status: "unreachable", error: `${code}: ${message}`, hint: null };
|
|
89
|
+
}
|
|
90
|
+
if (err instanceof TypeError && /fetch failed/i.test(message)) {
|
|
91
|
+
const cause = err.cause;
|
|
92
|
+
return {
|
|
93
|
+
status: "unreachable",
|
|
94
|
+
error: cause ? `fetch failed: ${msg(cause).slice(0, 300)}` : message,
|
|
95
|
+
hint: null
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const closed = err instanceof McpError && err.code === ErrorCode.ConnectionClosed || /connection closed/i.test(message);
|
|
99
|
+
if (closed && ctx.transport === "stdio") {
|
|
100
|
+
const missing = sniffMissingEnv(ctx.stderrTail);
|
|
101
|
+
if (missing) {
|
|
102
|
+
return {
|
|
103
|
+
status: "needs_config",
|
|
104
|
+
error: `the server exited, and its output names ${missing} as required`,
|
|
105
|
+
hint: `set ${missing} in this server's env block`
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (ctx.stdoutNoise > 0 && !ctx.stderrTail.trim()) {
|
|
109
|
+
return {
|
|
110
|
+
status: "protocol_error",
|
|
111
|
+
error: "the server wrote non-protocol output to stdout and then closed",
|
|
112
|
+
hint: "stdio servers must log to stderr; stdout is reserved for JSON-RPC"
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
status: "spawn_failed",
|
|
117
|
+
error: ctx.stderrTail.trim() ? `exited before completing the handshake: ${ctx.stderrTail.trim().split("\n").slice(-3).join(" | ")}` : "exited before completing the handshake",
|
|
118
|
+
hint: null
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (/protocol version is not supported/i.test(message)) {
|
|
122
|
+
return {
|
|
123
|
+
status: "protocol_error",
|
|
124
|
+
error: message,
|
|
125
|
+
hint: "the server speaks a protocol revision this lurq version does not; upgrade lurq"
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (ctx.stdoutNoise > 0) {
|
|
129
|
+
return {
|
|
130
|
+
status: "protocol_error",
|
|
131
|
+
error: `${message} (the server also wrote ${ctx.stdoutNoise} non-protocol line(s) to stdout)`,
|
|
132
|
+
hint: "stdio servers must log to stderr; stdout is reserved for JSON-RPC"
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return { status: "protocol_error", error: message || "unknown error", hint: null };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
sniffMissingEnv,
|
|
140
|
+
classifyError
|
|
141
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-I3M2KJXB.js";
|
|
5
|
+
|
|
6
|
+
// src/remoteProbe/url.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
var PLACEHOLDER = /\{[^{}]+\}/;
|
|
9
|
+
function endpointIdentity(raw) {
|
|
10
|
+
if (typeof raw !== "string") return null;
|
|
11
|
+
const trimmed = raw.trim();
|
|
12
|
+
if (!trimmed || trimmed.length > 2048) return null;
|
|
13
|
+
const templated = PLACEHOLDER.test(trimmed);
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = new URL(templated ? trimmed.replace(/\{[^{}]+\}/g, "placeholder") : trimmed);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
|
|
21
|
+
const host = parsed.hostname.toLowerCase();
|
|
22
|
+
if (!host) return null;
|
|
23
|
+
if (templated) return { url: trimmed, host, templated: true };
|
|
24
|
+
parsed.hash = "";
|
|
25
|
+
const path = parsed.pathname === "/" ? "" : parsed.pathname;
|
|
26
|
+
const port = parsed.port ? `:${parsed.port}` : "";
|
|
27
|
+
const auth = parsed.username ? `${parsed.username}${parsed.password ? `:${parsed.password}` : ""}@` : "";
|
|
28
|
+
return {
|
|
29
|
+
url: `${parsed.protocol}//${auth}${host}${port}${path}${parsed.search}`,
|
|
30
|
+
host,
|
|
31
|
+
templated: false
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
endpointIdentity
|
|
37
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
require_semver
|
|
4
|
+
} from "./chunk-3GHJR7XR.js";
|
|
5
|
+
import {
|
|
6
|
+
__toESM,
|
|
7
|
+
init_esm_shims
|
|
8
|
+
} from "./chunk-I3M2KJXB.js";
|
|
9
|
+
|
|
10
|
+
// src/fix/manifest.ts
|
|
11
|
+
init_esm_shims();
|
|
12
|
+
var import_semver = __toESM(require_semver(), 1);
|
|
13
|
+
import { readFileSync } from "fs";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import ts from "typescript";
|
|
16
|
+
var BLOCKS = ["dependencies", "devDependencies", "optionalDependencies"];
|
|
17
|
+
var SIMPLE_RANGE = /^(\^|~)?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/;
|
|
18
|
+
function declaredRange(text, pkg) {
|
|
19
|
+
const sf = ts.parseJsonText("package.json", text);
|
|
20
|
+
const root = sf.statements[0]?.expression;
|
|
21
|
+
if (!root || !ts.isObjectLiteralExpression(root)) return null;
|
|
22
|
+
const propNamed = (obj, name) => obj.properties.find(
|
|
23
|
+
(p) => ts.isPropertyAssignment(p) && ts.isStringLiteral(p.name) && p.name.text === name
|
|
24
|
+
);
|
|
25
|
+
for (const block of BLOCKS) {
|
|
26
|
+
const blockProp = propNamed(root, block);
|
|
27
|
+
if (!blockProp || !ts.isObjectLiteralExpression(blockProp.initializer)) continue;
|
|
28
|
+
const dep = propNamed(blockProp.initializer, pkg);
|
|
29
|
+
if (!dep || !ts.isStringLiteral(dep.initializer)) continue;
|
|
30
|
+
const node = dep.initializer;
|
|
31
|
+
return { block, range: node.text, start: node.getStart(sf) + 1, end: node.getEnd() - 1 };
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function decideRange(file, found, toVersion) {
|
|
36
|
+
if (!import_semver.default.valid(toVersion)) {
|
|
37
|
+
return { refusedBecause: `${toVersion} is not an exact version` };
|
|
38
|
+
}
|
|
39
|
+
if (import_semver.default.validRange(found.range) && import_semver.default.satisfies(toVersion, found.range)) {
|
|
40
|
+
return { satisfied: true };
|
|
41
|
+
}
|
|
42
|
+
const simple = SIMPLE_RANGE.exec(found.range);
|
|
43
|
+
if (!simple) {
|
|
44
|
+
return {
|
|
45
|
+
refusedBecause: `"${found.range}" is not a plain ^, ~ or exact range, so what it should become is a judgement`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const prefix = simple[1] ?? "";
|
|
49
|
+
return {
|
|
50
|
+
edit: {
|
|
51
|
+
file,
|
|
52
|
+
start: found.start,
|
|
53
|
+
end: found.end,
|
|
54
|
+
text: `${prefix}${toVersion}`,
|
|
55
|
+
was: found.range
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function manifestFindings(root, targets, opts = {}) {
|
|
60
|
+
const files = opts.files ?? ["package.json"];
|
|
61
|
+
const read = opts.read ?? ((file) => {
|
|
62
|
+
try {
|
|
63
|
+
return readFileSync(join(root, file), "utf8");
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const texts = /* @__PURE__ */ new Map();
|
|
69
|
+
for (const file of files) {
|
|
70
|
+
const text = read(file);
|
|
71
|
+
if (text !== null) texts.set(file, text);
|
|
72
|
+
}
|
|
73
|
+
const findings = [];
|
|
74
|
+
const refused = [];
|
|
75
|
+
for (const target of targets) {
|
|
76
|
+
const edits = [];
|
|
77
|
+
const bumped = [];
|
|
78
|
+
for (const [file, text] of texts) {
|
|
79
|
+
const found = declaredRange(text, target.package);
|
|
80
|
+
if (!found) continue;
|
|
81
|
+
const decision = decideRange(file, found, target.toVersion);
|
|
82
|
+
if (decision.edit) {
|
|
83
|
+
edits.push(decision.edit);
|
|
84
|
+
bumped.push(file);
|
|
85
|
+
} else if (decision.refusedBecause) {
|
|
86
|
+
refused.push({ package: target.package, file, reason: decision.refusedBecause });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (edits.length === 0) continue;
|
|
90
|
+
findings.push({
|
|
91
|
+
domain: "package",
|
|
92
|
+
code: `outdated-range:${target.package}`,
|
|
93
|
+
// Blocking: with the source rewritten and the range still pinning the old
|
|
94
|
+
// major, the next install puts the old version back under new code.
|
|
95
|
+
severity: "blocking",
|
|
96
|
+
detail: `${target.package} is declared at a range that excludes ${target.toVersion} in ${bumped.length} manifest(s): ${bumped.join(", ")}`,
|
|
97
|
+
file: bumped[0],
|
|
98
|
+
evidence: `upgrading ${target.package} ${target.fromVersion} \u2192 ${target.toVersion}`,
|
|
99
|
+
fix: {
|
|
100
|
+
summary: `bump ${target.package} to ${target.toVersion} in ${bumped.length} manifest(s)`,
|
|
101
|
+
edits,
|
|
102
|
+
// Installing is the user's call; the type check is what proves the tree agrees.
|
|
103
|
+
verify: ["typecheck"]
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return { findings, refused };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
declaredRange,
|
|
112
|
+
decideRange,
|
|
113
|
+
manifestFindings
|
|
114
|
+
};
|
|
@@ -2,27 +2,19 @@ import { createRequire as __lurqCreateRequire } from 'node:module'; const requir
|
|
|
2
2
|
import {
|
|
3
3
|
assessVerdict
|
|
4
4
|
} from "./chunk-QSL6QN5X.js";
|
|
5
|
-
import {
|
|
6
|
-
getStoredSurface,
|
|
7
|
-
upsertSurface
|
|
8
|
-
} from "./chunk-M6NYEXCW.js";
|
|
9
5
|
import {
|
|
10
6
|
getLatestVerificationByName
|
|
11
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NYZU5NCW.js";
|
|
12
8
|
import {
|
|
13
9
|
getStackResolution,
|
|
14
10
|
recordStackResolution,
|
|
15
11
|
resolveSet,
|
|
16
12
|
stackKey
|
|
17
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2WD4QAH4.js";
|
|
18
14
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
diffPolicies,
|
|
23
|
-
hasRules,
|
|
24
|
-
withoutExpired
|
|
25
|
-
} from "./chunk-PSX3GIAN.js";
|
|
15
|
+
getStoredSurface,
|
|
16
|
+
upsertSurface
|
|
17
|
+
} from "./chunk-DSROTZ3Z.js";
|
|
26
18
|
import {
|
|
27
19
|
FIRST_TOUCH_BUDGET_MS,
|
|
28
20
|
assembleMembers,
|
|
@@ -35,7 +27,7 @@ import {
|
|
|
35
27
|
lookupSuccessor,
|
|
36
28
|
recordOutcome,
|
|
37
29
|
truncateSentences
|
|
38
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-TUXQ32WE.js";
|
|
39
31
|
import {
|
|
40
32
|
resolveArchitectureCompat,
|
|
41
33
|
resolveRuntimeEngineConflicts
|
|
@@ -44,32 +36,25 @@ import {
|
|
|
44
36
|
CONFIDENCE_WEIGHT,
|
|
45
37
|
RANKING,
|
|
46
38
|
loadWeights
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import {
|
|
49
|
-
withBudget
|
|
50
|
-
} from "./chunk-4ESO33J6.js";
|
|
39
|
+
} from "./chunk-6DM6UQFD.js";
|
|
51
40
|
import {
|
|
52
41
|
enqueueCompatVerify,
|
|
53
42
|
getSandboxEdges,
|
|
54
43
|
pairKey
|
|
55
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-EYAKM6YN.js";
|
|
56
45
|
import {
|
|
57
46
|
fetchNpmCompatAtVersion,
|
|
58
47
|
fetchNpmRegistry,
|
|
59
48
|
npmPackageExists,
|
|
60
49
|
npmVersionExists
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import {
|
|
63
|
-
HttpError,
|
|
64
|
-
httpRequest
|
|
65
|
-
} from "./chunk-SJOVFF7B.js";
|
|
50
|
+
} from "./chunk-D3VTZS7V.js";
|
|
66
51
|
import {
|
|
67
|
-
|
|
68
|
-
} from "./chunk-
|
|
52
|
+
withBudget
|
|
53
|
+
} from "./chunk-4ESO33J6.js";
|
|
69
54
|
import {
|
|
70
55
|
getPackageByName,
|
|
71
56
|
getTopPackageNames
|
|
72
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-NPVN2THM.js";
|
|
73
58
|
import {
|
|
74
59
|
DEFAULT_ECOSYSTEM
|
|
75
60
|
} from "./chunk-VLRHFMGJ.js";
|
|
@@ -78,14 +63,29 @@ import {
|
|
|
78
63
|
policyDecisions,
|
|
79
64
|
selectionPolicies,
|
|
80
65
|
selectionPolicyChanges
|
|
81
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-4JHDSVIN.js";
|
|
67
|
+
import {
|
|
68
|
+
HttpError,
|
|
69
|
+
httpRequest
|
|
70
|
+
} from "./chunk-KYKSZ3XZ.js";
|
|
71
|
+
import {
|
|
72
|
+
applyPolicy,
|
|
73
|
+
check,
|
|
74
|
+
describeRules,
|
|
75
|
+
diffPolicies,
|
|
76
|
+
hasRules,
|
|
77
|
+
withoutExpired
|
|
78
|
+
} from "./chunk-HWFX4BC4.js";
|
|
79
|
+
import {
|
|
80
|
+
cached
|
|
81
|
+
} from "./chunk-6L67QMCP.js";
|
|
82
82
|
import {
|
|
83
83
|
logger
|
|
84
84
|
} from "./chunk-MYGSLK44.js";
|
|
85
85
|
import {
|
|
86
86
|
CACHE_TTL,
|
|
87
87
|
STALENESS_DAYS
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-72Y2FDVS.js";
|
|
89
89
|
import {
|
|
90
90
|
init_esm_shims
|
|
91
91
|
} from "./chunk-I3M2KJXB.js";
|
|
@@ -616,9 +616,25 @@ async function recommend(db, opts, provider = createEmbeddingProvider()) {
|
|
|
616
616
|
if (!queryVec) opts.onDegraded?.("vector retrieval unavailable");
|
|
617
617
|
const category = opts.category ?? inferCategory(opts.need);
|
|
618
618
|
const pool = Math.max(limit * 5, 25);
|
|
619
|
-
let fused = await hybridSearch(
|
|
619
|
+
let fused = await hybridSearch(
|
|
620
|
+
db,
|
|
621
|
+
queryVec,
|
|
622
|
+
provider.id,
|
|
623
|
+
opts.need,
|
|
624
|
+
opts.constraints,
|
|
625
|
+
category,
|
|
626
|
+
pool
|
|
627
|
+
);
|
|
620
628
|
if (category && fused.length < limit) {
|
|
621
|
-
const broad = await hybridSearch(
|
|
629
|
+
const broad = await hybridSearch(
|
|
630
|
+
db,
|
|
631
|
+
queryVec,
|
|
632
|
+
provider.id,
|
|
633
|
+
opts.need,
|
|
634
|
+
opts.constraints,
|
|
635
|
+
null,
|
|
636
|
+
pool
|
|
637
|
+
);
|
|
622
638
|
const seen = new Set(fused.map((f) => f.row.name));
|
|
623
639
|
fused = fused.concat(broad.filter((f) => !seen.has(f.row.name)));
|
|
624
640
|
}
|
|
@@ -695,7 +711,10 @@ async function runVectorQuery(db, queryVec, providerId, constraints, category, p
|
|
|
695
711
|
async function runLexicalQuery(db, need, constraints, category, pool) {
|
|
696
712
|
const tsquery = sql`websearch_to_tsquery('english', ${need})`;
|
|
697
713
|
const rank = sql`ts_rank(${packages.searchVector}, ${tsquery})`;
|
|
698
|
-
const conditions = [
|
|
714
|
+
const conditions = [
|
|
715
|
+
sql`${packages.searchVector} @@ ${tsquery}`,
|
|
716
|
+
...buildConditions(constraints, category)
|
|
717
|
+
];
|
|
699
718
|
return db.select(ROW_COLUMNS).from(packages).where(and(...conditions)).orderBy(sql`${rank} desc`).limit(pool);
|
|
700
719
|
}
|
|
701
720
|
function toCandidate(row) {
|
|
@@ -1087,11 +1106,7 @@ function editDistance(a, b) {
|
|
|
1087
1106
|
cur[0] = i;
|
|
1088
1107
|
for (let j = 1; j <= n; j++) {
|
|
1089
1108
|
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
1090
|
-
let val = Math.min(
|
|
1091
|
-
(prev[j] ?? 0) + 1,
|
|
1092
|
-
(cur[j - 1] ?? 0) + 1,
|
|
1093
|
-
(prev[j - 1] ?? 0) + cost
|
|
1094
|
-
);
|
|
1109
|
+
let val = Math.min((prev[j] ?? 0) + 1, (cur[j - 1] ?? 0) + 1, (prev[j - 1] ?? 0) + cost);
|
|
1095
1110
|
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
1096
1111
|
val = Math.min(val, (prevPrev[j - 2] ?? 0) + 1);
|
|
1097
1112
|
}
|
|
@@ -1506,7 +1521,9 @@ async function handleUsage(db, input) {
|
|
|
1506
1521
|
// The README is not in this response, so "fall back to the README"
|
|
1507
1522
|
// left the agent with nothing to act on. Name the two things it can do.
|
|
1508
1523
|
`No type-derived API surface for ${input.package}@${version}: it ships no .d.ts and ${types} has no matching major, or extraction is still running (retry in a few seconds). For the names it exports at runtime call resolve_surface; for usage, read https://www.npmjs.com/package/${input.package}/v/${version}.`
|
|
1509
|
-
) : shallow ? `Shallow surface: ${input.package} exports one value typed by ${surface.filter((s) => s.name !== "default").map((s) => s.name).join(
|
|
1524
|
+
) : shallow ? `Shallow surface: ${input.package} exports one value typed by ${surface.filter((s) => s.name !== "default").map((s) => s.name).join(
|
|
1525
|
+
", "
|
|
1526
|
+
)}, so its methods are that interface's members and are NOT listed here. Read them in its type declarations (${types} if the package bundles none), or call resolve_surface for the names it exports at runtime.` : page?.note
|
|
1510
1527
|
};
|
|
1511
1528
|
if (input.knownVersion && input.knownVersion !== version && surface) {
|
|
1512
1529
|
const known = await getOrExtractSurface(db, input.package, input.knownVersion, {
|
|
@@ -115,12 +115,29 @@ var FIELD = {
|
|
|
115
115
|
/** Reports at or above this cap the confidence note as fully-evidenced. */
|
|
116
116
|
wellEvidencedReports: 25
|
|
117
117
|
};
|
|
118
|
+
var DISCOVERY = {
|
|
119
|
+
/** A queued candidate must clear this quality pre-score to graduate to ingest. */
|
|
120
|
+
minPreScore: 45,
|
|
121
|
+
/** Max candidates fully ingested per crawler run (cost bound). */
|
|
122
|
+
perRunCap: 25,
|
|
123
|
+
/** npm-search hits to pull per category keyword. */
|
|
124
|
+
searchSizePerCategory: 10,
|
|
125
|
+
/** Max dependency-graph neighbors to enqueue per tracked seed. */
|
|
126
|
+
graphNeighborsPerSeed: 20,
|
|
127
|
+
/** Ingest failures a candidate gets before it is marked `failed` and stops
|
|
128
|
+
* being retried. Three, because the failures worth retrying are transient
|
|
129
|
+
* (a registry 5xx, a GitHub rate limit) and clear within an hour or two,
|
|
130
|
+
* while the ones that are not — a manifest we cannot parse — would otherwise
|
|
131
|
+
* re-buy an LLM summary every cycle for as long as the crawler runs. */
|
|
132
|
+
maxIngestAttempts: 3
|
|
133
|
+
};
|
|
118
134
|
var DEFAULT_WEIGHTS = {
|
|
119
135
|
health: { ...HEALTH_WEIGHTS },
|
|
120
136
|
composite: { ...COMPOSITE }
|
|
121
137
|
};
|
|
122
138
|
function activeWeightsPath() {
|
|
123
|
-
if (existsSync(projectWeightsPath()))
|
|
139
|
+
if (existsSync(projectWeightsPath()))
|
|
140
|
+
return { path: projectWeightsPath(), source: "project-config" };
|
|
124
141
|
if (existsSync(userWeightsPath())) return { path: userWeightsPath(), source: "user-config" };
|
|
125
142
|
return null;
|
|
126
143
|
}
|
|
@@ -288,6 +305,7 @@ export {
|
|
|
288
305
|
RELIABILITY,
|
|
289
306
|
EFFICIENCY,
|
|
290
307
|
FIELD,
|
|
308
|
+
DISCOVERY,
|
|
291
309
|
activeWeightsPath,
|
|
292
310
|
loadWeights,
|
|
293
311
|
validateWeights,
|
|
@@ -9,7 +9,7 @@ init_esm_shims();
|
|
|
9
9
|
// package.json
|
|
10
10
|
var package_default = {
|
|
11
11
|
name: "lurqrun",
|
|
12
|
-
version: "0.1.
|
|
12
|
+
version: "0.1.8",
|
|
13
13
|
description: "Verify npm packages before your AI coding agent installs them: hallucinated and typosquatted names, advisories, API drift and version conflicts. MCP server, CLI and agent skill for Claude Code, Cursor and VS Code.",
|
|
14
14
|
type: "module",
|
|
15
15
|
license: "MIT",
|
|
@@ -116,6 +116,7 @@ var package_default = {
|
|
|
116
116
|
semver: "^7.8.5",
|
|
117
117
|
stripe: "^22.6.0",
|
|
118
118
|
typescript: "^5.5.4",
|
|
119
|
+
undici: "^7.29.1",
|
|
119
120
|
yaml: "^2.9.0",
|
|
120
121
|
zod: "^3.23.8"
|
|
121
122
|
},
|