@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
@@ -23,8 +23,8 @@ export function routeSubmissionIntent(input: SubmissionRouterInput): SubmissionI
23
23
 
24
24
  if (!trimmed) {
25
25
  return {
26
- kind: input.panelFocused ? 'panel-action' : 'empty',
27
- label: input.panelFocused ? 'panel action' : 'prompt',
26
+ kind: 'empty',
27
+ label: 'prompt',
28
28
  hasAttachments,
29
29
  };
30
30
  }
@@ -46,7 +46,7 @@ export function routeSubmissionIntent(input: SubmissionRouterInput): SubmissionI
46
46
  return { kind: 'delegation', label: 'TUI delegation', commandName, hasAttachments };
47
47
  }
48
48
  if (PANEL_COMMANDS.has(commandName)) {
49
- return { kind: 'panel-action', label: 'panel action', commandName, hasAttachments };
49
+ return { kind: 'slash-command', label: 'Agent workspace', commandName, hasAttachments };
50
50
  }
51
51
  if (ORCHESTRATION_COMMANDS.has(commandName)) {
52
52
  return { kind: 'orchestration', label: 'orchestration', commandName, hasAttachments };
package/src/main.ts CHANGED
@@ -4,6 +4,7 @@ import { Compositor } from './renderer/compositor.ts';
4
4
  import { type Line } from './types/grid.ts';
5
5
  import { UIFactory } from './renderer/ui-factory.ts';
6
6
  import { Orchestrator } from './core/orchestrator';
7
+ import { conversationMessagesAsSessionRecords } from './core/conversation-message-snapshot.ts';
7
8
  import { InputHandler } from './input/handler.ts';
8
9
  import { SelectionManager } from './input/selection.ts';
9
10
  import type { ContentPart } from '@pellux/goodvibes-sdk/platform/providers';
@@ -38,6 +39,7 @@ import {
38
39
  persistConversation,
39
40
  writeRecoveryFile,
40
41
  } from '@/runtime/index.ts';
42
+ import type { SessionSnapshot } from '@/runtime/index.ts';
41
43
  import { handleBlockingShellInput, type PendingPermissionState } from './shell/blocking-input.ts';
42
44
  import { wireShellUiOpeners } from './shell/ui-openers.ts';
43
45
  import { deriveComposerState } from './core/composer-state.ts';
@@ -136,6 +138,16 @@ async function main() {
136
138
  openPanels: panelManager.getAllOpen().map((panel) => panel.id),
137
139
  };
138
140
  };
141
+ const buildCurrentSessionSnapshot = (): SessionSnapshot => {
142
+ const messages = conversation.getMessageSnapshot();
143
+ const persisted = buildPersistedSessionContext(messages, conversation.getTitleSource(), buildSessionContinuityHints());
144
+ return {
145
+ messages: conversationMessagesAsSessionRecords(messages),
146
+ timestamp: Date.now(),
147
+ title: conversation.title,
148
+ ...persisted,
149
+ };
150
+ };
139
151
 
140
152
  let pendingPermission: PendingPermissionState | null = null;
141
153
  approvalBroker.subscribe((approval) => {
@@ -219,8 +231,8 @@ async function main() {
219
231
  const exitApp = (): void => {
220
232
  stopSpokenOutputForExit?.();
221
233
  unsubs.forEach(fn => fn());
222
- const snapshot = conversation.toJSON() as { messages: Array<import('./core/conversation.ts').ConversationMessageSnapshot>; timestamp?: number };
223
- ctx.shutdown({ ...snapshot, ...buildPersistedSessionContext(snapshot.messages, conversation.getTitleSource(), buildSessionContinuityHints()) }).catch((err) => {
234
+ const snapshot = buildCurrentSessionSnapshot();
235
+ ctx.shutdown(snapshot).catch((err) => {
224
236
  logger.debug('ctx.shutdown error during exitApp (non-fatal)', { error: summarizeError(err) });
225
237
  });
226
238
  if (recoveryInterval !== null) { clearInterval(recoveryInterval); recoveryInterval = null; }
@@ -666,11 +678,10 @@ async function main() {
666
678
  unsubs.push(uiServices.events.turns.on('TURN_COMPLETED', () => {
667
679
  // Auto-save after every LLM turn so kills don't lose the session
668
680
  try {
669
- const snapshot = conversation.toJSON() as { messages: Array<import('./core/conversation.ts').ConversationMessageSnapshot>; timestamp?: number };
670
- const persisted = buildPersistedSessionContext(snapshot.messages, conversation.getTitleSource(), buildSessionContinuityHints());
681
+ const snapshot = buildCurrentSessionSnapshot();
671
682
  persistConversation(
672
683
  runtime.sessionId,
673
- { ...snapshot, ...persisted },
684
+ snapshot,
674
685
  runtime.model,
675
686
  runtime.provider,
676
687
  conversation.title || '',
@@ -748,10 +759,9 @@ async function main() {
748
759
 
749
760
  // --- Auto-save to recovery file every 60s ---
750
761
  recoveryInterval = setInterval(() => {
751
- const snapshot = conversation.toJSON() as { messages: Array<import('./core/conversation.ts').ConversationMessageSnapshot> };
752
- const persisted = buildPersistedSessionContext(snapshot.messages, conversation.getTitleSource(), buildSessionContinuityHints());
762
+ const snapshot = buildCurrentSessionSnapshot();
753
763
  writeRecoveryFile(
754
- { ...snapshot, ...persisted },
764
+ snapshot,
755
765
  runtime.sessionId,
756
766
  conversation.title ?? '',
757
767
  { workingDirectory: workingDir, homeDirectory },
@@ -15,14 +15,14 @@ const C = {
15
15
  } as const;
16
16
 
17
17
  const APPROVAL_ROWS = [
18
- ['shell', 'why prompted: side effects, destructive ops, secret exposure, escalation', 'review via /security and /policy preflight'],
18
+ ['shell', 'why prompted: side effects, destructive ops, secret exposure, escalation', 'review via /approval review shell'],
19
19
  ['file', 'why prompted: config mutation, notebook edits, secret-bearing paths', 'review via /approval review file'],
20
20
  ['network', 'why prompted: external hosts, fetch scope, egress policy', 'review via /approval review network'],
21
- ['delegate', 'why prompted: recursive agents, spawn ceilings, write-set inheritance', 'review via /approval review delegate'],
22
- ['mcp', 'why prompted: trust escalation, host scope, path scope, coherence mismatch', 'review via /mcp trust and /security'],
23
- ['remote', 'why prompted: runner trust, remote write scope, artifact requirements', 'review delegated TUI execution context'],
24
- ['hook', 'why prompted: deny/mutate authority, blocking behavior, runner provenance', 'review via /hooks and /security'],
25
- ['plugin', 'why prompted: install/update lifecycle, provenance, capability grants', 'review via /marketplace and /security'],
21
+ ['delegate', 'why prompted: explicit TUI build handoff, write scope, result ownership', 'review via /approval review delegate'],
22
+ ['mcp', 'why prompted: trust escalation, host scope, path scope, coherence mismatch', 'review via /approval review mcp'],
23
+ ['remote', 'why prompted: build-host trust, remote write scope, artifact requirements', 'review via /approval review remote'],
24
+ ['hook', 'why prompted: deny/mutate authority, blocking behavior, execution provenance', 'review via /approval review hook'],
25
+ ['plugin', 'why prompted: install/update lifecycle, provenance, capability grants', 'review via /approval review plugin'],
26
26
  ] as const;
27
27
 
28
28
  type ApprovalRow = (typeof APPROVAL_ROWS)[number];
@@ -123,8 +123,8 @@ export class ApprovalPanel extends ScrollableListPanel<ApprovalRow> {
123
123
  buildPanelLine(width, [[' Approval posture', C.label]]),
124
124
  buildKeyValueLine(width, [
125
125
  { label: 'why prompted', value: 'risk summary', valueColor: C.value },
126
- { label: 'what-if', value: '/policy simulate + preflight', valueColor: C.info },
127
- { label: 'operator', value: '/security + /cockpit', valueColor: C.good },
126
+ { label: 'what-if', value: '/security review', valueColor: C.info },
127
+ { label: 'operator', value: '/approval + /security', valueColor: C.good },
128
128
  ], C),
129
129
  buildPanelLine(width, [
130
130
  [' \u2713 ', C.good],
@@ -103,7 +103,7 @@ export class AutomationControlPanel extends ScrollableListPanel<AutomationRun> {
103
103
  lines: buildEmptyState(
104
104
  width,
105
105
  ' Connected-host automation state is unavailable.',
106
- 'Use /schedule list for the supported Agent schedule summary. This deferred panel does not start or mutate automation.',
106
+ 'This operator view is read-only. Use /schedule list for compact transcript output; automation stays unchanged.',
107
107
  [{ command: '/schedule list', summary: 'review automation without starting hidden work' }],
108
108
  C,
109
109
  ),
@@ -182,7 +182,7 @@ export class AutomationControlPanel extends ScrollableListPanel<AutomationRun> {
182
182
  );
183
183
  if (selectedRun.error) {
184
184
  footerLines.push(buildPanelLine(width, [
185
- [' Error: ', C.label],
185
+ [' Error ', C.label],
186
186
  [truncateDisplay(selectedRun.error, Math.max(0, width - 10)), C.error],
187
187
  ]));
188
188
  }
@@ -34,7 +34,7 @@ export abstract class BasePanel implements Panel {
34
34
 
35
35
  /**
36
36
  * Clear a specific timer and remove it from the registry.
37
- * Safe to call with an id that was never registered or already cleared.
37
+ * Safe to call with an unregistered or already-cleared id.
38
38
  */
39
39
  protected clearTimer(id: ReturnType<typeof setTimeout> | ReturnType<typeof setInterval>): void {
40
40
  clearInterval(id as ReturnType<typeof setInterval>);
@@ -80,7 +80,7 @@ export function registerAgentPanels(manager: PanelManager, deps: ResolvedBuiltin
80
80
  name: 'Schedule',
81
81
  icon: 'Z',
82
82
  category: 'agent',
83
- description: 'Read-only schedule posture from the connected GoodVibes host; local Agent schedule mutation is blocked',
83
+ description: 'Read-only schedule posture from the connected GoodVibes host; Agent-local schedule mutation is blocked',
84
84
  factory: () => new SchedulePanel(requireAutomationManager(deps)),
85
85
  });
86
86
  }
@@ -7,7 +7,6 @@ import { SecurityPanel } from '../security-panel.ts';
7
7
  import { TasksPanel } from '../tasks-panel.ts';
8
8
  import { ProviderStatsPanel } from '../provider-stats-panel.ts';
9
9
  import { ProviderHealthPanel } from '../provider-health-panel.ts';
10
- import { PolicyPanel } from '../policy-panel.ts';
11
10
  import { createProviderAccountSnapshotQuery } from '../provider-account-snapshot.ts';
12
11
  import {
13
12
  createEnvironmentVariableQuery,
@@ -72,7 +71,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
72
71
  name: 'Security',
73
72
  icon: 'U',
74
73
  category: 'monitoring',
75
- description: 'Security review workspace for token audit, policy posture, MCP quarantine, and incident pressure',
74
+ description: 'Security review workspace for token posture, policy posture, MCP quarantine, and incident pressure',
76
75
  factory: () => new SecurityPanel(ui.readModels.security),
77
76
  });
78
77
 
@@ -119,12 +118,4 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
119
118
  ),
120
119
  });
121
120
 
122
- manager.registerType({
123
- id: 'policy',
124
- name: 'Policy',
125
- icon: 'U',
126
- category: 'monitoring',
127
- description: 'Policy governance: active/candidate bundles, divergence gate, rollout history, and simulation evidence',
128
- factory: () => new PolicyPanel(deps.policyRuntimeState),
129
- });
130
121
  }
@@ -45,7 +45,7 @@ function readOperatorToken(tokenPath: string): string | null {
45
45
  try {
46
46
  const parsed = JSON.parse(readFileSync(tokenPath, 'utf-8')) as unknown;
47
47
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
48
- const token = (parsed as Record<string, unknown>)['token'];
48
+ const token = 'token' in parsed ? parsed.token : undefined;
49
49
  return typeof token === 'string' && token.trim().length > 0 ? token : null;
50
50
  } catch {
51
51
  return null;
@@ -58,23 +58,23 @@ export function registerSessionPanels(manager: PanelManager, deps: ResolvedBuilt
58
58
  name: 'QR Code',
59
59
  icon: 'Q',
60
60
  category: 'session',
61
- description: 'QR code for companion app pairing scan to connect a mobile or desktop companion',
61
+ description: 'QR code for companion app pairing through the connected GoodVibes host',
62
62
  factory: () => {
63
- if (!deps.daemonHomeDir) throw new Error('daemonHomeDir must be provided to the session panel factory via BuiltinPanelDeps');
64
- const token = readOperatorToken(`${deps.daemonHomeDir}/operator-tokens.json`);
65
- const daemonPort = deps.configManager.get('controlPlane.port');
66
- const daemonHost = String(process.env['GOODVIBES_DAEMON_HOST'] ?? getLocalNetworkIp());
67
- const daemonUrl = `http://${daemonHost}:${daemonPort}`;
63
+ if (!deps.connectedHostTokenDir) throw new Error('connected host token directory must be provided to the session panel factory via BuiltinPanelDeps');
64
+ const token = readOperatorToken(`${deps.connectedHostTokenDir}/operator-tokens.json`);
65
+ const connectedHostPort = deps.configManager.get('controlPlane.port');
66
+ const connectedHostName = String(process.env['GOODVIBES_AGENT_RUNTIME_HOST'] ?? process.env['GOODVIBES_DAEMON_HOST'] ?? getLocalNetworkIp());
67
+ const connectedHostUrl = `http://${connectedHostName}:${connectedHostPort}`;
68
68
  const bootstrapPassword = readBootstrapPassword(deps.localUserAuthManager.getBootstrapCredentialPath());
69
69
  const connectionInfo = token
70
70
  ? buildCompanionConnectionInfo({
71
- daemonUrl,
71
+ daemonUrl: connectedHostUrl,
72
72
  token,
73
73
  password: bootstrapPassword,
74
74
  surface: GOODVIBES_AGENT_PAIRING_SURFACE,
75
75
  })
76
76
  : {
77
- url: daemonUrl,
77
+ url: connectedHostUrl,
78
78
  token: '',
79
79
  username: 'admin',
80
80
  ...(bootstrapPassword !== undefined ? { password: bootstrapPassword } : {}),
@@ -80,7 +80,7 @@ export interface BuiltinPanelDeps {
80
80
  tokenAuditor: ApiTokenAuditor;
81
81
  /** Shared component-health monitor for rate-limited panels and diagnostics. */
82
82
  componentHealthMonitor: ComponentHealthMonitor;
83
- /** Copied shell dependency kept inert in Agent; build worktree UX belongs to GoodVibes TUI delegation. */
83
+ /** Inert shell dependency in Agent; build worktree UX belongs to GoodVibes TUI delegation. */
84
84
  worktreeRegistry: WorktreeRegistry;
85
85
  /** Isolation session registry used by MCP internals; Agent does not expose local execution-isolation command UX. */
86
86
  sandboxSessionRegistry: SandboxSessionRegistry;
@@ -88,7 +88,7 @@ export interface BuiltinPanelDeps {
88
88
  * Resolved connected-host token directory (e.g. `~/.goodvibes/daemon`) — owned by the
89
89
  * composition root and passed explicitly so panel factories do not discover cwd/home implicitly.
90
90
  */
91
- daemonHomeDir?: string;
91
+ connectedHostTokenDir?: string;
92
92
  /** Session memory store for context and token budget panels. */
93
93
  sessionMemoryStore?: SessionMemoryStore;
94
94
  /** Execution plan manager for plan dashboard panels. */
@@ -198,7 +198,7 @@ export class CostTrackerPanel extends BasePanel {
198
198
  turnEvents.on('TURN_COMPLETED', () => this.onTurnComplete()),
199
199
  );
200
200
 
201
- // Track agent spawns
201
+ // Track runtime worker events for cost attribution only.
202
202
  this.unsubs.push(
203
203
  agentEvents.on('AGENT_SPAWNING', (payload) => {
204
204
  this.agents.set(payload.agentId, {
@@ -36,15 +36,17 @@ const C = {
36
36
  // ---------------------------------------------------------------------------
37
37
  const SHORTCUTS: Array<{ key: string; desc: string }> = [
38
38
  { key: 'Ctrl+C', desc: 'Cancel generation / exit (double)' },
39
- { key: 'Ctrl+P', desc: 'Open panel picker' },
39
+ { key: 'Ctrl+P', desc: 'Open Agent operator workspace' },
40
40
  { key: 'Ctrl+F', desc: 'Search conversation' },
41
41
  { key: 'Ctrl+K', desc: 'Copy last response to clipboard' },
42
42
  { key: 'Ctrl+L', desc: 'Clear screen' },
43
43
  { key: 'Ctrl+Z', desc: 'Undo input' },
44
44
  { key: 'Alt+Enter', desc: 'Insert newline in prompt' },
45
45
  { key: 'PageUp/Down', desc: 'Scroll conversation' },
46
- { key: 'Alt+PgUp/Dn', desc: 'Scroll panel' },
47
- { key: 'Tab', desc: 'Path completion / tab panels' },
46
+ { key: 'Alt+PgUp/Dn', desc: 'Scroll active workspace surface' },
47
+ { key: 'Tab', desc: 'Path completion / workspace focus' },
48
+ { key: '@path', desc: 'Attach bounded file/folder/URL context in composer' },
49
+ { key: '!@path', desc: 'Inject raw file contents in composer' },
48
50
  { key: '/', desc: 'Start slash command' },
49
51
  { key: 'Enter', desc: 'Submit prompt' },
50
52
  { key: 'Esc', desc: 'Close overlay / cancel search' },
@@ -15,7 +15,6 @@ export { ToolInspectorPanel } from './tool-inspector-panel.ts';
15
15
  export { ContextVisualizerPanel } from './context-visualizer-panel.ts';
16
16
  export { registerBuiltinPanels } from './builtin-panels.ts';
17
17
  export type { BuiltinPanelDeps } from './builtin-panels.ts';
18
- export { PolicyPanel } from './policy-panel.ts';
19
18
  export { TasksPanel } from './tasks-panel.ts';
20
19
  export { SubscriptionPanel } from './subscription-panel.ts';
21
20
  export { SecurityPanel } from './security-panel.ts';
@@ -3,6 +3,7 @@ import { ScrollableListPanel } from './scrollable-list-panel.ts';
3
3
  import { type ConfirmState, handleConfirmInput, renderConfirmLines } from './confirm-state.ts';
4
4
  import type { MemoryClass, MemoryRecord, MemoryRegistry, MemoryReviewState } from '@pellux/goodvibes-sdk/platform/state';
5
5
  import type { KnowledgeStatus } from '@pellux/goodvibes-sdk/platform/knowledge';
6
+ import { formatAgentRecordReferences } from '../agent/record-labels.ts';
6
7
  import {
7
8
  buildBodyText,
8
9
  buildGuidanceLine,
@@ -105,7 +106,7 @@ export class KnowledgePanel extends ScrollableListPanel<MemoryRecord> {
105
106
  { command: '/knowledge status', summary: 'inspect the isolated Agent Knowledge store' },
106
107
  { command: '/knowledge ingest-url <url> --yes', summary: 'ingest source-backed material into Agent Knowledge only' },
107
108
  { command: '/knowledge queue', summary: 'review Agent Knowledge issues' },
108
- { command: '/recall add fact <summary>', summary: 'capture a local non-secret memory record when appropriate' },
109
+ { command: '/memory add fact <summary>', summary: 'capture a local non-secret memory record when appropriate' },
109
110
  ];
110
111
  }
111
112
 
@@ -233,7 +234,7 @@ export class KnowledgePanel extends ScrollableListPanel<MemoryRecord> {
233
234
  buildPanelLine(width, [
234
235
  [' route ', C.label],
235
236
  ['/api/goodvibes-agent/knowledge/*', C.info],
236
- [' isolated: no default Knowledge/Wiki or non-Agent fallback', C.dim],
237
+ [' isolated: no default knowledge or non-Agent fallback', C.dim],
237
238
  ]),
238
239
  ];
239
240
  if (this.agentKnowledgeLoading && !this.agentKnowledgeStatus) {
@@ -283,7 +284,7 @@ export class KnowledgePanel extends ScrollableListPanel<MemoryRecord> {
283
284
 
284
285
  if (this.records.length === 0) this.refresh();
285
286
 
286
- const intro = 'Isolated Agent Knowledge plus local non-secret memory review. This surface never falls back to default Knowledge/Wiki or non-Agent knowledge segments.';
287
+ const intro = 'Isolated Agent Knowledge plus local non-secret memory review. This surface never falls back to default knowledge or non-Agent knowledge segments.';
287
288
  const records = this.registry.search({ limit: 200 });
288
289
  const agentKnowledgeHeader = this.buildAgentKnowledgeHeader(width);
289
290
 
@@ -335,7 +336,7 @@ export class KnowledgePanel extends ScrollableListPanel<MemoryRecord> {
335
336
  [' project ', C.label], [String(byScope.get('project') ?? 0), C.value],
336
337
  [' team ', C.label], [String(byScope.get('team') ?? 0), C.good],
337
338
  ]),
338
- buildGuidanceLine(width, '/recall review', 'work the stale and contradicted queue from the command workspace', C),
339
+ buildGuidanceLine(width, '/memory review', 'work the stale and contradicted queue from the command workspace', C),
339
340
  ];
340
341
 
341
342
  const recentSummaryLines: Line[] = [];
@@ -376,7 +377,7 @@ export class KnowledgePanel extends ScrollableListPanel<MemoryRecord> {
376
377
  if (selectedRecord.provenance.length) {
377
378
  selectedLines.push(...buildBodyText(
378
379
  width,
379
- `Provenance: ${selectedRecord.provenance.map((p) => `${p.kind}:${p.ref}`).join(', ')}`,
380
+ `Origin: ${formatAgentRecordReferences(selectedRecord.provenance)}`,
380
381
  C,
381
382
  C.dim,
382
383
  ));
@@ -7,6 +7,7 @@
7
7
  import type { Line } from '../types/grid.ts';
8
8
  import type { MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state';
9
9
  import type { MemoryRecord, MemoryClass } from '@pellux/goodvibes-sdk/platform/state';
10
+ import { formatAgentRecordReferences } from '../agent/record-labels.ts';
10
11
  import { SearchableListPanel } from './scrollable-list-panel.ts';
11
12
  import {
12
13
  buildBodyText,
@@ -125,12 +126,12 @@ export class MemoryPanel extends SearchableListPanel<MemoryRecord> {
125
126
  protected override getEmptyStateMessage() {
126
127
  return this.searchQuery
127
128
  ? ` No records matching "${this.searchQuery}"`
128
- : ' No memory records. Use /recall add <class> <summary> to create one.';
129
+ : ' No memory records. Use /memory add <class> <summary> to create one.';
129
130
  }
130
131
  protected override getEmptyStateActions() {
131
132
  return [
132
- { command: '/recall add fact <summary>', summary: 'capture a durable fact directly' },
133
- { command: '/recall capture incident latest', summary: 'promote the latest incident into memory' },
133
+ { command: '/memory add fact <summary>', summary: 'capture a durable fact directly' },
134
+ { command: '/memory capture incident latest', summary: 'promote the latest incident into memory' },
134
135
  ];
135
136
  }
136
137
 
@@ -170,7 +171,7 @@ export class MemoryPanel extends SearchableListPanel<MemoryRecord> {
170
171
 
171
172
  render(width: number, height: number): Line[] {
172
173
  this.clampSelection();
173
- const intro = 'Durable project memory across decisions, constraints, incidents, patterns, risks, runbooks, and related provenance.';
174
+ const intro = 'Durable project memory across decisions, constraints, incidents, patterns, risks, runbooks, and related origin links.';
174
175
 
175
176
  const records = this.getItems();
176
177
  const byClass = new Map<MemoryClass, number>();
@@ -189,7 +190,7 @@ export class MemoryPanel extends SearchableListPanel<MemoryRecord> {
189
190
  { label: 'runbooks', value: String(byClass.get('runbook') ?? 0), valueColor: C.runbook },
190
191
  ], C),
191
192
  filterLine,
192
- buildGuidanceLine(width, '/recall review', 'review durable knowledge and queue posture from the command workspace', C),
193
+ buildGuidanceLine(width, '/memory review', 'review durable memory and queue posture from the command workspace', C),
193
194
  ];
194
195
 
195
196
  const selected = records[this.selectedIndex];
@@ -206,7 +207,7 @@ export class MemoryPanel extends SearchableListPanel<MemoryRecord> {
206
207
  if (selected.provenance.length) {
207
208
  selectedLines.push(...buildBodyText(
208
209
  width,
209
- `Provenance: ${selected.provenance.map((p) => `${p.kind}:${p.ref}`).join(' ')}`,
210
+ `Origin: ${formatAgentRecordReferences(selected.provenance)}`,
210
211
  C,
211
212
  C.dim,
212
213
  ));