@pellux/goodvibes-tui 0.19.6 → 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,42 @@ 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.
18
+ ## [0.19.7] - 2026-04-18
19
+
20
+ ### Changed
21
+ - Bumped `@pellux/goodvibes-sdk` from 0.21.10 to 0.21.12.
22
+
23
+ ### Investigation: No TUI-side changes required
24
+
25
+ SDK 0.21.12 ships three additive changes to the daemon:
26
+
27
+ 1. **`kind: 'message'` at `POST /api/sessions/:id/messages`** now calls `sessionBroker.submitMessage()` (previously called `appendCompanionMessage` + `publishConversationFollowup` only). A real turn is started and the full agent event chain (TURN_STARTED, STREAM_DELTA, TURN_COMPLETED) streams back.
28
+
29
+ 2. **`kind: 'followup'`** — new kind value that always spawns an agent. Full agent event chain streams to companion SSE.
30
+
31
+ 3. **`GET /api/sessions/:id/events`** — new session-scoped SSE endpoint for companion consumption.
32
+
33
+ 4. **`'turn'` added to `DEFAULT_DOMAINS`** in the control-plane gateway — turn events are now auto-delivered to all SSE subscribers.
34
+
35
+ Investigation of the TUI's `COMPANION_MESSAGE_RECEIVED` subscription in `src/runtime/bootstrap-core.ts` found **no double-render risk**: SDK 0.21.12 emits `COMPANION_MESSAGE_RECEIVED` _before_ calling `submitMessage`, so the user message is shown once (via the existing subscription), and the AI response streams in via the existing `uiServices.events.turns` path. These are distinct content on distinct code paths. No deduplication needed.
36
+
37
+ The `'turn'` addition to `DEFAULT_DOMAINS` affects external SSE subscribers (companion app). The TUI consumes turn events in-process via the runtime bus — unaffected.
38
+
39
+ Updated `docs/foundation-artifacts/operator-contract.json` SDK version field to `0.21.12`.
40
+
41
+ ---
42
+
7
43
  ## [0.19.6] - 2026-04-18
8
44
 
9
45
  ### Fixed
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.6-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.10"
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.6",
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.10",
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,14 +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
- // 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 };
292
308
  runtimeUnsubs.push(runtimeBus.on<Extract<SessionEvent, { type: 'COMPANION_MESSAGE_RECEIVED' }>>(
293
309
  'COMPANION_MESSAGE_RECEIVED',
294
310
  ({ payload }) => {
295
- conversation.addUserMessage(payload.body);
296
- 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
+ }
297
319
  },
298
320
  ));
299
321
 
@@ -418,6 +440,7 @@ export async function initializeBootstrapCore(
418
440
  permissionPromptRef,
419
441
  systemMessageRouterRef,
420
442
  conversationFollowUpRef,
443
+ orchestratorHandleUserInputRef,
421
444
  requestRender,
422
445
  setRenderRequest: (fn) => {
423
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.6';
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;