@kubuild/ai 0.4.0 → 0.6.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/dist/{chunk-T72YWBJS.js → chunk-K7CBTQCY.js} +30 -1
- package/dist/chunk-K7CBTQCY.js.map +1 -0
- package/dist/client/ai-client.d.ts +8 -1
- package/dist/client/ai-client.d.ts.map +1 -1
- package/dist/client/index.cjs +29 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/react/index.cjs +59 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +31 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/use-ai-generator.d.ts +2 -1
- package/dist/react/use-ai-generator.d.ts.map +1 -1
- package/dist/server/engine.d.ts +5 -1
- package/dist/server/engine.d.ts.map +1 -1
- package/dist/server/handler.d.ts +8 -1
- package/dist/server/handler.d.ts.map +1 -1
- package/dist/server/index.cjs +152 -41
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +152 -41
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +32 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-T72YWBJS.js.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -64,6 +64,13 @@ var KubuildAiEngine = class {
|
|
|
64
64
|
Tone: ${request.tone}`;
|
|
65
65
|
if (request.locale) userPrompt += `
|
|
66
66
|
Language/Locale: ${request.locale}`;
|
|
67
|
+
if (request.conversationHistory && request.conversationHistory.length > 0) {
|
|
68
|
+
const chatContext = request.conversationHistory.map((m) => `${m.role.toUpperCase()}: ${getMessageText(m)}`).join("\n");
|
|
69
|
+
userPrompt += `
|
|
70
|
+
|
|
71
|
+
Prior Conversation Discussion Context:
|
|
72
|
+
${chatContext}`;
|
|
73
|
+
}
|
|
67
74
|
const jsonSchema = buildJsonSchemaForMode("full-page");
|
|
68
75
|
const result = await this.options.adapter.generate({
|
|
69
76
|
systemPrompt,
|
|
@@ -202,18 +209,18 @@ ${JSON.stringify(request.node, null, 2)}`;
|
|
|
202
209
|
};
|
|
203
210
|
}
|
|
204
211
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
buildPlanPrompts(request) {
|
|
213
|
+
let sectionGuidance = "Plan between 4 to 6 cohesive, essential sections (e.g., hero, features, testimonials, pricing, cta, footer) that fulfill the request thoroughly.";
|
|
214
|
+
if (typeof request.sectionCount === "number") {
|
|
215
|
+
sectionGuidance = `Plan exactly ${request.sectionCount} cohesive sections that fulfill the request.`;
|
|
216
|
+
} else if (request.sectionCount?.min || request.sectionCount?.max) {
|
|
217
|
+
const min = request.sectionCount.min ?? 3;
|
|
218
|
+
const max = request.sectionCount.max ?? 8;
|
|
219
|
+
sectionGuidance = `Plan between ${min} and ${max} cohesive sections that fulfill the request.`;
|
|
220
|
+
} else {
|
|
221
|
+
sectionGuidance += " If the user request mentions a specific number or list of sections, respect the user request.";
|
|
222
|
+
}
|
|
223
|
+
const planSystemPrompt = `
|
|
217
224
|
You are a web architect for the KUBUILD page builder.
|
|
218
225
|
Given the user's prompt, plan the website structure. Output pure JSON (no markdown fences, no explanatory text):
|
|
219
226
|
{
|
|
@@ -235,44 +242,113 @@ Given the user's prompt, plan the website structure. Output pure JSON (no markdo
|
|
|
235
242
|
}
|
|
236
243
|
]
|
|
237
244
|
}
|
|
238
|
-
|
|
245
|
+
${sectionGuidance}
|
|
239
246
|
`;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
247
|
+
let planUserPrompt = `User Request: ${request.prompt}`;
|
|
248
|
+
if (request.stylePreference) {
|
|
249
|
+
planUserPrompt += `
|
|
243
250
|
Style Preference: ${request.stylePreference}`;
|
|
244
|
-
|
|
245
|
-
|
|
251
|
+
}
|
|
252
|
+
if (request.tone) planUserPrompt += `
|
|
246
253
|
Tone: ${request.tone}`;
|
|
247
|
-
|
|
254
|
+
if (request.locale) planUserPrompt += `
|
|
248
255
|
Locale: ${request.locale}`;
|
|
249
|
-
|
|
256
|
+
if (request.conversationHistory && request.conversationHistory.length > 0) {
|
|
257
|
+
const chatContext = request.conversationHistory.map((m) => `${m.role.toUpperCase()}: ${getMessageText(m)}`).join("\n");
|
|
258
|
+
planUserPrompt += `
|
|
259
|
+
|
|
260
|
+
Prior Conversation Discussion Context:
|
|
261
|
+
${chatContext}`;
|
|
262
|
+
}
|
|
263
|
+
return { systemPrompt: planSystemPrompt, userPrompt: planUserPrompt };
|
|
264
|
+
}
|
|
265
|
+
async planPage(request, context) {
|
|
266
|
+
let rawText = "";
|
|
267
|
+
try {
|
|
268
|
+
const { systemPrompt, userPrompt } = this.buildPlanPrompts(request);
|
|
269
|
+
this.log("info", `Planning website layout for: "${request.prompt}"`);
|
|
250
270
|
const planResult = await this.options.adapter.generate({
|
|
251
|
-
systemPrompt
|
|
252
|
-
userPrompt
|
|
271
|
+
systemPrompt,
|
|
272
|
+
userPrompt,
|
|
253
273
|
signal: context?.signal
|
|
254
274
|
});
|
|
255
|
-
|
|
275
|
+
rawText = planResult.text;
|
|
276
|
+
const plan = extractJsonFromResponse(rawText);
|
|
277
|
+
return {
|
|
278
|
+
success: true,
|
|
279
|
+
data: plan,
|
|
280
|
+
usage: planResult.usage,
|
|
281
|
+
rawModelResponse: rawText
|
|
282
|
+
};
|
|
283
|
+
} catch (err) {
|
|
284
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
285
|
+
this.log("warn", "Failed to generate plan JSON, using fallback plan", message);
|
|
286
|
+
const fallbackPlan = {
|
|
287
|
+
title: "AI Generated Page",
|
|
288
|
+
description: "Generated by KUBUILD AI",
|
|
289
|
+
sections: [
|
|
290
|
+
{ type: "hero", title: "Hero Banner", prompt: `Hero section for: ${request.prompt}` },
|
|
291
|
+
{ type: "features", title: "Key Features", prompt: `Features grid for: ${request.prompt}` },
|
|
292
|
+
{ type: "testimonials", title: "Testimonials", prompt: `Social proof and customer reviews for: ${request.prompt}` },
|
|
293
|
+
{ type: "cta", title: "Call To Action", prompt: `Call to action section for: ${request.prompt}` },
|
|
294
|
+
{ type: "footer", title: "Footer", prompt: `Footer navigation and copyright for: ${request.prompt}` }
|
|
295
|
+
]
|
|
296
|
+
};
|
|
297
|
+
return {
|
|
298
|
+
success: true,
|
|
299
|
+
data: fallbackPlan,
|
|
300
|
+
rawModelResponse: rawText || void 0
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Progressive Section Streaming Generator.
|
|
306
|
+
* Emits structured SSE events: status -> metadata -> section (one by one) -> complete.
|
|
307
|
+
*/
|
|
308
|
+
async *streamPage(request, context) {
|
|
309
|
+
try {
|
|
310
|
+
this.log("info", `[SSE] Starting streamPage for prompt: "${request.prompt}"`);
|
|
311
|
+
yield {
|
|
312
|
+
type: "status",
|
|
313
|
+
message: "Analyzing requirements and planning page sections..."
|
|
314
|
+
};
|
|
256
315
|
let plan;
|
|
257
|
-
|
|
258
|
-
plan =
|
|
259
|
-
this.log("
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
316
|
+
if (request.plan && Array.isArray(request.plan.sections) && request.plan.sections.length > 0) {
|
|
317
|
+
plan = request.plan;
|
|
318
|
+
this.log("info", `[SSE] Using approved pre-planned structure with ${plan.sections?.length ?? 0} sections`);
|
|
319
|
+
} else {
|
|
320
|
+
const { systemPrompt: planSystemPrompt, userPrompt: planUserPrompt } = this.buildPlanPrompts(request);
|
|
321
|
+
this.log("info", "[SSE] Generating website layout plan...");
|
|
322
|
+
const planResult = await this.options.adapter.generate({
|
|
323
|
+
systemPrompt: planSystemPrompt,
|
|
324
|
+
userPrompt: planUserPrompt,
|
|
325
|
+
signal: context?.signal
|
|
326
|
+
});
|
|
327
|
+
this.log("debug", "[SSE] Raw plan response from model", planResult.text);
|
|
328
|
+
try {
|
|
329
|
+
plan = extractJsonFromResponse(planResult.text);
|
|
330
|
+
this.log("debug", "[SSE] Parsed plan successfully", plan);
|
|
331
|
+
} catch (parseErr) {
|
|
332
|
+
this.log("warn", "[SSE] Failed to parse plan JSON, using fallback plan", parseErr);
|
|
333
|
+
plan = {
|
|
334
|
+
title: "AI Generated Page",
|
|
335
|
+
description: "Generated by KUBUILD AI",
|
|
336
|
+
sections: [
|
|
337
|
+
{ type: "hero", title: "Hero Banner", prompt: `Hero section for: ${request.prompt}` },
|
|
338
|
+
{ type: "features", title: "Key Features", prompt: `Features grid for: ${request.prompt}` },
|
|
339
|
+
{ type: "testimonials", title: "Testimonials", prompt: `Social proof for: ${request.prompt}` },
|
|
340
|
+
{ type: "cta", title: "Call To Action", prompt: `Call to action section for: ${request.prompt}` },
|
|
341
|
+
{ type: "footer", title: "Footer", prompt: `Footer for: ${request.prompt}` }
|
|
342
|
+
]
|
|
343
|
+
};
|
|
344
|
+
}
|
|
271
345
|
}
|
|
272
346
|
const sectionsToGenerate = Array.isArray(plan.sections) && plan.sections.length > 0 ? plan.sections : [
|
|
273
347
|
{ type: "hero", title: "Hero Section", prompt: `Hero banner for: ${request.prompt}` },
|
|
274
348
|
{ type: "features", title: "Features", prompt: `Features grid for: ${request.prompt}` },
|
|
275
|
-
{ type: "
|
|
349
|
+
{ type: "testimonials", title: "Testimonials", prompt: `Social proof for: ${request.prompt}` },
|
|
350
|
+
{ type: "cta", title: "Call To Action", prompt: `CTA section for: ${request.prompt}` },
|
|
351
|
+
{ type: "footer", title: "Footer", prompt: `Footer section for: ${request.prompt}` }
|
|
276
352
|
];
|
|
277
353
|
const metadata = DocumentMetadataSchema.parse({
|
|
278
354
|
title: plan.title || "AI Generated Page",
|
|
@@ -1667,7 +1743,10 @@ async function processAiRequest(engine, body, signal, agent) {
|
|
|
1667
1743
|
stylePreference: payload.stylePreference,
|
|
1668
1744
|
tone: payload.tone,
|
|
1669
1745
|
locale: payload.locale,
|
|
1670
|
-
metadata: payload.metadata
|
|
1746
|
+
metadata: payload.metadata,
|
|
1747
|
+
conversationHistory: payload.conversationHistory ?? payload.messages,
|
|
1748
|
+
sectionCount: payload.sectionCount,
|
|
1749
|
+
plan: payload.plan
|
|
1671
1750
|
},
|
|
1672
1751
|
{ signal }
|
|
1673
1752
|
);
|
|
@@ -1775,13 +1854,42 @@ async function processAiRequest(engine, body, signal, agent) {
|
|
|
1775
1854
|
response: { success: result.stoppedBy !== "error", data: result }
|
|
1776
1855
|
};
|
|
1777
1856
|
}
|
|
1857
|
+
if (mode === "plan") {
|
|
1858
|
+
if (!payload.prompt || typeof payload.prompt !== "string") {
|
|
1859
|
+
return {
|
|
1860
|
+
status: 400,
|
|
1861
|
+
response: {
|
|
1862
|
+
success: false,
|
|
1863
|
+
error: {
|
|
1864
|
+
code: "INVALID_PROMPT",
|
|
1865
|
+
message: '"prompt" is required for planning mode'
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
const result = await engine.planPage(
|
|
1871
|
+
{
|
|
1872
|
+
prompt: payload.prompt,
|
|
1873
|
+
stylePreference: payload.stylePreference,
|
|
1874
|
+
tone: payload.tone,
|
|
1875
|
+
locale: payload.locale,
|
|
1876
|
+
sectionCount: payload.sectionCount,
|
|
1877
|
+
conversationHistory: payload.conversationHistory ?? payload.messages
|
|
1878
|
+
},
|
|
1879
|
+
{ signal }
|
|
1880
|
+
);
|
|
1881
|
+
return {
|
|
1882
|
+
status: result.success ? 200 : 500,
|
|
1883
|
+
response: result
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
1778
1886
|
return {
|
|
1779
1887
|
status: 400,
|
|
1780
1888
|
response: {
|
|
1781
1889
|
success: false,
|
|
1782
1890
|
error: {
|
|
1783
1891
|
code: "UNKNOWN_MODE",
|
|
1784
|
-
message: `Unsupported mode: ${String(mode)}. Supported modes: 'full-page', 'section', 'refactor', 'chat', 'agent'`
|
|
1892
|
+
message: `Unsupported mode: ${String(mode)}. Supported modes: 'full-page', 'section', 'refactor', 'chat', 'agent', 'plan'`
|
|
1785
1893
|
}
|
|
1786
1894
|
}
|
|
1787
1895
|
};
|
|
@@ -1964,7 +2072,10 @@ function createAiHandler(engine, options) {
|
|
|
1964
2072
|
stylePreference: body.stylePreference,
|
|
1965
2073
|
tone: body.tone,
|
|
1966
2074
|
locale: body.locale,
|
|
1967
|
-
metadata: body.metadata
|
|
2075
|
+
metadata: body.metadata,
|
|
2076
|
+
conversationHistory: body.conversationHistory ?? body.messages,
|
|
2077
|
+
sectionCount: body.sectionCount,
|
|
2078
|
+
plan: body.plan
|
|
1968
2079
|
},
|
|
1969
2080
|
{ signal: request.signal }
|
|
1970
2081
|
),
|