lurqrun 0.1.7 → 0.1.9
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-G7PHKMZR.js} +12 -11
- package/dist/autopilotInit-JO2SH5K3.js +266 -0
- package/dist/bin/lurq.js +238 -83
- package/dist/{browserAuth-B6G27USY.js → browserAuth-PVYODBNR.js} +4 -3
- package/dist/{cache-DKI34SVS.js → cache-ND4VOUVY.js} +2 -2
- package/dist/check-A3FJE62G.js +2613 -0
- package/dist/{check-2FDGUOV7.js → check-PQSQ2MMA.js} +1 -1
- package/dist/checkUpgrade-Q4CV7GXG.js +24 -0
- package/dist/{chunk-BCANRN5B.js → chunk-2GAYNIHG.js} +8 -1
- package/dist/chunk-2LXYRDUN.js +92 -0
- package/dist/chunk-2XMD4H2I.js +243 -0
- package/dist/chunk-3D2MPGOQ.js +181 -0
- package/dist/chunk-53SG6XWA.js +141 -0
- package/dist/chunk-5ABNDB3I.js +37 -0
- package/dist/chunk-5ALIJFDA.js +114 -0
- package/dist/{chunk-LYMPYETA.js → chunk-6353IJJ5.js} +270 -6
- package/dist/{chunk-M6NYEXCW.js → chunk-64DPQSXV.js} +1 -1
- package/dist/chunk-64YOP5BQ.js +320 -0
- package/dist/{chunk-2VMOWSRY.js → chunk-6DM6UQFD.js} +19 -1
- package/dist/{chunk-NH5I4KHH.js → chunk-75LMEMJ3.js} +1 -5
- package/dist/{chunk-FW6BD2NO.js → chunk-ABH4BTK4.js} +458 -121
- package/dist/chunk-AHRDDKNO.js +90 -0
- package/dist/chunk-AQ6IVSFB.js +119 -0
- package/dist/chunk-BM3LF5T6.js +132 -0
- package/dist/chunk-D3K6IZVR.js +12845 -0
- package/dist/chunk-DONTW3NE.js +171 -0
- package/dist/{chunk-UDVNA7EA.js → chunk-ETY4FSOW.js} +161 -8
- package/dist/{chunk-VL2E5T2A.js → chunk-FHRT32JH.js} +6 -3
- package/dist/{chunk-DWAGCNEL.js → chunk-GM5Y555O.js} +36 -103
- package/dist/{chunk-6L3U7DZ5.js → chunk-GNNGXVCG.js} +1 -1
- package/dist/{chunk-PSX3GIAN.js → chunk-HWFX4BC4.js} +2 -1
- package/dist/{checkUpgrade-F2WESBPM.js → chunk-ILKYIVYV.js} +72 -10
- package/dist/{chunk-HWBBVLOT.js → chunk-J3NUERU7.js} +1 -1
- package/dist/chunk-J3U2CPSK.js +136 -0
- package/dist/{chunk-Y5GI7RL3.js → chunk-J6XQ7OPZ.js} +9 -1
- package/dist/{chunk-3N3Q3DSW.js → chunk-JGIJZJ3X.js} +8 -8
- package/dist/{chunk-DB2VF5UD.js → chunk-JJCQVOC6.js} +16 -11
- package/dist/{chunk-LBFGSSF2.js → chunk-KMV4Y6R3.js} +2 -1
- package/dist/{chunk-L6N4JFW2.js → chunk-KP5ZDDPE.js} +81 -4
- package/dist/{chunk-CW5HJ3LX.js → chunk-KT7PWDNV.js} +1 -1
- package/dist/{chunk-SJOVFF7B.js → chunk-KYKSZ3XZ.js} +3 -2
- package/dist/{chunk-GPTKSNR6.js → chunk-L3V7AVM6.js} +2 -1
- package/dist/{chunk-CUP36ND3.js → chunk-M2CYYBAH.js} +145 -36
- package/dist/{chunk-IQ4SDKKY.js → chunk-N2NYPTRU.js} +31 -228
- package/dist/chunk-N4TJO44E.js +603 -0
- package/dist/chunk-NEZNAPPN.js +41 -0
- package/dist/{chunk-WQ23REYT.js → chunk-NGMJQBOV.js} +1 -1
- package/dist/{chunk-BULZAX2U.js → chunk-POHTPT37.js} +55 -38
- package/dist/{chunk-EA3DP5HG.js → chunk-PZZU3FQY.js} +155 -25
- package/dist/{chunk-4F7ZESPO.js → chunk-Q7CMOU5C.js} +3 -5
- package/dist/{chunk-LRD4GBYE.js → chunk-QUIMQ7YL.js} +1 -1
- package/dist/chunk-RG3YLU6E.js +49 -0
- package/dist/{chunk-4ZYCIMY4.js → chunk-SFY5MPJE.js} +25 -4
- package/dist/{chunk-ST2X2GYN.js → chunk-SHZFOSXC.js} +109 -20
- package/dist/{chunk-CIDWNUAP.js → chunk-SOXFMMXC.js} +8 -2
- package/dist/{chunk-B43LCXBM.js → chunk-SWMWVK2R.js} +81 -16
- package/dist/{chunk-J5FZYN4A.js → chunk-TVOCVIM7.js} +1 -1
- package/dist/{chunk-U5AT3TD4.js → chunk-X4W64MHU.js} +1735 -1858
- package/dist/{chunk-BV32UNLL.js → chunk-XA2SLNBR.js} +2 -2
- package/dist/{chunk-AHBP533R.js → chunk-XBTYJQEK.js} +7 -5
- 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-LO35HLQZ.js → chunk-ZJ5XHA77.js} +25 -4
- package/dist/{client-IRKAMDYZ.js → client-SJIWK4CK.js} +3 -3
- package/dist/{commands-FIL5ET6P.js → commands-6BBLN5N5.js} +145 -33
- package/dist/{compat-R3UTFQ5Q.js → compat-6B3CRT5F.js} +6 -6
- package/dist/constants-HX3RTD6Q.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-RKRPVP5A.js +14 -0
- package/dist/env-UN6KGZ7S.js +15 -0
- package/dist/envCheck-IL22OTSC.js +71 -0
- package/dist/{extract-NKGKLIVT.js → extract-6WG265BL.js} +14 -3
- package/dist/{fetch-QYTUJVG2.js → fetch-GHIP3VHN.js} +4 -4
- package/dist/{firstTouch-QQTJH4QX.js → firstTouch-M64T2MWF.js} +1 -1
- package/dist/fix-Z7ZY55HB.js +220 -0
- package/dist/{handlers-GEJAVZDK.js → handlers-GOXW2GWZ.js} +19 -17
- package/dist/hook-TWFLIDK3.js +412 -0
- package/dist/{http-ETPYMBGD.js → http-7VF2RE2D.js} +2097 -509
- package/dist/{ingestQueue-VKN4KBIF.js → ingestQueue-RSEPMORK.js} +14 -12
- package/dist/{install-EK3W2COX.js → install-55EPX34C.js} +6 -6
- package/dist/{installSkill-VQJWJVCL.js → installSkill-A7KKPDMS.js} +21 -3
- package/dist/manifest-ENMIC54B.js +13 -0
- package/dist/{mcp-3JHD5SUZ.js → mcp-CM6CDLHM.js} +60 -32
- package/dist/mcpConfig-FENV6NI7.js +80 -0
- package/dist/{mcpHandlers-QFN4MCFL.js → mcpHandlers-2UCLKMWN.js} +7 -7
- package/dist/{mcpScan-QZHWENIP.js → mcpScan-CKBQNK5H.js} +306 -442
- package/dist/{mcpScanWorkflow-JPYCBGC4.js → mcpScanWorkflow-NFUD3S7U.js} +29 -12
- package/dist/{mcpStack-BYJCZNIV.js → mcpStack-FLQ6XY2P.js} +1 -1
- package/dist/model-ASMZWLM7.js +214 -0
- package/dist/{packages-THVFMWFP.js → packages-2XRHNBJ7.js} +3 -5
- package/dist/{plan-V4OEI3J4.js → plan-XRZS6C7Z.js} +23 -21
- package/dist/{planView-JRXGCG2N.js → planView-ZAKRTGVS.js} +4 -1
- package/dist/{policy-3P6BGRDN.js → policy-EQT43P7S.js} +5 -5
- package/dist/probe-ZEZFNIQZ.js +610 -0
- package/dist/publicUpgrades-JZEOV24A.js +42 -0
- package/dist/{references-6N7VEPHT.js → references-I6Y4BSRR.js} +3 -1
- package/dist/{release-4U4ABNSJ.js → release-EUOM5I3R.js} +5 -5
- package/dist/{remote-YGCXYI4V.js → remote-I5O43WAY.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-46TZNYZT.js} +4 -4
- package/dist/sarif-WLVJFJ7U.js +125 -0
- package/dist/server-LROMHS62.js +59 -0
- package/dist/{surface-YL6O67W3.js → surface-CZMHQLV3.js} +5 -3
- package/dist/{surface-V62GE554.js → surface-OH4TZR32.js} +18 -16
- package/dist/{surfaceHandlers-X2IZKA3E.js → surfaceHandlers-BDYRZMAC.js} +5 -5
- package/dist/{typecheck-X7U5ELMR.js → typecheck-NGOKNAJY.js} +23 -9
- package/dist/{uninstall-P7RGBX6G.js → uninstall-4E5YUDQO.js} +30 -4
- package/dist/{upgrade-NQ5IWFZB.js → upgrade-S72W7JVC.js} +86 -32
- package/dist/{upgradePlan-A4LRKLEG.js → upgradePlan-F3OUNL3E.js} +46 -11
- package/dist/upkeepHandler-7Q56A4UA.js +13 -0
- package/dist/{userConfig-Z3GQE776.js → userConfig-ICASHI47.js} +1 -1
- package/dist/{watch-DGFMWUDL.js → watch-LZPOKWCL.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,320 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
handleDiffSurface
|
|
4
|
+
} from "./chunk-JJCQVOC6.js";
|
|
5
|
+
import {
|
|
6
|
+
getPackageByName
|
|
7
|
+
} from "./chunk-75LMEMJ3.js";
|
|
8
|
+
import {
|
|
9
|
+
enqueueSurface
|
|
10
|
+
} from "./chunk-ZJ5XHA77.js";
|
|
11
|
+
import {
|
|
12
|
+
packages,
|
|
13
|
+
surfaceQueue
|
|
14
|
+
} from "./chunk-6353IJJ5.js";
|
|
15
|
+
import {
|
|
16
|
+
require_semver
|
|
17
|
+
} from "./chunk-3GHJR7XR.js";
|
|
18
|
+
import {
|
|
19
|
+
logger
|
|
20
|
+
} from "./chunk-MYGSLK44.js";
|
|
21
|
+
import {
|
|
22
|
+
__toESM,
|
|
23
|
+
init_esm_shims
|
|
24
|
+
} from "./chunk-I3M2KJXB.js";
|
|
25
|
+
|
|
26
|
+
// src/mcp/publicUpgrades.ts
|
|
27
|
+
init_esm_shims();
|
|
28
|
+
var import_semver = __toESM(require_semver(), 1);
|
|
29
|
+
import { and as and2, count, desc as desc2, gte, isNotNull as isNotNull2, sql } from "drizzle-orm";
|
|
30
|
+
|
|
31
|
+
// src/mcp/publicSet.ts
|
|
32
|
+
init_esm_shims();
|
|
33
|
+
import { and, desc, isNotNull } from "drizzle-orm";
|
|
34
|
+
var PUBLIC_TOP_LIMIT = 5e3;
|
|
35
|
+
var NPM_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/i;
|
|
36
|
+
function validPackageName(name) {
|
|
37
|
+
return name.length > 0 && name.length <= 214 && NPM_NAME.test(name);
|
|
38
|
+
}
|
|
39
|
+
var floor = null;
|
|
40
|
+
async function publicDownloadFloor(db) {
|
|
41
|
+
if (floor && Date.now() - floor.at < 36e5) return floor.value;
|
|
42
|
+
const rows = await db.select({ downloads: packages.weeklyDownloads }).from(packages).where(and(isNotNull(packages.weeklyDownloads), isNotNull(packages.healthScore))).orderBy(desc(packages.weeklyDownloads)).offset(PUBLIC_TOP_LIMIT - 1).limit(1);
|
|
43
|
+
floor = { at: Date.now(), value: Number(rows[0]?.downloads ?? 0) };
|
|
44
|
+
return floor.value;
|
|
45
|
+
}
|
|
46
|
+
async function publicPackageRow(db, name) {
|
|
47
|
+
const [row, min] = await Promise.all([getPackageByName(db, name), publicDownloadFloor(db)]);
|
|
48
|
+
if (!row || row.healthScore === null || (row.weeklyDownloads ?? 0) < min) return null;
|
|
49
|
+
return row;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/mcp/publicUpgrades.ts
|
|
53
|
+
var PAIRS_PER_PACKAGE = 3;
|
|
54
|
+
var LIST_CAP = 500;
|
|
55
|
+
function majorPairs(latest, keep = PAIRS_PER_PACKAGE) {
|
|
56
|
+
const sorted = [...latest].sort((a, b) => a.major - b.major);
|
|
57
|
+
const pairs = [];
|
|
58
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
59
|
+
const from = sorted[i - 1];
|
|
60
|
+
const to = sorted[i];
|
|
61
|
+
pairs.push({
|
|
62
|
+
fromMajor: from.major,
|
|
63
|
+
toMajor: to.major,
|
|
64
|
+
fromVersion: from.version,
|
|
65
|
+
toVersion: to.version,
|
|
66
|
+
ready: from.stored && to.stored
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return pairs.slice(-keep);
|
|
70
|
+
}
|
|
71
|
+
function unextractedSides(latest, keep = PAIRS_PER_PACKAGE) {
|
|
72
|
+
if (latest.length < 2) return [];
|
|
73
|
+
const involved = [...latest].sort((a, b) => a.major - b.major).slice(-(keep + 1));
|
|
74
|
+
return involved.reverse().filter((l) => !l.stored && !l.attempted).map((l) => l.version);
|
|
75
|
+
}
|
|
76
|
+
function upgradeVerdict(d) {
|
|
77
|
+
if (d.inconclusive) return "unknown";
|
|
78
|
+
if (d.removed.length > 0 || d.renamed.length > 0) return "removes-exports";
|
|
79
|
+
if (d.arityChanged.length > 0) return "arity-changed";
|
|
80
|
+
if (d.typeOnlyRemoved.length > 0) return "types-only";
|
|
81
|
+
return "clean";
|
|
82
|
+
}
|
|
83
|
+
function toPublicUpgrade(pkg, pair, diff) {
|
|
84
|
+
const renamedPaths = new Set(diff.renamed.map((r) => r.path));
|
|
85
|
+
const removed = diff.removed.filter((r) => !renamedPaths.has(r.path));
|
|
86
|
+
const lists = [
|
|
87
|
+
removed,
|
|
88
|
+
diff.renamed,
|
|
89
|
+
diff.arityChanged,
|
|
90
|
+
diff.typeOnlyRemoved,
|
|
91
|
+
diff.deprecated
|
|
92
|
+
];
|
|
93
|
+
const cap = (xs) => xs.slice(0, LIST_CAP);
|
|
94
|
+
return {
|
|
95
|
+
package: pkg,
|
|
96
|
+
pair,
|
|
97
|
+
status: "ready",
|
|
98
|
+
verdict: upgradeVerdict({ ...diff, removed }),
|
|
99
|
+
removed: cap(removed.map((r) => ({ path: r.path, kind: r.kind }))),
|
|
100
|
+
renamed: cap(diff.renamed),
|
|
101
|
+
arityChanged: cap(diff.arityChanged),
|
|
102
|
+
typeOnlyRemoved: cap(diff.typeOnlyRemoved),
|
|
103
|
+
deprecated: cap(diff.deprecated),
|
|
104
|
+
added: diff.added.length,
|
|
105
|
+
truncated: lists.some((l) => l.length > LIST_CAP),
|
|
106
|
+
tier: diff.tier ?? null,
|
|
107
|
+
inconclusive: diff.inconclusive ?? null,
|
|
108
|
+
observedAt: diff.observedAt ? new Date(diff.observedAt).toISOString() : null
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function pendingUpgrade(pkg, pair) {
|
|
112
|
+
return {
|
|
113
|
+
package: pkg,
|
|
114
|
+
pair,
|
|
115
|
+
status: "pending",
|
|
116
|
+
verdict: "unknown",
|
|
117
|
+
removed: [],
|
|
118
|
+
renamed: [],
|
|
119
|
+
arityChanged: [],
|
|
120
|
+
typeOnlyRemoved: [],
|
|
121
|
+
deprecated: [],
|
|
122
|
+
added: 0,
|
|
123
|
+
truncated: false,
|
|
124
|
+
tier: null,
|
|
125
|
+
inconclusive: "Both versions are queued for extraction. NOT evidence that nothing changed.",
|
|
126
|
+
observedAt: null
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function rowsOf(result) {
|
|
130
|
+
return result.rows ?? result;
|
|
131
|
+
}
|
|
132
|
+
async function latestOfMajors(db, names) {
|
|
133
|
+
const out = /* @__PURE__ */ new Map();
|
|
134
|
+
if (names.length === 0) return out;
|
|
135
|
+
const result = await db.execute(sql`
|
|
136
|
+
with stable as (
|
|
137
|
+
select package_name, version, (regexp_match(version, '^([0-9]+)\\.'))[1]::int as major
|
|
138
|
+
from package_versions
|
|
139
|
+
where package_name in (${sql.join(
|
|
140
|
+
names.map((n) => sql`${n}`),
|
|
141
|
+
sql`, `
|
|
142
|
+
)})
|
|
143
|
+
-- Stable releases only: an upgrade does not land on a prerelease.
|
|
144
|
+
and version ~ '^[0-9]+\\.[0-9]+\\.[0-9]+$'
|
|
145
|
+
),
|
|
146
|
+
latest as (
|
|
147
|
+
select distinct on (package_name, major) package_name, major, version
|
|
148
|
+
from stable
|
|
149
|
+
-- Numeric, not lexical (16.10.0 is newer than 16.9.0), and numeric rather
|
|
150
|
+
-- than int so a date-stamped version cannot overflow the cast.
|
|
151
|
+
order by package_name, major, string_to_array(version, '.')::numeric[] desc
|
|
152
|
+
)
|
|
153
|
+
select
|
|
154
|
+
l.package_name,
|
|
155
|
+
l.major,
|
|
156
|
+
l.version,
|
|
157
|
+
exists (
|
|
158
|
+
select 1 from entities e
|
|
159
|
+
join symbols s on s.entity_id = e.id and s.tier = 'shipped_js_ast'
|
|
160
|
+
where e.canonical_key = 'package_surface:npm:' || l.package_name || ':' || l.version
|
|
161
|
+
and e.tenant_id = 0
|
|
162
|
+
) as stored,
|
|
163
|
+
exists (
|
|
164
|
+
select 1 from entities e
|
|
165
|
+
where e.canonical_key = 'package_surface:npm:' || l.package_name || ':' || l.version
|
|
166
|
+
and e.tenant_id = 0
|
|
167
|
+
) as attempted
|
|
168
|
+
from latest l
|
|
169
|
+
`);
|
|
170
|
+
for (const r of rowsOf(result)) {
|
|
171
|
+
const list = out.get(r.package_name) ?? [];
|
|
172
|
+
list.push({
|
|
173
|
+
major: Number(r.major),
|
|
174
|
+
version: r.version,
|
|
175
|
+
stored: Boolean(r.stored),
|
|
176
|
+
attempted: Boolean(r.attempted)
|
|
177
|
+
});
|
|
178
|
+
out.set(r.package_name, list);
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
async function upgradePairsFor(db, name) {
|
|
183
|
+
return majorPairs((await latestOfMajors(db, [name])).get(name) ?? []);
|
|
184
|
+
}
|
|
185
|
+
async function upgradeGuideFor(db, pkg, fromVersion, toVersion, webUrl) {
|
|
186
|
+
const from = import_semver.default.coerce(fromVersion)?.major;
|
|
187
|
+
const to = import_semver.default.coerce(toVersion)?.major;
|
|
188
|
+
if (from === void 0 || to === void 0 || to <= from) return null;
|
|
189
|
+
if (!await publicPackageRow(db, pkg)) return null;
|
|
190
|
+
const pair = (await upgradePairsFor(db, pkg)).find(
|
|
191
|
+
(p) => p.fromMajor === from && p.toMajor === to && p.ready
|
|
192
|
+
);
|
|
193
|
+
if (!pair) return null;
|
|
194
|
+
const path = `/npm/${pkg.split("/").map(encodeURIComponent).join("/")}/${from}-to-${to}`;
|
|
195
|
+
return {
|
|
196
|
+
url: `${webUrl.replace(/\/$/, "")}${path}`,
|
|
197
|
+
fromVersion: pair.fromVersion,
|
|
198
|
+
toVersion: pair.toVersion
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function publicNames(db, limit = PUBLIC_TOP_LIMIT) {
|
|
202
|
+
const min = await publicDownloadFloor(db);
|
|
203
|
+
const rows = await db.select({ name: packages.name }).from(packages).where(and2(isNotNull2(packages.healthScore), gte(packages.weeklyDownloads, min))).orderBy(desc2(packages.weeklyDownloads)).limit(limit);
|
|
204
|
+
return rows.map((r) => r.name);
|
|
205
|
+
}
|
|
206
|
+
var QUEUE_HEADROOM = 20;
|
|
207
|
+
async function enqueuePublicUpgrades(db, opts = {}) {
|
|
208
|
+
const [{ pending } = { pending: 0 }] = await db.select({ pending: count() }).from(surfaceQueue);
|
|
209
|
+
let budget = QUEUE_HEADROOM - Number(pending);
|
|
210
|
+
if (budget <= 0) return 0;
|
|
211
|
+
const names = await publicNames(db, opts.packages ?? 1e3);
|
|
212
|
+
let queued = 0;
|
|
213
|
+
for (let i = 0; i < names.length && budget > 0; i += 250) {
|
|
214
|
+
const chunk = names.slice(i, i + 250);
|
|
215
|
+
const latest = await latestOfMajors(db, chunk);
|
|
216
|
+
for (const name of chunk) {
|
|
217
|
+
for (const version of unextractedSides(latest.get(name) ?? [])) {
|
|
218
|
+
if (budget <= 0) break;
|
|
219
|
+
await enqueueSurface(db, name, version);
|
|
220
|
+
queued++;
|
|
221
|
+
budget--;
|
|
222
|
+
}
|
|
223
|
+
if (budget <= 0) break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return queued;
|
|
227
|
+
}
|
|
228
|
+
function registerPublicUpgradeRoutes(app, db, limiter) {
|
|
229
|
+
const cacheable = (res) => res.setHeader("Cache-Control", "public, max-age=3600, s-maxage=86400");
|
|
230
|
+
app.get("/public/upgrade", limiter, async (req, res) => {
|
|
231
|
+
const name = typeof req.query.name === "string" ? req.query.name.trim() : "";
|
|
232
|
+
const from = Number(req.query.from);
|
|
233
|
+
const to = Number(req.query.to);
|
|
234
|
+
if (!validPackageName(name) || !Number.isInteger(from) || !Number.isInteger(to) || from < 0 || to <= from) {
|
|
235
|
+
res.status(400).json({ error: "Give an npm package name and two majors, from < to." });
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
if (!await publicPackageRow(db, name)) {
|
|
240
|
+
res.status(404).json({ error: "No public upgrade pages for that package." });
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const pairs = await upgradePairsFor(db, name);
|
|
244
|
+
const pair = pairs.find((p) => p.fromMajor === from && p.toMajor === to);
|
|
245
|
+
if (!pair) {
|
|
246
|
+
res.status(404).json({ error: "No upgrade page for that version jump.", pairs });
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (!pair.ready) {
|
|
250
|
+
await Promise.all([
|
|
251
|
+
enqueueSurface(db, name, pair.fromVersion),
|
|
252
|
+
enqueueSurface(db, name, pair.toVersion)
|
|
253
|
+
]).catch(() => {
|
|
254
|
+
});
|
|
255
|
+
res.setHeader("Cache-Control", "public, max-age=300, s-maxage=900");
|
|
256
|
+
res.json(pendingUpgrade(name, pair));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const diff = await handleDiffSurface(db, {
|
|
260
|
+
package: name,
|
|
261
|
+
fromVersion: pair.fromVersion,
|
|
262
|
+
toVersion: pair.toVersion
|
|
263
|
+
});
|
|
264
|
+
const body = toPublicUpgrade(name, pair, diff);
|
|
265
|
+
if (body.verdict === "unknown")
|
|
266
|
+
res.setHeader("Cache-Control", "public, max-age=300, s-maxage=900");
|
|
267
|
+
else cacheable(res);
|
|
268
|
+
res.json(body);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
logger.error("public upgrade read failed:", err instanceof Error ? err.message : String(err));
|
|
271
|
+
res.status(500).json({ error: "Could not read that upgrade." });
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
let index = null;
|
|
275
|
+
app.get("/public/upgrades", limiter, async (_req, res) => {
|
|
276
|
+
try {
|
|
277
|
+
if (!index || Date.now() - index.at > 36e5) {
|
|
278
|
+
const names = await publicNames(db);
|
|
279
|
+
const value = [];
|
|
280
|
+
for (let i = 0; i < names.length; i += 500) {
|
|
281
|
+
const chunk = names.slice(i, i + 500);
|
|
282
|
+
const latest = await latestOfMajors(db, chunk);
|
|
283
|
+
for (const name of chunk) {
|
|
284
|
+
const ready = majorPairs(latest.get(name) ?? []).filter((p) => p.ready);
|
|
285
|
+
if (ready.length) value.push({ package: name, pairs: ready });
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
index = { at: Date.now(), value };
|
|
289
|
+
}
|
|
290
|
+
cacheable(res);
|
|
291
|
+
res.json({ upgrades: index.value });
|
|
292
|
+
} catch (err) {
|
|
293
|
+
logger.error(
|
|
294
|
+
"public upgrade index failed:",
|
|
295
|
+
err instanceof Error ? err.message : String(err)
|
|
296
|
+
);
|
|
297
|
+
res.status(500).json({ error: "Could not list upgrade pages." });
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export {
|
|
303
|
+
PUBLIC_TOP_LIMIT,
|
|
304
|
+
validPackageName,
|
|
305
|
+
publicDownloadFloor,
|
|
306
|
+
publicPackageRow,
|
|
307
|
+
PAIRS_PER_PACKAGE,
|
|
308
|
+
LIST_CAP,
|
|
309
|
+
majorPairs,
|
|
310
|
+
unextractedSides,
|
|
311
|
+
upgradeVerdict,
|
|
312
|
+
toPublicUpgrade,
|
|
313
|
+
pendingUpgrade,
|
|
314
|
+
latestOfMajors,
|
|
315
|
+
upgradePairsFor,
|
|
316
|
+
upgradeGuideFor,
|
|
317
|
+
QUEUE_HEADROOM,
|
|
318
|
+
enqueuePublicUpgrades,
|
|
319
|
+
registerPublicUpgradeRoutes
|
|
320
|
+
};
|
|
@@ -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,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
packages,
|
|
8
8
|
seedPackages,
|
|
9
9
|
syncRuns
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-6353IJJ5.js";
|
|
11
11
|
import {
|
|
12
12
|
logger
|
|
13
13
|
} from "./chunk-MYGSLK44.js";
|
|
@@ -108,9 +108,6 @@ async function getTopPackageNames(db, limit = 1e3) {
|
|
|
108
108
|
const rows = await db.select({ name: packages.name }).from(packages).where(isNotNull(packages.weeklyDownloads)).orderBy(desc(packages.weeklyDownloads)).limit(limit);
|
|
109
109
|
return rows.map((r) => r.name);
|
|
110
110
|
}
|
|
111
|
-
async function ensureSeedEntry(db, name, category) {
|
|
112
|
-
await db.insert(seedPackages).values({ name, category }).onConflictDoNothing({ target: seedPackages.name });
|
|
113
|
-
}
|
|
114
111
|
async function upsertPackage(db, row) {
|
|
115
112
|
const { name: _name, ecosystem: _ecosystem, createdAt: _createdAt, ...mutable } = row;
|
|
116
113
|
await db.insert(packages).values(row).onConflictDoUpdate({
|
|
@@ -192,7 +189,6 @@ export {
|
|
|
192
189
|
upsertPackageVersions,
|
|
193
190
|
getPackageVersions,
|
|
194
191
|
getTopPackageNames,
|
|
195
|
-
ensureSeedEntry,
|
|
196
192
|
upsertPackage,
|
|
197
193
|
stampFirstRequester,
|
|
198
194
|
getContributionsByOwner,
|