@pellux/goodvibes-agent 0.1.117 → 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.
Files changed (253) hide show
  1. package/CHANGELOG.md +13 -4
  2. package/README.md +35 -14
  3. package/bin/goodvibes-agent.ts +16 -2
  4. package/dist/package/main.js +176073 -170980
  5. package/docs/README.md +11 -5
  6. package/docs/channels-remote-and-api.md +50 -0
  7. package/docs/connected-host.md +3 -3
  8. package/docs/getting-started.md +29 -15
  9. package/docs/knowledge-artifacts-and-multimodal.md +91 -0
  10. package/docs/project-planning.md +79 -0
  11. package/docs/providers-and-routing.md +46 -0
  12. package/docs/release-and-publishing.md +44 -9
  13. package/docs/tools-and-commands.md +123 -0
  14. package/docs/voice-and-live-tts.md +51 -0
  15. package/package.json +2 -5
  16. package/src/agent/channel-delivery.ts +201 -0
  17. package/src/agent/media-generation.ts +159 -0
  18. package/src/agent/memory-prompt.ts +0 -1
  19. package/src/agent/note-registry.ts +329 -0
  20. package/src/agent/operator-actions.ts +343 -0
  21. package/src/agent/persona-registry.ts +15 -14
  22. package/src/agent/record-labels.ts +107 -0
  23. package/src/agent/reminder-schedule-format.ts +33 -24
  24. package/src/agent/reminder-schedule.ts +26 -25
  25. package/src/agent/routine-registry.ts +13 -12
  26. package/src/agent/routine-schedule-args.ts +2 -1
  27. package/src/agent/routine-schedule-format.ts +77 -53
  28. package/src/agent/routine-schedule-promotion.ts +34 -32
  29. package/src/agent/routine-schedule-receipts.ts +28 -26
  30. package/src/agent/runtime-profile-starters.ts +2 -2
  31. package/src/agent/runtime-profile.ts +18 -17
  32. package/src/agent/skill-registry.ts +25 -24
  33. package/src/cli/agent-knowledge-args.ts +5 -1
  34. package/src/cli/agent-knowledge-command.ts +39 -33
  35. package/src/cli/agent-knowledge-format.ts +80 -67
  36. package/src/cli/agent-knowledge-methods.ts +1 -1
  37. package/src/cli/agent-knowledge-runtime.ts +32 -26
  38. package/src/cli/bundle-command.ts +13 -8
  39. package/src/cli/config-overrides.ts +37 -36
  40. package/src/cli/external-runtime.ts +10 -4
  41. package/src/cli/help.ts +29 -11
  42. package/src/cli/local-library-command.ts +134 -68
  43. package/src/cli/management-commands.ts +98 -62
  44. package/src/cli/management.ts +52 -26
  45. package/src/cli/memory-command.ts +66 -32
  46. package/src/cli/parser.ts +37 -24
  47. package/src/cli/profiles-command.ts +52 -35
  48. package/src/cli/provider-auth-routes.ts +2 -1
  49. package/src/cli/routines-command.ts +44 -36
  50. package/src/cli/service-posture.ts +6 -6
  51. package/src/cli/status.ts +46 -121
  52. package/src/core/conversation-message-snapshot.ts +131 -0
  53. package/src/input/agent-workspace-activation.ts +33 -7
  54. package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
  55. package/src/input/agent-workspace-basic-command-editors.ts +30 -10
  56. package/src/input/agent-workspace-categories.ts +276 -64
  57. package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
  58. package/src/input/agent-workspace-channel-command-editors.ts +23 -5
  59. package/src/input/agent-workspace-channels.ts +35 -2
  60. package/src/input/agent-workspace-command-editor.ts +18 -2
  61. package/src/input/agent-workspace-config-reader.ts +16 -0
  62. package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
  63. package/src/input/agent-workspace-editors.ts +140 -2
  64. package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
  65. package/src/input/agent-workspace-learned-behavior.ts +2 -2
  66. package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
  67. package/src/input/agent-workspace-library-command-editors.ts +2 -2
  68. package/src/input/agent-workspace-local-operations.ts +218 -0
  69. package/src/input/agent-workspace-local-selection.ts +75 -0
  70. package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
  71. package/src/input/agent-workspace-media-command-editors.ts +27 -0
  72. package/src/input/agent-workspace-memory-command-editors.ts +1 -1
  73. package/src/input/agent-workspace-memory-editor.ts +2 -2
  74. package/src/input/agent-workspace-navigation.ts +38 -2
  75. package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
  76. package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
  77. package/src/input/agent-workspace-operations-command-editors.ts +80 -3
  78. package/src/input/agent-workspace-panel-route.ts +43 -0
  79. package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
  80. package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
  81. package/src/input/agent-workspace-search.ts +169 -0
  82. package/src/input/agent-workspace-setup.ts +22 -11
  83. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
  84. package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
  85. package/src/input/agent-workspace-snapshot.ts +112 -13
  86. package/src/input/agent-workspace-task-command-editors.ts +4 -4
  87. package/src/input/agent-workspace-token.ts +18 -2
  88. package/src/input/agent-workspace-types.ts +92 -4
  89. package/src/input/agent-workspace-voice-media.ts +3 -6
  90. package/src/input/agent-workspace-web-research-editor.ts +104 -0
  91. package/src/input/agent-workspace.ts +136 -208
  92. package/src/input/command-registry.ts +4 -1
  93. package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
  94. package/src/input/commands/agent-skills-runtime.ts +83 -70
  95. package/src/input/commands/agent-workspace-runtime.ts +23 -7
  96. package/src/input/commands/brief-runtime.ts +25 -24
  97. package/src/input/commands/channels-runtime.ts +145 -31
  98. package/src/input/commands/delegation-runtime.ts +29 -23
  99. package/src/input/commands/experience-runtime.ts +6 -4
  100. package/src/input/commands/guidance-runtime.ts +4 -4
  101. package/src/input/commands/health-runtime.ts +140 -115
  102. package/src/input/commands/knowledge.ts +57 -56
  103. package/src/input/commands/local-provider-runtime.ts +36 -18
  104. package/src/input/commands/local-runtime.ts +138 -16
  105. package/src/input/commands/local-setup-review.ts +7 -7
  106. package/src/input/commands/mcp-runtime.ts +56 -35
  107. package/src/input/commands/notify-runtime.ts +38 -9
  108. package/src/input/commands/operator-actions-runtime.ts +138 -0
  109. package/src/input/commands/operator-runtime.ts +6 -17
  110. package/src/input/commands/personas-runtime.ts +45 -30
  111. package/src/input/commands/planning-runtime.ts +1 -1
  112. package/src/input/commands/platform-access-runtime.ts +29 -29
  113. package/src/input/commands/provider-accounts-runtime.ts +60 -39
  114. package/src/input/commands/qrcode-runtime.ts +45 -6
  115. package/src/input/commands/recall-bundle.ts +11 -11
  116. package/src/input/commands/recall-capture.ts +13 -11
  117. package/src/input/commands/recall-query.ts +29 -21
  118. package/src/input/commands/recall-review.ts +2 -1
  119. package/src/input/commands/routines-runtime.ts +59 -43
  120. package/src/input/commands/schedule-runtime.ts +33 -20
  121. package/src/input/commands/security-runtime.ts +4 -4
  122. package/src/input/commands/session-content.ts +80 -78
  123. package/src/input/commands/session-workflow.ts +132 -93
  124. package/src/input/commands/session.ts +3 -174
  125. package/src/input/commands/shell-core.ts +32 -17
  126. package/src/input/commands/subscription-runtime.ts +53 -179
  127. package/src/input/commands/tasks-runtime.ts +20 -20
  128. package/src/input/commands/work-plan-runtime.ts +33 -8
  129. package/src/input/commands.ts +2 -2
  130. package/src/input/feed-context-factory.ts +2 -1
  131. package/src/input/file-picker.ts +3 -2
  132. package/src/input/handler-command-route.ts +4 -7
  133. package/src/input/handler-content-actions.ts +89 -1
  134. package/src/input/handler-feed-routes.ts +19 -12
  135. package/src/input/handler-feed.ts +6 -3
  136. package/src/input/handler-interactions.ts +7 -5
  137. package/src/input/handler-modal-stack.ts +3 -3
  138. package/src/input/handler-onboarding.ts +24 -80
  139. package/src/input/handler-shortcuts.ts +15 -4
  140. package/src/input/handler.ts +47 -17
  141. package/src/input/input-history.ts +5 -6
  142. package/src/input/keybindings.ts +22 -11
  143. package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
  144. package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
  145. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
  146. package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
  147. package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
  148. package/src/input/onboarding/onboarding-wizard.ts +68 -0
  149. package/src/input/profile-picker-modal.ts +31 -12
  150. package/src/input/session-picker-modal.ts +21 -4
  151. package/src/input/settings-modal-behavior.ts +0 -3
  152. package/src/input/settings-modal-subscriptions.ts +3 -3
  153. package/src/input/settings-modal-types.ts +2 -13
  154. package/src/input/settings-modal.ts +6 -52
  155. package/src/input/submission-intent.ts +0 -1
  156. package/src/input/submission-router.ts +3 -3
  157. package/src/main.ts +18 -8
  158. package/src/panels/approval-panel.ts +8 -8
  159. package/src/panels/automation-control-panel.ts +2 -2
  160. package/src/panels/base-panel.ts +1 -1
  161. package/src/panels/builtin/agent.ts +1 -1
  162. package/src/panels/builtin/operations.ts +1 -10
  163. package/src/panels/builtin/session.ts +9 -9
  164. package/src/panels/builtin/shared.ts +2 -2
  165. package/src/panels/cost-tracker-panel.ts +1 -1
  166. package/src/panels/docs-panel.ts +5 -3
  167. package/src/panels/index.ts +0 -1
  168. package/src/panels/knowledge-panel.ts +6 -5
  169. package/src/panels/memory-panel.ts +7 -6
  170. package/src/panels/panel-list-panel.ts +36 -80
  171. package/src/panels/project-planning-panel.ts +18 -11
  172. package/src/panels/provider-account-snapshot.ts +51 -25
  173. package/src/panels/provider-accounts-panel.ts +33 -18
  174. package/src/panels/provider-health-domains.ts +45 -4
  175. package/src/panels/provider-health-panel.ts +5 -4
  176. package/src/panels/qr-panel.ts +1 -1
  177. package/src/panels/schedule-panel.ts +9 -17
  178. package/src/panels/security-panel.ts +8 -8
  179. package/src/panels/session-browser-panel.ts +10 -10
  180. package/src/panels/subscription-panel.ts +3 -3
  181. package/src/panels/system-messages-panel.ts +1 -1
  182. package/src/panels/tasks-panel.ts +20 -13
  183. package/src/panels/tool-inspector-panel.ts +19 -12
  184. package/src/panels/work-plan-panel.ts +5 -5
  185. package/src/planning/project-planning-coordinator.ts +1 -1
  186. package/src/provider-auth-route-display.ts +9 -0
  187. package/src/renderer/agent-workspace-style.ts +34 -0
  188. package/src/renderer/agent-workspace.ts +228 -52
  189. package/src/renderer/autocomplete-overlay.ts +25 -6
  190. package/src/renderer/bookmark-modal.ts +19 -4
  191. package/src/renderer/buffer.ts +4 -2
  192. package/src/renderer/context-inspector.ts +50 -13
  193. package/src/renderer/diff.ts +1 -1
  194. package/src/renderer/file-picker-overlay.ts +19 -6
  195. package/src/renderer/help-overlay.ts +106 -33
  196. package/src/renderer/history-search-overlay.ts +19 -4
  197. package/src/renderer/live-tail-modal.ts +27 -5
  198. package/src/renderer/mcp-workspace.ts +164 -50
  199. package/src/renderer/model-picker-overlay.ts +58 -2
  200. package/src/renderer/model-workspace.ts +104 -20
  201. package/src/renderer/process-modal.ts +27 -6
  202. package/src/renderer/profile-picker-modal.ts +20 -4
  203. package/src/renderer/search-overlay.ts +25 -5
  204. package/src/renderer/selection-modal-overlay.ts +46 -14
  205. package/src/renderer/session-picker-modal.ts +18 -1
  206. package/src/renderer/settings-modal-helpers.ts +2 -40
  207. package/src/renderer/settings-modal.ts +83 -50
  208. package/src/renderer/tool-call.ts +20 -11
  209. package/src/runtime/agent-runtime-events.ts +6 -6
  210. package/src/runtime/bootstrap-command-context.ts +7 -1
  211. package/src/runtime/bootstrap-command-parts.ts +9 -7
  212. package/src/runtime/bootstrap-core.ts +19 -1
  213. package/src/runtime/bootstrap-hook-bridge.ts +7 -18
  214. package/src/runtime/bootstrap-shell.ts +4 -4
  215. package/src/runtime/bootstrap.ts +31 -22
  216. package/src/runtime/connected-host-auth.ts +7 -2
  217. package/src/runtime/diagnostics/panels/index.ts +2 -2
  218. package/src/runtime/diagnostics/panels/policy.ts +7 -7
  219. package/src/runtime/index.ts +2 -1
  220. package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
  221. package/src/runtime/onboarding/apply.ts +80 -79
  222. package/src/runtime/onboarding/derivation.ts +5 -8
  223. package/src/runtime/onboarding/snapshot.ts +0 -15
  224. package/src/runtime/onboarding/types.ts +8 -19
  225. package/src/runtime/onboarding/verify.ts +32 -10
  226. package/src/runtime/operator-token-cleanup.ts +1 -1
  227. package/src/runtime/services.ts +91 -22
  228. package/src/runtime/store/selectors/index.ts +3 -3
  229. package/src/runtime/store/state.ts +1 -4
  230. package/src/runtime/surface-feature-flags.ts +41 -6
  231. package/src/runtime/ui-read-models.ts +3 -4
  232. package/src/runtime/ui-services.ts +6 -6
  233. package/src/shell/blocking-input.ts +2 -1
  234. package/src/shell/ui-openers.ts +3 -13
  235. package/src/tools/agent-analysis-registry-policy.ts +0 -1
  236. package/src/tools/agent-channel-send-tool.ts +133 -0
  237. package/src/tools/agent-context-policy.ts +1 -1
  238. package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
  239. package/src/tools/agent-knowledge-tool.ts +170 -0
  240. package/src/tools/agent-local-registry-tool.ts +269 -69
  241. package/src/tools/agent-media-generate-tool.ts +133 -0
  242. package/src/tools/agent-notify-tool.ts +143 -0
  243. package/src/tools/agent-operator-action-tool.ts +137 -0
  244. package/src/tools/agent-operator-briefing-tool.ts +217 -0
  245. package/src/tools/agent-reminder-schedule-tool.ts +237 -0
  246. package/src/tools/agent-tool-policy-guard.ts +8 -8
  247. package/src/tools/agent-work-plan-tool.ts +256 -0
  248. package/src/version.ts +1 -1
  249. package/src/input/commands/policy-dispatch.ts +0 -339
  250. package/src/input/commands/policy.ts +0 -13
  251. package/src/panels/panel-picker.ts +0 -105
  252. package/src/panels/policy-panel.ts +0 -308
  253. package/src/renderer/panel-picker-overlay.ts +0 -202
@@ -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: 'Context Inspector',
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: 'No messages in conversation yet.' },
114
+ { type: 'text', content: CONTEXT_INSPECTOR_EMPTY_MESSAGE },
76
115
  ],
77
- hints: ['[Esc] Close'],
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: `Total: ~${fmtN(totalTokens)} tokens (${messages.length} messages)${capacityStr}`,
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: 'WARNING: context is 80%+ full. Run /compact to free space.',
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: `(${startOffset} older messages not shown)`,
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: `Compaction hint: ${largeMsgs.length} message${largeMsgs.length > 1 ? 's' : ''} use ${largePct} of context.`,
238
+ content: contextInspectorCompactionHintText(largeMsgs.length, largePct),
202
239
  style: { fg: '#00ffcc' },
203
240
  });
204
241
  sections.push({
205
242
  type: 'text',
206
- content: 'Run /compact to summarise and reduce context size.',
243
+ content: CONTEXT_INSPECTOR_COMPACT_GUIDANCE,
207
244
  style: { dim: true },
208
245
  });
209
246
  }
210
247
 
211
248
  return ModalFactory.createModal({
212
- title: 'Context Inspector',
249
+ title: CONTEXT_INSPECTOR_TITLE,
213
250
  width: metrics.boxWidth,
214
251
  margin: metrics.margin,
215
252
  targetContentRows,
216
253
  sections,
217
- hints: ['[*] >10% of context', '[Esc] Close'],
254
+ hints: CONTEXT_INSPECTOR_CONTEXT_HINTS,
218
255
  }, width);
219
256
  }
@@ -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 was never written this frame (clean) and new row is also
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, 'Select File', { fg: titleFg, bold: true });
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
- const noResults = createOverlayContentLine(width, layout, borderFg, DEFAULT_OVERLAY_PALETTE.bodyBg);
58
- putOverlayText(noResults, layout.margin + 2, contentW, fitDisplay('No matching files', contentW), { fg: '244', dim: true });
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(hints, layout.width - 4), { fg: mutedFg, dim: true });
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 };
@@ -62,37 +161,11 @@ export function renderHelpOverlay(
62
161
  ` ${'?'.padEnd(20)} Toggle help`,
63
162
  ` ${'/shortcuts'.padEnd(20)} Full keyboard shortcuts`,
64
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
- ['agent', 'setup', 'Open setup, local behavior, channel, and voice workspaces'],
74
- ['agent', 'knowledge', 'Open isolated Agent Knowledge workflows'],
75
- ['agent', 'voice-media', 'Open voice, image, browser, and media setup'],
76
- ['setup', '', 'Open Agent setup with current settings preloaded'],
77
- ['knowledge', 'status', 'Inspect isolated Agent Knowledge readiness'],
78
- ['memory', '', 'Manage local Agent memory records'],
79
- ['personas', '', 'Manage serial Agent operating personas'],
80
- ['agent-skills', '', 'Manage local Agent skills and bundles'],
81
- ['routines', '', 'Manage reusable main-conversation routines'],
82
- ['workplan', '', 'Inspect shared work-plan state'],
83
- ['approval', '', 'Review and explicitly act on approvals'],
84
- ['schedule', 'remind', 'Create confirmed reminders or inspect schedules'],
85
- ['delegate', '', 'Explicitly hand build/fix/review work to GoodVibes TUI'],
86
- ['mcp', '', 'Inspect MCP servers and tool readiness'],
87
- ['provider', '', 'Choose provider or model family'],
88
- ['model', '', 'Select the active model route'],
89
- ['subscription', '', 'Review provider logins and subscriptions'],
90
- ['secrets', '', 'Manage secret references without printing values'],
91
- ['bundle', 'inspect', 'Inspect Agent support bundles from the TUI'],
92
- ['compat', '', 'Inspect connected-host and Agent Knowledge compatibility'],
93
- ['health', '', 'Run Agent runtime and setup diagnostics'],
94
- ];
95
-
96
169
  // Build command rows from featured list, filtering out unregistered commands.
97
170
  function featuredRow(name: string, argHint: string, desc: string): string {
98
171
  const invocation = argHint ? `/${name} ${argHint}` : `/${name}`;
@@ -101,7 +174,7 @@ export function renderHelpOverlay(
101
174
 
102
175
  const quickStartRows: string[] = [];
103
176
  try {
104
- for (const [name, argHint, desc] of FEATURED_COMMANDS) {
177
+ for (const [name, argHint, desc] of FEATURED_HELP_COMMANDS) {
105
178
  if (!hasCommand(name)) continue; // omit if not in live registry
106
179
  quickStartRows.push(featuredRow(name, argHint, desc));
107
180
  }
@@ -110,7 +183,7 @@ export function renderHelpOverlay(
110
183
  // unfiltered quick-start list so /help remains reachable.
111
184
  logger.warn(`[help-overlay] registry traversal error during command filter; using unfiltered list: ${err}`);
112
185
  quickStartRows.length = 0;
113
- for (const [name, argHint, desc] of FEATURED_COMMANDS) {
186
+ for (const [name, argHint, desc] of FEATURED_HELP_COMMANDS) {
114
187
  quickStartRows.push(featuredRow(name, argHint, desc));
115
188
  }
116
189
  }
@@ -128,7 +201,7 @@ export function renderHelpOverlay(
128
201
  'knowledge',
129
202
  'memory',
130
203
  'personas',
131
- 'agent-skills',
204
+ 'skills',
132
205
  'routines',
133
206
  'workplan',
134
207
  'approval',
@@ -261,8 +334,8 @@ export function renderShortcutsOverlay(
261
334
  ' ' + '\u2500'.repeat(40),
262
335
  row('Tab', 'Swap focus between input and active Agent workspace'),
263
336
  row(kb('panel-picker'), 'Open the Agent operator workspace'),
264
- row(kb('panel-tab-next'), 'Reserved for future Agent workspace tabs'),
265
- row(kb('panel-tab-prev'), 'Reserved for future Agent workspace tabs'),
337
+ row(kb('panel-tab-next'), 'Cycle Agent workspace category forward'),
338
+ row(kb('panel-tab-prev'), 'Cycle Agent workspace category backward'),
266
339
  '',
267
340
  ` Config: /keybindings to list and customize`,
268
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
- ? '(failed reverse-i-search)`'
46
- : '(reverse-i-search)`';
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 + queryPart;
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 || '(no output yet)';
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 = `[exec] ${entry.label.slice(0, maxLabelW)}`;
99
+ const title = liveTailTitle(entry.label.slice(0, maxLabelW));
78
100
  const scrollInfo = totalLines > maxOutputLines
79
- ? ` Lines ${startIdx + 1}-${Math.min(endIdx, totalLines)} of ${totalLines} [Up/Down] Scroll`
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') || '(no output yet)' });
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: ['[Up/Down] Scroll', '[k] Stop process', '[Esc] Back'],
117
+ hints: LIVE_TAIL_HINTS,
96
118
  }, width);
97
119
  }