@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/dist/index.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AIToolNotFoundError,
|
|
3
|
+
GitCloneError,
|
|
4
|
+
InvalidSessionCodeError,
|
|
5
|
+
ScenarioFetchError,
|
|
6
|
+
ScenarioNotFoundError,
|
|
7
|
+
ScenarioValidationError,
|
|
8
|
+
SessionNotFoundError,
|
|
9
|
+
SetupError,
|
|
10
|
+
VibeError,
|
|
11
|
+
decodeSessionCode,
|
|
12
|
+
encodeSessionCode,
|
|
13
|
+
isCloudSessionCode
|
|
14
|
+
} from "./chunk-CI3BD2WQ.js";
|
|
15
|
+
|
|
1
16
|
// src/scenario/types.ts
|
|
2
17
|
import { z } from "zod";
|
|
3
18
|
var AIRulesSchema = z.object({
|
|
@@ -14,6 +29,24 @@ var EvaluationSchema = z.object({
|
|
|
14
29
|
/** Description of the expected fix */
|
|
15
30
|
expected_fix: z.string().optional()
|
|
16
31
|
});
|
|
32
|
+
var KeySignalSchema = z.object({
|
|
33
|
+
/** What behavior or skill this signal measures */
|
|
34
|
+
signal: z.string(),
|
|
35
|
+
/** What a strong candidate does (green flag) */
|
|
36
|
+
positive: z.string(),
|
|
37
|
+
/** What a weak candidate does (red flag) */
|
|
38
|
+
negative: z.string()
|
|
39
|
+
});
|
|
40
|
+
var InterviewerGuideSchema = z.object({
|
|
41
|
+
/** High-level summary of what this scenario evaluates and why */
|
|
42
|
+
overview: z.string(),
|
|
43
|
+
/** Specific behaviors to watch for, with green/red flag indicators */
|
|
44
|
+
key_signals: z.array(KeySignalSchema).default([]),
|
|
45
|
+
/** Common mistakes candidates make */
|
|
46
|
+
common_pitfalls: z.array(z.string()).default([]),
|
|
47
|
+
/** Questions to ask the candidate after the session */
|
|
48
|
+
debrief_questions: z.array(z.string()).default([])
|
|
49
|
+
});
|
|
17
50
|
var PatchSchema = z.object({
|
|
18
51
|
/** Path to the file relative to repo root */
|
|
19
52
|
file: z.string(),
|
|
@@ -22,11 +55,14 @@ var PatchSchema = z.object({
|
|
|
22
55
|
/** The replacement text (with the bug) */
|
|
23
56
|
replace: z.string()
|
|
24
57
|
});
|
|
58
|
+
var ScenarioTypeSchema = z.enum(["debug", "feature", "refactor"]).default("debug");
|
|
25
59
|
var ScenarioConfigSchema = z.object({
|
|
26
60
|
/** Scenario display name */
|
|
27
61
|
name: z.string(),
|
|
28
|
-
/** One-line description */
|
|
62
|
+
/** One-line description (candidate-visible — describe symptoms/task, never the root cause or solution) */
|
|
29
63
|
description: z.string(),
|
|
64
|
+
/** Scenario type: debug (find a bug), feature (build something), refactor (improve code) */
|
|
65
|
+
type: ScenarioTypeSchema,
|
|
30
66
|
/** Difficulty level */
|
|
31
67
|
difficulty: z.enum(["easy", "medium", "hard"]),
|
|
32
68
|
/** Estimated time (e.g., "30-45m") */
|
|
@@ -41,14 +77,20 @@ var ScenarioConfigSchema = z.object({
|
|
|
41
77
|
setup: z.array(z.string()).default([]),
|
|
42
78
|
/** Find-and-replace patches to inject the bug after cloning */
|
|
43
79
|
patch: z.array(PatchSchema).default([]),
|
|
80
|
+
/** Files or directories to delete after cloning (globs relative to repo root) */
|
|
81
|
+
delete_files: z.array(z.string()).default([]),
|
|
44
82
|
/** Briefing shown to the candidate (written like a team lead message) */
|
|
45
83
|
briefing: z.string(),
|
|
46
84
|
/** AI behavioral rules (injected via system prompt, hidden from candidate) */
|
|
47
85
|
ai_rules: AIRulesSchema,
|
|
48
|
-
/** Interviewer reference — what the fix looks like */
|
|
49
|
-
solution: z.string(),
|
|
86
|
+
/** Interviewer reference — what the fix/implementation looks like */
|
|
87
|
+
solution: z.string().optional(),
|
|
88
|
+
/** Acceptance criteria for feature scenarios (concrete, testable requirements) */
|
|
89
|
+
acceptance_criteria: z.array(z.string()).optional(),
|
|
50
90
|
/** Evaluation rubric */
|
|
51
91
|
evaluation: EvaluationSchema.optional(),
|
|
92
|
+
/** Structured interviewer guide — what to watch for, common pitfalls, debrief questions */
|
|
93
|
+
interviewer_guide: InterviewerGuideSchema.optional(),
|
|
52
94
|
/** License of the original project */
|
|
53
95
|
license: z.string().optional()
|
|
54
96
|
});
|
|
@@ -56,90 +98,76 @@ var ScenarioConfigSchema = z.object({
|
|
|
56
98
|
// src/scenario/loader.ts
|
|
57
99
|
import { readFile } from "fs/promises";
|
|
58
100
|
import { parse as parseYaml } from "yaml";
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
var ScenarioNotFoundError = class extends VibeError {
|
|
70
|
-
constructor(name) {
|
|
71
|
-
super(
|
|
72
|
-
`Scenario not found: ${name}`,
|
|
73
|
-
"SCENARIO_NOT_FOUND",
|
|
74
|
-
"Run `vibe-interviewing list` to see available scenarios"
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
var ScenarioValidationError = class extends VibeError {
|
|
79
|
-
constructor(message, issues) {
|
|
80
|
-
super(`Invalid scenario config: ${message}`, "SCENARIO_VALIDATION_ERROR", issues.join("\n"));
|
|
81
|
-
this.issues = issues;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
var AIToolNotFoundError = class _AIToolNotFoundError extends VibeError {
|
|
85
|
-
static installHints = {
|
|
86
|
-
"claude-code": "Install Claude Code: npm install -g @anthropic-ai/claude-code"
|
|
87
|
-
};
|
|
88
|
-
constructor(tool) {
|
|
89
|
-
super(
|
|
90
|
-
`${tool} is not installed`,
|
|
91
|
-
"AI_TOOL_NOT_FOUND",
|
|
92
|
-
_AIToolNotFoundError.installHints[tool] ?? `Install ${tool} and try again`
|
|
93
|
-
);
|
|
101
|
+
import { existsSync } from "fs";
|
|
102
|
+
var MAX_RESPONSE_BYTES = 1048576;
|
|
103
|
+
var FETCH_TIMEOUT_MS = 15e3;
|
|
104
|
+
function isUrl(input) {
|
|
105
|
+
return input.startsWith("http://") || input.startsWith("https://");
|
|
106
|
+
}
|
|
107
|
+
function toGitHubRawUrl(url) {
|
|
108
|
+
const match = url.match(/^https?:\/\/github\.com\/([^/]+\/[^/]+)\/blob\/(.+)$/);
|
|
109
|
+
if (match) {
|
|
110
|
+
return `https://raw.githubusercontent.com/${match[1]}/${match[2]}`;
|
|
94
111
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
112
|
+
return url;
|
|
113
|
+
}
|
|
114
|
+
async function fetchScenarioYaml(url) {
|
|
115
|
+
const rawUrl = toGitHubRawUrl(url);
|
|
116
|
+
let response;
|
|
117
|
+
try {
|
|
118
|
+
response = await fetch(rawUrl, {
|
|
119
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
120
|
+
headers: { Accept: "text/plain, application/x-yaml, */*" }
|
|
121
|
+
});
|
|
122
|
+
} catch (err) {
|
|
123
|
+
const message = err instanceof Error ? err.message : "unknown error";
|
|
124
|
+
throw new ScenarioFetchError(url, message);
|
|
103
125
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
constructor(repo, reason) {
|
|
107
|
-
super(
|
|
108
|
-
`Failed to clone repository: ${repo}${reason ? ` \u2014 ${reason}` : ""}`,
|
|
109
|
-
"GIT_CLONE_FAILED",
|
|
110
|
-
"Check the repo URL and your network connection"
|
|
111
|
-
);
|
|
126
|
+
if (!response.ok) {
|
|
127
|
+
throw new ScenarioFetchError(url, `HTTP ${response.status} ${response.statusText}`);
|
|
112
128
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
super(
|
|
117
|
-
`Setup command failed: ${command}${reason ? ` \u2014 ${reason}` : ""}`,
|
|
118
|
-
"SETUP_FAILED",
|
|
119
|
-
"Check the scenario setup commands and try again"
|
|
120
|
-
);
|
|
129
|
+
const contentLength = response.headers.get("content-length");
|
|
130
|
+
if (contentLength && parseInt(contentLength, 10) > MAX_RESPONSE_BYTES) {
|
|
131
|
+
throw new ScenarioFetchError(url, "response too large (>1 MB)");
|
|
121
132
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
import { existsSync } from "fs";
|
|
126
|
-
async function loadScenarioConfig(configPath) {
|
|
127
|
-
if (!existsSync(configPath)) {
|
|
128
|
-
throw new ScenarioNotFoundError(configPath);
|
|
133
|
+
const text = await response.text();
|
|
134
|
+
if (text.length > MAX_RESPONSE_BYTES) {
|
|
135
|
+
throw new ScenarioFetchError(url, "response too large (>1 MB)");
|
|
129
136
|
}
|
|
130
|
-
|
|
137
|
+
return text;
|
|
138
|
+
}
|
|
139
|
+
function parseScenarioYaml(raw, source) {
|
|
131
140
|
const parsed = parseYaml(raw);
|
|
132
141
|
const result = ScenarioConfigSchema.safeParse(parsed);
|
|
133
142
|
if (!result.success) {
|
|
134
143
|
const issues = result.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`);
|
|
135
|
-
throw new ScenarioValidationError(
|
|
144
|
+
throw new ScenarioValidationError(`validation failed (${source})`, issues);
|
|
136
145
|
}
|
|
137
146
|
return result.data;
|
|
138
147
|
}
|
|
148
|
+
async function loadScenarioConfig(pathOrUrl) {
|
|
149
|
+
if (isUrl(pathOrUrl)) {
|
|
150
|
+
const raw2 = await fetchScenarioYaml(pathOrUrl);
|
|
151
|
+
return parseScenarioYaml(raw2, pathOrUrl);
|
|
152
|
+
}
|
|
153
|
+
if (!existsSync(pathOrUrl)) {
|
|
154
|
+
throw new ScenarioNotFoundError(pathOrUrl);
|
|
155
|
+
}
|
|
156
|
+
const raw = await readFile(pathOrUrl, "utf-8");
|
|
157
|
+
return parseScenarioYaml(raw, pathOrUrl);
|
|
158
|
+
}
|
|
139
159
|
function generateSystemPrompt(config) {
|
|
140
160
|
const lines = [];
|
|
141
161
|
lines.push(`# Interview Scenario: ${config.name}`);
|
|
142
162
|
lines.push("");
|
|
163
|
+
const typeDescriptions = {
|
|
164
|
+
debug: "The candidate is debugging a bug in this codebase. Guide them through the debugging process without revealing the answer.",
|
|
165
|
+
feature: "The candidate is building a new feature. Help them understand the requirements, plan their approach, and implement it. Offer architectural guidance but let them drive the implementation.",
|
|
166
|
+
refactor: "The candidate is improving existing code. Help them identify issues and plan improvements. Encourage them to explain their reasoning for changes."
|
|
167
|
+
};
|
|
168
|
+
lines.push("## Scenario Type");
|
|
169
|
+
lines.push(typeDescriptions[config.type] ?? typeDescriptions["debug"]);
|
|
170
|
+
lines.push("");
|
|
143
171
|
lines.push("## Your Role");
|
|
144
172
|
lines.push(config.ai_rules.role.trim());
|
|
145
173
|
lines.push("");
|
|
@@ -148,13 +176,18 @@ function generateSystemPrompt(config) {
|
|
|
148
176
|
lines.push(`- ${rule}`);
|
|
149
177
|
}
|
|
150
178
|
lines.push("");
|
|
151
|
-
|
|
179
|
+
const knowledgeHeaders = {
|
|
180
|
+
debug: "Knowledge (DO NOT share directly with the candidate)",
|
|
181
|
+
feature: "Implementation Context (DO NOT share directly with the candidate)",
|
|
182
|
+
refactor: "Improvement Context (DO NOT share directly with the candidate)"
|
|
183
|
+
};
|
|
184
|
+
lines.push(`## ${knowledgeHeaders[config.type] ?? knowledgeHeaders["debug"]}`);
|
|
152
185
|
lines.push(config.ai_rules.knowledge.trim());
|
|
153
186
|
return lines.join("\n");
|
|
154
187
|
}
|
|
155
188
|
|
|
156
189
|
// src/scenario/validator.ts
|
|
157
|
-
|
|
190
|
+
function validateScenario(config) {
|
|
158
191
|
const warnings = [];
|
|
159
192
|
const errors = [];
|
|
160
193
|
if (!config.briefing.trim()) {
|
|
@@ -168,24 +201,46 @@ async function validateScenario(config) {
|
|
|
168
201
|
}
|
|
169
202
|
if (!config.commit.trim()) {
|
|
170
203
|
errors.push("commit cannot be empty \u2014 pin to a specific commit SHA for reproducibility");
|
|
204
|
+
} else if (!/^[0-9a-f]{7,40}$/i.test(config.commit.trim())) {
|
|
205
|
+
errors.push(
|
|
206
|
+
"commit must be a hex SHA (7-40 characters) \u2014 branch/tag names are not allowed for reproducibility"
|
|
207
|
+
);
|
|
171
208
|
}
|
|
172
209
|
if (config.ai_rules.rules.length === 0) {
|
|
173
210
|
warnings.push("ai_rules.rules is empty \u2014 the AI will have no behavioral constraints");
|
|
174
211
|
}
|
|
175
|
-
if (
|
|
176
|
-
|
|
212
|
+
if (config.type === "debug") {
|
|
213
|
+
if (config.patch.length === 0) {
|
|
214
|
+
warnings.push("debug scenario has no patches \u2014 a bug must be injected via patch");
|
|
215
|
+
}
|
|
216
|
+
if (!config.solution?.trim()) {
|
|
217
|
+
warnings.push("solution is empty \u2014 interviewers will have no solution reference");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (config.type === "feature") {
|
|
221
|
+
const hasCriteria = config.acceptance_criteria && config.acceptance_criteria.length > 0 || config.evaluation && config.evaluation.criteria && config.evaluation.criteria.length > 0;
|
|
222
|
+
if (!hasCriteria) {
|
|
223
|
+
warnings.push(
|
|
224
|
+
"feature scenario has no acceptance_criteria or evaluation.criteria \u2014 candidates need a definition of done"
|
|
225
|
+
);
|
|
226
|
+
}
|
|
177
227
|
}
|
|
178
228
|
if (!config.evaluation) {
|
|
179
229
|
warnings.push("No evaluation criteria defined");
|
|
180
230
|
}
|
|
231
|
+
if (!config.interviewer_guide) {
|
|
232
|
+
warnings.push(
|
|
233
|
+
"No interviewer_guide defined \u2014 interviewers will have limited context during the session"
|
|
234
|
+
);
|
|
235
|
+
}
|
|
181
236
|
return {
|
|
182
237
|
valid: errors.length === 0,
|
|
183
238
|
warnings,
|
|
184
239
|
errors
|
|
185
240
|
};
|
|
186
241
|
}
|
|
187
|
-
|
|
188
|
-
const result =
|
|
242
|
+
function validateScenarioOrThrow(config) {
|
|
243
|
+
const result = validateScenario(config);
|
|
189
244
|
if (!result.valid) {
|
|
190
245
|
throw new ScenarioValidationError("scenario validation failed", result.errors);
|
|
191
246
|
}
|
|
@@ -230,6 +285,10 @@ async function discoverBuiltInScenarios() {
|
|
|
230
285
|
config,
|
|
231
286
|
builtIn: true
|
|
232
287
|
});
|
|
288
|
+
} else {
|
|
289
|
+
console.warn(
|
|
290
|
+
`Warning: scenario "${entry.name}" listed in registry but ${scenarioConfigPath} not found`
|
|
291
|
+
);
|
|
233
292
|
}
|
|
234
293
|
}
|
|
235
294
|
return scenarios;
|
|
@@ -326,6 +385,9 @@ var SessionRecorder = class _SessionRecorder {
|
|
|
326
385
|
static fromJSON(data) {
|
|
327
386
|
const recorder = new _SessionRecorder();
|
|
328
387
|
Object.defineProperty(recorder, "startedAt", { value: data.startedAt });
|
|
388
|
+
Object.defineProperty(recorder, "startTime", {
|
|
389
|
+
value: new Date(data.startedAt).getTime()
|
|
390
|
+
});
|
|
329
391
|
for (const event of data.events) {
|
|
330
392
|
recorder.events.push({ ...event });
|
|
331
393
|
}
|
|
@@ -496,17 +558,7 @@ async function listActiveSessions() {
|
|
|
496
558
|
|
|
497
559
|
// src/session/types.ts
|
|
498
560
|
function toStoredSession(session) {
|
|
499
|
-
return {
|
|
500
|
-
id: session.id,
|
|
501
|
-
scenarioName: session.scenarioName,
|
|
502
|
-
status: session.status,
|
|
503
|
-
workdir: session.workdir,
|
|
504
|
-
systemPromptPath: session.systemPromptPath,
|
|
505
|
-
aiTool: session.aiTool,
|
|
506
|
-
createdAt: session.createdAt,
|
|
507
|
-
startedAt: session.startedAt,
|
|
508
|
-
completedAt: session.completedAt
|
|
509
|
-
};
|
|
561
|
+
return { ...session };
|
|
510
562
|
}
|
|
511
563
|
|
|
512
564
|
// src/session/manager.ts
|
|
@@ -520,12 +572,13 @@ var SessionManager = class {
|
|
|
520
572
|
* Flow:
|
|
521
573
|
* 1. Clone the repo at a pinned commit
|
|
522
574
|
* 2. Apply bug patches (find/replace in source files)
|
|
523
|
-
* 3.
|
|
524
|
-
* 4.
|
|
525
|
-
* 5.
|
|
526
|
-
* 6.
|
|
575
|
+
* 3. Delete files excluded by the scenario (e.g., tests that reveal the bug)
|
|
576
|
+
* 4. Wipe git history so the candidate can't diff to find the bug
|
|
577
|
+
* 5. Remove scenario.yaml from workspace (interviewer-only)
|
|
578
|
+
* 6. Write BRIEFING.md and system prompt
|
|
579
|
+
* 7. Run setup commands (npm install, etc.)
|
|
527
580
|
*/
|
|
528
|
-
async createSession(config, workdir, onProgress) {
|
|
581
|
+
async createSession(config, workdir, onProgress, options) {
|
|
529
582
|
const id = randomBytes(4).toString("hex");
|
|
530
583
|
const sessionDir = workdir ?? join5(homedir3(), "vibe-sessions", `${config.name}-${id}`);
|
|
531
584
|
const session = {
|
|
@@ -542,7 +595,7 @@ var SessionManager = class {
|
|
|
542
595
|
for (const p of config.patch) {
|
|
543
596
|
const filePath = join5(sessionDir, p.file);
|
|
544
597
|
const content = await readFile6(filePath, "utf-8");
|
|
545
|
-
const patched = content.
|
|
598
|
+
const patched = content.replaceAll(p.find, p.replace);
|
|
546
599
|
if (patched === content) {
|
|
547
600
|
throw new SetupError(
|
|
548
601
|
`patch ${p.file}`,
|
|
@@ -551,12 +604,18 @@ var SessionManager = class {
|
|
|
551
604
|
}
|
|
552
605
|
await writeFile3(filePath, patched);
|
|
553
606
|
}
|
|
607
|
+
if (config.delete_files.length > 0) {
|
|
608
|
+
onProgress?.("Removing excluded files...");
|
|
609
|
+
for (const target of config.delete_files) {
|
|
610
|
+
await rm(join5(sessionDir, target), { recursive: true, force: true });
|
|
611
|
+
}
|
|
612
|
+
}
|
|
554
613
|
onProgress?.("Preparing workspace...");
|
|
555
614
|
await rm(join5(sessionDir, ".git"), { recursive: true, force: true });
|
|
556
|
-
execSync(
|
|
557
|
-
|
|
558
|
-
stdio: "ignore"
|
|
559
|
-
|
|
615
|
+
execSync(
|
|
616
|
+
'git init && git add -A && git -c user.name=vibe -c user.email=vibe@local commit -m "initial"',
|
|
617
|
+
{ cwd: sessionDir, stdio: "ignore" }
|
|
618
|
+
);
|
|
560
619
|
await rm(join5(sessionDir, "scenario.yaml"), { force: true });
|
|
561
620
|
await writeFile3(join5(sessionDir, "BRIEFING.md"), `# Interview Briefing
|
|
562
621
|
|
|
@@ -566,13 +625,15 @@ ${config.briefing}`);
|
|
|
566
625
|
const systemPromptPath = join5(promptDir, `${id}.md`);
|
|
567
626
|
await writeFile3(systemPromptPath, generateSystemPrompt(config));
|
|
568
627
|
session.systemPromptPath = systemPromptPath;
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
628
|
+
if (!options?.skipSetup) {
|
|
629
|
+
session.status = "setting-up";
|
|
630
|
+
for (const cmd of config.setup) {
|
|
631
|
+
onProgress?.(`Running: ${cmd}`);
|
|
632
|
+
try {
|
|
633
|
+
execSync(cmd, { cwd: sessionDir, stdio: "pipe", timeout: 3e5 });
|
|
634
|
+
} catch (err) {
|
|
635
|
+
throw new SetupError(cmd, err instanceof Error ? err.message : String(err));
|
|
636
|
+
}
|
|
576
637
|
}
|
|
577
638
|
}
|
|
578
639
|
session.status = "running";
|
|
@@ -614,7 +675,9 @@ export {
|
|
|
614
675
|
AIToolNotFoundError,
|
|
615
676
|
ClaudeCodeLauncher,
|
|
616
677
|
GitCloneError,
|
|
678
|
+
InvalidSessionCodeError,
|
|
617
679
|
ScenarioConfigSchema,
|
|
680
|
+
ScenarioFetchError,
|
|
618
681
|
ScenarioNotFoundError,
|
|
619
682
|
ScenarioValidationError,
|
|
620
683
|
SessionManager,
|
|
@@ -622,14 +685,18 @@ export {
|
|
|
622
685
|
SessionRecorder,
|
|
623
686
|
SetupError,
|
|
624
687
|
VibeError,
|
|
688
|
+
decodeSessionCode,
|
|
625
689
|
deleteSession,
|
|
626
690
|
detectInstalledTools,
|
|
627
691
|
discoverAllScenarios,
|
|
628
692
|
discoverBuiltInScenarios,
|
|
693
|
+
encodeSessionCode,
|
|
629
694
|
generateSystemPrompt,
|
|
630
695
|
getAllLaunchers,
|
|
631
696
|
getLauncher,
|
|
632
697
|
importRepo,
|
|
698
|
+
isCloudSessionCode,
|
|
699
|
+
isUrl,
|
|
633
700
|
listActiveSessions,
|
|
634
701
|
listSessions,
|
|
635
702
|
loadScenarioConfig,
|