@ouro.bot/cli 0.1.0-alpha.93 → 0.1.0-alpha.95

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/changelog.json CHANGED
@@ -1,6 +1,20 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.95",
6
+ "changes": [
7
+ "CLI chats now surface coding-session feedback back into the live `ouro chat` thread, so hidden child work no longer finishes silently while the operator sees an idle prompt.",
8
+ "Those async coding updates are also persisted into the CLI session history, which keeps the visible return loop truthful across follow-up turns instead of losing the fact that work already came back."
9
+ ]
10
+ },
11
+ {
12
+ "version": "0.1.0-alpha.94",
13
+ "changes": [
14
+ "Fix stale CurrentVersion symlink not healing during `ouro up` — the daemon now detects and repairs dangling version symlinks before reading the active version.",
15
+ "Fix homedir regression in daemon-cli-defaults test and cover changelog-null branch."
16
+ ]
17
+ },
4
18
  {
5
19
  "version": "0.1.0-alpha.93",
6
20
  "changes": [
@@ -1353,12 +1353,12 @@ function createDefaultOuroCliDeps(socketPath = socket_client_1.DEFAULT_DAEMON_SO
1353
1353
  runAuthFlow: auth_flow_1.runRuntimeAuthFlow,
1354
1354
  registerOuroBundleType: ouro_uti_1.registerOuroBundleUti,
1355
1355
  installOuroCommand: ouro_path_installer_1.installOuroCommand,
1356
- /* v8 ignore start -- self-healing: ensures versioned layout has current version installed @preserve */
1356
+ /* v8 ignore start -- self-healing: ensures active symlink matches running runtime version @preserve */
1357
1357
  ensureCurrentVersionInstalled: () => {
1358
- const currentVersion = (0, ouro_version_manager_1.getCurrentVersion)({});
1359
- if (currentVersion)
1360
- return; // Already installed and linked
1358
+ const linkedVersion = (0, ouro_version_manager_1.getCurrentVersion)({});
1361
1359
  const version = (0, bundle_manifest_1.getPackageVersion)();
1360
+ if (linkedVersion === version)
1361
+ return;
1362
1362
  (0, ouro_version_manager_1.ensureLayout)({});
1363
1363
  const cliHome = (0, ouro_version_manager_1.getOuroCliHome)();
1364
1364
  const versionEntry = path.join(cliHome, "versions", version, "node_modules", "@ouro.bot", "cli", "dist", "heart", "daemon", "ouro-entry.js");
@@ -1817,6 +1817,7 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
1817
1817
  meta: { kind: command.kind },
1818
1818
  });
1819
1819
  if (command.kind === "daemon.up") {
1820
+ const linkedVersionBeforeUp = deps.getCurrentCliVersion?.() ?? null;
1820
1821
  // ── versioned CLI update check ──
1821
1822
  if (deps.checkForCliUpdate) {
1822
1823
  let pendingReExec = false;
@@ -1824,7 +1825,7 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
1824
1825
  const updateResult = await deps.checkForCliUpdate();
1825
1826
  if (updateResult.available && updateResult.latestVersion) {
1826
1827
  /* v8 ignore next -- fallback: getCurrentCliVersion always injected in tests @preserve */
1827
- const currentVersion = deps.getCurrentCliVersion?.() ?? "unknown";
1828
+ const currentVersion = linkedVersionBeforeUp ?? "unknown";
1828
1829
  await deps.installCliVersion(updateResult.latestVersion);
1829
1830
  deps.activateCliVersion(updateResult.latestVersion);
1830
1831
  deps.writeStdout(`ouro updated to ${updateResult.latestVersion} (was ${currentVersion})`);
@@ -1852,6 +1853,15 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
1852
1853
  }
1853
1854
  }
1854
1855
  await performSystemSetup(deps);
1856
+ const linkedVersionAfterSetup = deps.getCurrentCliVersion?.() ?? null;
1857
+ const runtimeVersion = (0, bundle_manifest_1.getPackageVersion)();
1858
+ if (linkedVersionBeforeUp && linkedVersionBeforeUp !== runtimeVersion && linkedVersionAfterSetup === runtimeVersion) {
1859
+ deps.writeStdout(`ouro updated to ${runtimeVersion} (was ${linkedVersionBeforeUp})`);
1860
+ const changelogCommand = (0, ouro_version_manager_1.buildChangelogCommand)(linkedVersionBeforeUp, runtimeVersion);
1861
+ if (changelogCommand) {
1862
+ deps.writeStdout(`review changes with: ${changelogCommand}`);
1863
+ }
1864
+ }
1855
1865
  if (deps.ensureDaemonBootPersistence) {
1856
1866
  try {
1857
1867
  await Promise.resolve(deps.ensureDaemonBootPersistence(deps.socketPath));
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.MarkdownStreamer = exports.InputController = exports.Spinner = exports.StreamingWordWrapper = exports.wrapCliText = exports.formatEchoedInputSummary = void 0;
37
37
  exports.formatPendingPrefix = formatPendingPrefix;
38
38
  exports.getCliContinuityIngressTexts = getCliContinuityIngressTexts;
39
+ exports.writeCliAsyncAssistantMessage = writeCliAsyncAssistantMessage;
39
40
  exports.pauseActiveSpinner = pauseActiveSpinner;
40
41
  exports.resumeActiveSpinner = resumeActiveSpinner;
41
42
  exports.setActiveSpinner = setActiveSpinner;
@@ -94,6 +95,21 @@ function getCliContinuityIngressTexts(input) {
94
95
  const trimmed = input.trim();
95
96
  return trimmed ? [trimmed] : [];
96
97
  }
98
+ const CLI_PROMPT = "\x1b[36m> \x1b[0m";
99
+ function writeCliAsyncAssistantMessage(rl, message, stdout = process.stdout) {
100
+ const rlInt = rl;
101
+ const currentLine = rlInt.line ?? "";
102
+ const currentCursor = rlInt.cursor ?? currentLine.length;
103
+ stdout.write("\r\x1b[K");
104
+ stdout.write(`${renderMarkdown(message)}\n`);
105
+ stdout.write(CLI_PROMPT);
106
+ if (!currentLine)
107
+ return;
108
+ stdout.write(currentLine);
109
+ if (currentCursor < currentLine.length) {
110
+ readline.cursorTo(process.stdout, 2 + currentCursor);
111
+ }
112
+ }
97
113
  // Module-level active spinner for log coordination.
98
114
  // The terminal log sink calls these to avoid interleaving with spinner output.
99
115
  let _activeSpinner = null;
@@ -515,6 +531,22 @@ async function runCliSession(options) {
515
531
  console.log(`\n${bannerText}\n`);
516
532
  }
517
533
  const cliCallbacks = createCliCallbacks();
534
+ const effectiveToolContext = {
535
+ signin: options.toolContext?.signin ?? (async () => undefined),
536
+ ...options.toolContext,
537
+ codingFeedback: {
538
+ send: async (message) => {
539
+ const assistantMessage = {
540
+ role: "assistant",
541
+ content: message,
542
+ };
543
+ messages.push(assistantMessage);
544
+ await options.onAsyncAssistantMessage?.(messages, assistantMessage);
545
+ writeCliAsyncAssistantMessage(rl, message);
546
+ await options.toolContext?.codingFeedback?.send(message);
547
+ },
548
+ },
549
+ };
518
550
  // exitOnToolCall machinery: wrap execTool to detect target tool
519
551
  let exitToolResult;
520
552
  let exitToolFired = false;
@@ -542,14 +574,14 @@ async function runCliSession(options) {
542
574
  if (result === "clear") {
543
575
  rlInt.line = "";
544
576
  rlInt.cursor = 0;
545
- process.stdout.write("\r\x1b[K\x1b[36m> \x1b[0m");
577
+ process.stdout.write(`\r\x1b[K${CLI_PROMPT}`);
546
578
  }
547
579
  else if (result === "warn") {
548
580
  rlInt.line = "";
549
581
  rlInt.cursor = 0;
550
582
  process.stdout.write("\r\x1b[K");
551
583
  process.stderr.write("press Ctrl-C again to exit\n");
552
- process.stdout.write("\x1b[36m> \x1b[0m");
584
+ process.stdout.write(CLI_PROMPT);
553
585
  }
554
586
  else {
555
587
  rl.close();
@@ -576,7 +608,7 @@ async function runCliSession(options) {
576
608
  traceId,
577
609
  tools: options.tools,
578
610
  execTool: wrappedExecTool,
579
- toolContext: options.toolContext,
611
+ toolContext: effectiveToolContext,
580
612
  });
581
613
  }
582
614
  catch (err) {
@@ -605,14 +637,14 @@ async function runCliSession(options) {
605
637
  }
606
638
  }
607
639
  if (!exitToolFired) {
608
- process.stdout.write("\x1b[36m> \x1b[0m");
640
+ process.stdout.write(CLI_PROMPT);
609
641
  }
610
642
  try {
611
643
  for await (const input of debouncedLines(rl)) {
612
644
  if (closed)
613
645
  break;
614
646
  if (!input.trim()) {
615
- process.stdout.write("\x1b[36m> \x1b[0m");
647
+ process.stdout.write(CLI_PROMPT);
616
648
  continue;
617
649
  }
618
650
  // Optional input gate (e.g. trust gate in main)
@@ -624,7 +656,7 @@ async function runCliSession(options) {
624
656
  }
625
657
  if (closed)
626
658
  break;
627
- process.stdout.write("\x1b[36m> \x1b[0m");
659
+ process.stdout.write(CLI_PROMPT);
628
660
  continue;
629
661
  }
630
662
  }
@@ -642,13 +674,13 @@ async function runCliSession(options) {
642
674
  await options.onNewSession?.();
643
675
  // eslint-disable-next-line no-console -- terminal UX: session cleared
644
676
  console.log("session cleared");
645
- process.stdout.write("\x1b[36m> \x1b[0m");
677
+ process.stdout.write(CLI_PROMPT);
646
678
  continue;
647
679
  }
648
680
  else if (dispatchResult.result.action === "response") {
649
681
  // eslint-disable-next-line no-console -- terminal UX: command dispatch result
650
682
  console.log(dispatchResult.result.message || "");
651
- process.stdout.write("\x1b[36m> \x1b[0m");
683
+ process.stdout.write(CLI_PROMPT);
652
684
  continue;
653
685
  }
654
686
  }
@@ -664,7 +696,7 @@ async function runCliSession(options) {
664
696
  if (options.runTurn) {
665
697
  // Pipeline-based turn: the runTurn callback handles user message assembly,
666
698
  // pending drain, trust gate, runAgent, postTurn, and token accumulation.
667
- result = await options.runTurn(messages, input, cliCallbacks, currentAbort.signal);
699
+ result = await options.runTurn(messages, input, cliCallbacks, currentAbort.signal, effectiveToolContext);
668
700
  }
669
701
  else {
670
702
  // Legacy path: inline runAgent (used by adoption specialist and tests)
@@ -676,7 +708,7 @@ async function runCliSession(options) {
676
708
  traceId,
677
709
  tools: options.tools,
678
710
  execTool: wrappedExecTool,
679
- toolContext: options.toolContext,
711
+ toolContext: effectiveToolContext,
680
712
  });
681
713
  }
682
714
  }
@@ -707,7 +739,7 @@ async function runCliSession(options) {
707
739
  }
708
740
  if (closed)
709
741
  break;
710
- process.stdout.write("\x1b[36m> \x1b[0m");
742
+ process.stdout.write(CLI_PROMPT);
711
743
  }
712
744
  }
713
745
  finally {
@@ -781,7 +813,10 @@ async function main(agentName, options) {
781
813
  agentName: currentAgentName,
782
814
  pasteDebounceMs,
783
815
  messages: sessionMessages,
784
- runTurn: async (messages, userInput, callbacks, signal) => {
816
+ onAsyncAssistantMessage: async (messages, _assistantMessage) => {
817
+ (0, context_1.postTurn)(messages, sessPath, undefined, undefined, sessionState);
818
+ },
819
+ runTurn: async (messages, userInput, callbacks, signal, toolContext) => {
785
820
  // Run the full per-turn pipeline: resolve -> gate -> session -> drain -> runAgent -> postTurn -> tokens
786
821
  // User message passed via input.messages so the pipeline can prepend pending messages to it.
787
822
  const result = await (0, pipeline_1.handleInboundTurn)({
@@ -819,6 +854,7 @@ async function main(agentName, options) {
819
854
  toolChoiceRequired: (0, commands_1.getToolChoiceRequired)(),
820
855
  traceId: (0, nerves_1.createTraceId)(),
821
856
  mcpManager,
857
+ toolContext,
822
858
  },
823
859
  });
824
860
  // Handle gate rejection: display auto-reply if present
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.93",
3
+ "version": "0.1.0-alpha.95",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",