@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
@@ -17,6 +17,7 @@ import {
17
17
  type ProvenanceLinkKind,
18
18
  } from '@pellux/goodvibes-sdk/platform/state';
19
19
  import { assertNoSecretLikeMemoryText } from '../agent/memory-safety.ts';
20
+ import { formatAgentRecordReference, formatAgentRecordReviewState } from '../agent/record-labels.ts';
20
21
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
21
22
  import type { CliCommandOutput } from './types.ts';
22
23
  import type { CliCommandRuntime } from './management.ts';
@@ -172,12 +173,12 @@ function isProvenanceKind(value: string): value is ProvenanceLinkKind {
172
173
  }
173
174
 
174
175
  function requireClass(value: string | undefined): MemoryClass {
175
- if (!value || !isMemoryClass(value)) throw new Error(`Invalid memory class "${value ?? ''}". Valid: ${VALID_CLASSES.join(', ')}`);
176
+ if (!value || !isMemoryClass(value)) throw new Error(`Invalid memory class "${value ?? ''}". Valid values ${VALID_CLASSES.join(', ')}`);
176
177
  return value;
177
178
  }
178
179
 
179
180
  function requireScope(value: string | undefined): MemoryScope {
180
- if (!value || !isMemoryScope(value)) throw new Error(`Invalid memory scope "${value ?? ''}". Valid: ${VALID_SCOPES.join(', ')}`);
181
+ if (!value || !isMemoryScope(value)) throw new Error(`Invalid memory scope "${value ?? ''}". Valid values ${VALID_SCOPES.join(', ')}`);
181
182
  return value;
182
183
  }
183
184
 
@@ -217,23 +218,23 @@ async function withMemory<T>(runtime: CliCommandRuntime, fn: (context: MemoryCon
217
218
  }
218
219
 
219
220
  function renderRecordLine(record: MemoryRecord, semanticEntry?: MemorySemanticSearchResult): string {
220
- const tags = record.tags.length > 0 ? ` tags=${record.tags.join(',')}` : '';
221
- const score = semanticEntry ? ` sim=${Math.round(semanticEntry.similarity * 100)}%` : '';
222
- return ` ${record.id} ${record.scope}/${record.cls} ${record.reviewState} ${record.confidence}%${score}${tags} ${record.summary}`;
221
+ const tags = record.tags.length > 0 ? ` tags ${record.tags.join(', ')}` : '';
222
+ const score = semanticEntry ? ` similarity ${Math.round(semanticEntry.similarity * 100)}%` : '';
223
+ return ` ${record.id} ${record.scope}/${record.cls} ${formatAgentRecordReviewState(record.reviewState)} ${record.confidence}%${score}${tags} ${record.summary}`;
223
224
  }
224
225
 
225
226
  function renderRecordList(title: string, path: string, records: readonly MemoryRecord[], semanticResults: readonly MemorySemanticSearchResult[] = []): string {
226
227
  if (records.length === 0) {
227
228
  return [
228
229
  title,
229
- ` store: ${path}`,
230
+ ` store ${path}`,
230
231
  ' No Agent memory records found.',
231
232
  ' Add one with: goodvibes-agent memory add fact "Useful durable fact" --scope project',
232
233
  ].join('\n');
233
234
  }
234
235
  return [
235
236
  `${title} (${records.length})`,
236
- ` store: ${path}`,
237
+ ` store ${path}`,
237
238
  ...records.map((record) => renderRecordLine(record, semanticResults.find((entry) => entry.record.id === record.id))),
238
239
  ].join('\n');
239
240
  }
@@ -243,7 +244,7 @@ function renderRecord(record: MemoryRecord, links: readonly MemoryLink[]): strin
243
244
  `Memory ${record.id}`,
244
245
  ` scope: ${record.scope}`,
245
246
  ` class: ${record.cls}`,
246
- ` review: ${record.reviewState}`,
247
+ ` review: ${formatAgentRecordReviewState(record.reviewState)}`,
247
248
  ` confidence: ${record.confidence}`,
248
249
  ` tags: ${record.tags.join(', ') || '(none)'}`,
249
250
  ` created: ${timestamp(record.createdAt)}`,
@@ -253,9 +254,9 @@ function renderRecord(record: MemoryRecord, links: readonly MemoryLink[]): strin
253
254
  '',
254
255
  record.summary,
255
256
  record.detail ? `\n${record.detail}` : '',
256
- record.provenance.length > 0 ? '\nProvenance:' : '',
257
- ...record.provenance.map((entry) => ` ${entry.kind}:${entry.ref}${entry.label ? ` (${entry.label})` : ''}`),
258
- links.length > 0 ? '\nLinks:' : '',
257
+ record.provenance.length > 0 ? '\nProvenance' : '',
258
+ ...record.provenance.map((entry) => ` ${formatAgentRecordReference(entry)}`),
259
+ links.length > 0 ? '\nLinks' : '',
259
260
  ...links.map((link) => ` ${link.fromId} -> ${link.toId} [${link.relation}]`),
260
261
  ].filter((line): line is string => Boolean(line)).join('\n');
261
262
  }
@@ -283,7 +284,7 @@ function provenanceFromOptions(options: ParsedOptions): readonly ProvenanceLink[
283
284
  addProvenance(provenance, 'turn', optionValue(options, 'turn'));
284
285
  addProvenance(provenance, 'task', optionValue(options, 'task'));
285
286
  addProvenance(provenance, 'file', optionValue(options, 'file'));
286
- if (provenance.length === 0) provenance.push({ kind: 'event', ref: 'cli' });
287
+ if (provenance.length === 0) provenance.push({ kind: 'event', ref: 'Command' });
287
288
  return provenance;
288
289
  }
289
290
 
@@ -306,7 +307,7 @@ function usage(): string {
306
307
  ' handoff-inspect <path>',
307
308
  ' vector [status|doctor|rebuild]',
308
309
  '',
309
- 'Agent memory is local to GoodVibes Agent and never falls back to default Knowledge/Wiki or non-Agent knowledge segments.',
310
+ 'Agent memory is local to GoodVibes Agent and never falls back to default knowledge or non-Agent knowledge segments.',
310
311
  ].join('\n');
311
312
  }
312
313
 
@@ -391,11 +392,11 @@ function writeBundle(path: string, bundle: MemoryBundle): void {
391
392
  function renderBundleInspection(path: string, bundle: MemoryBundle): string {
392
393
  return [
393
394
  'Agent memory handoff bundle',
394
- ` path: ${path}`,
395
- ` scope: ${bundle.scope}`,
396
- ` records: ${bundle.recordCount}`,
397
- ` links: ${bundle.linkCount}`,
398
- ...bundle.records.slice(0, 20).map((record) => ` ${record.id} ${record.scope}/${record.cls} ${record.reviewState} ${record.summary}`),
395
+ ` path ${path}`,
396
+ ` scope ${bundle.scope}`,
397
+ ` records ${bundle.recordCount}`,
398
+ ` links ${bundle.linkCount}`,
399
+ ...bundle.records.slice(0, 20).map((record) => ` ${record.id} ${record.scope}/${record.cls} ${formatAgentRecordReviewState(record.reviewState)} ${record.summary}`),
399
400
  bundle.records.length > 20 ? ` ... ${bundle.records.length - 20} more` : '',
400
401
  ].filter((line): line is string => Boolean(line)).join('\n');
401
402
  }
@@ -441,7 +442,7 @@ async function handleAdd(runtime: CliCommandRuntime, context: MemoryContext, arg
441
442
  assertNoSecretLikeMemoryText([summary, detail ?? '', ...(tags ?? [])]);
442
443
  const reviewState = optionValue(options, 'review-state');
443
444
  if (reviewState !== undefined && !isReviewState(reviewState)) {
444
- return failure(runtime, 'invalid_memory_command', `Invalid review state "${reviewState}". Valid: ${VALID_REVIEW_STATES.join(', ')}`, 2);
445
+ return failure(runtime, 'invalid_memory_command', `Invalid review state "${reviewState}". Valid values ${VALID_REVIEW_STATES.join(', ')}`, 2);
445
446
  }
446
447
  const record = await context.registry.add({
447
448
  scope: optionalScope(optionValue(options, 'scope')) ?? 'project',
@@ -456,14 +457,17 @@ async function handleAdd(runtime: CliCommandRuntime, context: MemoryContext, arg
456
457
  reviewedBy: optionValue(options, 'by'),
457
458
  },
458
459
  });
459
- return success(runtime, 'agent.memory.add', record, `Agent memory added: ${record.id}`);
460
+ return success(runtime, 'agent.memory.add', record, [
461
+ 'Agent memory added',
462
+ ` id ${record.id}`,
463
+ ].join('\n'));
460
464
  }
461
465
 
462
466
  async function handleShow(runtime: CliCommandRuntime, context: MemoryContext, args: readonly string[]): Promise<CliCommandOutput> {
463
467
  const id = args[0];
464
468
  if (!id) return failure(runtime, 'invalid_memory_command', 'Usage: goodvibes-agent memory show <id>', 2);
465
469
  const record = context.registry.get(id);
466
- if (!record) return failure(runtime, 'memory_not_found', `Memory record not found: ${id}`, 1);
470
+ if (!record) return failure(runtime, 'memory_not_found', `Memory record not found ${id}`, 1);
467
471
  return success(runtime, 'agent.memory.show', { record, links: context.registry.linksFor(id) }, renderRecord(record, context.registry.linksFor(id)));
468
472
  }
469
473
 
@@ -485,8 +489,13 @@ async function handleReview(runtime: CliCommandRuntime, context: MemoryContext,
485
489
  reviewedBy: optionValue(options, 'by') ?? 'operator',
486
490
  staleReason: optionValue(options, 'reason'),
487
491
  });
488
- if (!record) return failure(runtime, 'memory_not_found', `Memory record not found: ${id}`, 1);
489
- return success(runtime, 'agent.memory.review', record, `Agent memory reviewed: ${record.id} ${record.reviewState} ${record.confidence}%`);
492
+ if (!record) return failure(runtime, 'memory_not_found', `Memory record not found ${id}`, 1);
493
+ return success(runtime, 'agent.memory.review', record, [
494
+ 'Agent memory reviewed',
495
+ ` id ${record.id}`,
496
+ ` review ${formatAgentRecordReviewState(record.reviewState)}`,
497
+ ` confidence ${record.confidence}%`,
498
+ ].join('\n'));
490
499
  }
491
500
 
492
501
  async function handleReviewShortcut(runtime: CliCommandRuntime, context: MemoryContext, state: Extract<MemoryReviewState, 'stale' | 'contradicted'>, args: readonly string[]): Promise<CliCommandOutput> {
@@ -499,8 +508,11 @@ async function handleReviewShortcut(runtime: CliCommandRuntime, context: MemoryC
499
508
  reviewedBy: 'operator',
500
509
  staleReason: reasonParts.join(' '),
501
510
  });
502
- if (!record) return failure(runtime, 'memory_not_found', `Memory record not found: ${id}`, 1);
503
- return success(runtime, `agent.memory.${state}`, record, `Agent memory marked ${state}: ${record.id}`);
511
+ if (!record) return failure(runtime, 'memory_not_found', `Memory record not found ${id}`, 1);
512
+ return success(runtime, `agent.memory.${state}`, record, [
513
+ `Agent memory marked ${state}`,
514
+ ` id ${record.id}`,
515
+ ].join('\n'));
504
516
  }
505
517
 
506
518
  async function handlePromote(runtime: CliCommandRuntime, context: MemoryContext, args: readonly string[]): Promise<CliCommandOutput> {
@@ -509,8 +521,12 @@ async function handlePromote(runtime: CliCommandRuntime, context: MemoryContext,
509
521
  if (!id || !scopeRaw) return failure(runtime, 'invalid_memory_command', 'Usage: goodvibes-agent memory promote <id> <session|project|team> --yes', 2);
510
522
  if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to promote memory record ${id} without --yes.`, 2);
511
523
  const record = context.registry.update(id, { scope: requireScope(scopeRaw) });
512
- if (!record) return failure(runtime, 'memory_not_found', `Memory record not found: ${id}`, 1);
513
- return success(runtime, 'agent.memory.promote', record, `Agent memory promoted: ${record.id} -> ${record.scope}`);
524
+ if (!record) return failure(runtime, 'memory_not_found', `Memory record not found ${id}`, 1);
525
+ return success(runtime, 'agent.memory.promote', record, [
526
+ 'Agent memory promoted',
527
+ ` id ${record.id}`,
528
+ ` scope ${record.scope}`,
529
+ ].join('\n'));
514
530
  }
515
531
 
516
532
  async function handleLink(runtime: CliCommandRuntime, context: MemoryContext, args: readonly string[]): Promise<CliCommandOutput> {
@@ -520,7 +536,12 @@ async function handleLink(runtime: CliCommandRuntime, context: MemoryContext, ar
520
536
  if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to link memory records ${fromId} and ${toId} without --yes.`, 2);
521
537
  const link = await context.registry.link(fromId, toId, relation);
522
538
  if (!link) return failure(runtime, 'memory_link_failed', 'Memory link failed; check that both records exist.', 1);
523
- return success(runtime, 'agent.memory.link', link, `Agent memory linked: ${fromId} -> ${toId} [${relation}]`);
539
+ return success(runtime, 'agent.memory.link', link, [
540
+ 'Agent memory linked',
541
+ ` from ${fromId}`,
542
+ ` to ${toId}`,
543
+ ` relation ${relation}`,
544
+ ].join('\n'));
524
545
  }
525
546
 
526
547
  async function handleDelete(runtime: CliCommandRuntime, context: MemoryContext, args: readonly string[]): Promise<CliCommandOutput> {
@@ -528,8 +549,11 @@ async function handleDelete(runtime: CliCommandRuntime, context: MemoryContext,
528
549
  const id = options.positionals[0];
529
550
  if (!id) return failure(runtime, 'invalid_memory_command', 'Usage: goodvibes-agent memory delete <id> --yes', 2);
530
551
  if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete memory record ${id} without --yes.`, 2);
531
- if (!context.registry.delete(id)) return failure(runtime, 'memory_not_found', `Memory record not found: ${id}`, 1);
532
- return success(runtime, 'agent.memory.delete', { id }, `Agent memory deleted: ${id}`);
552
+ if (!context.registry.delete(id)) return failure(runtime, 'memory_not_found', `Memory record not found ${id}`, 1);
553
+ return success(runtime, 'agent.memory.delete', { id }, [
554
+ `Agent memory deleted: ${id}`,
555
+ ` id ${id}`,
556
+ ].join('\n'));
533
557
  }
534
558
 
535
559
  async function handleExport(runtime: CliCommandRuntime, context: MemoryContext, args: readonly string[]): Promise<CliCommandOutput> {
@@ -541,7 +565,12 @@ async function handleExport(runtime: CliCommandRuntime, context: MemoryContext,
541
565
  const path = resolvePath(runtime, pathArg);
542
566
  const bundle = context.registry.exportBundle(filter);
543
567
  writeBundle(path, bundle);
544
- return success(runtime, 'agent.memory.export', { path, bundle }, `Agent memory exported: ${bundle.recordCount} record(s), ${bundle.linkCount} link(s) -> ${path}`);
568
+ return success(runtime, 'agent.memory.export', { path, bundle }, [
569
+ 'Agent memory exported',
570
+ ` records ${bundle.recordCount}`,
571
+ ` links ${bundle.linkCount}`,
572
+ ` path ${path}`,
573
+ ].join('\n'));
545
574
  }
546
575
 
547
576
  async function handleImport(runtime: CliCommandRuntime, context: MemoryContext, args: readonly string[]): Promise<CliCommandOutput> {
@@ -552,7 +581,12 @@ async function handleImport(runtime: CliCommandRuntime, context: MemoryContext,
552
581
  const path = resolvePath(runtime, pathArg);
553
582
  const bundle = readBundle(path);
554
583
  const result = await context.registry.importBundle(bundle);
555
- return success(runtime, 'agent.memory.import', { path, result }, `Agent memory imported: ${result.importedRecords} record(s), ${result.importedLinks} link(s); skipped ${result.skippedRecords}`);
584
+ return success(runtime, 'agent.memory.import', { path, result }, [
585
+ `Agent memory imported: ${result.importedRecords} record${result.importedRecords === 1 ? '' : 's'}`,
586
+ ` records: ${result.importedRecords}`,
587
+ ` links: ${result.importedLinks}`,
588
+ ` skipped: ${result.skippedRecords}`,
589
+ ].join('\n'));
556
590
  }
557
591
 
558
592
  async function handleInspect(runtime: CliCommandRuntime, args: readonly string[]): Promise<CliCommandOutput> {
package/src/cli/parser.ts CHANGED
@@ -58,28 +58,40 @@ const COMMAND_ALIASES: Readonly<Record<string, GoodVibesCliCommand>> = {
58
58
  version: 'version',
59
59
  };
60
60
 
61
- const BLOCKED_PRODUCT_COMMANDS = new Set([
62
- 'app',
63
- 'bridge',
64
- 'control-plane',
65
- 'controlplane',
66
- 'cp',
67
- 'daemon',
68
- 'http-listener',
69
- 'launch',
70
- 'listener',
71
- 'remote',
72
- 'serve',
73
- 'server',
74
- 'service',
75
- 'services',
76
- 'start',
77
- 'surface',
78
- 'surfaces',
79
- 'tui',
80
- 'web',
81
- 'webhook',
82
- ]);
61
+ const BLOCKED_PRODUCT_COMMAND_HINTS: Readonly<Partial<Record<string, (binary: string) => string>>> = {
62
+ app: (binary) => `Unsupported command: app. Launch the Agent TUI with "${binary}" and no command.`,
63
+ bridge: () => 'Unsupported command: bridge. GoodVibes Agent connects to an externally managed GoodVibes host and does not expose bridge processes.',
64
+ 'control-plane': () => 'Unsupported command: control-plane. GoodVibes Agent can inspect connected-host posture, but it does not manage host endpoints.',
65
+ controlplane: () => 'Unsupported command: controlplane. GoodVibes Agent can inspect connected-host posture, but it does not manage host endpoints.',
66
+ cp: () => 'Unsupported command: cp. GoodVibes Agent can inspect connected-host posture, but it does not manage host endpoints.',
67
+ daemon: () => 'Unsupported command: daemon. GoodVibes Agent connects to an externally managed GoodVibes host and does not start or manage host processes.',
68
+ 'http-listener': () => 'Unsupported command: http-listener. GoodVibes Agent does not start listeners or expose inbound host endpoints.',
69
+ launch: (binary) => `Unsupported command: launch. Launch the Agent TUI with "${binary}" and no command.`,
70
+ listener: () => 'Unsupported command: listener. GoodVibes Agent does not start listeners or expose inbound host endpoints.',
71
+ remote: () => 'Unsupported command: remote. GoodVibes Agent uses explicit connected-host routes and does not manage remote host transport.',
72
+ serve: () => 'Unsupported command: serve. GoodVibes Agent connects to an externally managed GoodVibes host and does not start server processes.',
73
+ server: () => 'Unsupported command: server. GoodVibes Agent connects to an externally managed GoodVibes host and does not start server processes.',
74
+ service: () => 'Unsupported command: service. GoodVibes Agent keeps host lifecycle ownership outside this product.',
75
+ services: () => 'Unsupported command: services. GoodVibes Agent keeps host lifecycle ownership outside this product.',
76
+ start: (binary) => `Unsupported command: start. Launch the Agent TUI with "${binary}" and no command; Agent does not start connected-host processes.`,
77
+ surface: () => 'Unsupported command: surface. GoodVibes Agent does not manage connected-host surfaces.',
78
+ surfaces: () => 'Unsupported command: surfaces. GoodVibes Agent does not manage connected-host surfaces.',
79
+ tui: (binary) => `Unsupported command: tui. Launch the Agent TUI with "${binary}" and no command.`,
80
+ web: () => 'Unsupported command: web. GoodVibes Agent does not start web servers or expose browser routes.',
81
+ webhook: () => 'Unsupported command: webhook. GoodVibes Agent can send explicit channel messages, but it does not create webhook listeners.',
82
+ };
83
+
84
+ export function listGoodVibesCliCommandTokens(): readonly string[] {
85
+ return Object.keys(COMMAND_ALIASES).sort();
86
+ }
87
+
88
+ export function listGoodVibesCliCommands(): readonly GoodVibesCliCommand[] {
89
+ return [...new Set<GoodVibesCliCommand>(['tui', ...Object.values(COMMAND_ALIASES)])].sort();
90
+ }
91
+
92
+ export function listBlockedGoodVibesCliCommandTokens(): readonly string[] {
93
+ return Object.keys(BLOCKED_PRODUCT_COMMAND_HINTS).sort();
94
+ }
83
95
 
84
96
  function createDefaultFlags(): GoodVibesCliFlags {
85
97
  return {
@@ -221,7 +233,7 @@ export function parseGoodVibesCli(
221
233
  if (!token.startsWith('-') || token === '-') {
222
234
  if (!sawCommand) {
223
235
  const commandToken = token.toLowerCase();
224
- if (BLOCKED_PRODUCT_COMMANDS.has(commandToken)) {
236
+ if (BLOCKED_PRODUCT_COMMAND_HINTS[commandToken]) {
225
237
  command = 'unknown';
226
238
  rawCommand = token;
227
239
  sawCommand = true;
@@ -394,7 +406,8 @@ export function parseGoodVibesCli(
394
406
  }
395
407
 
396
408
  if (rawCommand !== undefined && command === 'unknown') {
397
- errors.push(`Unknown command: ${rawCommand}`);
409
+ const blockedHint = BLOCKED_PRODUCT_COMMAND_HINTS[rawCommand.toLowerCase()];
410
+ errors.push(blockedHint ? blockedHint(binary) : `Unknown command ${rawCommand}`);
398
411
  }
399
412
 
400
413
  return {
@@ -16,6 +16,7 @@ import {
16
16
  type AgentRuntimeProfileCommandResult,
17
17
  type AgentRuntimeProfileInfo,
18
18
  } from '../agent/runtime-profile.ts';
19
+ import { formatAgentRecordSource } from '../agent/record-labels.ts';
19
20
  import type { CliCommandOutput, GoodVibesCliParseResult } from './types.ts';
20
21
 
21
22
  interface ProfilesCommandRuntime {
@@ -56,7 +57,7 @@ function parseTemplate(args: readonly string[]): AgentRuntimeProfileTemplateId |
56
57
  if (!raw || raw === 'blank') return undefined;
57
58
  const normalized = raw.trim().toLowerCase().replace(/_/g, '-');
58
59
  if (isAgentRuntimeProfileTemplateId(normalized)) return normalized;
59
- throw new Error(`Unknown Agent starter profile template: ${raw}. Use profiles templates to list starters.`);
60
+ throw new Error(`Unknown Agent starter profile template ${raw}. Use profiles templates to list starters.`);
60
61
  }
61
62
 
62
63
  function parseCsvFlag(args: readonly string[], names: readonly string[]): readonly string[] | undefined {
@@ -66,16 +67,21 @@ function parseCsvFlag(args: readonly string[], names: readonly string[]): readon
66
67
  }
67
68
 
68
69
  function profileLine(profile: AgentRuntimeProfileInfo): string {
69
- const created = profile.createdAt ? ` created=${profile.createdAt}` : '';
70
+ const created = profile.createdAt ? ` created ${profile.createdAt}` : '';
70
71
  const starter = profile.starterTemplateId ? ` starter=${profile.starterTemplateId}` : '';
71
- return ` ${profile.id} home=${profile.homeDirectory}${created}${starter}`;
72
+ return ` ${profile.id} home ${profile.homeDirectory}${created}${starter}`;
72
73
  }
73
74
 
74
75
  function renderProfilesResult(result: AgentRuntimeProfileCommandResult): string {
75
76
  if (!result.ok) return result.error ?? 'Agent profile command failed.';
76
77
  if (result.kind === 'agent.profiles.list') {
77
78
  const profiles = result.data?.profiles ?? [];
78
- if (profiles.length === 0) return 'No Agent profiles. Use: goodvibes-agent profiles create <name> --template <id> --yes';
79
+ if (profiles.length === 0) {
80
+ return [
81
+ 'No Agent profiles',
82
+ ' next goodvibes-agent profiles create <name> --template <id> --yes',
83
+ ].join('\n');
84
+ }
79
85
  return [
80
86
  `Agent profiles (${profiles.length})`,
81
87
  ...profiles.map(profileLine),
@@ -86,63 +92,71 @@ function renderProfilesResult(result: AgentRuntimeProfileCommandResult): string
86
92
  return [
87
93
  `Agent starter profile templates (${templates.length})`,
88
94
  ...templates.map((template) => [
89
- ` ${template.id} ${template.name} [${template.source}]`,
95
+ ` ${template.id} ${template.name} [${formatAgentRecordSource(template.source).toLowerCase()}]`,
90
96
  ` ${template.description}`,
91
- ` persona: ${template.personaName}`,
92
- ` skills: ${template.skillNames.join(', ')}`,
93
- ` routines: ${template.routineNames.join(', ')}`,
97
+ ` persona ${template.personaName}`,
98
+ ` skills ${template.skillNames.join(', ')}`,
99
+ ` routines ${template.routineNames.join(', ')}`,
94
100
  ].join('\n')),
95
- 'Use: goodvibes-agent profiles create <name> --template <id> --yes',
96
- 'Export/edit/import: goodvibes-agent profiles templates export <id> <path> --yes',
101
+ 'Use goodvibes-agent profiles create <name> --template <id> --yes',
102
+ 'Export/edit/import with goodvibes-agent profiles templates export <id> <path> --yes',
97
103
  ].join('\n');
98
104
  }
99
105
  if (result.kind === 'agent.profiles.template.export' && result.data?.template && result.data.path) {
100
106
  return [
101
107
  `Agent starter template exported: ${result.data.template.id}`,
102
- ` path: ${result.data.path}`,
103
- ' edit the JSON, then import it with: goodvibes-agent profiles templates import <path> --yes',
108
+ ` path ${result.data.path}`,
109
+ ' edit the JSON, then import it with goodvibes-agent profiles templates import <path> --yes',
104
110
  ].join('\n');
105
111
  }
106
112
  if (result.kind === 'agent.profiles.template.import' && result.data?.template) {
107
113
  return [
108
114
  `Agent starter template imported: ${result.data.template.id}`,
109
- ` name: ${result.data.template.name}`,
110
- ` source: ${result.data.template.source}`,
111
- ` use: goodvibes-agent profiles create <name> --template ${result.data.template.id} --yes`,
115
+ ` name ${result.data.template.name}`,
116
+ ` origin ${formatAgentRecordSource(result.data.template.source)}`,
117
+ ` use goodvibes-agent profiles create <name> --template ${result.data.template.id} --yes`,
112
118
  ].join('\n');
113
119
  }
114
120
  if (result.kind === 'agent.profiles.template.from_discovered' && result.data?.template) {
115
121
  return [
116
122
  `Agent starter template created from discovered behavior: ${result.data.template.id}`,
117
- ` name: ${result.data.template.name}`,
118
- ` persona: ${result.data.template.personaName}`,
119
- ` skills: ${result.data.template.skillNames.join(', ')}`,
120
- ` routines: ${result.data.template.routineNames.join(', ')}`,
121
- ` use: goodvibes-agent profiles create <name> --template ${result.data.template.id} --yes`,
123
+ ` name ${result.data.template.name}`,
124
+ ` persona ${result.data.template.personaName}`,
125
+ ` skills ${result.data.template.skillNames.join(', ')}`,
126
+ ` routines ${result.data.template.routineNames.join(', ')}`,
127
+ ` use goodvibes-agent profiles create <name> --template ${result.data.template.id} --yes`,
122
128
  ].join('\n');
123
129
  }
124
130
  if (result.kind === 'agent.profiles.default') {
125
131
  const selected = result.data?.selectedProfile;
126
- if (!selected) return 'No default Agent profile selected. Use: goodvibes-agent profiles use <name> --yes';
132
+ if (!selected) {
133
+ return [
134
+ 'No default Agent profile selected',
135
+ ' next goodvibes-agent profiles use <name> --yes',
136
+ ].join('\n');
137
+ }
127
138
  return [
128
139
  `Default Agent profile: ${selected.id}${selected.exists ? '' : ' (missing)'}`,
129
- ` home: ${selected.homeDirectory}`,
130
- selected.selectedAt ? ` selectedAt: ${selected.selectedAt}` : '',
140
+ ` home ${selected.homeDirectory}`,
141
+ selected.selectedAt ? ` selected ${selected.selectedAt}` : '',
131
142
  ` next launch: ${result.data?.nextCommand ?? 'goodvibes-agent'}`,
132
- selected.exists ? '' : ' fix: create the profile again or clear it with goodvibes-agent profiles default clear --yes',
143
+ selected.exists ? '' : ' fix create the profile again or clear it with goodvibes-agent profiles default clear --yes',
133
144
  ].filter(Boolean).join('\n');
134
145
  }
135
146
  if (result.kind === 'agent.profiles.default.clear') {
136
- return 'Default Agent profile cleared. Next launch uses the base Agent home unless --agent-profile is provided.';
147
+ return [
148
+ 'Default Agent profile cleared',
149
+ ' next launch uses the base Agent home unless --agent-profile is provided',
150
+ ].join('\n');
137
151
  }
138
152
  if (result.kind === 'agent.profiles.create_from_discovered' && result.data?.profile && result.data.template) {
139
153
  return [
140
154
  `Agent profile created from discovered behavior: ${result.data.profile.id}`,
141
- ` home: ${result.data.profile.homeDirectory}`,
155
+ ` home ${result.data.profile.homeDirectory}`,
142
156
  ` starter: ${result.data.template.id}`,
143
- ` persona: ${result.data.template.personaName}`,
144
- ` skills: ${result.data.template.skillNames.join(', ')}`,
145
- ` routines: ${result.data.template.routineNames.join(', ')}`,
157
+ ` persona ${result.data.template.personaName}`,
158
+ ` skills ${result.data.template.skillNames.join(', ')}`,
159
+ ` routines ${result.data.template.routineNames.join(', ')}`,
146
160
  ` launch: ${result.data.nextCommand ?? `goodvibes-agent --agent-profile ${result.data.profile.id}`}`,
147
161
  ].join('\n');
148
162
  }
@@ -151,16 +165,19 @@ function renderProfilesResult(result: AgentRuntimeProfileCommandResult): string
151
165
  const template = result.data?.appliedTemplate;
152
166
  return [
153
167
  `Agent profile created: ${profile.id}`,
154
- ` home: ${profile.homeDirectory}`,
168
+ ` home ${profile.homeDirectory}`,
155
169
  ...(template ? [
156
170
  ` starter: ${template.id} (${template.name})`,
157
171
  ` seeded: ${template.personaIds.length} persona, ${template.skillIds.length} skills, ${template.routineIds.length} routine`,
158
172
  ] : []),
159
- ` use: ${result.data?.nextCommand ?? `goodvibes-agent --agent-profile ${profile.id}`}`,
173
+ ` use ${result.data?.nextCommand ?? `goodvibes-agent --agent-profile ${profile.id}`}`,
160
174
  ].join('\n');
161
175
  }
162
176
  if (result.kind === 'agent.profiles.delete' && profile) {
163
- return `Agent profile deleted: ${profile.id}`;
177
+ return [
178
+ `Agent profile deleted: ${profile.id}`,
179
+ ` id ${profile.id}`,
180
+ ].join('\n');
164
181
  }
165
182
  return 'Agent profile command completed.';
166
183
  }
@@ -435,7 +452,7 @@ export async function handleProfilesCommand(runtime: ProfilesCommandRuntime): Pr
435
452
  data: { profile: info },
436
453
  };
437
454
  const starter = info.starterTemplateId ? [` starter: ${info.starterTemplateId} (${info.starterTemplateName ?? info.starterTemplateId})`] : [];
438
- const text = [`Agent profile: ${profile.id}`, ` home: ${profile.homeDirectory}`, ...starter, ` use: goodvibes-agent --agent-profile ${profile.id}`].join('\n');
455
+ const text = [`Agent profile: ${profile.id}`, ` home ${profile.homeDirectory}`, ...starter, ` use goodvibes-agent --agent-profile ${profile.id}`].join('\n');
439
456
  return {
440
457
  output: runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(result, null, 2) : text,
441
458
  exitCode: 0,
@@ -571,8 +588,8 @@ export async function handleProfilesCommand(runtime: ProfilesCommandRuntime): Pr
571
588
  : {
572
589
  ok: false,
573
590
  kind: 'agent.profiles.error',
574
- error: `Agent profile not found: ${resolution.id}`,
575
- };
591
+ error: `Agent profile not found ${resolution.id}`,
592
+ };
576
593
  return {
577
594
  output: renderProfilesOutput(result, runtime.cli.flags.outputFormat),
578
595
  exitCode: deleted ? 0 : 1,
@@ -1,4 +1,5 @@
1
1
  import type { ProviderAuthRouteDescriptor } from '@pellux/goodvibes-sdk/platform/providers';
2
+ import { formatProviderAuthRouteId, formatProviderAuthRouteLabel } from '../provider-auth-route-display.ts';
2
3
 
3
4
  function routeUsable(route: ProviderAuthRouteDescriptor): boolean {
4
5
  return route.usable ?? route.configured;
@@ -18,5 +19,5 @@ export function formatProviderAuthRoute(route: ProviderAuthRouteDescriptor): str
18
19
  route.freshness,
19
20
  ].filter((part): part is string => Boolean(part));
20
21
  const detail = route.detail?.trim();
21
- return `${route.label} [${route.route}; ${status.join(', ')}]${detail ? ` - ${detail}` : ''}`;
22
+ return `${formatProviderAuthRouteLabel(route.route, route.label)} [${formatProviderAuthRouteId(route.route)}; ${status.join(', ')}]${detail ? ` - ${detail}` : ''}`;
22
23
  }