@viberaven/cli 1.1.3 → 1.1.4
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/AGENTS.md +2 -2
- package/README.md +1 -1
- package/SECURITY.md +1 -1
- package/dist/cli.js +343 -334
- package/dist/cli.js.map +4 -4
- package/package.json +2 -2
- package/templates/AGENTS.snippet.md +1 -1
- package/templates/CLAUDE.snippet.md +1 -1
- package/templates/CURSOR.snippet.md +1 -1
package/dist/cli.js
CHANGED
|
@@ -5342,7 +5342,7 @@ ${scan.files.map((file) => file.path).join("\n")}`.replace(/\\/g, "/").toLowerCa
|
|
|
5342
5342
|
];
|
|
5343
5343
|
const passedCount = items.filter((entry) => entry.status === "passed").length;
|
|
5344
5344
|
const totalCount = items.length;
|
|
5345
|
-
const
|
|
5345
|
+
const readinessPercent = Math.round(passedCount / Math.max(totalCount, 1) * 100);
|
|
5346
5346
|
return {
|
|
5347
5347
|
key: "supabase-database",
|
|
5348
5348
|
provider: "supabase",
|
|
@@ -5353,7 +5353,7 @@ ${scan.files.map((file) => file.path).join("\n")}`.replace(/\\/g, "/").toLowerCa
|
|
|
5353
5353
|
items,
|
|
5354
5354
|
passedCount,
|
|
5355
5355
|
totalCount,
|
|
5356
|
-
readinessPercent
|
|
5356
|
+
readinessPercent
|
|
5357
5357
|
};
|
|
5358
5358
|
}
|
|
5359
5359
|
function visibleFiles2(scan) {
|
|
@@ -8493,7 +8493,7 @@ function needsScanMessage(startDir) {
|
|
|
8493
8493
|
return [
|
|
8494
8494
|
"No CLI scan found for this folder.",
|
|
8495
8495
|
`Looking from: ${cwd}`,
|
|
8496
|
-
'Choose "
|
|
8496
|
+
'Choose "Make this app production ready", or run the menu from your repo root (where .viberaven/ lives).',
|
|
8497
8497
|
"VS Code extension scans stay inside the editor \u2014 run a CLI scan once to create .viberaven/ on disk."
|
|
8498
8498
|
].join("\n");
|
|
8499
8499
|
}
|
|
@@ -11454,7 +11454,7 @@ function buildAgentFixPrompt(artifact, gap2) {
|
|
|
11454
11454
|
}
|
|
11455
11455
|
|
|
11456
11456
|
// src/version.ts
|
|
11457
|
-
var VERSION = "1.1.
|
|
11457
|
+
var VERSION = "1.1.4";
|
|
11458
11458
|
|
|
11459
11459
|
// src/commands/guide.ts
|
|
11460
11460
|
var import_picocolors3 = __toESM(require_picocolors());
|
|
@@ -11770,7 +11770,7 @@ ${AGENT_NEGATIVE_CONSTRAINTS}
|
|
|
11770
11770
|
## VibeRaven Production-Readiness Gate
|
|
11771
11771
|
|
|
11772
11772
|
- Before running build, compile, cleanup, deployment, vercel, or supabase commands, run \`${PUBLIC_AGENT_MODE_COMMAND}\` first from the project root.
|
|
11773
|
-
- Treat VibeRaven as the
|
|
11773
|
+
- Treat VibeRaven as the agent production layer for AI-built apps, especially apps using Vercel, Supabase, auth, database, payments, webhooks, monitoring, rate limits, or environment variables.
|
|
11774
11774
|
- Read \`.viberaven/agent-tasklist.md\` first. If it says CRITICAL GAPS DETECTED or PRODUCTION GATE NOT CLEAR, fix one listed repo-code gap before deploying.
|
|
11775
11775
|
- Read \`.viberaven/gate-result.json\` for the machine verdict.
|
|
11776
11776
|
- Read \`.viberaven/context-map.json\` for compact agent context.
|
|
@@ -12291,6 +12291,37 @@ function formatAgentRulesInitSummary(output) {
|
|
|
12291
12291
|
);
|
|
12292
12292
|
return lines.join("\n");
|
|
12293
12293
|
}
|
|
12294
|
+
async function maybeAutoInstallAgentRules(options) {
|
|
12295
|
+
const existing = await Promise.all([
|
|
12296
|
+
fileExists2((0, import_node_path13.join)(options.cwd, AGENT_RULE_TARGETS.codex.file)),
|
|
12297
|
+
fileExists2((0, import_node_path13.join)(options.cwd, AGENT_RULE_TARGETS.claude.file)),
|
|
12298
|
+
fileExists2((0, import_node_path13.join)(options.cwd, AGENT_RULE_TARGETS.cursor.file))
|
|
12299
|
+
]);
|
|
12300
|
+
if (existing.some(Boolean)) {
|
|
12301
|
+
return { status: "ready" };
|
|
12302
|
+
}
|
|
12303
|
+
try {
|
|
12304
|
+
const output = await initAgentRules({
|
|
12305
|
+
cwd: options.cwd,
|
|
12306
|
+
targets: ["codex", "claude", "cursor", "agentContext", "missionMap"]
|
|
12307
|
+
});
|
|
12308
|
+
return { status: "installed", output };
|
|
12309
|
+
} catch (error) {
|
|
12310
|
+
return { status: "skipped", reason: error instanceof Error ? error.message : String(error) };
|
|
12311
|
+
}
|
|
12312
|
+
}
|
|
12313
|
+
function formatAgentRulesBootstrapSummary(result) {
|
|
12314
|
+
if (result.status === "ready") {
|
|
12315
|
+
return "Agent setup: Codex/Claude/Cursor instructions already connected.";
|
|
12316
|
+
}
|
|
12317
|
+
if (result.status === "skipped") {
|
|
12318
|
+
return `Agent setup: skipped (${result.reason})`;
|
|
12319
|
+
}
|
|
12320
|
+
const created = result.output.results.filter((item3) => item3.action === "created").map((item3) => item3.file);
|
|
12321
|
+
const updated = result.output.results.filter((item3) => item3.action === "updated").map((item3) => item3.file);
|
|
12322
|
+
const changed = [...created, ...updated];
|
|
12323
|
+
return changed.length > 0 ? `Agent setup: connected ${changed.join(", ")}.` : "Agent setup: Codex/Claude/Cursor instructions already connected.";
|
|
12324
|
+
}
|
|
12294
12325
|
async function readExistingFile2(path3) {
|
|
12295
12326
|
try {
|
|
12296
12327
|
return { exists: true, content: await (0, import_promises10.readFile)(path3, "utf-8") };
|
|
@@ -12301,6 +12332,14 @@ async function readExistingFile2(path3) {
|
|
|
12301
12332
|
throw error;
|
|
12302
12333
|
}
|
|
12303
12334
|
}
|
|
12335
|
+
async function fileExists2(path3) {
|
|
12336
|
+
try {
|
|
12337
|
+
await (0, import_promises10.access)(path3);
|
|
12338
|
+
return true;
|
|
12339
|
+
} catch {
|
|
12340
|
+
return false;
|
|
12341
|
+
}
|
|
12342
|
+
}
|
|
12304
12343
|
function isFileNotFoundError2(error) {
|
|
12305
12344
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
12306
12345
|
}
|
|
@@ -12580,19 +12619,15 @@ async function handleOpenDashboard(cwd) {
|
|
|
12580
12619
|
}
|
|
12581
12620
|
function buildMenuOptions(isSignedIn) {
|
|
12582
12621
|
return [
|
|
12583
|
-
{ value: "
|
|
12584
|
-
{ value: "
|
|
12585
|
-
{ value: "open-
|
|
12586
|
-
{ value: "guide", label: "Provider guide", hint: "
|
|
12587
|
-
{ value: "
|
|
12588
|
-
{ value: "gaps", label: "View top gaps", hint: "From last scan" },
|
|
12589
|
-
{ value: "prompt", label: "Copy top prompt", hint: "Agent-ready fix prompt" },
|
|
12590
|
-
{ value: "agent-rules", label: "Install agent rules", hint: "AGENTS.md, CLAUDE.md, Cursor" },
|
|
12591
|
-
{ value: "audit", label: "Vercel/Supabase audit", hint: "RLS, service-role, serverless pooler evidence" },
|
|
12622
|
+
{ value: "scan", label: "Make this app production ready", hint: "Scan, write tasks, start the next fix" },
|
|
12623
|
+
{ value: "next", label: "Continue next step", hint: "One action from the last run" },
|
|
12624
|
+
{ value: "open-dashboard", label: "Open provider step", hint: "Supabase, Stripe, Vercel, auth" },
|
|
12625
|
+
{ value: "guide", label: "Provider setup guide", hint: "Simple dashboard steps" },
|
|
12626
|
+
{ value: "agent-rules", label: "Connect this AI agent", hint: "Codex, Claude, Cursor rules" },
|
|
12592
12627
|
{
|
|
12593
12628
|
value: "auth",
|
|
12594
12629
|
label: isSignedIn ? "Sign out" : "Sign in",
|
|
12595
|
-
hint: isSignedIn ? "Clear local credentials" : "
|
|
12630
|
+
hint: isSignedIn ? "Clear local credentials" : "Use the managed VibeRaven scan"
|
|
12596
12631
|
},
|
|
12597
12632
|
{ value: "exit", label: "Exit" }
|
|
12598
12633
|
];
|
|
@@ -12608,7 +12643,7 @@ async function runInteractiveSession(startDir = process.cwd()) {
|
|
|
12608
12643
|
if (!artifactsAt) {
|
|
12609
12644
|
M2.message(
|
|
12610
12645
|
import_picocolors4.default.dim(
|
|
12611
|
-
|
|
12646
|
+
'No .viberaven/ here yet. Choose "Make this app production ready" to start.'
|
|
12612
12647
|
)
|
|
12613
12648
|
);
|
|
12614
12649
|
}
|
|
@@ -13851,7 +13886,7 @@ var STALE_PATTERNS = [
|
|
|
13851
13886
|
async function checkAgentInjection(cwd) {
|
|
13852
13887
|
const checks = [];
|
|
13853
13888
|
for (const item3 of REQUIRED_EXISTENCE_CHECKS) {
|
|
13854
|
-
const exists = await
|
|
13889
|
+
const exists = await fileExists3((0, import_node_path23.join)(cwd, item3.file));
|
|
13855
13890
|
checks.push({
|
|
13856
13891
|
id: item3.id,
|
|
13857
13892
|
status: exists ? "pass" : "fail",
|
|
@@ -13859,7 +13894,7 @@ async function checkAgentInjection(cwd) {
|
|
|
13859
13894
|
});
|
|
13860
13895
|
}
|
|
13861
13896
|
for (const item3 of OPTIONAL_CURSOR_PACK_CHECKS) {
|
|
13862
|
-
const exists = await
|
|
13897
|
+
const exists = await fileExists3((0, import_node_path23.join)(cwd, item3.file));
|
|
13863
13898
|
checks.push({
|
|
13864
13899
|
id: item3.id,
|
|
13865
13900
|
status: exists ? "pass" : "fail",
|
|
@@ -13867,9 +13902,9 @@ async function checkAgentInjection(cwd) {
|
|
|
13867
13902
|
});
|
|
13868
13903
|
}
|
|
13869
13904
|
const legacyCursorPath = (0, import_node_path23.join)(cwd, ".cursor/rules/viberaven.mdc");
|
|
13870
|
-
if (await
|
|
13905
|
+
if (await fileExists3(legacyCursorPath)) {
|
|
13871
13906
|
const legacyContent = await (0, import_promises18.readFile)(legacyCursorPath, "utf-8");
|
|
13872
|
-
const hasCoreSplit = await
|
|
13907
|
+
const hasCoreSplit = await fileExists3((0, import_node_path23.join)(cwd, ".cursor/rules/viberaven-core.mdc"));
|
|
13873
13908
|
if (!hasCoreSplit || legacyContent.includes("alwaysApply: true")) {
|
|
13874
13909
|
checks.push({
|
|
13875
13910
|
id: "cursor-legacy-mdc",
|
|
@@ -13881,7 +13916,7 @@ async function checkAgentInjection(cwd) {
|
|
|
13881
13916
|
for (const target of CORE_AGENT_INJECTION_TARGETS) {
|
|
13882
13917
|
const file = target === "cursor" ? ".cursor/rules/viberaven-core.mdc" : AGENT_RULE_TARGETS[target].file;
|
|
13883
13918
|
const path3 = (0, import_node_path23.join)(cwd, file);
|
|
13884
|
-
const exists = await
|
|
13919
|
+
const exists = await fileExists3(path3);
|
|
13885
13920
|
if (!exists) {
|
|
13886
13921
|
checks.push({
|
|
13887
13922
|
id: `canonical-${target}`,
|
|
@@ -13922,7 +13957,7 @@ function formatDoctorAgentsReport(report) {
|
|
|
13922
13957
|
lines.push(report.ok ? "All agent injection checks passed." : "Agent injection checks failed.");
|
|
13923
13958
|
return lines.join("\n");
|
|
13924
13959
|
}
|
|
13925
|
-
async function
|
|
13960
|
+
async function fileExists3(path3) {
|
|
13926
13961
|
try {
|
|
13927
13962
|
await (0, import_promises18.access)(path3);
|
|
13928
13963
|
return true;
|
|
@@ -14249,9 +14284,6 @@ function banner(decision, options) {
|
|
|
14249
14284
|
const style = decisionStyle(decision, options.mode);
|
|
14250
14285
|
return `${style.glyph} ${style.label}`;
|
|
14251
14286
|
}
|
|
14252
|
-
function kv(key, value, options) {
|
|
14253
|
-
return `${accent.dim(key, options.mode)}: ${value}`;
|
|
14254
|
-
}
|
|
14255
14287
|
|
|
14256
14288
|
// src/brand/wordmark.ts
|
|
14257
14289
|
var DEFAULT_TAGLINE = "production operator for AI-built apps";
|
|
@@ -14468,247 +14500,6 @@ function printNextActionBlock(block) {
|
|
|
14468
14500
|
console.log(NEXT_ACTION_END);
|
|
14469
14501
|
}
|
|
14470
14502
|
|
|
14471
|
-
// src/output/actionPanelBlock.ts
|
|
14472
|
-
var ACTION_PANEL_START = "VIBERAVEN_ACTION_PANEL_START";
|
|
14473
|
-
var ACTION_PANEL_END = "VIBERAVEN_ACTION_PANEL_END";
|
|
14474
|
-
function buildActionPanelBlock(reportPath) {
|
|
14475
|
-
return {
|
|
14476
|
-
VIBERAVEN_ACTION_PANEL: {
|
|
14477
|
-
surface: "local-report",
|
|
14478
|
-
title: "Visual action panel",
|
|
14479
|
-
reportPath,
|
|
14480
|
-
openCommand: "npx -y viberaven report --open",
|
|
14481
|
-
nextCommand: "npx -y viberaven next --json",
|
|
14482
|
-
agentInstruction: "Use the native chat for reasoning. Open this local report only when the user needs buttons, provider links, copy actions, or visual progress."
|
|
14483
|
-
}
|
|
14484
|
-
};
|
|
14485
|
-
}
|
|
14486
|
-
function printActionPanelBlock(reportPath) {
|
|
14487
|
-
const block = buildActionPanelBlock(reportPath);
|
|
14488
|
-
console.log(ACTION_PANEL_START);
|
|
14489
|
-
console.log(JSON.stringify(block, null, 2));
|
|
14490
|
-
console.log(ACTION_PANEL_END);
|
|
14491
|
-
}
|
|
14492
|
-
|
|
14493
|
-
// src/output/operatorBlock.ts
|
|
14494
|
-
var OPERATOR_START = "VIBERAVEN_OPERATOR_START";
|
|
14495
|
-
var OPERATOR_END = "VIBERAVEN_OPERATOR_END";
|
|
14496
|
-
function stackLine(prp) {
|
|
14497
|
-
const parts = Array.from(
|
|
14498
|
-
/* @__PURE__ */ new Set([
|
|
14499
|
-
...prp.detectedStack.deployment,
|
|
14500
|
-
...prp.detectedStack.database,
|
|
14501
|
-
...prp.detectedStack.auth,
|
|
14502
|
-
...prp.detectedStack.payments,
|
|
14503
|
-
...prp.detectedStack.monitoring
|
|
14504
|
-
])
|
|
14505
|
-
);
|
|
14506
|
-
if (parts.length > 0) {
|
|
14507
|
-
return parts.join(" + ");
|
|
14508
|
-
}
|
|
14509
|
-
return prp.detectedStack.archetype ?? "unknown";
|
|
14510
|
-
}
|
|
14511
|
-
function uniqueEnvNames(tasks) {
|
|
14512
|
-
return Array.from(
|
|
14513
|
-
new Set(
|
|
14514
|
-
tasks.map((task) => task.providerAction?.envKeyName).filter((name) => Boolean(name))
|
|
14515
|
-
)
|
|
14516
|
-
);
|
|
14517
|
-
}
|
|
14518
|
-
function humanTaskText(task) {
|
|
14519
|
-
if (task.fixType === "provider-action") {
|
|
14520
|
-
return task.providerAction?.exactStep ?? task.title;
|
|
14521
|
-
}
|
|
14522
|
-
if (task.fixType === "upgrade-required") {
|
|
14523
|
-
return `Upgrade required: ${task.action ?? task.exactFix ?? task.title}`;
|
|
14524
|
-
}
|
|
14525
|
-
if (task.fixType === "manual-verify") {
|
|
14526
|
-
return `Manual verification required: ${task.action ?? task.exactFix ?? task.title}`;
|
|
14527
|
-
}
|
|
14528
|
-
return task.title;
|
|
14529
|
-
}
|
|
14530
|
-
function riskSuffixFor(task, prp) {
|
|
14531
|
-
const topRisk = prp.findings.find((finding) => finding.id === task.gapId)?.riskMapping?.owaspLlm?.[0];
|
|
14532
|
-
return topRisk ? ` (risk: ${topRisk})` : "";
|
|
14533
|
-
}
|
|
14534
|
-
function readinessPercent(prp) {
|
|
14535
|
-
if (prp.decision === "CLEAR") return 100;
|
|
14536
|
-
if (prp.decision === "WARNING") return 65;
|
|
14537
|
-
return 25;
|
|
14538
|
-
}
|
|
14539
|
-
function buildPlainOperatorBlock(prp, tasks) {
|
|
14540
|
-
const repoTasks = tasks.filter((task) => task.fixType === "repo-code");
|
|
14541
|
-
const humanTasks = tasks.filter((task) => task.fixType !== "repo-code");
|
|
14542
|
-
const providerTasks = tasks.filter((task) => task.fixType === "provider-action");
|
|
14543
|
-
const nextRepoTask = repoTasks[0];
|
|
14544
|
-
const envNames = uniqueEnvNames(providerTasks);
|
|
14545
|
-
const lines = [];
|
|
14546
|
-
lines.push(`Decision: ${prp.decision}`);
|
|
14547
|
-
lines.push(`Detected stack: ${stackLine(prp)}`);
|
|
14548
|
-
lines.push("");
|
|
14549
|
-
lines.push("What I can fix:");
|
|
14550
|
-
if (repoTasks.length === 0) {
|
|
14551
|
-
lines.push(" (none - no automated repo-code recipes apply)");
|
|
14552
|
-
} else {
|
|
14553
|
-
repoTasks.forEach((task, index) => {
|
|
14554
|
-
lines.push(` ${index + 1}. ${task.title}${riskSuffixFor(task, prp)}`);
|
|
14555
|
-
});
|
|
14556
|
-
}
|
|
14557
|
-
lines.push("");
|
|
14558
|
-
lines.push("What you must do:");
|
|
14559
|
-
if (humanTasks.length === 0) {
|
|
14560
|
-
lines.push(" (none - no human-owned steps required)");
|
|
14561
|
-
} else {
|
|
14562
|
-
humanTasks.forEach((task, index) => {
|
|
14563
|
-
lines.push(` ${index + 1}. ${humanTaskText(task)}${riskSuffixFor(task, prp)}`);
|
|
14564
|
-
});
|
|
14565
|
-
}
|
|
14566
|
-
lines.push("");
|
|
14567
|
-
lines.push("Next repo-code fix:");
|
|
14568
|
-
lines.push(
|
|
14569
|
-
nextRepoTask ? ` ${nextRepoTask.title}${riskSuffixFor(nextRepoTask, prp)} -> npx -y viberaven --heal --apply --gap ${nextRepoTask.gapId} --yes` : " (none)"
|
|
14570
|
-
);
|
|
14571
|
-
lines.push("");
|
|
14572
|
-
lines.push("Provider actions:");
|
|
14573
|
-
if (providerTasks.length === 0) {
|
|
14574
|
-
lines.push(" (none)");
|
|
14575
|
-
} else {
|
|
14576
|
-
providerTasks.forEach((task) => {
|
|
14577
|
-
const providerAction = task.providerAction;
|
|
14578
|
-
if (!providerAction) {
|
|
14579
|
-
lines.push(` - ${task.title}${riskSuffixFor(task, prp)}`);
|
|
14580
|
-
return;
|
|
14581
|
-
}
|
|
14582
|
-
lines.push(` - ${providerAction.provider}: ${providerAction.dashboardUrl}`);
|
|
14583
|
-
lines.push(` Step: ${providerAction.exactStep}${riskSuffixFor(task, prp)}`);
|
|
14584
|
-
lines.push(` Done when: ${providerAction.doneSignal}`);
|
|
14585
|
-
});
|
|
14586
|
-
}
|
|
14587
|
-
lines.push("");
|
|
14588
|
-
lines.push("Copy these env var names:");
|
|
14589
|
-
lines.push(envNames.length > 0 ? ` ${envNames.join(", ")}` : " (none)");
|
|
14590
|
-
lines.push("");
|
|
14591
|
-
lines.push(`Verify command: ${prp.verifyCommand}`);
|
|
14592
|
-
lines.push("");
|
|
14593
|
-
lines.push(`Do not deploy until: decision is CLEAR (current: ${prp.decision}). Run the verify command after fixes.`);
|
|
14594
|
-
if (prp.decision === "CLEAR") {
|
|
14595
|
-
lines.push("Share your launch proof: npx -y viberaven badge");
|
|
14596
|
-
}
|
|
14597
|
-
return lines.join("\n");
|
|
14598
|
-
}
|
|
14599
|
-
function buildRichOperatorBlock(prp, tasks) {
|
|
14600
|
-
const repoTasks = tasks.filter((task) => task.fixType === "repo-code");
|
|
14601
|
-
const humanTasks = tasks.filter((task) => task.fixType !== "repo-code");
|
|
14602
|
-
const providerTasks = tasks.filter((task) => task.fixType === "provider-action");
|
|
14603
|
-
const nextRepoTask = repoTasks[0];
|
|
14604
|
-
const envNames = uniqueEnvNames(providerTasks);
|
|
14605
|
-
const mode = "rich";
|
|
14606
|
-
const lines = [];
|
|
14607
|
-
lines.push(wordmark({ variant: "compact", mode }));
|
|
14608
|
-
lines.push(rule(64, { mode }));
|
|
14609
|
-
lines.push(
|
|
14610
|
-
`${accent.bold("Decision", mode)}: ${banner(prp.decision, { mode })} ${gauge(readinessPercent(prp), {
|
|
14611
|
-
width: 18,
|
|
14612
|
-
mode
|
|
14613
|
-
})}`
|
|
14614
|
-
);
|
|
14615
|
-
lines.push(kv("Detected stack", stackLine(prp), { mode }));
|
|
14616
|
-
lines.push("");
|
|
14617
|
-
lines.push(`${accent.bold("What I can fix", mode)}:`);
|
|
14618
|
-
if (repoTasks.length === 0) {
|
|
14619
|
-
lines.push(` ${accent.dim("(none - no automated repo-code recipes apply)", mode)}`);
|
|
14620
|
-
} else {
|
|
14621
|
-
repoTasks.forEach((task, index) => {
|
|
14622
|
-
lines.push(` ${index + 1}. ${task.title}${riskSuffixFor(task, prp)}`);
|
|
14623
|
-
});
|
|
14624
|
-
}
|
|
14625
|
-
lines.push("");
|
|
14626
|
-
lines.push(`${accent.bold("What you must do", mode)}:`);
|
|
14627
|
-
if (humanTasks.length === 0) {
|
|
14628
|
-
lines.push(` ${accent.dim("(none - no human-owned steps required)", mode)}`);
|
|
14629
|
-
} else {
|
|
14630
|
-
humanTasks.forEach((task, index) => {
|
|
14631
|
-
lines.push(` ${index + 1}. ${humanTaskText(task)}${riskSuffixFor(task, prp)}`);
|
|
14632
|
-
});
|
|
14633
|
-
}
|
|
14634
|
-
lines.push("");
|
|
14635
|
-
lines.push(`${accent.bold("Next repo-code fix", mode)}:`);
|
|
14636
|
-
lines.push(
|
|
14637
|
-
nextRepoTask ? ` ${nextRepoTask.title}${riskSuffixFor(nextRepoTask, prp)} -> npx -y viberaven --heal --apply --gap ${nextRepoTask.gapId} --yes` : ` ${accent.dim("(none)", mode)}`
|
|
14638
|
-
);
|
|
14639
|
-
lines.push("");
|
|
14640
|
-
lines.push(`${accent.bold("Provider actions", mode)}:`);
|
|
14641
|
-
if (providerTasks.length === 0) {
|
|
14642
|
-
lines.push(` ${accent.dim("(none)", mode)}`);
|
|
14643
|
-
} else {
|
|
14644
|
-
providerTasks.forEach((task) => {
|
|
14645
|
-
const providerAction = task.providerAction;
|
|
14646
|
-
if (!providerAction) {
|
|
14647
|
-
lines.push(` - ${task.title}${riskSuffixFor(task, prp)}`);
|
|
14648
|
-
return;
|
|
14649
|
-
}
|
|
14650
|
-
lines.push(` - ${accent.brand(providerAction.provider, mode)}: ${providerAction.dashboardUrl}`);
|
|
14651
|
-
lines.push(` ${kv("Step", `${providerAction.exactStep}${riskSuffixFor(task, prp)}`, { mode })}`);
|
|
14652
|
-
lines.push(` ${kv("Done when", providerAction.doneSignal, { mode })}`);
|
|
14653
|
-
});
|
|
14654
|
-
}
|
|
14655
|
-
lines.push("");
|
|
14656
|
-
lines.push(`${accent.bold("Copy these env var names", mode)}:`);
|
|
14657
|
-
lines.push(envNames.length > 0 ? ` ${envNames.join(", ")}` : ` ${accent.dim("(none)", mode)}`);
|
|
14658
|
-
lines.push("");
|
|
14659
|
-
lines.push(kv("Verify command", prp.verifyCommand, { mode }));
|
|
14660
|
-
lines.push("");
|
|
14661
|
-
lines.push(
|
|
14662
|
-
`${accent.bold("Do not deploy until", mode)}: decision is CLEAR (current: ${banner(
|
|
14663
|
-
prp.decision,
|
|
14664
|
-
{ mode }
|
|
14665
|
-
)}). Run the verify command after fixes.`
|
|
14666
|
-
);
|
|
14667
|
-
if (prp.decision === "CLEAR") {
|
|
14668
|
-
lines.push(kv("Share your launch proof", "npx -y viberaven badge", { mode }));
|
|
14669
|
-
}
|
|
14670
|
-
return lines.join("\n");
|
|
14671
|
-
}
|
|
14672
|
-
function buildOperatorBlock(prp, tasks, mode = "plain") {
|
|
14673
|
-
return mode === "rich" ? buildRichOperatorBlock(prp, tasks) : buildPlainOperatorBlock(prp, tasks);
|
|
14674
|
-
}
|
|
14675
|
-
function printOperatorBlock(prp, tasks, mode = "plain") {
|
|
14676
|
-
if (mode === "rich") {
|
|
14677
|
-
console.log(buildOperatorBlock(prp, tasks, "rich"));
|
|
14678
|
-
}
|
|
14679
|
-
console.log(OPERATOR_START);
|
|
14680
|
-
console.log(buildOperatorBlock(prp, tasks, "plain"));
|
|
14681
|
-
console.log(OPERATOR_END);
|
|
14682
|
-
}
|
|
14683
|
-
|
|
14684
|
-
// src/output/celebration.ts
|
|
14685
|
-
function renderClearCelebration(prp, mode) {
|
|
14686
|
-
if (prp.decision !== "CLEAR") return "";
|
|
14687
|
-
const verifiedDate = prp.generatedAt.slice(0, 10);
|
|
14688
|
-
const style = decisionStyle("CLEAR", mode);
|
|
14689
|
-
const lines = [
|
|
14690
|
-
`${style.glyph} ${style.label} production gate is clear`,
|
|
14691
|
-
accent.dim(`Verified ${verifiedDate}`, mode),
|
|
14692
|
-
"",
|
|
14693
|
-
`Share your launch proof: ${accent.bold("npx -y viberaven badge", mode)}`
|
|
14694
|
-
];
|
|
14695
|
-
return [wordmark({ variant: "compact", mode }), box(lines, { mode }), rule(40, { mode })].join("\n");
|
|
14696
|
-
}
|
|
14697
|
-
|
|
14698
|
-
// src/output/loopProgress.ts
|
|
14699
|
-
function safeCount(value) {
|
|
14700
|
-
if (!Number.isFinite(value)) return 0;
|
|
14701
|
-
return Math.max(0, Math.floor(value));
|
|
14702
|
-
}
|
|
14703
|
-
function renderLoopProgress(input, mode) {
|
|
14704
|
-
if (mode === "plain" && input.silentInPlain) return "";
|
|
14705
|
-
const total = safeCount(input.total);
|
|
14706
|
-
const applied = total > 0 ? Math.min(safeCount(input.applied), total) : safeCount(input.applied);
|
|
14707
|
-
const percent = total === 0 ? 100 : applied / total * 100;
|
|
14708
|
-
const label2 = `${STATUS_GLYPH.fixable} ${input.label}`;
|
|
14709
|
-
return `${accent.bold(label2, mode)} ${gauge(percent, { width: 12, mode })} ${applied}/${total}`;
|
|
14710
|
-
}
|
|
14711
|
-
|
|
14712
14503
|
// src/providerMcpBridge.ts
|
|
14713
14504
|
var import_node_fs12 = require("node:fs");
|
|
14714
14505
|
var import_node_os2 = require("node:os");
|
|
@@ -14853,6 +14644,247 @@ function detectConnectedTools() {
|
|
|
14853
14644
|
return tools;
|
|
14854
14645
|
}
|
|
14855
14646
|
|
|
14647
|
+
// src/output/actionPanelBlock.ts
|
|
14648
|
+
var ACTION_PANEL_START = "VIBERAVEN_ACTION_PANEL_START";
|
|
14649
|
+
var ACTION_PANEL_END = "VIBERAVEN_ACTION_PANEL_END";
|
|
14650
|
+
function stackLine(prp) {
|
|
14651
|
+
const parts = Array.from(
|
|
14652
|
+
/* @__PURE__ */ new Set([
|
|
14653
|
+
...prp.detectedStack.deployment,
|
|
14654
|
+
...prp.detectedStack.database,
|
|
14655
|
+
...prp.detectedStack.auth,
|
|
14656
|
+
...prp.detectedStack.payments,
|
|
14657
|
+
...prp.detectedStack.monitoring
|
|
14658
|
+
])
|
|
14659
|
+
);
|
|
14660
|
+
return parts.length > 0 ? parts.join(" + ") : prp.detectedStack.archetype ?? "unknown";
|
|
14661
|
+
}
|
|
14662
|
+
function envVarNames(tasks) {
|
|
14663
|
+
return Array.from(
|
|
14664
|
+
new Set(
|
|
14665
|
+
tasks.map((task) => task.providerAction?.envKeyName).filter((name) => Boolean(name))
|
|
14666
|
+
)
|
|
14667
|
+
);
|
|
14668
|
+
}
|
|
14669
|
+
function humanStep(task) {
|
|
14670
|
+
if (task.fixType === "provider-action") {
|
|
14671
|
+
return task.providerAction?.exactStep ?? task.title;
|
|
14672
|
+
}
|
|
14673
|
+
if (task.fixType === "upgrade-required") {
|
|
14674
|
+
return `Upgrade required: ${task.action ?? task.exactFix ?? task.title}`;
|
|
14675
|
+
}
|
|
14676
|
+
if (task.fixType === "manual-verify") {
|
|
14677
|
+
return `Manual verification required: ${task.action ?? task.exactFix ?? task.title}`;
|
|
14678
|
+
}
|
|
14679
|
+
return task.title;
|
|
14680
|
+
}
|
|
14681
|
+
function repoTaskTitle(task) {
|
|
14682
|
+
return task.action ?? task.exactFix ?? task.title;
|
|
14683
|
+
}
|
|
14684
|
+
function parseDecision(value) {
|
|
14685
|
+
if (value === "CLEAR" || value === "WARNING" || value === "BLOCKED") return value;
|
|
14686
|
+
return "BLOCKED";
|
|
14687
|
+
}
|
|
14688
|
+
function providerFromConnectedToolKey(tool) {
|
|
14689
|
+
if (!tool.endsWith("Mcp")) return void 0;
|
|
14690
|
+
return tool.slice(0, -3).toLowerCase();
|
|
14691
|
+
}
|
|
14692
|
+
function normalizeProvider3(provider2) {
|
|
14693
|
+
const lower = provider2.trim().toLowerCase();
|
|
14694
|
+
const tokens = lower.split(/[^a-z0-9]+/).filter(Boolean);
|
|
14695
|
+
for (const knownProvider of ["supabase", "stripe", "vercel", "github"]) {
|
|
14696
|
+
if (lower === knownProvider || tokens.includes(knownProvider)) {
|
|
14697
|
+
return knownProvider;
|
|
14698
|
+
}
|
|
14699
|
+
}
|
|
14700
|
+
return lower;
|
|
14701
|
+
}
|
|
14702
|
+
function toolSetupFor(prp) {
|
|
14703
|
+
const relevantProviders = new Set([
|
|
14704
|
+
...prp.detectedStack.auth,
|
|
14705
|
+
...prp.detectedStack.database,
|
|
14706
|
+
...prp.detectedStack.deployment,
|
|
14707
|
+
...prp.detectedStack.payments
|
|
14708
|
+
].map(normalizeProvider3));
|
|
14709
|
+
return Object.entries(prp.connectedTools).flatMap(([tool, state]) => {
|
|
14710
|
+
const provider2 = providerFromConnectedToolKey(tool);
|
|
14711
|
+
if (!provider2 || state !== "missing" || !relevantProviders.has(provider2)) {
|
|
14712
|
+
return [];
|
|
14713
|
+
}
|
|
14714
|
+
return [provider2];
|
|
14715
|
+
}).map((provider2) => ({
|
|
14716
|
+
provider: provider2,
|
|
14717
|
+
command: installHintFor(provider2),
|
|
14718
|
+
reason: "Connect this provider MCP so the agent can verify live provider state when available."
|
|
14719
|
+
}));
|
|
14720
|
+
}
|
|
14721
|
+
function checklistFor(repoTasks, humanTasks) {
|
|
14722
|
+
return [
|
|
14723
|
+
{ label: "Understand the stack and launch gaps", done: true, kind: "scan" },
|
|
14724
|
+
...repoTasks.slice(0, 3).map((task) => ({
|
|
14725
|
+
label: repoTaskTitle(task),
|
|
14726
|
+
done: false,
|
|
14727
|
+
kind: "repo-code"
|
|
14728
|
+
})),
|
|
14729
|
+
...humanTasks.slice(0, 3).map((task) => ({
|
|
14730
|
+
label: humanStep(task),
|
|
14731
|
+
done: false,
|
|
14732
|
+
kind: "provider"
|
|
14733
|
+
})),
|
|
14734
|
+
{ label: "Verify again before launch", done: false, kind: "verify" }
|
|
14735
|
+
];
|
|
14736
|
+
}
|
|
14737
|
+
function mermaidFor(prp, tasks) {
|
|
14738
|
+
const status = prp.decision === "CLEAR" ? "Clear" : prp.decision === "WARNING" ? "Review" : "Blocked";
|
|
14739
|
+
const hasProvider = tasks.some((task) => task.fixType === "provider-action");
|
|
14740
|
+
const hasRepo = tasks.some((task) => task.fixType === "repo-code" && !task.requiresUserAction);
|
|
14741
|
+
const lines = [
|
|
14742
|
+
"flowchart LR",
|
|
14743
|
+
` app["AI-built app"] --> stack["${stackLine(prp)}"]`,
|
|
14744
|
+
` stack --> gate["VibeRaven: ${status}"]`
|
|
14745
|
+
];
|
|
14746
|
+
if (hasRepo) lines.push(' gate --> repo["Repo fixes"]');
|
|
14747
|
+
if (hasProvider) lines.push(' gate --> provider["Provider setup"]');
|
|
14748
|
+
lines.push(' gate --> verify["Verify before launch"]');
|
|
14749
|
+
return lines.join("\n");
|
|
14750
|
+
}
|
|
14751
|
+
function buildActionPanelBlock(prp, tasks) {
|
|
14752
|
+
const repoTasks = tasks.filter((task) => task.fixType === "repo-code" && !task.requiresUserAction);
|
|
14753
|
+
const humanTasks = tasks.filter((task) => task.fixType !== "repo-code" || task.requiresUserAction);
|
|
14754
|
+
const nextRepoTask = repoTasks[0];
|
|
14755
|
+
const toolSetup = toolSetupFor(prp);
|
|
14756
|
+
const statusLine = [
|
|
14757
|
+
prp.decision,
|
|
14758
|
+
stackLine(prp),
|
|
14759
|
+
`${tasks.length} launch gap${tasks.length === 1 ? "" : "s"}`
|
|
14760
|
+
].join(" | ");
|
|
14761
|
+
return {
|
|
14762
|
+
VIBERAVEN_ACTION_PANEL: {
|
|
14763
|
+
surface: "native-agent-chat",
|
|
14764
|
+
title: "VibeRaven",
|
|
14765
|
+
statusLine,
|
|
14766
|
+
primaryCommand: nextRepoTask ? `npx -y viberaven --heal --apply --gap ${nextRepoTask.gapId} --yes` : "npx -y viberaven next --json",
|
|
14767
|
+
nextCommand: "npx -y viberaven next --json",
|
|
14768
|
+
verifyCommand: prp.verifyCommand,
|
|
14769
|
+
checklist: checklistFor(repoTasks, humanTasks),
|
|
14770
|
+
mermaidDiagram: mermaidFor(prp, tasks),
|
|
14771
|
+
agentCanDo: repoTasks.length > 0 ? repoTasks.map(repoTaskTitle) : ["No safe repo-code fix is available yet. I will guide the provider steps first."],
|
|
14772
|
+
userMustDo: humanTasks.map((task) => ({
|
|
14773
|
+
provider: task.providerAction?.provider,
|
|
14774
|
+
dashboardUrl: task.providerAction?.dashboardUrl,
|
|
14775
|
+
step: humanStep(task),
|
|
14776
|
+
doneWhen: task.providerAction?.doneSignal
|
|
14777
|
+
})),
|
|
14778
|
+
toolSetup,
|
|
14779
|
+
envVarNames: envVarNames(tasks),
|
|
14780
|
+
agentInstruction: "Render this as a short VibeRaven action message in the native chat. Use the checklist as the live execution timeline and update [ ] to [x] as tasks complete. Present toolSetup as optional connection help, not as a blocker for safe repo fixes. Do not describe the output with internal product labels. Keep the user inside Codex, Claude Code, Cursor, or the terminal. Do not open report.html unless the user explicitly asks for the legacy report."
|
|
14781
|
+
}
|
|
14782
|
+
};
|
|
14783
|
+
}
|
|
14784
|
+
function nextHumanStep(panel) {
|
|
14785
|
+
const hasRepoFix = panel.agentCanDo.some((item3) => !item3.startsWith("No safe repo-code fix"));
|
|
14786
|
+
if (hasRepoFix) {
|
|
14787
|
+
return "Next: I will apply the first safe repo fix, then verify the launch state.";
|
|
14788
|
+
}
|
|
14789
|
+
if (panel.userMustDo.length > 0) {
|
|
14790
|
+
return "Next: I will guide the blocked provider setup, then verify when you confirm it is done.";
|
|
14791
|
+
}
|
|
14792
|
+
return "Next: I will verify the launch state before deploy.";
|
|
14793
|
+
}
|
|
14794
|
+
function buildActionPanelCard(block, mode = "plain") {
|
|
14795
|
+
const panel = block.VIBERAVEN_ACTION_PANEL;
|
|
14796
|
+
const agentCanDo = panel.agentCanDo.slice(0, 3);
|
|
14797
|
+
const userMustDo = panel.userMustDo.slice(0, 3);
|
|
14798
|
+
const lines = [];
|
|
14799
|
+
const statusParts = panel.statusLine.split(/\s*\|\s*/);
|
|
14800
|
+
const decision = parseDecision(statusParts[0] ?? "BLOCKED");
|
|
14801
|
+
const rest = statusParts.slice(1).join(" | ");
|
|
14802
|
+
lines.push(accent.bold("VibeRaven", mode));
|
|
14803
|
+
lines.push("Taking this app from demo to production.");
|
|
14804
|
+
lines.push("");
|
|
14805
|
+
lines.push(`Status: ${banner(decision, { mode })}${rest ? ` | ${rest}` : ""}`);
|
|
14806
|
+
lines.push("");
|
|
14807
|
+
lines.push("Progress:");
|
|
14808
|
+
panel.checklist.slice(0, 6).forEach((item3) => {
|
|
14809
|
+
lines.push(` - [${item3.done ? "x" : " "}] ${item3.label}`);
|
|
14810
|
+
});
|
|
14811
|
+
lines.push("");
|
|
14812
|
+
lines.push("I can do now:");
|
|
14813
|
+
agentCanDo.forEach((item3, index) => {
|
|
14814
|
+
lines.push(` ${index + 1}. ${item3}`);
|
|
14815
|
+
});
|
|
14816
|
+
lines.push("");
|
|
14817
|
+
lines.push("I need you for:");
|
|
14818
|
+
if (userMustDo.length === 0) {
|
|
14819
|
+
lines.push(" (none)");
|
|
14820
|
+
} else {
|
|
14821
|
+
userMustDo.forEach((item3, index) => {
|
|
14822
|
+
const provider2 = item3.provider ? `${item3.provider}: ` : "";
|
|
14823
|
+
lines.push(` ${index + 1}. ${provider2}${item3.step}`);
|
|
14824
|
+
});
|
|
14825
|
+
}
|
|
14826
|
+
const links = userMustDo.filter((item3) => item3.dashboardUrl);
|
|
14827
|
+
if (links.length > 0) {
|
|
14828
|
+
lines.push("");
|
|
14829
|
+
lines.push("Open:");
|
|
14830
|
+
links.forEach((item3) => {
|
|
14831
|
+
const label2 = item3.provider ?? "provider";
|
|
14832
|
+
lines.push(` ${label2}: ${item3.dashboardUrl}`);
|
|
14833
|
+
});
|
|
14834
|
+
}
|
|
14835
|
+
if (panel.envVarNames.length > 0) {
|
|
14836
|
+
lines.push("");
|
|
14837
|
+
lines.push(`Copy env names: ${panel.envVarNames.join(", ")}`);
|
|
14838
|
+
}
|
|
14839
|
+
const toolSetup = panel.toolSetup.slice(0, 3);
|
|
14840
|
+
if (toolSetup.length > 0) {
|
|
14841
|
+
lines.push("");
|
|
14842
|
+
lines.push("Connect tools:");
|
|
14843
|
+
toolSetup.forEach((item3) => {
|
|
14844
|
+
lines.push(` ${item3.provider}: ${item3.command}`);
|
|
14845
|
+
});
|
|
14846
|
+
}
|
|
14847
|
+
lines.push("");
|
|
14848
|
+
lines.push(nextHumanStep(panel));
|
|
14849
|
+
lines.push("Verify: I will re-check after the repo fix or provider step.");
|
|
14850
|
+
return lines.join("\n");
|
|
14851
|
+
}
|
|
14852
|
+
function printActionPanelBlock(prp, tasks, mode = "plain") {
|
|
14853
|
+
const block = buildActionPanelBlock(prp, tasks);
|
|
14854
|
+
console.log(buildActionPanelCard(block, mode));
|
|
14855
|
+
console.log(ACTION_PANEL_START);
|
|
14856
|
+
console.log(JSON.stringify(block, null, 2));
|
|
14857
|
+
console.log(ACTION_PANEL_END);
|
|
14858
|
+
}
|
|
14859
|
+
|
|
14860
|
+
// src/output/celebration.ts
|
|
14861
|
+
function renderClearCelebration(prp, mode) {
|
|
14862
|
+
if (prp.decision !== "CLEAR") return "";
|
|
14863
|
+
const verifiedDate = prp.generatedAt.slice(0, 10);
|
|
14864
|
+
const style = decisionStyle("CLEAR", mode);
|
|
14865
|
+
const lines = [
|
|
14866
|
+
`${style.glyph} ${style.label} production gate is clear`,
|
|
14867
|
+
accent.dim(`Verified ${verifiedDate}`, mode),
|
|
14868
|
+
"",
|
|
14869
|
+
`Share your launch proof: ${accent.bold("npx -y viberaven badge", mode)}`
|
|
14870
|
+
];
|
|
14871
|
+
return [wordmark({ variant: "compact", mode }), box(lines, { mode }), rule(40, { mode })].join("\n");
|
|
14872
|
+
}
|
|
14873
|
+
|
|
14874
|
+
// src/output/loopProgress.ts
|
|
14875
|
+
function safeCount(value) {
|
|
14876
|
+
if (!Number.isFinite(value)) return 0;
|
|
14877
|
+
return Math.max(0, Math.floor(value));
|
|
14878
|
+
}
|
|
14879
|
+
function renderLoopProgress(input, mode) {
|
|
14880
|
+
if (mode === "plain" && input.silentInPlain) return "";
|
|
14881
|
+
const total = safeCount(input.total);
|
|
14882
|
+
const applied = total > 0 ? Math.min(safeCount(input.applied), total) : safeCount(input.applied);
|
|
14883
|
+
const percent = total === 0 ? 100 : applied / total * 100;
|
|
14884
|
+
const label2 = `${STATUS_GLYPH.fixable} ${input.label}`;
|
|
14885
|
+
return `${accent.bold(label2, mode)} ${gauge(percent, { width: 12, mode })} ${applied}/${total}`;
|
|
14886
|
+
}
|
|
14887
|
+
|
|
14856
14888
|
// src/demo/runDemo.ts
|
|
14857
14889
|
var import_node_fs13 = require("node:fs");
|
|
14858
14890
|
var import_node_path27 = __toESM(require("node:path"));
|
|
@@ -15036,49 +15068,51 @@ function bundledFixtureRoot() {
|
|
|
15036
15068
|
return candidates.find((candidate) => (0, import_node_fs13.existsSync)(import_node_path27.default.join(candidate, "package.json"))) ?? candidates[0];
|
|
15037
15069
|
}
|
|
15038
15070
|
function canUseInteractiveTryMenu(options) {
|
|
15039
|
-
return options.label
|
|
15071
|
+
return isPreviewLabel(options.label) && !options.agentMode && !options.openReport && process.stdin.isTTY === true && process.stdout.isTTY === true && process.env.CI !== "true";
|
|
15072
|
+
}
|
|
15073
|
+
function isPreviewLabel(label2) {
|
|
15074
|
+
return label2 === "preview" || label2 === "try";
|
|
15040
15075
|
}
|
|
15041
15076
|
function printTryMenuSummary(input) {
|
|
15042
15077
|
const providerStack = Array.from(new Set(Object.values(input.artifact.selectedProviders ?? {}))).filter(Boolean).join(" + ");
|
|
15043
15078
|
console.log("");
|
|
15044
|
-
console.log("VibeRaven
|
|
15045
|
-
console.log("
|
|
15079
|
+
console.log("VibeRaven Preview");
|
|
15080
|
+
console.log("Local production rehearsal. No login or API spend.");
|
|
15046
15081
|
console.log("");
|
|
15047
|
-
console.log(`
|
|
15082
|
+
console.log(`Preview stack: ${input.artifact.archetype}${providerStack ? ` (${providerStack})` : ""}`);
|
|
15048
15083
|
console.log(
|
|
15049
15084
|
`Decision: BLOCKED | Production core: ${input.artifact.productionCorePercent}% | Gaps: ${input.artifact.gaps.length}`
|
|
15050
15085
|
);
|
|
15051
15086
|
console.log("");
|
|
15052
15087
|
console.log("Menu:");
|
|
15053
|
-
console.log(" 1.
|
|
15054
|
-
console.log(" npx -y viberaven
|
|
15055
|
-
console.log(" 2.
|
|
15056
|
-
console.log(" npx -y viberaven try --agent-mode");
|
|
15057
|
-
console.log(" 3. Run VibeRaven on your real app");
|
|
15088
|
+
console.log(" 1. Show Codex/Claude native agent UI");
|
|
15089
|
+
console.log(" npx -y viberaven preview --agent-mode");
|
|
15090
|
+
console.log(" 2. Run VibeRaven on your real app");
|
|
15058
15091
|
console.log(" npx -y viberaven --agent-mode");
|
|
15092
|
+
console.log(" 3. Open legacy HTML report only if you explicitly want it");
|
|
15093
|
+
console.log(" npx -y viberaven preview --open");
|
|
15059
15094
|
console.log("");
|
|
15060
|
-
console.log(`Local UI: ${input.reportPath}`);
|
|
15061
15095
|
if (input.opened) {
|
|
15062
|
-
console.log("Opened
|
|
15096
|
+
console.log("Opened legacy HTML report in your browser.");
|
|
15063
15097
|
}
|
|
15064
15098
|
console.log("");
|
|
15065
15099
|
}
|
|
15066
15100
|
async function runInteractiveTryMenu(input) {
|
|
15067
|
-
Ie(`${import_picocolors7.default.bold("VibeRaven
|
|
15101
|
+
Ie(`${import_picocolors7.default.bold("VibeRaven Preview")} ${import_picocolors7.default.dim("local production rehearsal")}`);
|
|
15068
15102
|
M2.message(
|
|
15069
|
-
`
|
|
15103
|
+
`Preview stack: ${input.artifact.archetype} | Production core ${input.artifact.productionCorePercent}% | ${input.artifact.gaps.length} gaps`
|
|
15070
15104
|
);
|
|
15071
15105
|
const action = await ve({
|
|
15072
15106
|
message: "What do you want to see?",
|
|
15073
15107
|
options: [
|
|
15074
|
-
{ value: "
|
|
15075
|
-
{ value: "agent-output", label: "Show Codex/Claude output", hint: "Native chat transcript" },
|
|
15108
|
+
{ value: "agent-output", label: "Show Codex/Claude native UI", hint: "Checklist, provider links, and next step" },
|
|
15076
15109
|
{ value: "real-app", label: "Run on my real app", hint: "Copy/use the agent command" },
|
|
15110
|
+
{ value: "open-report", label: "Open legacy HTML report", hint: "Optional old browser report" },
|
|
15077
15111
|
{ value: "exit", label: "Exit" }
|
|
15078
15112
|
]
|
|
15079
15113
|
});
|
|
15080
15114
|
if (pD(action) || action === "exit") {
|
|
15081
|
-
Se(import_picocolors7.default.dim("Run npx -y viberaven
|
|
15115
|
+
Se(import_picocolors7.default.dim("Run npx -y viberaven preview anytime."));
|
|
15082
15116
|
return;
|
|
15083
15117
|
}
|
|
15084
15118
|
if (action === "open-report") {
|
|
@@ -15091,8 +15125,8 @@ async function runInteractiveTryMenu(input) {
|
|
|
15091
15125
|
mode: "demo",
|
|
15092
15126
|
connectedTools: input.connectedTools
|
|
15093
15127
|
});
|
|
15094
|
-
|
|
15095
|
-
printActionPanelBlock(
|
|
15128
|
+
const tasks = buildTaskList(input.artifact);
|
|
15129
|
+
printActionPanelBlock(prp, tasks, currentRenderMode("demo"));
|
|
15096
15130
|
Se(import_picocolors7.default.dim("This is the output Codex/Claude/Cursor should reason over."));
|
|
15097
15131
|
return;
|
|
15098
15132
|
}
|
|
@@ -15100,7 +15134,7 @@ async function runInteractiveTryMenu(input) {
|
|
|
15100
15134
|
console.log("Run this inside Codex, Claude Code, Cursor, Windsurf, or Gemini CLI:");
|
|
15101
15135
|
console.log(" npx -y viberaven --agent-mode");
|
|
15102
15136
|
console.log("");
|
|
15103
|
-
Se(import_picocolors7.default.dim("The native agent chat stays the main UX
|
|
15137
|
+
Se(import_picocolors7.default.dim("The native agent chat stays the main UX. Use report.html only as a legacy fallback."));
|
|
15104
15138
|
}
|
|
15105
15139
|
async function runDemo(options) {
|
|
15106
15140
|
const label2 = options.label ?? "demo";
|
|
@@ -15128,21 +15162,21 @@ async function runDemo(options) {
|
|
|
15128
15162
|
}
|
|
15129
15163
|
if (options.agentMode) {
|
|
15130
15164
|
console.log(
|
|
15131
|
-
label2 === "demo" ? "VibeRaven demo mode - no login, no API spend. Provider verification is simulated." :
|
|
15165
|
+
label2 === "demo" ? "VibeRaven demo mode - no login, no API spend. Provider verification is simulated." : isPreviewLabel(label2) ? "VibeRaven Preview - local production rehearsal. Provider verification is simulated." : "VibeRaven showcase run - no login, no API spend. Provider verification is simulated."
|
|
15132
15166
|
);
|
|
15133
15167
|
const prp = generateProductionProtocol(artifact, { mode: "demo", connectedTools });
|
|
15134
15168
|
const mode = currentRenderMode("demo");
|
|
15135
|
-
|
|
15169
|
+
const tasks = buildTaskList(artifact);
|
|
15136
15170
|
const celebration = renderClearCelebration(prp, mode);
|
|
15171
|
+
printActionPanelBlock(prp, tasks, mode);
|
|
15137
15172
|
if (celebration) {
|
|
15138
15173
|
console.log(celebration);
|
|
15139
15174
|
}
|
|
15140
|
-
|
|
15141
|
-
} else if (label2 === "try") {
|
|
15175
|
+
} else if (isPreviewLabel(label2)) {
|
|
15142
15176
|
if (canUseInteractiveTryMenu(options)) {
|
|
15143
15177
|
await runInteractiveTryMenu({ artifact, reportPath: paths.reportPath, connectedTools });
|
|
15144
15178
|
} else {
|
|
15145
|
-
printTryMenuSummary({ artifact,
|
|
15179
|
+
printTryMenuSummary({ artifact, opened: reportOpened });
|
|
15146
15180
|
}
|
|
15147
15181
|
} else {
|
|
15148
15182
|
console.log(
|
|
@@ -15179,19 +15213,22 @@ Usage:
|
|
|
15179
15213
|
viberaven scan [--open] [--json] [--api-url <url>] [path]
|
|
15180
15214
|
|
|
15181
15215
|
viberaven --agent-mode [--json|--jsonl] [path]
|
|
15182
|
-
Agent-first
|
|
15216
|
+
Agent-first production flow for Codex, Claude Code, Cursor, or terminal agents
|
|
15183
15217
|
|
|
15184
15218
|
viberaven --demo [path]
|
|
15185
15219
|
No-login demo scan over the bundled fixture; writes demo artifacts locally
|
|
15186
15220
|
|
|
15187
15221
|
viberaven --agent-mode --demo [path]
|
|
15188
|
-
Demo
|
|
15222
|
+
Demo production flow; no login, no managed API spend
|
|
15223
|
+
|
|
15224
|
+
viberaven preview [--agent-mode] [path]
|
|
15225
|
+
Local production flow preview with native chat/terminal UX
|
|
15189
15226
|
|
|
15190
|
-
viberaven try [--
|
|
15191
|
-
|
|
15227
|
+
viberaven try [--agent-mode] [path]
|
|
15228
|
+
Alias for preview
|
|
15192
15229
|
|
|
15193
15230
|
viberaven --showcase --agent-mode [path]
|
|
15194
|
-
|
|
15231
|
+
Legacy alias for the local preview run
|
|
15195
15232
|
|
|
15196
15233
|
viberaven --strict[=warning] [path]
|
|
15197
15234
|
Fail when production gate is not clear; warning mode also fails on warnings
|
|
@@ -15200,7 +15237,7 @@ Usage:
|
|
|
15200
15237
|
Refresh .viberaven/context-map.json from the last scan
|
|
15201
15238
|
|
|
15202
15239
|
viberaven report [--open] [path]
|
|
15203
|
-
|
|
15240
|
+
Legacy: rebuild report.html from last scan (no new API scan)
|
|
15204
15241
|
|
|
15205
15242
|
viberaven prompt [--gap <id>] [--provider <key>] [--area <key>] [--no-copy]
|
|
15206
15243
|
|
|
@@ -15317,6 +15354,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
15317
15354
|
"next",
|
|
15318
15355
|
"open",
|
|
15319
15356
|
"prompt",
|
|
15357
|
+
"preview",
|
|
15320
15358
|
"provider-verify",
|
|
15321
15359
|
"report",
|
|
15322
15360
|
"scan",
|
|
@@ -15364,7 +15402,7 @@ function isBooleanFlag(command, key) {
|
|
|
15364
15402
|
return true;
|
|
15365
15403
|
}
|
|
15366
15404
|
if (key === "strict") return true;
|
|
15367
|
-
if (key === "open" && (command === "" || command === "scan" || command === "report" || command === "try")) return true;
|
|
15405
|
+
if (key === "open" && (command === "" || command === "scan" || command === "report" || command === "preview" || command === "try")) return true;
|
|
15368
15406
|
if (key === "verify" && command === "") return true;
|
|
15369
15407
|
if (key === "vercel-supabase" && command === "audit") return true;
|
|
15370
15408
|
if (key === "svg" && command === "badge") return true;
|
|
@@ -15442,36 +15480,6 @@ function resolveDefaultEntrypointMode(options) {
|
|
|
15442
15480
|
function formatScanJsonStdout(artifact) {
|
|
15443
15481
|
return JSON.stringify(sanitizeArtifactForDisk(artifact), null, 2);
|
|
15444
15482
|
}
|
|
15445
|
-
function providerFromConnectedToolKey(tool) {
|
|
15446
|
-
if (!tool.endsWith("Mcp")) return void 0;
|
|
15447
|
-
return tool.slice(0, -3).toLowerCase();
|
|
15448
|
-
}
|
|
15449
|
-
function normalizeProviderForConnectedToolHint(provider2) {
|
|
15450
|
-
const lower = provider2.trim().toLowerCase();
|
|
15451
|
-
const tokens = lower.split(/[^a-z0-9]+/).filter(Boolean);
|
|
15452
|
-
for (const knownProvider of ["supabase", "stripe", "vercel", "github"]) {
|
|
15453
|
-
if (lower === knownProvider || tokens.includes(knownProvider)) {
|
|
15454
|
-
return knownProvider;
|
|
15455
|
-
}
|
|
15456
|
-
}
|
|
15457
|
-
return lower;
|
|
15458
|
-
}
|
|
15459
|
-
function printMissingConnectedToolHints(prp) {
|
|
15460
|
-
const relevantProviders = new Set([
|
|
15461
|
-
...prp.detectedStack.auth,
|
|
15462
|
-
...prp.detectedStack.database,
|
|
15463
|
-
...prp.detectedStack.deployment,
|
|
15464
|
-
...prp.detectedStack.payments
|
|
15465
|
-
].map(normalizeProviderForConnectedToolHint));
|
|
15466
|
-
for (const [tool, state] of Object.entries(prp.connectedTools)) {
|
|
15467
|
-
const provider2 = providerFromConnectedToolKey(tool);
|
|
15468
|
-
if (!provider2 || state !== "missing" || !relevantProviders.has(provider2)) {
|
|
15469
|
-
continue;
|
|
15470
|
-
}
|
|
15471
|
-
console.log(`${provider2} MCP is not connected. For stronger verification, add it:`);
|
|
15472
|
-
console.log(` ${installHintFor(provider2)}`);
|
|
15473
|
-
}
|
|
15474
|
-
}
|
|
15475
15483
|
async function cmdLogin(flags) {
|
|
15476
15484
|
const apiBaseUrl = resolveApiBaseUrl(typeof flags["api-url"] === "string" ? flags["api-url"] : void 0);
|
|
15477
15485
|
await runDeviceLogin(apiBaseUrl);
|
|
@@ -15715,10 +15723,10 @@ async function runScanCommand(flags, positional, options) {
|
|
|
15715
15723
|
console.log(formatScanJsonStdout(artifact));
|
|
15716
15724
|
return { exitCode: 0, artifacts: paths };
|
|
15717
15725
|
}
|
|
15718
|
-
if (!options?.deferMachineOutput) {
|
|
15726
|
+
if (!options?.deferMachineOutput && !flags["agent-mode"]) {
|
|
15719
15727
|
printScanSummary(artifact, paths);
|
|
15720
15728
|
}
|
|
15721
|
-
if (artifact.usage && !options?.deferMachineOutput) {
|
|
15729
|
+
if (artifact.usage && !options?.deferMachineOutput && !flags["agent-mode"]) {
|
|
15722
15730
|
console.log(formatUsageLine(artifact.usage));
|
|
15723
15731
|
}
|
|
15724
15732
|
if (flags["agent-mode"] && !options?.deferMachineOutput) {
|
|
@@ -15728,13 +15736,14 @@ async function runScanCommand(flags, positional, options) {
|
|
|
15728
15736
|
const tasks = buildTaskList(artifact);
|
|
15729
15737
|
const prp = generateProductionProtocol(artifact, { connectedTools });
|
|
15730
15738
|
const mode = currentRenderMode("agent-mode");
|
|
15731
|
-
|
|
15739
|
+
const bootstrap = await maybeAutoInstallAgentRules({ cwd: workspacePath });
|
|
15740
|
+
console.log(formatAgentRulesBootstrapSummary(bootstrap));
|
|
15741
|
+
console.log("");
|
|
15742
|
+
printActionPanelBlock(prp, tasks, mode);
|
|
15732
15743
|
const celebration = renderClearCelebration(prp, mode);
|
|
15733
15744
|
if (celebration) {
|
|
15734
15745
|
console.log(celebration);
|
|
15735
15746
|
}
|
|
15736
|
-
printActionPanelBlock(paths.reportPath);
|
|
15737
|
-
printMissingConnectedToolHints(prp);
|
|
15738
15747
|
const plan = artifact.plan ?? "free";
|
|
15739
15748
|
const block = buildNextActionBlock(tasks, updatedState, plan);
|
|
15740
15749
|
printNextActionBlock(block);
|
|
@@ -15889,12 +15898,12 @@ async function main() {
|
|
|
15889
15898
|
console.log(JSON.stringify(result, null, 2));
|
|
15890
15899
|
return result.status.startsWith("refused") || result.status === "failed" ? 1 : 0;
|
|
15891
15900
|
}
|
|
15892
|
-
if (command === "try") {
|
|
15901
|
+
if (command === "preview" || command === "try") {
|
|
15893
15902
|
const cwd = resolveCliPath(positional[0]);
|
|
15894
15903
|
return runDemo({
|
|
15895
15904
|
cwd,
|
|
15896
15905
|
agentMode: isAgentMode,
|
|
15897
|
-
label: "try",
|
|
15906
|
+
label: command === "preview" ? "preview" : "try",
|
|
15898
15907
|
openReport: flags.open === true || flags.ui === true
|
|
15899
15908
|
});
|
|
15900
15909
|
}
|