@pellux/goodvibes-agent 0.1.116 → 1.0.0
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 +48 -661
- package/README.md +64 -57
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +199180 -192185
- package/docs/README.md +15 -8
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +59 -0
- package/docs/getting-started.md +61 -50
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +48 -11
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +3 -6
- package/src/agent/behavior-discovery-summary.ts +1 -3
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +19 -16
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +27 -26
- package/src/agent/routine-registry.ts +54 -14
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +35 -33
- package/src/agent/routine-schedule-receipts.ts +29 -27
- package/src/agent/runtime-profile-starters.ts +5 -5
- package/src/agent/runtime-profile.ts +91 -12
- package/src/agent/skill-registry.ts +210 -32
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +40 -34
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +14 -9
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +54 -29
- package/src/cli/local-library-command.ts +203 -83
- package/src/cli/management-commands.ts +105 -68
- package/src/cli/management.ts +55 -74
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -3
- package/src/cli/profiles-command.ts +166 -31
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +176 -40
- package/src/cli/service-posture.ts +16 -16
- package/src/cli/status.ts +56 -135
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
- package/src/input/agent-workspace-access-command-editors.ts +170 -0
- package/src/input/agent-workspace-activation.ts +35 -8
- package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
- package/src/input/agent-workspace-basic-command-editors.ts +502 -9
- package/src/input/agent-workspace-categories.ts +423 -51
- package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
- package/src/input/agent-workspace-channel-command-editors.ts +65 -0
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +41 -3
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +166 -1
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
- package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +67 -0
- package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
- package/src/input/agent-workspace-library-command-editors.ts +35 -0
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +81 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
- package/src/input/agent-workspace-operations-command-editors.ts +196 -0
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
- package/src/input/agent-workspace-provider-command-editors.ts +93 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-requirements.ts +11 -0
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
- package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
- package/src/input/agent-workspace-session-command-editors.ts +249 -0
- package/src/input/agent-workspace-setup.ts +37 -16
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
- package/src/input/agent-workspace-snapshot.ts +162 -21
- package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
- package/src/input/agent-workspace-task-command-editors.ts +47 -0
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +212 -4
- package/src/input/agent-workspace-voice-media.ts +4 -7
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +178 -240
- package/src/input/command-registry.ts +5 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
- package/src/input/commands/agent-skills-runtime.ts +149 -72
- package/src/input/commands/agent-workspace-runtime.ts +23 -6
- package/src/input/commands/brief-runtime.ts +55 -25
- package/src/input/commands/channels-runtime.ts +147 -33
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +149 -126
- package/src/input/commands/knowledge.ts +82 -60
- package/src/input/commands/local-provider-runtime.ts +43 -21
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +10 -20
- package/src/input/commands/mcp-runtime.ts +63 -46
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -76
- package/src/input/commands/personas-runtime.ts +46 -31
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +35 -98
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +50 -9
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +99 -45
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +6 -11
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +134 -104
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +38 -17
- package/src/input/commands/subscription-runtime.ts +54 -185
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +21 -21
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +6 -2
- package/src/input/feed-context-factory.ts +2 -2
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -26
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -5
- package/src/input/handler-interactions.ts +9 -36
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +52 -91
- package/src/input/handler-shortcuts.ts +16 -7
- package/src/input/handler.ts +50 -23
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +27 -16
- package/src/input/mcp-workspace.ts +90 -26
- package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +62 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
- package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
- package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
- package/src/input/onboarding/onboarding-wizard.ts +87 -2
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +20 -66
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -10
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +4 -4
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +3 -12
- package/src/panels/builtin/session.ts +32 -24
- package/src/panels/builtin/shared.ts +7 -7
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +19 -12
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +48 -7
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +6 -6
- package/src/panels/system-messages-panel.ts +3 -3
- package/src/panels/tasks-panel.ts +21 -14
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +3 -3
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +254 -57
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +112 -34
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +176 -43
- package/src/renderer/model-picker-overlay.ts +58 -3
- package/src/renderer/model-workspace.ts +104 -22
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +21 -5
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +88 -55
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +11 -8
- package/src/runtime/bootstrap-core.ts +23 -65
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +46 -8
- package/src/runtime/bootstrap.ts +36 -46
- package/src/runtime/connected-host-auth.ts +47 -0
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -5
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +288 -74
- package/src/runtime/onboarding/derivation.ts +10 -13
- package/src/runtime/onboarding/snapshot.ts +2 -17
- package/src/runtime/onboarding/types.ts +34 -20
- package/src/runtime/onboarding/verify.ts +105 -4
- package/src/runtime/operator-token-cleanup.ts +3 -3
- package/src/runtime/services.ts +95 -11
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +17 -38
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +279 -73
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +13 -15
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/docs/connected-services.md +0 -51
- package/src/cli/package-verification.ts +0 -274
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -17
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -13,6 +13,21 @@ import { BookmarkModal } from '../input/bookmark-modal.ts';
|
|
|
13
13
|
import type { BookmarkEntry } from '@pellux/goodvibes-sdk/platform/bookmarks';
|
|
14
14
|
import { getOverlayContentBudget, getStableOverlayContentRows } from './overlay-viewport.ts';
|
|
15
15
|
|
|
16
|
+
const BOOKMARK_MODAL_TITLE = 'Bookmarks';
|
|
17
|
+
const BOOKMARK_MODAL_EMPTY_MESSAGE = 'No bookmarks - use Ctrl+B to bookmark a block';
|
|
18
|
+
const BOOKMARK_MODAL_COLUMNS = ' Key Label Time';
|
|
19
|
+
const BOOKMARK_MODAL_HINTS = ['Up/Down Navigate', 'Enter Jump', 'o Open file', 'd Remove', 'Esc Close'];
|
|
20
|
+
|
|
21
|
+
export function renderBookmarkModalPackageText(): string {
|
|
22
|
+
return [
|
|
23
|
+
BOOKMARK_MODAL_TITLE,
|
|
24
|
+
BOOKMARK_MODAL_EMPTY_MESSAGE,
|
|
25
|
+
BOOKMARK_MODAL_COLUMNS.trim(),
|
|
26
|
+
'[<start>-<end> of <count>]',
|
|
27
|
+
...BOOKMARK_MODAL_HINTS,
|
|
28
|
+
].join('\n');
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
// ---------------------------------------------------------------------------
|
|
17
32
|
// Helpers
|
|
18
33
|
// ---------------------------------------------------------------------------
|
|
@@ -60,7 +75,7 @@ export function renderBookmarkModal(
|
|
|
60
75
|
const relSelected = Math.max(0, modal.selectedIndex - modal.scrollOffset);
|
|
61
76
|
|
|
62
77
|
const items = visible.length === 0
|
|
63
|
-
? [{ label:
|
|
78
|
+
? [{ label: BOOKMARK_MODAL_EMPTY_MESSAGE, selected: false }]
|
|
64
79
|
: visible.map((entry, i) => ({
|
|
65
80
|
label: entryLabel(entry),
|
|
66
81
|
selected: i === relSelected,
|
|
@@ -68,7 +83,7 @@ export function renderBookmarkModal(
|
|
|
68
83
|
const sections: import('./modal-factory.ts').ModalSection[] = [
|
|
69
84
|
{
|
|
70
85
|
type: 'text',
|
|
71
|
-
content:
|
|
86
|
+
content: BOOKMARK_MODAL_COLUMNS,
|
|
72
87
|
style: { dim: true },
|
|
73
88
|
},
|
|
74
89
|
{ type: 'separator' },
|
|
@@ -90,11 +105,11 @@ export function renderBookmarkModal(
|
|
|
90
105
|
|
|
91
106
|
return ModalFactory.createModal(
|
|
92
107
|
{
|
|
93
|
-
title:
|
|
108
|
+
title: `${BOOKMARK_MODAL_TITLE} ${totalStr}`,
|
|
94
109
|
width: 80,
|
|
95
110
|
targetContentRows,
|
|
96
111
|
sections,
|
|
97
|
-
hints:
|
|
112
|
+
hints: BOOKMARK_MODAL_HINTS,
|
|
98
113
|
},
|
|
99
114
|
width,
|
|
100
115
|
);
|
package/src/renderer/buffer.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type Line, type Cell, createEmptyLine, createEmptyCell } from '../types/grid.ts';
|
|
2
2
|
|
|
3
|
+
const CELL_KEYS: readonly (keyof Cell)[] = ['char', 'fg', 'bg', 'bold', 'dim', 'underline', 'italic', 'strikethrough', 'link'];
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* TerminalBuffer - Represents a 2D grid of styled cells.
|
|
5
7
|
* Tracks a per-row dirty bitmap so the diff engine can skip rows that were
|
|
@@ -21,8 +23,8 @@ export class TerminalBuffer {
|
|
|
21
23
|
// already matches the current cell value (idempotent write).
|
|
22
24
|
const current = this.cells[y][x]!;
|
|
23
25
|
let changed = false;
|
|
24
|
-
for (const
|
|
25
|
-
if ((cell
|
|
26
|
+
for (const key of CELL_KEYS) {
|
|
27
|
+
if (Object.prototype.hasOwnProperty.call(cell, key) && cell[key] !== current[key]) {
|
|
26
28
|
changed = true;
|
|
27
29
|
break;
|
|
28
30
|
}
|
|
@@ -3,6 +3,45 @@ import { ModalFactory } from './modal-factory.ts';
|
|
|
3
3
|
import type { ConversationManager } from '../core/conversation';
|
|
4
4
|
import { getOverlayContentBudget, getOverlaySurfaceMetrics, getStableOverlayContentRows } from './overlay-viewport.ts';
|
|
5
5
|
|
|
6
|
+
const CONTEXT_INSPECTOR_TITLE = 'Context Inspector';
|
|
7
|
+
const CONTEXT_INSPECTOR_EMPTY_MESSAGE = 'No messages in conversation yet.';
|
|
8
|
+
const CONTEXT_INSPECTOR_CLOSE_HINTS = ['[Esc] Close'];
|
|
9
|
+
const CONTEXT_INSPECTOR_CONTEXT_HINTS = ['[*] >10% of context', '[Esc] Close'];
|
|
10
|
+
const CONTEXT_INSPECTOR_FULL_WARNING = 'WARNING: context is 80%+ full. Open Agent Workspace -> Conversation -> Compact conversation.';
|
|
11
|
+
const CONTEXT_INSPECTOR_COMPACT_GUIDANCE = 'Open Agent Workspace -> Conversation -> Compact conversation to summarise and reduce context size.';
|
|
12
|
+
|
|
13
|
+
function contextInspectorTotalText(
|
|
14
|
+
totalTokens: string,
|
|
15
|
+
messageCount: string | number,
|
|
16
|
+
capacity: string | null = null,
|
|
17
|
+
): string {
|
|
18
|
+
const capacityStr = capacity ? ` | Capacity: ${totalTokens} / ${capacity}` : '';
|
|
19
|
+
return `Total: ~${totalTokens} tokens (${messageCount} messages)${capacityStr}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function contextInspectorOlderMessagesText(count: string | number): string {
|
|
23
|
+
return `(${count} older messages not shown)`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function contextInspectorCompactionHintText(count: string | number, percent: string): string {
|
|
27
|
+
const suffix = typeof count === 'number' && count === 1 ? '' : 's';
|
|
28
|
+
return `Compaction hint: ${count} message${suffix} use ${percent} of context.`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function renderContextInspectorPackageText(): string {
|
|
32
|
+
return [
|
|
33
|
+
CONTEXT_INSPECTOR_TITLE,
|
|
34
|
+
CONTEXT_INSPECTOR_EMPTY_MESSAGE,
|
|
35
|
+
contextInspectorTotalText('<tokens>', '<messages>', '<window> (<percent>)'),
|
|
36
|
+
CONTEXT_INSPECTOR_FULL_WARNING,
|
|
37
|
+
contextInspectorOlderMessagesText('<count>'),
|
|
38
|
+
contextInspectorCompactionHintText('<count>', '<percent>'),
|
|
39
|
+
CONTEXT_INSPECTOR_COMPACT_GUIDANCE,
|
|
40
|
+
...CONTEXT_INSPECTOR_CLOSE_HINTS,
|
|
41
|
+
...CONTEXT_INSPECTOR_CONTEXT_HINTS,
|
|
42
|
+
].join('\n');
|
|
43
|
+
}
|
|
44
|
+
|
|
6
45
|
// ─── ContextInspectorModal ────────────────────────────────────────────────────
|
|
7
46
|
|
|
8
47
|
/**
|
|
@@ -67,14 +106,14 @@ export function renderContextInspector(
|
|
|
67
106
|
|
|
68
107
|
if (messages.length === 0) {
|
|
69
108
|
return ModalFactory.createModal({
|
|
70
|
-
title:
|
|
109
|
+
title: CONTEXT_INSPECTOR_TITLE,
|
|
71
110
|
width: metrics.boxWidth,
|
|
72
111
|
margin: metrics.margin,
|
|
73
112
|
targetContentRows,
|
|
74
113
|
sections: [
|
|
75
|
-
{ type: 'text', content:
|
|
114
|
+
{ type: 'text', content: CONTEXT_INSPECTOR_EMPTY_MESSAGE },
|
|
76
115
|
],
|
|
77
|
-
hints:
|
|
116
|
+
hints: CONTEXT_INSPECTOR_CLOSE_HINTS,
|
|
78
117
|
}, width);
|
|
79
118
|
}
|
|
80
119
|
|
|
@@ -139,19 +178,17 @@ export function renderContextInspector(
|
|
|
139
178
|
const sections: import('./modal-factory.ts').ModalSection[] = [];
|
|
140
179
|
|
|
141
180
|
// Summary header
|
|
142
|
-
const capacityStr = contextWindow > 0
|
|
143
|
-
? ` | Capacity: ${fmtN(totalTokens)} / ${fmtN(contextWindow)} (${fmtPct(totalTokens / contextWindow)})`
|
|
144
|
-
: '';
|
|
181
|
+
const capacityStr = contextWindow > 0 ? `${fmtN(contextWindow)} (${fmtPct(totalTokens / contextWindow)})` : null;
|
|
145
182
|
sections.push({
|
|
146
183
|
type: 'text',
|
|
147
|
-
content:
|
|
184
|
+
content: contextInspectorTotalText(fmtN(totalTokens), messages.length, capacityStr),
|
|
148
185
|
style: { bold: true },
|
|
149
186
|
});
|
|
150
187
|
|
|
151
188
|
if (contextWindow > 0 && totalTokens / contextWindow >= 0.80) {
|
|
152
189
|
sections.push({
|
|
153
190
|
type: 'text',
|
|
154
|
-
content:
|
|
191
|
+
content: CONTEXT_INSPECTOR_FULL_WARNING,
|
|
155
192
|
style: { fg: '#ff9900', bold: true },
|
|
156
193
|
});
|
|
157
194
|
}
|
|
@@ -169,7 +206,7 @@ export function renderContextInspector(
|
|
|
169
206
|
if (startOffset > 0) {
|
|
170
207
|
sections.push({
|
|
171
208
|
type: 'text',
|
|
172
|
-
content:
|
|
209
|
+
content: contextInspectorOlderMessagesText(startOffset),
|
|
173
210
|
style: { dim: true },
|
|
174
211
|
});
|
|
175
212
|
}
|
|
@@ -198,22 +235,22 @@ export function renderContextInspector(
|
|
|
198
235
|
);
|
|
199
236
|
sections.push({
|
|
200
237
|
type: 'text',
|
|
201
|
-
content:
|
|
238
|
+
content: contextInspectorCompactionHintText(largeMsgs.length, largePct),
|
|
202
239
|
style: { fg: '#00ffcc' },
|
|
203
240
|
});
|
|
204
241
|
sections.push({
|
|
205
242
|
type: 'text',
|
|
206
|
-
content:
|
|
243
|
+
content: CONTEXT_INSPECTOR_COMPACT_GUIDANCE,
|
|
207
244
|
style: { dim: true },
|
|
208
245
|
});
|
|
209
246
|
}
|
|
210
247
|
|
|
211
248
|
return ModalFactory.createModal({
|
|
212
|
-
title:
|
|
249
|
+
title: CONTEXT_INSPECTOR_TITLE,
|
|
213
250
|
width: metrics.boxWidth,
|
|
214
251
|
margin: metrics.margin,
|
|
215
252
|
targetContentRows,
|
|
216
253
|
sections,
|
|
217
|
-
hints:
|
|
254
|
+
hints: CONTEXT_INSPECTOR_CONTEXT_HINTS,
|
|
218
255
|
}, width);
|
|
219
256
|
}
|
package/src/renderer/diff.ts
CHANGED
|
@@ -31,7 +31,7 @@ export class DiffEngine {
|
|
|
31
31
|
for (let y = 0; y < newBuffer.height; y++) {
|
|
32
32
|
// Skip rows that were not written in either the old or new buffer.
|
|
33
33
|
// If neither side touched the row, both must match the prior frame:
|
|
34
|
-
// old row
|
|
34
|
+
// old row had no write this frame (clean) and new row is also
|
|
35
35
|
// clean, so the on-screen content is still correct. No diff needed.
|
|
36
36
|
const newDirty = newBuffer.dirtyRows[y] ?? false;
|
|
37
37
|
const oldDirty = oldBuffer ? (oldBuffer.dirtyRows[y] ?? false) : true;
|
|
@@ -11,6 +11,20 @@ import {
|
|
|
11
11
|
} from './overlay-box.ts';
|
|
12
12
|
import { getOverlaySurfaceMetrics } from './overlay-viewport.ts';
|
|
13
13
|
|
|
14
|
+
const FILE_PICKER_TITLE = 'Select File';
|
|
15
|
+
const FILE_PICKER_SEARCH_PREFIX = '@ ';
|
|
16
|
+
const FILE_PICKER_EMPTY_MESSAGE = 'No matching files';
|
|
17
|
+
const FILE_PICKER_HINTS = '[Up/Down] Navigate [/] Search [Enter] Select [Esc] Cancel';
|
|
18
|
+
|
|
19
|
+
export function renderFilePickerPackageText(): string {
|
|
20
|
+
return [
|
|
21
|
+
FILE_PICKER_TITLE,
|
|
22
|
+
FILE_PICKER_SEARCH_PREFIX.trim(),
|
|
23
|
+
FILE_PICKER_EMPTY_MESSAGE,
|
|
24
|
+
FILE_PICKER_HINTS,
|
|
25
|
+
].join('\n');
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
/**
|
|
15
29
|
* Render the file picker modal as Line[] for overlay in the viewport.
|
|
16
30
|
* Shows a bordered box with fuzzy-matched file results.
|
|
@@ -37,13 +51,13 @@ export function renderFilePickerOverlay(
|
|
|
37
51
|
|
|
38
52
|
// Title bar
|
|
39
53
|
const titleLine = createOverlayFilledBorderLine(width, layout, OVERLAY_GLYPHS.topLeft, OVERLAY_GLYPHS.horizontal, OVERLAY_GLYPHS.topRight, borderFg, DEFAULT_OVERLAY_PALETTE.titleBg);
|
|
40
|
-
putOverlayText(titleLine, layout.margin + 2, layout.width - 4,
|
|
54
|
+
putOverlayText(titleLine, layout.margin + 2, layout.width - 4, FILE_PICKER_TITLE, { fg: titleFg, bold: true });
|
|
41
55
|
lines.push(titleLine);
|
|
42
56
|
|
|
43
57
|
// Search input
|
|
44
58
|
const queryDisplay = picker.query || '';
|
|
45
59
|
const searchLine = createOverlayContentLine(width, layout, borderFg, DEFAULT_OVERLAY_PALETTE.inputBg);
|
|
46
|
-
const searchPrefix =
|
|
60
|
+
const searchPrefix = FILE_PICKER_SEARCH_PREFIX;
|
|
47
61
|
const queryText = fitDisplay(`${queryDisplay}${picker.searchFocused ? OVERLAY_GLYPHS.cursor : ''}`, Math.max(0, contentW - getDisplayWidth(searchPrefix)));
|
|
48
62
|
putOverlayText(searchLine, layout.margin + 2, getDisplayWidth(searchPrefix), searchPrefix, { fg: picker.searchFocused ? bodyFg : mutedFg });
|
|
49
63
|
putOverlayText(searchLine, layout.margin + 2 + getDisplayWidth(searchPrefix), contentW - getDisplayWidth(searchPrefix), queryText, { fg: picker.query.length > 0 || picker.searchFocused ? bodyFg : mutedFg });
|
|
@@ -54,8 +68,8 @@ export function renderFilePickerOverlay(
|
|
|
54
68
|
|
|
55
69
|
// Results
|
|
56
70
|
if (picker.results.length === 0) {
|
|
57
|
-
|
|
58
|
-
putOverlayText(noResults, layout.margin + 2, contentW, fitDisplay(
|
|
71
|
+
const noResults = createOverlayContentLine(width, layout, borderFg, DEFAULT_OVERLAY_PALETTE.bodyBg);
|
|
72
|
+
putOverlayText(noResults, layout.margin + 2, contentW, fitDisplay(FILE_PICKER_EMPTY_MESSAGE, contentW), { fg: '244', dim: true });
|
|
59
73
|
lines.push(noResults);
|
|
60
74
|
} else {
|
|
61
75
|
const maxVisible = metrics.contentRows;
|
|
@@ -92,9 +106,8 @@ export function renderFilePickerOverlay(
|
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
// Bottom border with hints
|
|
95
|
-
const hints = '[Up/Down] Navigate [/] Search [Enter] Select [Esc] Cancel';
|
|
96
109
|
const bottomLine = createOverlayFilledBorderLine(width, layout, OVERLAY_GLYPHS.bottomLeft, OVERLAY_GLYPHS.horizontal, OVERLAY_GLYPHS.bottomRight, borderFg, DEFAULT_OVERLAY_PALETTE.sectionBg);
|
|
97
|
-
putOverlayText(bottomLine, layout.margin + 2, layout.width - 4, truncateDisplay(
|
|
110
|
+
putOverlayText(bottomLine, layout.margin + 2, layout.width - 4, truncateDisplay(FILE_PICKER_HINTS, layout.width - 4), { fg: mutedFg, dim: true });
|
|
98
111
|
lines.push(bottomLine);
|
|
99
112
|
|
|
100
113
|
return lines;
|
|
@@ -12,6 +12,105 @@ import { getOverlaySurfaceMetrics } from './overlay-viewport.ts';
|
|
|
12
12
|
import { getVisibleWindow } from './surface-layout.ts';
|
|
13
13
|
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
14
14
|
|
|
15
|
+
const FEATURED_HELP_COMMANDS: Array<[name: string, argHint: string, desc: string]> = [
|
|
16
|
+
['agent', '', 'Open workspace; press / there to search every action'],
|
|
17
|
+
['agent', 'setup', 'Open setup workspace for local behavior, channels, and voice'],
|
|
18
|
+
['agent', 'knowledge', 'Open isolated Agent Knowledge workspace actions'],
|
|
19
|
+
['agent', 'voice-media', 'Open voice, image, browser, and media workspace actions'],
|
|
20
|
+
['setup', '', 'Open Agent setup with current settings preloaded'],
|
|
21
|
+
['knowledge', 'status', 'Inspect isolated Agent Knowledge readiness'],
|
|
22
|
+
['memory', '', 'Manage Agent-local memory records'],
|
|
23
|
+
['personas', '', 'Manage serial Agent operating personas'],
|
|
24
|
+
['skills', '', 'Manage Agent-local skills and bundles'],
|
|
25
|
+
['routines', '', 'Manage reusable main-conversation routines'],
|
|
26
|
+
['workplan', '', 'Inspect shared work-plan state'],
|
|
27
|
+
['approval', '', 'Review and explicitly act on approvals'],
|
|
28
|
+
['automation', '', 'Run confirmed connected-host automation actions'],
|
|
29
|
+
['schedule', 'remind', 'Create confirmed reminders or inspect schedules'],
|
|
30
|
+
['delegate', '', 'Explicitly hand build/fix/review work to GoodVibes TUI'],
|
|
31
|
+
['mcp', '', 'Inspect MCP servers and tool readiness'],
|
|
32
|
+
['provider', '', 'Choose provider or model family'],
|
|
33
|
+
['model', '', 'Select the active model route'],
|
|
34
|
+
['subscription', '', 'Review provider logins and subscriptions'],
|
|
35
|
+
['secrets', '', 'Manage secret references without printing values'],
|
|
36
|
+
['bundle', 'inspect', 'Inspect Agent support bundles from the TUI'],
|
|
37
|
+
['compat', '', 'Inspect connected-host and Agent Knowledge compatibility'],
|
|
38
|
+
['health', '', 'Run Agent runtime and setup diagnostics'],
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const HELP_OVERLAY_STATIC_TEXT = [
|
|
42
|
+
'Core Navigation',
|
|
43
|
+
'Scroll / history recall',
|
|
44
|
+
'Scroll by full page',
|
|
45
|
+
'Search conversation (Ctrl+F)',
|
|
46
|
+
'Prompt And Editing',
|
|
47
|
+
'Submit message',
|
|
48
|
+
'Insert newline',
|
|
49
|
+
'Paste (image priority)',
|
|
50
|
+
'Undo / redo',
|
|
51
|
+
'Overlays And Workspace',
|
|
52
|
+
'Toggle help',
|
|
53
|
+
'Full keyboard shortcuts',
|
|
54
|
+
'Open the Agent operator workspace',
|
|
55
|
+
'Search all Agent workspace actions',
|
|
56
|
+
'Open selected action or form',
|
|
57
|
+
'Quick Start',
|
|
58
|
+
'Available Slash Commands',
|
|
59
|
+
'More Commands',
|
|
60
|
+
'Essentials',
|
|
61
|
+
'Show this help overlay',
|
|
62
|
+
'Keyboard shortcut reference',
|
|
63
|
+
'Select LLM model',
|
|
64
|
+
'Clear conversation',
|
|
65
|
+
] as const;
|
|
66
|
+
|
|
67
|
+
const SHORTCUT_OVERLAY_STATIC_TEXT = [
|
|
68
|
+
'Navigation',
|
|
69
|
+
'Scroll / history recall',
|
|
70
|
+
'Scroll by full page',
|
|
71
|
+
'Jump to start / end of line',
|
|
72
|
+
'Search conversation',
|
|
73
|
+
'Scroll conversation or hovered panel',
|
|
74
|
+
'Editing',
|
|
75
|
+
'Submit message',
|
|
76
|
+
'Insert newline',
|
|
77
|
+
'Open file picker',
|
|
78
|
+
'Slash command mode',
|
|
79
|
+
'Paste (image priority)',
|
|
80
|
+
'Undo / redo',
|
|
81
|
+
'Clear prompt',
|
|
82
|
+
'Delete word backward',
|
|
83
|
+
'Kill to end of line',
|
|
84
|
+
'Move to start of line',
|
|
85
|
+
'Next error / line end',
|
|
86
|
+
'Actions',
|
|
87
|
+
'Collapse/expand block',
|
|
88
|
+
'Bookmark block',
|
|
89
|
+
'Copy block to clipboard',
|
|
90
|
+
'Block file save disabled; copy or export',
|
|
91
|
+
'Copy selection',
|
|
92
|
+
'Process monitor',
|
|
93
|
+
'Help overlay',
|
|
94
|
+
'Exit',
|
|
95
|
+
'Workspace',
|
|
96
|
+
'Swap focus between input and active Agent workspace',
|
|
97
|
+
'Open the Agent operator workspace',
|
|
98
|
+
'Cycle Agent workspace category forward',
|
|
99
|
+
'Cycle Agent workspace category backward',
|
|
100
|
+
'Config: /keybindings to list and customize',
|
|
101
|
+
] as const;
|
|
102
|
+
|
|
103
|
+
export function renderHelpOverlayPackageText(): string {
|
|
104
|
+
return [
|
|
105
|
+
...HELP_OVERLAY_STATIC_TEXT,
|
|
106
|
+
...FEATURED_HELP_COMMANDS.flatMap(([name, argHint, desc]) => [
|
|
107
|
+
argHint ? `/${name} ${argHint}` : `/${name}`,
|
|
108
|
+
desc,
|
|
109
|
+
]),
|
|
110
|
+
...SHORTCUT_OVERLAY_STATIC_TEXT,
|
|
111
|
+
].join('\n');
|
|
112
|
+
}
|
|
113
|
+
|
|
15
114
|
function toModalSections(rows: readonly string[]): import('./modal-factory.ts').ModalSection[] {
|
|
16
115
|
return rows.map((row) => {
|
|
17
116
|
if (row === '') return { type: 'spacer' as const };
|
|
@@ -57,37 +156,16 @@ export function renderHelpOverlay(
|
|
|
57
156
|
` ${kb('paste').padEnd(20)} Paste (image priority)`,
|
|
58
157
|
` ${(kb('undo') + ' / ' + kb('redo')).padEnd(20)} Undo / redo`,
|
|
59
158
|
'',
|
|
60
|
-
' Overlays And
|
|
159
|
+
' Overlays And Workspace',
|
|
61
160
|
' ' + '\u2500'.repeat(40),
|
|
62
161
|
` ${'?'.padEnd(20)} Toggle help`,
|
|
63
162
|
` ${'/shortcuts'.padEnd(20)} Full keyboard shortcuts`,
|
|
64
|
-
` ${kb('panel-picker').padEnd(20)} Open
|
|
163
|
+
` ${kb('panel-picker').padEnd(20)} Open the Agent operator workspace`,
|
|
164
|
+
` ${'Workspace /'.padEnd(20)} Search all Agent workspace actions`,
|
|
165
|
+
` ${'Workspace Enter'.padEnd(20)} Open selected action or form`,
|
|
65
166
|
'',
|
|
66
167
|
];
|
|
67
168
|
|
|
68
|
-
// Featured commands shown in the Quick Start section.
|
|
69
|
-
// Each entry is [commandName, subcommandOrArgHint, description].
|
|
70
|
-
// Commands not registered in the live registry are omitted at render time.
|
|
71
|
-
const FEATURED_COMMANDS: Array<[name: string, argHint: string, desc: string]> = [
|
|
72
|
-
['agent', '', 'Open the Agent operator workspace'],
|
|
73
|
-
['setup', '', 'Open Agent setup with current settings preloaded'],
|
|
74
|
-
['knowledge', 'status', 'Inspect isolated Agent Knowledge readiness'],
|
|
75
|
-
['memory', '', 'Manage local Agent memory records'],
|
|
76
|
-
['personas', '', 'Manage serial Agent operating personas'],
|
|
77
|
-
['agent-skills', '', 'Manage local Agent skills and bundles'],
|
|
78
|
-
['routines', '', 'Manage reusable main-conversation routines'],
|
|
79
|
-
['workplan', '', 'Inspect shared work-plan state'],
|
|
80
|
-
['approval', '', 'Review and explicitly act on approvals'],
|
|
81
|
-
['schedule', 'remind', 'Create confirmed reminders or inspect schedules'],
|
|
82
|
-
['delegate', '', 'Explicitly hand build/fix/review work to GoodVibes TUI'],
|
|
83
|
-
['mcp', '', 'Inspect MCP servers and tool readiness'],
|
|
84
|
-
['provider', '', 'Choose provider or model family'],
|
|
85
|
-
['model', '', 'Select the active model route'],
|
|
86
|
-
['subscription', '', 'Review provider logins and subscriptions'],
|
|
87
|
-
['secrets', '', 'Manage secret references without printing values'],
|
|
88
|
-
['health', '', 'Run Agent runtime and setup diagnostics'],
|
|
89
|
-
];
|
|
90
|
-
|
|
91
169
|
// Build command rows from featured list, filtering out unregistered commands.
|
|
92
170
|
function featuredRow(name: string, argHint: string, desc: string): string {
|
|
93
171
|
const invocation = argHint ? `/${name} ${argHint}` : `/${name}`;
|
|
@@ -96,7 +174,7 @@ export function renderHelpOverlay(
|
|
|
96
174
|
|
|
97
175
|
const quickStartRows: string[] = [];
|
|
98
176
|
try {
|
|
99
|
-
for (const [name, argHint, desc] of
|
|
177
|
+
for (const [name, argHint, desc] of FEATURED_HELP_COMMANDS) {
|
|
100
178
|
if (!hasCommand(name)) continue; // omit if not in live registry
|
|
101
179
|
quickStartRows.push(featuredRow(name, argHint, desc));
|
|
102
180
|
}
|
|
@@ -105,7 +183,7 @@ export function renderHelpOverlay(
|
|
|
105
183
|
// unfiltered quick-start list so /help remains reachable.
|
|
106
184
|
logger.warn(`[help-overlay] registry traversal error during command filter; using unfiltered list: ${err}`);
|
|
107
185
|
quickStartRows.length = 0;
|
|
108
|
-
for (const [name, argHint, desc] of
|
|
186
|
+
for (const [name, argHint, desc] of FEATURED_HELP_COMMANDS) {
|
|
109
187
|
quickStartRows.push(featuredRow(name, argHint, desc));
|
|
110
188
|
}
|
|
111
189
|
}
|
|
@@ -123,7 +201,7 @@ export function renderHelpOverlay(
|
|
|
123
201
|
'knowledge',
|
|
124
202
|
'memory',
|
|
125
203
|
'personas',
|
|
126
|
-
'
|
|
204
|
+
'skills',
|
|
127
205
|
'routines',
|
|
128
206
|
'workplan',
|
|
129
207
|
'approval',
|
|
@@ -238,7 +316,7 @@ export function renderShortcutsOverlay(
|
|
|
238
316
|
row(kb('clear-prompt'), 'Clear prompt'),
|
|
239
317
|
row(kb('delete-word'), 'Delete word backward'),
|
|
240
318
|
row(kb('kill-line'), 'Kill to end of line'),
|
|
241
|
-
row(kb('
|
|
319
|
+
row(kb('line-start'), 'Move to start of line'),
|
|
242
320
|
row(kb('next-error-line-end'), 'Next error / line end'),
|
|
243
321
|
'',
|
|
244
322
|
' Actions',
|
|
@@ -252,12 +330,12 @@ export function renderShortcutsOverlay(
|
|
|
252
330
|
row('?', 'Help overlay'),
|
|
253
331
|
row(`${kb('clear-cancel')} x2`, 'Exit'),
|
|
254
332
|
'',
|
|
255
|
-
'
|
|
333
|
+
' Workspace',
|
|
256
334
|
' ' + '\u2500'.repeat(40),
|
|
257
|
-
row('Tab', 'Swap focus between input and
|
|
258
|
-
row(kb('panel-picker'), 'Open
|
|
259
|
-
row(kb('panel-tab-next'), '
|
|
260
|
-
row(kb('panel-tab-prev'), '
|
|
335
|
+
row('Tab', 'Swap focus between input and active Agent workspace'),
|
|
336
|
+
row(kb('panel-picker'), 'Open the Agent operator workspace'),
|
|
337
|
+
row(kb('panel-tab-next'), 'Cycle Agent workspace category forward'),
|
|
338
|
+
row(kb('panel-tab-prev'), 'Cycle Agent workspace category backward'),
|
|
261
339
|
'',
|
|
262
340
|
` Config: /keybindings to list and customize`,
|
|
263
341
|
];
|
|
@@ -3,6 +3,22 @@ import { getDisplayWidth } from '../utils/terminal-width.ts';
|
|
|
3
3
|
import type { HistorySearch } from '../input/input-history.ts';
|
|
4
4
|
import { createBottomBarLine, writeBottomBarText } from './bottom-bar.ts';
|
|
5
5
|
|
|
6
|
+
const HISTORY_SEARCH_PREFIX = '(reverse-i-search)`';
|
|
7
|
+
const HISTORY_SEARCH_FAILED_PREFIX = '(failed reverse-i-search)`';
|
|
8
|
+
const HISTORY_SEARCH_QUERY_SUFFIX = "': ";
|
|
9
|
+
|
|
10
|
+
function historySearchLabel(prefix: string, query: string): string {
|
|
11
|
+
return prefix + query + HISTORY_SEARCH_QUERY_SUFFIX;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function renderHistorySearchOverlayPackageText(): string {
|
|
15
|
+
return [
|
|
16
|
+
historySearchLabel(HISTORY_SEARCH_PREFIX, '<query>'),
|
|
17
|
+
historySearchLabel(HISTORY_SEARCH_FAILED_PREFIX, '<query>'),
|
|
18
|
+
'<matched-command-text>',
|
|
19
|
+
].join('\n');
|
|
20
|
+
}
|
|
21
|
+
|
|
6
22
|
/**
|
|
7
23
|
* Truncate `text` to at most `maxWidth` display columns, then pad with spaces
|
|
8
24
|
* to exactly `maxWidth` columns. CJK/emoji wide characters count as 2 columns.
|
|
@@ -42,13 +58,12 @@ export function renderHistorySearchOverlay(
|
|
|
42
58
|
const noMatch = historySearch.query.length > 0 && !hasMatch;
|
|
43
59
|
|
|
44
60
|
const prefix = noMatch
|
|
45
|
-
?
|
|
46
|
-
:
|
|
47
|
-
const queryPart = historySearch.query + "': ";
|
|
61
|
+
? HISTORY_SEARCH_FAILED_PREFIX
|
|
62
|
+
: HISTORY_SEARCH_PREFIX;
|
|
48
63
|
const matchText = hasMatch ? match?.entry ?? '' : '';
|
|
49
64
|
|
|
50
65
|
// Build the display string
|
|
51
|
-
const label = prefix
|
|
66
|
+
const label = historySearchLabel(prefix, historySearch.query);
|
|
52
67
|
const full = truncateToWidth(label + matchText, width);
|
|
53
68
|
|
|
54
69
|
const line = createBottomBarLine(width, { fg: '#000000', bg: '#00ffcc' });
|
|
@@ -4,6 +4,28 @@ import type { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
|
4
4
|
import type { ProcessEntry } from './process-modal.ts';
|
|
5
5
|
import { getOverlaySurfaceMetrics, getStableOverlayContentRows } from './overlay-viewport.ts';
|
|
6
6
|
|
|
7
|
+
const LIVE_TAIL_PROCESS_TAG = '[exec]';
|
|
8
|
+
const LIVE_TAIL_EMPTY_OUTPUT = '(no output yet)';
|
|
9
|
+
const LIVE_TAIL_SCROLL_HINT = '[Up/Down] Scroll';
|
|
10
|
+
const LIVE_TAIL_HINTS = [LIVE_TAIL_SCROLL_HINT, '[k] Stop process', '[Esc] Back'];
|
|
11
|
+
|
|
12
|
+
function liveTailTitle(label: string): string {
|
|
13
|
+
return `${LIVE_TAIL_PROCESS_TAG} ${label}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function liveTailScrollInfo(start: string | number, end: string | number, total: string | number): string {
|
|
17
|
+
return ` Lines ${start}-${end} of ${total} ${LIVE_TAIL_SCROLL_HINT}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function renderLiveTailModalPackageText(): string {
|
|
21
|
+
return [
|
|
22
|
+
liveTailTitle('<process>'),
|
|
23
|
+
LIVE_TAIL_EMPTY_OUTPUT,
|
|
24
|
+
liveTailScrollInfo('<start>', '<end>', '<total>'),
|
|
25
|
+
...LIVE_TAIL_HINTS,
|
|
26
|
+
].join('\n');
|
|
27
|
+
}
|
|
28
|
+
|
|
7
29
|
export interface LiveTailModalDeps {
|
|
8
30
|
readonly processManager: Pick<ProcessManager, 'stop' | 'getOutput'>;
|
|
9
31
|
}
|
|
@@ -45,7 +67,7 @@ export class LiveTailModal {
|
|
|
45
67
|
const output = this.deps.processManager.getOutput(this.entry.id);
|
|
46
68
|
if (!output) return '';
|
|
47
69
|
const combined = [output.stdout, output.stderr].filter(Boolean).join('\n').trim();
|
|
48
|
-
return combined ||
|
|
70
|
+
return combined || LIVE_TAIL_EMPTY_OUTPUT;
|
|
49
71
|
}
|
|
50
72
|
}
|
|
51
73
|
|
|
@@ -74,9 +96,9 @@ export function renderLiveTailModal(
|
|
|
74
96
|
const visibleLines = allLines.slice(startIdx, endIdx);
|
|
75
97
|
|
|
76
98
|
const maxLabelW = Math.max(20, width - 30);
|
|
77
|
-
const title =
|
|
99
|
+
const title = liveTailTitle(entry.label.slice(0, maxLabelW));
|
|
78
100
|
const scrollInfo = totalLines > maxOutputLines
|
|
79
|
-
?
|
|
101
|
+
? liveTailScrollInfo(startIdx + 1, Math.min(endIdx, totalLines), totalLines)
|
|
80
102
|
: '';
|
|
81
103
|
|
|
82
104
|
const sections: import('./modal-factory.ts').ModalSection[] = [];
|
|
@@ -84,7 +106,7 @@ export function renderLiveTailModal(
|
|
|
84
106
|
sections.push({ type: 'text', content: scrollInfo });
|
|
85
107
|
sections.push({ type: 'separator' });
|
|
86
108
|
}
|
|
87
|
-
sections.push({ type: 'text', content: visibleLines.join('\n') ||
|
|
109
|
+
sections.push({ type: 'text', content: visibleLines.join('\n') || LIVE_TAIL_EMPTY_OUTPUT });
|
|
88
110
|
|
|
89
111
|
return ModalFactory.createModal({
|
|
90
112
|
title,
|
|
@@ -92,6 +114,6 @@ export function renderLiveTailModal(
|
|
|
92
114
|
margin: 2,
|
|
93
115
|
targetContentRows,
|
|
94
116
|
sections,
|
|
95
|
-
hints:
|
|
117
|
+
hints: LIVE_TAIL_HINTS,
|
|
96
118
|
}, width);
|
|
97
119
|
}
|