litmus-cli 1.0.19 → 1.0.21

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 (56) hide show
  1. package/README.md +2 -2
  2. package/dist/commands/init.js +2 -2
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/commands/status.js +1 -1
  5. package/dist/commands/status.js.map +1 -1
  6. package/dist/commands/submit.d.ts.map +1 -1
  7. package/dist/commands/submit.js +35 -11
  8. package/dist/commands/submit.js.map +1 -1
  9. package/dist/index.js +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/api.d.ts +6 -16
  12. package/dist/lib/api.d.ts.map +1 -1
  13. package/dist/lib/api.js +67 -5
  14. package/dist/lib/api.js.map +1 -1
  15. package/dist/lib/config.d.ts +0 -3
  16. package/dist/lib/config.d.ts.map +1 -1
  17. package/dist/lib/config.js +0 -3
  18. package/dist/lib/config.js.map +1 -1
  19. package/dist/lib/detect-project.d.ts.map +1 -0
  20. package/dist/lib/detect-project.js.map +1 -0
  21. package/dist/{utils → lib}/errors.d.ts +1 -1
  22. package/dist/lib/errors.d.ts.map +1 -0
  23. package/dist/{utils → lib}/errors.js +2 -3
  24. package/dist/lib/errors.js.map +1 -0
  25. package/dist/lib/extract.d.ts +1 -1
  26. package/dist/lib/extract.d.ts.map +1 -1
  27. package/dist/lib/extract.js +19 -3
  28. package/dist/lib/extract.js.map +1 -1
  29. package/dist/lib/hook-logger.cjs +13 -6
  30. package/dist/lib/platform.d.ts +37 -0
  31. package/dist/lib/platform.d.ts.map +1 -0
  32. package/dist/lib/platform.js +69 -0
  33. package/dist/lib/platform.js.map +1 -0
  34. package/dist/lib/schemas.d.ts +24 -0
  35. package/dist/lib/schemas.d.ts.map +1 -0
  36. package/dist/lib/schemas.js +21 -0
  37. package/dist/lib/schemas.js.map +1 -0
  38. package/dist/lib/tracker.d.ts +1 -1
  39. package/dist/lib/tracker.js +2 -2
  40. package/dist/lib/tracker.js.map +1 -1
  41. package/dist/lib/watcher.d.ts +17 -0
  42. package/dist/lib/watcher.d.ts.map +1 -0
  43. package/dist/lib/watcher.js +752 -0
  44. package/dist/lib/watcher.js.map +1 -0
  45. package/package.json +23 -8
  46. package/dist/lib/watcher.cjs +0 -414
  47. package/dist/staging.d.ts +0 -2
  48. package/dist/staging.d.ts.map +0 -1
  49. package/dist/staging.js +0 -6
  50. package/dist/staging.js.map +0 -1
  51. package/dist/utils/detect-project.d.ts.map +0 -1
  52. package/dist/utils/detect-project.js.map +0 -1
  53. package/dist/utils/errors.d.ts.map +0 -1
  54. package/dist/utils/errors.js.map +0 -1
  55. /package/dist/{utils → lib}/detect-project.d.ts +0 -0
  56. /package/dist/{utils → lib}/detect-project.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Extract a ZIP file from disk to a target directory.
3
- * Using Open.file + extract() is the most reliable unzipper API.
3
+ * Iterates entries individually to validate paths against traversal attacks.
4
4
  */
5
5
  export declare function extractZip(zipPath: string, targetDir: string): Promise<void>;
6
6
  //# sourceMappingURL=extract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/lib/extract.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf"}
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/lib/extract.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -1,12 +1,28 @@
1
+ import { createWriteStream } from "fs";
1
2
  import { mkdir } from "fs/promises";
3
+ import path from "path";
4
+ import { pipeline } from "stream/promises";
2
5
  import unzipper from "unzipper";
3
6
  /**
4
7
  * Extract a ZIP file from disk to a target directory.
5
- * Using Open.file + extract() is the most reliable unzipper API.
8
+ * Iterates entries individually to validate paths against traversal attacks.
6
9
  */
7
10
  export async function extractZip(zipPath, targetDir) {
8
- await mkdir(targetDir, { recursive: true });
11
+ const resolvedTarget = path.resolve(targetDir) + path.sep;
12
+ await mkdir(resolvedTarget, { recursive: true });
9
13
  const directory = await unzipper.Open.file(zipPath);
10
- await directory.extract({ path: targetDir });
14
+ for (const entry of directory.files) {
15
+ const resolvedPath = path.resolve(resolvedTarget, entry.path);
16
+ if (!resolvedPath.startsWith(resolvedTarget)) {
17
+ throw new Error(`ZIP path traversal detected: "${entry.path}" escapes target directory`);
18
+ }
19
+ if (entry.type === "Directory") {
20
+ await mkdir(resolvedPath, { recursive: true });
21
+ }
22
+ else {
23
+ await mkdir(path.dirname(resolvedPath), { recursive: true });
24
+ await pipeline(entry.stream(), createWriteStream(resolvedPath));
25
+ }
26
+ }
11
27
  }
12
28
  //# sourceMappingURL=extract.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/lib/extract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,SAAiB;IAEjB,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnD,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;AAC9C,CAAC"}
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/lib/extract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,SAAiB;IAEjB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,CAAA;IACzD,MAAM,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEhD,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAEnD,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QAC7D,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CACb,iCAAiC,KAAK,CAAC,IAAI,4BAA4B,CACxE,CAAA;QACH,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAChD,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAC5D,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -58,14 +58,16 @@ function uploadEvent(config, event) {
58
58
  if (!config || !config.token || !config.backendUrl) return
59
59
 
60
60
  const body = JSON.stringify({ events: [event] })
61
- const url = new URL(
62
- `${config.backendUrl}/cli/activity?token=${encodeURIComponent(config.token)}`
63
- )
61
+ const url = new URL(`${config.backendUrl}/cli/activity`)
64
62
  const reqFn = url.protocol === "https:" ? https.request : http.request
65
63
 
66
64
  const req = reqFn(url, {
67
65
  method: "POST",
68
- headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) },
66
+ headers: {
67
+ "Content-Type": "application/json",
68
+ "Content-Length": Buffer.byteLength(body),
69
+ "Authorization": `Bearer ${config.token}`,
70
+ },
69
71
  timeout: 5000,
70
72
  })
71
73
  req.on("error", () => {}) // Swallow — fire-and-forget
@@ -146,7 +148,12 @@ async function main() {
146
148
  const raw = await readStdin()
147
149
  if (!raw.trim()) return
148
150
 
149
- const { prompt, sessionId } = extractPrompt(raw, tool)
151
+ // Detect Cursor firing Claude Code hooks — Cursor sets CURSOR_TRACE_ID
152
+ const effectiveTool = (tool === "claude" && process.env.CURSOR_TRACE_ID)
153
+ ? "cursor"
154
+ : tool
155
+
156
+ const { prompt, sessionId } = extractPrompt(raw, effectiveTool)
150
157
  if (!prompt) return
151
158
 
152
159
  const truncated = prompt.length > MAX_PROMPT_LENGTH
@@ -156,7 +163,7 @@ async function main() {
156
163
  const event = {
157
164
  ts: new Date().toISOString(),
158
165
  type: "ai_prompt",
159
- tool,
166
+ tool: effectiveTool,
160
167
  prompt: truncated,
161
168
  }
162
169
  if (sessionId) event.sessionId = sessionId
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Platform adapter — encapsulates OS-specific commands so detection logic
3
+ * stays platform-agnostic. Callers never branch on process.platform.
4
+ */
5
+ /**
6
+ * Returns lowercase text listing all running processes.
7
+ * Used for regex matching against editor/AI tool name patterns.
8
+ *
9
+ * - macOS/Linux: `ps aux` (full command lines)
10
+ * - Windows: `tasklist` (image names like Code.exe, Cursor.exe)
11
+ *
12
+ * Output is lowercased so patterns like /\bcode\b/ match uniformly.
13
+ */
14
+ export declare function getProcessList(): string;
15
+ /**
16
+ * Lists active network connections asynchronously.
17
+ * Calls cb(err, stdout) with raw connection output.
18
+ * Handles platform fallbacks internally (lsof → ss on Linux).
19
+ *
20
+ * - macOS: `lsof -i -n -P`
21
+ * - Linux: `lsof -i -n -P`, falls back to `ss -tnp` if lsof is unavailable
22
+ * - Windows: `netstat -ano`
23
+ */
24
+ export declare function getConnections(cb: (err: Error | null, stdout?: string) => void): void;
25
+ /**
26
+ * Extracts the destination IP address from a single connection output line.
27
+ * Returns a regex match array [fullMatch, ip, port] or null.
28
+ *
29
+ * Format varies by tool:
30
+ * lsof: "... ->104.18.7.42:443 ..."
31
+ * ss: "... 104.18.7.42:443" (IP:port at end of line)
32
+ * netstat: " TCP local:port foreign:port STATE PID" (3rd column)
33
+ *
34
+ * On Unix, trying both lsof and ss patterns is safe — they don't cross-match.
35
+ */
36
+ export declare function extractConnectionIP(line: string): RegExpMatchArray | null;
37
+ //# sourceMappingURL=platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/lib/platform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;;;;;GAQG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAarF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAYzE"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Platform adapter — encapsulates OS-specific commands so detection logic
3
+ * stays platform-agnostic. Callers never branch on process.platform.
4
+ */
5
+ import { execSync, execFile } from "child_process";
6
+ const isWin = process.platform === "win32";
7
+ const isLinux = process.platform === "linux";
8
+ /**
9
+ * Returns lowercase text listing all running processes.
10
+ * Used for regex matching against editor/AI tool name patterns.
11
+ *
12
+ * - macOS/Linux: `ps aux` (full command lines)
13
+ * - Windows: `tasklist` (image names like Code.exe, Cursor.exe)
14
+ *
15
+ * Output is lowercased so patterns like /\bcode\b/ match uniformly.
16
+ */
17
+ export function getProcessList() {
18
+ const cmd = isWin ? "tasklist" : "ps aux";
19
+ return execSync(cmd, { timeout: 5000, encoding: "utf8" }).toLowerCase();
20
+ }
21
+ /**
22
+ * Lists active network connections asynchronously.
23
+ * Calls cb(err, stdout) with raw connection output.
24
+ * Handles platform fallbacks internally (lsof → ss on Linux).
25
+ *
26
+ * - macOS: `lsof -i -n -P`
27
+ * - Linux: `lsof -i -n -P`, falls back to `ss -tnp` if lsof is unavailable
28
+ * - Windows: `netstat -ano`
29
+ */
30
+ export function getConnections(cb) {
31
+ if (isWin) {
32
+ execFile("netstat", ["-ano"], { timeout: 10000, encoding: "utf8", maxBuffer: 2 * 1024 * 1024 }, cb);
33
+ return;
34
+ }
35
+ execFile("lsof", ["-i", "-n", "-P"], { timeout: 10000, encoding: "utf8", maxBuffer: 2 * 1024 * 1024 }, (err, stdout) => {
36
+ if (err && err.code === "ENOENT" && isLinux) {
37
+ // lsof unavailable on Linux — fall back to ss
38
+ execFile("ss", ["-tnp"], { timeout: 5000, encoding: "utf8", maxBuffer: 1024 * 1024 }, cb);
39
+ }
40
+ else {
41
+ cb(err, stdout);
42
+ }
43
+ });
44
+ }
45
+ /**
46
+ * Extracts the destination IP address from a single connection output line.
47
+ * Returns a regex match array [fullMatch, ip, port] or null.
48
+ *
49
+ * Format varies by tool:
50
+ * lsof: "... ->104.18.7.42:443 ..."
51
+ * ss: "... 104.18.7.42:443" (IP:port at end of line)
52
+ * netstat: " TCP local:port foreign:port STATE PID" (3rd column)
53
+ *
54
+ * On Unix, trying both lsof and ss patterns is safe — they don't cross-match.
55
+ */
56
+ export function extractConnectionIP(line) {
57
+ if (isWin) {
58
+ const parts = line.trim().split(/\s+/);
59
+ if (parts.length >= 4 && (parts[0] === "TCP" || parts[0] === "UDP")) {
60
+ return parts[2].match(/^(\d+\.\d+\.\d+\.\d+):(\d+)$/);
61
+ }
62
+ return null;
63
+ }
64
+ // lsof "->IP:port" (won't match ss output — no "->" in ss)
65
+ // ss "IP:port" at EOL (won't match lsof — lines end with "(STATE)")
66
+ return line.match(/->(\d+\.\d+\.\d+\.\d+):(\d+)/) ||
67
+ line.match(/\s(\d+\.\d+\.\d+\.\d+):(\d+)\s*$/);
68
+ }
69
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/lib/platform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAElD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAA;AAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAA;AAE5C;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAA;IACzC,OAAO,QAAQ,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;AACzE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,EAAgD;IAC7E,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,KAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QACpG,OAAM;IACR,CAAC;IACD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,KAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACtH,IAAI,GAAG,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,EAAE,CAAC;YACvE,8CAA8C;YAC9C,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;QAC3F,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACtC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACpE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAA;QACvD,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,2DAA2D;IAC3D,oEAAoE;IACpE,OAAO,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAA;AACvD,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ export declare const InitMetadataSchema: z.ZodObject<{
3
+ assessmentId: z.ZodUUID;
4
+ assessmentName: z.ZodString;
5
+ folderName: z.ZodString;
6
+ backendUrl: z.ZodURL;
7
+ candidateEmail: z.ZodEmail;
8
+ candidateName: z.ZodString;
9
+ deadline: z.ZodNullable<z.ZodISODateTime>;
10
+ timeLimit: z.ZodNullable<z.ZodNumber>;
11
+ startedAt: z.ZodISODateTime;
12
+ }, z.core.$strip>;
13
+ export type InitMetadata = z.infer<typeof InitMetadataSchema>;
14
+ export declare const SubmitResultSchema: z.ZodObject<{
15
+ submissionId: z.ZodUUID;
16
+ success: z.ZodBoolean;
17
+ message: z.ZodString;
18
+ }, z.core.$strip>;
19
+ export type SubmitResult = z.infer<typeof SubmitResultSchema>;
20
+ export declare const SubmitStatusSchema: z.ZodObject<{
21
+ videoUploaded: z.ZodBoolean;
22
+ }, z.core.$strip>;
23
+ export type SubmitStatus = z.infer<typeof SubmitStatusSchema>;
24
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,kBAAkB;;;;;;;;;;iBAa7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D,eAAO,MAAM,kBAAkB;;;;iBAI7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D,eAAO,MAAM,kBAAkB;;iBAE7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ export const InitMetadataSchema = z.object({
3
+ assessmentId: z.uuid(),
4
+ assessmentName: z.string(),
5
+ folderName: z.string(),
6
+ backendUrl: z.url(),
7
+ candidateEmail: z.email(),
8
+ candidateName: z.string(),
9
+ deadline: z.iso.datetime().nullable(),
10
+ timeLimit: z.number().nullable(),
11
+ startedAt: z.iso.datetime(),
12
+ });
13
+ export const SubmitResultSchema = z.object({
14
+ submissionId: z.uuid(),
15
+ success: z.boolean(),
16
+ message: z.string(),
17
+ });
18
+ export const SubmitStatusSchema = z.object({
19
+ videoUploaded: z.boolean(),
20
+ });
21
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE;IACtB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAE1B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE;IAEnB,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE;IACzB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IAEzB,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAA;AAIF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE;IACtB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAA;AAIF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE;CAC3B,CAAC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Start the file watcher in the background.
3
- * Spawns watcher.cjs as a detached process; logs file events to
3
+ * Spawns watcher.js as a detached process; logs file events to
4
4
  * <projectDir>/.litmus/activity.jsonl for later inclusion in the submission ZIP.
5
5
  */
6
6
  export declare function startTracker(projectDir: string): void;
@@ -15,7 +15,7 @@ function isProcessAlive(pid) {
15
15
  }
16
16
  /**
17
17
  * Start the file watcher in the background.
18
- * Spawns watcher.cjs as a detached process; logs file events to
18
+ * Spawns watcher.js as a detached process; logs file events to
19
19
  * <projectDir>/.litmus/activity.jsonl for later inclusion in the submission ZIP.
20
20
  */
21
21
  export function startTracker(projectDir) {
@@ -42,7 +42,7 @@ export function startTracker(projectDir) {
42
42
  }
43
43
  }
44
44
  const errFd = openSync(errLog, "a");
45
- const watcherPath = path.join(__dirname, "watcher.cjs");
45
+ const watcherPath = path.join(__dirname, "watcher.js");
46
46
  const cliBinPath = path.join(__dirname, "..", "index.js");
47
47
  const child = spawn(process.execPath, [watcherPath, projectDir, activityLog, cliBinPath], {
48
48
  detached: true,
@@ -1 +1 @@
1
- {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/lib/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AACjF,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1C,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA,CAAC,qCAAqC;QAC1D,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAElD,IAAI,CAAC;QACH,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,wCAAwC;IACxC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;YACtE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;gBACvD,OAAM,CAAC,0BAA0B;YACnC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uDAAuD;QACzD,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IAEzD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE;QACxF,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;KACnC,CAAC,CAAA;IAEF,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,IAAI,CAAC;YACH,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/lib/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AACjF,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1C,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA,CAAC,qCAAqC;QAC1D,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAElD,IAAI,CAAC;QACH,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,wCAAwC;IACxC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;YACtE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;gBACvD,OAAM,CAAC,0BAA0B;YACnC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uDAAuD;QACzD,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;IACtD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IAEzD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE;QACxF,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC;KACnC,CAAC,CAAA;IAEF,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,IAAI,CAAC;YACH,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Litmus file activity watcher.
4
+ * Runs as a detached background process started by `litmus init`.
5
+ * Usage: node watcher.js <projectDir> <activityLogPath> [cliBinPath]
6
+ *
7
+ * Tracks:
8
+ * - File changes with size deltas and large-paste detection (debounced 500ms per file)
9
+ * - Heartbeat events every 5 minutes
10
+ * - Git commit events (polled every 30s)
11
+ * - Editor and AI tool detection (polled every 10 min)
12
+ * - Auto-submit at deadline (if deadline/timeLimit configured)
13
+ *
14
+ * Writes newline-delimited JSON to the activity log.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/lib/watcher.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}