@pellux/goodvibes-tui 0.19.23 → 0.19.25
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 +21 -0
- package/README.md +5 -5
- package/bin/goodvibes +5 -0
- package/bin/goodvibes-daemon +5 -0
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/cli/completion.ts +89 -0
- package/src/cli/config-overrides.ts +159 -0
- package/src/cli/endpoints.ts +63 -0
- package/src/cli/entrypoint.ts +155 -0
- package/src/cli/help.ts +122 -0
- package/src/cli/index.ts +8 -0
- package/src/cli/management-commands.ts +576 -0
- package/src/cli/management.ts +693 -0
- package/src/cli/parser.ts +367 -0
- package/src/cli/status.ts +112 -0
- package/src/cli/tui-startup.ts +32 -0
- package/src/cli/types.ts +63 -0
- package/src/cli-flags.ts +17 -55
- package/src/config/index.ts +1 -1
- package/src/config/secrets.ts +44 -0
- package/src/core/conversation.ts +36 -13
- package/src/daemon/cli.ts +62 -11
- package/src/input/command-registry.ts +3 -0
- package/src/input/commands/guidance-runtime.ts +9 -4
- package/src/input/commands/local-runtime.ts +21 -7
- package/src/input/commands/local-setup.ts +31 -38
- package/src/input/commands/onboarding-runtime.ts +14 -0
- package/src/input/commands/runtime-services.ts +9 -0
- package/src/input/commands.ts +2 -0
- package/src/input/feed-context-factory.ts +8 -1
- package/src/input/handler-feed.ts +13 -8
- package/src/input/handler-interactions.ts +266 -0
- package/src/input/handler-modal-stack.ts +23 -3
- package/src/input/handler-modal-token-routes.ts +23 -1
- package/src/input/handler-onboarding.ts +696 -0
- package/src/input/handler-picker-routes.ts +15 -7
- package/src/input/handler-ui-state.ts +58 -0
- package/src/input/handler.ts +120 -246
- package/src/input/onboarding/handler-onboarding-routes.ts +105 -0
- package/src/input/onboarding/onboarding-wizard-apply.ts +211 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +148 -0
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +712 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +218 -0
- package/src/input/onboarding/onboarding-wizard-rules.ts +224 -0
- package/src/input/onboarding/onboarding-wizard-state.ts +354 -0
- package/src/input/onboarding/onboarding-wizard-steps.ts +642 -0
- package/src/input/onboarding/onboarding-wizard-types.ts +170 -0
- package/src/input/onboarding/onboarding-wizard.ts +594 -0
- package/src/main.ts +32 -39
- package/src/panels/builtin/operations.ts +0 -10
- package/src/panels/index.ts +0 -1
- package/src/panels/panel-manager.ts +6 -2
- package/src/renderer/conversation-overlays.ts +6 -0
- package/src/renderer/help-overlay.ts +1 -1
- package/src/renderer/onboarding/onboarding-wizard.ts +533 -0
- package/src/renderer/panel-composite.ts +42 -5
- package/src/renderer/panel-workspace-bar.ts +5 -1
- package/src/runtime/bootstrap-core.ts +1 -0
- package/src/runtime/bootstrap.ts +123 -0
- package/src/runtime/onboarding/apply.ts +685 -0
- package/src/runtime/onboarding/derivation.ts +495 -0
- package/src/runtime/onboarding/index.ts +7 -0
- package/src/runtime/onboarding/markers.ts +161 -0
- package/src/runtime/onboarding/snapshot.ts +400 -0
- package/src/runtime/onboarding/state.ts +140 -0
- package/src/runtime/onboarding/types.ts +402 -0
- package/src/runtime/onboarding/verify.ts +233 -0
- package/src/runtime/ui-services.ts +16 -0
- package/src/shell/ui-openers.ts +12 -2
- package/src/version.ts +1 -1
- package/src/panels/welcome-panel.ts +0 -64
package/src/main.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
3
|
import { Compositor } from './renderer/compositor.ts';
|
|
5
4
|
import { type Line } from './types/grid.ts';
|
|
6
5
|
import { UIFactory } from './renderer/ui-factory.ts';
|
|
7
6
|
import { Orchestrator } from './core/orchestrator';
|
|
8
7
|
import { InputHandler } from './input/handler.ts';
|
|
9
8
|
import { SelectionManager } from './input/selection.ts';
|
|
10
|
-
import { ConfigManager } from './config/index.ts';
|
|
11
9
|
import type { ContentPart } from '@pellux/goodvibes-sdk/platform/providers/interface';
|
|
12
10
|
import { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools/registry';
|
|
13
11
|
import { registerAllTools } from '@pellux/goodvibes-sdk/platform/tools/index';
|
|
@@ -32,7 +30,7 @@ import {
|
|
|
32
30
|
} from './renderer/conversation-layout.ts';
|
|
33
31
|
import { applyConversationOverlays } from './renderer/conversation-overlays.ts';
|
|
34
32
|
import { buildPanelCompositeData } from './renderer/panel-composite.ts';
|
|
35
|
-
import {
|
|
33
|
+
import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
|
|
36
34
|
import { registerBuiltinPanels } from './panels/builtin-panels.ts';
|
|
37
35
|
import { renderPanelTabBar } from './renderer/panel-tab-bar.ts';
|
|
38
36
|
import { bootstrapRuntime } from './runtime/bootstrap.ts';
|
|
@@ -50,9 +48,9 @@ import { handleBlockingShellInput, type PendingPermissionState } from './shell/b
|
|
|
50
48
|
import { wireShellUiOpeners } from './shell/ui-openers.ts';
|
|
51
49
|
import { deriveComposerState } from './core/composer-state.ts';
|
|
52
50
|
import { buildPersistedSessionContext, formatReturnContextForDisplay, getReturnContextMode, maybeAssistReturnContextSummary } from '@pellux/goodvibes-sdk/platform/runtime/session-return-context';
|
|
53
|
-
import { GlobalNetworkTransportInstaller } from '@pellux/goodvibes-sdk/platform/runtime/network/index';
|
|
54
51
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
|
|
55
|
-
import {
|
|
52
|
+
import { prepareShellCliRuntime } from './cli/entrypoint.ts';
|
|
53
|
+
import { applyInitialTuiCliState } from './cli/tui-startup.ts';
|
|
56
54
|
|
|
57
55
|
const ALT_SCREEN_ENTER = '\x1b[?1049h';
|
|
58
56
|
const ALT_SCREEN_EXIT = '\x1b[?1049l';
|
|
@@ -66,41 +64,13 @@ const KEYBOARD_EXT_DISABLE = '\x1b[>4;0m' + '\x1b[?1l';
|
|
|
66
64
|
const PASTE_ENABLE = '\x1b[?2004h';
|
|
67
65
|
const PASTE_DISABLE = '\x1b[?2004l';
|
|
68
66
|
|
|
69
|
-
type ShellEntrypointOwnership = {
|
|
70
|
-
readonly workingDirectory: string;
|
|
71
|
-
readonly homeDirectory: string;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
function resolveShellEntrypointOwnership(): ShellEntrypointOwnership {
|
|
75
|
-
return {
|
|
76
|
-
workingDirectory: process.cwd(),
|
|
77
|
-
homeDirectory: homedir(),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
67
|
async function main() {
|
|
82
68
|
const stdout = process.stdout;
|
|
83
69
|
const stdin = process.stdin;
|
|
84
|
-
const {
|
|
85
|
-
|
|
86
|
-
homeDirectory:
|
|
87
|
-
}
|
|
88
|
-
configureActivityLogger(join(bootstrapWorkingDir, '.goodvibes', 'logs'));
|
|
89
|
-
const configManager = new ConfigManager({
|
|
90
|
-
workingDir: bootstrapWorkingDir,
|
|
91
|
-
homeDir: bootstrapHomeDirectory,
|
|
92
|
-
surfaceRoot: 'tui',
|
|
93
|
-
});
|
|
94
|
-
new GlobalNetworkTransportInstaller().install(configManager);
|
|
95
|
-
|
|
96
|
-
// Apply CLI flags — override settings.json before the provider registry is constructed
|
|
97
|
-
const cliFlags = parseCliFlags(process.argv.slice(2), 'goodvibes');
|
|
98
|
-
if (cliFlags.provider !== undefined) {
|
|
99
|
-
configManager.set('provider.provider', cliFlags.provider);
|
|
100
|
-
}
|
|
101
|
-
if (cliFlags.model !== undefined) {
|
|
102
|
-
configManager.set('provider.model', cliFlags.model);
|
|
103
|
-
}
|
|
70
|
+
const { cli, configManager, bootstrapWorkingDir, bootstrapHomeDirectory } = await prepareShellCliRuntime(process.argv.slice(2), {
|
|
71
|
+
defaultWorkingDirectory: process.env['GOODVIBES_WORKING_DIR'] ?? process.cwd(),
|
|
72
|
+
homeDirectory: homedir(),
|
|
73
|
+
}, 'goodvibes');
|
|
104
74
|
|
|
105
75
|
// ── Bootstrap runtime subsystems via bootstrapRuntime.
|
|
106
76
|
const ctx: BootstrapContext = await bootstrapRuntime(stdout, {
|
|
@@ -288,7 +258,7 @@ async function main() {
|
|
|
288
258
|
stdout.removeListener('resize', resizeHandler);
|
|
289
259
|
process.removeListener('SIGINT', sigintHandler);
|
|
290
260
|
process.removeListener('unhandledRejection', unhandledRejectionHandler);
|
|
291
|
-
stdout.write(PASTE_DISABLE + KEYBOARD_EXT_DISABLE + MOUSE_DISABLE + CURSOR_SHOW + ALT_SCREEN_EXIT);
|
|
261
|
+
stdout.write(PASTE_DISABLE + KEYBOARD_EXT_DISABLE + MOUSE_DISABLE + CURSOR_SHOW + (cli.flags.noAltScreen ? '' : ALT_SCREEN_EXIT));
|
|
292
262
|
stdin.setRawMode(false);
|
|
293
263
|
process.exit(0);
|
|
294
264
|
};
|
|
@@ -404,6 +374,20 @@ async function main() {
|
|
|
404
374
|
favoritesStore: ctx.services.favoritesStore,
|
|
405
375
|
providerRegistry: ctx.services.providerRegistry,
|
|
406
376
|
},
|
|
377
|
+
platform: {
|
|
378
|
+
configManager: ctx.services.configManager,
|
|
379
|
+
localUserAuthManager: ctx.services.localUserAuthManager,
|
|
380
|
+
mcpRegistry: ctx.services.mcpRegistry,
|
|
381
|
+
serviceRegistry: ctx.services.serviceRegistry,
|
|
382
|
+
surfaceRegistry: ctx.services.surfaceRegistry,
|
|
383
|
+
subscriptionManager: ctx.services.subscriptionManager,
|
|
384
|
+
secretsManager: ctx.services.secretsManager,
|
|
385
|
+
tokenAuditor: ctx.services.tokenAuditor,
|
|
386
|
+
replayEngine: ctx.services.replayEngine,
|
|
387
|
+
webhookNotifier: ctx.services.webhookNotifier,
|
|
388
|
+
policyRuntimeState: ctx.services.policyRuntimeState,
|
|
389
|
+
externalServices: uiServices.platform.externalServices,
|
|
390
|
+
},
|
|
407
391
|
shell: {
|
|
408
392
|
bookmarkManager: ctx.services.bookmarkManager,
|
|
409
393
|
keybindingsManager: ctx.services.keybindingsManager,
|
|
@@ -690,6 +674,15 @@ async function main() {
|
|
|
690
674
|
render,
|
|
691
675
|
});
|
|
692
676
|
|
|
677
|
+
applyInitialTuiCliState({
|
|
678
|
+
cli,
|
|
679
|
+
input,
|
|
680
|
+
commandRegistry,
|
|
681
|
+
commandContext,
|
|
682
|
+
shellPaths: ctx.services.shellPaths,
|
|
683
|
+
render,
|
|
684
|
+
});
|
|
685
|
+
|
|
693
686
|
// --- Streaming speed + tool preview wiring ---
|
|
694
687
|
const refreshGit = () => gitStatusProvider.refresh().then((info) => { lastGitInfoRef.value = info; render(); }).catch(() => { /* non-fatal */ });
|
|
695
688
|
// Refresh git status after each turn completes or after tool results arrive
|
|
@@ -733,7 +726,7 @@ async function main() {
|
|
|
733
726
|
stdin.setRawMode(true);
|
|
734
727
|
stdin.resume();
|
|
735
728
|
stdin.setEncoding('utf8');
|
|
736
|
-
stdout.write(ALT_SCREEN_ENTER + CLEAR_SCREEN + CURSOR_HIDE + MOUSE_ENABLE + KEYBOARD_EXT_ENABLE + PASTE_ENABLE);
|
|
729
|
+
stdout.write((cli.flags.noAltScreen ? '' : ALT_SCREEN_ENTER) + CLEAR_SCREEN + CURSOR_HIDE + MOUSE_ENABLE + KEYBOARD_EXT_ENABLE + PASTE_ENABLE);
|
|
737
730
|
|
|
738
731
|
stdin.on('data', (data: string) => {
|
|
739
732
|
const blocking = handleBlockingShellInput({
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { PanelManager } from '../panel-manager.ts';
|
|
2
2
|
import { CockpitPanel } from '../cockpit-panel.ts';
|
|
3
3
|
import { ApprovalPanel } from '../approval-panel.ts';
|
|
4
|
-
import { WelcomePanel } from '../welcome-panel.ts';
|
|
5
4
|
import { PluginsPanel } from '../plugins-panel.ts';
|
|
6
5
|
import { SkillsPanel } from '../skills-panel.ts';
|
|
7
6
|
import { ServicesPanel } from '../services-panel.ts';
|
|
@@ -72,15 +71,6 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
72
71
|
factory: () => new ApprovalPanel(deps.policyRuntimeState),
|
|
73
72
|
});
|
|
74
73
|
|
|
75
|
-
manager.registerType({
|
|
76
|
-
id: 'welcome',
|
|
77
|
-
name: 'Welcome',
|
|
78
|
-
icon: 'W',
|
|
79
|
-
category: 'monitoring',
|
|
80
|
-
description: 'Guided start surface for setup, security, marketplace, remote, and operator workflows',
|
|
81
|
-
factory: () => new WelcomePanel(),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
74
|
manager.registerType({
|
|
85
75
|
id: 'plugins',
|
|
86
76
|
name: 'Plugins',
|
package/src/panels/index.ts
CHANGED
|
@@ -41,7 +41,6 @@ export { SecurityPanel } from './security-panel.ts';
|
|
|
41
41
|
export { MarketplacePanel } from './marketplace-panel.ts';
|
|
42
42
|
export { SandboxPanel } from './sandbox-panel.ts';
|
|
43
43
|
export { ApprovalPanel } from './approval-panel.ts';
|
|
44
|
-
export { WelcomePanel } from './welcome-panel.ts';
|
|
45
44
|
export { KnowledgePanel } from './knowledge-panel.ts';
|
|
46
45
|
export { SystemMessagesPanel } from './system-messages-panel.ts';
|
|
47
46
|
export { PanelListPanel } from './panel-list-panel.ts';
|
|
@@ -347,13 +347,17 @@ export class PanelManager {
|
|
|
347
347
|
|
|
348
348
|
getWorkspaceTabs(): readonly WorkspaceTab[] {
|
|
349
349
|
if (this._cachedWorkspaceTabs !== null) return this._cachedWorkspaceTabs;
|
|
350
|
+
// `active` = the currently selected tab in its own pane (independent of focus).
|
|
351
|
+
// `focused` = true only for the one tab in the globally focused pane that is active.
|
|
350
352
|
const focusedPanelId = this.getActivePanel()?.id;
|
|
353
|
+
const topActivePanelId = this.topPane.panels[this.topPane.activeIndex]?.id;
|
|
354
|
+
const bottomActivePanelId = this.bottomPane.panels[this.bottomPane.activeIndex]?.id;
|
|
351
355
|
const topTabs = this.topPane.panels.map((panel) => ({
|
|
352
356
|
id: panel.id,
|
|
353
357
|
name: panel.name,
|
|
354
358
|
icon: panel.icon,
|
|
355
359
|
pane: 'top' as const,
|
|
356
|
-
active: panel.id ===
|
|
360
|
+
active: panel.id === topActivePanelId,
|
|
357
361
|
focused: panel.id === focusedPanelId,
|
|
358
362
|
}));
|
|
359
363
|
const bottomTabs = this.bottomPane.panels.map((panel) => ({
|
|
@@ -361,7 +365,7 @@ export class PanelManager {
|
|
|
361
365
|
name: panel.name,
|
|
362
366
|
icon: panel.icon,
|
|
363
367
|
pane: 'bottom' as const,
|
|
364
|
-
active: panel.id ===
|
|
368
|
+
active: panel.id === bottomActivePanelId,
|
|
365
369
|
focused: panel.id === focusedPanelId,
|
|
366
370
|
}));
|
|
367
371
|
const tabs = [...topTabs, ...bottomTabs] as WorkspaceTab[];
|
|
@@ -18,6 +18,7 @@ import { renderProfilePickerModal } from './profile-picker-modal.ts';
|
|
|
18
18
|
import { renderBookmarkModal } from './bookmark-modal.ts';
|
|
19
19
|
import { renderHelpOverlay, renderShortcutsOverlay } from './help-overlay.ts';
|
|
20
20
|
import { renderAutocompleteOverlay } from './autocomplete-overlay.ts';
|
|
21
|
+
import { renderOnboardingWizard } from './onboarding/onboarding-wizard.ts';
|
|
21
22
|
import { overlayViewportBottom, replaceViewportWithOverlay } from './conversation-layout.ts';
|
|
22
23
|
|
|
23
24
|
export interface ConversationOverlayContext {
|
|
@@ -38,6 +39,11 @@ export function applyConversationOverlays(
|
|
|
38
39
|
let next = viewport;
|
|
39
40
|
const bottomDockInset = 1 + (input.searchManager.active || input.historySearch.active ? 1 : 0);
|
|
40
41
|
|
|
42
|
+
if (input.onboardingWizard.active) {
|
|
43
|
+
const lines = renderOnboardingWizard(input.onboardingWizard, conversationWidth, viewportHeight);
|
|
44
|
+
next = replaceViewportWithOverlay(lines, conversationWidth, viewportHeight);
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
if (input.filePicker.active) {
|
|
42
48
|
const lines = renderFilePickerOverlay(input.filePicker, conversationWidth, viewportHeight);
|
|
43
49
|
next = overlayViewportBottom(next, lines, conversationWidth, viewportHeight, bottomDockInset);
|
|
@@ -69,7 +69,7 @@ export function renderHelpOverlay(
|
|
|
69
69
|
// Each entry is [commandName, subcommandOrArgHint, description].
|
|
70
70
|
// Commands not registered in the live registry are omitted at render time.
|
|
71
71
|
const FEATURED_COMMANDS: Array<[name: string, argHint: string, desc: string]> = [
|
|
72
|
-
['
|
|
72
|
+
['onboarding', '', 'Open the onboarding wizard with current settings preloaded'],
|
|
73
73
|
['cockpit', '', 'Unified runtime control room'],
|
|
74
74
|
['settings', '', 'Settings and config browser'],
|
|
75
75
|
['provider', '', 'Choose provider or model family'],
|