@pellux/goodvibes-agent 0.1.101 → 0.1.103
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 +14 -0
- package/README.md +10 -0
- package/docs/README.md +1 -1
- package/docs/getting-started.md +17 -3
- package/package.json +1 -18
- package/src/cli/help.ts +86 -0
- package/src/cli/local-library-command.ts +516 -0
- package/src/cli/management.ts +17 -0
- package/src/cli/memory-command.ts +646 -0
- package/src/cli/package-verification.ts +10 -0
- package/src/cli/parser.ts +8 -0
- package/src/cli/types.ts +3 -0
- package/src/input/agent-workspace-setup.ts +2 -2
- package/src/input/agent-workspace-snapshot.ts +4 -4
- package/src/input/agent-workspace-types.ts +2 -2
- package/src/input/command-registry.ts +0 -8
- package/src/input/feed-context-factory.ts +1 -3
- package/src/input/handler-feed.ts +1 -4
- package/src/input/handler-interactions.ts +0 -1
- package/src/input/handler-modal-stack.ts +0 -1
- package/src/input/handler-modal-token-routes.ts +0 -11
- package/src/input/handler-picker-routes.ts +11 -20
- package/src/input/handler-ui-state.ts +0 -6
- package/src/input/handler.ts +1 -17
- package/src/main.ts +0 -6
- package/src/panels/builtin/agent.ts +0 -17
- package/src/panels/index.ts +0 -2
- package/src/renderer/agent-workspace.ts +3 -3
- package/src/renderer/conversation-overlays.ts +0 -6
- package/src/renderer/live-tail-modal.ts +10 -69
- package/src/renderer/process-modal.ts +28 -530
- package/src/runtime/bootstrap-command-parts.ts +0 -28
- package/src/runtime/bootstrap-core.ts +1 -1
- package/src/runtime/bootstrap.ts +3 -12
- package/src/runtime/services.ts +3 -4
- package/src/tools/{wrfc-agent-guard.ts → agent-tool-policy-guard.ts} +0 -6
- package/src/version.ts +1 -1
- package/src/panels/agent-inspector-panel.ts +0 -521
- package/src/panels/agent-inspector-shared.ts +0 -94
- package/src/panels/agent-logs-panel.ts +0 -559
- package/src/panels/agent-logs-shared.ts +0 -129
- package/src/renderer/agent-detail-modal.ts +0 -331
- package/src/renderer/process-summary.ts +0 -67
package/src/cli/parser.ts
CHANGED
|
@@ -21,6 +21,14 @@ const COMMAND_ALIASES: Readonly<Record<string, GoodVibesCliCommand>> = {
|
|
|
21
21
|
provider: 'providers',
|
|
22
22
|
profiles: 'profiles',
|
|
23
23
|
profile: 'profiles',
|
|
24
|
+
personas: 'personas',
|
|
25
|
+
persona: 'personas',
|
|
26
|
+
skills: 'skills',
|
|
27
|
+
skill: 'skills',
|
|
28
|
+
'agent-skills': 'skills',
|
|
29
|
+
memory: 'memory',
|
|
30
|
+
memories: 'memory',
|
|
31
|
+
recall: 'memory',
|
|
24
32
|
routines: 'routines',
|
|
25
33
|
routine: 'routines',
|
|
26
34
|
auth: 'auth',
|
package/src/cli/types.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface AgentWorkspaceSetupChecklistItem {
|
|
|
11
11
|
export interface AgentWorkspaceSetupChecklistInput {
|
|
12
12
|
readonly provider: string;
|
|
13
13
|
readonly model: string;
|
|
14
|
-
readonly
|
|
14
|
+
readonly runtimeBaseUrl: string;
|
|
15
15
|
readonly sessionMemoryCount: number;
|
|
16
16
|
readonly routineCount: number;
|
|
17
17
|
readonly enabledRoutineCount: number;
|
|
@@ -39,7 +39,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
39
39
|
id: 'runtime',
|
|
40
40
|
label: 'GoodVibes runtime',
|
|
41
41
|
status: 'ready',
|
|
42
|
-
detail: `Agent will connect to ${input.
|
|
42
|
+
detail: `Agent will connect to ${input.runtimeBaseUrl}; runtime ownership stays outside this product.`,
|
|
43
43
|
command: '/health',
|
|
44
44
|
},
|
|
45
45
|
{
|
|
@@ -252,7 +252,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
252
252
|
const ttsVoice = readConfigString(context, 'tts.voice', '(voice default)');
|
|
253
253
|
const ttsLlmProvider = readConfigString(context, 'tts.llmProvider', '');
|
|
254
254
|
const ttsLlmModel = readConfigString(context, 'tts.llmModel', '');
|
|
255
|
-
const
|
|
255
|
+
const runtimeBaseUrl = `http://${host}:${port}`;
|
|
256
256
|
const channels = buildAgentWorkspaceChannels(context);
|
|
257
257
|
const voiceMediaReadiness = buildAgentWorkspaceVoiceMediaReadiness({
|
|
258
258
|
context,
|
|
@@ -262,7 +262,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
262
262
|
const setupChecklist = buildAgentWorkspaceSetupChecklist({
|
|
263
263
|
provider,
|
|
264
264
|
model,
|
|
265
|
-
|
|
265
|
+
runtimeBaseUrl,
|
|
266
266
|
sessionMemoryCount,
|
|
267
267
|
routineCount: routineSnapshot.count,
|
|
268
268
|
enabledRoutineCount: routineSnapshot.enabled,
|
|
@@ -285,8 +285,8 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
285
285
|
sessionId: context.session?.runtime?.sessionId ?? 'unknown',
|
|
286
286
|
workingDirectory: context.workspace?.shellPaths?.workingDirectory ?? 'unavailable',
|
|
287
287
|
homeDirectory: context.workspace?.shellPaths?.homeDirectory ?? 'unavailable',
|
|
288
|
-
|
|
289
|
-
|
|
288
|
+
runtimeBaseUrl,
|
|
289
|
+
runtimeOwnership: 'external',
|
|
290
290
|
sessionMemoryCount,
|
|
291
291
|
localRoutineCount: routineSnapshot.count,
|
|
292
292
|
enabledRoutineCount: routineSnapshot.enabled,
|
|
@@ -120,8 +120,8 @@ export interface AgentWorkspaceRuntimeSnapshot {
|
|
|
120
120
|
readonly sessionId: string;
|
|
121
121
|
readonly workingDirectory: string;
|
|
122
122
|
readonly homeDirectory: string;
|
|
123
|
-
readonly
|
|
124
|
-
readonly
|
|
123
|
+
readonly runtimeBaseUrl: string;
|
|
124
|
+
readonly runtimeOwnership: 'external';
|
|
125
125
|
readonly sessionMemoryCount: number;
|
|
126
126
|
readonly localRoutineCount: number;
|
|
127
127
|
readonly enabledRoutineCount: number;
|
|
@@ -108,19 +108,11 @@ export interface CommandShellUiOpeners {
|
|
|
108
108
|
showPanel?: (panelId: string, pane?: 'top' | 'bottom') => void;
|
|
109
109
|
focusPanels?: () => void;
|
|
110
110
|
focusPrompt?: () => void;
|
|
111
|
-
openOpsPanel?: () => void;
|
|
112
|
-
openCockpitPanel?: () => void;
|
|
113
|
-
openOrchestrationPanel?: () => void;
|
|
114
|
-
openForensicsPanel?: () => void;
|
|
115
|
-
openIncidentPanel?: () => void;
|
|
116
111
|
openPolicyPanel?: () => void;
|
|
117
|
-
openHooksPanel?: () => void;
|
|
118
|
-
openCommunicationPanel?: () => void;
|
|
119
112
|
openMcpWorkspace?: () => void;
|
|
120
113
|
openAgentWorkspace?: () => void;
|
|
121
114
|
openSecurityPanel?: () => void;
|
|
122
115
|
openKnowledgePanel?: () => void;
|
|
123
|
-
openRemotePanel?: () => void;
|
|
124
116
|
openSubscriptionPanel?: () => void;
|
|
125
117
|
}
|
|
126
118
|
|
|
@@ -25,7 +25,6 @@ import type { ConversationManager } from '../core/conversation';
|
|
|
25
25
|
import type { ProcessModal } from '../renderer/process-modal.ts';
|
|
26
26
|
import type { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
27
27
|
import type { BlockActionsMenu } from '../renderer/block-actions.ts';
|
|
28
|
-
import type { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
29
28
|
import type { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
30
29
|
import type { BookmarkModal } from './bookmark-modal.ts';
|
|
31
30
|
import type { SettingsModal } from './settings-modal.ts';
|
|
@@ -83,7 +82,7 @@ export interface FeedContextMutableInit {
|
|
|
83
82
|
* - `selectionModal`, `bookmarkModal`, `settingsModal`, `sessionPickerModal`,
|
|
84
83
|
* `profilePickerModal` — modal objects constructed once
|
|
85
84
|
* - `filePicker`, `modelPicker`, `processModal`, `liveTailModal`,
|
|
86
|
-
* `
|
|
85
|
+
* `contextInspectorModal`, `blockActionsMenu`,
|
|
87
86
|
* `searchManager`, `historySearch`, `onboardingWizard` — service objects constructed once
|
|
88
87
|
* - `panelManager`, `keybindingsManager` — from uiServices, stable
|
|
89
88
|
* - `modalStack` — reference to the handler's shared array
|
|
@@ -117,7 +116,6 @@ export interface FeedContextStableRefs {
|
|
|
117
116
|
onboardingWizard: OnboardingWizardController;
|
|
118
117
|
processModal: ProcessModal;
|
|
119
118
|
liveTailModal: LiveTailModal;
|
|
120
|
-
agentDetailModal: AgentDetailModal;
|
|
121
119
|
contextInspectorModal: ContextInspectorModal;
|
|
122
120
|
blockActionsMenu: BlockActionsMenu;
|
|
123
121
|
searchManager: SearchManager;
|
|
@@ -12,7 +12,6 @@ import type { BlockMeta, ConversationManager } from '../core/conversation';
|
|
|
12
12
|
import { ProcessModal } from '../renderer/process-modal.ts';
|
|
13
13
|
import { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
14
14
|
import { BlockActionsMenu } from '../renderer/block-actions.ts';
|
|
15
|
-
import { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
16
15
|
import { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
17
16
|
import { BookmarkModal } from './bookmark-modal.ts';
|
|
18
17
|
import { SettingsModal } from './settings-modal.ts';
|
|
@@ -73,7 +72,7 @@ import type { ModelPickerTarget } from './model-picker.ts';
|
|
|
73
72
|
* - `selectionModal`, `bookmarkModal`, `settingsModal`, `sessionPickerModal`,
|
|
74
73
|
* `profilePickerModal` — modal objects constructed once in InputHandler constructor
|
|
75
74
|
* - `filePicker`, `modelPicker`, `onboardingWizard`, `processModal`, `liveTailModal`,
|
|
76
|
-
* `
|
|
75
|
+
* `contextInspectorModal`, `blockActionsMenu`, `searchManager`, `historySearch` —
|
|
77
76
|
* service objects constructed once
|
|
78
77
|
* - `panelManager`, `keybindingsManager` — from uiServices, stable for app lifetime
|
|
79
78
|
* - `modalStack` — reference to the handler's shared array (mutated in place)
|
|
@@ -121,7 +120,6 @@ export interface InputFeedContext {
|
|
|
121
120
|
readonly onboardingWizard: OnboardingWizardController;
|
|
122
121
|
readonly processModal: ProcessModal;
|
|
123
122
|
readonly liveTailModal: LiveTailModal;
|
|
124
|
-
readonly agentDetailModal: AgentDetailModal;
|
|
125
123
|
readonly contextInspectorModal: ContextInspectorModal;
|
|
126
124
|
readonly blockActionsMenu: BlockActionsMenu;
|
|
127
125
|
readonly searchManager: SearchManager;
|
|
@@ -211,7 +209,6 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
211
209
|
handleEscape: context.handleEscape,
|
|
212
210
|
liveTailModal: context.liveTailModal,
|
|
213
211
|
processModal: context.processModal,
|
|
214
|
-
agentDetailModal: context.agentDetailModal,
|
|
215
212
|
contextInspectorModal: context.contextInspectorModal,
|
|
216
213
|
modalOpened: context.modalOpened,
|
|
217
214
|
filePicker: context.filePicker,
|
|
@@ -235,7 +235,6 @@ export function handleEscapeForHandler(handler: InputHandler): void {
|
|
|
235
235
|
helpOverlayActive: handler.helpOverlayActive,
|
|
236
236
|
shortcutsOverlayActive: handler.shortcutsOverlayActive,
|
|
237
237
|
bookmarkModal: handler.bookmarkModal,
|
|
238
|
-
agentDetailModal: handler.agentDetailModal,
|
|
239
238
|
liveTailModal: handler.liveTailModal,
|
|
240
239
|
settingsModal: handler.settingsModal,
|
|
241
240
|
mcpWorkspace: handler.mcpWorkspace,
|
|
@@ -121,7 +121,6 @@ export function handleEscape(state: EscapeState): {
|
|
|
121
121
|
shortcutsScrollOffset = 0;
|
|
122
122
|
},
|
|
123
123
|
closeBookmark: () => state.bookmarkModal.close(),
|
|
124
|
-
closeAgentDetail: () => state.agentDetailModal.close(),
|
|
125
124
|
closeLiveTail: () => state.liveTailModal.close(),
|
|
126
125
|
closeSettings: () => state.settingsModal.close(),
|
|
127
126
|
closeMcpWorkspace: () => state.mcpWorkspace?.close(),
|
|
@@ -12,7 +12,6 @@ import { handleMcpWorkspaceToken, type McpWorkspace } from './mcp-workspace.ts';
|
|
|
12
12
|
import type { CommandContext } from './command-registry.ts';
|
|
13
13
|
import type { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
14
14
|
import type { ProcessModal } from '../renderer/process-modal.ts';
|
|
15
|
-
import type { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
16
15
|
import type { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
17
16
|
import type { FilePickerModal } from './file-picker.ts';
|
|
18
17
|
import type { BlockActionsMenu, BlockActionId } from '../renderer/block-actions.ts';
|
|
@@ -65,7 +64,6 @@ export type ModalTokenRouteState = {
|
|
|
65
64
|
handleEscape: () => void;
|
|
66
65
|
liveTailModal: LiveTailModal;
|
|
67
66
|
processModal: ProcessModal;
|
|
68
|
-
agentDetailModal: AgentDetailModal;
|
|
69
67
|
contextInspectorModal: ContextInspectorModal;
|
|
70
68
|
modalOpened: (name: string) => void;
|
|
71
69
|
filePicker: FilePickerModal;
|
|
@@ -240,14 +238,6 @@ export function handleModalTokenRoutes(state: ModalTokenRouteState, token: Input
|
|
|
240
238
|
return withState(state, true);
|
|
241
239
|
}
|
|
242
240
|
|
|
243
|
-
if (handleEscapeOnlyModalToken({
|
|
244
|
-
active: state.agentDetailModal.active,
|
|
245
|
-
requestRender: state.requestRender,
|
|
246
|
-
handleEscape: state.handleEscape,
|
|
247
|
-
}, token)) {
|
|
248
|
-
return withState(state, true);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
241
|
if (handleEscapeOnlyModalToken({
|
|
252
242
|
active: state.contextInspectorModal.active,
|
|
253
243
|
requestRender: state.requestRender,
|
|
@@ -259,7 +249,6 @@ export function handleModalTokenRoutes(state: ModalTokenRouteState, token: Input
|
|
|
259
249
|
if (handleProcessModalToken({
|
|
260
250
|
processModal: state.processModal,
|
|
261
251
|
liveTailModal: state.liveTailModal,
|
|
262
|
-
agentDetailModal: state.agentDetailModal,
|
|
263
252
|
modalOpened: state.modalOpened,
|
|
264
253
|
requestRender: state.requestRender,
|
|
265
254
|
handleEscape: state.handleEscape,
|
|
@@ -204,15 +204,12 @@ type ProcessRouteState = {
|
|
|
204
204
|
getSelected: () => ProcessEntry | undefined;
|
|
205
205
|
close: () => void;
|
|
206
206
|
open: () => void;
|
|
207
|
-
|
|
207
|
+
stopSelected: () => boolean;
|
|
208
208
|
refresh: () => void;
|
|
209
209
|
};
|
|
210
210
|
liveTailModal: {
|
|
211
211
|
open: (entry: ProcessEntry) => void;
|
|
212
212
|
};
|
|
213
|
-
agentDetailModal: {
|
|
214
|
-
open: (id: string) => void;
|
|
215
|
-
};
|
|
216
213
|
modalOpened: (name: string) => void;
|
|
217
214
|
requestRender: () => void;
|
|
218
215
|
handleEscape: () => void;
|
|
@@ -231,20 +228,14 @@ export function handleProcessModalToken(state: ProcessRouteState, token: InputTo
|
|
|
231
228
|
else if (token.logicalName === 'enter') {
|
|
232
229
|
const entry = state.processModal.getSelected();
|
|
233
230
|
if (entry) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
state.agentDetailModal.open(entry.id);
|
|
238
|
-
} else {
|
|
239
|
-
state.modalOpened('liveTail');
|
|
240
|
-
state.processModal.close();
|
|
241
|
-
state.liveTailModal.open(entry);
|
|
242
|
-
}
|
|
231
|
+
state.modalOpened('liveTail');
|
|
232
|
+
state.processModal.close();
|
|
233
|
+
state.liveTailModal.open(entry);
|
|
243
234
|
}
|
|
244
235
|
}
|
|
245
236
|
} else if (token.type === 'text' && token.value === 'k') {
|
|
246
|
-
const
|
|
247
|
-
if (
|
|
237
|
+
const stopped = state.processModal.stopSelected();
|
|
238
|
+
if (stopped) state.processModal.refresh();
|
|
248
239
|
}
|
|
249
240
|
|
|
250
241
|
state.requestRender();
|
|
@@ -256,7 +247,7 @@ type LiveTailRouteState = {
|
|
|
256
247
|
active: boolean;
|
|
257
248
|
scrollUp: () => void;
|
|
258
249
|
scrollDown: () => void;
|
|
259
|
-
|
|
250
|
+
stopProcess: () => boolean;
|
|
260
251
|
close: () => void;
|
|
261
252
|
};
|
|
262
253
|
processModal: {
|
|
@@ -269,8 +260,8 @@ type LiveTailRouteState = {
|
|
|
269
260
|
export function handleLiveTailToken(state: LiveTailRouteState, token: InputToken): boolean {
|
|
270
261
|
if (!state.liveTailModal.active) return false;
|
|
271
262
|
|
|
272
|
-
const
|
|
273
|
-
if (state.liveTailModal.
|
|
263
|
+
const stopAndReturn = (): void => {
|
|
264
|
+
if (state.liveTailModal.stopProcess()) state.handleEscape();
|
|
274
265
|
};
|
|
275
266
|
|
|
276
267
|
if (token.type === 'key') {
|
|
@@ -280,9 +271,9 @@ export function handleLiveTailToken(state: LiveTailRouteState, token: InputToken
|
|
|
280
271
|
}
|
|
281
272
|
if (token.logicalName === 'up') state.liveTailModal.scrollUp();
|
|
282
273
|
else if (token.logicalName === 'down') state.liveTailModal.scrollDown();
|
|
283
|
-
else if (token.logicalName === 'k')
|
|
274
|
+
else if (token.logicalName === 'k') stopAndReturn();
|
|
284
275
|
} else if (token.type === 'text' && token.value === 'k') {
|
|
285
|
-
|
|
276
|
+
stopAndReturn();
|
|
286
277
|
}
|
|
287
278
|
|
|
288
279
|
state.requestRender();
|
|
@@ -55,7 +55,6 @@ export type ActiveModalState = {
|
|
|
55
55
|
helpOverlayActive: boolean;
|
|
56
56
|
shortcutsOverlayActive: boolean;
|
|
57
57
|
bookmarkModal: { active: boolean; close: () => void };
|
|
58
|
-
agentDetailModal: { active: boolean; close: () => void };
|
|
59
58
|
liveTailModal: { active: boolean; close: () => void };
|
|
60
59
|
settingsModal: { active: boolean; close: () => void };
|
|
61
60
|
mcpWorkspace?: { active: boolean; close: () => void; reopen: () => void };
|
|
@@ -76,7 +75,6 @@ export function getActiveModalName(state: ActiveModalState): string | null {
|
|
|
76
75
|
if (state.helpOverlayActive) return 'help';
|
|
77
76
|
if (state.shortcutsOverlayActive) return 'shortcuts';
|
|
78
77
|
if (state.bookmarkModal.active) return 'bookmark';
|
|
79
|
-
if (state.agentDetailModal.active) return 'agentDetail';
|
|
80
78
|
if (state.liveTailModal.active) return 'liveTail';
|
|
81
79
|
if (state.settingsModal.active) return 'settings';
|
|
82
80
|
if (state.mcpWorkspace?.active) return 'mcpWorkspace';
|
|
@@ -98,7 +96,6 @@ export type ModalCloseOps = {
|
|
|
98
96
|
resetHelp: () => void;
|
|
99
97
|
resetShortcuts: () => void;
|
|
100
98
|
closeBookmark: () => void;
|
|
101
|
-
closeAgentDetail: () => void;
|
|
102
99
|
closeLiveTail: () => void;
|
|
103
100
|
closeSettings: () => void;
|
|
104
101
|
closeMcpWorkspace: () => void;
|
|
@@ -126,9 +123,6 @@ export function closeModalByName(name: string, ops: ModalCloseOps): void {
|
|
|
126
123
|
case 'bookmark':
|
|
127
124
|
ops.closeBookmark();
|
|
128
125
|
break;
|
|
129
|
-
case 'agentDetail':
|
|
130
|
-
ops.closeAgentDetail();
|
|
131
|
-
break;
|
|
132
126
|
case 'liveTail':
|
|
133
127
|
ops.closeLiveTail();
|
|
134
128
|
break;
|
package/src/input/handler.ts
CHANGED
|
@@ -21,14 +21,12 @@ import type { BlockMeta, ConversationManager } from '../core/conversation';
|
|
|
21
21
|
import { ProcessModal } from '../renderer/process-modal.ts';
|
|
22
22
|
import { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
23
23
|
import { BlockActionsMenu } from '../renderer/block-actions.ts';
|
|
24
|
-
import { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
25
24
|
import { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
26
25
|
import { BookmarkModal } from './bookmark-modal.ts';
|
|
27
26
|
import { SettingsModal } from './settings-modal.ts';
|
|
28
27
|
import { McpWorkspace } from './mcp-workspace.ts';
|
|
29
28
|
import { AgentWorkspace } from './agent-workspace.ts';
|
|
30
29
|
import { SessionPickerModal } from './session-picker-modal.ts';
|
|
31
|
-
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
32
30
|
import { ProfilePickerModal } from './profile-picker-modal.ts';
|
|
33
31
|
import { OnboardingWizardController, type OnboardingWizardAction, type OnboardingWizardMode } from './onboarding/onboarding-wizard.ts';
|
|
34
32
|
import {
|
|
@@ -155,7 +153,6 @@ export class InputHandler {
|
|
|
155
153
|
public searchManager = new SearchManager();
|
|
156
154
|
public processModal: ProcessModal;
|
|
157
155
|
public liveTailModal: LiveTailModal;
|
|
158
|
-
public agentDetailModal: AgentDetailModal;
|
|
159
156
|
public contextInspectorModal = new ContextInspectorModal();
|
|
160
157
|
public bookmarkModal: BookmarkModal;
|
|
161
158
|
public blockActionsMenu = new BlockActionsMenu();
|
|
@@ -220,8 +217,7 @@ export class InputHandler {
|
|
|
220
217
|
public scroll: (delta: number) => void,
|
|
221
218
|
public exitApp: () => void,
|
|
222
219
|
public readonly uiServices: Pick<UiRuntimeServices,
|
|
223
|
-
'
|
|
224
|
-
| 'environment'
|
|
220
|
+
'environment'
|
|
225
221
|
| 'platform'
|
|
226
222
|
| 'providers'
|
|
227
223
|
| 'sessions'
|
|
@@ -235,22 +231,11 @@ export class InputHandler {
|
|
|
235
231
|
uiServices.providers.providerRegistry,
|
|
236
232
|
);
|
|
237
233
|
this.processModal = new ProcessModal({
|
|
238
|
-
agentManager: uiServices.agents.agentManager,
|
|
239
234
|
processManager: uiServices.shell.processManager,
|
|
240
|
-
wrfcController: uiServices.agents.wrfcController,
|
|
241
|
-
agentEntries: 'hidden',
|
|
242
235
|
});
|
|
243
236
|
this.liveTailModal = new LiveTailModal({
|
|
244
|
-
agentManager: uiServices.agents.agentManager,
|
|
245
237
|
processManager: uiServices.shell.processManager,
|
|
246
238
|
});
|
|
247
|
-
this.agentDetailModal = new AgentDetailModal({
|
|
248
|
-
agentManager: uiServices.agents.agentManager,
|
|
249
|
-
agentMessageBus: uiServices.agents.agentMessageBus,
|
|
250
|
-
sessionLogPathResolver: (agentId) => uiServices.environment.shellPaths.resolveProjectPath(GOODVIBES_AGENT_SURFACE_ROOT, 'sessions', `${agentId}.jsonl`),
|
|
251
|
-
// SDK 0.23.0: supply wrfcController so the modal can show constraint data
|
|
252
|
-
wrfcController: uiServices.agents.wrfcController,
|
|
253
|
-
});
|
|
254
239
|
this.bookmarkModal = new BookmarkModal(uiServices.shell.bookmarkManager);
|
|
255
240
|
this.sessionPickerModal = new SessionPickerModal(uiServices.sessions.sessionManager);
|
|
256
241
|
this.profilePickerModal = new ProfilePickerModal(uiServices.shell.profileManager);
|
|
@@ -294,7 +279,6 @@ export class InputHandler {
|
|
|
294
279
|
onboardingWizard: this.onboardingWizard,
|
|
295
280
|
processModal: this.processModal,
|
|
296
281
|
liveTailModal: this.liveTailModal,
|
|
297
|
-
agentDetailModal: this.agentDetailModal,
|
|
298
282
|
contextInspectorModal: this.contextInspectorModal,
|
|
299
283
|
blockActionsMenu: this.blockActionsMenu,
|
|
300
284
|
searchManager: this.searchManager,
|
package/src/main.ts
CHANGED
|
@@ -398,11 +398,6 @@ async function main() {
|
|
|
398
398
|
scroll,
|
|
399
399
|
exitApp,
|
|
400
400
|
{
|
|
401
|
-
agents: {
|
|
402
|
-
agentManager,
|
|
403
|
-
agentMessageBus: ctx.services.agentMessageBus,
|
|
404
|
-
wrfcController: ctx.services.wrfcController,
|
|
405
|
-
},
|
|
406
401
|
providers: {
|
|
407
402
|
benchmarkStore: ctx.services.benchmarkStore,
|
|
408
403
|
favoritesStore: ctx.services.favoritesStore,
|
|
@@ -450,7 +445,6 @@ async function main() {
|
|
|
450
445
|
input.setConversationManager(conversation);
|
|
451
446
|
input.setContentWidth(getPromptContentWidth());
|
|
452
447
|
input.filePicker.setOnUpdate(() => render());
|
|
453
|
-
input.agentDetailModal.setOnRefresh(() => render());
|
|
454
448
|
input.processModal.setOnRefresh(() => render());
|
|
455
449
|
|
|
456
450
|
// Model picker callback is handled in bootstrap.ts — do not duplicate here.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { PanelManager } from '../panel-manager.ts';
|
|
2
|
-
import { AgentLogsPanel } from '../agent-logs-panel.ts';
|
|
3
2
|
import { ContextVisualizerPanel } from '../context-visualizer-panel.ts';
|
|
4
3
|
import { ThinkingPanel } from '../thinking-panel.ts';
|
|
5
4
|
import { ToolInspectorPanel } from '../tool-inspector-panel.ts';
|
|
@@ -50,22 +49,6 @@ export function registerAgentPanels(manager: PanelManager, deps: ResolvedBuiltin
|
|
|
50
49
|
),
|
|
51
50
|
});
|
|
52
51
|
|
|
53
|
-
manager.registerType({
|
|
54
|
-
id: 'agent-logs',
|
|
55
|
-
name: 'Agents',
|
|
56
|
-
icon: 'A',
|
|
57
|
-
category: 'agent',
|
|
58
|
-
description: 'View-only stream for explicit delegated build/review session records',
|
|
59
|
-
preload: true,
|
|
60
|
-
factory: () => {
|
|
61
|
-
const ui = requireUiServices(deps);
|
|
62
|
-
return new AgentLogsPanel(ui.events.agents, {
|
|
63
|
-
agentManager: ui.agents.agentManager,
|
|
64
|
-
workingDirectory: ui.environment.workingDirectory,
|
|
65
|
-
});
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
52
|
manager.registerType({
|
|
70
53
|
id: 'work-plan',
|
|
71
54
|
name: 'Work Plan',
|
package/src/panels/index.ts
CHANGED
|
@@ -4,8 +4,6 @@ export { BasePanel } from './base-panel.ts';
|
|
|
4
4
|
export { PanelManager } from './panel-manager.ts';
|
|
5
5
|
export { TokenBudgetPanel } from './token-budget-panel.ts';
|
|
6
6
|
export { CostTrackerPanel } from './cost-tracker-panel.ts';
|
|
7
|
-
export { AgentInspectorPanel } from './agent-inspector-panel.ts';
|
|
8
|
-
export { AgentLogsPanel } from './agent-logs-panel.ts';
|
|
9
7
|
export { ProviderHealthPanel } from './provider-health-panel.ts';
|
|
10
8
|
export { ProviderHealthTracker } from './provider-health-tracker.ts';
|
|
11
9
|
export type { ProviderHealth, ProviderStatus } from './provider-health-tracker.ts';
|
|
@@ -194,8 +194,8 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
194
194
|
);
|
|
195
195
|
} else if (category.id === 'setup') {
|
|
196
196
|
base.push(
|
|
197
|
-
{ text: `GoodVibes runtime: ${snapshot.
|
|
198
|
-
{ text: `Runtime owner: ${snapshot.
|
|
197
|
+
{ text: `GoodVibes runtime: ${snapshot.runtimeBaseUrl}`, fg: PALETTE.info },
|
|
198
|
+
{ text: `Runtime owner: ${snapshot.runtimeOwnership}; Agent connects but never starts or restarts it`, fg: PALETTE.good },
|
|
199
199
|
...setupChecklistLines(snapshot),
|
|
200
200
|
{ text: '' },
|
|
201
201
|
{ text: `Workspace: ${snapshot.workingDirectory}`, fg: PALETTE.muted },
|
|
@@ -216,7 +216,7 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
216
216
|
...snapshot.channels.filter((channel) => !channel.enabled),
|
|
217
217
|
].slice(0, 6);
|
|
218
218
|
base.push(
|
|
219
|
-
{ text: `GoodVibes runtime: ${snapshot.
|
|
219
|
+
{ text: `GoodVibes runtime: ${snapshot.runtimeBaseUrl}`, fg: PALETTE.info },
|
|
220
220
|
{ text: `Readiness: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} default target(s) configured.`, fg: PALETTE.info },
|
|
221
221
|
{ text: `Ready channels: ${readyChannels.join(', ') || 'none'}.`, fg: readyChannels.length > 0 ? PALETTE.good : PALETTE.warn },
|
|
222
222
|
{ text: `Needs default target: ${needsTarget.map((channel) => `${channel.label} -> ${channel.defaultTargetKeys.join('|')}`).join(', ') || 'none'}.`, fg: needsTarget.length > 0 ? PALETTE.warn : PALETTE.muted },
|
|
@@ -9,7 +9,6 @@ import { renderSelectionModalOverlay } from './selection-modal-overlay.ts';
|
|
|
9
9
|
import { renderSearchOverlay } from './search-overlay.ts';
|
|
10
10
|
import { renderHistorySearchOverlay } from './history-search-overlay.ts';
|
|
11
11
|
import { renderProcessModal } from './process-modal.ts';
|
|
12
|
-
import { renderAgentDetailModal } from './agent-detail-modal.ts';
|
|
13
12
|
import { renderLiveTailModal } from './live-tail-modal.ts';
|
|
14
13
|
import { renderContextInspector } from './context-inspector.ts';
|
|
15
14
|
import { renderSettingsModal } from './settings-modal.ts';
|
|
@@ -74,11 +73,6 @@ export function applyConversationOverlays(
|
|
|
74
73
|
next = overlayViewportBottom(next, lines, conversationWidth, viewportHeight, bottomDockInset);
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
if (input.agentDetailModal.active) {
|
|
78
|
-
const lines = renderAgentDetailModal(input.agentDetailModal, conversationWidth);
|
|
79
|
-
next = overlayViewportBottom(next, lines, conversationWidth, viewportHeight, bottomDockInset);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
76
|
if (input.liveTailModal.active) {
|
|
83
77
|
const lines = renderLiveTailModal(input.liveTailModal, conversationWidth, viewportHeight);
|
|
84
78
|
next = overlayViewportBottom(next, lines, conversationWidth, viewportHeight, bottomDockInset);
|
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
import { type Line } from '../types/grid.ts';
|
|
2
2
|
import { ModalFactory } from './modal-factory.ts';
|
|
3
3
|
import type { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
4
|
-
import type { AgentManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
5
4
|
import type { ProcessEntry } from './process-modal.ts';
|
|
6
5
|
import { getOverlaySurfaceMetrics, getStableOverlayContentRows } from './overlay-viewport.ts';
|
|
7
6
|
|
|
8
7
|
export interface LiveTailModalDeps {
|
|
9
|
-
readonly agentManager: Pick<AgentManager, 'getStatus'>;
|
|
10
8
|
readonly processManager: Pick<ProcessManager, 'stop' | 'getOutput'>;
|
|
11
9
|
}
|
|
12
10
|
|
|
13
|
-
// ─── LiveTailModal ────────────────────────────────────────────────────────────
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* LiveTailModal — manages state for the live output peek modal.
|
|
17
|
-
*
|
|
18
|
-
* Shows streaming stdout/stderr from a selected shell process or agent
|
|
19
|
-
* progress notes. Auto-scrolls to the bottom unless the user scrolled up.
|
|
20
|
-
*/
|
|
21
11
|
export class LiveTailModal {
|
|
22
12
|
public active = false;
|
|
23
13
|
public entry: ProcessEntry | null = null;
|
|
24
|
-
|
|
25
|
-
/** Number of lines scrolled up from the bottom (0 = at bottom). */
|
|
26
14
|
public scrollOffset = 0;
|
|
27
15
|
|
|
28
16
|
constructor(private readonly deps: LiveTailModalDeps) {}
|
|
@@ -40,64 +28,27 @@ export class LiveTailModal {
|
|
|
40
28
|
}
|
|
41
29
|
|
|
42
30
|
scrollUp(): void {
|
|
43
|
-
this.scrollOffset
|
|
31
|
+
this.scrollOffset += 1;
|
|
44
32
|
}
|
|
45
33
|
|
|
46
34
|
scrollDown(): void {
|
|
47
35
|
this.scrollOffset = Math.max(0, this.scrollOffset - 1);
|
|
48
36
|
}
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
* Stop the current shell process when it is an exec entry.
|
|
52
|
-
* Agent entries are read-only in GoodVibes Agent; build execution and
|
|
53
|
-
* cancellation belong to GoodVibes TUI/shared-session owners.
|
|
54
|
-
*/
|
|
55
|
-
killProcess(): boolean {
|
|
38
|
+
stopProcess(): boolean {
|
|
56
39
|
if (!this.entry) return false;
|
|
57
|
-
|
|
58
|
-
if (this.entry.type === 'exec') {
|
|
59
|
-
return this.deps.processManager.stop(this.entry.id);
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
40
|
+
return this.deps.processManager.stop(this.entry.id);
|
|
62
41
|
}
|
|
63
42
|
|
|
64
|
-
/** Retrieve the current output text for the watched process. */
|
|
65
43
|
getOutput(): string {
|
|
66
44
|
if (!this.entry) return '';
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const combined = [out.stdout, out.stderr].filter(Boolean).join('\n').trim();
|
|
72
|
-
return combined || '(no output yet)';
|
|
73
|
-
} else {
|
|
74
|
-
// For agents, show progress note and status
|
|
75
|
-
const rec = this.deps.agentManager.getStatus(this.entry.id);
|
|
76
|
-
if (!rec) return '(process not found)';
|
|
77
|
-
const parts: string[] = [
|
|
78
|
-
`Task: ${rec.task}`,
|
|
79
|
-
`Status: ${rec.status}`,
|
|
80
|
-
`Tool calls: ${rec.toolCallCount}`,
|
|
81
|
-
];
|
|
82
|
-
if (rec.progress) parts.push(`Progress: ${rec.progress}`);
|
|
83
|
-
if (rec.error) parts.push(`Error: ${rec.error}`);
|
|
84
|
-
return parts.join('\n');
|
|
85
|
-
}
|
|
45
|
+
const output = this.deps.processManager.getOutput(this.entry.id);
|
|
46
|
+
if (!output) return '';
|
|
47
|
+
const combined = [output.stdout, output.stderr].filter(Boolean).join('\n').trim();
|
|
48
|
+
return combined || '(no output yet)';
|
|
86
49
|
}
|
|
87
50
|
}
|
|
88
51
|
|
|
89
|
-
// ─── renderLiveTailModal ──────────────────────────────────────────────────────
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Render the live-tail peek modal as Line[] for overlay in the viewport.
|
|
93
|
-
*
|
|
94
|
-
* Shows a scrollable view of the process output. scrollOffset=0 means the
|
|
95
|
-
* bottom of the output is visible (auto-scroll behaviour).
|
|
96
|
-
*
|
|
97
|
-
* @param modal LiveTailModal state
|
|
98
|
-
* @param width Terminal width
|
|
99
|
-
* @param maxOutputLines Maximum lines to show inside the box (default: 16)
|
|
100
|
-
*/
|
|
101
52
|
export function renderLiveTailModal(
|
|
102
53
|
modal: LiveTailModal,
|
|
103
54
|
width: number,
|
|
@@ -115,35 +66,25 @@ export function renderLiveTailModal(
|
|
|
115
66
|
|
|
116
67
|
const output = modal.getOutput();
|
|
117
68
|
const allLines = output.split('\n');
|
|
118
|
-
|
|
119
|
-
// Apply scroll: scrollOffset=0 → show tail; larger → scroll toward head
|
|
120
69
|
const totalLines = allLines.length;
|
|
121
|
-
// Clamp scrollOffset so we never scroll past the top of the content
|
|
122
70
|
const maxScroll = Math.max(0, totalLines - maxOutputLines);
|
|
123
71
|
const clampedOffset = Math.min(modal.scrollOffset, maxScroll);
|
|
124
72
|
const endIdx = Math.max(maxOutputLines, totalLines - clampedOffset);
|
|
125
73
|
const startIdx = Math.max(0, endIdx - maxOutputLines);
|
|
126
74
|
const visibleLines = allLines.slice(startIdx, endIdx);
|
|
127
75
|
|
|
128
|
-
const typeTag = entry.type === 'agent' ? '[agent]' : '[exec]';
|
|
129
76
|
const maxLabelW = Math.max(20, width - 30);
|
|
130
|
-
const title =
|
|
131
|
-
|
|
132
|
-
// Build scroll indicator for text section header
|
|
77
|
+
const title = `[exec] ${entry.label.slice(0, maxLabelW)}`;
|
|
133
78
|
const scrollInfo = totalLines > maxOutputLines
|
|
134
79
|
? ` Lines ${startIdx + 1}-${Math.min(endIdx, totalLines)} of ${totalLines} [Up/Down] Scroll`
|
|
135
80
|
: '';
|
|
136
81
|
|
|
137
|
-
const contentText = visibleLines.join('\n') || '(no output yet)';
|
|
138
|
-
|
|
139
82
|
const sections: import('./modal-factory.ts').ModalSection[] = [];
|
|
140
|
-
|
|
141
83
|
if (scrollInfo) {
|
|
142
84
|
sections.push({ type: 'text', content: scrollInfo });
|
|
143
85
|
sections.push({ type: 'separator' });
|
|
144
86
|
}
|
|
145
|
-
|
|
146
|
-
sections.push({ type: 'text', content: contentText });
|
|
87
|
+
sections.push({ type: 'text', content: visibleLines.join('\n') || '(no output yet)' });
|
|
147
88
|
|
|
148
89
|
return ModalFactory.createModal({
|
|
149
90
|
title,
|
|
@@ -151,6 +92,6 @@ export function renderLiveTailModal(
|
|
|
151
92
|
margin: 2,
|
|
152
93
|
targetContentRows,
|
|
153
94
|
sections,
|
|
154
|
-
hints: ['[Up/Down] Scroll', '[k] Stop
|
|
95
|
+
hints: ['[Up/Down] Scroll', '[k] Stop process', '[Esc] Back'],
|
|
155
96
|
}, width);
|
|
156
97
|
}
|