lurqrun 0.1.6 → 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.
Files changed (239) hide show
  1. package/README.md +311 -139
  2. package/dist/auditHandler-VWCXSDVO.js +24 -0
  3. package/dist/autopilotInit-Q62MX5M6.js +178 -0
  4. package/dist/bin/lurq.js +3255 -23319
  5. package/dist/browserAuth-J7APSD4P.js +96 -0
  6. package/dist/cache-AEAKCV4I.js +12 -0
  7. package/dist/check-2JTQDQA6.js +2613 -0
  8. package/dist/check-PQSQ2MMA.js +192 -0
  9. package/dist/checkUpgrade-5YW77OBL.js +24 -0
  10. package/dist/chunk-2GAYNIHG.js +40 -0
  11. package/dist/chunk-2O6Z37IT.js +423 -0
  12. package/dist/chunk-2WD4QAH4.js +116 -0
  13. package/dist/chunk-3676XOBU.js +2235 -0
  14. package/dist/chunk-3D2MPGOQ.js +181 -0
  15. package/dist/chunk-3GHJR7XR.js +2049 -0
  16. package/dist/chunk-4ESO33J6.js +34 -0
  17. package/dist/chunk-4JHDSVIN.js +1229 -0
  18. package/dist/chunk-4KCPOMG6.js +68 -0
  19. package/dist/chunk-53SG6XWA.js +141 -0
  20. package/dist/chunk-5ABNDB3I.js +37 -0
  21. package/dist/chunk-5ALIJFDA.js +114 -0
  22. package/dist/chunk-63MUJNZL.js +318 -0
  23. package/dist/chunk-64ZF7KO4.js +1571 -0
  24. package/dist/chunk-6DM6UQFD.js +318 -0
  25. package/dist/chunk-6EQ3ARXA.js +304 -0
  26. package/dist/chunk-6L67QMCP.js +92 -0
  27. package/dist/chunk-72Y2FDVS.js +172 -0
  28. package/dist/chunk-A3TYI2TF.js +288 -0
  29. package/dist/chunk-B2UUYRBX.js +536 -0
  30. package/dist/chunk-BJT2LHAR.js +320 -0
  31. package/dist/chunk-BM3LF5T6.js +132 -0
  32. package/dist/chunk-BN3NM47Q.js +214 -0
  33. package/dist/chunk-BUALU27S.js +123 -0
  34. package/dist/chunk-C6GLE626.js +160 -0
  35. package/dist/chunk-D3K6IZVR.js +12845 -0
  36. package/dist/chunk-D3VTZS7V.js +222 -0
  37. package/dist/chunk-DM37MTOO.js +636 -0
  38. package/dist/chunk-DONTW3NE.js +171 -0
  39. package/dist/chunk-DSROTZ3Z.js +38 -0
  40. package/dist/chunk-ELGCAM7P.js +184 -0
  41. package/dist/chunk-EQCXENKZ.js +130 -0
  42. package/dist/chunk-EYAKM6YN.js +96 -0
  43. package/dist/chunk-FDFPMBCA.js +112 -0
  44. package/dist/chunk-FVYFV5HA.js +154 -0
  45. package/dist/chunk-GE37NVLN.js +15 -0
  46. package/dist/chunk-GM5Y555O.js +143 -0
  47. package/dist/chunk-GRJXQBQZ.js +793 -0
  48. package/dist/chunk-HWFX4BC4.js +177 -0
  49. package/dist/chunk-I3M2KJXB.js +56 -0
  50. package/dist/chunk-IFNONGRQ.js +603 -0
  51. package/dist/chunk-J3U2CPSK.js +136 -0
  52. package/dist/chunk-J6XQ7OPZ.js +74 -0
  53. package/dist/chunk-KMV4Y6R3.js +127 -0
  54. package/dist/chunk-KP5ZDDPE.js +340 -0
  55. package/dist/chunk-KYKSZ3XZ.js +202 -0
  56. package/dist/chunk-LEGPB7DO.js +81 -0
  57. package/dist/chunk-LUAKDHLZ.js +40 -0
  58. package/dist/chunk-MHUEVBVO.js +35 -0
  59. package/dist/chunk-MYGSLK44.js +37 -0
  60. package/dist/chunk-NEZNAPPN.js +41 -0
  61. package/dist/chunk-NPVN2THM.js +197 -0
  62. package/dist/chunk-NYZU5NCW.js +23 -0
  63. package/dist/chunk-O4KHCV6I.js +320 -0
  64. package/dist/chunk-ONDVTXUO.js +240 -0
  65. package/dist/chunk-OTJFHESY.js +176 -0
  66. package/dist/chunk-P6MIKSPY.js +243 -0
  67. package/dist/chunk-Q5VPF4WI.js +26 -0
  68. package/dist/chunk-QCRBX3LV.js +165 -0
  69. package/dist/chunk-QKGYDMWB.js +7409 -0
  70. package/dist/chunk-QSL6QN5X.js +115 -0
  71. package/dist/chunk-QUIMQ7YL.js +73 -0
  72. package/dist/chunk-RG3YLU6E.js +49 -0
  73. package/dist/chunk-SHCEBP3J.js +107 -0
  74. package/dist/chunk-SHZFOSXC.js +462 -0
  75. package/dist/chunk-SOXFMMXC.js +151 -0
  76. package/dist/chunk-TDTYV6QI.js +119 -0
  77. package/dist/chunk-TNTXWSYA.js +19 -0
  78. package/dist/chunk-TUXQ32WE.js +2251 -0
  79. package/dist/chunk-VGCDRK3S.js +37 -0
  80. package/dist/chunk-VLRHFMGJ.js +58 -0
  81. package/dist/chunk-WHX2ZFCG.js +4048 -0
  82. package/dist/chunk-X4W64MHU.js +2005 -0
  83. package/dist/chunk-XBQA4I36.js +92 -0
  84. package/dist/chunk-XGOV6KV4.js +413 -0
  85. package/dist/chunk-XIFQIFSZ.js +940 -0
  86. package/dist/chunk-XLXPVN3Y.js +15393 -0
  87. package/dist/chunk-ZJMLQ37G.js +90 -0
  88. package/dist/client-MU4EUDZV.js +15 -0
  89. package/dist/commands-UOOTMBKA.js +1023 -0
  90. package/dist/compat-Q5DVPITN.js +201 -0
  91. package/dist/constants-DJFOFZ44.js +24 -0
  92. package/dist/dashboardIssue-KBKLQMGC.js +274 -0
  93. package/dist/diff-I4SNUHU3.js +13 -0
  94. package/dist/dist-4XXIXHHZ.js +12945 -0
  95. package/dist/domains-VRT4BRVZ.js +14 -0
  96. package/dist/e2b-FVPHDULZ.js +172 -0
  97. package/dist/env-UN6KGZ7S.js +15 -0
  98. package/dist/envCheck-KUPTORFQ.js +71 -0
  99. package/dist/extract-6WG265BL.js +455 -0
  100. package/dist/fetch-PJ3SC32M.js +22 -0
  101. package/dist/firstTouch-COJCMOB3.js +55 -0
  102. package/dist/fix-3EDWNKW3.js +220 -0
  103. package/dist/handlers-4Q37WIFT.js +55 -0
  104. package/dist/hook-NA66XJLC.js +412 -0
  105. package/dist/http-25GJ6SKK.js +6928 -0
  106. package/dist/ingestQueue-FSVJC3AA.js +37 -0
  107. package/dist/install-G2HHXYJ2.js +20 -0
  108. package/dist/installSkill-5TIMYIJZ.js +70 -0
  109. package/dist/inventory-5AWSLJYU.js +31 -0
  110. package/dist/local-XPZMRH5R.js +13 -0
  111. package/dist/manifest-ENMIC54B.js +13 -0
  112. package/dist/mcp-PENLL2PK.js +500 -0
  113. package/dist/mcpConfig-3LYPRY5Q.js +80 -0
  114. package/dist/mcpHandlers-PO7GENA7.js +22 -0
  115. package/dist/mcpScan-ULP626TQ.js +1735 -0
  116. package/dist/mcpScanWorkflow-27O44FOE.js +98 -0
  117. package/dist/mcpStack-ZNYIFXZ5.js +20 -0
  118. package/dist/model-ASMZWLM7.js +214 -0
  119. package/dist/packages-RWF2LXST.js +40 -0
  120. package/dist/plan-SDILIDZT.js +465 -0
  121. package/dist/planView-ZAKRTGVS.js +82 -0
  122. package/dist/policy-JAGNMQJI.js +115 -0
  123. package/dist/probe-3IK646WN.js +610 -0
  124. package/dist/publicUpgrades-WTBGLDIK.js +42 -0
  125. package/dist/references-I6Y4BSRR.js +16 -0
  126. package/dist/release-7IU2R4YG.js +128 -0
  127. package/dist/remote-FN6225AH.js +42 -0
  128. package/dist/rename-OS6JYBZQ.js +204 -0
  129. package/dist/reportRuns-O4X7ZFTX.js +77 -0
  130. package/dist/safeFetch-COERXGFN.js +19 -0
  131. package/dist/sandbox-SAPSRKEI.js +39 -0
  132. package/dist/sarif-WLVJFJ7U.js +125 -0
  133. package/dist/server-OLTY3NYT.js +59 -0
  134. package/dist/surface-7MHE3RL7.js +143 -0
  135. package/dist/surface-JS2XU3U3.js +38 -0
  136. package/dist/surfaceHandlers-4B6TMZ34.js +20 -0
  137. package/dist/typecheck-NGOKNAJY.js +282 -0
  138. package/dist/types-M5JP2W3D.js +10 -0
  139. package/dist/uninstall-I2IJP5JZ.js +200 -0
  140. package/dist/upgrade-FS26DJGG.js +650 -0
  141. package/dist/upgradePlan-ZS5IOVMZ.js +181 -0
  142. package/dist/upkeepHandler-VFGYXJKB.js +13 -0
  143. package/dist/userConfig-ICASHI47.js +20 -0
  144. package/dist/watch-OCNEUXG6.js +204 -0
  145. package/package.json +26 -20
  146. package/templates/agent-rules.md +4 -4
  147. package/templates/skill-instructions.md +35 -17
  148. package/dist/bin/lurq.js.map +0 -1
  149. package/dist/index.d.ts +0 -805
  150. package/dist/index.js +0 -23570
  151. package/dist/index.js.map +0 -1
  152. package/drizzle/0000_confused_fabian_cortez.sql +0 -54
  153. package/drizzle/0001_aspiring_timeslip.sql +0 -15
  154. package/drizzle/0002_lyrical_lila_cheney.sql +0 -14
  155. package/drizzle/0003_violet_giant_girl.sql +0 -14
  156. package/drizzle/0004_slim_valeria_richards.sql +0 -15
  157. package/drizzle/0005_petite_luke_cage.sql +0 -12
  158. package/drizzle/0006_calm_nighthawk.sql +0 -3
  159. package/drizzle/0007_slimy_naoko.sql +0 -1
  160. package/drizzle/0008_peaceful_tigra.sql +0 -1
  161. package/drizzle/0009_smooth_harrier.sql +0 -10
  162. package/drizzle/0010_curved_amphibian.sql +0 -2
  163. package/drizzle/0011_compat_provenance_closures.sql +0 -11
  164. package/drizzle/0012_api_surfaces.sql +0 -9
  165. package/drizzle/0013_nice_thanos.sql +0 -1
  166. package/drizzle/0014_luxuriant_malcolm_colcord.sql +0 -10
  167. package/drizzle/0015_past_fat_cobra.sql +0 -11
  168. package/drizzle/0016_futuristic_junta.sql +0 -50
  169. package/drizzle/0017_absent_grandmaster.sql +0 -20
  170. package/drizzle/0018_rainy_proemial_gods.sql +0 -1
  171. package/drizzle/0019_dashing_korvac.sql +0 -11
  172. package/drizzle/0020_normal_vulture.sql +0 -3
  173. package/drizzle/0021_dazzling_blue_shield.sql +0 -17
  174. package/drizzle/0022_massive_ghost_rider.sql +0 -24
  175. package/drizzle/0023_next_shatterstar.sql +0 -1
  176. package/drizzle/0024_dusty_maelstrom.sql +0 -15
  177. package/drizzle/0025_gifted_harpoon.sql +0 -5
  178. package/drizzle/0026_awesome_mordo.sql +0 -1
  179. package/drizzle/0027_charming_ulik.sql +0 -2
  180. package/drizzle/0028_romantic_loners.sql +0 -2
  181. package/drizzle/0029_busy_korvac.sql +0 -16
  182. package/drizzle/0030_steady_mathemanic.sql +0 -6
  183. package/drizzle/0031_redundant_maginty.sql +0 -2
  184. package/drizzle/0032_stack_resolutions.sql +0 -14
  185. package/drizzle/0033_graceful_tyger_tiger.sql +0 -3
  186. package/drizzle/0034_uneven_thunderbird.sql +0 -1
  187. package/drizzle/0035_api_key_scopes.sql +0 -1
  188. package/drizzle/0036_policy_audit.sql +0 -21
  189. package/drizzle/0037_subscription_seats.sql +0 -1
  190. package/drizzle/0038_symbol_offsets.sql +0 -2
  191. package/drizzle/0039_mcp_runtime_scans.sql +0 -80
  192. package/drizzle/0040_subscription_overage_and_interval.sql +0 -4
  193. package/drizzle/0041_account_email.sql +0 -38
  194. package/drizzle/0042_alert_channels.sql +0 -21
  195. package/drizzle/meta/0000_snapshot.json +0 -370
  196. package/drizzle/meta/0001_snapshot.json +0 -482
  197. package/drizzle/meta/0002_snapshot.json +0 -575
  198. package/drizzle/meta/0003_snapshot.json +0 -667
  199. package/drizzle/meta/0004_snapshot.json +0 -769
  200. package/drizzle/meta/0005_snapshot.json +0 -864
  201. package/drizzle/meta/0006_snapshot.json +0 -882
  202. package/drizzle/meta/0007_snapshot.json +0 -876
  203. package/drizzle/meta/0008_snapshot.json +0 -882
  204. package/drizzle/meta/0009_snapshot.json +0 -948
  205. package/drizzle/meta/0010_snapshot.json +0 -969
  206. package/drizzle/meta/0011_snapshot.json +0 -1049
  207. package/drizzle/meta/0012_snapshot.json +0 -1115
  208. package/drizzle/meta/0013_snapshot.json +0 -1121
  209. package/drizzle/meta/0014_snapshot.json +0 -1190
  210. package/drizzle/meta/0015_snapshot.json +0 -1280
  211. package/drizzle/meta/0016_snapshot.json +0 -1683
  212. package/drizzle/meta/0017_snapshot.json +0 -1834
  213. package/drizzle/meta/0018_snapshot.json +0 -1834
  214. package/drizzle/meta/0019_snapshot.json +0 -1909
  215. package/drizzle/meta/0020_snapshot.json +0 -1921
  216. package/drizzle/meta/0021_snapshot.json +0 -2045
  217. package/drizzle/meta/0022_snapshot.json +0 -2246
  218. package/drizzle/meta/0023_snapshot.json +0 -2252
  219. package/drizzle/meta/0024_snapshot.json +0 -2375
  220. package/drizzle/meta/0025_snapshot.json +0 -2407
  221. package/drizzle/meta/0026_snapshot.json +0 -2413
  222. package/drizzle/meta/0027_snapshot.json +0 -2425
  223. package/drizzle/meta/0028_snapshot.json +0 -2438
  224. package/drizzle/meta/0029_snapshot.json +0 -2546
  225. package/drizzle/meta/0030_snapshot.json +0 -2586
  226. package/drizzle/meta/0031_snapshot.json +0 -2598
  227. package/drizzle/meta/0032_snapshot.json +0 -2699
  228. package/drizzle/meta/0033_snapshot.json +0 -2712
  229. package/drizzle/meta/0034_snapshot.json +0 -2719
  230. package/drizzle/meta/0035_snapshot.json +0 -2726
  231. package/drizzle/meta/0036_snapshot.json +0 -2876
  232. package/drizzle/meta/0037_snapshot.json +0 -2883
  233. package/drizzle/meta/0038_snapshot.json +0 -2895
  234. package/drizzle/meta/0039_snapshot.json +0 -3501
  235. package/drizzle/meta/0040_snapshot.json +0 -3527
  236. package/drizzle/meta/0041_snapshot.json +0 -3824
  237. package/drizzle/meta/0042_snapshot.json +0 -3960
  238. package/drizzle/meta/_journal.json +0 -307
  239. package/src/data/seed.json +0 -253
@@ -0,0 +1,192 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ checkApi
4
+ } from "./chunk-SOXFMMXC.js";
5
+ import {
6
+ require_dist
7
+ } from "./chunk-QKGYDMWB.js";
8
+ import "./chunk-3GHJR7XR.js";
9
+ import {
10
+ __toESM,
11
+ init_esm_shims
12
+ } from "./chunk-I3M2KJXB.js";
13
+
14
+ // src/api/check.ts
15
+ init_esm_shims();
16
+ import { execFile } from "child_process";
17
+ import { existsSync, readFileSync } from "fs";
18
+ import { relative, resolve } from "path";
19
+ import { promisify } from "util";
20
+
21
+ // src/api/openapi.ts
22
+ init_esm_shims();
23
+ var import_yaml = __toESM(require_dist(), 1);
24
+ var METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
25
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
26
+ function deref(root, node, seen = /* @__PURE__ */ new Set()) {
27
+ if (!isRecord(node)) return null;
28
+ const ref = node.$ref;
29
+ if (typeof ref !== "string") return node;
30
+ if (!ref.startsWith("#/") || seen.has(ref)) return null;
31
+ seen.add(ref);
32
+ let cursor = root;
33
+ for (const segment of ref.slice(2).split("/")) {
34
+ if (!isRecord(cursor)) return null;
35
+ cursor = cursor[segment.replace(/~1/g, "/").replace(/~0/g, "~")];
36
+ }
37
+ return deref(root, cursor, seen);
38
+ }
39
+ function readParams(root, shared, own) {
40
+ const required = /* @__PURE__ */ new Set();
41
+ const optional = /* @__PURE__ */ new Set();
42
+ for (const list of [shared, own]) {
43
+ if (!Array.isArray(list)) continue;
44
+ for (const raw of list) {
45
+ const param = deref(root, raw);
46
+ const name = param?.name;
47
+ if (typeof name !== "string") continue;
48
+ const key = `${name} (${typeof param?.in === "string" ? param.in : "unknown"})`;
49
+ if (param?.required === true) {
50
+ required.add(key);
51
+ optional.delete(key);
52
+ } else if (!required.has(key)) {
53
+ optional.add(key);
54
+ }
55
+ }
56
+ }
57
+ return { required: [...required].sort(), optional: [...optional].sort() };
58
+ }
59
+ function readBodyFields(root, requestBody) {
60
+ const body = deref(root, requestBody);
61
+ if (!body || body.required !== true) return [];
62
+ const content = body.content;
63
+ if (!isRecord(content)) return [];
64
+ const out = /* @__PURE__ */ new Set();
65
+ for (const media of Object.values(content)) {
66
+ const schema = deref(root, isRecord(media) ? media.schema : null);
67
+ const required = schema?.required;
68
+ if (!Array.isArray(required)) continue;
69
+ for (const field of required) if (typeof field === "string") out.add(field);
70
+ }
71
+ return [...out].sort();
72
+ }
73
+ function extractApiSurface(source, label = "document") {
74
+ const empty = { title: null, version: null, operations: /* @__PURE__ */ new Map() };
75
+ let doc;
76
+ try {
77
+ doc = (0, import_yaml.parse)(source);
78
+ } catch (err) {
79
+ return {
80
+ ...empty,
81
+ unreadableReason: `${label} is not valid YAML or JSON: ${err instanceof Error ? err.message : String(err)}`
82
+ };
83
+ }
84
+ if (!isRecord(doc)) return { ...empty, unreadableReason: `${label} is not an object` };
85
+ if (!doc.openapi && !doc.swagger) {
86
+ return { ...empty, unreadableReason: `${label} has no openapi/swagger version field` };
87
+ }
88
+ const info = isRecord(doc.info) ? doc.info : {};
89
+ const paths = isRecord(doc.paths) ? doc.paths : {};
90
+ const operations = /* @__PURE__ */ new Map();
91
+ for (const [path, rawItem] of Object.entries(paths)) {
92
+ const item = deref(doc, rawItem);
93
+ if (!item) continue;
94
+ for (const method of METHODS) {
95
+ const op = item[method];
96
+ if (!isRecord(op)) continue;
97
+ const { required, optional } = readParams(doc, item.parameters, op.parameters);
98
+ const responses = isRecord(op.responses) ? Object.keys(op.responses).sort() : [];
99
+ const id = `${method.toUpperCase()} ${path}`;
100
+ operations.set(id, {
101
+ id,
102
+ method: method.toUpperCase(),
103
+ path,
104
+ requiredParams: required,
105
+ optionalParams: optional,
106
+ requiredBodyFields: readBodyFields(doc, op.requestBody),
107
+ responseCodes: responses,
108
+ deprecated: op.deprecated === true
109
+ });
110
+ }
111
+ }
112
+ return {
113
+ title: typeof info.title === "string" ? info.title : null,
114
+ version: typeof info.version === "string" ? info.version : null,
115
+ operations,
116
+ ...operations.size === 0 ? { unreadableReason: `${label} declares no operations` } : {}
117
+ };
118
+ }
119
+
120
+ // src/api/check.ts
121
+ var execFileP = promisify(execFile);
122
+ var CANDIDATES = [
123
+ "openapi.yaml",
124
+ "openapi.yml",
125
+ "openapi.json",
126
+ "swagger.yaml",
127
+ "swagger.yml",
128
+ "swagger.json",
129
+ "api/openapi.yaml",
130
+ "api/openapi.yml",
131
+ "api/openapi.json",
132
+ "docs/openapi.yaml",
133
+ "docs/openapi.yml"
134
+ ];
135
+ function findSpec(dir) {
136
+ for (const candidate of CANDIDATES) {
137
+ const full = resolve(dir, candidate);
138
+ if (existsSync(full)) return full;
139
+ }
140
+ return null;
141
+ }
142
+ async function showAtRevision(dir, rev, repoPath) {
143
+ try {
144
+ const { stdout } = await execFileP("git", ["show", `${rev}:${repoPath}`], {
145
+ cwd: dir,
146
+ maxBuffer: 32 * 1024 * 1024
147
+ });
148
+ return stdout;
149
+ } catch {
150
+ return null;
151
+ }
152
+ }
153
+ async function runApiCheck(dir, opts = {}) {
154
+ const against = opts.against ?? "HEAD";
155
+ const specPath = opts.spec ? resolve(dir, opts.spec) : findSpec(dir);
156
+ const spec = specPath ? relative(dir, specPath) || specPath : "(none found)";
157
+ const base = { spec, against, title: null, fromVersion: null, toVersion: null };
158
+ if (!specPath) {
159
+ return {
160
+ ...base,
161
+ verdict: "inconclusive",
162
+ versionCovers: null,
163
+ diff: {
164
+ breaking: [],
165
+ other: [],
166
+ inconclusive: `no OpenAPI document found in ${dir}. Name one: lurq check-api <file>`
167
+ }
168
+ };
169
+ }
170
+ const current = extractApiSurface(readFileSync(specPath, "utf8"), spec);
171
+ const previousSource = await showAtRevision(dir, against, spec);
172
+ if (previousSource === null) {
173
+ return {
174
+ ...base,
175
+ title: current.title,
176
+ toVersion: current.version,
177
+ verdict: "inconclusive",
178
+ versionCovers: null,
179
+ diff: {
180
+ breaking: [],
181
+ other: [],
182
+ inconclusive: `${spec} does not exist at ${against}, so there is nothing to compare against`
183
+ }
184
+ };
185
+ }
186
+ const previous = extractApiSurface(previousSource, `${spec} at ${against}`);
187
+ return { ...base, ...checkApi(previous, current) };
188
+ }
189
+ export {
190
+ findSpec,
191
+ runApiCheck
192
+ };
@@ -0,0 +1,24 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ SCAN_LIMIT,
4
+ fixableTargets,
5
+ modeDisagreement,
6
+ parseUpgradeSpec,
7
+ planMode,
8
+ planUpgrades,
9
+ runCheckUpgrade,
10
+ targetsFromPlanFile,
11
+ targetsFromUpgrades
12
+ } from "./chunk-QCRBX3LV.js";
13
+ import "./chunk-I3M2KJXB.js";
14
+ export {
15
+ SCAN_LIMIT,
16
+ fixableTargets,
17
+ modeDisagreement,
18
+ parseUpgradeSpec,
19
+ planMode,
20
+ planUpgrades,
21
+ runCheckUpgrade,
22
+ targetsFromPlanFile,
23
+ targetsFromUpgrades
24
+ };
@@ -0,0 +1,40 @@
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/github/types.ts
7
+ init_esm_shims();
8
+ var DEFAULT_REPO_POLICY = {
9
+ enabled: false,
10
+ scope: "blocking",
11
+ autoMerge: false,
12
+ // Stated rather than relied upon. `permits()` already reads an absent
13
+ // `checks` as on, so a repo connected before this shipped behaves the same as
14
+ // a new one — which is the point of the inversion. Writing it here keeps the
15
+ // default visible in the policy the dashboard round-trips.
16
+ checks: { env: true }
17
+ };
18
+ var RUN_TRIGGERS = ["schedule", "dispatch", "push", "pull_request", "other"];
19
+ var UPGRADE_SEVERITIES = ["blocking", "warning", "ok", "unverified"];
20
+ var UPGRADE_RUN_STATUSES = [
21
+ "checked",
22
+ "skipped",
23
+ "edited",
24
+ "pr_open",
25
+ "merged",
26
+ "failed"
27
+ ];
28
+ var REPO_MANIFEST_CAP = 25;
29
+ var REPO_DRIFT_DETAIL_CAP = 200;
30
+ var TRANSITIVE_DETAIL_CAP = 100;
31
+
32
+ export {
33
+ DEFAULT_REPO_POLICY,
34
+ RUN_TRIGGERS,
35
+ UPGRADE_SEVERITIES,
36
+ UPGRADE_RUN_STATUSES,
37
+ REPO_MANIFEST_CAP,
38
+ REPO_DRIFT_DETAIL_CAP,
39
+ TRANSITIVE_DETAIL_CAP
40
+ };
@@ -0,0 +1,423 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ bold,
4
+ dim,
5
+ green,
6
+ yellow
7
+ } from "./chunk-4KCPOMG6.js";
8
+ import {
9
+ agentSpecs,
10
+ installAgent,
11
+ installInstructionsFile,
12
+ lurqInvocation,
13
+ printInstallReport,
14
+ resolveAgents
15
+ } from "./chunk-DM37MTOO.js";
16
+ import {
17
+ MissingKeyError
18
+ } from "./chunk-OTJFHESY.js";
19
+ import {
20
+ readUserConfig,
21
+ resolveApiKey,
22
+ resolveEndpoint,
23
+ writeUserConfig
24
+ } from "./chunk-J6XQ7OPZ.js";
25
+ import {
26
+ openInBrowser
27
+ } from "./chunk-TNTXWSYA.js";
28
+ import {
29
+ DEFAULT_ENDPOINT,
30
+ KEYS_URL,
31
+ PACKAGE_NAME
32
+ } from "./chunk-72Y2FDVS.js";
33
+ import {
34
+ init_esm_shims
35
+ } from "./chunk-I3M2KJXB.js";
36
+
37
+ // src/cli/install.ts
38
+ init_esm_shims();
39
+ import { spawnSync } from "child_process";
40
+
41
+ // src/cli/agentLink.ts
42
+ init_esm_shims();
43
+ import { spawn } from "child_process";
44
+ var LINK_PREFIX = "LURQ_SIGNIN ";
45
+ var LINK_WAIT_MS = 15 * 6e4;
46
+ var START_TIMEOUT_MS = 15e3;
47
+ function setupMode(o) {
48
+ if (o.yes) return o.hasKey ? "non-interactive" : "needs-key";
49
+ if (o.tty) return "interactive";
50
+ if (o.hasKey) return "non-interactive";
51
+ return o.ci || o.selfHosted ? "needs-key" : "agent-link";
52
+ }
53
+ function startAgentLink(opts, spawnImpl = spawn) {
54
+ const args = [...process.execArgv, process.argv[1] ?? "", "setup", "--wait-for-signin"];
55
+ if (opts.agent) args.push("--agent", opts.agent);
56
+ if (opts.noOpen) args.push("--no-open");
57
+ const child = spawnImpl(process.execPath, args, {
58
+ detached: true,
59
+ stdio: ["ignore", "pipe", "ignore"],
60
+ // The link has to be the first thing it prints; an update notice first would only be noise.
61
+ env: { ...process.env, NO_UPDATE_NOTIFIER: "1" }
62
+ });
63
+ return new Promise((resolve) => {
64
+ let buffered = "";
65
+ const done = (link) => {
66
+ clearTimeout(timer);
67
+ child.stdout?.removeAllListeners("data");
68
+ child.stdout?.destroy();
69
+ child.unref();
70
+ resolve(link);
71
+ };
72
+ const timer = setTimeout(() => done(null), START_TIMEOUT_MS);
73
+ child.stdout?.on("data", (chunk) => {
74
+ buffered += chunk.toString();
75
+ const line = buffered.split("\n").find((l) => l.startsWith(LINK_PREFIX));
76
+ if (line) done(line.slice(LINK_PREFIX.length).trim());
77
+ });
78
+ child.once("error", () => done(null));
79
+ child.once("exit", () => done(null));
80
+ });
81
+ }
82
+
83
+ // src/cli/install.ts
84
+ async function withSetupOnMissingKey(run, ask = askToConnect, setup = () => runSetup({})) {
85
+ try {
86
+ await run();
87
+ } catch (err) {
88
+ if (!(err instanceof MissingKeyError) || !await ask()) throw err;
89
+ await setup();
90
+ await run();
91
+ }
92
+ }
93
+ async function askToConnect() {
94
+ const interactive = process.stdin.isTTY && process.stdout.isTTY && !process.env.CI && !process.argv.includes("--json");
95
+ if (!interactive) return false;
96
+ const { confirm } = await import("./dist-4XXIXHHZ.js");
97
+ return confirm({
98
+ message: "This machine has no lurq API key yet. Connect it now?",
99
+ default: true
100
+ });
101
+ }
102
+ async function validateKey(url, apiKey) {
103
+ try {
104
+ const res = await fetch(url, {
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ Accept: "application/json, text/event-stream",
109
+ Authorization: `Bearer ${apiKey}`
110
+ },
111
+ body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" }),
112
+ // A black-holed endpoint must not hang setup; it reads as unreachable.
113
+ signal: AbortSignal.timeout(15e3)
114
+ });
115
+ if (res.ok) return "valid";
116
+ if (res.status === 401 || res.status === 403) return "invalid";
117
+ return "unreachable";
118
+ } catch {
119
+ return "unreachable";
120
+ }
121
+ }
122
+ function runningFromNpx(moduleUrl = import.meta.url) {
123
+ return moduleUrl.includes("/_npx/");
124
+ }
125
+ function installGlobally() {
126
+ process.stdout.write(` Installing ${PACKAGE_NAME} globally (npm install -g, a few seconds)\u2026 `);
127
+ const res = spawnSync("npm", ["install", "--global", `${PACKAGE_NAME}@latest`], {
128
+ stdio: ["ignore", "ignore", "pipe"],
129
+ encoding: "utf8",
130
+ // npm is a .cmd shim on Windows, which is not directly executable.
131
+ shell: process.platform === "win32"
132
+ });
133
+ if (res.status === 0) {
134
+ console.log(green("ok"));
135
+ console.log(dim(" `lurq` now works in any terminal, no npx needed."));
136
+ return;
137
+ }
138
+ console.log(yellow("skipped"));
139
+ const reason = (res.stderr || res.error?.message || "").trim().split("\n").pop();
140
+ if (reason) console.log(dim(` ${reason}`));
141
+ console.log(
142
+ dim(` Setup continues. Run \`npm install -g ${PACKAGE_NAME}\` later if you want it.`)
143
+ );
144
+ }
145
+ async function runSetup(opts) {
146
+ if (opts.waitForSignin) return waitForSigninAndFinish(opts);
147
+ const url = resolveEndpoint(opts.url) ?? DEFAULT_ENDPOINT;
148
+ let apiKey = resolveApiKey(opts.apiKey);
149
+ const selfHosted = url !== DEFAULT_ENDPOINT;
150
+ const mode = setupMode({
151
+ yes: Boolean(opts.yes),
152
+ tty: Boolean(process.stdin.isTTY && process.stdout.isTTY),
153
+ ci: Boolean(process.env.CI),
154
+ hasKey: Boolean(apiKey),
155
+ selfHosted
156
+ });
157
+ if (mode === "agent-link") return runAgentLink(opts);
158
+ if (mode === "needs-key" && !opts.yes) {
159
+ throw new Error(
160
+ `lurq setup asks questions, and this is not an interactive terminal (CI, a pipe, or an agent shell).
161
+ Run it non-interactively: npx ${PACKAGE_NAME} setup --yes --api-key <key>
162
+ Get a key at ${KEYS_URL}`
163
+ );
164
+ }
165
+ const interactive = mode === "interactive";
166
+ if (interactive) {
167
+ const { input, checkbox, confirm, select } = await import("./dist-4XXIXHHZ.js");
168
+ console.log(`
169
+ ${bold("lurq setup")}: connect this machine to the package index.
170
+ `);
171
+ console.log(` Endpoint: ${url}${selfHosted ? dim(" (your own server)") : ""}
172
+ `);
173
+ if (runningFromNpx()) {
174
+ const goGlobal = await confirm({
175
+ message: `Install ${PACKAGE_NAME} globally, so \`lurq\` works without npx?`,
176
+ default: true
177
+ });
178
+ if (goGlobal) installGlobally();
179
+ console.log("");
180
+ }
181
+ if (apiKey && !opts.apiKey) {
182
+ const stored = readUserConfig().apiKey === apiKey;
183
+ const reuse = await confirm({
184
+ message: `Use the API key already configured${stored ? " on this machine" : " in your environment"}?`,
185
+ default: true
186
+ });
187
+ if (!reuse) apiKey = void 0;
188
+ }
189
+ if (!apiKey && !selfHosted) {
190
+ const { keyViaBrowser } = await import("./browserAuth-J7APSD4P.js");
191
+ console.log(" Sign in and this machine gets its key. Nothing to copy.\n");
192
+ process.stdout.write(" Waiting for the browser\u2026 ");
193
+ const skip = new AbortController();
194
+ const onEnter = () => skip.abort();
195
+ process.stdin.once("data", onEnter);
196
+ const handoff = await keyViaBrowser({
197
+ noOpen: opts.noOpen,
198
+ signal: skip.signal,
199
+ via: "terminal",
200
+ // Printed rather than only opened: the browser may not have launched,
201
+ // and a spinner pointing at a URL nobody can see is a hung flow.
202
+ onUrl: (link) => console.log(`
203
+
204
+ ${dim(link)}
205
+ ${dim("Press Enter to paste a key instead.")}
206
+ `)
207
+ });
208
+ process.stdin.off("data", onEnter);
209
+ process.stdin.pause();
210
+ if (handoff) {
211
+ apiKey = handoff.key;
212
+ console.log(green(` \u2713 key received${handoff.label ? dim(` (${handoff.label})`) : ""}
213
+ `));
214
+ } else {
215
+ console.log(yellow(skip.signal.aborted ? " skipped" : " no response"));
216
+ console.log(dim(" Falling back to pasting it in.\n"));
217
+ }
218
+ }
219
+ if (!apiKey) {
220
+ if (selfHosted) {
221
+ console.log(` Issue a key on the machine running ${url}:
222
+ `);
223
+ console.log(` ${bold("lurq keys create --label my-laptop")}
224
+ `);
225
+ console.log(" Then paste it below.\n");
226
+ } else {
227
+ if (!opts.noOpen) {
228
+ console.log(` Opening ${KEYS_URL}
229
+ `);
230
+ openInBrowser(KEYS_URL);
231
+ } else {
232
+ console.log(` Open ${KEYS_URL}
233
+ `);
234
+ }
235
+ console.log(" 1. Sign in, or create an account. It takes a moment.");
236
+ console.log(" 2. Create an API key and copy it.");
237
+ console.log(" 3. Paste it below.\n");
238
+ }
239
+ apiKey = (await input({
240
+ message: "Paste your lurq API key",
241
+ validate: (v) => v.trim().startsWith("lurq_") ? true : "Keys look like lurq_live_\u2026 "
242
+ })).trim();
243
+ }
244
+ process.stdout.write(" Validating key\u2026 ");
245
+ const check2 = await validateKey(url, apiKey);
246
+ console.log(
247
+ check2 === "valid" ? green("ok") : check2 === "invalid" ? yellow("rejected") : yellow("could not reach endpoint")
248
+ );
249
+ if (check2 !== "valid") {
250
+ const proceed = await confirm({
251
+ message: check2 === "invalid" ? `That key was rejected (401) by ${url}. Continue anyway?` : `Couldn't reach ${url} to validate the key. Continue anyway?`,
252
+ default: false
253
+ });
254
+ if (!proceed) {
255
+ console.log("Aborted. No config was changed.");
256
+ return;
257
+ }
258
+ }
259
+ if (opts.agent) {
260
+ await finish(resolveAgents(opts.agent), { url, apiKey });
261
+ return;
262
+ }
263
+ const specs = agentSpecs();
264
+ const detected = specs.filter((s) => s.detected);
265
+ const primary = detected.find((s) => s.id === "claude-code") ?? detected[0];
266
+ if (primary) {
267
+ const others = detected.length - 1;
268
+ const choice = await select({
269
+ message: others > 0 ? `Looks like you have ${detected.map((s) => s.label).join(", ")}. Connect lurq to them?` : `Looks like you have ${primary.label}. Connect lurq to it?`,
270
+ default: "yes",
271
+ choices: [
272
+ {
273
+ name: others > 0 ? `Yes, set up all ${detected.length} detected agents` : `Yes, set up ${primary.label} for me`,
274
+ value: "yes"
275
+ },
276
+ { name: "No, let me choose which agent(s)", value: "other" },
277
+ { name: "Cancel, change nothing", value: "cancel" }
278
+ ]
279
+ });
280
+ if (choice === "cancel") {
281
+ console.log("No problem. Nothing was changed; run `lurq setup` again anytime.");
282
+ return;
283
+ }
284
+ if (choice === "yes") {
285
+ await finish(detected, { url, apiKey });
286
+ return;
287
+ }
288
+ }
289
+ const ids = await checkbox({
290
+ message: "Which assistant(s) should I configure?",
291
+ choices: specs.map((s) => ({
292
+ name: `${s.label}${s.detected ? " (detected)" : ""}`,
293
+ value: s.id,
294
+ checked: s.detected
295
+ }))
296
+ });
297
+ await finish(
298
+ specs.filter((s) => ids.includes(s.id)),
299
+ { url, apiKey }
300
+ );
301
+ return;
302
+ }
303
+ if (!apiKey) {
304
+ throw new Error(
305
+ `No API key. Pass --api-key <key> or set LURQ_API_KEY (or drop --yes to be prompted). Get a key at ${KEYS_URL}`
306
+ );
307
+ }
308
+ const check = await validateKey(url, apiKey);
309
+ if (check === "invalid") {
310
+ throw new Error(
311
+ `${url} rejected that API key (401). Nothing was written. ` + (selfHosted ? `Issue one on the server with \`lurq keys create\`.` : `Check it, or create a new one at ${KEYS_URL}`)
312
+ );
313
+ }
314
+ if (check === "unreachable") {
315
+ throw new Error(
316
+ `Could not reach ${url} to validate the API key. Nothing was written. Check the URL and your connection, then re-run.`
317
+ );
318
+ }
319
+ const selected = opts.agent ? resolveAgents(opts.agent) : agentSpecs().filter((s) => s.detected);
320
+ await finish(selected, { url, apiKey });
321
+ }
322
+ async function runAgentLink(opts) {
323
+ const link = await startAgentLink({ agent: opts.agent, noOpen: opts.noOpen });
324
+ if (!link) {
325
+ throw new Error(
326
+ `Could not start the sign-in listener on this machine.
327
+ Run it non-interactively instead: npx ${PACKAGE_NAME} setup --yes --api-key <key>
328
+ Get a key at ${KEYS_URL}`
329
+ );
330
+ }
331
+ const selected = opts.agent ? resolveAgents(opts.agent) : agentSpecs().filter((s) => s.detected);
332
+ console.log(
333
+ "lurq needs a one-time sign-in to connect this machine. Open this link on this computer:\n"
334
+ );
335
+ console.log(` ${link}
336
+ `);
337
+ console.log(
338
+ `Signing in finishes setup by itself: the key is stored${selected.length ? ` and lurq is connected to ${selected.map((s) => s.label).join(", ")}` : " for the lurq CLI (no coding agents detected)"}. The link works for ${LINK_WAIT_MS / 6e4} minutes.`
339
+ );
340
+ console.log("Afterwards, restart your coding agent so it loads lurq.");
341
+ }
342
+ async function waitForSigninAndFinish(opts) {
343
+ process.stdout.on("error", () => {
344
+ });
345
+ const { keyViaBrowser } = await import("./browserAuth-J7APSD4P.js");
346
+ const handoff = await keyViaBrowser({
347
+ noOpen: opts.noOpen,
348
+ deadlineMs: LINK_WAIT_MS,
349
+ via: "agent",
350
+ onUrl: (link) => {
351
+ process.stdout.write(`${LINK_PREFIX}${link}
352
+ `);
353
+ console.log = () => {
354
+ };
355
+ }
356
+ });
357
+ if (!handoff) return;
358
+ if (await validateKey(DEFAULT_ENDPOINT, handoff.key) !== "valid") return;
359
+ const selected = opts.agent ? resolveAgents(opts.agent) : agentSpecs().filter((s) => s.detected);
360
+ await finish(selected, { url: DEFAULT_ENDPOINT, apiKey: handoff.key });
361
+ }
362
+ async function finish(selected, remote) {
363
+ const configPath = writeUserConfig({
364
+ apiKey: remote.apiKey,
365
+ // Only persist a non-default endpoint. Storing the default would pin this
366
+ // machine to today's URL and quietly ignore a later change to the built-in.
367
+ endpoint: remote.url === DEFAULT_ENDPOINT ? void 0 : remote.url
368
+ });
369
+ console.log(`
370
+ ${green("\u2713")} API key saved to ${configPath} ${dim("(mode 0600)")}`);
371
+ console.log(
372
+ `${green("\u2713")} Pointed at ${remote.url}${remote.url === DEFAULT_ENDPOINT ? "" : dim(" (your own server)")}`
373
+ );
374
+ const { command } = lurqInvocation();
375
+ console.log(
376
+ dim(
377
+ ` \`${command} verify <package>\`, \`evaluate\`, \`compare\`, \`usage\` now work anywhere.`
378
+ )
379
+ );
380
+ if (selected.length === 0) {
381
+ console.log(
382
+ "\nNo agents selected or detected. Re-run `lurq setup --agent <id>` once your assistant is installed."
383
+ );
384
+ } else {
385
+ const mode = { kind: "remote", ...remote };
386
+ const results = selected.map((s) => installAgent(s, mode));
387
+ const instructionsPath = installInstructionsFile();
388
+ console.log("");
389
+ printInstallReport(results, instructionsPath, mode);
390
+ }
391
+ await printFirstScan(remote);
392
+ }
393
+ var FIRST_SCAN_TIMEOUT_MS = 15e3;
394
+ async function printFirstScan(remote) {
395
+ try {
396
+ const { buildUpgradePlan, planHeadline, scanSourceDrift } = await import("./upgradePlan-ZS5IOVMZ.js");
397
+ const [plan, source] = await Promise.all([
398
+ buildUpgradePlan(process.cwd(), {
399
+ url: remote.url,
400
+ apiKey: remote.apiKey,
401
+ timeoutMs: FIRST_SCAN_TIMEOUT_MS
402
+ }),
403
+ scanSourceDrift(process.cwd())
404
+ ]);
405
+ const headline = planHeadline(plan, source);
406
+ if (!headline) return;
407
+ const { command } = lurqInvocation();
408
+ console.log(`
409
+ ${yellow("!")} ${bold("In this project right now:")} ${headline}`);
410
+ console.log(
411
+ dim(
412
+ ` \`${command} upgrade-plan\` for the list, \`${command} fix\` to write the changes that need no judgement.`
413
+ )
414
+ );
415
+ } catch {
416
+ }
417
+ }
418
+
419
+ export {
420
+ withSetupOnMissingKey,
421
+ runningFromNpx,
422
+ runSetup
423
+ };