@vendian/cli 0.0.24 → 0.0.26

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/cli-wrapper.mjs +172 -24
  2. package/package.json +1 -1
package/cli-wrapper.mjs CHANGED
@@ -1107,7 +1107,7 @@ import path8 from "node:path";
1107
1107
  import readlinePromises from "node:readline/promises";
1108
1108
 
1109
1109
  // src/version.js
1110
- var CLI_VERSION = true ? "0.0.24" : process.env.npm_package_version || "0.0.0-dev";
1110
+ var CLI_VERSION = true ? "0.0.26" : process.env.npm_package_version || "0.0.0-dev";
1111
1111
 
1112
1112
  // src/npm-update.js
1113
1113
  var NPM_CHECK_INTERVAL_MS = 30 * 60 * 1e3;
@@ -1383,6 +1383,10 @@ function serveProcessExitMessage({ stderr = "", code = 0, signal = "" } = {}) {
1383
1383
  }
1384
1384
  return "";
1385
1385
  }
1386
+ function serveProcessExitStderrTail(stderr = "", limit = 1200) {
1387
+ const text = String(stderr || "").trim();
1388
+ return text.length > limit ? text.slice(-limit) : text;
1389
+ }
1386
1390
  function applyServeEvent(state, event) {
1387
1391
  if (!event || typeof event.type !== "string") {
1388
1392
  return state;
@@ -1443,6 +1447,14 @@ function applyServeEvent(state, event) {
1443
1447
  activity: `Dispatch acknowledged for run ${stringValue(event.runId || event.sessionId || "unknown")}`
1444
1448
  };
1445
1449
  }
1450
+ if (event.type === "daemon_stderr") {
1451
+ const message = stringValue(event.message || event.stderr || "Daemon wrote to stderr");
1452
+ return {
1453
+ ...next,
1454
+ activity: `Daemon stderr: ${message}`,
1455
+ errors: looksLikeError(message) ? appendError(state.errors, "Local daemon stderr", message) : state.errors
1456
+ };
1457
+ }
1446
1458
  if (event.type === "agent_discovery_started") {
1447
1459
  return {
1448
1460
  ...next,
@@ -1648,6 +1660,9 @@ function applyServeEvent(state, event) {
1648
1660
  }
1649
1661
  return next;
1650
1662
  }
1663
+ function serveDebugEntries(logs = [], maxLines = 8) {
1664
+ return (logs || []).map(serveDebugEntry).filter(Boolean).slice(-maxLines);
1665
+ }
1651
1666
  function appendLog(logs, event) {
1652
1667
  return [...logs, event].slice(-200);
1653
1668
  }
@@ -1890,6 +1905,89 @@ function agentRuntimeStatus(agent, agentRunState = {}) {
1890
1905
  function appendError(errors, scope, message) {
1891
1906
  return [...errors, { scope, message: stringValue(message) }].slice(-20);
1892
1907
  }
1908
+ function serveDebugEntry(event) {
1909
+ if (!event || typeof event !== "object") return null;
1910
+ const type = stringValue(event.type);
1911
+ const timestamp = event.timestamp || event.occurredAt || (/* @__PURE__ */ new Date()).toISOString();
1912
+ const base = { timestamp, eventType: type, level: debugLevel(event) };
1913
+ switch (type) {
1914
+ case "workspace_resolved":
1915
+ return { ...base, message: `workspace resolved collection=${stringValue(event.collectionId || "unknown")}` };
1916
+ case "daemon_registered":
1917
+ return { ...base, message: `daemon registered daemon=${shortId(event.daemonId)} cli=${shortId(event.cliSessionId)}` };
1918
+ case "daemon_event_stream_connected":
1919
+ return { ...base, message: `daemon event stream connected daemon=${shortId(event.daemonId)}` };
1920
+ case "daemon_event_stream_lost":
1921
+ return { ...base, level: "warn", message: `daemon event stream lost retry=${formatSeconds(event.retryInSeconds)} error=${stringValue(event.error || "unknown")}` };
1922
+ case "daemon_wake_received":
1923
+ return {
1924
+ ...base,
1925
+ message: [
1926
+ `wake received source=${stringValue(event.sourceEventType || "backend")}`,
1927
+ event.eventType ? `event=${stringValue(event.eventType)}` : "",
1928
+ event.sessionId ? `session=${shortId(event.sessionId)}` : "",
1929
+ event.runId ? `run=${shortId(event.runId)}` : "",
1930
+ event.localAgentRowId ? `agentRow=${shortId(event.localAgentRowId)}` : ""
1931
+ ].filter(Boolean).join(" ")
1932
+ };
1933
+ case "lease_claim_no_job":
1934
+ return {
1935
+ ...base,
1936
+ level: "warn",
1937
+ message: `lease claim returned no job stream=${boolText(event.streamConnected)} wake=${boolText(event.wakeRequested)} wait=${Number(event.waitSeconds ?? 0)}s`
1938
+ };
1939
+ case "dispatch_job_received":
1940
+ return {
1941
+ ...base,
1942
+ message: `dispatch received delivery=${shortId(event.deliveryId)} run=${shortId(event.runId || event.sessionId)} attempt=${shortId(event.attemptId)}`
1943
+ };
1944
+ case "dispatch_job_acked":
1945
+ return {
1946
+ ...base,
1947
+ message: `dispatch acked delivery=${shortId(event.deliveryId)} run=${shortId(event.runId || event.sessionId)} attempt=${shortId(event.attemptId)}`
1948
+ };
1949
+ case "job_started":
1950
+ return { ...base, message: `job started type=${stringValue(event.jobType || "run")} run=${shortId(event.runId || event.sessionId || event.deployRequestId || event.testRunId)}` };
1951
+ case "job_completed":
1952
+ return {
1953
+ ...base,
1954
+ level: event.success === false ? "error" : "info",
1955
+ message: `job completed success=${event.success !== false} run=${shortId(event.runId || event.sessionId || event.deployRequestId || event.testRunId)}${event.error ? ` error=${formatErrorMessage(event.error)}` : ""}`
1956
+ };
1957
+ case "backend_connection_lost":
1958
+ return { ...base, level: "warn", message: `backend connection lost activity=${stringValue(event.activity)} error=${stringValue(event.error)}` };
1959
+ case "backend_connection_restored":
1960
+ return { ...base, message: `backend connection restored activity=${stringValue(event.activity)}` };
1961
+ case "retry_scheduled":
1962
+ return { ...base, level: "warn", message: `retry scheduled activity=${stringValue(event.activity)} delay=${formatSeconds(event.delaySeconds)}` };
1963
+ case "daemon_stderr":
1964
+ return { ...base, level: looksLikeError(event.message || event.stderr) ? "error" : "warn", message: `stderr ${stringValue(event.message || event.stderr)}` };
1965
+ case "error":
1966
+ return { ...base, level: "error", message: `error scope=${stringValue(event.relativePath || event.path || "daemon")} ${stringValue(event.error || event.code || "unknown")}` };
1967
+ case "process_exit":
1968
+ case "daemon_exit":
1969
+ return { ...base, level: "error", message: stringValue(event.message || processExitMessage(event)) };
1970
+ case "stopped":
1971
+ return { ...base, message: `stopped jobsRun=${Number(event.jobsRun ?? 0)}` };
1972
+ default:
1973
+ return null;
1974
+ }
1975
+ }
1976
+ function debugLevel(event) {
1977
+ if (event?.level) return stringValue(event.level);
1978
+ if (event?.type === "error" || event?.type === "process_exit" || event?.type === "daemon_exit") return "error";
1979
+ return "info";
1980
+ }
1981
+ function boolText(value) {
1982
+ return value ? "yes" : "no";
1983
+ }
1984
+ function shortId(value) {
1985
+ const text = stringValue(value);
1986
+ return text ? text.slice(0, 8) : "unknown";
1987
+ }
1988
+ function looksLikeError(value) {
1989
+ return /(error|exception|traceback|failed|fatal|denied|unauthorized|timeout)/i.test(stringValue(value));
1990
+ }
1893
1991
  function setAgentRunState(agentRunState, relativePath, patch) {
1894
1992
  const key = stringValue(relativePath || ".");
1895
1993
  return {
@@ -2725,6 +2823,8 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2725
2823
  let overlayActive = false;
2726
2824
  let ctrlCArmed = false;
2727
2825
  let ctrlCArmTimer = null;
2826
+ let dashboardClosed = false;
2827
+ let exitPromptActive = false;
2728
2828
  let selectedIdx = 0;
2729
2829
  const agentRowMap = /* @__PURE__ */ new Map();
2730
2830
  function agentDisplayList() {
@@ -2748,8 +2848,11 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2748
2848
  all.sort((a, b) => (a.timestamp || "").localeCompare(b.timestamp || ""));
2749
2849
  return all.slice(-maxLines);
2750
2850
  }
2851
+ function daemonDebugLines(maxLines = 8) {
2852
+ return serveDebugEntries(state.logs, maxLines);
2853
+ }
2751
2854
  function redraw() {
2752
- if (overlayActive) return;
2855
+ if (dashboardClosed || overlayActive) return;
2753
2856
  drawHeader({ env, platform, serveState: state });
2754
2857
  term.moveTo(1, SERVE_CONTENT_ROW);
2755
2858
  term.eraseDisplayBelow();
@@ -2777,7 +2880,6 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2777
2880
  for (const ag of agents) {
2778
2881
  const isSelected = ag.num - 1 === selectedIdx;
2779
2882
  agentRowMap.set(lineOffset, ag.num - 1);
2780
- term(isSelected ? term.bgCyan.black : term.gray);
2781
2883
  const numStr = String(ag.num).padStart(2);
2782
2884
  const nameStr = clip(ag.name, 28).padEnd(28);
2783
2885
  const statLine = ` ${numStr} ${ag.status.icon} ${nameStr} ${ag.status.text}`;
@@ -2863,6 +2965,29 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2863
2965
  `);
2864
2966
  } else {
2865
2967
  term.gray(` ${t} ${name} \u2014 ${msg}
2968
+ `);
2969
+ }
2970
+ }
2971
+ }
2972
+ const diagnostics = daemonDebugLines();
2973
+ if (diagnostics.length > 0) {
2974
+ const divW = Math.min((term.width || 80) - 4, 72);
2975
+ term("\n");
2976
+ term.gray(` ${"\u2500".repeat(3)} Daemon diagnostics ${"\u2500".repeat(Math.max(0, divW - 23))}
2977
+ `);
2978
+ for (const entry of diagnostics) {
2979
+ const t = formatLogTime(entry.timestamp);
2980
+ const type = clip(entry.eventType || "event", 24).padEnd(24);
2981
+ const msg = clip(entry.message || "", (term.width || 80) - 38);
2982
+ term.gray(` ${t} `);
2983
+ if (entry.level === "error") {
2984
+ term.red(`${type} ${msg}
2985
+ `);
2986
+ } else if (entry.level === "warn") {
2987
+ term.yellow(`${type} ${msg}
2988
+ `);
2989
+ } else {
2990
+ term.gray(`${type} ${msg}
2866
2991
  `);
2867
2992
  }
2868
2993
  }
@@ -2899,6 +3024,7 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2899
3024
  env,
2900
3025
  platform,
2901
3026
  onProgress: (msg) => {
3027
+ if (dashboardClosed) return;
2902
3028
  state = { ...state, activity: msg || "Preparing\u2026" };
2903
3029
  redraw();
2904
3030
  }
@@ -2908,10 +3034,12 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2908
3034
  attachServeChild(
2909
3035
  child,
2910
3036
  (updater) => {
3037
+ if (dashboardClosed) return;
2911
3038
  state = updater(state);
2912
3039
  redraw();
2913
3040
  },
2914
3041
  ({ message } = {}) => {
3042
+ if (dashboardClosed) return;
2915
3043
  if (!state.stopped) state = { ...state, stopped: true, activity: message || "Stopped" };
2916
3044
  redraw();
2917
3045
  },
@@ -2923,23 +3051,39 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2923
3051
  }
2924
3052
  return new Promise((resolve) => {
2925
3053
  function openAgentLog(idx) {
2926
- if (idx < 0 || idx >= state.agents.length) return;
3054
+ if (dashboardClosed || exitPromptActive || idx < 0 || idx >= state.agents.length) return;
2927
3055
  overlayActive = true;
2928
3056
  const ag = agentDisplayList()[idx];
2929
3057
  showAgentLog({ agent: ag, state, env, platform }).then(() => {
3058
+ if (dashboardClosed) return;
2930
3059
  overlayActive = false;
2931
3060
  term.clear();
2932
3061
  redraw();
2933
3062
  });
2934
3063
  }
3064
+ function clearCtrlCArm() {
3065
+ ctrlCArmed = false;
3066
+ if (ctrlCArmTimer) {
3067
+ clearTimeout(ctrlCArmTimer);
3068
+ ctrlCArmTimer = null;
3069
+ }
3070
+ }
3071
+ function detachDashboardHandlers() {
3072
+ term.off("key", handleKey);
3073
+ term.off("mouse", handleMouse);
3074
+ }
3075
+ function finish(next) {
3076
+ if (dashboardClosed) return;
3077
+ dashboardClosed = true;
3078
+ clearCtrlCArm();
3079
+ detachDashboardHandlers();
3080
+ resolve(next);
3081
+ }
2935
3082
  function handleKey(name) {
2936
3083
  if (name === "CTRL_C") {
2937
3084
  if (ctrlCArmed) {
2938
- clearTimeout(ctrlCArmTimer);
2939
3085
  child?.kill("SIGINT");
2940
- term.off("key", handleKey);
2941
- term.off("mouse", handleMouse);
2942
- resolve("exit");
3086
+ finish("exit");
2943
3087
  return;
2944
3088
  }
2945
3089
  ctrlCArmed = true;
@@ -2966,9 +3110,7 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2966
3110
  openAgentLog(selectedIdx);
2967
3111
  } else if (name === "s" || name === "S") {
2968
3112
  child?.kill("SIGINT");
2969
- term.off("key", handleKey);
2970
- term.off("mouse", handleMouse);
2971
- resolve("home");
3113
+ finish("home");
2972
3114
  }
2973
3115
  }
2974
3116
  function handleMouse(name, data) {
@@ -2989,16 +3131,13 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
2989
3131
  if (child) {
2990
3132
  child.once("exit", () => {
2991
3133
  setTimeout(() => {
2992
- if (!overlayActive) {
2993
- redraw();
2994
- term("\n");
2995
- term.gray(" Your agents have stopped. Press any key to go back\u2026");
2996
- term.once("key", () => {
2997
- term.off("key", handleKey);
2998
- term.off("mouse", handleMouse);
2999
- resolve("home");
3000
- });
3001
- }
3134
+ if (dashboardClosed || overlayActive) return;
3135
+ exitPromptActive = true;
3136
+ detachDashboardHandlers();
3137
+ redraw();
3138
+ term("\n");
3139
+ term.gray(" Your agents have stopped. Press any key to go back\u2026");
3140
+ term.once("key", () => finish("home"));
3002
3141
  }, 600);
3003
3142
  });
3004
3143
  }
@@ -3184,16 +3323,25 @@ function attachServeChild(child, onUpdate, onExit, logStore = null) {
3184
3323
  child.stderr.setEncoding("utf8");
3185
3324
  child.stderr.on("data", (chunk) => {
3186
3325
  const text = String(chunk).trim();
3187
- if (text) stderrChunks.push(text);
3326
+ if (text) {
3327
+ stderrChunks.push(text);
3328
+ onUpdate((cur) => applyServeEvent(cur, {
3329
+ type: "daemon_stderr",
3330
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3331
+ message: text
3332
+ }));
3333
+ }
3188
3334
  });
3189
3335
  child.on("error", (error) => {
3190
3336
  onUpdate((cur) => ({ ...cur, errors: [...cur.errors, { scope: "daemon", message: errMsg(error) }].slice(-20) }));
3191
3337
  });
3192
3338
  child.on("exit", (code, signal) => {
3193
- const message = serveProcessExitMessage({ stderr: stderrChunks.join("\n"), code, signal });
3339
+ const stderr = stderrChunks.join("\n");
3340
+ const stderrTail = serveProcessExitStderrTail(stderr);
3341
+ const message = serveProcessExitMessage({ stderr, code, signal });
3194
3342
  if (message) {
3195
3343
  onUpdate((cur) => {
3196
- const event = { type: "process_exit", timestamp: (/* @__PURE__ */ new Date()).toISOString(), code, signal, message, relativePath: cur.currentJob?.relativePath || "", runId: cur.currentJob?.runId || "" };
3344
+ const event = { type: "process_exit", timestamp: (/* @__PURE__ */ new Date()).toISOString(), code, signal, message, stderrTail, relativePath: cur.currentJob?.relativePath || "", runId: cur.currentJob?.runId || "" };
3197
3345
  try {
3198
3346
  logStore?.append(event);
3199
3347
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vendian/cli",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "Public Vendian CLI bootstrapper and launcher",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,