@pellux/goodvibes-tui 0.19.50 → 0.19.51

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.51] — 2026-04-28
8
+
9
+ ### Changed
10
+ - Updated `@pellux/goodvibes-sdk` to `0.26.6`.
11
+ - Embedded and standalone daemon hosts now wrap Bun request handlers so unexpected daemon/listener route exceptions return bounded JSON errors and are logged instead of printing raw stack/source output into the TUI terminal.
12
+
13
+ ### Fixed
14
+ - Picked up SDK Home Assistant Home Graph snapshot sync fixes for Home Assistant-native snake_case registry fields, incomplete registry objects, and JSON error responses from Home Graph admin routes.
15
+
16
+ ---
17
+
7
18
  ## [0.19.50] — 2026-04-28
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.50-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
5
+ [![Version](https://img.shields.io/badge/version-0.19.51-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.26.5"
6
+ "version": "0.26.6"
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.50",
3
+ "version": "0.19.51",
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",
@@ -91,7 +91,7 @@
91
91
  "@anthropic-ai/vertex-sdk": "^0.16.0",
92
92
  "@ast-grep/napi": "^0.42.0",
93
93
  "@aws/bedrock-token-generator": "^1.1.0",
94
- "@pellux/goodvibes-sdk": "0.26.5",
94
+ "@pellux/goodvibes-sdk": "0.26.6",
95
95
  "bash-language-server": "^5.6.0",
96
96
  "fuse.js": "^7.1.0",
97
97
  "graphql": "^16.13.2",
package/src/daemon/cli.ts CHANGED
@@ -26,6 +26,7 @@ import {
26
26
  loadPersistedProviders,
27
27
  persistProviders,
28
28
  } from '@pellux/goodvibes-sdk/platform/discovery/index';
29
+ import { createSafeHostServeFactory } from './safe-serve.ts';
29
30
 
30
31
  import {
31
32
  parseGoodVibesCli,
@@ -195,11 +196,17 @@ async function main(): Promise<void> {
195
196
  });
196
197
 
197
198
  const userAuth = runtimeServices.localUserAuthManager;
198
- const daemon = new DaemonServer({ runtimeBus, userAuth, runtimeServices });
199
+ const daemon = new DaemonServer({
200
+ runtimeBus,
201
+ userAuth,
202
+ runtimeServices,
203
+ serveFactory: createSafeHostServeFactory('Standalone daemon'),
204
+ });
199
205
  const listener = new HttpListener({
200
206
  hookDispatcher: runtimeServices.hookDispatcher,
201
207
  userAuth,
202
208
  configManager: config,
209
+ serveFactory: createSafeHostServeFactory('Standalone HTTP listener'),
203
210
  });
204
211
  const { daemonToken, httpToken } = readDaemonCliTokens(process.env);
205
212
 
@@ -0,0 +1,61 @@
1
+ import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
2
+ import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
3
+
4
+ type HostServeFetch = (
5
+ request: Request,
6
+ server: unknown,
7
+ ) => Response | undefined | Promise<Response | undefined>;
8
+
9
+ type HostServeOptions = Parameters<typeof Bun.serve>[0] & {
10
+ fetch?: HostServeFetch;
11
+ };
12
+
13
+ function requestPath(request: Request): string {
14
+ try {
15
+ return new URL(request.url).pathname;
16
+ } catch {
17
+ return request.url;
18
+ }
19
+ }
20
+
21
+ export function createHostRequestFailureResponse(
22
+ surface: string,
23
+ request: Request,
24
+ error: unknown,
25
+ ): Response {
26
+ const message = summarizeError(error);
27
+ logger.error(`${surface}: request handler failed`, {
28
+ method: request.method,
29
+ path: requestPath(request),
30
+ error: message,
31
+ });
32
+ return Response.json({
33
+ error: message,
34
+ code: 'HOST_REQUEST_HANDLER_FAILED',
35
+ }, { status: 500 });
36
+ }
37
+
38
+ export function createSafeHostServeFactory(
39
+ surface: string,
40
+ baseServeFactory: typeof Bun.serve = Bun.serve,
41
+ ): typeof Bun.serve {
42
+ return ((options: HostServeOptions) => {
43
+ const originalFetch = options.fetch;
44
+ if (typeof originalFetch !== 'function') {
45
+ return baseServeFactory(options as Parameters<typeof Bun.serve>[0]);
46
+ }
47
+
48
+ const wrappedFetch: HostServeFetch = async (request, server) => {
49
+ try {
50
+ return await originalFetch(request, server);
51
+ } catch (error) {
52
+ return createHostRequestFailureResponse(surface, request, error);
53
+ }
54
+ };
55
+
56
+ return baseServeFactory({
57
+ ...options,
58
+ fetch: wrappedFetch,
59
+ } as Parameters<typeof Bun.serve>[0]);
60
+ }) as typeof Bun.serve;
61
+ }
@@ -43,6 +43,11 @@ import { createDeferredStartupCoordinator } from '@pellux/goodvibes-sdk/platform
43
43
  import { initializeBootstrapCore } from './bootstrap-core.ts';
44
44
  import { createBootstrapShell } from './bootstrap-shell.ts';
45
45
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
46
+ import { DaemonServer } from '@pellux/goodvibes-sdk/platform/daemon/server';
47
+ import { HttpListener } from '@pellux/goodvibes-sdk/platform/daemon/http-listener';
48
+ import { createSafeHostServeFactory } from '../daemon/safe-serve.ts';
49
+
50
+ type ExternalServiceFactories = NonNullable<Parameters<typeof startExternalServices>[3]>;
46
51
 
47
52
  // ── Bootstrap context type ──────────────────────────────────────────────────
48
53
 
@@ -350,6 +355,22 @@ export async function bootstrapRuntime(
350
355
  ]);
351
356
  };
352
357
 
358
+ const createExternalServiceFactories = (sharedDaemonToken: string): ExternalServiceFactories => ({
359
+ sharedDaemonToken,
360
+ createDaemonServer: (bus, userAuth, runtimeServices) => new DaemonServer({
361
+ runtimeBus: bus,
362
+ userAuth,
363
+ runtimeServices,
364
+ serveFactory: createSafeHostServeFactory('Embedded daemon'),
365
+ }),
366
+ createHttpListener: (dispatcher, userAuth, configManager) => new HttpListener({
367
+ hookDispatcher: dispatcher,
368
+ userAuth,
369
+ configManager,
370
+ serveFactory: createSafeHostServeFactory('Embedded HTTP listener'),
371
+ }),
372
+ });
373
+
353
374
  let externalServices: ExternalServicesHandle = {
354
375
  daemonServer: null,
355
376
  httpListener: null,
@@ -380,7 +401,7 @@ export async function bootstrapRuntime(
380
401
  configManager,
381
402
  runtimeBus,
382
403
  hookDispatcher,
383
- { sharedDaemonToken: companionTokenRecord.token },
404
+ createExternalServiceFactories(companionTokenRecord.token),
384
405
  services,
385
406
  );
386
407
  externalServices = await externalServicesPromise;
@@ -443,7 +464,7 @@ export async function bootstrapRuntime(
443
464
  configManager,
444
465
  runtimeBus,
445
466
  hookDispatcher,
446
- { sharedDaemonToken: companionTokenRecord.token },
467
+ createExternalServiceFactories(companionTokenRecord.token),
447
468
  services,
448
469
  );
449
470
  externalServices = await externalServicesPromise;
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.50';
9
+ let _version = '0.19.51';
10
10
  try {
11
11
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8'));
12
12
  _version = pkg.version ?? _version;