@vibe-interviewing/core 0.1.0 → 0.3.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.
- package/README.md +26 -0
- package/dist/chunk-CI3BD2WQ.js +141 -0
- package/dist/chunk-CI3BD2WQ.js.map +1 -0
- package/dist/index.d.ts +19 -364
- package/dist/index.js +172 -105
- package/dist/index.js.map +1 -1
- package/dist/network/index.d.ts +81 -0
- package/dist/network/index.js +309 -0
- package/dist/network/index.js.map +1 -0
- package/dist/session-code-CfhXelpW.d.ts +519 -0
- package/package.json +6 -2
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @vibe-interviewing/core
|
|
2
|
+
|
|
3
|
+
Core library for [vibe-interviewing](https://github.com/cpaczek/vibe-interviewing).
|
|
4
|
+
|
|
5
|
+
Provides the scenario engine, git-based session management, workspace setup, and Claude Code launcher used by the CLI.
|
|
6
|
+
|
|
7
|
+
## What's inside
|
|
8
|
+
|
|
9
|
+
- **Scenario engine** — loads and validates `scenario.yaml` configs via Zod schemas
|
|
10
|
+
- **Workspace manager** — clones repos at pinned commits, applies patches, injects bugs, wipes git history
|
|
11
|
+
- **Session manager** — tracks interview sessions (timing, state, metadata)
|
|
12
|
+
- **AI tool launcher** — launches Claude Code with system prompt injection via `--append-system-prompt`
|
|
13
|
+
- **Network client** — uploads/downloads sessions to the cloud relay for remote interviews
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
This package is used internally by the `vibe-interviewing` CLI. It's published as `@vibe-interviewing/core` on npm for the CLI's dependency resolution.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { ScenarioEngine, WorkspaceManager, SessionManager } from '@vibe-interviewing/core'
|
|
21
|
+
import { CloudClient } from '@vibe-interviewing/core/network'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
MIT
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var VibeError = class extends Error {
|
|
3
|
+
constructor(message, code, hint) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.hint = hint;
|
|
7
|
+
this.name = "VibeError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var ScenarioNotFoundError = class extends VibeError {
|
|
11
|
+
constructor(name) {
|
|
12
|
+
super(
|
|
13
|
+
`Scenario not found: ${name}`,
|
|
14
|
+
"SCENARIO_NOT_FOUND",
|
|
15
|
+
"Run `vibe-interviewing list` to see available scenarios"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var ScenarioValidationError = class extends VibeError {
|
|
20
|
+
constructor(message, issues) {
|
|
21
|
+
super(`Invalid scenario config: ${message}`, "SCENARIO_VALIDATION_ERROR", issues.join("\n"));
|
|
22
|
+
this.issues = issues;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var AIToolNotFoundError = class _AIToolNotFoundError extends VibeError {
|
|
26
|
+
static installHints = {
|
|
27
|
+
"claude-code": "Install Claude Code: npm install -g @anthropic-ai/claude-code"
|
|
28
|
+
};
|
|
29
|
+
constructor(tool) {
|
|
30
|
+
super(
|
|
31
|
+
`${tool} is not installed`,
|
|
32
|
+
"AI_TOOL_NOT_FOUND",
|
|
33
|
+
_AIToolNotFoundError.installHints[tool] ?? `Install ${tool} and try again`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var SessionNotFoundError = class extends VibeError {
|
|
38
|
+
constructor(id) {
|
|
39
|
+
super(
|
|
40
|
+
`Session not found: ${id}`,
|
|
41
|
+
"SESSION_NOT_FOUND",
|
|
42
|
+
"Run `vibe-interviewing list` to see active sessions"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var GitCloneError = class extends VibeError {
|
|
47
|
+
constructor(repo, reason) {
|
|
48
|
+
super(
|
|
49
|
+
`Failed to clone repository: ${repo}${reason ? ` \u2014 ${reason}` : ""}`,
|
|
50
|
+
"GIT_CLONE_FAILED",
|
|
51
|
+
"Check the repo URL and your network connection"
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var SetupError = class extends VibeError {
|
|
56
|
+
constructor(command, reason) {
|
|
57
|
+
super(
|
|
58
|
+
`Setup command failed: ${command}${reason ? ` \u2014 ${reason}` : ""}`,
|
|
59
|
+
"SETUP_FAILED",
|
|
60
|
+
"Check the scenario setup commands and try again"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var ScenarioFetchError = class extends VibeError {
|
|
65
|
+
constructor(url, reason) {
|
|
66
|
+
super(
|
|
67
|
+
`Failed to fetch scenario from URL: ${url}${reason ? ` \u2014 ${reason}` : ""}`,
|
|
68
|
+
"SCENARIO_FETCH_FAILED",
|
|
69
|
+
"Check the URL is accessible and returns valid YAML"
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/network/session-code.ts
|
|
75
|
+
function encodeSessionCode(host, port) {
|
|
76
|
+
const octets = host.split(".").map(Number);
|
|
77
|
+
if (octets.length !== 4 || octets.some((o) => isNaN(o) || o < 0 || o > 255)) {
|
|
78
|
+
throw new InvalidSessionCodeError(`Invalid IPv4 address: ${host}`);
|
|
79
|
+
}
|
|
80
|
+
if (port < 1 || port > 65535) {
|
|
81
|
+
throw new InvalidSessionCodeError(`Invalid port: ${port}`);
|
|
82
|
+
}
|
|
83
|
+
const buf = Buffer.alloc(6);
|
|
84
|
+
buf[0] = octets[0];
|
|
85
|
+
buf[1] = octets[1];
|
|
86
|
+
buf[2] = octets[2];
|
|
87
|
+
buf[3] = octets[3];
|
|
88
|
+
buf.writeUInt16BE(port, 4);
|
|
89
|
+
const num = buf.readUIntBE(0, 6);
|
|
90
|
+
const code = num.toString(36).toUpperCase().padStart(10, "0");
|
|
91
|
+
return `VIBE-${code}`;
|
|
92
|
+
}
|
|
93
|
+
function decodeSessionCode(code) {
|
|
94
|
+
let raw = code.trim().toUpperCase();
|
|
95
|
+
if (raw.startsWith("VIBE-")) {
|
|
96
|
+
raw = raw.slice(5);
|
|
97
|
+
}
|
|
98
|
+
if (!/^[0-9A-Z]{1,10}$/.test(raw)) {
|
|
99
|
+
throw new InvalidSessionCodeError(`Invalid session code format: ${code}`);
|
|
100
|
+
}
|
|
101
|
+
const num = parseInt(raw, 36);
|
|
102
|
+
if (isNaN(num) || num > 281474976710655) {
|
|
103
|
+
throw new InvalidSessionCodeError(`Invalid session code: ${code}`);
|
|
104
|
+
}
|
|
105
|
+
const buf = Buffer.alloc(6);
|
|
106
|
+
buf.writeUIntBE(num, 0, 6);
|
|
107
|
+
const host = `${buf[0]}.${buf[1]}.${buf[2]}.${buf[3]}`;
|
|
108
|
+
const port = buf.readUInt16BE(4);
|
|
109
|
+
if (port === 0) {
|
|
110
|
+
throw new InvalidSessionCodeError(`Invalid session code (port 0): ${code}`);
|
|
111
|
+
}
|
|
112
|
+
return { host, port };
|
|
113
|
+
}
|
|
114
|
+
function isCloudSessionCode(code) {
|
|
115
|
+
let raw = code.trim().toUpperCase();
|
|
116
|
+
if (raw.startsWith("VIBE-")) {
|
|
117
|
+
raw = raw.slice(5);
|
|
118
|
+
}
|
|
119
|
+
return /^[0-9A-Z]{6}$/.test(raw);
|
|
120
|
+
}
|
|
121
|
+
var InvalidSessionCodeError = class extends VibeError {
|
|
122
|
+
constructor(message) {
|
|
123
|
+
super(message, "INVALID_SESSION_CODE", "Session codes look like VIBE-XXXXXXXXXX");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
VibeError,
|
|
129
|
+
ScenarioNotFoundError,
|
|
130
|
+
ScenarioValidationError,
|
|
131
|
+
AIToolNotFoundError,
|
|
132
|
+
SessionNotFoundError,
|
|
133
|
+
GitCloneError,
|
|
134
|
+
SetupError,
|
|
135
|
+
ScenarioFetchError,
|
|
136
|
+
encodeSessionCode,
|
|
137
|
+
decodeSessionCode,
|
|
138
|
+
isCloudSessionCode,
|
|
139
|
+
InvalidSessionCodeError
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=chunk-CI3BD2WQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/network/session-code.ts"],"sourcesContent":["/** Base error class for all vibe-interviewing errors */\nexport class VibeError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly hint?: string,\n ) {\n super(message)\n this.name = 'VibeError'\n }\n}\n\nexport class ScenarioNotFoundError extends VibeError {\n constructor(name: string) {\n super(\n `Scenario not found: ${name}`,\n 'SCENARIO_NOT_FOUND',\n 'Run `vibe-interviewing list` to see available scenarios',\n )\n }\n}\n\nexport class ScenarioValidationError extends VibeError {\n constructor(\n message: string,\n public readonly issues: string[],\n ) {\n super(`Invalid scenario config: ${message}`, 'SCENARIO_VALIDATION_ERROR', issues.join('\\n'))\n }\n}\n\nexport class AIToolNotFoundError extends VibeError {\n static readonly installHints: Record<string, string> = {\n 'claude-code': 'Install Claude Code: npm install -g @anthropic-ai/claude-code',\n }\n\n constructor(tool: string) {\n super(\n `${tool} is not installed`,\n 'AI_TOOL_NOT_FOUND',\n AIToolNotFoundError.installHints[tool] ?? `Install ${tool} and try again`,\n )\n }\n}\n\nexport class SessionNotFoundError extends VibeError {\n constructor(id: string) {\n super(\n `Session not found: ${id}`,\n 'SESSION_NOT_FOUND',\n 'Run `vibe-interviewing list` to see active sessions',\n )\n }\n}\n\nexport class GitCloneError extends VibeError {\n constructor(repo: string, reason?: string) {\n super(\n `Failed to clone repository: ${repo}${reason ? ` — ${reason}` : ''}`,\n 'GIT_CLONE_FAILED',\n 'Check the repo URL and your network connection',\n )\n }\n}\n\nexport class SetupError extends VibeError {\n constructor(command: string, reason?: string) {\n super(\n `Setup command failed: ${command}${reason ? ` — ${reason}` : ''}`,\n 'SETUP_FAILED',\n 'Check the scenario setup commands and try again',\n )\n }\n}\n\nexport class ScenarioFetchError extends VibeError {\n constructor(url: string, reason?: string) {\n super(\n `Failed to fetch scenario from URL: ${url}${reason ? ` — ${reason}` : ''}`,\n 'SCENARIO_FETCH_FAILED',\n 'Check the URL is accessible and returns valid YAML',\n )\n }\n}\n","import { VibeError } from '../errors.js'\n\n/**\n * Encode a host:port pair into a human-typeable session code.\n *\n * Format: VIBE-XXXXXXXXXX (10 base36 chars encoding 6 bytes: 4 IP octets + 2 port bytes)\n */\nexport function encodeSessionCode(host: string, port: number): string {\n const octets = host.split('.').map(Number)\n if (octets.length !== 4 || octets.some((o) => isNaN(o) || o < 0 || o > 255)) {\n throw new InvalidSessionCodeError(`Invalid IPv4 address: ${host}`)\n }\n if (port < 1 || port > 65535) {\n throw new InvalidSessionCodeError(`Invalid port: ${port}`)\n }\n\n // Pack into 6 bytes: [ip0, ip1, ip2, ip3, port_hi, port_lo]\n const buf = Buffer.alloc(6)\n buf[0] = octets[0]!\n buf[1] = octets[1]!\n buf[2] = octets[2]!\n buf[3] = octets[3]!\n buf.writeUInt16BE(port, 4)\n\n // Convert to base36, zero-pad to 10 chars\n const num = buf.readUIntBE(0, 6)\n const code = num.toString(36).toUpperCase().padStart(10, '0')\n\n return `VIBE-${code}`\n}\n\n/**\n * Decode a session code back to host:port.\n *\n * Accepts formats: VIBE-XXXXXXXXXX, vibe-xxxxxxxxxx, or just XXXXXXXXXX\n */\nexport function decodeSessionCode(code: string): { host: string; port: number } {\n // Strip VIBE- prefix if present\n let raw = code.trim().toUpperCase()\n if (raw.startsWith('VIBE-')) {\n raw = raw.slice(5)\n }\n\n if (!/^[0-9A-Z]{1,10}$/.test(raw)) {\n throw new InvalidSessionCodeError(`Invalid session code format: ${code}`)\n }\n\n const num = parseInt(raw, 36)\n if (isNaN(num) || num > 0xffffffffffff) {\n throw new InvalidSessionCodeError(`Invalid session code: ${code}`)\n }\n\n const buf = Buffer.alloc(6)\n // Write as 6-byte big-endian\n buf.writeUIntBE(num, 0, 6)\n\n const host = `${buf[0]}.${buf[1]}.${buf[2]}.${buf[3]}`\n const port = buf.readUInt16BE(4)\n\n if (port === 0) {\n throw new InvalidSessionCodeError(`Invalid session code (port 0): ${code}`)\n }\n\n return { host, port }\n}\n\n/**\n * Check if a session code is a cloud code (6 chars) vs LAN code (10 chars).\n *\n * Cloud codes are 6 alphanumeric characters: VIBE-A3X9K2\n * LAN codes are 10 alphanumeric characters: VIBE-3R8KW1F0NX\n */\nexport function isCloudSessionCode(code: string): boolean {\n let raw = code.trim().toUpperCase()\n if (raw.startsWith('VIBE-')) {\n raw = raw.slice(5)\n }\n // Cloud codes are exactly 6 chars, LAN codes are up to 10\n return /^[0-9A-Z]{6}$/.test(raw)\n}\n\n/** Error for invalid session codes */\nexport class InvalidSessionCodeError extends VibeError {\n constructor(message: string) {\n super(message, 'INVALID_SESSION_CODE', 'Session codes look like VIBE-XXXXXXXXXX')\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,177 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/** Role description for the AI assistant */
|
|
5
|
-
role: z.ZodString;
|
|
6
|
-
/** Behavioral rules (e.g., "don't reveal the answer") */
|
|
7
|
-
rules: z.ZodArray<z.ZodString, "many">;
|
|
8
|
-
/** Knowledge about the bug/solution (hidden from candidate) */
|
|
9
|
-
knowledge: z.ZodString;
|
|
10
|
-
}, "strip", z.ZodTypeAny, {
|
|
11
|
-
role: string;
|
|
12
|
-
rules: string[];
|
|
13
|
-
knowledge: string;
|
|
14
|
-
}, {
|
|
15
|
-
role: string;
|
|
16
|
-
rules: string[];
|
|
17
|
-
knowledge: string;
|
|
18
|
-
}>;
|
|
19
|
-
declare const EvaluationSchema: z.ZodObject<{
|
|
20
|
-
/** Evaluation criteria for the interviewer */
|
|
21
|
-
criteria: z.ZodArray<z.ZodString, "many">;
|
|
22
|
-
/** Description of the expected fix */
|
|
23
|
-
expected_fix: z.ZodOptional<z.ZodString>;
|
|
24
|
-
}, "strip", z.ZodTypeAny, {
|
|
25
|
-
criteria: string[];
|
|
26
|
-
expected_fix?: string | undefined;
|
|
27
|
-
}, {
|
|
28
|
-
criteria: string[];
|
|
29
|
-
expected_fix?: string | undefined;
|
|
30
|
-
}>;
|
|
31
|
-
/** Full scenario configuration schema */
|
|
32
|
-
declare const ScenarioConfigSchema: z.ZodObject<{
|
|
33
|
-
/** Scenario display name */
|
|
34
|
-
name: z.ZodString;
|
|
35
|
-
/** One-line description */
|
|
36
|
-
description: z.ZodString;
|
|
37
|
-
/** Difficulty level */
|
|
38
|
-
difficulty: z.ZodEnum<["easy", "medium", "hard"]>;
|
|
39
|
-
/** Estimated time (e.g., "30-45m") */
|
|
40
|
-
estimated_time: z.ZodString;
|
|
41
|
-
/** Searchable tags */
|
|
42
|
-
tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
43
|
-
/** GitHub repo URL or owner/repo shorthand */
|
|
44
|
-
repo: z.ZodString;
|
|
45
|
-
/** Commit SHA to pin the clone to (ensures reproducibility) */
|
|
46
|
-
commit: z.ZodString;
|
|
47
|
-
/** Shell commands to run after cloning (e.g., ["npm install"]) */
|
|
48
|
-
setup: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
49
|
-
/** Find-and-replace patches to inject the bug after cloning */
|
|
50
|
-
patch: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
51
|
-
/** Path to the file relative to repo root */
|
|
52
|
-
file: z.ZodString;
|
|
53
|
-
/** The original text to find */
|
|
54
|
-
find: z.ZodString;
|
|
55
|
-
/** The replacement text (with the bug) */
|
|
56
|
-
replace: z.ZodString;
|
|
57
|
-
}, "strip", z.ZodTypeAny, {
|
|
58
|
-
find: string;
|
|
59
|
-
file: string;
|
|
60
|
-
replace: string;
|
|
61
|
-
}, {
|
|
62
|
-
find: string;
|
|
63
|
-
file: string;
|
|
64
|
-
replace: string;
|
|
65
|
-
}>, "many">>;
|
|
66
|
-
/** Briefing shown to the candidate (written like a team lead message) */
|
|
67
|
-
briefing: z.ZodString;
|
|
68
|
-
/** AI behavioral rules (injected via system prompt, hidden from candidate) */
|
|
69
|
-
ai_rules: z.ZodObject<{
|
|
70
|
-
/** Role description for the AI assistant */
|
|
71
|
-
role: z.ZodString;
|
|
72
|
-
/** Behavioral rules (e.g., "don't reveal the answer") */
|
|
73
|
-
rules: z.ZodArray<z.ZodString, "many">;
|
|
74
|
-
/** Knowledge about the bug/solution (hidden from candidate) */
|
|
75
|
-
knowledge: z.ZodString;
|
|
76
|
-
}, "strip", z.ZodTypeAny, {
|
|
77
|
-
role: string;
|
|
78
|
-
rules: string[];
|
|
79
|
-
knowledge: string;
|
|
80
|
-
}, {
|
|
81
|
-
role: string;
|
|
82
|
-
rules: string[];
|
|
83
|
-
knowledge: string;
|
|
84
|
-
}>;
|
|
85
|
-
/** Interviewer reference — what the fix looks like */
|
|
86
|
-
solution: z.ZodString;
|
|
87
|
-
/** Evaluation rubric */
|
|
88
|
-
evaluation: z.ZodOptional<z.ZodObject<{
|
|
89
|
-
/** Evaluation criteria for the interviewer */
|
|
90
|
-
criteria: z.ZodArray<z.ZodString, "many">;
|
|
91
|
-
/** Description of the expected fix */
|
|
92
|
-
expected_fix: z.ZodOptional<z.ZodString>;
|
|
93
|
-
}, "strip", z.ZodTypeAny, {
|
|
94
|
-
criteria: string[];
|
|
95
|
-
expected_fix?: string | undefined;
|
|
96
|
-
}, {
|
|
97
|
-
criteria: string[];
|
|
98
|
-
expected_fix?: string | undefined;
|
|
99
|
-
}>>;
|
|
100
|
-
/** License of the original project */
|
|
101
|
-
license: z.ZodOptional<z.ZodString>;
|
|
102
|
-
}, "strip", z.ZodTypeAny, {
|
|
103
|
-
name: string;
|
|
104
|
-
description: string;
|
|
105
|
-
difficulty: "easy" | "medium" | "hard";
|
|
106
|
-
estimated_time: string;
|
|
107
|
-
tags: string[];
|
|
108
|
-
repo: string;
|
|
109
|
-
commit: string;
|
|
110
|
-
setup: string[];
|
|
111
|
-
patch: {
|
|
112
|
-
find: string;
|
|
113
|
-
file: string;
|
|
114
|
-
replace: string;
|
|
115
|
-
}[];
|
|
116
|
-
briefing: string;
|
|
117
|
-
ai_rules: {
|
|
118
|
-
role: string;
|
|
119
|
-
rules: string[];
|
|
120
|
-
knowledge: string;
|
|
121
|
-
};
|
|
122
|
-
solution: string;
|
|
123
|
-
evaluation?: {
|
|
124
|
-
criteria: string[];
|
|
125
|
-
expected_fix?: string | undefined;
|
|
126
|
-
} | undefined;
|
|
127
|
-
license?: string | undefined;
|
|
128
|
-
}, {
|
|
129
|
-
name: string;
|
|
130
|
-
description: string;
|
|
131
|
-
difficulty: "easy" | "medium" | "hard";
|
|
132
|
-
estimated_time: string;
|
|
133
|
-
repo: string;
|
|
134
|
-
commit: string;
|
|
135
|
-
briefing: string;
|
|
136
|
-
ai_rules: {
|
|
137
|
-
role: string;
|
|
138
|
-
rules: string[];
|
|
139
|
-
knowledge: string;
|
|
140
|
-
};
|
|
141
|
-
solution: string;
|
|
142
|
-
tags?: string[] | undefined;
|
|
143
|
-
setup?: string[] | undefined;
|
|
144
|
-
patch?: {
|
|
145
|
-
find: string;
|
|
146
|
-
file: string;
|
|
147
|
-
replace: string;
|
|
148
|
-
}[] | undefined;
|
|
149
|
-
evaluation?: {
|
|
150
|
-
criteria: string[];
|
|
151
|
-
expected_fix?: string | undefined;
|
|
152
|
-
} | undefined;
|
|
153
|
-
license?: string | undefined;
|
|
154
|
-
}>;
|
|
155
|
-
type ScenarioConfig = z.infer<typeof ScenarioConfigSchema>;
|
|
156
|
-
type AIRules = z.infer<typeof AIRulesSchema>;
|
|
157
|
-
type Evaluation = z.infer<typeof EvaluationSchema>;
|
|
158
|
-
/** Metadata about a discovered scenario */
|
|
159
|
-
interface ScenarioInfo {
|
|
160
|
-
/** Scenario name */
|
|
161
|
-
name: string;
|
|
162
|
-
/** Parsed config */
|
|
163
|
-
config: ScenarioConfig;
|
|
164
|
-
/** Whether this is a built-in scenario */
|
|
165
|
-
builtIn: boolean;
|
|
166
|
-
}
|
|
1
|
+
import { S as ScenarioConfig, a as ScenarioInfo, A as AIToolLauncher, L as LaunchConfig, b as LaunchedProcess, c as StoredSession } from './session-code-CfhXelpW.js';
|
|
2
|
+
export { d as AIRules, e as AIToolNotFoundError, E as Evaluation, G as GitCloneError, I as InterviewerGuide, f as InvalidSessionCodeError, K as KeySignal, P as ProgressCallback, R as RecordingData, g as ScenarioConfigSchema, h as ScenarioFetchError, i as ScenarioNotFoundError, j as ScenarioType, k as ScenarioValidationError, l as Session, m as SessionEvent, n as SessionEventType, o as SessionManager, p as SessionNotFoundError, q as SessionRecorder, r as SetupError, V as VibeError, s as decodeSessionCode, t as encodeSessionCode, u as isCloudSessionCode, v as toStoredSession } from './session-code-CfhXelpW.js';
|
|
3
|
+
import 'zod';
|
|
167
4
|
|
|
168
5
|
/**
|
|
169
|
-
*
|
|
6
|
+
* Check whether a string looks like a URL (http:// or https://).
|
|
7
|
+
*
|
|
8
|
+
* @param input - The string to test
|
|
9
|
+
* @returns true if the string starts with http:// or https://
|
|
10
|
+
*/
|
|
11
|
+
declare function isUrl(input: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Load and parse a scenario config from a YAML file or URL.
|
|
170
14
|
*
|
|
171
|
-
*
|
|
15
|
+
* Accepts either a local file path or an HTTP(S) URL. GitHub blob URLs
|
|
16
|
+
* are automatically converted to raw content URLs.
|
|
17
|
+
*
|
|
18
|
+
* @param pathOrUrl - Absolute path to a scenario.yaml file, or a URL
|
|
172
19
|
* @returns The parsed and validated scenario config
|
|
173
20
|
*/
|
|
174
|
-
declare function loadScenarioConfig(
|
|
21
|
+
declare function loadScenarioConfig(pathOrUrl: string): Promise<ScenarioConfig>;
|
|
175
22
|
/**
|
|
176
23
|
* Generate a system prompt string from a scenario's ai_rules.
|
|
177
24
|
*
|
|
@@ -198,7 +45,7 @@ interface ValidationResult {
|
|
|
198
45
|
* @param config - The scenario config to validate
|
|
199
46
|
* @returns Validation result with errors and warnings
|
|
200
47
|
*/
|
|
201
|
-
declare function validateScenario(config: ScenarioConfig):
|
|
48
|
+
declare function validateScenario(config: ScenarioConfig): ValidationResult;
|
|
202
49
|
/**
|
|
203
50
|
* Validate a scenario config and throw if invalid.
|
|
204
51
|
*
|
|
@@ -206,7 +53,7 @@ declare function validateScenario(config: ScenarioConfig): Promise<ValidationRes
|
|
|
206
53
|
* @returns Validation result (only returned if valid)
|
|
207
54
|
* @throws ScenarioValidationError if the config has errors
|
|
208
55
|
*/
|
|
209
|
-
declare function validateScenarioOrThrow(config: ScenarioConfig):
|
|
56
|
+
declare function validateScenarioOrThrow(config: ScenarioConfig): ValidationResult;
|
|
210
57
|
|
|
211
58
|
/**
|
|
212
59
|
* Discover built-in scenarios from the registry.yaml file in the scenarios package.
|
|
@@ -240,93 +87,6 @@ declare function discoverAllScenarios(): Promise<ScenarioInfo[]>;
|
|
|
240
87
|
*/
|
|
241
88
|
declare function importRepo(repoUrl: string, targetPath?: string, ref?: string): Promise<string>;
|
|
242
89
|
|
|
243
|
-
/** Event types that can be captured during a session */
|
|
244
|
-
type SessionEventType = 'stdout' | 'stderr' | 'command' | 'note';
|
|
245
|
-
/** A single timestamped event captured during a session */
|
|
246
|
-
interface SessionEvent {
|
|
247
|
-
/** Milliseconds since recording started */
|
|
248
|
-
timestamp: number;
|
|
249
|
-
/** The kind of event */
|
|
250
|
-
type: SessionEventType;
|
|
251
|
-
/** The captured data */
|
|
252
|
-
data: string;
|
|
253
|
-
}
|
|
254
|
-
/** Serialized recording format */
|
|
255
|
-
interface RecordingData {
|
|
256
|
-
/** Session ID this recording belongs to */
|
|
257
|
-
sessionId: string;
|
|
258
|
-
/** ISO string of when recording started */
|
|
259
|
-
startedAt: string;
|
|
260
|
-
/** All captured events */
|
|
261
|
-
events: SessionEvent[];
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Records timestamped events during an interview session.
|
|
265
|
-
*
|
|
266
|
-
* Captures stdout, stderr, commands, and notes with millisecond timestamps
|
|
267
|
-
* relative to when the recorder was created.
|
|
268
|
-
*/
|
|
269
|
-
declare class SessionRecorder {
|
|
270
|
-
private readonly events;
|
|
271
|
-
private readonly startTime;
|
|
272
|
-
private readonly startedAt;
|
|
273
|
-
constructor();
|
|
274
|
-
/** Record a timestamped event */
|
|
275
|
-
record(type: SessionEventType, data: string): void;
|
|
276
|
-
/** Get all recorded events */
|
|
277
|
-
getEvents(): ReadonlyArray<SessionEvent>;
|
|
278
|
-
/** Serialize the recording to a JSON-compatible object */
|
|
279
|
-
toJSON(sessionId: string): RecordingData;
|
|
280
|
-
/** Create a SessionRecorder pre-populated with events from serialized data */
|
|
281
|
-
static fromJSON(data: RecordingData): SessionRecorder;
|
|
282
|
-
/** Save the recording to disk */
|
|
283
|
-
save(sessionId: string): Promise<void>;
|
|
284
|
-
/** Load a recording from disk */
|
|
285
|
-
static load(sessionId: string): Promise<SessionRecorder>;
|
|
286
|
-
/** List all available recording session IDs */
|
|
287
|
-
static list(): Promise<string[]>;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/** Configuration for launching an AI coding tool */
|
|
291
|
-
interface LaunchConfig {
|
|
292
|
-
/** Scenario name for display */
|
|
293
|
-
scenarioName: string;
|
|
294
|
-
/** Path to system prompt file (hidden from candidate) */
|
|
295
|
-
systemPromptPath: string;
|
|
296
|
-
/** Model to use */
|
|
297
|
-
model?: string;
|
|
298
|
-
/** Permission mode for the AI tool */
|
|
299
|
-
permissionMode?: 'default' | 'plan' | 'acceptEdits' | 'bypassPermissions';
|
|
300
|
-
/** Tools to disallow (e.g., WebSearch for fairness) */
|
|
301
|
-
disallowedTools?: string[];
|
|
302
|
-
/** Whether to record stdout/stderr during the session */
|
|
303
|
-
recording?: boolean;
|
|
304
|
-
}
|
|
305
|
-
/** A running AI tool process */
|
|
306
|
-
interface LaunchedProcess {
|
|
307
|
-
/** Wait for the process to exit */
|
|
308
|
-
wait(): Promise<{
|
|
309
|
-
exitCode: number;
|
|
310
|
-
}>;
|
|
311
|
-
/** Kill the process */
|
|
312
|
-
kill(): Promise<void>;
|
|
313
|
-
/** Session recorder, present when recording is enabled */
|
|
314
|
-
recorder?: SessionRecorder;
|
|
315
|
-
}
|
|
316
|
-
/** Interface for AI coding tool launchers */
|
|
317
|
-
interface AIToolLauncher {
|
|
318
|
-
/** Internal name identifier */
|
|
319
|
-
readonly name: string;
|
|
320
|
-
/** Human-readable display name */
|
|
321
|
-
readonly displayName: string;
|
|
322
|
-
/** Check if this tool is installed and accessible */
|
|
323
|
-
isInstalled(): Promise<boolean>;
|
|
324
|
-
/** Get the installed version string */
|
|
325
|
-
getVersion(): Promise<string | null>;
|
|
326
|
-
/** Launch the tool pointed at a working directory */
|
|
327
|
-
launch(workdir: string, config: LaunchConfig): Promise<LaunchedProcess>;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
90
|
/** Launcher for Anthropic's Claude Code CLI */
|
|
331
91
|
declare class ClaudeCodeLauncher implements AIToolLauncher {
|
|
332
92
|
readonly name = "claude-code";
|
|
@@ -353,84 +113,6 @@ declare function getLauncher(name: string): AIToolLauncher | undefined;
|
|
|
353
113
|
/** Get all registered launchers */
|
|
354
114
|
declare function getAllLaunchers(): AIToolLauncher[];
|
|
355
115
|
|
|
356
|
-
/** Status of an interview session */
|
|
357
|
-
type SessionStatus = 'cloning' | 'setting-up' | 'running' | 'complete';
|
|
358
|
-
/** A live interview session */
|
|
359
|
-
interface Session {
|
|
360
|
-
/** Unique session identifier */
|
|
361
|
-
id: string;
|
|
362
|
-
/** Name of the scenario being run */
|
|
363
|
-
scenarioName: string;
|
|
364
|
-
/** Local working directory for the candidate */
|
|
365
|
-
workdir: string;
|
|
366
|
-
/** Path to the system prompt file (outside workspace) */
|
|
367
|
-
systemPromptPath: string;
|
|
368
|
-
/** Current session status */
|
|
369
|
-
status: SessionStatus;
|
|
370
|
-
/** ISO timestamp of session creation */
|
|
371
|
-
createdAt: string;
|
|
372
|
-
/** ISO timestamp of when the AI tool was launched */
|
|
373
|
-
startedAt?: string;
|
|
374
|
-
/** ISO timestamp of session completion */
|
|
375
|
-
completedAt?: string;
|
|
376
|
-
/** Name of the AI tool used */
|
|
377
|
-
aiTool?: string;
|
|
378
|
-
}
|
|
379
|
-
/** Serializable session data for persistence */
|
|
380
|
-
interface StoredSession {
|
|
381
|
-
/** Unique session identifier */
|
|
382
|
-
id: string;
|
|
383
|
-
/** Name of the scenario being run */
|
|
384
|
-
scenarioName: string;
|
|
385
|
-
/** Current session status */
|
|
386
|
-
status: SessionStatus;
|
|
387
|
-
/** Local working directory for the candidate */
|
|
388
|
-
workdir: string;
|
|
389
|
-
/** Path to the system prompt file */
|
|
390
|
-
systemPromptPath: string;
|
|
391
|
-
/** Name of the AI tool used */
|
|
392
|
-
aiTool?: string;
|
|
393
|
-
/** ISO timestamp of session creation */
|
|
394
|
-
createdAt: string;
|
|
395
|
-
/** ISO timestamp of when the AI tool was launched */
|
|
396
|
-
startedAt?: string;
|
|
397
|
-
/** ISO timestamp of session completion */
|
|
398
|
-
completedAt?: string;
|
|
399
|
-
}
|
|
400
|
-
/** Convert a Session to a StoredSession for persistence */
|
|
401
|
-
declare function toStoredSession(session: Session): StoredSession;
|
|
402
|
-
|
|
403
|
-
/** Callback for reporting session progress */
|
|
404
|
-
type ProgressCallback = (stage: string) => void;
|
|
405
|
-
/** Manages the lifecycle of an interview session */
|
|
406
|
-
declare class SessionManager {
|
|
407
|
-
private launcher;
|
|
408
|
-
constructor(launcher: AIToolLauncher);
|
|
409
|
-
/**
|
|
410
|
-
* Create a new interview session.
|
|
411
|
-
*
|
|
412
|
-
* Flow:
|
|
413
|
-
* 1. Clone the repo at a pinned commit
|
|
414
|
-
* 2. Apply bug patches (find/replace in source files)
|
|
415
|
-
* 3. Wipe git history so the candidate can't diff to find the bug
|
|
416
|
-
* 4. Remove scenario.yaml from workspace (interviewer-only)
|
|
417
|
-
* 5. Write BRIEFING.md and system prompt
|
|
418
|
-
* 6. Run setup commands (npm install, etc.)
|
|
419
|
-
*/
|
|
420
|
-
createSession(config: ScenarioConfig, workdir?: string, onProgress?: ProgressCallback): Promise<{
|
|
421
|
-
session: Session;
|
|
422
|
-
config: ScenarioConfig;
|
|
423
|
-
}>;
|
|
424
|
-
/** Launch the AI coding tool for an active session */
|
|
425
|
-
launchAITool(session: Session, _config: ScenarioConfig, launchConfig?: Partial<LaunchConfig>): Promise<{
|
|
426
|
-
exitCode: number;
|
|
427
|
-
}>;
|
|
428
|
-
/** Destroy a session by removing its stored data */
|
|
429
|
-
destroySession(session: Session): Promise<void>;
|
|
430
|
-
/** Get elapsed time since the AI tool was launched, formatted as a human-readable string */
|
|
431
|
-
getElapsedTime(session: Session): string | null;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
116
|
/** Save a session to disk */
|
|
435
117
|
declare function saveSession(session: StoredSession): Promise<void>;
|
|
436
118
|
/** Load a session from disk */
|
|
@@ -442,31 +124,4 @@ declare function listSessions(): Promise<StoredSession[]>;
|
|
|
442
124
|
/** List only active (non-complete) sessions */
|
|
443
125
|
declare function listActiveSessions(): Promise<StoredSession[]>;
|
|
444
126
|
|
|
445
|
-
|
|
446
|
-
declare class VibeError extends Error {
|
|
447
|
-
readonly code: string;
|
|
448
|
-
readonly hint?: string | undefined;
|
|
449
|
-
constructor(message: string, code: string, hint?: string | undefined);
|
|
450
|
-
}
|
|
451
|
-
declare class ScenarioNotFoundError extends VibeError {
|
|
452
|
-
constructor(name: string);
|
|
453
|
-
}
|
|
454
|
-
declare class ScenarioValidationError extends VibeError {
|
|
455
|
-
readonly issues: string[];
|
|
456
|
-
constructor(message: string, issues: string[]);
|
|
457
|
-
}
|
|
458
|
-
declare class AIToolNotFoundError extends VibeError {
|
|
459
|
-
static readonly installHints: Record<string, string>;
|
|
460
|
-
constructor(tool: string);
|
|
461
|
-
}
|
|
462
|
-
declare class SessionNotFoundError extends VibeError {
|
|
463
|
-
constructor(id: string);
|
|
464
|
-
}
|
|
465
|
-
declare class GitCloneError extends VibeError {
|
|
466
|
-
constructor(repo: string, reason?: string);
|
|
467
|
-
}
|
|
468
|
-
declare class SetupError extends VibeError {
|
|
469
|
-
constructor(command: string, reason?: string);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
export { type AIRules, type AIToolLauncher, AIToolNotFoundError, ClaudeCodeLauncher, type DetectedTool, type Evaluation, GitCloneError, type LaunchConfig, type LaunchedProcess, type ProgressCallback, type RecordingData, type ScenarioConfig, ScenarioConfigSchema, type ScenarioInfo, ScenarioNotFoundError, ScenarioValidationError, type Session, type SessionEvent, type SessionEventType, SessionManager, SessionNotFoundError, SessionRecorder, SetupError, type StoredSession, type ValidationResult, VibeError, deleteSession, detectInstalledTools, discoverAllScenarios, discoverBuiltInScenarios, generateSystemPrompt, getAllLaunchers, getLauncher, importRepo, listActiveSessions, listSessions, loadScenarioConfig, loadSession, saveSession, toStoredSession, validateScenario, validateScenarioOrThrow };
|
|
127
|
+
export { AIToolLauncher, ClaudeCodeLauncher, type DetectedTool, LaunchConfig, LaunchedProcess, ScenarioConfig, ScenarioInfo, StoredSession, type ValidationResult, deleteSession, detectInstalledTools, discoverAllScenarios, discoverBuiltInScenarios, generateSystemPrompt, getAllLaunchers, getLauncher, importRepo, isUrl, listActiveSessions, listSessions, loadScenarioConfig, loadSession, saveSession, validateScenario, validateScenarioOrThrow };
|