@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.
Files changed (285) hide show
  1. package/CHANGELOG.md +48 -661
  2. package/README.md +64 -57
  3. package/bin/goodvibes-agent.ts +16 -2
  4. package/dist/package/main.js +199180 -192185
  5. package/docs/README.md +15 -8
  6. package/docs/channels-remote-and-api.md +50 -0
  7. package/docs/connected-host.md +59 -0
  8. package/docs/getting-started.md +61 -50
  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 +48 -11
  13. package/docs/tools-and-commands.md +123 -0
  14. package/docs/voice-and-live-tts.md +51 -0
  15. package/package.json +3 -6
  16. package/src/agent/behavior-discovery-summary.ts +1 -3
  17. package/src/agent/channel-delivery.ts +201 -0
  18. package/src/agent/media-generation.ts +159 -0
  19. package/src/agent/memory-prompt.ts +0 -1
  20. package/src/agent/note-registry.ts +329 -0
  21. package/src/agent/operator-actions.ts +343 -0
  22. package/src/agent/persona-discovery.ts +1 -3
  23. package/src/agent/persona-registry.ts +19 -16
  24. package/src/agent/record-labels.ts +107 -0
  25. package/src/agent/reminder-schedule-format.ts +33 -24
  26. package/src/agent/reminder-schedule.ts +27 -26
  27. package/src/agent/routine-registry.ts +54 -14
  28. package/src/agent/routine-schedule-args.ts +2 -1
  29. package/src/agent/routine-schedule-format.ts +77 -53
  30. package/src/agent/routine-schedule-promotion.ts +35 -33
  31. package/src/agent/routine-schedule-receipts.ts +29 -27
  32. package/src/agent/runtime-profile-starters.ts +5 -5
  33. package/src/agent/runtime-profile.ts +91 -12
  34. package/src/agent/skill-registry.ts +210 -32
  35. package/src/cli/agent-knowledge-args.ts +5 -1
  36. package/src/cli/agent-knowledge-command.ts +40 -34
  37. package/src/cli/agent-knowledge-format.ts +80 -67
  38. package/src/cli/agent-knowledge-methods.ts +1 -1
  39. package/src/cli/agent-knowledge-runtime.ts +32 -26
  40. package/src/cli/bundle-command.ts +14 -9
  41. package/src/cli/config-overrides.ts +37 -36
  42. package/src/cli/entrypoint.ts +16 -7
  43. package/src/cli/external-runtime.ts +10 -4
  44. package/src/cli/help.ts +54 -29
  45. package/src/cli/local-library-command.ts +203 -83
  46. package/src/cli/management-commands.ts +105 -68
  47. package/src/cli/management.ts +55 -74
  48. package/src/cli/memory-command.ts +66 -32
  49. package/src/cli/parser.ts +37 -3
  50. package/src/cli/profiles-command.ts +166 -31
  51. package/src/cli/provider-auth-routes.ts +2 -1
  52. package/src/cli/routines-command.ts +176 -40
  53. package/src/cli/service-posture.ts +16 -16
  54. package/src/cli/status.ts +56 -135
  55. package/src/core/conversation-message-snapshot.ts +131 -0
  56. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  57. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  58. package/src/input/agent-workspace-activation.ts +35 -8
  59. package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
  60. package/src/input/agent-workspace-basic-command-editors.ts +502 -9
  61. package/src/input/agent-workspace-categories.ts +423 -51
  62. package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
  63. package/src/input/agent-workspace-channel-command-editors.ts +65 -0
  64. package/src/input/agent-workspace-channels.ts +35 -2
  65. package/src/input/agent-workspace-command-editor.ts +41 -3
  66. package/src/input/agent-workspace-config-reader.ts +16 -0
  67. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  68. package/src/input/agent-workspace-editors.ts +166 -1
  69. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  70. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  71. package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
  72. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  73. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  74. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  75. package/src/input/agent-workspace-local-operations.ts +218 -0
  76. package/src/input/agent-workspace-local-selection.ts +75 -0
  77. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  78. package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
  79. package/src/input/agent-workspace-media-command-editors.ts +27 -0
  80. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  81. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  82. package/src/input/agent-workspace-memory-editor.ts +2 -2
  83. package/src/input/agent-workspace-navigation.ts +81 -0
  84. package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
  85. package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
  86. package/src/input/agent-workspace-operations-command-editors.ts +196 -0
  87. package/src/input/agent-workspace-panel-route.ts +43 -0
  88. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  89. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  90. package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
  91. package/src/input/agent-workspace-requirements.ts +11 -0
  92. package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
  93. package/src/input/agent-workspace-search.ts +169 -0
  94. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  95. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  96. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  97. package/src/input/agent-workspace-setup.ts +37 -16
  98. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  99. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  100. package/src/input/agent-workspace-snapshot.ts +162 -21
  101. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  102. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  103. package/src/input/agent-workspace-token.ts +18 -2
  104. package/src/input/agent-workspace-types.ts +212 -4
  105. package/src/input/agent-workspace-voice-media.ts +4 -7
  106. package/src/input/agent-workspace-web-research-editor.ts +104 -0
  107. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  108. package/src/input/agent-workspace.ts +178 -240
  109. package/src/input/command-registry.ts +5 -2
  110. package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
  111. package/src/input/commands/agent-skills-runtime.ts +149 -72
  112. package/src/input/commands/agent-workspace-runtime.ts +23 -6
  113. package/src/input/commands/brief-runtime.ts +55 -25
  114. package/src/input/commands/channels-runtime.ts +147 -33
  115. package/src/input/commands/compat-runtime.ts +32 -0
  116. package/src/input/commands/delegation-runtime.ts +29 -23
  117. package/src/input/commands/experience-runtime.ts +6 -4
  118. package/src/input/commands/guidance-runtime.ts +4 -4
  119. package/src/input/commands/health-runtime.ts +149 -126
  120. package/src/input/commands/knowledge.ts +82 -60
  121. package/src/input/commands/local-provider-runtime.ts +43 -21
  122. package/src/input/commands/local-runtime.ts +138 -16
  123. package/src/input/commands/local-setup-review.ts +10 -20
  124. package/src/input/commands/mcp-runtime.ts +63 -46
  125. package/src/input/commands/notify-runtime.ts +38 -9
  126. package/src/input/commands/operator-actions-runtime.ts +138 -0
  127. package/src/input/commands/operator-runtime.ts +6 -76
  128. package/src/input/commands/personas-runtime.ts +46 -31
  129. package/src/input/commands/planning-runtime.ts +1 -1
  130. package/src/input/commands/platform-access-runtime.ts +35 -98
  131. package/src/input/commands/product-runtime.ts +2 -2
  132. package/src/input/commands/provider-accounts-runtime.ts +60 -39
  133. package/src/input/commands/qrcode-runtime.ts +50 -9
  134. package/src/input/commands/recall-bundle.ts +11 -11
  135. package/src/input/commands/recall-capture.ts +13 -11
  136. package/src/input/commands/recall-query.ts +29 -21
  137. package/src/input/commands/recall-review.ts +2 -1
  138. package/src/input/commands/routines-runtime.ts +99 -45
  139. package/src/input/commands/runtime-services.ts +1 -14
  140. package/src/input/commands/schedule-runtime.ts +33 -20
  141. package/src/input/commands/security-runtime.ts +6 -11
  142. package/src/input/commands/session-content.ts +80 -78
  143. package/src/input/commands/session-workflow.ts +134 -104
  144. package/src/input/commands/session.ts +3 -174
  145. package/src/input/commands/shell-core.ts +38 -17
  146. package/src/input/commands/subscription-runtime.ts +54 -185
  147. package/src/input/commands/support-bundle-runtime.ts +53 -0
  148. package/src/input/commands/tasks-runtime.ts +21 -21
  149. package/src/input/commands/work-plan-runtime.ts +33 -8
  150. package/src/input/commands.ts +6 -2
  151. package/src/input/feed-context-factory.ts +2 -2
  152. package/src/input/file-picker.ts +3 -2
  153. package/src/input/handler-command-route.ts +4 -7
  154. package/src/input/handler-content-actions.ts +89 -26
  155. package/src/input/handler-feed-routes.ts +19 -12
  156. package/src/input/handler-feed.ts +6 -5
  157. package/src/input/handler-interactions.ts +9 -36
  158. package/src/input/handler-modal-stack.ts +3 -3
  159. package/src/input/handler-onboarding.ts +52 -91
  160. package/src/input/handler-shortcuts.ts +16 -7
  161. package/src/input/handler.ts +50 -23
  162. package/src/input/input-history.ts +5 -6
  163. package/src/input/keybindings.ts +27 -16
  164. package/src/input/mcp-workspace.ts +90 -26
  165. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  166. package/src/input/onboarding/onboarding-wizard-apply.ts +62 -0
  167. package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
  168. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  169. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
  170. package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
  171. package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
  172. package/src/input/onboarding/onboarding-wizard.ts +87 -2
  173. package/src/input/profile-picker-modal.ts +31 -12
  174. package/src/input/session-picker-modal.ts +21 -4
  175. package/src/input/settings-modal-agent-policy.ts +6 -6
  176. package/src/input/settings-modal-behavior.ts +0 -3
  177. package/src/input/settings-modal-subscriptions.ts +3 -3
  178. package/src/input/settings-modal-types.ts +2 -13
  179. package/src/input/settings-modal.ts +20 -66
  180. package/src/input/submission-intent.ts +0 -1
  181. package/src/input/submission-router.ts +3 -3
  182. package/src/main.ts +18 -10
  183. package/src/panels/approval-panel.ts +8 -8
  184. package/src/panels/automation-control-panel.ts +4 -4
  185. package/src/panels/base-panel.ts +1 -1
  186. package/src/panels/builtin/agent.ts +1 -1
  187. package/src/panels/builtin/operations.ts +3 -12
  188. package/src/panels/builtin/session.ts +32 -24
  189. package/src/panels/builtin/shared.ts +7 -7
  190. package/src/panels/cost-tracker-panel.ts +1 -1
  191. package/src/panels/docs-panel.ts +5 -3
  192. package/src/panels/index.ts +0 -1
  193. package/src/panels/knowledge-panel.ts +6 -5
  194. package/src/panels/memory-panel.ts +7 -6
  195. package/src/panels/panel-list-panel.ts +36 -80
  196. package/src/panels/project-planning-panel.ts +19 -12
  197. package/src/panels/provider-account-snapshot.ts +51 -25
  198. package/src/panels/provider-accounts-panel.ts +33 -18
  199. package/src/panels/provider-health-domains.ts +48 -7
  200. package/src/panels/provider-health-panel.ts +5 -4
  201. package/src/panels/qr-panel.ts +44 -20
  202. package/src/panels/schedule-panel.ts +9 -17
  203. package/src/panels/security-panel.ts +8 -8
  204. package/src/panels/session-browser-panel.ts +10 -10
  205. package/src/panels/subscription-panel.ts +6 -6
  206. package/src/panels/system-messages-panel.ts +3 -3
  207. package/src/panels/tasks-panel.ts +21 -14
  208. package/src/panels/tool-inspector-panel.ts +19 -12
  209. package/src/panels/work-plan-panel.ts +5 -5
  210. package/src/planning/project-planning-coordinator.ts +3 -3
  211. package/src/provider-auth-route-display.ts +9 -0
  212. package/src/renderer/agent-workspace-style.ts +34 -0
  213. package/src/renderer/agent-workspace.ts +254 -57
  214. package/src/renderer/autocomplete-overlay.ts +25 -6
  215. package/src/renderer/block-actions.ts +1 -3
  216. package/src/renderer/bookmark-modal.ts +19 -4
  217. package/src/renderer/buffer.ts +4 -2
  218. package/src/renderer/context-inspector.ts +50 -13
  219. package/src/renderer/diff.ts +1 -1
  220. package/src/renderer/file-picker-overlay.ts +19 -6
  221. package/src/renderer/help-overlay.ts +112 -34
  222. package/src/renderer/history-search-overlay.ts +19 -4
  223. package/src/renderer/live-tail-modal.ts +27 -5
  224. package/src/renderer/mcp-workspace.ts +176 -43
  225. package/src/renderer/model-picker-overlay.ts +58 -3
  226. package/src/renderer/model-workspace.ts +104 -22
  227. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  228. package/src/renderer/process-modal.ts +27 -6
  229. package/src/renderer/profile-picker-modal.ts +21 -5
  230. package/src/renderer/search-overlay.ts +25 -5
  231. package/src/renderer/selection-modal-overlay.ts +46 -14
  232. package/src/renderer/session-picker-modal.ts +18 -1
  233. package/src/renderer/settings-modal-helpers.ts +2 -40
  234. package/src/renderer/settings-modal.ts +88 -55
  235. package/src/renderer/system-message.ts +1 -1
  236. package/src/renderer/tool-call.ts +20 -11
  237. package/src/runtime/agent-runtime-events.ts +129 -0
  238. package/src/runtime/bootstrap-command-context.ts +7 -1
  239. package/src/runtime/bootstrap-command-parts.ts +11 -8
  240. package/src/runtime/bootstrap-core.ts +23 -65
  241. package/src/runtime/bootstrap-hook-bridge.ts +7 -18
  242. package/src/runtime/bootstrap-shell.ts +46 -8
  243. package/src/runtime/bootstrap.ts +36 -46
  244. package/src/runtime/connected-host-auth.ts +47 -0
  245. package/src/runtime/diagnostics/panels/index.ts +2 -2
  246. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  247. package/src/runtime/diagnostics/panels/policy.ts +7 -7
  248. package/src/runtime/index.ts +2 -5
  249. package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
  250. package/src/runtime/onboarding/apply.ts +288 -74
  251. package/src/runtime/onboarding/derivation.ts +10 -13
  252. package/src/runtime/onboarding/snapshot.ts +2 -17
  253. package/src/runtime/onboarding/types.ts +34 -20
  254. package/src/runtime/onboarding/verify.ts +105 -4
  255. package/src/runtime/operator-token-cleanup.ts +3 -3
  256. package/src/runtime/services.ts +95 -11
  257. package/src/runtime/store/selectors/index.ts +3 -3
  258. package/src/runtime/store/state.ts +1 -4
  259. package/src/runtime/surface-feature-flags.ts +41 -6
  260. package/src/runtime/ui-read-models.ts +3 -4
  261. package/src/runtime/ui-services.ts +6 -6
  262. package/src/shell/blocking-input.ts +2 -1
  263. package/src/shell/service-settings-sync.ts +7 -7
  264. package/src/shell/ui-openers.ts +17 -38
  265. package/src/tools/agent-analysis-registry-policy.ts +0 -1
  266. package/src/tools/agent-channel-send-tool.ts +133 -0
  267. package/src/tools/agent-context-policy.ts +1 -1
  268. package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
  269. package/src/tools/agent-knowledge-tool.ts +170 -0
  270. package/src/tools/agent-local-registry-tool.ts +279 -73
  271. package/src/tools/agent-media-generate-tool.ts +133 -0
  272. package/src/tools/agent-notify-tool.ts +143 -0
  273. package/src/tools/agent-operator-action-tool.ts +137 -0
  274. package/src/tools/agent-operator-briefing-tool.ts +217 -0
  275. package/src/tools/agent-reminder-schedule-tool.ts +237 -0
  276. package/src/tools/agent-tool-policy-guard.ts +13 -15
  277. package/src/tools/agent-work-plan-tool.ts +256 -0
  278. package/src/version.ts +1 -1
  279. package/docs/connected-services.md +0 -51
  280. package/src/cli/package-verification.ts +0 -274
  281. package/src/input/commands/policy-dispatch.ts +0 -339
  282. package/src/input/commands/policy.ts +0 -17
  283. package/src/panels/panel-picker.ts +0 -105
  284. package/src/panels/policy-panel.ts +0 -308
  285. package/src/renderer/panel-picker-overlay.ts +0 -202
@@ -3,6 +3,7 @@ import { dirname } from 'node:path';
3
3
  import type { CommandRegistry } from '../command-registry.ts';
4
4
  import { listBuiltinSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
5
5
  import { buildAuthInspectionSnapshot, inspectProviderAuth } from '@/runtime/index.ts';
6
+ import { formatAgentRecordSource } from '../../agent/record-labels.ts';
6
7
  import { requireSecretsManager, requireServiceRegistry, requireShellPaths, requireSubscriptionManager } from './runtime-services.ts';
7
8
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
8
9
 
@@ -18,78 +19,15 @@ interface AuthReviewBundle {
18
19
  function inspectAuthBundle(bundle: AuthReviewBundle): string {
19
20
  return [
20
21
  'Auth Review Bundle',
21
- ` exportedAt: ${new Date(bundle.exportedAt).toISOString()}`,
22
- ` externalRuntimeAuth: ${bundle.externalRuntimeAuth}`,
23
- ` stored secrets: ${bundle.secretKeys.length}`,
24
- ` active subscriptions: ${bundle.activeSubscriptions.length}`,
25
- ` pending subscriptions: ${bundle.pendingSubscriptions.length}`,
22
+ ` exported at ${new Date(bundle.exportedAt).toISOString()}`,
23
+ ` connected host auth ${bundle.externalRuntimeAuth}`,
24
+ ` stored secrets ${bundle.secretKeys.length}`,
25
+ ` active subscriptions ${bundle.activeSubscriptions.length}`,
26
+ ` pending subscriptions ${bundle.pendingSubscriptions.length}`,
26
27
  ].join('\n');
27
28
  }
28
29
 
29
30
  export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry): void {
30
- registry.register({
31
- name: 'login',
32
- description: 'Front-door login flow for provider subscriptions',
33
- usage: 'provider <name> start|finish <code> --yes',
34
- async handler(args, ctx) {
35
- const parsed = stripYesFlag(args);
36
- const commandArgs = [...parsed.rest];
37
- const target = (commandArgs[0] ?? '').toLowerCase();
38
- if (target === 'provider') {
39
- const provider = commandArgs[1];
40
- const mode = commandArgs[2]?.toLowerCase();
41
- if (!provider || !mode) {
42
- ctx.print('Usage: /login provider <name> start|finish <code> --yes');
43
- return;
44
- }
45
- if (!parsed.yes) {
46
- requireYesFlag(ctx, `${mode} provider subscription login for ${provider}`, '/login provider <name> start|finish <code> --yes');
47
- return;
48
- }
49
- if (ctx.executeCommand) {
50
- await ctx.executeCommand('subscription', ['login', provider, mode, ...commandArgs.slice(3), '--yes']);
51
- return;
52
- }
53
- ctx.print(`Use /subscription login ${provider} ${mode}${commandArgs[3] ? ` ${commandArgs[3]}` : ''} --yes`);
54
- return;
55
- }
56
- if (target === 'service' || target === 'runtime' || target === 'listener' || target === 'daemon') {
57
- ctx.print([
58
- 'Connected-service login is outside GoodVibes Agent.',
59
- 'Agent does not create, exchange, store, rotate, revoke, or clear connected-service sessions.',
60
- 'Use the owning GoodVibes host for connected-service auth administration.',
61
- 'Agent login supports provider subscriptions only: /login provider <name> start|finish <code> --yes.',
62
- ].join('\n'));
63
- return;
64
- }
65
- ctx.print('Usage: /login provider <name> start|finish <code> --yes');
66
- },
67
- });
68
-
69
- registry.register({
70
- name: 'logout',
71
- description: 'Front-door logout flow for provider subscription sessions and supported overrides',
72
- usage: 'provider <name> --yes',
73
- async handler(args, ctx) {
74
- const parsed = stripYesFlag(args);
75
- const commandArgs = [...parsed.rest];
76
- const target = (commandArgs[0] ?? '').toLowerCase();
77
- if (target !== 'provider' || !commandArgs[1]) {
78
- ctx.print('Usage: /logout provider <name> --yes');
79
- return;
80
- }
81
- if (!parsed.yes) {
82
- requireYesFlag(ctx, `log out provider subscription ${commandArgs[1]}`, '/logout provider <name> --yes');
83
- return;
84
- }
85
- if (ctx.executeCommand) {
86
- await ctx.executeCommand('subscription', ['logout', commandArgs[1], '--yes']);
87
- return;
88
- }
89
- ctx.print(`Use /subscription logout ${commandArgs[1]} --yes`);
90
- },
91
- });
92
-
93
31
  registry.register({
94
32
  name: 'auth',
95
33
  description: 'Review provider auth posture and export redacted auth review bundles',
@@ -100,18 +38,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
100
38
  const sub = commandArgs[0] ?? 'review';
101
39
  if (sub === 'local') {
102
40
  ctx.print([
103
- 'Connected-service auth management is outside GoodVibes Agent.',
104
- 'Agent connects to GoodVibes services owned outside this package and does not create, delete, rotate, revoke, or clear connected-service auth users, sessions, or bootstrap credentials.',
105
- 'Use the owning GoodVibes host for connected-service auth administration.',
41
+ 'Connected-host auth management is outside GoodVibes Agent.',
42
+ 'Agent connects to a GoodVibes host owned outside this package and does not create, delete, rotate, revoke, or clear connected-host auth users, sessions, or bootstrap credentials.',
43
+ 'Use the owning GoodVibes host for connected-host auth administration.',
106
44
  'Agent auth commands available here: /auth review, /auth show <provider>, /auth repair <provider>, /auth bundle export <path> --yes, /auth bundle inspect <path>.',
107
45
  ].join('\n'));
108
46
  return;
109
47
  }
110
48
  if (sub === 'login') {
111
49
  ctx.print([
112
- 'Connected-service login is outside GoodVibes Agent.',
113
- 'Agent does not create, exchange, store, rotate, revoke, or clear connected-service sessions.',
114
- 'Use the owning GoodVibes host for connected-service auth administration.',
50
+ 'Connected-host login is outside GoodVibes Agent.',
51
+ 'Agent does not create, exchange, store, rotate, revoke, or clear connected-host sessions.',
52
+ 'Use the owning GoodVibes host for connected-host auth administration.',
115
53
  ].join('\n'));
116
54
  return;
117
55
  }
@@ -129,12 +67,12 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
129
67
  const builtinProviders = listBuiltinSubscriptionProviders().map((entry) => entry.provider);
130
68
  ctx.print([
131
69
  'Auth Review',
132
- ' connected-service auth: managed outside goodvibes-agent',
133
- ` stored secrets: ${snapshot.secretKeyCount}`,
134
- ` built-in providers: ${builtinProviders.length}${builtinProviders.length > 0 ? ` (${builtinProviders.join(', ')})` : ''}`,
135
- ` active subscriptions: ${snapshot.activeSubscriptions}${snapshot.activeSubscriptions > 0 ? ` (${snapshot.providers.filter((provider) => provider.activeSubscription).map((provider) => provider.provider).join(', ')})` : ''}`,
136
- ` pending subscriptions: ${snapshot.pendingSubscriptions}${snapshot.pendingSubscriptions > 0 ? ` (${snapshot.providers.filter((provider) => provider.pendingLogin).map((provider) => provider.provider).join(', ')})` : ''}`,
137
- ...snapshot.providers.map((provider) => ` ${provider.provider} freshness=${provider.freshness} mode=${provider.callbackMode} configured=${provider.configured ? 'yes' : 'no'}`),
70
+ ' connected host auth managed outside goodvibes-agent',
71
+ ` stored secrets ${snapshot.secretKeyCount}`,
72
+ ` built-in providers ${builtinProviders.length}${builtinProviders.length > 0 ? ` (${builtinProviders.join(', ')})` : ''}`,
73
+ ` active subscriptions ${snapshot.activeSubscriptions}${snapshot.activeSubscriptions > 0 ? ` (${snapshot.providers.filter((provider) => provider.activeSubscription).map((provider) => provider.provider).join(', ')})` : ''}`,
74
+ ` pending subscriptions ${snapshot.pendingSubscriptions}${snapshot.pendingSubscriptions > 0 ? ` (${snapshot.providers.filter((provider) => provider.pendingLogin).map((provider) => provider.provider).join(', ')})` : ''}`,
75
+ ...snapshot.providers.map((provider) => ` ${provider.provider} auth ${provider.freshness} finish manual configured ${provider.configured ? 'yes' : 'no'}`),
138
76
  ].join('\n'));
139
77
  return;
140
78
  }
@@ -152,19 +90,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
152
90
  });
153
91
  ctx.print([
154
92
  `Auth Provider ${provider}`,
155
- ` configured: ${inspection.configured ? 'yes' : 'no'}`,
156
- ...(inspection.source ? [` source: ${inspection.source}`] : []),
157
- ` freshness: ${inspection.freshness}`,
158
- ` callbackMode: ${inspection.callbackMode}`,
159
- ...(inspection.redirectUri ? [` redirectUri: ${inspection.redirectUri}`] : []),
160
- ...(inspection.localCallback ? [` localCallback: ${inspection.localCallback}`] : []),
161
- ` activeSubscription: ${inspection.activeSubscription ? 'yes' : 'no'}`,
162
- ` pendingLogin: ${inspection.pendingLogin ? 'yes' : 'no'}`,
163
- ` overrideAmbientApiKeys: ${inspection.overrideAmbientApiKeys ? 'yes' : 'no'}`,
164
- ...(inspection.tokenType ? [` tokenType: ${inspection.tokenType}`] : []),
165
- ...(inspection.expiresAt ? [` expiresAt: ${new Date(inspection.expiresAt).toISOString()}`] : []),
166
- ...inspection.issues.map((issue) => ` issue: ${issue}`),
167
- ...inspection.nextActions.map((action) => ` next: ${action}`),
93
+ ` configured ${inspection.configured ? 'yes' : 'no'}`,
94
+ ...(inspection.source ? [` origin ${formatAgentRecordSource(inspection.source)}`] : []),
95
+ ` freshness ${inspection.freshness}`,
96
+ ' finish mode explicit manual',
97
+ ...(inspection.redirectUri ? [` redirect URI ${inspection.redirectUri}`] : []),
98
+ ` active subscription ${inspection.activeSubscription ? 'yes' : 'no'}`,
99
+ ` pending login ${inspection.pendingLogin ? 'yes' : 'no'}`,
100
+ ` ambient API key override ${inspection.overrideAmbientApiKeys ? 'yes' : 'no'}`,
101
+ ...(inspection.tokenType ? [` token type ${inspection.tokenType}`] : []),
102
+ ...(inspection.expiresAt ? [` expires at ${new Date(inspection.expiresAt).toISOString()}`] : []),
103
+ ...inspection.issues.map((issue) => ` issue ${issue}`),
104
+ ...inspection.nextActions.map((action) => ` next ${action}`),
168
105
  ].join('\n'));
169
106
  return;
170
107
  }
@@ -182,12 +119,12 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
182
119
  });
183
120
  ctx.print([
184
121
  `Auth Repair ${provider}`,
185
- ` configured: ${inspection.configured ? 'yes' : 'no'}`,
186
- ` freshness: ${inspection.freshness}`,
187
- ` callbackMode: ${inspection.callbackMode}`,
188
- ...inspection.issues.map((issue) => ` issue: ${issue}`),
122
+ ` configured ${inspection.configured ? 'yes' : 'no'}`,
123
+ ` freshness ${inspection.freshness}`,
124
+ ' finish mode explicit manual',
125
+ ...inspection.issues.map((issue) => ` issue ${issue}`),
189
126
  ...(inspection.nextActions.length > 0
190
- ? [' next:', ...inspection.nextActions.map((action) => ` ${action}`)]
127
+ ? [' next', ...inspection.nextActions.map((action) => ` ${action}`)]
191
128
  : [' No active repair actions suggested.']),
192
129
  ].join('\n'));
193
130
  return;
@@ -68,7 +68,7 @@ function formatTrustReview(bundle: TrustReviewBundle): string {
68
68
  'Trust Review',
69
69
  ` permission mode: ${bundle.permissionMode}`,
70
70
  ` secrets stored: ${bundle.secretKeys.length}`,
71
- ` configured services: ${bundle.serviceNames.length}`,
71
+ ` configured integrations: ${bundle.serviceNames.length}`,
72
72
  ` plugins: ${bundle.pluginSummary.total} (trusted ${bundle.pluginSummary.trusted}, limited ${bundle.pluginSummary.limited}, untrusted ${bundle.pluginSummary.untrusted}, quarantined ${bundle.pluginSummary.quarantined})`,
73
73
  ` MCP servers: ${bundle.mcpSummary.total} (constrained ${bundle.mcpSummary.constrained}, ask-on-risk ${bundle.mcpSummary.askOnRisk}, allow-all ${bundle.mcpSummary.allowAll}, blocked ${bundle.mcpSummary.blocked}, quarantined ${bundle.mcpSummary.quarantined})`,
74
74
  ].join('\n');
@@ -81,7 +81,7 @@ function inspectTrustBundle(path: string): string {
81
81
  ` captured: ${new Date(parsed.capturedAt).toISOString()}`,
82
82
  ` permission mode: ${parsed.permissionMode}`,
83
83
  ` secrets stored: ${parsed.secretKeys.length}`,
84
- ` configured services: ${parsed.serviceNames.length}`,
84
+ ` configured integrations: ${parsed.serviceNames.length}`,
85
85
  ` plugins: ${parsed.pluginSummary.total}`,
86
86
  ` MCP servers: ${parsed.mcpSummary.total}`,
87
87
  ].join('\n');
@@ -2,13 +2,34 @@ import type { CommandContext, CommandRegistry } from '../command-registry.ts';
2
2
  import type {
3
3
  ProviderAccountRecord,
4
4
  ProviderAccountSnapshot,
5
- } from '@/runtime/index.ts';
5
+ ProviderAuthRoute,
6
+ ProviderRouteRecord,
7
+ } from '../../panels/provider-account-snapshot.ts';
8
+ import { buildProviderAccountSnapshot } from '../../panels/provider-account-snapshot.ts';
6
9
  import {
7
- requireOperatorClient,
10
+ requireProvider,
11
+ requireServiceRegistry,
12
+ requireSubscriptionManager,
8
13
  } from './runtime-services.ts';
14
+ import { formatProviderAuthRouteId } from '../../provider-auth-route-display.ts';
15
+
16
+ function formatRouteList(routes: readonly ProviderAuthRoute[]): string {
17
+ return routes.map((route) => formatProviderAuthRouteId(route)).join(', ');
18
+ }
19
+
20
+ function formatRouteRecord(route: ProviderRouteRecord): string {
21
+ return `${formatProviderAuthRouteId(route.route)} ${route.usable ? 'usable' : 'blocked'} auth ${route.freshness} ${route.detail}`;
22
+ }
9
23
 
10
24
  async function loadProviderAccountSnapshot(context: CommandContext): Promise<ProviderAccountSnapshot> {
11
- return await requireOperatorClient(context).providers.accountSnapshot();
25
+ return await buildProviderAccountSnapshot({
26
+ providerModels: requireProvider(context).providerRegistry,
27
+ services: requireServiceRegistry(context),
28
+ subscriptions: requireSubscriptionManager(context),
29
+ environment: {
30
+ hasEnvironmentVariable: (name: string) => Boolean(process.env[name]),
31
+ },
32
+ });
12
33
  }
13
34
 
14
35
  function findProviderAccountRecord(
@@ -28,7 +49,7 @@ export function registerProviderAccountsRuntimeCommands(registry: CommandRegistr
28
49
  async handler(args, ctx) {
29
50
  const sub = (args[0] ?? 'review').toLowerCase();
30
51
  if (sub === 'panel' || sub === 'open') {
31
- ctx.print('Provider account panels are not part of the Agent workspace. Use /accounts review.');
52
+ ctx.print('Open Agent Workspace -> Setup -> Provider accounts for the workspace view, or run /accounts review for compact command output.');
32
53
  return;
33
54
  }
34
55
  const snapshot = await loadProviderAccountSnapshot(ctx);
@@ -36,16 +57,16 @@ export function registerProviderAccountsRuntimeCommands(registry: CommandRegistr
36
57
  const providerId = args[1];
37
58
  const record = findProviderAccountRecord(snapshot, providerId);
38
59
  if (!record) {
39
- ctx.print(providerId ? `Unknown provider account: ${providerId}` : 'Usage: /accounts routes <provider>');
60
+ ctx.print(providerId ? `Unknown provider account ${providerId}` : 'Usage: /accounts routes <provider>');
40
61
  return;
41
62
  }
42
63
  ctx.print([
43
64
  `Provider Routes ${record.providerId}`,
44
- ` preferred: ${record.preferredRoute}`,
45
- ` active: ${record.activeRoute}`,
46
- ` reason: ${record.activeRouteReason}`,
47
- ...record.routeRecords.map((route) => ` ${route.route} usable=${route.usable ? 'yes' : 'no'} freshness=${route.freshness} ${route.detail}`),
48
- ...record.routeRecords.flatMap((route) => route.issues.map((issue) => ` issue: ${issue}`)),
65
+ ` preferred route ${formatProviderAuthRouteId(record.preferredRoute)}`,
66
+ ` active route ${formatProviderAuthRouteId(record.activeRoute)}`,
67
+ ` reason ${record.activeRouteReason}`,
68
+ ...record.routeRecords.map((route) => ` ${formatRouteRecord(route)}`),
69
+ ...record.routeRecords.flatMap((route) => route.issues.map((issue) => ` issue ${issue}`)),
49
70
  ].join('\n'));
50
71
  return;
51
72
  }
@@ -53,17 +74,17 @@ export function registerProviderAccountsRuntimeCommands(registry: CommandRegistr
53
74
  const providerId = args[1];
54
75
  const record = findProviderAccountRecord(snapshot, providerId);
55
76
  if (!record) {
56
- ctx.print(providerId ? `Unknown provider account: ${providerId}` : 'Usage: /accounts repair <provider>');
77
+ ctx.print(providerId ? `Unknown provider account ${providerId}` : 'Usage: /accounts repair <provider>');
57
78
  return;
58
79
  }
59
80
  ctx.print([
60
81
  `Provider Account Repair ${record.providerId}`,
61
- ` active route: ${record.activeRoute}`,
62
- ` preferred route: ${record.preferredRoute}`,
63
- ...(record.fallbackRisk ? [` fallback: ${record.fallbackRisk}`] : []),
64
- ...(record.issues.map((issue) => ` issue: ${issue}`)),
82
+ ` active route ${formatProviderAuthRouteId(record.activeRoute)}`,
83
+ ` preferred route ${formatProviderAuthRouteId(record.preferredRoute)}`,
84
+ ...(record.fallbackRisk ? [` routing risk ${record.fallbackRisk}`] : []),
85
+ ...(record.issues.map((issue) => ` issue ${issue}`)),
65
86
  ...(record.recommendedActions.length > 0
66
- ? [' next:', ...record.recommendedActions.map((action) => ` ${action}`)]
87
+ ? [' next', ...record.recommendedActions.map((action) => ` ${action}`)]
67
88
  : [' No active repair actions suggested.']),
68
89
  ].join('\n'));
69
90
  return;
@@ -72,39 +93,39 @@ export function registerProviderAccountsRuntimeCommands(registry: CommandRegistr
72
93
  const providerId = args[1];
73
94
  const record = findProviderAccountRecord(snapshot, providerId);
74
95
  if (!record) {
75
- ctx.print(providerId ? `Unknown provider account: ${providerId}` : 'Usage: /accounts show <provider>');
96
+ ctx.print(providerId ? `Unknown provider account ${providerId}` : 'Usage: /accounts show <provider>');
76
97
  return;
77
98
  }
78
99
  ctx.print([
79
100
  `Provider Account ${record.providerId}`,
80
- ` preferredRoute: ${record.preferredRoute}`,
81
- ` activeRoute: ${record.activeRoute}`,
82
- ` authFreshness: ${record.authFreshness}`,
83
- ` configured: ${record.configured ? 'yes' : 'no'}`,
84
- ` oauthReady: ${record.oauthReady ? 'yes' : 'no'}`,
85
- ` pendingLogin: ${record.pendingLogin ? 'yes' : 'no'}`,
86
- ` availableRoutes: ${record.availableRoutes.join(', ')}`,
87
- ` modelCount: ${record.modelCount}`,
88
- ` routeReason: ${record.activeRouteReason}`,
89
- ...(record.fallbackRoute ? [` fallbackRoute: ${record.fallbackRoute}`] : []),
90
- ...(record.fallbackRisk ? [` fallbackRisk: ${record.fallbackRisk}`] : []),
91
- ...(record.expiresAt ? [` expiresAt: ${new Date(record.expiresAt).toISOString()}`] : []),
92
- ...record.routeRecords.map((route) => ` route ${route.route}: usable=${route.usable ? 'yes' : 'no'} freshness=${route.freshness} — ${route.detail}`),
93
- ...record.routeRecords.flatMap((route) => route.issues.map((issue) => ` issue: ${issue}`)),
94
- ...record.usageWindows.map((entry) => ` window: ${entry.label} — ${entry.detail}`),
95
- ...record.issues.map((issue) => ` issue: ${issue}`),
96
- ...record.notes.map((note) => ` note: ${note}`),
97
- ...record.recommendedActions.map((action) => ` next: ${action}`),
101
+ ` preferred route ${formatProviderAuthRouteId(record.preferredRoute)}`,
102
+ ` active route ${formatProviderAuthRouteId(record.activeRoute)}`,
103
+ ` auth freshness ${record.authFreshness}`,
104
+ ` configured ${record.configured ? 'yes' : 'no'}`,
105
+ ` OAuth ready ${record.oauthReady ? 'yes' : 'no'}`,
106
+ ` pending login ${record.pendingLogin ? 'yes' : 'no'}`,
107
+ ` available routes ${formatRouteList(record.availableRoutes)}`,
108
+ ` model count ${record.modelCount}`,
109
+ ` route reason ${record.activeRouteReason}`,
110
+ ...(record.fallbackRoute ? [` fallback route ${formatProviderAuthRouteId(record.fallbackRoute)}`] : []),
111
+ ...(record.fallbackRisk ? [` routing risk ${record.fallbackRisk}`] : []),
112
+ ...(record.expiresAt ? [` expires at ${new Date(record.expiresAt).toISOString()}`] : []),
113
+ ...record.routeRecords.map((route) => ` route ${formatRouteRecord(route)}`),
114
+ ...record.routeRecords.flatMap((route) => route.issues.map((issue) => ` issue ${issue}`)),
115
+ ...record.usageWindows.map((entry) => ` window ${entry.label} — ${entry.detail}`),
116
+ ...record.issues.map((issue) => ` issue ${issue}`),
117
+ ...record.notes.map((note) => ` note ${note}`),
118
+ ...record.recommendedActions.map((action) => ` next ${action}`),
98
119
  ].join('\n'));
99
120
  return;
100
121
  }
101
122
  ctx.print([
102
123
  'Provider Account Review',
103
- ` providers: ${snapshot.providers.length}`,
104
- ` configured: ${snapshot.configuredCount}`,
105
- ` issues: ${snapshot.issueCount}`,
124
+ ` providers ${snapshot.providers.length}`,
125
+ ` configured ${snapshot.configuredCount}`,
126
+ ` issues ${snapshot.issueCount}`,
106
127
  ...snapshot.providers.map((record) => (
107
- ` ${record.providerId} active=${record.activeRoute} preferred=${record.preferredRoute} freshness=${record.authFreshness} models=${record.modelCount} issues=${record.issues.length}`
128
+ ` ${record.providerId} active route ${formatProviderAuthRouteId(record.activeRoute)} preferred route ${formatProviderAuthRouteId(record.preferredRoute)} auth ${record.authFreshness} models ${record.modelCount} issues ${record.issues.length}`
108
129
  )),
109
130
  ].join('\n'));
110
131
  },
@@ -1,16 +1,15 @@
1
1
  import type { CommandRegistry } from '../command-registry.ts';
2
- import { join } from 'node:path';
3
2
  import { networkInterfaces } from 'node:os';
4
3
  import {
5
4
  buildCompanionConnectionInfo,
5
+ type CompanionConnectionInfo,
6
6
  encodeConnectionPayload,
7
- formatConnectionBlock,
8
7
  generateQrMatrix,
9
- getOrCreateCompanionToken,
10
8
  renderQrToString,
11
9
  } from '@pellux/goodvibes-sdk/platform/pairing';
12
10
  import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../../config/surface.ts';
13
11
  import { resolveRuntimeEndpointBinding } from '../../cli/endpoints.ts';
12
+ import { connectedHostOperatorTokenFingerprint, connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../../runtime/connected-host-auth.ts';
14
13
  import { requirePlatform, requireShellPaths } from './runtime-services.ts';
15
14
 
16
15
  function getLocalNetworkIp(): string {
@@ -32,28 +31,70 @@ function urlHostForBindHost(host: string): string {
32
31
  return host || '127.0.0.1';
33
32
  }
34
33
 
34
+ function formatTokenLine(token: string, showToken: boolean): string {
35
+ if (showToken) return `Token: ${token}`;
36
+ return `Token: present sha256:${connectedHostOperatorTokenFingerprint(token)} (hidden in text; QR contains pairing payload)`;
37
+ }
38
+
39
+ function formatAgentPairingBlock(info: CompanionConnectionInfo, qr: string, showToken: boolean): string {
40
+ return [
41
+ `GoodVibes Agent companion pairing v${info.version}`,
42
+ '━━━━━━━━━━━━━━━━━━━━━━━━',
43
+ `Connected host: ${info.url}`,
44
+ `Surface: ${info.surface}`,
45
+ `User: ${info.username}`,
46
+ formatTokenLine(info.token, showToken),
47
+ '',
48
+ 'Scan to connect:',
49
+ '',
50
+ qr,
51
+ '',
52
+ showToken
53
+ ? 'Manual token display was explicitly confirmed for this command.'
54
+ : 'For manual setup, rerun /pair --show-token --yes to print the token once.',
55
+ 'Agent is waiting for the companion app to connect to the owning GoodVibes host.',
56
+ ].join('\n');
57
+ }
58
+
59
+ function shouldShowToken(args: readonly string[]): boolean {
60
+ return args.includes('--show-token') || args.includes('--manual-token');
61
+ }
62
+
35
63
  export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
36
64
  registry.register({
37
65
  name: 'qrcode',
38
66
  aliases: ['qr', 'pair'],
39
67
  description: 'Print companion pairing details and a QR code',
40
68
  usage: '',
41
- handler(_args, ctx) {
69
+ handler(args, ctx) {
42
70
  const shellPaths = requireShellPaths(ctx);
43
71
  const configManager = requirePlatform(ctx).configManager;
44
- const daemonHomeDir = join(shellPaths.homeDirectory, '.goodvibes', 'daemon');
45
- const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
72
+ const tokenRecord = readConnectedHostOperatorToken(shellPaths.homeDirectory);
73
+ if (!tokenRecord.token) {
74
+ ctx.print(connectedHostTokenRequiredMessage(tokenRecord.path));
75
+ return;
76
+ }
46
77
  const binding = resolveRuntimeEndpointBinding(configManager, 'controlPlane');
47
- const daemonUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
78
+ const connectedHostUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
48
79
  const info = buildCompanionConnectionInfo({
49
- daemonUrl,
80
+ daemonUrl: connectedHostUrl,
50
81
  token: tokenRecord.token,
51
82
  username: 'admin',
52
83
  surface: GOODVIBES_AGENT_PAIRING_SURFACE,
53
84
  });
54
85
  const payload = encodeConnectionPayload(info);
55
86
  const qr = renderQrToString(generateQrMatrix(payload));
56
- ctx.print([formatConnectionBlock(info, payload), '', qr].join('\n'));
87
+ const showToken = shouldShowToken(args);
88
+ if (showToken && !args.includes('--yes')) {
89
+ ctx.print([
90
+ 'Manual companion token display requires confirmation.',
91
+ ' rerun: /pair --show-token --yes',
92
+ ` token fingerprint: sha256:${connectedHostOperatorTokenFingerprint(tokenRecord.token)}`,
93
+ ' QR pairing remains available without printing the raw token.',
94
+ ].join('\n'));
95
+ return;
96
+ }
97
+ ctx.print(formatAgentPairingBlock(info, qr, showToken));
57
98
  },
58
99
  });
59
100
  }
@@ -31,7 +31,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
31
31
  if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
32
32
  const scope = commandArgs[scopeIdx + 1];
33
33
  if (!isValidScope(scope)) {
34
- context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
34
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
35
35
  return;
36
36
  }
37
37
  filter.scope = scope;
@@ -41,7 +41,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
41
41
  if (clsIdx !== -1 && commandArgs[clsIdx + 1]) {
42
42
  const cls = commandArgs[clsIdx + 1];
43
43
  if (!isValidClass(cls)) {
44
- context.print(`[memory] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
44
+ context.print(`[memory] Unknown class "${cls}". Valid values ${VALID_CLASSES.join(', ')}.`);
45
45
  return;
46
46
  }
47
47
  filter.cls = cls;
@@ -77,23 +77,23 @@ export async function handleRecallImport(args: string[], context: CommandContext
77
77
  try {
78
78
  bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
79
79
  } catch (error) {
80
- context.print(`[memory] Failed to read memory bundle: ${summarizeError(error)}`);
80
+ context.print(`[memory] Failed to read memory bundle ${summarizeError(error)}`);
81
81
  return;
82
82
  }
83
83
 
84
84
  const result = await memory.importBundle(bundle);
85
85
  context.print(`[memory] Imported bundle from ${targetPath}`);
86
- context.print(` Records: imported=${result.importedRecords} skipped=${result.skippedRecords}`);
87
- context.print(` Links: imported=${result.importedLinks}`);
86
+ context.print(` records imported=${result.importedRecords} skipped=${result.skippedRecords}`);
87
+ context.print(` links imported=${result.importedLinks}`);
88
88
  }
89
89
 
90
90
  function inspectBundle(bundle: MemoryBundle): string {
91
91
  return [
92
92
  'Memory Handoff Review',
93
- ` scope: ${bundle.scope}`,
94
- ` records: ${bundle.recordCount}`,
95
- ` links: ${bundle.linkCount}`,
96
- ` exportedAt: ${new Date(bundle.exportedAt).toISOString()}`,
93
+ ` scope ${bundle.scope}`,
94
+ ` records ${bundle.recordCount}`,
95
+ ` links ${bundle.linkCount}`,
96
+ ` exportedAt ${new Date(bundle.exportedAt).toISOString()}`,
97
97
  ].join('\n');
98
98
  }
99
99
 
@@ -116,7 +116,7 @@ export function handleRecallHandoffExport(args: string[], context: CommandContex
116
116
  const scopeIdx = commandArgs.indexOf('--scope');
117
117
  const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : 'team';
118
118
  if (!scopeRaw || !isValidScope(scopeRaw)) {
119
- context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid: ${VALID_SCOPES.join(', ')}`);
119
+ context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid values ${VALID_SCOPES.join(', ')}.`);
120
120
  return;
121
121
  }
122
122
  const bundle = memory.exportBundle({ scope: scopeRaw });
@@ -137,7 +137,7 @@ export function handleRecallHandoffInspect(args: string[], context: CommandConte
137
137
  const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
138
138
  context.print(inspectBundle(bundle));
139
139
  } catch (error) {
140
- context.print(`[memory] Failed to inspect handoff bundle: ${summarizeError(error)}`);
140
+ context.print(`[memory] Failed to inspect handoff bundle ${summarizeError(error)}`);
141
141
  }
142
142
  }
143
143
 
@@ -1,5 +1,6 @@
1
1
  import type { CommandContext } from '../command-registry.ts';
2
2
  import type { ProvenanceLink } from '@pellux/goodvibes-sdk/platform/state';
3
+ import { formatAgentRecordReferences } from '../../agent/record-labels.ts';
3
4
  import {
4
5
  buildIncidentMemoryAddOptions,
5
6
  buildMcpSecurityMemoryAddOptions,
@@ -17,7 +18,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
17
18
 
18
19
  const cls = args[0];
19
20
  if (!cls || !isValidClass(cls)) {
20
- context.print(`[memory] Invalid class "${cls ?? ''}". Valid: ${VALID_CLASSES.join(', ')}`);
21
+ context.print(`[memory] Invalid class "${cls ?? ''}". Valid values ${VALID_CLASSES.join(', ')}.`);
21
22
  return;
22
23
  }
23
24
 
@@ -36,7 +37,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
36
37
  const scope = scopeRaw && isValidScope(scopeRaw) ? scopeRaw : 'project';
37
38
 
38
39
  if (scopeRaw && !isValidScope(scopeRaw)) {
39
- context.print(`[memory] Invalid scope "${scopeRaw}". Valid: ${VALID_SCOPES.join(', ')}`);
40
+ context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES.join(', ')}.`);
40
41
  return;
41
42
  }
42
43
 
@@ -60,12 +61,13 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
60
61
  }
61
62
 
62
63
  const record = await memory.add({ scope, cls, summary, detail, tags, provenance });
63
- context.print(`[memory] Added ${cls}: ${record.id}`);
64
- context.print(` Scope: ${record.scope}`);
65
- context.print(` Summary: ${record.summary}`);
66
- if (record.tags.length) context.print(` Tags: ${record.tags.join(', ')}`);
64
+ context.print(`[memory] Added ${cls}`);
65
+ context.print(` id ${record.id}`);
66
+ context.print(` scope ${record.scope}`);
67
+ context.print(` summary ${record.summary}`);
68
+ if (record.tags.length) context.print(` tags ${record.tags.join(', ')}`);
67
69
  if (record.provenance.length) {
68
- context.print(` Provenance: ${record.provenance.map((entry) => `${entry.kind}:${entry.ref}`).join(', ')}`);
70
+ context.print(` origin ${formatAgentRecordReferences(record.provenance)}`);
69
71
  }
70
72
  }
71
73
 
@@ -87,12 +89,12 @@ export async function handleRecallCapture(args: string[], context: CommandContex
87
89
  ? context.extensions.forensicsRegistry.latest()
88
90
  : context.extensions.forensicsRegistry.getById(requestedId);
89
91
  if (!report) {
90
- context.print(`[memory] Incident not found: ${requestedId ?? 'latest'}`);
92
+ context.print(`[memory] Incident not found ${requestedId ?? 'latest'}`);
91
93
  return;
92
94
  }
93
95
  const bundle = context.extensions.forensicsRegistry.buildBundle(report.id);
94
96
  if (!bundle) {
95
- context.print(`[memory] Failed to build incident bundle: ${report.id}`);
97
+ context.print(`[memory] Failed to build incident bundle ${report.id}`);
96
98
  return;
97
99
  }
98
100
  const record = await memory.add(buildIncidentMemoryAddOptions(bundle));
@@ -119,7 +121,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
119
121
  }
120
122
  const server = context.extensions.mcpRegistry.listServerSecurity().find((entry) => entry.name === serverName);
121
123
  if (!server) {
122
- context.print(`[memory] MCP server not found: ${serverName}`);
124
+ context.print(`[memory] MCP server not found ${serverName}`);
123
125
  return;
124
126
  }
125
127
  const record = await memory.add(buildMcpSecurityMemoryAddOptions(server));
@@ -139,7 +141,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
139
141
  }
140
142
  const plugin = pluginManager.list().find((entry) => entry.name === pluginName);
141
143
  if (!plugin) {
142
- context.print(`[memory] Plugin not found: ${pluginName}`);
144
+ context.print(`[memory] Plugin not found ${pluginName}`);
143
145
  return;
144
146
  }
145
147
  const quarantineReason = pluginManager.getQuarantineRecord(plugin.name)?.reason;