@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 +8 -0
- package/package.json +1 -1
- package/src/cli/tui-startup.ts +64 -0
- package/src/main.ts +7 -17
- package/src/version.ts +1 -1
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.
|
|
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",
|
package/src/cli/tui-startup.ts
CHANGED
|
@@ -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 =
|
|
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${
|
|
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.
|
|
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 {
|