sproutkit-code 0.2.0 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +17 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -79735,33 +79735,42 @@ content state.
79735
79735
  OUTPUT
79736
79736
  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
79737
79737
  Return ONLY the complete App.jsx code. No markdown fences, no explanation, no preamble. Just code.`;
79738
+ let lastStop = null;
79738
79739
  async function generateOnce(extraSystemNote) {
79739
79740
  const finalPrompt = extraSystemNote ? `${extraSystemNote}
79740
79741
 
79741
79742
  ${prompt}` : prompt;
79742
79743
  const res2 = await anthropic.messages.create({
79743
79744
  model: (0, models_1.getPreferredModel)(),
79744
- max_tokens: 16e3,
79745
+ // The API requires a max_tokens, so we set it to the model's ceiling
79746
+ // rather than an arbitrary low cap — truncation was the main build
79747
+ // failure. 64000 covers current Claude output limits; the model stops
79748
+ // naturally at end_turn long before this for a normal site.
79749
+ max_tokens: 64e3,
79745
79750
  messages: [{ role: "user", content: finalPrompt }]
79746
79751
  });
79752
+ lastStop = res2.stop_reason ?? null;
79747
79753
  const textBlock = res2.content.find((b) => b.type === "text");
79748
79754
  if (!textBlock) {
79749
79755
  const types = res2.content.map((b) => b.type).join(", ") || "empty";
79750
79756
  throw new Error(`Claude returned no text (stop_reason=${res2.stop_reason}, blocks=[${types}], model=${res2.model})`);
79751
79757
  }
79752
79758
  if (res2.stop_reason === "max_tokens") {
79753
- onProgress(`\u26A0\uFE0E Claude hit max_tokens \u2014 output may be truncated.`);
79759
+ onProgress(`\u26A0\uFE0E Claude hit the length limit \u2014 output was truncated.`);
79754
79760
  }
79755
79761
  return textBlock.text.replace(/^```[a-z]*\s*/i, "").replace(/\s*```$/, "").trim();
79756
79762
  }
79757
79763
  let appCode = await generateOnce();
79758
79764
  if (!appCode.includes("export default App")) {
79759
- onProgress("First attempt came back truncated \u2014 retrying with a leaner build\u2026");
79760
- const retry = await generateOnce("Your previous attempt was cut off before finishing. Produce a COMPLETE, self-contained App component that ends with `export default App;`. Keep it tighter \u2014 fewer sections, less inline copy \u2014 so it fits comfortably. Do not exceed what you can finish.");
79765
+ const wasTruncated = lastStop === "max_tokens";
79766
+ onProgress(wasTruncated ? "Output was truncated \u2014 retrying\u2026" : "First attempt came back incomplete \u2014 retrying\u2026");
79767
+ const retry = await generateOnce("Your previous attempt did not finish with `export default App;`. Produce the COMPLETE, self-contained App component ending in that exact line. Do not stop early.");
79761
79768
  if (retry.includes("export default App")) {
79762
79769
  appCode = retry;
79770
+ } else if (lastStop === "max_tokens") {
79771
+ throw new Error("This site's content is unusually large and Claude's output was cut off. Try regenerating with 'keep it minimal \u2014 few sections'.");
79763
79772
  } else {
79764
- throw new Error("The site was too large to generate in one pass (Claude's output was cut off twice). Try again with instructions to keep it simple \u2014 e.g. 'minimal, few sections'.");
79773
+ throw new Error(`Claude returned incomplete code twice (stop reason: ${lastStop ?? "unknown"}). This usually clears on another try, or check the model with 'sproutkit models'.`);
79765
79774
  }
79766
79775
  }
79767
79776
  const stockHosts = findStockImages(appCode);
@@ -81178,8 +81187,9 @@ Formatting \u2014 you're writing into a narrow chat bubble, not a document:
81178
81187
  - Skip empty fields entirely rather than writing "\u2014" or "N/A" in a column.
81179
81188
  - Lead with the answer. If the user asked "how many", give the number first, then the breakdown.
81180
81189
  - For more than about 8 leads, show the most relevant handful and say how many others there are instead of listing everything.`;
81190
+ var VOLATILE_INPUT_FIELDS = /* @__PURE__ */ new Set(["instructions", "message", "concurrency"]);
81181
81191
  function confirmKey(name, input) {
81182
- const norm = Object.keys(input ?? {}).sort().reduce((acc, k) => {
81192
+ const norm = Object.keys(input ?? {}).filter((k) => !VOLATILE_INPUT_FIELDS.has(k)).sort().reduce((acc, k) => {
81183
81193
  const v = input[k];
81184
81194
  if (v === void 0 || v === null || v === false || v === "")
81185
81195
  return acc;
@@ -82053,7 +82063,7 @@ var require_package = __commonJS({
82053
82063
  "package.json"(exports2, module2) {
82054
82064
  module2.exports = {
82055
82065
  name: "sproutkit-code",
82056
- version: "0.2.0",
82066
+ version: "0.2.1",
82057
82067
  description: "Sproutkit in your terminal \u2014 find leads, build sites, run outreach, all via chat.",
82058
82068
  bin: {
82059
82069
  sproutkit: "./dist/index.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sproutkit-code",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Sproutkit in your terminal — find leads, build sites, run outreach, all via chat.",
5
5
  "bin": {
6
6
  "sproutkit": "./dist/index.js"