@pellux/goodvibes-tui 0.19.7 → 0.19.9

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.md CHANGED
@@ -4,6 +4,17 @@ All notable changes to GoodVibes TUI.
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.19.9] - 2026-04-19
8
+
9
+ ### Fixed
10
+ - Regenerated `docs/foundation-artifacts/operator-contract.json` after the 0.19.8 SDK bump; the foundation-artifacts-gate test failed on the 0.19.8 CI because the JSON was not regenerated. 0.19.8 tag has no npm artifact; 0.19.9 supersedes.
11
+ ## [0.19.8] - 2026-04-19
12
+
13
+ ### Changed
14
+ - Upgraded `@pellux/goodvibes-sdk` from 0.21.10 to 0.21.15. Carries the companion main-chat routing fix: `POST /api/sessions/:id/messages` with `kind: 'message'` now short-circuits the daemon's WRFC engineer-chain fall-through. The TUI wires `orchestrator.handleUserInput()` into the `COMPANION_MESSAGE_RECEIVED` runtime bus subscriber, so companion main-chat sends fire a real LLM turn via the same entry point as the TUI input box. Turn `STREAM_DELTA` / `TURN_COMPLETED` events stream back to both TUI and companion SSE.
15
+
16
+ ### Fixed
17
+ - Companion main-chat no longer produces engineer-agent acknowledgement boilerplate ("Update noted", "WRFC chain has passed all gates"). The message is received by the daemon, persisted, rendered in the TUI, and answered by a normal chat turn.
7
18
  ## [0.19.7] - 2026-04-18
8
19
 
9
20
  ### Changed
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![CI](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml/badge.svg)](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![Version](https://img.shields.io/badge/version-0.19.7-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
5
+ [![Version](https://img.shields.io/badge/version-0.19.9-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
6
6
 
7
7
  A terminal-native AI coding, operations, automation, knowledge, and integration console with a typed runtime, omnichannel surfaces, structured memory/knowledge, and a raw ANSI renderer.
8
8
 
@@ -3,7 +3,7 @@
3
3
  "product": {
4
4
  "id": "goodvibes",
5
5
  "surface": "operator",
6
- "version": "0.21.12"
6
+ "version": "0.21.15"
7
7
  },
8
8
  "auth": {
9
9
  "modes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-tui",
3
- "version": "0.19.7",
3
+ "version": "0.19.9",
4
4
  "description": "Terminal-native GoodVibes product for coding, operations, automation, knowledge, channels, and daemon-backed control-plane workflows.",
5
5
  "type": "module",
6
6
  "main": "src/main.ts",
@@ -89,7 +89,7 @@
89
89
  "@anthropic-ai/vertex-sdk": "^0.16.0",
90
90
  "@ast-grep/napi": "^0.42.0",
91
91
  "@aws/bedrock-token-generator": "^1.1.0",
92
- "@pellux/goodvibes-sdk": "0.21.12",
92
+ "@pellux/goodvibes-sdk": "0.21.15",
93
93
  "bash-language-server": "^5.6.0",
94
94
  "fuse.js": "^7.1.0",
95
95
  "graphql": "^16.13.2",
@@ -50,6 +50,12 @@ export interface BootstrapCoreState {
50
50
  readonly permissionPromptRef: { requestPermission: PermissionRequestHandler };
51
51
  readonly systemMessageRouterRef: { value: SystemMessageRouter | null };
52
52
  readonly conversationFollowUpRef: { value: ((item: ConversationFollowUpItem) => void) | null };
53
+ /**
54
+ * Mutable ref patched by bootstrap.ts after the Orchestrator is constructed.
55
+ * When non-null, COMPANION_MESSAGE_RECEIVED fires a real LLM turn via
56
+ * orchestrator.handleUserInput() instead of only appending the user message.
57
+ */
58
+ readonly orchestratorHandleUserInputRef: { value: ((text: string) => void) | null };
53
59
  readonly requestRender: () => void;
54
60
  readonly setRenderRequest: (fn: () => void) => void;
55
61
  readonly runtimeSessionIdRef: { value: string };
@@ -286,20 +292,30 @@ export async function initializeBootstrapCore(
286
292
  wrfcController: services.wrfcController,
287
293
  });
288
294
 
289
- // Subscribe to companion follow-up messages received from the daemon's HTTP layer.
290
- // The daemon emits COMPANION_MESSAGE_RECEIVED on the runtime bus (SDK 0.21.10+).
291
- // In SDK 0.21.12, kind='message' at POST /api/sessions/:id/messages now also calls
292
- // sessionBroker.submitMessage(), starting a real turn. COMPANION_MESSAGE_RECEIVED
293
- // still fires BEFORE submitMessage so the user message appears immediately in the
294
- // conversation view, and the AI response streams in via the normal turn path.
295
- // No double-render: COMPANION_MESSAGE_RECEIVED adds the user message once; the turn
296
- // path adds the AI response. Both paths are correctly wired with no changes required.
297
- // after persisting the message, so the TUI conversation view can render it immediately.
295
+ // Subscribe to companion main-chat messages received from the daemon's HTTP layer.
296
+ // The daemon emits COMPANION_MESSAGE_RECEIVED on the runtime bus when a companion
297
+ // POST /api/sessions/:id/messages with kind='message' arrives.
298
+ //
299
+ // bootstrap.ts patches orchestratorHandleUserInputRef.value after the Orchestrator
300
+ // is constructed. When that ref is set, we delegate to orchestrator.handleUserInput()
301
+ // which (a) adds the user message to the conversation view and (b) fires a real LLM
302
+ // turn whose STREAM_DELTA / TURN_COMPLETED events flow to both TUI and companion SSE.
303
+ //
304
+ // The fallback (ref not yet set) adds the message to the conversation view only —
305
+ // this path is unreachable in practice because the event bus is not connected to
306
+ // any live HTTP traffic until after the orchestrator is wired in bootstrap.ts.
307
+ const orchestratorHandleUserInputRef: { value: ((text: string) => void) | null } = { value: null };
298
308
  runtimeUnsubs.push(runtimeBus.on<Extract<SessionEvent, { type: 'COMPANION_MESSAGE_RECEIVED' }>>(
299
309
  'COMPANION_MESSAGE_RECEIVED',
300
310
  ({ payload }) => {
301
- conversation.addUserMessage(payload.body);
302
- requestRender();
311
+ if (orchestratorHandleUserInputRef.value) {
312
+ // Delegate to the orchestrator: adds user message + fires a real LLM turn.
313
+ orchestratorHandleUserInputRef.value(payload.body);
314
+ } else {
315
+ // Fallback: render the user message immediately (orchestrator not yet ready).
316
+ conversation.addUserMessage(payload.body);
317
+ requestRender();
318
+ }
303
319
  },
304
320
  ));
305
321
 
@@ -424,6 +440,7 @@ export async function initializeBootstrapCore(
424
440
  permissionPromptRef,
425
441
  systemMessageRouterRef,
426
442
  conversationFollowUpRef,
443
+ orchestratorHandleUserInputRef,
427
444
  requestRender,
428
445
  setRenderRequest: (fn) => {
429
446
  renderRequestRef.value = fn;
@@ -155,6 +155,7 @@ export async function bootstrapRuntime(
155
155
  permissionPromptRef,
156
156
  systemMessageRouterRef,
157
157
  conversationFollowUpRef,
158
+ orchestratorHandleUserInputRef,
158
159
  requestRender,
159
160
  setRenderRequest,
160
161
  runtimeSessionIdRef,
@@ -199,6 +200,12 @@ export async function bootstrapRuntime(
199
200
  },
200
201
  });
201
202
  conversationFollowUpRef.value = (item) => orchestrator.enqueueConversationFollowUp(item);
203
+ // Wire orchestratorHandleUserInputRef so COMPANION_MESSAGE_RECEIVED fires a real LLM turn.
204
+ orchestratorHandleUserInputRef.value = (text: string) => {
205
+ orchestrator.handleUserInput(text).catch((err: unknown) => {
206
+ logger.debug('companion handleUserInput safety catch', { error: String(err) });
207
+ });
208
+ };
202
209
  orchestrator.setCoreServices({
203
210
  configManager,
204
211
  providerRegistry,
package/src/version.ts CHANGED
@@ -6,7 +6,7 @@ import { join } from 'node:path';
6
6
  // The prebuild script updates the fallback value before compilation.
7
7
  // Uses import.meta.dir (Bun) to locate package.json relative to this file,
8
8
  // which is correct regardless of the process working directory.
9
- let _version = '0.19.7';
9
+ let _version = '0.19.9';
10
10
  try {
11
11
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8'));
12
12
  _version = pkg.version ?? _version;