@tritard/waterbrother 0.12.1 → 0.12.3
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 +12 -31
- package/src/prompt.js +1 -2
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -5013,30 +5013,9 @@ async function promptLoop(agent, session, context) {
|
|
|
5013
5013
|
if (detectProductRequest(line)) {
|
|
5014
5014
|
const intent = parseProductIntent(line);
|
|
5015
5015
|
|
|
5016
|
-
//
|
|
5017
|
-
|
|
5018
|
-
|
|
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
|
|
5016
|
+
// Extract everything from the request — no interactive prompts (stdin is unreliable on Windows)
|
|
5017
|
+
// Users can be specific: "I want a mobile recipe app, clean style, deploy to vercel"
|
|
5018
|
+
// Or minimal: "I want a recipe app" — LLM infers the rest
|
|
5040
5019
|
const spinner = createProgressSpinner("building your blueprint...");
|
|
5041
5020
|
try {
|
|
5042
5021
|
const { createJsonCompletion } = await import("./grok-client.js");
|
|
@@ -5046,16 +5025,19 @@ async function promptLoop(agent, session, context) {
|
|
|
5046
5025
|
baseUrl: context.runtime.baseUrl,
|
|
5047
5026
|
model,
|
|
5048
5027
|
messages: [
|
|
5049
|
-
{ role: "system", content: `You are a product strategist.
|
|
5028
|
+
{ role: "system", content: `You are a product strategist. Extract a complete product brief from the user's request. Infer anything not stated. Respond with JSON only:
|
|
5050
5029
|
{
|
|
5051
5030
|
"name": "short product name",
|
|
5052
5031
|
"description": "one-sentence description",
|
|
5032
|
+
"audience": "who is this for",
|
|
5033
|
+
"type": "web|mobile|api",
|
|
5053
5034
|
"surfaces": ["Landing", "Login", "Dashboard"],
|
|
5054
5035
|
"stack": { "framework": "Next.js", "styling": "Tailwind", "backend": "Supabase", "auth": "email", "deploy": "Vercel" },
|
|
5036
|
+
"taste": "visual style in 3-5 words",
|
|
5055
5037
|
"features": ["feature 1", "feature 2"]
|
|
5056
5038
|
}
|
|
5057
|
-
Be concrete about surfaces — name actual pages/flows.
|
|
5058
|
-
{ role: "user", content:
|
|
5039
|
+
Be concrete about surfaces — name actual pages/flows. Choose the best stack for the request. Default to web if not specified.` },
|
|
5040
|
+
{ role: "user", content: line }
|
|
5059
5041
|
],
|
|
5060
5042
|
temperature: 0.3
|
|
5061
5043
|
});
|
|
@@ -5068,8 +5050,8 @@ Be concrete about surfaces — name actual pages/flows. Infer features from the
|
|
|
5068
5050
|
const product = createProduct({
|
|
5069
5051
|
name: brief.name || intent.name || "My Product",
|
|
5070
5052
|
description: brief.description || line,
|
|
5071
|
-
audience:
|
|
5072
|
-
type:
|
|
5053
|
+
audience: brief.audience || "",
|
|
5054
|
+
type: brief.type || intent.type
|
|
5073
5055
|
});
|
|
5074
5056
|
|
|
5075
5057
|
// Apply template if detected
|
|
@@ -5082,8 +5064,7 @@ Be concrete about surfaces — name actual pages/flows. Infer features from the
|
|
|
5082
5064
|
if (brief.stack) {
|
|
5083
5065
|
product.stack = { ...product.stack, ...brief.stack };
|
|
5084
5066
|
}
|
|
5085
|
-
product.
|
|
5086
|
-
product.qualityBar.taste = answers.taste;
|
|
5067
|
+
if (brief.taste) product.qualityBar.taste = brief.taste;
|
|
5087
5068
|
if (Array.isArray(brief.surfaces)) {
|
|
5088
5069
|
for (const s of brief.surfaces) {
|
|
5089
5070
|
addSurface(product, { name: s, type: "page", status: "planned" });
|
package/src/prompt.js
CHANGED
|
@@ -30,8 +30,7 @@ export async function promptLine(label, { input = process.stdin, output = proces
|
|
|
30
30
|
if (settled) return;
|
|
31
31
|
const str = chunk.toString();
|
|
32
32
|
for (const ch of str) {
|
|
33
|
-
if (ch === "\r")
|
|
34
|
-
if (ch === "\n") { output.write("\n"); finish(buf); return; }
|
|
33
|
+
if (ch === "\r" || ch === "\n") { output.write("\n"); finish(buf); return; }
|
|
35
34
|
if (ch === "\u0003") { finish("", new DOMException("The operation was aborted.", "AbortError")); return; }
|
|
36
35
|
if (ch === "\u007f" || ch === "\b") {
|
|
37
36
|
if (buf.length > 0) { buf = buf.slice(0, -1); output.write("\b \b"); }
|