@dadado/agent-kit-cli 5.15.1 → 5.17.0

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 (72) hide show
  1. package/dashboard/dashboard-data.mjs +69 -65
  2. package/dashboard/lib/guards.d.mts +5 -0
  3. package/dashboard/lib/guards.mjs +31 -0
  4. package/dashboard/lib/identity-probe.mjs +56 -0
  5. package/dashboard/lib/pipeline-cache.mjs +58 -0
  6. package/dashboard/lib/processes.mjs +71 -0
  7. package/dashboard/serve.mjs +43 -1
  8. package/dashboard/start-broadcast.mjs +2 -12
  9. package/dashboard/start.mjs +2 -13
  10. package/dist/add-HTYIFKMN.js +150 -0
  11. package/dist/chunk-2IPXQFJE.js +253 -0
  12. package/dist/chunk-2RDRMGD3.js +82 -0
  13. package/dist/chunk-2YU2H7I6.js +42 -0
  14. package/dist/chunk-4IWG5CVE.js +214 -0
  15. package/dist/chunk-5VCOWTTP.js +6 -0
  16. package/dist/chunk-77V75A7O.js +39 -0
  17. package/dist/chunk-7HDQEK6T.js +26 -0
  18. package/dist/chunk-AW74INUW.js +1456 -0
  19. package/dist/chunk-B73KQ5KX.js +972 -0
  20. package/dist/chunk-CBCW5R5J.js +484 -0
  21. package/dist/chunk-DE3LQFSJ.js +18 -0
  22. package/dist/chunk-DQA434Y4.js +106 -0
  23. package/dist/chunk-F4VMYR7U.js +318 -0
  24. package/dist/chunk-F6C3GFKV.js +57 -0
  25. package/dist/chunk-HFUH3HVS.js +282 -0
  26. package/dist/chunk-HS7LVVLO.js +74 -0
  27. package/dist/chunk-IHROBTNM.js +135 -0
  28. package/dist/chunk-KD2MYBB6.js +213 -0
  29. package/dist/chunk-MAPOQEA2.js +43 -0
  30. package/dist/chunk-N3HTJVBR.js +341 -0
  31. package/dist/chunk-NQ7IQ5XT.js +26 -0
  32. package/dist/chunk-OUQZC744.js +1315 -0
  33. package/dist/chunk-PCCQUWE5.js +817 -0
  34. package/dist/chunk-PNFF6OU3.js +273 -0
  35. package/dist/chunk-PNG7LO2F.js +53 -0
  36. package/dist/chunk-QTON2GQX.js +203 -0
  37. package/dist/chunk-S6GMFDKV.js +50 -0
  38. package/dist/chunk-SMGFN3Z4.js +503 -0
  39. package/dist/chunk-STGFBAYT.js +641 -0
  40. package/dist/chunk-TFZ2JUXH.js +1081 -0
  41. package/dist/chunk-VY7MTPJ2.js +205 -0
  42. package/dist/chunk-W24CMQ32.js +525 -0
  43. package/dist/chunk-WW3YZKHW.js +165 -0
  44. package/dist/chunk-ZB43YMHW.js +20 -0
  45. package/dist/chunk-ZCTSUQRR.js +874 -0
  46. package/dist/chunk-ZXKZBTXE.js +17 -0
  47. package/dist/contribute-C6AW2P6J.js +367 -0
  48. package/dist/cursor-awareness-KTL2RGKD.js +77 -0
  49. package/dist/dashboard-YSNUGBFY.js +21 -0
  50. package/dist/dashboard-broadcast-M4CMW7RX.js +119 -0
  51. package/dist/diff-VHNR62SI.js +74 -0
  52. package/dist/doctor-PET2HRRJ.js +236 -0
  53. package/dist/dogfood-KKFVRWT6.js +366 -0
  54. package/dist/guard-EHXF76ID.js +530 -0
  55. package/dist/handoff-3UI6VKVG.js +302 -0
  56. package/dist/hook-DYIMKJYL.js +1074 -0
  57. package/dist/index.js +62 -14068
  58. package/dist/init-Q4LBM6KT.js +127 -0
  59. package/dist/install-RHOS3OYZ.js +34 -0
  60. package/dist/mission-control-LJACEVVN.js +89 -0
  61. package/dist/monitors-QV2IS3MP.js +176 -0
  62. package/dist/plan-index-JMC7Z4DW.js +44 -0
  63. package/dist/public-inbound-radar-WP3XF7GS.js +68 -0
  64. package/dist/remote-issues-SZ4HDQL5.js +44 -0
  65. package/dist/run-I3BFGULT.js +243 -0
  66. package/dist/run-plan-FO7CL4M3.js +118 -0
  67. package/dist/scan-NI2SWJ2E.js +33 -0
  68. package/dist/setup-global-M42GEODI.js +340 -0
  69. package/dist/status-XPVQVQMX.js +150 -0
  70. package/dist/update-FJ2EBZVO.js +283 -0
  71. package/dist/validate-V2CW7J4B.js +201 -0
  72. package/package.json +3 -3
@@ -0,0 +1,503 @@
1
+ import {
2
+ contextConfigPath,
3
+ intervalElapsed,
4
+ loadContextConfig
5
+ } from "./chunk-NQ7IQ5XT.js";
6
+ import {
7
+ diffAgainstRegistry,
8
+ summarizeDiff
9
+ } from "./chunk-2RDRMGD3.js";
10
+ import {
11
+ DEFAULT_REGISTRY_URL,
12
+ assertSafeRegistrySource,
13
+ loadAgentKitManifest,
14
+ resolveRegistryRoot
15
+ } from "./chunk-AW74INUW.js";
16
+ import {
17
+ KIT_PACKAGE_SPEC,
18
+ KIT_VERSION
19
+ } from "./chunk-7HDQEK6T.js";
20
+ import {
21
+ readJson,
22
+ writeJson
23
+ } from "./chunk-77V75A7O.js";
24
+
25
+ // src/lifecycle/check-updates.ts
26
+ import { execFile } from "child_process";
27
+ import path from "path";
28
+ import { promisify } from "util";
29
+ var execFileAsync = promisify(execFile);
30
+ var SEMVER_CORE = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/i;
31
+ var FACTORY_URL_MARKERS = ["agent-kit-dev"];
32
+ var FACTORY_REFS = /* @__PURE__ */ new Set(["staging", "homologacao", "develop", "dev"]);
33
+ var DEFAULT_UPDATE_CHECK = {
34
+ enabled: false,
35
+ intervalDays: 7,
36
+ lastCheckedAt: null
37
+ };
38
+ function gitEnv() {
39
+ return { ...process.env, GIT_ALLOW_PROTOCOL: "https" };
40
+ }
41
+ function compareSemver(a, b) {
42
+ const pa = parseSemverParts(a);
43
+ const pb = parseSemverParts(b);
44
+ if (!pa || !pb) {
45
+ throw new Error(`Invalid semver for compare: "${a}" vs "${b}"`);
46
+ }
47
+ for (let i = 0; i < 3; i++) {
48
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
49
+ if (d !== 0) return d < 0 ? -1 : 1;
50
+ }
51
+ return 0;
52
+ }
53
+ function parseSemverParts(version) {
54
+ const m = SEMVER_CORE.exec(version.trim());
55
+ if (!m) return null;
56
+ return [Number(m[1]), Number(m[2]), Number(m[3])];
57
+ }
58
+ function normalizeSemver(version) {
59
+ const parts = parseSemverParts(version);
60
+ if (!parts) return null;
61
+ return `${parts[0]}.${parts[1]}.${parts[2]}`;
62
+ }
63
+ function isFactoryOrDevRegistry(url, ref) {
64
+ if (url) {
65
+ const lower = url.toLowerCase();
66
+ if (FACTORY_URL_MARKERS.some((m) => lower.includes(m))) return true;
67
+ }
68
+ if (ref && FACTORY_REFS.has(ref.toLowerCase())) return true;
69
+ return false;
70
+ }
71
+ function pickLatestSemverTag(lsRemoteStdout) {
72
+ let best = null;
73
+ for (const line of lsRemoteStdout.split("\n")) {
74
+ const trimmed = line.trim();
75
+ if (!trimmed) continue;
76
+ const ref = trimmed.split(/\s+/)[1];
77
+ if (!ref?.startsWith("refs/tags/")) continue;
78
+ if (ref.endsWith("^{}")) continue;
79
+ const tag = ref.slice("refs/tags/".length);
80
+ const norm = normalizeSemver(tag);
81
+ if (!norm) continue;
82
+ if (!best || compareSemver(norm, best) > 0) best = norm;
83
+ }
84
+ return best;
85
+ }
86
+ async function fetchLatestPublicVersion(registryUrl = DEFAULT_REGISTRY_URL) {
87
+ assertSafeRegistrySource(registryUrl, "main");
88
+ const { stdout } = await execFileAsync("git", ["ls-remote", "--tags", "--", registryUrl], {
89
+ env: gitEnv(),
90
+ timeout: 2e4
91
+ });
92
+ return pickLatestSemverTag(stdout);
93
+ }
94
+ var NPM_CLI_LATEST_URL = "https://registry.npmjs.org/@dadado%2Fagent-kit-cli/latest";
95
+ async function fetchLatestNpmDistTag() {
96
+ try {
97
+ const res = await fetch(NPM_CLI_LATEST_URL, {
98
+ method: "GET",
99
+ headers: { accept: "application/json" },
100
+ signal: AbortSignal.timeout(8e3)
101
+ });
102
+ if (!res.ok) return null;
103
+ const body = await res.json();
104
+ if (!body || typeof body !== "object" || Array.isArray(body)) return null;
105
+ const version = body.version;
106
+ return typeof version === "string" ? normalizeSemver(version) : null;
107
+ } catch {
108
+ return null;
109
+ }
110
+ }
111
+ function readUpdateCheckPrefs(config) {
112
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
113
+ return { ...DEFAULT_UPDATE_CHECK };
114
+ }
115
+ const raw = config.updateCheck;
116
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
117
+ return { ...DEFAULT_UPDATE_CHECK };
118
+ }
119
+ const uc = raw;
120
+ const intervalDays = typeof uc.intervalDays === "number" && Number.isInteger(uc.intervalDays) && uc.intervalDays >= 1 ? uc.intervalDays : DEFAULT_UPDATE_CHECK.intervalDays;
121
+ return {
122
+ enabled: uc.enabled === true,
123
+ intervalDays,
124
+ lastCheckedAt: typeof uc.lastCheckedAt === "string" ? uc.lastCheckedAt : null
125
+ };
126
+ }
127
+ async function stampLastCheckedAt(cwd) {
128
+ const existing = await loadContextConfig(cwd) ?? {};
129
+ const prev = existing.updateCheck && typeof existing.updateCheck === "object" ? { ...existing.updateCheck } : {};
130
+ existing.updateCheck = {
131
+ ...DEFAULT_UPDATE_CHECK,
132
+ ...prev,
133
+ lastCheckedAt: (/* @__PURE__ */ new Date()).toISOString()
134
+ };
135
+ await writeJson(contextConfigPath(cwd), existing);
136
+ }
137
+ async function readLocalKitVersion(registryRoot) {
138
+ for (const rel of ["packages/cli/package.json", "package.json"]) {
139
+ const data = await readJson(path.join(registryRoot, rel));
140
+ if (data && typeof data.version === "string" && data.version.length > 0) {
141
+ return data.version;
142
+ }
143
+ }
144
+ return null;
145
+ }
146
+ async function checkAgainstLocalRegistry(cwd, manifest, options) {
147
+ const registryPath = options.registryPath;
148
+ if (!registryPath) {
149
+ throw new Error("checkAgainstLocalRegistry requires registryPath");
150
+ }
151
+ let resolved;
152
+ try {
153
+ resolved = await resolveRegistryRoot({ cwd, registryPath });
154
+ } catch (err) {
155
+ const msg = err instanceof Error ? err.message : String(err);
156
+ return {
157
+ status: "error",
158
+ installedVersion: manifest.version,
159
+ latestVersion: null,
160
+ registryUrl: path.resolve(registryPath),
161
+ registryRef: "local",
162
+ applyRecommended: false,
163
+ message: `Failed to resolve --registry: ${msg}`
164
+ };
165
+ }
166
+ const registryUrl = resolved.root;
167
+ const registryRef = "local";
168
+ try {
169
+ let latest;
170
+ if (options.latestVersion !== void 0) {
171
+ latest = options.latestVersion;
172
+ } else {
173
+ const raw = await readLocalKitVersion(resolved.root);
174
+ latest = raw ? normalizeSemver(raw) : null;
175
+ }
176
+ const summary = summarizeDiff(await diffAgainstRegistry(resolved.root, cwd, manifest));
177
+ const hasFileDrift = summary.drift > 0 || summary["missing-local"] > 0;
178
+ const installed = normalizeSemver(manifest.version);
179
+ if (!installed) {
180
+ return {
181
+ status: "error",
182
+ installedVersion: manifest.version,
183
+ latestVersion: latest,
184
+ registryUrl,
185
+ registryRef,
186
+ applyRecommended: false,
187
+ message: `Installed version "${manifest.version}" is not valid semver.`
188
+ };
189
+ }
190
+ if (!latest) {
191
+ return {
192
+ status: "error",
193
+ installedVersion: installed,
194
+ latestVersion: null,
195
+ registryUrl,
196
+ registryRef,
197
+ applyRecommended: false,
198
+ message: "No semver found in the local --registry checkout (packages/cli/package.json or package.json)."
199
+ };
200
+ }
201
+ const cmp = compareSemver(installed, latest);
202
+ if (hasFileDrift) {
203
+ return {
204
+ status: "update-available",
205
+ installedVersion: installed,
206
+ latestVersion: latest,
207
+ registryUrl,
208
+ registryRef,
209
+ applyRecommended: false,
210
+ message: `Local registry has drift vs this install (drift=${summary.drift}, missing-local=${summary["missing-local"]}; source v${latest}). Run /update --registry <path> (Ask confirm) to apply; never silent.`
211
+ };
212
+ }
213
+ if (cmp === 0) {
214
+ return {
215
+ status: "up-to-date",
216
+ installedVersion: installed,
217
+ latestVersion: latest,
218
+ registryUrl,
219
+ registryRef,
220
+ applyRecommended: false,
221
+ message: `Installed v${installed} matches local registry v${latest}.`
222
+ };
223
+ }
224
+ if (cmp < 0) {
225
+ return {
226
+ status: "update-available",
227
+ installedVersion: installed,
228
+ latestVersion: latest,
229
+ registryUrl,
230
+ registryRef,
231
+ applyRecommended: false,
232
+ message: `Update available from local registry: v${installed} \u2192 v${latest}. Run /update --registry <path> (Ask confirm) to apply; never silent.`
233
+ };
234
+ }
235
+ return {
236
+ status: "ahead-of-public",
237
+ installedVersion: installed,
238
+ latestVersion: latest,
239
+ registryUrl,
240
+ registryRef,
241
+ applyRecommended: false,
242
+ message: `Installed v${installed} is ahead of local registry v${latest}.`
243
+ };
244
+ } finally {
245
+ await resolved.unlock?.();
246
+ }
247
+ }
248
+ async function checkForUpdates(cwd, options = {}) {
249
+ const manifest = await loadAgentKitManifest(cwd);
250
+ if (!manifest) {
251
+ return {
252
+ status: "skipped-no-manifest",
253
+ installedVersion: null,
254
+ latestVersion: null,
255
+ registryUrl: null,
256
+ registryRef: null,
257
+ applyRecommended: false,
258
+ message: "No .cursor/agent-kit.json \u2014 run agent-kit install first."
259
+ };
260
+ }
261
+ if (options.registryPath) {
262
+ return checkAgainstLocalRegistry(cwd, manifest, options);
263
+ }
264
+ const registryUrl = options.publicRegistryUrl ?? manifest.registry?.url ?? null;
265
+ const registryRef = manifest.registry?.ref ?? null;
266
+ if (isFactoryOrDevRegistry(registryUrl, registryRef)) {
267
+ return {
268
+ status: "skipped-factory",
269
+ installedVersion: manifest.version,
270
+ latestVersion: null,
271
+ registryUrl,
272
+ registryRef,
273
+ applyRecommended: false,
274
+ message: "Factory/dev registry detected \u2014 skipping public update check. Use /update only with explicit consumer intent."
275
+ };
276
+ }
277
+ if (options.respectPrefs) {
278
+ const config = await loadContextConfig(cwd);
279
+ const prefs = readUpdateCheckPrefs(config);
280
+ if (!prefs.enabled) {
281
+ return {
282
+ status: "skipped-disabled",
283
+ installedVersion: manifest.version,
284
+ latestVersion: null,
285
+ registryUrl,
286
+ registryRef,
287
+ applyRecommended: false,
288
+ message: "updateCheck.enabled is false (opt-in). Set true in .cursor/context/config.json to nudge."
289
+ };
290
+ }
291
+ if (!intervalElapsed(prefs.lastCheckedAt, prefs.intervalDays)) {
292
+ return {
293
+ status: "skipped-interval",
294
+ installedVersion: manifest.version,
295
+ latestVersion: null,
296
+ registryUrl,
297
+ registryRef,
298
+ applyRecommended: false,
299
+ message: `Within updateCheck.intervalDays (${prefs.intervalDays}); last check ${prefs.lastCheckedAt}.`
300
+ };
301
+ }
302
+ }
303
+ let latest;
304
+ try {
305
+ latest = options.latestVersion !== void 0 ? options.latestVersion : await fetchLatestPublicVersion(options.publicRegistryUrl ?? DEFAULT_REGISTRY_URL);
306
+ } catch (err) {
307
+ const msg = err instanceof Error ? err.message : String(err);
308
+ return {
309
+ status: "error",
310
+ installedVersion: manifest.version,
311
+ latestVersion: null,
312
+ registryUrl,
313
+ registryRef,
314
+ applyRecommended: false,
315
+ message: `Failed to fetch public tags: ${msg}`
316
+ };
317
+ }
318
+ if (options.stamp) {
319
+ try {
320
+ await stampLastCheckedAt(cwd);
321
+ } catch {
322
+ }
323
+ }
324
+ const installed = normalizeSemver(manifest.version);
325
+ if (!installed) {
326
+ return {
327
+ status: "error",
328
+ installedVersion: manifest.version,
329
+ latestVersion: latest,
330
+ registryUrl,
331
+ registryRef,
332
+ applyRecommended: false,
333
+ message: `Installed version "${manifest.version}" is not valid semver.`
334
+ };
335
+ }
336
+ if (!latest) {
337
+ return {
338
+ status: "error",
339
+ installedVersion: installed,
340
+ latestVersion: null,
341
+ registryUrl,
342
+ registryRef,
343
+ applyRecommended: false,
344
+ message: "No semver tags found on the public registry."
345
+ };
346
+ }
347
+ const cmp = compareSemver(installed, latest);
348
+ if (cmp === 0) {
349
+ return {
350
+ status: "up-to-date",
351
+ installedVersion: installed,
352
+ latestVersion: latest,
353
+ registryUrl,
354
+ registryRef,
355
+ applyRecommended: false,
356
+ message: `Installed v${installed} matches latest public v${latest}.`
357
+ };
358
+ }
359
+ if (cmp < 0) {
360
+ const cliBehind = compareSemver(KIT_VERSION, latest) < 0;
361
+ const remedy = cliBehind ? `This CLI is v${KIT_VERSION}, older than v${latest} \u2014 upgrade the binary first (\`npm i -g ${KIT_PACKAGE_SPEC}@${latest}\`), then run /update (Ask confirm); /update alone would re-apply v${KIT_VERSION}.` : "Run /update (Ask confirm) to apply; never silent.";
362
+ return {
363
+ status: "update-available",
364
+ installedVersion: installed,
365
+ latestVersion: latest,
366
+ registryUrl,
367
+ registryRef,
368
+ applyRecommended: false,
369
+ message: `Update available: v${installed} \u2192 v${latest}. ${remedy}`
370
+ };
371
+ }
372
+ return {
373
+ status: "ahead-of-public",
374
+ installedVersion: installed,
375
+ latestVersion: latest,
376
+ registryUrl,
377
+ registryRef,
378
+ applyRecommended: false,
379
+ message: `Installed v${installed} is ahead of latest public v${latest} (dev/local build).`
380
+ };
381
+ }
382
+ function runningCliBehindMessage(running, latest) {
383
+ return `Running CLI v${running} is behind npm latest v${latest}. Re-run with npx ${KIT_PACKAGE_SPEC}@latest or npm i -g ${KIT_PACKAGE_SPEC}@${latest}.`;
384
+ }
385
+ async function checkRunningCliVsNpmLatest(cwd, options = {}) {
386
+ const running = normalizeSemver(KIT_VERSION) ?? KIT_VERSION;
387
+ if (options.respectPrefs) {
388
+ const config = await loadContextConfig(cwd);
389
+ const prefs = readUpdateCheckPrefs(config);
390
+ if (!prefs.enabled) {
391
+ return {
392
+ status: "skipped-disabled",
393
+ runningVersion: running,
394
+ latestVersion: null,
395
+ message: "updateCheck.enabled is false (opt-in). Set true in .cursor/context/config.json to nudge."
396
+ };
397
+ }
398
+ if (!intervalElapsed(prefs.lastCheckedAt, prefs.intervalDays)) {
399
+ return {
400
+ status: "skipped-interval",
401
+ runningVersion: running,
402
+ latestVersion: null,
403
+ message: `Within updateCheck.intervalDays (${prefs.intervalDays}); last check ${prefs.lastCheckedAt}.`
404
+ };
405
+ }
406
+ }
407
+ let latest;
408
+ try {
409
+ if (options.latestVersion !== void 0) {
410
+ latest = options.latestVersion;
411
+ } else if (options.fetchLatest) {
412
+ latest = await options.fetchLatest();
413
+ } else {
414
+ latest = await fetchLatestNpmDistTag();
415
+ }
416
+ } catch (err) {
417
+ const msg = err instanceof Error ? err.message : String(err);
418
+ return {
419
+ status: "error",
420
+ runningVersion: running,
421
+ latestVersion: null,
422
+ message: `Failed to fetch npm latest: ${msg}`
423
+ };
424
+ }
425
+ if (options.stamp) {
426
+ try {
427
+ await stampLastCheckedAt(cwd);
428
+ } catch {
429
+ }
430
+ }
431
+ if (!latest) {
432
+ return {
433
+ status: "error",
434
+ runningVersion: running,
435
+ latestVersion: null,
436
+ message: "No semver on npm dist-tags.latest for @dadado/agent-kit-cli."
437
+ };
438
+ }
439
+ let cmp;
440
+ try {
441
+ cmp = compareSemver(running, latest);
442
+ } catch {
443
+ return {
444
+ status: "error",
445
+ runningVersion: running,
446
+ latestVersion: latest,
447
+ message: `Invalid semver for compare: "${running}" vs "${latest}"`
448
+ };
449
+ }
450
+ if (cmp === 0) {
451
+ return {
452
+ status: "up-to-date",
453
+ runningVersion: running,
454
+ latestVersion: latest,
455
+ message: `Running CLI v${running} matches npm latest v${latest}.`
456
+ };
457
+ }
458
+ if (cmp < 0) {
459
+ return {
460
+ status: "behind",
461
+ runningVersion: running,
462
+ latestVersion: latest,
463
+ message: runningCliBehindMessage(running, latest)
464
+ };
465
+ }
466
+ return {
467
+ status: "ahead",
468
+ runningVersion: running,
469
+ latestVersion: latest,
470
+ message: `Running CLI v${running} is ahead of npm latest v${latest} (dev/local build).`
471
+ };
472
+ }
473
+ async function warnIfRunningCliBehindNpm(cwd, options = {}) {
474
+ try {
475
+ const result = await checkRunningCliVsNpmLatest(cwd, {
476
+ respectPrefs: options.respectPrefs ?? true,
477
+ stamp: options.stamp ?? true,
478
+ latestVersion: options.latestVersion,
479
+ fetchLatest: options.fetchLatest
480
+ });
481
+ if (result.status === "behind") {
482
+ (options.warn ?? ((message) => console.warn(message)))(result.message);
483
+ }
484
+ return result;
485
+ } catch (err) {
486
+ const msg = err instanceof Error ? err.message : String(err);
487
+ return {
488
+ status: "error",
489
+ runningVersion: normalizeSemver(KIT_VERSION) ?? KIT_VERSION,
490
+ latestVersion: null,
491
+ message: msg
492
+ };
493
+ }
494
+ }
495
+
496
+ export {
497
+ compareSemver,
498
+ normalizeSemver,
499
+ stampLastCheckedAt,
500
+ readLocalKitVersion,
501
+ checkForUpdates,
502
+ warnIfRunningCliBehindNpm
503
+ };