litmus-cli 1.4.7-eng1502.4 → 1.4.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 (67) hide show
  1. package/README.md +0 -29
  2. package/dist/commands/connect.d.ts.map +1 -1
  3. package/dist/commands/connect.js +20 -2
  4. package/dist/commands/connect.js.map +1 -1
  5. package/dist/commands/doctor.d.ts +1 -41
  6. package/dist/commands/doctor.d.ts.map +1 -1
  7. package/dist/commands/doctor.js +26 -188
  8. package/dist/commands/doctor.js.map +1 -1
  9. package/dist/commands/init.d.ts +1 -3
  10. package/dist/commands/init.d.ts.map +1 -1
  11. package/dist/commands/init.js +36 -77
  12. package/dist/commands/init.js.map +1 -1
  13. package/dist/commands/status.d.ts.map +1 -1
  14. package/dist/commands/status.js +25 -1
  15. package/dist/commands/status.js.map +1 -1
  16. package/dist/commands/submit.d.ts.map +1 -1
  17. package/dist/commands/submit.js +4 -83
  18. package/dist/commands/submit.js.map +1 -1
  19. package/dist/index.js +2 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/lib/ai-tracking.d.ts +10 -0
  22. package/dist/lib/ai-tracking.d.ts.map +1 -1
  23. package/dist/lib/ai-tracking.js +25 -0
  24. package/dist/lib/ai-tracking.js.map +1 -1
  25. package/dist/lib/backlog-flush.d.ts +118 -0
  26. package/dist/lib/backlog-flush.d.ts.map +1 -0
  27. package/dist/lib/backlog-flush.js +268 -0
  28. package/dist/lib/backlog-flush.js.map +1 -0
  29. package/dist/lib/config.d.ts +0 -20
  30. package/dist/lib/config.d.ts.map +1 -1
  31. package/dist/lib/config.js +0 -27
  32. package/dist/lib/config.js.map +1 -1
  33. package/dist/lib/detect-project.d.ts +46 -1
  34. package/dist/lib/detect-project.d.ts.map +1 -1
  35. package/dist/lib/detect-project.js +40 -19
  36. package/dist/lib/detect-project.js.map +1 -1
  37. package/dist/lib/hook-logger.cjs +136 -2
  38. package/dist/lib/keepalive.d.ts +33 -0
  39. package/dist/lib/keepalive.d.ts.map +1 -0
  40. package/dist/lib/keepalive.js +39 -0
  41. package/dist/lib/keepalive.js.map +1 -0
  42. package/dist/lib/shadow.d.ts +14 -0
  43. package/dist/lib/shadow.d.ts.map +1 -1
  44. package/dist/lib/shadow.js +33 -0
  45. package/dist/lib/shadow.js.map +1 -1
  46. package/dist/lib/tracker.d.ts.map +1 -1
  47. package/dist/lib/tracker.js +9 -1
  48. package/dist/lib/tracker.js.map +1 -1
  49. package/dist/lib/watcher.js +31 -7
  50. package/dist/lib/watcher.js.map +1 -1
  51. package/package.json +1 -1
  52. package/dist/lib/editor.d.ts +0 -73
  53. package/dist/lib/editor.d.ts.map +0 -1
  54. package/dist/lib/editor.js +0 -222
  55. package/dist/lib/editor.js.map +0 -1
  56. package/dist/lib/open-url.d.ts +0 -9
  57. package/dist/lib/open-url.d.ts.map +0 -1
  58. package/dist/lib/open-url.js +0 -45
  59. package/dist/lib/open-url.js.map +0 -1
  60. package/dist/lib/select.d.ts +0 -64
  61. package/dist/lib/select.d.ts.map +0 -1
  62. package/dist/lib/select.js +0 -170
  63. package/dist/lib/select.js.map +0 -1
  64. package/dist/lib/session.d.ts +0 -104
  65. package/dist/lib/session.d.ts.map +0 -1
  66. package/dist/lib/session.js +0 -327
  67. package/dist/lib/session.js.map +0 -1
@@ -0,0 +1,268 @@
1
+ import { readFileSync, writeFileSync, renameSync, unlinkSync } from "fs";
2
+ import path from "path";
3
+ import { uploadActivityEvents } from "./api.js";
4
+ /**
5
+ * Backlog flush for a dead watcher's un-uploaded tail (ENG-1491, extracted
6
+ * verbatim from `litmus doctor`).
7
+ *
8
+ * Everything the trackers record lands in activity.jsonl first, so the file
9
+ * is the source of truth. When the watcher dies, whatever sat in its
10
+ * in-memory upload buffer (at most one heartbeat interval of events) never
11
+ * reached the server — but it is still on disk. This module delivers that
12
+ * gap through the same /cli/activity endpoint, verbatim (chained watcher
13
+ * events stay verifiable), with a forward-only byte cursor so an interrupted
14
+ * flush resumes without re-sending or skipping anything.
15
+ *
16
+ * Two callers: `litmus doctor` (the loud, candidate-facing repair) and
17
+ * `litmus status`'s tracker revival (quiet — see flushDeathGapBacklog).
18
+ */
19
+ // Backlog flush window when there is no cursor: the dead watcher's last
20
+ // heartbeat marks roughly when server uploads stopped, and its unflushed
21
+ // in-memory buffer held at most one heartbeat interval of events. Reaching
22
+ // one extra interval further back trades a few duplicate rows (the server
23
+ // stores batches append-only) for never missing the gap.
24
+ export const FLUSH_WINDOW_BEFORE_LAST_HEARTBEAT_MS = 10 * 60 * 1000;
25
+ // Per-request caps for the backlog flush. The server accepts up to 5000
26
+ // events per batch and rate-limits /cli/activity per candidate, so a bounded
27
+ // number of modest batches per run stays well inside both while still
28
+ // clearing any realistic gap. Anything left over is remembered in the cursor
29
+ // and picked up by the next run.
30
+ export const MAX_EVENTS_PER_BATCH = 500;
31
+ export const MAX_BATCH_BYTES = 2000000;
32
+ export const MAX_BATCHES_PER_RUN = 4;
33
+ /** One pass over raw activity-log text: counts and latest timestamps. */
34
+ export function scanActivityLog(text) {
35
+ const scan = {
36
+ totalBytes: Buffer.byteLength(text, "utf8"),
37
+ eventCount: 0,
38
+ malformedCount: 0,
39
+ aiPromptCount: 0,
40
+ lastEventTs: null,
41
+ lastHeartbeatTs: null,
42
+ lastLiveAiPromptTs: null,
43
+ };
44
+ for (const line of text.split("\n")) {
45
+ if (!line.trim())
46
+ continue;
47
+ let event;
48
+ try {
49
+ event = JSON.parse(line);
50
+ }
51
+ catch {
52
+ scan.malformedCount++;
53
+ continue;
54
+ }
55
+ if (!event || typeof event !== "object") {
56
+ scan.malformedCount++;
57
+ continue;
58
+ }
59
+ scan.eventCount++;
60
+ const e = event;
61
+ if (typeof e.ts === "string")
62
+ scan.lastEventTs = e.ts;
63
+ if (e.type === "ai_prompt") {
64
+ scan.aiPromptCount++;
65
+ if (e.backfilled !== true && typeof e.ts === "string")
66
+ scan.lastLiveAiPromptTs = e.ts;
67
+ }
68
+ if (e.type === "heartbeat" && typeof e.ts === "string")
69
+ scan.lastHeartbeatTs = e.ts;
70
+ }
71
+ return scan;
72
+ }
73
+ /**
74
+ * Byte offset of the first log line whose event timestamp is at or after
75
+ * `cutoffMs`. Lines without a parseable timestamp don't start the window.
76
+ * Returns the total byte length (i.e. "flush nothing") when no line qualifies.
77
+ */
78
+ export function offsetForFirstEventAtOrAfter(text, cutoffMs) {
79
+ let offset = 0;
80
+ for (const line of text.split("\n")) {
81
+ const lineBytes = Buffer.byteLength(line, "utf8") + 1; // + newline
82
+ if (line.trim()) {
83
+ try {
84
+ const event = JSON.parse(line);
85
+ if (typeof event.ts === "string") {
86
+ const ts = Date.parse(event.ts);
87
+ if (!isNaN(ts) && ts >= cutoffMs)
88
+ return offset;
89
+ }
90
+ }
91
+ catch { /* malformed line can't start the window */ }
92
+ }
93
+ offset += lineBytes;
94
+ }
95
+ return Buffer.byteLength(text, "utf8");
96
+ }
97
+ /**
98
+ * Slice the log from `startOffset` into upload batches. Events are passed
99
+ * through VERBATIM (chained watcher events stay verifiable); malformed lines
100
+ * are skipped but still advance the offset so they are never retried forever.
101
+ * `startOffset` must fall on a line boundary (it always does: every stored
102
+ * cursor value is a `FlushBatch.endOffset`); a mid-line offset skips the torn
103
+ * line rather than uploading half an event.
104
+ */
105
+ export function planFlushBatches(text, startOffset) {
106
+ const batches = [];
107
+ let offset = 0;
108
+ let current = [];
109
+ let currentBytes = 0;
110
+ let end = startOffset;
111
+ const finish = () => {
112
+ if (current.length > 0) {
113
+ batches.push({ events: current, endOffset: end });
114
+ current = [];
115
+ currentBytes = 0;
116
+ }
117
+ };
118
+ for (const line of text.split("\n")) {
119
+ const lineBytes = Buffer.byteLength(line, "utf8") + 1;
120
+ const lineStart = offset;
121
+ offset += lineBytes;
122
+ if (lineStart < startOffset)
123
+ continue;
124
+ if (!line.trim()) {
125
+ end = Math.min(offset, Buffer.byteLength(text, "utf8"));
126
+ continue;
127
+ }
128
+ let event;
129
+ try {
130
+ event = JSON.parse(line);
131
+ }
132
+ catch {
133
+ end = offset; // skip malformed, but move past it
134
+ continue;
135
+ }
136
+ const eventBytes = Buffer.byteLength(line, "utf8");
137
+ if (current.length >= MAX_EVENTS_PER_BATCH || currentBytes + eventBytes > MAX_BATCH_BYTES) {
138
+ finish();
139
+ }
140
+ current.push(event);
141
+ currentBytes += eventBytes;
142
+ end = Math.min(offset, Buffer.byteLength(text, "utf8"));
143
+ }
144
+ finish();
145
+ return batches;
146
+ }
147
+ // ── Flush cursor (.litmus/upload-state.json) ─────────────────────
148
+ // Records the byte offset up to which a flush has delivered locally-recorded
149
+ // events to the server. Only exists while a recovery is in flight: a fully
150
+ // flushed backlog removes it (live watcher uploads own everything after
151
+ // that), and it NEVER moves backward.
152
+ const UPLOAD_STATE_FILE = "upload-state.json";
153
+ export function readUploadState(litmusDir) {
154
+ try {
155
+ const raw = JSON.parse(readFileSync(path.join(litmusDir, UPLOAD_STATE_FILE), "utf8"));
156
+ const v = raw?.flushFromBytes;
157
+ if (typeof v === "number" && Number.isFinite(v) && v >= 0)
158
+ return v;
159
+ }
160
+ catch { /* absent or unreadable */ }
161
+ return null;
162
+ }
163
+ export function writeUploadState(litmusDir, flushFromBytes) {
164
+ const existing = readUploadState(litmusDir);
165
+ // Forward-only: a smaller offset would make the next run re-upload events
166
+ // the server already has.
167
+ const value = Math.max(existing ?? 0, flushFromBytes);
168
+ const target = path.join(litmusDir, UPLOAD_STATE_FILE);
169
+ const tmp = `${target}.litmus-tmp-${process.pid}-${Date.now()}`;
170
+ writeFileSync(tmp, JSON.stringify({ flushFromBytes: value, updatedAt: new Date().toISOString() }, null, 2) + "\n", "utf8");
171
+ renameSync(tmp, target);
172
+ }
173
+ export function clearUploadState(litmusDir) {
174
+ try {
175
+ unlinkSync(path.join(litmusDir, UPLOAD_STATE_FILE));
176
+ }
177
+ catch { /* already gone */ }
178
+ }
179
+ /**
180
+ * Where a flush should start, or null when there is nothing to flush. A
181
+ * stored cursor (an earlier interrupted flush) always wins; otherwise the
182
+ * window opens FLUSH_WINDOW_BEFORE_LAST_HEARTBEAT_MS before the dead
183
+ * watcher's last heartbeat.
184
+ */
185
+ export function resolveFlushStart(args) {
186
+ const cursor = readUploadState(args.litmusDir);
187
+ if (cursor !== null)
188
+ return Math.min(cursor, args.totalBytes ?? cursor);
189
+ if (args.lastHeartbeatTs) {
190
+ const cutoff = Date.parse(args.lastHeartbeatTs) - FLUSH_WINDOW_BEFORE_LAST_HEARTBEAT_MS;
191
+ return offsetForFirstEventAtOrAfter(args.logText, cutoff);
192
+ }
193
+ return null;
194
+ }
195
+ /**
196
+ * Deliver up to MAX_BATCHES_PER_RUN batches starting at `flushFrom`. Stops at
197
+ * the first upload failure; the caller persists `lastGood` so the next run
198
+ * resumes exactly where this one stopped.
199
+ */
200
+ export async function deliverFlushBatches(logText, flushFrom, upload) {
201
+ const batches = planFlushBatches(logText, flushFrom);
202
+ const totalEvents = batches.reduce((n, b) => n + b.events.length, 0);
203
+ let sent = 0;
204
+ let lastGood = flushFrom;
205
+ let failure = null;
206
+ for (const batch of batches.slice(0, MAX_BATCHES_PER_RUN)) {
207
+ try {
208
+ await upload(batch.events);
209
+ sent += batch.events.length;
210
+ lastGood = batch.endOffset;
211
+ }
212
+ catch (err) {
213
+ failure = err instanceof Error ? err.message : String(err);
214
+ break;
215
+ }
216
+ }
217
+ return { totalEvents, sent, lastGood, failure };
218
+ }
219
+ /**
220
+ * The quiet twin of doctor's backlog flush, for `litmus status`'s tracker
221
+ * revival (ENG-1491). When status revives a dead watcher, the dead watcher's
222
+ * last few minutes of events are on disk but never reached the server — and
223
+ * the replacement watcher only uploads what IT captures, so without this the
224
+ * gap sat there until someone happened to run doctor.
225
+ *
226
+ * `logText` must be snapshotted BEFORE the replacement watcher starts
227
+ * appending, so the flush delivers the dead watcher's tail rather than
228
+ * racing the live one's own uploads. Cursor handling matches doctor: cleared
229
+ * when the backlog is fully delivered, advanced to the last good batch when
230
+ * it is not (doctor or the next revival picks up the rest).
231
+ *
232
+ * Returns null when there was nothing to flush. Never throws — a status run
233
+ * must not fail over an upload courtesy.
234
+ */
235
+ export async function flushDeathGapBacklog(args) {
236
+ try {
237
+ const litmusDir = path.join(args.projectRoot, ".litmus");
238
+ const scan = scanActivityLog(args.logText);
239
+ const flushFrom = resolveFlushStart({
240
+ litmusDir,
241
+ logText: args.logText,
242
+ totalBytes: scan.totalBytes,
243
+ // Revival implies the tracker was dead, so the heartbeat window applies.
244
+ lastHeartbeatTs: scan.lastHeartbeatTs,
245
+ });
246
+ if (flushFrom === null)
247
+ return null;
248
+ const { totalEvents, sent, lastGood, failure } = await deliverFlushBatches(args.logText, flushFrom, (events) => uploadActivityEvents(args.backendUrl, args.token, events));
249
+ if (totalEvents === 0) {
250
+ clearUploadState(litmusDir);
251
+ return null;
252
+ }
253
+ if (totalEvents - sent === 0 && failure === null) {
254
+ clearUploadState(litmusDir);
255
+ }
256
+ else {
257
+ try {
258
+ writeUploadState(litmusDir, lastGood);
259
+ }
260
+ catch { /* next run recomputes */ }
261
+ }
262
+ return { sent, total: totalEvents, failure };
263
+ }
264
+ catch {
265
+ return null;
266
+ }
267
+ }
268
+ //# sourceMappingURL=backlog-flush.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backlog-flush.js","sourceRoot":"","sources":["../../src/lib/backlog-flush.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import type { EditorId } from "./editor.js";
2
1
  export interface LitmusConfig {
3
2
  assessmentId: string;
4
3
  assessmentName: string;
@@ -12,7 +11,6 @@ export interface LitmusConfig {
12
11
  apiBase: string;
13
12
  backendUrl?: string;
14
13
  cliVersion?: string;
15
- editor?: EditorId;
16
14
  }
17
15
  /**
18
16
  * Calculate the effective deadline timestamp (ms) from config.
@@ -20,24 +18,6 @@ export interface LitmusConfig {
20
18
  */
21
19
  export declare function getEffectiveDeadline(config: Pick<LitmusConfig, "deadline" | "startedAt" | "timeLimit">): number | null;
22
20
  export declare function writeConfig(projectRoot: string, config: LitmusConfig): Promise<void>;
23
- /**
24
- * Record the editor the candidate picked, merging into whatever is on disk NOW
25
- * rather than over an in-memory copy.
26
- *
27
- * This has to be a read-modify-write. Init writes the config, starts the
28
- * watcher, and only then asks which editor to open — and while that prompt sits
29
- * there the watcher can fold server-authoritative times into config.json
30
- * (ENG-1489). Writing back an object captured before the prompt would revert
31
- * that sync, and it would NOT self-correct: computeTimeSync compares against
32
- * the watcher's own in-memory copy, so having already applied the change it
33
- * writes nothing further until the server times move again. A deadline
34
- * extension granted at init time could be silently rolled back on disk, and a
35
- * watcher restart would then arm the earlier cutoff.
36
- *
37
- * Best-effort: failing to record the editor only costs the window close at
38
- * submit, which is itself best-effort.
39
- */
40
- export declare function recordEditorChoice(projectRoot: string, editor: EditorId): Promise<void>;
41
21
  /**
42
22
  * Sanity-check restore-time metadata before writing a rebuilt config.
43
23
  * Returns a human-readable problem, or null when the times are usable.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IAOnB,UAAU,CAAC,EAAE,MAAM,CAAA;IAInB,MAAM,CAAC,EAAE,QAAQ,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,MAAM,GAAG,IAAI,CAStH;AAKD,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAC9E,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CASf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACtF,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAsBtF;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAe/C;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB/D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IAOnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,MAAM,GAAG,IAAI,CAStH;AAKD,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAC9E,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CASf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACtF,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAsBtF;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAe/C;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB/D"}
@@ -32,33 +32,6 @@ export async function writeConfig(projectRoot, config) {
32
32
  // restored without the candidate doing anything. Best-effort by design.
33
33
  writeShadowConfig(projectRoot, config);
34
34
  }
35
- /**
36
- * Record the editor the candidate picked, merging into whatever is on disk NOW
37
- * rather than over an in-memory copy.
38
- *
39
- * This has to be a read-modify-write. Init writes the config, starts the
40
- * watcher, and only then asks which editor to open — and while that prompt sits
41
- * there the watcher can fold server-authoritative times into config.json
42
- * (ENG-1489). Writing back an object captured before the prompt would revert
43
- * that sync, and it would NOT self-correct: computeTimeSync compares against
44
- * the watcher's own in-memory copy, so having already applied the change it
45
- * writes nothing further until the server times move again. A deadline
46
- * extension granted at init time could be silently rolled back on disk, and a
47
- * watcher restart would then arm the earlier cutoff.
48
- *
49
- * Best-effort: failing to record the editor only costs the window close at
50
- * submit, which is itself best-effort.
51
- */
52
- export async function recordEditorChoice(projectRoot, editor) {
53
- const configPath = path.join(projectRoot, CONFIG_DIR, CONFIG_FILE);
54
- try {
55
- const current = JSON.parse(await readFile(configPath, "utf8"));
56
- await writeConfig(projectRoot, { ...current, editor });
57
- }
58
- catch {
59
- // No readable config to merge into — nothing safe to write.
60
- }
61
- }
62
35
  /**
63
36
  * Sanity-check restore-time metadata before writing a rebuilt config.
64
37
  * Returns a human-readable problem, or null when the times are usable.
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,10 @@
1
1
  export type ProjectType = "node" | "python" | "go" | "java" | "dotnet" | "rust" | "ruby" | "php" | "unknown";
2
+ /** Seams the caller can replace. Both read the HOST by default, which is what
3
+ * makes them worth injecting: a test cannot control whether this machine has
4
+ * bun, so without these the runtime behaviour is only assertable as "either". */
5
+ export interface DetectDeps {
6
+ isOnPath?: (bin: string) => boolean;
7
+ }
2
8
  export interface ProjectInfo {
3
9
  type: ProjectType;
4
10
  installCommand: string | null;
@@ -9,6 +15,17 @@ export interface ProjectInfo {
9
15
  * the README told them could not happen.
10
16
  */
11
17
  toolchainWarning?: string;
18
+ /**
19
+ * A RUNTIME that `installCommand` needs and that is not on PATH.
20
+ *
21
+ * Reported as state rather than as a warning string, because the right thing
22
+ * to say depends on what the caller manages to DO about it: `init` installs
23
+ * bun and says nothing, or fails to and says so. A message authored here
24
+ * would have to be written before either outcome is known, which is how the
25
+ * first version came to tell candidates to install bun by hand in the case
26
+ * where we had just installed it for them.
27
+ */
28
+ missingRuntime?: "bun";
12
29
  }
13
30
  /**
14
31
  * The Python the candidate's submission is actually GRADED on.
@@ -38,8 +55,36 @@ export declare function resolvePythonInterpreter(): {
38
55
  matchesGrader: boolean;
39
56
  detectedVersion: string | null;
40
57
  };
58
+ /**
59
+ * Is `bin` runnable from PATH?
60
+ *
61
+ * `--version` rather than `which`/`where`: one probe that works on all three
62
+ * platforms, and it proves the binary actually EXECUTES. A PATH entry pointing at
63
+ * a broken install or the wrong architecture resolves fine and then fails on use,
64
+ * which is the case a warning most needs to catch. `shell: true` on Windows so
65
+ * `.cmd`/`.ps1` shims resolve, matching the Python probe above.
66
+ */
67
+ export declare function isOnPath(bin: string): boolean;
41
68
  /**
42
69
  * Detect project type and suggest an install command.
43
70
  */
44
- export declare function detectProject(dir: string): ProjectInfo;
71
+ export declare function detectProject(dir: string, deps?: DetectDeps): ProjectInfo;
72
+ /** How each supported runtime is obtained. npm ships per-platform bun binaries,
73
+ * and npm is guaranteed present because this CLI is an npm package. */
74
+ export declare const RUNTIME_INSTALL: Record<"bun", string>;
75
+ export type RuntimeOutcome = "installed" | "unavailable";
76
+ export interface InstallRuntimeDeps {
77
+ exec?: (command: string) => void;
78
+ isOnPath?: (bin: string) => boolean;
79
+ }
80
+ /**
81
+ * Install a runtime the project needs and the machine lacks.
82
+ *
83
+ * Separated from `init`'s reporting so all three outcomes are assertable: the
84
+ * install failing, and the install "succeeding" while leaving nothing on PATH.
85
+ * That second case is the one worth a unit test — a global install can land
86
+ * somewhere this process cannot reach, and treating it as success means the
87
+ * dependency install below dies on a command-not-found we already knew about.
88
+ */
89
+ export declare function installRuntime(runtime: "bun", deps?: InstallRuntimeDeps): RuntimeOutcome;
45
90
  //# sourceMappingURL=detect-project.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detect-project.d.ts","sourceRoot":"","sources":["../../src/lib/detect-project.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,QAAQ,GACR,MAAM,GACN,MAAM,GACN,KAAK,GACL,SAAS,CAAA;AAEb,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAA;AA0D5C;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,OAAO,CAAA;IACtB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B,CAkBA;AAyBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAmGtD"}
1
+ {"version":3,"file":"detect-project.d.ts","sourceRoot":"","sources":["../../src/lib/detect-project.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,QAAQ,GACR,MAAM,GACN,MAAM,GACN,KAAK,GACL,SAAS,CAAA;AAEb;;kFAEkF;AAClF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,KAAK,CAAA;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAA;AA0D5C;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,OAAO,CAAA;IACtB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B,CAkBA;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAY7C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,WAAW,CAyF7E;AAGD;wEACwE;AACxE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAEjD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,aAAa,CAAA;AAExD,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;CACpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,KAAK,EACd,IAAI,GAAE,kBAAuB,GAC5B,cAAc,CAchB"}
@@ -101,7 +101,7 @@ export function resolvePythonInterpreter() {
101
101
  * which is the case a warning most needs to catch. `shell: true` on Windows so
102
102
  * `.cmd`/`.ps1` shims resolve, matching the Python probe above.
103
103
  */
104
- function isOnPath(bin) {
104
+ export function isOnPath(bin) {
105
105
  try {
106
106
  return (spawnSync(bin, ["--version"], {
107
107
  encoding: "utf8",
@@ -116,7 +116,8 @@ function isOnPath(bin) {
116
116
  /**
117
117
  * Detect project type and suggest an install command.
118
118
  */
119
- export function detectProject(dir) {
119
+ export function detectProject(dir, deps = {}) {
120
+ const onPath = deps.isOnPath ?? isOnPath;
120
121
  if (existsSync(path.join(dir, "package.json"))) {
121
122
  const hasYarnLock = existsSync(path.join(dir, "yarn.lock"));
122
123
  const hasPnpmLock = existsSync(path.join(dir, "pnpm-lock.yaml"));
@@ -133,24 +134,13 @@ export function detectProject(dir) {
133
134
  : hasBunLock
134
135
  ? "bun install"
135
136
  : "npm install";
136
- // Same disclosure contract as the Python skew below: a missing toolchain is
137
- // ours to state here, not theirs to infer. Without this, `init`'s install
138
- // failure prints "run `bun install` manually", which is the command that just
139
- // failed — and the candidate is left guessing that a runtime they may never
140
- // have heard of is the missing piece.
141
- //
142
137
  // Gated on the SELECTED command, not on `hasBunLock`. A repo carrying both a
143
- // bun lockfile and a pnpm/yarn one resolves to pnpm/yarn above, and telling
144
- // that candidate to install Bun and run `bun install` would send them to
145
- // install a second, competing dependency tree over the one we just built.
146
- // Also means npm/yarn/pnpm repos never pay for the PATH probe.
147
- const toolchainWarning = installCommand === "bun install" && !isOnPath("bun")
148
- ? "This assessment's scaffold is a Bun project (bun.lock), and Bun isn't on " +
149
- "your PATH. Install it from https://bun.sh, then re-run `bun install` in " +
150
- "this folder. npm can install the dependencies but cannot run the " +
151
- "scaffold's server — it uses Bun-only APIs."
152
- : undefined;
153
- return { type: "node", installCommand, toolchainWarning };
138
+ // bun lockfile and a pnpm/yarn one resolves to pnpm/yarn above, and reporting
139
+ // bun as missing there would send the candidate to install a second,
140
+ // competing dependency tree over the one we just built. Also means
141
+ // npm/yarn/pnpm repos never pay for the PATH probe.
142
+ const missingRuntime = installCommand === "bun install" && !onPath("bun") ? "bun" : undefined;
143
+ return { type: "node", installCommand, missingRuntime };
154
144
  }
155
145
  if (existsSync(path.join(dir, "requirements.txt")) ||
156
146
  existsSync(path.join(dir, "pyproject.toml")) ||
@@ -203,4 +193,35 @@ export function detectProject(dir) {
203
193
  }
204
194
  return { type: "unknown", installCommand: null };
205
195
  }
196
+ /** How each supported runtime is obtained. npm ships per-platform bun binaries,
197
+ * and npm is guaranteed present because this CLI is an npm package. */
198
+ export const RUNTIME_INSTALL = {
199
+ bun: "npm install -g bun",
200
+ };
201
+ /**
202
+ * Install a runtime the project needs and the machine lacks.
203
+ *
204
+ * Separated from `init`'s reporting so all three outcomes are assertable: the
205
+ * install failing, and the install "succeeding" while leaving nothing on PATH.
206
+ * That second case is the one worth a unit test — a global install can land
207
+ * somewhere this process cannot reach, and treating it as success means the
208
+ * dependency install below dies on a command-not-found we already knew about.
209
+ */
210
+ export function installRuntime(runtime, deps = {}) {
211
+ const exec = deps.exec ?? ((command) => {
212
+ // spawnSync reports a failure in `status` rather than throwing, so surface
213
+ // it as one — the catch below is what turns it into "unavailable".
214
+ const r = spawnSync(command, { shell: true, stdio: "pipe" });
215
+ if (r.status !== 0)
216
+ throw new Error(`\`${command}\` exited ${r.status}`);
217
+ });
218
+ const onPath = deps.isOnPath ?? isOnPath;
219
+ try {
220
+ exec(RUNTIME_INSTALL[runtime]);
221
+ }
222
+ catch {
223
+ return "unavailable";
224
+ }
225
+ return onPath(runtime) ? "installed" : "unavailable";
226
+ }
206
227
  //# sourceMappingURL=detect-project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"detect-project.js","sourceRoot":"","sources":["../../src/lib/detect-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAA;AAC5C,OAAO,IAAI,MAAM,MAAM,CAAA;AAyBvB;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAA;AAS5C;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,gBAAgB;IACvB,MAAM,OAAO,GAAG,sBAAsB,CAAA;IACtC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO;YACL,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,OAAO,EAAE,EAAE;YAC/D,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;YACtC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;YAC9C,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;SACjD,CAAA;IACH,CAAC;IACD,OAAO;QACL,EAAE,GAAG,EAAE,SAAS,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,OAAO,EAAE,EAAE;QAClE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;KACjD,CAAA;AACH,CAAC;AAED,2EAA2E;AAC3E,SAAS,YAAY,CAAC,SAA0B;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE;YACxE,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,CAAC,CAAA;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QACpC,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAA;QAChG,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB;IAKtC,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAA;IACrC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QAC/C,IAAI,CAAC,eAAe;YAAE,SAAQ;QAC9B,OAAO;YACL,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,wEAAwE;YACxE,mEAAmE;YACnE,sCAAsC;YACtC,aAAa,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG,sBAAsB,GAAG,CAAC;gBACrE,eAAe,KAAK,sBAAsB;YAC5C,eAAe;SAChB,CAAA;IACH,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,CAAA;AAC/E,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,QAAQ,CAAC,GAAW;IAC3B,IAAI,CAAC;QACH,OAAO,CACL,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE;YAC5B,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,CAAC,CAAC,MAAM,KAAK,CAAC,CAChB,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;QAC/C,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAA;QAC3D,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAA;QAChE,8EAA8E;QAC9E,+EAA+E;QAC/E,gFAAgF;QAChF,+EAA+E;QAC/E,yDAAyD;QACzD,MAAM,UAAU,GACd,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAA;QACnF,MAAM,cAAc,GAAG,WAAW;YAChC,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,WAAW;gBACX,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,UAAU;oBACV,CAAC,CAAC,aAAa;oBACf,CAAC,CAAC,aAAa,CAAA;QACrB,4EAA4E;QAC5E,0EAA0E;QAC1E,8EAA8E;QAC9E,4EAA4E;QAC5E,sCAAsC;QACtC,EAAE;QACF,6EAA6E;QAC7E,4EAA4E;QAC5E,yEAAyE;QACzE,0EAA0E;QAC1E,+DAA+D;QAC/D,MAAM,gBAAgB,GACpB,cAAc,KAAK,aAAa,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAClD,CAAC,CAAC,2EAA2E;gBAC3E,0EAA0E;gBAC1E,mEAAmE;gBACnE,4CAA4C;YAC9C,CAAC,CAAC,SAAS,CAAA;QACf,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;IAC3D,CAAC;IAED,IACE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QAC9C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAC5C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,EACtC,CAAC;QACD,0EAA0E;QAC1E,0EAA0E;QAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,cAAc,CAAA;QACnF,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAA;QACzC,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;YACnE,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,oBAAoB,MAAM,8BAA8B;YAC3E,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,oBAAoB,MAAM,eAAe,CAAA;QAC9D,2EAA2E;QAC3E,yEAAyE;QACzE,yEAAyE;QACzE,4EAA4E;QAC5E,mDAAmD;QACnD,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa;YAC3C,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,MAAM,CAAC,eAAe;gBACtB,CAAC,CAAC,uCAAuC,sBAAsB,yBAAyB;oBACtF,UAAU,MAAM,CAAC,eAAe,OAAO,MAAM,CAAC,OAAO,wCAAwC;oBAC7F,oEAAoE;oBACpE,GAAG,sBAAsB,oDAAoD;gBAC/E,CAAC,CAAC,sDAAsD,MAAM,CAAC,OAAO,kBAAkB;oBACtF,sDAAsD,sBAAsB,aAAa;oBACzF,0CAA0C,CAAA;QAChD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;IAC7D,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;QACzC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAA;IAC1D,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;IACxD,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,EAAE,CAAC;QACjG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,CAAA;IACzD,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;IAC7D,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,CAAA;IAC/C,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;IAC3D,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA;IAC5D,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,CAAA;AAClD,CAAC"}
1
+ {"version":3,"file":"detect-project.js","sourceRoot":"","sources":["../../src/lib/detect-project.ts"],"names":[],"mappings":"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"}