sproutkit-code 0.7.0 → 0.8.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.
Files changed (2) hide show
  1. package/dist/index.js +133 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35355,21 +35355,21 @@ var require_cross_spawn = __commonJS({
35355
35355
  var cp = require("child_process");
35356
35356
  var parse = require_parse();
35357
35357
  var enoent = require_enoent();
35358
- function spawn(command, args, options) {
35358
+ function spawn2(command, args, options) {
35359
35359
  const parsed = parse(command, args, options);
35360
35360
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
35361
35361
  enoent.hookChildProcess(spawned, parsed);
35362
35362
  return spawned;
35363
35363
  }
35364
- function spawnSync2(command, args, options) {
35364
+ function spawnSync3(command, args, options) {
35365
35365
  const parsed = parse(command, args, options);
35366
35366
  const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
35367
35367
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
35368
35368
  return result;
35369
35369
  }
35370
- module2.exports = spawn;
35371
- module2.exports.spawn = spawn;
35372
- module2.exports.sync = spawnSync2;
35370
+ module2.exports = spawn2;
35371
+ module2.exports.spawn = spawn2;
35372
+ module2.exports.sync = spawnSync3;
35373
35373
  module2.exports._parse = parse;
35374
35374
  module2.exports._enoent = enoent;
35375
35375
  }
@@ -82456,7 +82456,7 @@ var require_package = __commonJS({
82456
82456
  "package.json"(exports2, module2) {
82457
82457
  module2.exports = {
82458
82458
  name: "sproutkit-code",
82459
- version: "0.7.0",
82459
+ version: "0.8.0",
82460
82460
  description: "Sproutkit in your terminal \u2014 find leads, build sites, run outreach, all via chat.",
82461
82461
  bin: {
82462
82462
  sproutkit: "./dist/index.js"
@@ -83740,8 +83740,108 @@ async function cmdBuildAll(argv) {
83740
83740
  });
83741
83741
  }
83742
83742
 
83743
+ // src/claude-bridge.ts
83744
+ var import_child_process3 = require("child_process");
83745
+ function runClaudeTurn(args) {
83746
+ const { message, sessionId, write } = args;
83747
+ const timeoutMs = args.timeoutMs ?? 6e5;
83748
+ const cliArgs = [
83749
+ "-p",
83750
+ "--output-format",
83751
+ "stream-json",
83752
+ "--include-partial-messages",
83753
+ "--verbose",
83754
+ // required for stream_event emission
83755
+ // Let Claude drive the sproutkit CLI without hanging on a permission
83756
+ // prompt, but ONLY the sproutkit command — nothing else runs unattended.
83757
+ "--allowedTools",
83758
+ "Bash(sproutkit *)"
83759
+ ];
83760
+ if (sessionId) cliArgs.push("--resume", sessionId);
83761
+ return new Promise((resolve) => {
83762
+ let child;
83763
+ try {
83764
+ child = (0, import_child_process3.spawn)(claudeBin(), cliArgs, { stdio: ["pipe", "pipe", "pipe"] });
83765
+ } catch (e) {
83766
+ resolve({ sessionId, ok: false, error: e.message });
83767
+ return;
83768
+ }
83769
+ let buf = "";
83770
+ let newSessionId = sessionId;
83771
+ let sawText = false;
83772
+ let settled = false;
83773
+ let stderr = "";
83774
+ const timer = setTimeout(() => {
83775
+ if (settled) return;
83776
+ settled = true;
83777
+ child.kill("SIGKILL");
83778
+ resolve({ sessionId: newSessionId, ok: false, error: `Timed out after ${Math.round(timeoutMs / 1e3)}s.` });
83779
+ }, timeoutMs);
83780
+ child.stdout.on("data", (d) => {
83781
+ buf += d.toString();
83782
+ let nl;
83783
+ while ((nl = buf.indexOf("\n")) >= 0) {
83784
+ const line = buf.slice(0, nl).trim();
83785
+ buf = buf.slice(nl + 1);
83786
+ if (!line) continue;
83787
+ let ev;
83788
+ try {
83789
+ ev = JSON.parse(line);
83790
+ } catch {
83791
+ continue;
83792
+ }
83793
+ if (ev.session_id) newSessionId = ev.session_id;
83794
+ if (ev.type === "stream_event" && ev.event?.delta?.type === "text_delta" && typeof ev.event.delta.text === "string") {
83795
+ sawText = true;
83796
+ write(ev.event.delta.text);
83797
+ }
83798
+ if (ev.type === "result" && !sawText && typeof ev.result === "string") {
83799
+ write(ev.result);
83800
+ }
83801
+ }
83802
+ });
83803
+ child.stderr.on("data", (d) => stderr += d.toString());
83804
+ child.on("error", (e) => {
83805
+ if (settled) return;
83806
+ settled = true;
83807
+ clearTimeout(timer);
83808
+ const msg = e.code === "ENOENT" ? `Claude Code CLI not found. Install it and run 'claude /login'.` : `Failed to run Claude Code: ${e.message}`;
83809
+ resolve({ sessionId: newSessionId, ok: false, error: msg });
83810
+ });
83811
+ child.on("close", (code) => {
83812
+ if (settled) return;
83813
+ settled = true;
83814
+ clearTimeout(timer);
83815
+ if (code !== 0 && !sawText) {
83816
+ resolve({
83817
+ sessionId: newSessionId,
83818
+ ok: false,
83819
+ error: stderr.trim() || `Claude Code exited with code ${code}.`
83820
+ });
83821
+ } else {
83822
+ resolve({ sessionId: newSessionId, ok: true });
83823
+ }
83824
+ });
83825
+ child.stdin.write(message);
83826
+ child.stdin.end();
83827
+ });
83828
+ }
83829
+
83743
83830
  // src/index.ts
83831
+ var import_child_process4 = require("child_process");
83744
83832
  process.env.SPROUTKIT_HEADLESS = "1";
83833
+ function claudePresent() {
83834
+ try {
83835
+ const bin = process.env.SPROUTKIT_CLAUDE_BIN || "claude";
83836
+ return (0, import_child_process4.spawnSync)(bin, ["--version"], { stdio: "ignore", timeout: 1e4 }).status === 0;
83837
+ } catch {
83838
+ return false;
83839
+ }
83840
+ }
83841
+ function useClaudeBridge() {
83842
+ if (getBackend() === "claude_code") return true;
83843
+ return claudePresent() && !getSetting("anthropic_key");
83844
+ }
83745
83845
  async function main() {
83746
83846
  const arg = process.argv[2];
83747
83847
  initDatabase();
@@ -83831,23 +83931,47 @@ async function main() {
83831
83931
  closeTty();
83832
83932
  return;
83833
83933
  }
83934
+ const bridged = useClaudeBridge();
83834
83935
  const oneShot = process.argv.slice(2).join(" ").trim();
83835
83936
  if (oneShot) {
83836
- await runTurn(oneShot);
83937
+ if (bridged) {
83938
+ const r = await runClaudeTurn({ message: oneShot, sessionId: null, write: (t) => process.stdout.write(t) });
83939
+ say();
83940
+ if (!r.ok) say(c.red(` ${r.error ?? "Claude Code failed."}`));
83941
+ } else {
83942
+ await runTurn(oneShot);
83943
+ }
83837
83944
  closeTty();
83838
83945
  return;
83839
83946
  }
83840
83947
  await refreshIfStale(getSetting("anthropic_key")).catch(() => {
83841
83948
  });
83842
83949
  await notifyIfOutdated();
83843
- say(c.dim(" Chat with Sproutkit. Type a request, or 'exit' to quit."));
83950
+ if (bridged && !skillInstalled()) {
83951
+ say(c.amber(" Tip: run 'sproutkit setup' to install the Sproutkit skill so Claude can find/build/book for you."));
83952
+ }
83953
+ say(
83954
+ bridged ? c.dim(" Talk to Sproutkit (powered by your Claude subscription). Type a request, or 'exit'.") : c.dim(" Chat with Sproutkit. Type a request, or 'exit' to quit.")
83955
+ );
83844
83956
  say();
83957
+ let claudeSession = null;
83845
83958
  while (true) {
83846
83959
  const line = await ask(c.greenBold("sproutkit \u203A "));
83847
83960
  if (!line) continue;
83848
83961
  if (line === "exit" || line === "quit") break;
83849
83962
  try {
83850
- await runTurn(line);
83963
+ if (bridged) {
83964
+ const r = await runClaudeTurn({
83965
+ message: line,
83966
+ sessionId: claudeSession,
83967
+ write: (t) => process.stdout.write(t)
83968
+ });
83969
+ say();
83970
+ if (r.sessionId) claudeSession = r.sessionId;
83971
+ if (!r.ok) say(c.red(` ${r.error ?? "Claude Code failed."}`));
83972
+ } else {
83973
+ await runTurn(line);
83974
+ }
83851
83975
  } catch (e) {
83852
83976
  say(c.red(` Error: ${e.message}`));
83853
83977
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sproutkit-code",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
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"