@tritard/waterbrother 0.12.0 → 0.12.1
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/package.json +1 -1
- package/src/cli.js +49 -13
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -5012,10 +5012,33 @@ async function promptLoop(agent, session, context) {
|
|
|
5012
5012
|
// Product builder intake: detect "I want a recipe app" in any mode
|
|
5013
5013
|
if (detectProductRequest(line)) {
|
|
5014
5014
|
const intent = parseProductIntent(line);
|
|
5015
|
-
const spinner = createProgressSpinner("understanding your product...");
|
|
5016
5015
|
|
|
5016
|
+
// Multi-turn brief intake — ask the right questions
|
|
5017
|
+
const questions = [
|
|
5018
|
+
{ key: "type", prompt: "Web app or mobile? [web]", default: intent.type || "web" },
|
|
5019
|
+
{ key: "audience", prompt: "Who is this for?", default: "" },
|
|
5020
|
+
{ key: "taste", prompt: "Visual style? (e.g. clean, bold, minimal, playful) [clean and modern]", default: "clean and modern" },
|
|
5021
|
+
{ key: "deploy", prompt: "Deploy where? (vercel, netlify, github-pages) [vercel]", default: "vercel" }
|
|
5022
|
+
];
|
|
5023
|
+
|
|
5024
|
+
const answers = { type: intent.type || "web", audience: "", taste: "clean and modern", deploy: "vercel" };
|
|
5025
|
+
|
|
5026
|
+
console.log(`\n${bold("Let's scope this out.")}`);
|
|
5027
|
+
|
|
5028
|
+
for (const q of questions) {
|
|
5029
|
+
try {
|
|
5030
|
+
const raw = await promptLine(` ${q.prompt} `, { input: process.stdin, output: process.stdout });
|
|
5031
|
+
const answer = raw.trim();
|
|
5032
|
+
if (answer) answers[q.key] = answer;
|
|
5033
|
+
else answers[q.key] = q.default;
|
|
5034
|
+
} catch {
|
|
5035
|
+
answers[q.key] = q.default;
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
|
|
5039
|
+
// Now use the LLM to generate the full brief with user context
|
|
5040
|
+
const spinner = createProgressSpinner("building your blueprint...");
|
|
5017
5041
|
try {
|
|
5018
|
-
// Ask the model to extract product details via structured JSON
|
|
5019
5042
|
const { createJsonCompletion } = await import("./grok-client.js");
|
|
5020
5043
|
const model = context.runtime.plannerModel || agent.getModel();
|
|
5021
5044
|
const completion = await createJsonCompletion({
|
|
@@ -5023,19 +5046,16 @@ async function promptLoop(agent, session, context) {
|
|
|
5023
5046
|
baseUrl: context.runtime.baseUrl,
|
|
5024
5047
|
model,
|
|
5025
5048
|
messages: [
|
|
5026
|
-
{ role: "system", content: `You are a product strategist.
|
|
5049
|
+
{ role: "system", content: `You are a product strategist. Given the user's request and answers, create a product brief. Respond with JSON only:
|
|
5027
5050
|
{
|
|
5028
5051
|
"name": "short product name",
|
|
5029
5052
|
"description": "one-sentence description",
|
|
5030
|
-
"
|
|
5031
|
-
"type": "web|mobile|api|cli|desktop",
|
|
5032
|
-
"surfaces": ["Landing", "Login", "Dashboard", "Settings"],
|
|
5053
|
+
"surfaces": ["Landing", "Login", "Dashboard"],
|
|
5033
5054
|
"stack": { "framework": "Next.js", "styling": "Tailwind", "backend": "Supabase", "auth": "email", "deploy": "Vercel" },
|
|
5034
|
-
"taste": "visual style in 3-5 words",
|
|
5035
5055
|
"features": ["feature 1", "feature 2"]
|
|
5036
5056
|
}
|
|
5037
|
-
|
|
5038
|
-
{ role: "user", content: line }
|
|
5057
|
+
Be concrete about surfaces — name actual pages/flows. Infer features from the request.` },
|
|
5058
|
+
{ role: "user", content: `Request: ${line}\nType: ${answers.type}\nAudience: ${answers.audience}\nStyle: ${answers.taste}\nDeploy: ${answers.deploy}` }
|
|
5039
5059
|
],
|
|
5040
5060
|
temperature: 0.3
|
|
5041
5061
|
});
|
|
@@ -5048,8 +5068,8 @@ Infer reasonable defaults. Keep it practical.` },
|
|
|
5048
5068
|
const product = createProduct({
|
|
5049
5069
|
name: brief.name || intent.name || "My Product",
|
|
5050
5070
|
description: brief.description || line,
|
|
5051
|
-
audience:
|
|
5052
|
-
type:
|
|
5071
|
+
audience: answers.audience,
|
|
5072
|
+
type: answers.type
|
|
5053
5073
|
});
|
|
5054
5074
|
|
|
5055
5075
|
// Apply template if detected
|
|
@@ -5058,11 +5078,12 @@ Infer reasonable defaults. Keep it practical.` },
|
|
|
5058
5078
|
applyTemplate(product, templateType);
|
|
5059
5079
|
}
|
|
5060
5080
|
|
|
5061
|
-
// Fill in
|
|
5081
|
+
// Fill in from brief + answers
|
|
5062
5082
|
if (brief.stack) {
|
|
5063
5083
|
product.stack = { ...product.stack, ...brief.stack };
|
|
5064
5084
|
}
|
|
5065
|
-
|
|
5085
|
+
product.stack.deploy = answers.deploy;
|
|
5086
|
+
product.qualityBar.taste = answers.taste;
|
|
5066
5087
|
if (Array.isArray(brief.surfaces)) {
|
|
5067
5088
|
for (const s of brief.surfaces) {
|
|
5068
5089
|
addSurface(product, { name: s, type: "page", status: "planned" });
|
|
@@ -5186,6 +5207,21 @@ Infer reasonable defaults. Keep it practical.` },
|
|
|
5186
5207
|
return true;
|
|
5187
5208
|
}
|
|
5188
5209
|
|
|
5210
|
+
// Mode transitions: builder ↔ cockpit
|
|
5211
|
+
if (/^(show me the code|show code|view code|drop into code|engineering mode|cockpit)$/.test(lower)) {
|
|
5212
|
+
agent.setExperienceMode("expert");
|
|
5213
|
+
console.log("switched to expert mode — cockpit active");
|
|
5214
|
+
console.log(dim("use /feature to start a structured task, or type what to work on"));
|
|
5215
|
+
updatePanel();
|
|
5216
|
+
return true;
|
|
5217
|
+
}
|
|
5218
|
+
if (/^(back to builder|builder mode|just build|product mode|guide mode)$/.test(lower)) {
|
|
5219
|
+
agent.setExperienceMode("guide");
|
|
5220
|
+
console.log("switched to guide mode — product builder active");
|
|
5221
|
+
console.log(generateBlueprint(product));
|
|
5222
|
+
return true;
|
|
5223
|
+
}
|
|
5224
|
+
|
|
5189
5225
|
if (/^(adjust|change|modify)$/.test(lower)) {
|
|
5190
5226
|
console.log(generateBlueprint(product));
|
|
5191
5227
|
console.log("\nDescribe what to adjust (e.g. 'add a settings page' or 'change auth to Google')");
|