sproutkit-code 0.1.3 → 0.2.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/index.js +145 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30351,11 +30351,11 @@ var require_models = __commonJS({
|
|
|
30351
30351
|
};
|
|
30352
30352
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
30353
30353
|
exports2.fetchModelsFromAnthropic = fetchModelsFromAnthropic;
|
|
30354
|
-
exports2.refreshModels =
|
|
30355
|
-
exports2.listCachedModels =
|
|
30354
|
+
exports2.refreshModels = refreshModels2;
|
|
30355
|
+
exports2.listCachedModels = listCachedModels2;
|
|
30356
30356
|
exports2.getCacheFetchedAt = getCacheFetchedAt;
|
|
30357
|
-
exports2.refreshIfStale =
|
|
30358
|
-
exports2.getPreferredModel =
|
|
30357
|
+
exports2.refreshIfStale = refreshIfStale2;
|
|
30358
|
+
exports2.getPreferredModel = getPreferredModel2;
|
|
30359
30359
|
var axios_1 = __importDefault(require_axios());
|
|
30360
30360
|
var db_1 = require_db();
|
|
30361
30361
|
var CACHE_KEY = "claude_models_cache";
|
|
@@ -30398,36 +30398,36 @@ var require_models = __commonJS({
|
|
|
30398
30398
|
created_at: m.created_at
|
|
30399
30399
|
}));
|
|
30400
30400
|
}
|
|
30401
|
-
async function
|
|
30402
|
-
const
|
|
30403
|
-
if (
|
|
30401
|
+
async function refreshModels2(apiKey) {
|
|
30402
|
+
const models2 = await fetchModelsFromAnthropic(apiKey);
|
|
30403
|
+
if (models2.length === 0)
|
|
30404
30404
|
throw new Error("Anthropic returned no models");
|
|
30405
|
-
writeCache({ fetched_at: Date.now(), models });
|
|
30406
|
-
return
|
|
30405
|
+
writeCache({ fetched_at: Date.now(), models: models2 });
|
|
30406
|
+
return models2;
|
|
30407
30407
|
}
|
|
30408
|
-
function
|
|
30408
|
+
function listCachedModels2() {
|
|
30409
30409
|
const cache = readCache();
|
|
30410
30410
|
return cache?.models ?? FALLBACK_MODELS;
|
|
30411
30411
|
}
|
|
30412
30412
|
function getCacheFetchedAt() {
|
|
30413
30413
|
return readCache()?.fetched_at ?? null;
|
|
30414
30414
|
}
|
|
30415
|
-
async function
|
|
30415
|
+
async function refreshIfStale2(apiKey) {
|
|
30416
30416
|
if (!apiKey)
|
|
30417
30417
|
return;
|
|
30418
30418
|
const cache = readCache();
|
|
30419
30419
|
if (cache && Date.now() - cache.fetched_at < REFRESH_INTERVAL_MS)
|
|
30420
30420
|
return;
|
|
30421
30421
|
try {
|
|
30422
|
-
await
|
|
30422
|
+
await refreshModels2(apiKey);
|
|
30423
30423
|
} catch {
|
|
30424
30424
|
}
|
|
30425
30425
|
}
|
|
30426
|
-
function
|
|
30426
|
+
function getPreferredModel2() {
|
|
30427
30427
|
const db2 = (0, db_1.getDb)();
|
|
30428
30428
|
const row = db2.get("SELECT value FROM settings WHERE key = ?", ["claude_model"]);
|
|
30429
30429
|
const chosen = row?.value;
|
|
30430
|
-
const available =
|
|
30430
|
+
const available = listCachedModels2();
|
|
30431
30431
|
if (chosen && available.some((m) => m.id === chosen))
|
|
30432
30432
|
return chosen;
|
|
30433
30433
|
const sortedByRecency = [...available].sort((a, b) => {
|
|
@@ -79756,7 +79756,13 @@ ${prompt}` : prompt;
|
|
|
79756
79756
|
}
|
|
79757
79757
|
let appCode = await generateOnce();
|
|
79758
79758
|
if (!appCode.includes("export default App")) {
|
|
79759
|
-
|
|
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.");
|
|
79761
|
+
if (retry.includes("export default App")) {
|
|
79762
|
+
appCode = retry;
|
|
79763
|
+
} 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'.");
|
|
79765
|
+
}
|
|
79760
79766
|
}
|
|
79761
79767
|
const stockHosts = findStockImages(appCode);
|
|
79762
79768
|
if (stockHosts.length > 0) {
|
|
@@ -82047,7 +82053,7 @@ var require_package = __commonJS({
|
|
|
82047
82053
|
"package.json"(exports2, module2) {
|
|
82048
82054
|
module2.exports = {
|
|
82049
82055
|
name: "sproutkit-code",
|
|
82050
|
-
version: "0.
|
|
82056
|
+
version: "0.2.0",
|
|
82051
82057
|
description: "Sproutkit in your terminal \u2014 find leads, build sites, run outreach, all via chat.",
|
|
82052
82058
|
bin: {
|
|
82053
82059
|
sproutkit: "./dist/index.js"
|
|
@@ -82093,6 +82099,7 @@ var autoMode = require_auto_mode();
|
|
|
82093
82099
|
var cms = require_cms_provision();
|
|
82094
82100
|
var bookingPreset = require_booking_preset();
|
|
82095
82101
|
var builder = require_builder();
|
|
82102
|
+
var models = require_models();
|
|
82096
82103
|
var initDatabase = db.initDatabase;
|
|
82097
82104
|
var getDb = db.getDb;
|
|
82098
82105
|
var chatWithTools = chat.chatWithTools;
|
|
@@ -82100,6 +82107,10 @@ var startAutoJob = autoMode.startAutoJob;
|
|
|
82100
82107
|
var provisionCmsForLead = cms.provisionCmsForLead;
|
|
82101
82108
|
var generatePreset = bookingPreset.generatePreset;
|
|
82102
82109
|
var deployBookingOnly = builder.deployBookingOnly;
|
|
82110
|
+
var refreshModels = models.refreshModels;
|
|
82111
|
+
var refreshIfStale = models.refreshIfStale;
|
|
82112
|
+
var listCachedModels = models.listCachedModels;
|
|
82113
|
+
var getPreferredModel = models.getPreferredModel;
|
|
82103
82114
|
|
|
82104
82115
|
// src/config.ts
|
|
82105
82116
|
var REQUIRED_KEYS = [
|
|
@@ -82236,6 +82247,53 @@ function closeTty() {
|
|
|
82236
82247
|
function say(msg = "") {
|
|
82237
82248
|
process.stdout.write(msg + "\n");
|
|
82238
82249
|
}
|
|
82250
|
+
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
82251
|
+
var Status = class {
|
|
82252
|
+
timer = null;
|
|
82253
|
+
frame = 0;
|
|
82254
|
+
label = "";
|
|
82255
|
+
stage = "";
|
|
82256
|
+
tty = process.stdout.isTTY && useColor;
|
|
82257
|
+
start(label) {
|
|
82258
|
+
this.label = label;
|
|
82259
|
+
this.stage = "";
|
|
82260
|
+
if (!this.tty) {
|
|
82261
|
+
say(c.cyan(` \u27F3 ${label}`));
|
|
82262
|
+
return;
|
|
82263
|
+
}
|
|
82264
|
+
this.render();
|
|
82265
|
+
this.timer = setInterval(() => {
|
|
82266
|
+
this.frame = (this.frame + 1) % FRAMES.length;
|
|
82267
|
+
this.render();
|
|
82268
|
+
}, 80);
|
|
82269
|
+
}
|
|
82270
|
+
// Update the current stage (e.g. "Generating site with Claude…").
|
|
82271
|
+
update(stage) {
|
|
82272
|
+
this.stage = stage;
|
|
82273
|
+
if (!this.tty) {
|
|
82274
|
+
say(c.dim(` \u2026 ${stage}`));
|
|
82275
|
+
return;
|
|
82276
|
+
}
|
|
82277
|
+
this.render();
|
|
82278
|
+
}
|
|
82279
|
+
render() {
|
|
82280
|
+
const spin = c.cyan(FRAMES[this.frame]);
|
|
82281
|
+
const stage = this.stage ? c.dim(` \xB7 ${this.stage}`) : "";
|
|
82282
|
+
process.stdout.write(`\r\x1B[2K ${spin} ${this.label}${stage}`);
|
|
82283
|
+
}
|
|
82284
|
+
// Stop with a terminal state, leaving one clean line behind.
|
|
82285
|
+
done(ok, finalLabel) {
|
|
82286
|
+
if (this.timer) {
|
|
82287
|
+
clearInterval(this.timer);
|
|
82288
|
+
this.timer = null;
|
|
82289
|
+
}
|
|
82290
|
+
const label = finalLabel ?? this.label;
|
|
82291
|
+
const mark = ok ? c.green("\u2713") : c.red("\u2717");
|
|
82292
|
+
if (this.tty) process.stdout.write(`\r\x1B[2K ${mark} ${label}
|
|
82293
|
+
`);
|
|
82294
|
+
else say(` ${mark} ${label}`);
|
|
82295
|
+
}
|
|
82296
|
+
};
|
|
82239
82297
|
|
|
82240
82298
|
// src/onboarding.ts
|
|
82241
82299
|
async function onboardLicense(force) {
|
|
@@ -82286,6 +82344,13 @@ async function runOnboarding(force = false) {
|
|
|
82286
82344
|
}
|
|
82287
82345
|
say();
|
|
82288
82346
|
}
|
|
82347
|
+
const anthropicKey = getSetting("anthropic_key");
|
|
82348
|
+
if (anthropicKey) {
|
|
82349
|
+
try {
|
|
82350
|
+
await refreshModels(anthropicKey);
|
|
82351
|
+
} catch {
|
|
82352
|
+
}
|
|
82353
|
+
}
|
|
82289
82354
|
const stillMissing = missingRequiredKeys();
|
|
82290
82355
|
if (stillMissing.length > 0) {
|
|
82291
82356
|
say(c.amber(` Still missing: ${stillMissing.map((m) => m.label).join(", ")}.`));
|
|
@@ -82529,12 +82594,14 @@ async function runTurn(userMessage) {
|
|
|
82529
82594
|
const history = loadHistory().slice(0, -1);
|
|
82530
82595
|
const confirmations = {};
|
|
82531
82596
|
const completedResults = {};
|
|
82597
|
+
const status = new Status();
|
|
82598
|
+
let statusActive = false;
|
|
82532
82599
|
let lastProgress = "";
|
|
82533
|
-
const emit = (
|
|
82600
|
+
const emit = (_channel, payload) => {
|
|
82534
82601
|
const p = payload;
|
|
82535
82602
|
if (p?.msg && p.msg !== lastProgress) {
|
|
82536
82603
|
lastProgress = p.msg;
|
|
82537
|
-
|
|
82604
|
+
if (statusActive) status.update(p.msg);
|
|
82538
82605
|
}
|
|
82539
82606
|
};
|
|
82540
82607
|
const invokeIpc = makeInvokeIpc(emit);
|
|
@@ -82553,11 +82620,15 @@ async function runTurn(userMessage) {
|
|
|
82553
82620
|
const t = e.data;
|
|
82554
82621
|
if (t.status === "pending" && !seenRunning.has(t.id)) {
|
|
82555
82622
|
seenRunning.add(t.id);
|
|
82556
|
-
|
|
82623
|
+
lastProgress = "";
|
|
82624
|
+
status.start(labelFor(t));
|
|
82625
|
+
statusActive = true;
|
|
82557
82626
|
} else if (t.status === "completed") {
|
|
82558
|
-
|
|
82627
|
+
status.done(true, labelFor(t));
|
|
82628
|
+
statusActive = false;
|
|
82559
82629
|
} else if (t.status === "error") {
|
|
82560
|
-
|
|
82630
|
+
status.done(false, `${labelFor(t)} \u2014 ${t.error ?? "failed"}`);
|
|
82631
|
+
statusActive = false;
|
|
82561
82632
|
}
|
|
82562
82633
|
}
|
|
82563
82634
|
},
|
|
@@ -82576,6 +82647,10 @@ async function runTurn(userMessage) {
|
|
|
82576
82647
|
if (ranSomething) autoSync();
|
|
82577
82648
|
return;
|
|
82578
82649
|
}
|
|
82650
|
+
if (statusActive) {
|
|
82651
|
+
status.done(false, "paused for confirmation");
|
|
82652
|
+
statusActive = false;
|
|
82653
|
+
}
|
|
82579
82654
|
say();
|
|
82580
82655
|
say(c.amber(` ${pending.length} action${pending.length === 1 ? "" : "s"} need confirmation:`));
|
|
82581
82656
|
for (const t of pending) {
|
|
@@ -82651,6 +82726,47 @@ async function notifyIfOutdated() {
|
|
|
82651
82726
|
}
|
|
82652
82727
|
}
|
|
82653
82728
|
|
|
82729
|
+
// src/models-cmd.ts
|
|
82730
|
+
async function runModels() {
|
|
82731
|
+
const apiKey = getSetting("anthropic_key");
|
|
82732
|
+
if (!apiKey) {
|
|
82733
|
+
say(c.red(" No Anthropic key set. Run 'sproutkit setup' first."));
|
|
82734
|
+
return;
|
|
82735
|
+
}
|
|
82736
|
+
say(c.dim(" Fetching your available models from Anthropic\u2026"));
|
|
82737
|
+
let models2 = listCachedModels();
|
|
82738
|
+
try {
|
|
82739
|
+
models2 = await refreshModels(apiKey);
|
|
82740
|
+
} catch (e) {
|
|
82741
|
+
say(c.amber(` Couldn't refresh from the API (${e.message}).`));
|
|
82742
|
+
say(c.dim(" Showing the last known list instead."));
|
|
82743
|
+
}
|
|
82744
|
+
if (models2.length === 0) {
|
|
82745
|
+
say(c.red(" No models returned. Check your Anthropic key and connection."));
|
|
82746
|
+
return;
|
|
82747
|
+
}
|
|
82748
|
+
const current = getPreferredModel();
|
|
82749
|
+
say();
|
|
82750
|
+
say(c.bold(" Available models:"));
|
|
82751
|
+
models2.forEach((m, i) => {
|
|
82752
|
+
const active = m.id === current ? c.green(" \u2190 current") : "";
|
|
82753
|
+
say(` ${c.greenBold(String(i + 1).padStart(2))} ${m.display_name ?? m.id} ${c.dim(m.id)}${active}`);
|
|
82754
|
+
});
|
|
82755
|
+
say();
|
|
82756
|
+
const pick = await ask(c.green(" Pick a number to switch (or Enter to keep current): "));
|
|
82757
|
+
if (!pick) {
|
|
82758
|
+
say(c.dim(" Kept current model."));
|
|
82759
|
+
return;
|
|
82760
|
+
}
|
|
82761
|
+
const idx = Number(pick) - 1;
|
|
82762
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= models2.length) {
|
|
82763
|
+
say(c.amber(" Not a valid choice \u2014 no change made."));
|
|
82764
|
+
return;
|
|
82765
|
+
}
|
|
82766
|
+
setSetting("claude_model", models2[idx].id);
|
|
82767
|
+
say(c.green(` \u2713 Now using ${models2[idx].display_name ?? models2[idx].id}.`));
|
|
82768
|
+
}
|
|
82769
|
+
|
|
82654
82770
|
// src/index.ts
|
|
82655
82771
|
process.env.SPROUTKIT_HEADLESS = "1";
|
|
82656
82772
|
async function main() {
|
|
@@ -82666,6 +82782,11 @@ async function main() {
|
|
|
82666
82782
|
closeTty();
|
|
82667
82783
|
return;
|
|
82668
82784
|
}
|
|
82785
|
+
if (arg === "models") {
|
|
82786
|
+
await runModels();
|
|
82787
|
+
closeTty();
|
|
82788
|
+
return;
|
|
82789
|
+
}
|
|
82669
82790
|
if (arg === "sync") {
|
|
82670
82791
|
const r = syncToDesktop();
|
|
82671
82792
|
if (!r.ok && r.reason === "no_desktop_db") {
|
|
@@ -82687,6 +82808,7 @@ async function main() {
|
|
|
82687
82808
|
say();
|
|
82688
82809
|
say(` ${c.bold("sproutkit")} start the chat`);
|
|
82689
82810
|
say(` ${c.bold("sproutkit setup")} set or update your keys and licence`);
|
|
82811
|
+
say(` ${c.bold("sproutkit models")} list Claude models and pick one`);
|
|
82690
82812
|
say(` ${c.bold("sproutkit sync")} push your leads into the desktop app`);
|
|
82691
82813
|
say(` ${c.bold("sproutkit update")} update to the latest version`);
|
|
82692
82814
|
say(` ${c.bold("sproutkit version")} show the installed version`);
|
|
@@ -82715,6 +82837,8 @@ async function main() {
|
|
|
82715
82837
|
closeTty();
|
|
82716
82838
|
return;
|
|
82717
82839
|
}
|
|
82840
|
+
await refreshIfStale(getSetting("anthropic_key")).catch(() => {
|
|
82841
|
+
});
|
|
82718
82842
|
await notifyIfOutdated();
|
|
82719
82843
|
say(c.dim(" Chat with Sproutkit. Type a request, or 'exit' to quit."));
|
|
82720
82844
|
say();
|