@pellux/goodvibes-agent 0.1.86 → 0.1.88

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
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to GoodVibes Agent will be recorded here.
4
4
 
5
+ ## 0.1.88 - 2026-06-01
6
+
7
+ - e97d2a2 Fix release test daemon port allocation
8
+
9
+ ## 0.1.87 - 2026-06-01
10
+
11
+ - cd0d9fc Improve Agent TUI startup diagnostics
12
+
5
13
  ## 0.1.86 - 2026-06-01
6
14
 
7
15
  - aac1849 Retry npm publish verification
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "0.1.86",
3
+ "version": "0.1.88",
4
4
  "private": false,
5
5
  "description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
6
6
  "type": "module",
@@ -9,6 +9,70 @@ export type InteractiveTerminalCheckInput = {
9
9
  readonly stdoutIsTTY: boolean | undefined;
10
10
  };
11
11
 
12
+ type NodeLikeError = Error & {
13
+ readonly code?: string;
14
+ readonly path?: string;
15
+ readonly syscall?: string;
16
+ };
17
+
18
+ export type FatalStartupFormatOptions = {
19
+ readonly binary: string;
20
+ readonly debug?: boolean;
21
+ };
22
+
23
+ function isNodeLikeError(error: unknown): error is NodeLikeError {
24
+ return error instanceof Error;
25
+ }
26
+
27
+ function fatalStartupMessage(error: unknown): string {
28
+ if (error instanceof Error) return error.message;
29
+ if (typeof error === 'string') return error;
30
+ try {
31
+ return JSON.stringify(error);
32
+ } catch {
33
+ return String(error);
34
+ }
35
+ }
36
+
37
+ function fatalStartupStack(error: unknown): string {
38
+ if (error instanceof Error) return error.stack ?? error.message;
39
+ return fatalStartupMessage(error);
40
+ }
41
+
42
+ export function formatFatalStartupErrorForLog(error: unknown): string {
43
+ return fatalStartupStack(error);
44
+ }
45
+
46
+ export function formatFatalStartupErrorForUser(error: unknown, options: FatalStartupFormatOptions): string {
47
+ if (options.debug === true) return fatalStartupStack(error);
48
+
49
+ const message = fatalStartupMessage(error);
50
+ if (isNodeLikeError(error) && (error.code === 'EACCES' || error.code === 'EPERM')) {
51
+ return [
52
+ `${options.binary} could not prepare its local workspace or log directory.`,
53
+ error.path ? ` path: ${error.path}` : '',
54
+ error.syscall ? ` operation: ${error.syscall}` : '',
55
+ ' reason: permission denied',
56
+ ` next: launch from a writable directory, pass '${options.binary} --cd <dir>', or set GOODVIBES_WORKING_DIR to a writable path.`,
57
+ ' note: GOODVIBES_AGENT_HOME can be set to move Agent-local config, sessions, memory, skills, personas, and routines.',
58
+ ].filter((line) => line.length > 0).join('\n');
59
+ }
60
+
61
+ if (isNodeLikeError(error) && error.code === 'ENOENT') {
62
+ return [
63
+ `${options.binary} could not find a required startup path.`,
64
+ error.path ? ` path: ${error.path}` : '',
65
+ ` reason: ${message}`,
66
+ ` next: check '${options.binary} --cd <dir>' and GOODVIBES_WORKING_DIR, then rerun '${options.binary} status'.`,
67
+ ].filter((line) => line.length > 0).join('\n');
68
+ }
69
+
70
+ return [
71
+ message || `${options.binary} failed during startup.`,
72
+ 'Set GOODVIBES_AGENT_DEBUG=1 to print a stack trace.',
73
+ ].join('\n');
74
+ }
75
+
12
76
  export function getInteractiveTerminalLaunchError(input: InteractiveTerminalCheckInput): string | null {
13
77
  const stdinReady = input.stdinIsTTY === true;
14
78
  const stdoutReady = input.stdoutIsTTY === true;
package/src/main.ts CHANGED
@@ -45,7 +45,7 @@ import { deriveComposerState } from './core/composer-state.ts';
45
45
  import { buildPersistedSessionContext, formatReturnContextForDisplay, getReturnContextMode, maybeAssistReturnContextSummary } from '@/runtime/index.ts';
46
46
  import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
47
47
  import { prepareShellCliRuntime } from './cli/entrypoint.ts';
48
- import { applyInitialTuiCliState, getInteractiveTerminalLaunchError } from './cli/tui-startup.ts';
48
+ import { applyInitialTuiCliState, formatFatalStartupErrorForLog, formatFatalStartupErrorForUser, getInteractiveTerminalLaunchError } from './cli/tui-startup.ts';
49
49
  import { wireSpokenTurnRuntime } from './audio/spoken-turn-wiring.ts';
50
50
  import { attachSpokenTurnModelRouting, createSpokenTurnInputOptions } from './audio/spoken-turn-model-routing.ts';
51
51
  import { allowTerminalWrite, installTuiTerminalOutputGuard } from './runtime/terminal-output-guard.ts';
@@ -768,29 +768,19 @@ async function main() {
768
768
 
769
769
  }
770
770
 
771
- function formatFatalStartupError(error: unknown): string {
772
- if (error instanceof Error) {
773
- return error.stack ?? error.message;
774
- }
775
- if (typeof error === 'string') {
776
- return error;
777
- }
778
- try {
779
- return JSON.stringify(error);
780
- } catch {
781
- return String(error);
782
- }
783
- }
784
-
785
771
  main().catch((err: unknown) => {
786
- const detail = formatFatalStartupError(err);
772
+ const detail = formatFatalStartupErrorForLog(err);
787
773
  try {
788
774
  logger.error('Fatal error', { error: detail });
789
775
  } catch {
790
776
  // Startup diagnostics must never hide the original launch failure.
791
777
  }
778
+ const userDetail = formatFatalStartupErrorForUser(err, {
779
+ binary: 'goodvibes-agent',
780
+ debug: process.env['GOODVIBES_AGENT_DEBUG'] === '1',
781
+ });
792
782
  try {
793
- process.stderr.write(`goodvibes-agent failed to launch:\n${detail}\n`);
783
+ process.stderr.write(`goodvibes-agent failed to launch:\n${userDetail}\n`);
794
784
  } catch {
795
785
  // Ignore secondary stderr failures during process teardown.
796
786
  }
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.1.86';
9
+ let _version = '0.1.88';
10
10
  let _sdkVersion = '0.33.35';
11
11
  try {
12
12
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {