buildwithnexus 0.8.6 → 0.8.8

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/bin.js CHANGED
@@ -1229,8 +1229,6 @@ var TUI = class {
1229
1229
  );
1230
1230
  }
1231
1231
  displayBrainstormResponse(response) {
1232
- console.log("");
1233
- console.log(chalk.blue.bold("\u{1F4A1} Ideas & Analysis"));
1234
1232
  console.log("");
1235
1233
  const lines = response.split("\n");
1236
1234
  for (const line of lines) {
@@ -1607,10 +1605,25 @@ init_secrets();
1607
1605
  init_docker();
1608
1606
 
1609
1607
  // src/core/version.ts
1610
- var resolvedVersion = true ? "0.8.6" : pkg.version;
1608
+ var resolvedVersion = true ? "0.8.8" : pkg.version;
1611
1609
 
1612
1610
  // src/cli/interactive.ts
1613
1611
  var appVersion = resolvedVersion;
1612
+ var SSE_STALL_WARNING_MS = 8e3;
1613
+ async function reportBackendError(label, response) {
1614
+ let bodySnippet = "";
1615
+ try {
1616
+ const text = await response.text();
1617
+ bodySnippet = text.slice(0, 300);
1618
+ } catch {
1619
+ bodySnippet = "(could not read response body)";
1620
+ }
1621
+ console.error(chalk3.red(`${label}: HTTP ${response.status} ${response.statusText}`));
1622
+ if (bodySnippet) {
1623
+ console.error(chalk3.gray(` body: ${bodySnippet}`));
1624
+ }
1625
+ console.error(chalk3.gray(" Tip: stream backend logs with `buildwithnexus logs -f`"));
1626
+ }
1614
1627
  async function interactiveMode() {
1615
1628
  const backendUrl = process.env.BACKEND_URL || "http://localhost:4200";
1616
1629
  const urlCheck = validateBackendUrl(backendUrl);
@@ -1784,7 +1797,7 @@ async function planModeLoop(task, backendUrl, currentMode, ask) {
1784
1797
  signal: AbortSignal.timeout(12e4)
1785
1798
  });
1786
1799
  if (!response.ok) {
1787
- console.error(chalk3.red("Backend error \u2014 cannot fetch plan."));
1800
+ await reportBackendError("Backend error fetching plan", response);
1788
1801
  return "cancel";
1789
1802
  }
1790
1803
  const planText = await response.text();
@@ -1808,27 +1821,36 @@ async function planModeLoop(task, backendUrl, currentMode, ask) {
1808
1821
  tui.displayConnected(run_id);
1809
1822
  const streamResponse = await fetch(`${backendUrl}/api/stream/${run_id}`, { signal: AbortSignal.timeout(12e4) });
1810
1823
  if (!streamResponse.ok) {
1811
- console.error(chalk3.red(`Stream endpoint returned ${streamResponse.status}`));
1824
+ await reportBackendError("Stream endpoint error", streamResponse);
1812
1825
  return "cancel";
1813
1826
  }
1814
1827
  const reader = streamResponse.body?.getReader();
1815
1828
  if (!reader) throw new Error("No response body");
1816
1829
  let planReceived = false;
1817
- for await (const parsed of parseSSEStream(reader)) {
1818
- if (parsed.type === "plan") {
1819
- steps = parsed.data["steps"] || [];
1820
- planReceived = true;
1821
- reader.cancel();
1822
- break;
1823
- } else if (parsed.type === "error") {
1824
- const errorMsg = parsed.data["error"] || parsed.data["content"] || "Unknown error";
1825
- tui.displayError(errorMsg);
1826
- reader.cancel();
1827
- return "cancel";
1830
+ const stallTimer = setTimeout(() => {
1831
+ console.log(chalk3.gray(`(no events from backend after ${SSE_STALL_WARNING_MS / 1e3}s \u2014 backend may be stalled; check \`buildwithnexus logs -f\`)`));
1832
+ }, SSE_STALL_WARNING_MS);
1833
+ try {
1834
+ for await (const parsed of parseSSEStream(reader)) {
1835
+ if (parsed.type === "plan") {
1836
+ steps = parsed.data["steps"] || [];
1837
+ planReceived = true;
1838
+ reader.cancel();
1839
+ break;
1840
+ } else if (parsed.type === "error") {
1841
+ const errorMsg = parsed.data["error"] || parsed.data["content"] || "Unknown error";
1842
+ tui.displayError(errorMsg);
1843
+ reader.cancel();
1844
+ return "cancel";
1845
+ }
1828
1846
  }
1847
+ } finally {
1848
+ clearTimeout(stallTimer);
1829
1849
  }
1830
1850
  if (!planReceived || steps.length === 0) {
1831
1851
  console.log(chalk3.yellow("No plan received from backend."));
1852
+ console.log(chalk3.gray(" This usually means the backend exited without emitting a plan event."));
1853
+ console.log(chalk3.gray(" Check `buildwithnexus logs -f` for the underlying error."));
1832
1854
  steps = ["(no steps returned \u2014 execute anyway?)"];
1833
1855
  }
1834
1856
  } catch (err) {
@@ -1843,7 +1865,7 @@ async function planModeLoop(task, backendUrl, currentMode, ask) {
1843
1865
  if (answer === "" || answer === "y") {
1844
1866
  return "BUILD";
1845
1867
  }
1846
- if (answer === "n" || answer === "\x1B") {
1868
+ if (answer === "n" || answer === "") {
1847
1869
  console.log(chalk3.yellow("\nExecution cancelled.\n"));
1848
1870
  return "cancel";
1849
1871
  }
@@ -1895,7 +1917,7 @@ async function buildModeLoop(task, backendUrl, currentMode, ask) {
1895
1917
  signal: AbortSignal.timeout(12e4)
1896
1918
  });
1897
1919
  if (!response.ok) {
1898
- console.error(chalk3.red("Backend error"));
1920
+ await reportBackendError("Backend error starting run", response);
1899
1921
  return "done";
1900
1922
  }
1901
1923
  const buildText = await response.text();
@@ -1921,30 +1943,45 @@ async function buildModeLoop(task, backendUrl, currentMode, ask) {
1921
1943
  tui.displayStreamStart();
1922
1944
  const streamResponse = await fetch(`${backendUrl}/api/stream/${run_id}`, { signal: AbortSignal.timeout(12e4) });
1923
1945
  if (!streamResponse.ok) {
1924
- console.error(chalk3.red(`Stream endpoint returned ${streamResponse.status}`));
1946
+ await reportBackendError("Stream endpoint error", streamResponse);
1925
1947
  return "done";
1926
1948
  }
1927
1949
  const reader = streamResponse.body?.getReader();
1928
1950
  if (!reader) throw new Error("No response body");
1929
- for await (const parsed of parseSSEStream(reader)) {
1930
- const type = parsed.type;
1931
- if (type === "execution_complete") {
1932
- const summary = parsed.data["summary"] || "";
1933
- const count = parsed.data["todos_completed"] || 0;
1934
- tui.displayResults(summary, count);
1935
- tui.displayComplete(tui.getElapsedTime());
1936
- break;
1937
- } else if (type === "done") {
1938
- tui.displayEvent(type, { content: "Task completed successfully" });
1939
- tui.displayComplete(tui.getElapsedTime());
1940
- break;
1941
- } else if (type === "error") {
1942
- const errorMsg = parsed.data["error"] || parsed.data["content"] || "Unknown error";
1943
- tui.displayError(errorMsg);
1944
- break;
1945
- } else if (type !== "plan") {
1946
- tui.displayEvent(type, parsed.data);
1951
+ let sawTerminal = false;
1952
+ const stallTimer = setTimeout(() => {
1953
+ console.log(chalk3.gray(`(no events from backend after ${SSE_STALL_WARNING_MS / 1e3}s \u2014 backend may be stalled; check \`buildwithnexus logs -f\`)`));
1954
+ }, SSE_STALL_WARNING_MS);
1955
+ try {
1956
+ for await (const parsed of parseSSEStream(reader)) {
1957
+ const type = parsed.type;
1958
+ if (type === "execution_complete") {
1959
+ const summary = parsed.data["summary"] || "";
1960
+ const count = parsed.data["todos_completed"] || 0;
1961
+ tui.displayResults(summary, count);
1962
+ tui.displayComplete(tui.getElapsedTime());
1963
+ sawTerminal = true;
1964
+ break;
1965
+ } else if (type === "done") {
1966
+ tui.displayEvent(type, { content: "Task completed successfully" });
1967
+ tui.displayComplete(tui.getElapsedTime());
1968
+ sawTerminal = true;
1969
+ break;
1970
+ } else if (type === "error") {
1971
+ const errorMsg = parsed.data["error"] || parsed.data["content"] || "Unknown error";
1972
+ tui.displayError(errorMsg);
1973
+ sawTerminal = true;
1974
+ break;
1975
+ } else if (type !== "plan") {
1976
+ tui.displayEvent(type, parsed.data);
1977
+ }
1947
1978
  }
1979
+ } finally {
1980
+ clearTimeout(stallTimer);
1981
+ }
1982
+ if (!sawTerminal) {
1983
+ console.log(chalk3.yellow("Stream ended without a terminal event (no execution_complete / done / error)."));
1984
+ console.log(chalk3.gray(" The backend likely crashed mid-run. Check `buildwithnexus logs -f`."));
1948
1985
  }
1949
1986
  } catch (err) {
1950
1987
  const msg = err instanceof Error ? err.message : String(err);
@@ -1974,7 +2011,9 @@ async function brainstormModeLoop(task, backendUrl, currentMode, ask) {
1974
2011
  )),
1975
2012
  signal: AbortSignal.timeout(12e4)
1976
2013
  });
1977
- if (response.ok) {
2014
+ if (!response.ok) {
2015
+ await reportBackendError("Backend error in brainstorm", response);
2016
+ } else {
1978
2017
  const brainstormText = await response.text();
1979
2018
  let brainstormParsed;
1980
2019
  try {
@@ -1995,7 +2034,7 @@ async function brainstormModeLoop(task, backendUrl, currentMode, ask) {
1995
2034
  const run_id = brainstormRunId;
1996
2035
  const streamResponse = await fetch(`${backendUrl}/api/stream/${run_id}`, { signal: AbortSignal.timeout(12e4) });
1997
2036
  if (!streamResponse.ok) {
1998
- console.error(chalk3.red(`Stream endpoint returned ${streamResponse.status}`));
2037
+ await reportBackendError("Stream endpoint error", streamResponse);
1999
2038
  continue;
2000
2039
  }
2001
2040
  const reader = streamResponse.body?.getReader();
@@ -2005,50 +2044,55 @@ async function brainstormModeLoop(task, backendUrl, currentMode, ask) {
2005
2044
  }
2006
2045
  let responseText = "";
2007
2046
  let firstEvent = true;
2008
- for await (const parsed of parseSSEStream(reader)) {
2009
- const type = parsed.type;
2010
- const data = parsed.data;
2011
- if (firstEvent && type !== "done" && type !== "error") {
2012
- console.log(chalk3.bold.blue("\u{1F4AD} Thinking...\n"));
2013
- firstEvent = false;
2014
- }
2015
- if (type === "done" || type === "execution_complete" || type === "final_result") {
2016
- const summary = data["summary"] || data["result"] || "";
2017
- if (summary) responseText = summary;
2018
- break;
2019
- } else if (type === "error") {
2020
- const errorMsg = data["error"] || data["content"] || "Unknown error";
2021
- responseText += errorMsg + "\n";
2022
- break;
2023
- } else if (type === "thought" || type === "observation") {
2024
- const content = data["content"] || "";
2025
- if (content) {
2026
- console.log(chalk3.gray("\u2192 " + content));
2027
- responseText += content + "\n";
2047
+ const stallTimer = setTimeout(() => {
2048
+ console.log(chalk3.gray(`(no events from backend after ${SSE_STALL_WARNING_MS / 1e3}s \u2014 backend may be stalled; check \`buildwithnexus logs -f\`)`));
2049
+ }, SSE_STALL_WARNING_MS);
2050
+ try {
2051
+ for await (const parsed of parseSSEStream(reader)) {
2052
+ const type = parsed.type;
2053
+ const data = parsed.data;
2054
+ if (firstEvent && type !== "done" && type !== "error") {
2055
+ console.log(chalk3.bold.blue("\u{1F4AD} Thinking...\n"));
2056
+ firstEvent = false;
2028
2057
  }
2029
- } else if (type === "agent_response" || type === "agent_result") {
2030
- const content = data["content"] || data["result"] || "";
2031
- if (content) responseText += content + "\n";
2032
- } else if (type === "action") {
2033
- const content = data["content"] || "";
2034
- if (content) {
2035
- console.log(chalk3.cyan("\u2699\uFE0F " + content));
2036
- responseText += content + "\n";
2058
+ if (type === "done" || type === "execution_complete" || type === "final_result") {
2059
+ const summary = data["summary"] || data["result"] || "";
2060
+ if (summary) responseText = summary;
2061
+ break;
2062
+ } else if (type === "error") {
2063
+ const errorMsg = data["error"] || data["content"] || "Unknown error";
2064
+ responseText += errorMsg + "\n";
2065
+ break;
2066
+ } else if (type === "thought" || type === "observation") {
2067
+ const content = data["content"] || "";
2068
+ if (content) {
2069
+ console.log(chalk3.gray("\u2192 " + content));
2070
+ responseText += content + "\n";
2071
+ }
2072
+ } else if (type === "agent_response" || type === "agent_result") {
2073
+ const content = data["content"] || data["result"] || "";
2074
+ if (content) responseText += content + "\n";
2075
+ } else if (type === "action") {
2076
+ const content = data["content"] || "";
2077
+ if (content) {
2078
+ console.log(chalk3.cyan("\u2699\uFE0F " + content));
2079
+ responseText += content + "\n";
2080
+ }
2081
+ } else if (type === "agent_working" || type === "started") {
2082
+ } else if (type !== "plan") {
2083
+ const content = data["content"] || data["response"] || "";
2084
+ if (content) responseText += content + "\n";
2037
2085
  }
2038
- } else if (type === "agent_working" || type === "started") {
2039
- } else if (type !== "plan") {
2040
- const content = data["content"] || data["response"] || "";
2041
- if (content) responseText += content + "\n";
2042
2086
  }
2087
+ } finally {
2088
+ clearTimeout(stallTimer);
2043
2089
  }
2044
2090
  console.log("");
2045
2091
  if (responseText.trim()) {
2046
2092
  tui.displayBrainstormResponse(responseText.trim());
2047
2093
  } else {
2048
- console.log(chalk3.gray("(No response received from agent)"));
2094
+ console.log(chalk3.gray("(No response received from agent \u2014 check `buildwithnexus logs -f`)"));
2049
2095
  }
2050
- } else {
2051
- console.log(chalk3.red("Could not reach backend for brainstorm response."));
2052
2096
  }
2053
2097
  } catch (err) {
2054
2098
  const msg = err instanceof Error ? err.message : String(err);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buildwithnexus",
3
- "version": "0.8.6",
3
+ "version": "0.8.8",
4
4
  "description": "Interactive AI agent orchestrator with intent-based planning, execution, and brainstorming modes",
5
5
  "type": "module",
6
6
  "bin": {