@pellux/goodvibes-agent 1.4.3 → 1.5.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 (227) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +7 -7
  3. package/dist/package/main.js +7450 -12285
  4. package/docs/README.md +2 -2
  5. package/docs/channels-remote-and-api.md +1 -1
  6. package/docs/getting-started.md +2 -2
  7. package/docs/release-and-publishing.md +1 -1
  8. package/docs/tools-and-commands.md +5 -5
  9. package/package.json +4 -2
  10. package/release/performance-snapshot.json +2 -2
  11. package/release/release-notes.md +11 -7
  12. package/release/release-readiness.json +6 -6
  13. package/src/agent/behavior-discovery-summary.ts +4 -18
  14. package/src/agent/calendar-registry.ts +322 -0
  15. package/src/agent/competitive-feature-inventory.ts +268 -130
  16. package/src/agent/document-registry.ts +5 -1
  17. package/src/agent/email/email-service.ts +350 -0
  18. package/src/agent/email/imap-client.ts +596 -0
  19. package/src/agent/email/smtp-client.ts +453 -0
  20. package/src/agent/ics-calendar.ts +662 -0
  21. package/src/agent/ics-timezone.ts +172 -0
  22. package/src/agent/markdown-frontmatter.ts +31 -0
  23. package/src/agent/memory-safety.ts +1 -1
  24. package/src/agent/note-registry.ts +3 -9
  25. package/src/agent/persona-discovery.ts +3 -15
  26. package/src/agent/persona-registry.ts +1 -10
  27. package/src/agent/research-source-registry.ts +5 -1
  28. package/src/agent/routine-discovery.ts +3 -15
  29. package/src/agent/runtime-profile.ts +3 -0
  30. package/src/agent/skill-discovery.ts +3 -15
  31. package/src/agent/skill-draft-proposer.ts +203 -0
  32. package/src/agent/skill-draft-runner.ts +201 -0
  33. package/src/agent/skill-registry.ts +36 -1
  34. package/src/agent/skill-standard.ts +99 -0
  35. package/src/agent/vibe-file.ts +7 -22
  36. package/src/cli/completion.ts +1 -1
  37. package/src/cli/config-overrides.ts +10 -1
  38. package/src/cli/redaction.ts +17 -5
  39. package/src/config/provider-model.ts +2 -1
  40. package/src/config/secret-config.ts +13 -6
  41. package/src/core/activity-feed.ts +97 -0
  42. package/src/core/away-digest.ts +161 -0
  43. package/src/core/conversation-rendering.ts +7 -3
  44. package/src/core/conversation.ts +22 -15
  45. package/src/core/hardware-profile.ts +362 -0
  46. package/src/core/last-seen-store.ts +78 -0
  47. package/src/core/plain-language.ts +52 -0
  48. package/src/core/setup-incomplete-hint.ts +90 -0
  49. package/src/core/system-message-router.ts +38 -87
  50. package/src/input/agent-workspace-basic-command-editor-submission.ts +60 -220
  51. package/src/input/agent-workspace-basic-command-editors.ts +39 -141
  52. package/src/input/agent-workspace-categories.ts +63 -158
  53. package/src/input/agent-workspace-command-editor.ts +4 -0
  54. package/src/input/agent-workspace-host-category.ts +0 -5
  55. package/src/input/agent-workspace-local-editor-submission.ts +3 -1
  56. package/src/input/agent-workspace-navigation.ts +10 -3
  57. package/src/input/agent-workspace-onboarding-actions.ts +132 -0
  58. package/src/input/agent-workspace-onboarding-categories.ts +29 -26
  59. package/src/input/agent-workspace-onboarding-finish.ts +11 -4
  60. package/src/input/agent-workspace-onboarding-state.ts +111 -0
  61. package/src/input/agent-workspace-profile-editor-submission.ts +260 -0
  62. package/src/input/agent-workspace-profile-editors.ts +155 -0
  63. package/src/input/agent-workspace-subscription-editor.ts +7 -0
  64. package/src/input/agent-workspace-types.ts +5 -1
  65. package/src/input/agent-workspace.ts +65 -39
  66. package/src/input/command-registry.ts +18 -5
  67. package/src/input/commands/agent-runtime-profile-runtime.ts +2 -1
  68. package/src/input/commands/agent-skills-runtime.ts +60 -3
  69. package/src/input/commands/calendar-runtime.ts +209 -0
  70. package/src/input/commands/channels-runtime.ts +1 -0
  71. package/src/input/commands/command-error.ts +9 -0
  72. package/src/input/commands/compat-runtime.ts +1 -0
  73. package/src/input/commands/config.ts +1 -0
  74. package/src/input/commands/conversation-runtime.ts +1 -1
  75. package/src/input/commands/delegation-runtime.ts +5 -6
  76. package/src/input/commands/email-runtime.ts +387 -0
  77. package/src/input/commands/experience-runtime.ts +17 -4
  78. package/src/input/commands/guidance-runtime.ts +1 -1
  79. package/src/input/commands/health-runtime.ts +6 -1
  80. package/src/input/commands/knowledge-format.ts +73 -0
  81. package/src/input/commands/knowledge.ts +9 -74
  82. package/src/input/commands/local-provider-runtime.ts +2 -1
  83. package/src/input/commands/local-runtime.ts +10 -4
  84. package/src/input/commands/mcp-runtime.ts +7 -0
  85. package/src/input/commands/notify-runtime.ts +17 -1
  86. package/src/input/commands/onboarding-runtime.ts +1 -0
  87. package/src/input/commands/operator-actions-runtime.ts +1 -0
  88. package/src/input/commands/operator-runtime.ts +3 -0
  89. package/src/input/commands/personas-runtime.ts +1 -0
  90. package/src/input/commands/platform-access-runtime.ts +40 -17
  91. package/src/input/commands/product-runtime.ts +6 -1
  92. package/src/input/commands/provider-accounts-runtime.ts +3 -2
  93. package/src/input/commands/qrcode-runtime.ts +1 -0
  94. package/src/input/commands/routines-runtime.ts +1 -0
  95. package/src/input/commands/runtime-services.ts +0 -13
  96. package/src/input/commands/security-runtime.ts +1 -0
  97. package/src/input/commands/session-content.ts +1 -0
  98. package/src/input/commands/shell-core.ts +5 -2
  99. package/src/input/commands/subscription-runtime.ts +33 -9
  100. package/src/input/commands/support-bundle-runtime.ts +8 -1
  101. package/src/input/commands/tasks-runtime.ts +1 -0
  102. package/src/input/commands/tts-runtime.ts +1 -0
  103. package/src/input/commands/vibe-runtime.ts +1 -0
  104. package/src/input/commands.ts +4 -0
  105. package/src/input/feed-context-factory.ts +3 -12
  106. package/src/input/handler-command-route.ts +7 -60
  107. package/src/input/handler-feed-routes.ts +0 -194
  108. package/src/input/handler-feed.ts +2 -54
  109. package/src/input/handler-interactions.ts +0 -2
  110. package/src/input/handler-modal-stack.ts +0 -9
  111. package/src/input/handler-picker-routes.ts +24 -1
  112. package/src/input/handler-shortcuts.ts +11 -40
  113. package/src/input/handler-ui-state.ts +13 -0
  114. package/src/input/handler.ts +8 -35
  115. package/src/input/keybindings.ts +40 -17
  116. package/src/input/model-picker-local-fit.ts +130 -0
  117. package/src/input/submission-router.ts +0 -5
  118. package/src/main.ts +111 -89
  119. package/src/renderer/activity-sidebar.ts +186 -0
  120. package/src/renderer/agent-workspace-context-lines.ts +5 -48
  121. package/src/renderer/agent-workspace-style.ts +1 -1
  122. package/src/renderer/agent-workspace.ts +14 -2
  123. package/src/renderer/compositor.ts +37 -125
  124. package/src/renderer/conversation-overlays.ts +3 -3
  125. package/src/renderer/help-overlay.ts +7 -5
  126. package/src/renderer/model-workspace.ts +101 -86
  127. package/src/{panels → renderer}/polish.ts +3 -3
  128. package/src/renderer/shell-surface.ts +4 -5
  129. package/src/renderer/status-token.ts +31 -11
  130. package/src/renderer/tab-strip.ts +1 -1
  131. package/src/renderer/tool-call.ts +7 -8
  132. package/src/renderer/tool-labels.ts +92 -0
  133. package/src/renderer/ui-factory.ts +48 -96
  134. package/src/runtime/bootstrap-command-context.ts +0 -5
  135. package/src/runtime/bootstrap-command-parts.ts +6 -15
  136. package/src/runtime/bootstrap-core.ts +34 -13
  137. package/src/runtime/bootstrap-hook-bridge.ts +3 -1
  138. package/src/runtime/bootstrap-shell.ts +3 -50
  139. package/src/runtime/bootstrap.ts +3 -4
  140. package/src/runtime/context.ts +1 -1
  141. package/src/runtime/diagnostics/panels/index.ts +0 -1
  142. package/src/runtime/diagnostics/panels/policy.ts +1 -1
  143. package/src/runtime/execution-ledger.ts +16 -1
  144. package/src/runtime/index.ts +6 -1
  145. package/src/runtime/onboarding/index.ts +1 -0
  146. package/src/runtime/onboarding/onboarding-state.ts +200 -0
  147. package/src/{panels → runtime}/provider-account-snapshot.ts +5 -2
  148. package/src/runtime/services.ts +16 -4
  149. package/src/runtime/terminal-output-guard.ts +7 -0
  150. package/src/runtime/tool-permission-safety.ts +1 -1
  151. package/src/runtime/ui/model-picker/data-provider.ts +1 -1
  152. package/src/runtime/ui/model-picker/health-enrichment.ts +2 -2
  153. package/src/runtime/ui/model-picker/types.ts +2 -2
  154. package/src/runtime/ui/provider-health/data-provider.ts +3 -3
  155. package/src/runtime/ui/provider-health/types.ts +2 -2
  156. package/src/runtime/ui-services.ts +0 -2
  157. package/src/shell/agent-workspace-fullscreen.ts +0 -1
  158. package/src/shell/autonomy-surfacing.ts +272 -0
  159. package/src/shell/session-continuity-hints.ts +0 -6
  160. package/src/shell/startup-wiring.ts +221 -0
  161. package/src/shell/ui-openers.ts +18 -29
  162. package/src/tools/agent-context-policy.ts +1 -1
  163. package/src/tools/agent-harness-background-processes.ts +4 -4
  164. package/src/tools/agent-harness-browser-cockpit-route.ts +3 -3
  165. package/src/tools/agent-harness-command-runner.ts +6 -1
  166. package/src/tools/agent-harness-document-ops.ts +26 -53
  167. package/src/tools/agent-harness-execution-history.ts +1 -13
  168. package/src/tools/agent-harness-execution-posture.ts +0 -15
  169. package/src/tools/agent-harness-keybinding-metadata.ts +28 -29
  170. package/src/tools/agent-harness-local-model-cookbook.ts +24 -1
  171. package/src/tools/agent-harness-metadata.ts +16 -0
  172. package/src/tools/agent-harness-mode-catalog.ts +2 -9
  173. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  174. package/src/tools/agent-harness-setup-posture-utils.ts +1 -1
  175. package/src/tools/agent-harness-tool-schema.ts +13 -14
  176. package/src/tools/agent-harness-tool.ts +27 -23
  177. package/src/tools/agent-harness-ui-surface-metadata.ts +10 -20
  178. package/src/tools/agent-harness-workspace-action-runner.ts +3 -4
  179. package/src/tools/agent-workspace-tool.ts +2 -33
  180. package/src/utils/terminal-width.ts +9 -3
  181. package/src/version.ts +1 -1
  182. package/src/input/agent-workspace-panel-route.ts +0 -44
  183. package/src/input/panel-integration-actions.ts +0 -26
  184. package/src/panels/approval-panel.ts +0 -149
  185. package/src/panels/automation-control-panel.ts +0 -212
  186. package/src/panels/base-panel.ts +0 -254
  187. package/src/panels/builtin/agent.ts +0 -58
  188. package/src/panels/builtin/knowledge.ts +0 -26
  189. package/src/panels/builtin/operations.ts +0 -121
  190. package/src/panels/builtin/session.ts +0 -138
  191. package/src/panels/builtin/shared.ts +0 -275
  192. package/src/panels/builtin/usage.ts +0 -21
  193. package/src/panels/builtin-panels.ts +0 -23
  194. package/src/panels/confirm-state.ts +0 -61
  195. package/src/panels/context-visualizer-panel.ts +0 -204
  196. package/src/panels/cost-tracker-panel.ts +0 -444
  197. package/src/panels/docs-panel.ts +0 -285
  198. package/src/panels/index.ts +0 -25
  199. package/src/panels/knowledge-panel.ts +0 -417
  200. package/src/panels/memory-panel.ts +0 -226
  201. package/src/panels/panel-list-panel.ts +0 -464
  202. package/src/panels/panel-manager.ts +0 -570
  203. package/src/panels/provider-accounts-panel.ts +0 -233
  204. package/src/panels/provider-health-domains.ts +0 -208
  205. package/src/panels/provider-health-panel.ts +0 -720
  206. package/src/panels/provider-health-tracker.ts +0 -115
  207. package/src/panels/provider-stats-panel.ts +0 -366
  208. package/src/panels/qr-panel.ts +0 -207
  209. package/src/panels/schedule-panel.ts +0 -321
  210. package/src/panels/scrollable-list-panel.ts +0 -491
  211. package/src/panels/search-focus.ts +0 -32
  212. package/src/panels/security-panel.ts +0 -295
  213. package/src/panels/session-browser-panel.ts +0 -395
  214. package/src/panels/session-maintenance.ts +0 -125
  215. package/src/panels/subscription-panel.ts +0 -263
  216. package/src/panels/system-messages-panel.ts +0 -230
  217. package/src/panels/tasks-panel.ts +0 -344
  218. package/src/panels/thinking-panel.ts +0 -304
  219. package/src/panels/token-budget-panel.ts +0 -475
  220. package/src/panels/tool-inspector-panel.ts +0 -436
  221. package/src/panels/types.ts +0 -54
  222. package/src/renderer/panel-composite.ts +0 -158
  223. package/src/renderer/panel-tab-bar.ts +0 -69
  224. package/src/renderer/panel-workspace-bar.ts +0 -42
  225. package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
  226. package/src/tools/agent-harness-panel-metadata.ts +0 -211
  227. /package/src/runtime/perf/{panel-health-monitor.ts → component-health.ts} +0 -0
@@ -1,5 +1,5 @@
1
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { dirname, resolve } from 'node:path';
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
3
  import type { CommandRegistry } from '../command-registry.ts';
4
4
  import { requireShellPaths } from './runtime-services.ts';
5
5
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
@@ -26,6 +26,7 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
26
26
  name: 'approval',
27
27
  aliases: ['approvals'],
28
28
  description: 'Review action-specific approval classes and the specialized security UX matrix',
29
+ hidden: true,
29
30
  usage: '[matrix|review <kind>|approve <id> --yes|deny <id> --yes|cancel <id> --yes]',
30
31
  async handler(args, ctx) {
31
32
  const sub = (args[0] ?? 'matrix').toLowerCase();
@@ -74,6 +75,7 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
74
75
  description: 'Review voice posture and package portable voice interaction metadata',
75
76
  usage: '[review|enable --yes|disable --yes|bundle export <path> --yes|bundle inspect <path>]',
76
77
  handler(args, ctx) {
78
+ try {
77
79
  const parsed = stripYesFlag(args);
78
80
  const commandArgs = [...parsed.rest];
79
81
  const shellPaths = requireShellPaths(ctx);
@@ -126,12 +128,23 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
126
128
  return;
127
129
  }
128
130
  if (mode === 'inspect') {
129
- const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as VoiceBundle;
130
- ctx.print(inspectVoiceBundle(bundle));
131
+ if (!existsSync(targetPath)) {
132
+ ctx.print(`File not found: ${targetPath}`);
133
+ return;
134
+ }
135
+ try {
136
+ const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as VoiceBundle;
137
+ ctx.print(inspectVoiceBundle(bundle));
138
+ } catch {
139
+ ctx.print('could not read voice bundle');
140
+ }
131
141
  return;
132
142
  }
133
143
  }
134
144
  ctx.print('Usage: /voice [review|enable --yes|disable --yes|bundle export <path> --yes|bundle inspect <path>]');
145
+ } catch (error) {
146
+ ctx.print(`voice command failed: ${error instanceof Error ? error.message : String(error)}`);
147
+ }
135
148
  },
136
149
  });
137
150
  }
@@ -25,7 +25,7 @@ export function registerGuidanceRuntimeCommands(registry: CommandRegistry): void
25
25
  ' /knowledge - inspect isolated Agent Knowledge status, ask/search, libraries, map, connectors, and ingest paths',
26
26
  ' /memory - manage Agent-local memory',
27
27
  ' /personas - manage Agent-local personas',
28
- ' /skills - manage reusable Agent-local skills',
28
+ ' /skills - manage reusable Agent-local skills',
29
29
  ' /routines - manage Agent-local routines',
30
30
  ' /delegate - explicitly hand build/fix/review work to GoodVibes TUI',
31
31
  ].join('\n'));
@@ -3,7 +3,7 @@ import { evaluateSessionMaintenance, formatSessionMaintenanceLines } from '@/run
3
3
  import { estimateConversationTokens } from '@pellux/goodvibes-sdk/platform/core';
4
4
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
5
5
  import { buildSetupReviewSnapshot } from './local-setup-review.ts';
6
- import { buildProviderAccountSnapshot } from '../../panels/provider-account-snapshot.ts';
6
+ import { buildProviderAccountSnapshot } from '../../runtime/provider-account-snapshot.ts';
7
7
  import { getSettingsControlPlaneSnapshot } from '@/runtime/index.ts';
8
8
  import { checkRecoveryFile, readLastSessionPointer } from '@/runtime/index.ts';
9
9
  import {
@@ -48,9 +48,11 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
48
48
  name: 'health',
49
49
  aliases: ['doctor'],
50
50
  description: 'Health workspace for startup posture, connected host readiness, provider health, and Agent continuity',
51
+ hidden: true,
51
52
  usage: '[review|setup|host|provider|accounts|auth|settings|remote|mcp|continuity|maintenance|repair [domain]]',
52
53
  async handler(args, ctx) {
53
54
  const sub = (args[0] ?? 'review').toLowerCase();
55
+ try {
54
56
 
55
57
  if (sub === 'open' || sub === 'panel') {
56
58
  ctx.print('Open Agent Workspace -> Home -> Review health for the workspace view, or run /health review for the compact command output.');
@@ -371,6 +373,9 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
371
373
  ' /health repair <domain>',
372
374
  ' /setup',
373
375
  ].join('\n'));
376
+ } catch (error) {
377
+ ctx.print(`Health command failed: ${error instanceof Error ? error.message : String(error)}`);
378
+ }
374
379
  },
375
380
  });
376
381
  }
@@ -0,0 +1,73 @@
1
+ import type { KnowledgeMapResult, KnowledgeService } from '@pellux/goodvibes-sdk/platform/knowledge';
2
+
3
+ export type KnowledgeAskResult = Awaited<ReturnType<KnowledgeService['ask']>>;
4
+
5
+ export function cleanInline(value: unknown): string {
6
+ return typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '';
7
+ }
8
+
9
+ export function formatKnowledgeMap(result: KnowledgeMapResult): string {
10
+ return [
11
+ 'Agent Knowledge map',
12
+ ` nodes: ${result.nodeCount}${result.totalNodeCount !== undefined && result.totalNodeCount !== result.nodeCount ? ` of ${result.totalNodeCount}` : ''}`,
13
+ ` edges: ${result.edgeCount}${result.totalEdgeCount !== undefined && result.totalEdgeCount !== result.edgeCount ? ` of ${result.totalEdgeCount}` : ''}`,
14
+ ' route /api/goodvibes-agent/knowledge/map',
15
+ ].join('\n');
16
+ }
17
+
18
+ export function nodeLabel(node: { readonly kind?: string; readonly title?: string; readonly summary?: string; readonly confidence?: number }): string {
19
+ const kind = cleanInline(node.kind) || 'node';
20
+ const title = cleanInline(node.title) || 'untitled';
21
+ const summary = cleanInline(node.summary);
22
+ const confidence = typeof node.confidence === 'number' ? ` confidence ${node.confidence}` : '';
23
+ return summary ? `[${kind}] ${title}${confidence} - ${summary}` : `[${kind}] ${title}${confidence}`;
24
+ }
25
+
26
+ export function sourceLabel(source: {
27
+ readonly id?: string;
28
+ readonly sourceType?: string;
29
+ readonly title?: string;
30
+ readonly canonicalUri?: string;
31
+ readonly sourceUri?: string;
32
+ readonly summary?: string;
33
+ readonly status?: string;
34
+ }): string {
35
+ const title = cleanInline(source.title) || cleanInline(source.canonicalUri) || cleanInline(source.sourceUri) || cleanInline(source.id) || 'untitled';
36
+ const type = cleanInline(source.sourceType) || 'source';
37
+ const status = cleanInline(source.status);
38
+ const summary = cleanInline(source.summary);
39
+ const suffix = status ? `/${status}` : '';
40
+ return summary ? `[${type}${suffix}] ${title} - ${summary}` : `[${type}${suffix}] ${title}`;
41
+ }
42
+
43
+ export function renderKnowledgeAskResult(result: KnowledgeAskResult): string {
44
+ const answer = result.answer;
45
+ const lines = [
46
+ `[knowledge] ${result.query}`,
47
+ answer.text,
48
+ '',
49
+ `mode ${answer.mode} confidence ${answer.confidence} synthesized ${answer.synthesized ? 'yes' : 'no'}`,
50
+ ];
51
+
52
+ if (answer.sources.length > 0) {
53
+ lines.push('', 'Sources:');
54
+ for (const source of answer.sources) lines.push(` - ${sourceLabel(source)}`);
55
+ }
56
+
57
+ if (answer.facts.length > 0) {
58
+ lines.push('', 'Facts:');
59
+ for (const fact of answer.facts) lines.push(` - ${nodeLabel(fact)}`);
60
+ }
61
+
62
+ if (answer.linkedObjects.length > 0) {
63
+ lines.push('', 'Linked objects:');
64
+ for (const object of answer.linkedObjects) lines.push(` - ${nodeLabel(object)}`);
65
+ }
66
+
67
+ if (answer.gaps.length > 0) {
68
+ lines.push('', 'Gaps:');
69
+ for (const gap of answer.gaps) lines.push(` - ${nodeLabel(gap)}`);
70
+ }
71
+
72
+ return lines.join('\n');
73
+ }
@@ -1,13 +1,13 @@
1
- import type { KnowledgeMapResult, KnowledgeService } from '@pellux/goodvibes-sdk/platform/knowledge';
2
1
  import type { CommandContext, SlashCommand } from '../command-registry.ts';
3
2
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
4
3
  import { toBrowserKinds, toBrowserSourceKinds } from './knowledge-browser-flags.ts';
4
+ import { formatKnowledgeMap, nodeLabel, renderKnowledgeAskResult, sourceLabel } from './knowledge-format.ts';
5
+ import type { KnowledgeAskResult } from './knowledge-format.ts';
5
6
 
6
7
  const KNOWLEDGE_REVIEW_ACTIONS = ['accept', 'reject', 'resolve', 'reopen', 'edit', 'forget'] as const;
7
8
 
8
9
  type KnowledgeReviewAction = typeof KNOWLEDGE_REVIEW_ACTIONS[number];
9
- type KnowledgeAskInput = Parameters<KnowledgeService['ask']>[0];
10
- type KnowledgeAskResult = Awaited<ReturnType<KnowledgeService['ask']>>;
10
+ type KnowledgeAskInput = Parameters<import('@pellux/goodvibes-sdk/platform/knowledge').KnowledgeService['ask']>[0];
11
11
  type KnowledgeAskMode = NonNullable<KnowledgeAskInput['mode']>;
12
12
 
13
13
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -126,82 +126,13 @@ function requireAgentKnowledgeAsk(context: CommandContext): ((input: KnowledgeAs
126
126
  return null;
127
127
  }
128
128
 
129
- function cleanInline(value: unknown): string {
130
- return typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '';
131
- }
132
-
133
- function formatKnowledgeMap(result: KnowledgeMapResult): string {
134
- return [
135
- 'Agent Knowledge map',
136
- ` nodes: ${result.nodeCount}${result.totalNodeCount !== undefined && result.totalNodeCount !== result.nodeCount ? ` of ${result.totalNodeCount}` : ''}`,
137
- ` edges: ${result.edgeCount}${result.totalEdgeCount !== undefined && result.totalEdgeCount !== result.edgeCount ? ` of ${result.totalEdgeCount}` : ''}`,
138
- ' route /api/goodvibes-agent/knowledge/map',
139
- ].join('\n');
140
- }
141
-
142
- function nodeLabel(node: { readonly kind?: string; readonly title?: string; readonly summary?: string; readonly confidence?: number }): string {
143
- const kind = cleanInline(node.kind) || 'node';
144
- const title = cleanInline(node.title) || 'untitled';
145
- const summary = cleanInline(node.summary);
146
- const confidence = typeof node.confidence === 'number' ? ` confidence ${node.confidence}` : '';
147
- return summary ? `[${kind}] ${title}${confidence} - ${summary}` : `[${kind}] ${title}${confidence}`;
148
- }
149
-
150
- function sourceLabel(source: {
151
- readonly id?: string;
152
- readonly sourceType?: string;
153
- readonly title?: string;
154
- readonly canonicalUri?: string;
155
- readonly sourceUri?: string;
156
- readonly summary?: string;
157
- readonly status?: string;
158
- }): string {
159
- const title = cleanInline(source.title) || cleanInline(source.canonicalUri) || cleanInline(source.sourceUri) || cleanInline(source.id) || 'untitled';
160
- const type = cleanInline(source.sourceType) || 'source';
161
- const status = cleanInline(source.status);
162
- const summary = cleanInline(source.summary);
163
- const suffix = status ? `/${status}` : '';
164
- return summary ? `[${type}${suffix}] ${title} - ${summary}` : `[${type}${suffix}] ${title}`;
165
- }
166
-
167
- function renderKnowledgeAskResult(result: KnowledgeAskResult): string {
168
- const answer = result.answer;
169
- const lines = [
170
- `[knowledge] ${result.query}`,
171
- answer.text,
172
- '',
173
- `mode ${answer.mode} confidence ${answer.confidence} synthesized ${answer.synthesized ? 'yes' : 'no'}`,
174
- ];
175
-
176
- if (answer.sources.length > 0) {
177
- lines.push('', 'Sources:');
178
- for (const source of answer.sources) lines.push(` - ${sourceLabel(source)}`);
179
- }
180
-
181
- if (answer.facts.length > 0) {
182
- lines.push('', 'Facts:');
183
- for (const fact of answer.facts) lines.push(` - ${nodeLabel(fact)}`);
184
- }
185
-
186
- if (answer.linkedObjects.length > 0) {
187
- lines.push('', 'Linked objects:');
188
- for (const object of answer.linkedObjects) lines.push(` - ${nodeLabel(object)}`);
189
- }
190
-
191
- if (answer.gaps.length > 0) {
192
- lines.push('', 'Gaps:');
193
- for (const gap of answer.gaps) lines.push(` - ${nodeLabel(gap)}`);
194
- }
195
-
196
- return lines.join('\n');
197
- }
198
-
199
129
  export const knowledgeCommand: SlashCommand = {
200
130
  name: 'knowledge',
201
131
  aliases: ['know', 'kb'],
202
132
  description: 'Agent Knowledge: isolated Agent-owned status, ask/search, source/node/issue lists, item lookup, map, connectors, ingest, and review queue.',
133
+ hidden: true,
203
134
  usage: '<subcommand> [args]',
204
- argsHint: 'status|ask|search|list|get|map|connectors|connector|connector-doctor|ingest-url --yes|ingest-file --yes|ingest-artifact --yes|import-urls --yes|import-bookmarks --yes|import-browser-history --yes|ingest-connector --yes|review-issue --yes|reindex --yes',
135
+ argsHint: 'status|ask|search|list|get|map|connectors|ingest-url --yes|ingest-file --yes|ingest-artifact --yes|import-urls --yes|import-bookmarks --yes|import-browser-history --yes|ingest-connector --yes|review-issue --yes|reindex --yes',
205
136
  handler: async (args: string[], context: CommandContext): Promise<void> => {
206
137
  if (args.length === 0 && context.openAgentWorkspace) {
207
138
  context.openAgentWorkspace('knowledge');
@@ -220,6 +151,7 @@ export const knowledgeCommand: SlashCommand = {
220
151
  return;
221
152
  }
222
153
 
154
+ try {
223
155
  switch (sub) {
224
156
  case 'ask': {
225
157
  const ask = requireAgentKnowledgeAsk(context);
@@ -792,5 +724,8 @@ export const knowledgeCommand: SlashCommand = {
792
724
  ' consolidate [light|deep] --yes',
793
725
  ].join('\n'));
794
726
  }
727
+ } catch (error) {
728
+ context.print(`[knowledge] ${error instanceof Error ? error.message : String(error)}`);
729
+ }
795
730
  },
796
731
  };
@@ -26,6 +26,7 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
26
26
  name: 'provider',
27
27
  aliases: ['p'],
28
28
  description: 'Switch provider or manage custom providers (add/remove)',
29
+ hidden: true,
29
30
  usage: '[add <name> <baseURL> [apiKey] --yes | remove <name> --yes | <provider-name>]',
30
31
  argsHint: '[name|add --yes|remove --yes]',
31
32
  async handler(args, ctx) {
@@ -171,6 +172,7 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
171
172
  const providerName = commandArgs[0];
172
173
  const requestedModel = commandArgs[1];
173
174
  const providerApi = requireProviderApi(ctx);
175
+ try {
174
176
  const selectable = await providerApi.listModels({
175
177
  providerId: providerName,
176
178
  selectableOnly: true,
@@ -183,7 +185,6 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
183
185
  ].join('\n'));
184
186
  return;
185
187
  }
186
- try {
187
188
  const registryKey = requestedModel
188
189
  ? requestedModel.includes(':') ? requestedModel : `${providerName}:${requestedModel}`
189
190
  : match.registryKey;
@@ -1,4 +1,4 @@
1
- import { dirname, resolve } from 'path';
1
+ import { dirname } from 'path';
2
2
  import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import type { CommandRegistry, CommandContext } from '../command-registry.ts';
@@ -108,13 +108,14 @@ function parseMediaGenerateArgs(args: readonly string[]): MediaGenerateArgs {
108
108
  }
109
109
 
110
110
  export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
111
- registry.register({ name: 'expand', description: 'Expand blocks by type', usage: '[all|thinking|tool|code]', argsHint: '[all|thinking|tool|code]', handler(args, ctx) { toggleBlocks(args[0] || 'all', false, ctx); } });
112
- registry.register({ name: 'collapse', description: 'Collapse blocks by type', usage: '[all|thinking|tool|code]', argsHint: '[all|thinking|tool|code]', handler(args, ctx) { toggleBlocks(args[0] || 'all', true, ctx); } });
111
+ registry.register({ name: 'expand', description: 'Expand blocks by type', hidden: true, usage: '[all|thinking|tool|code]', argsHint: '[all|thinking|tool|code]', handler(args, ctx) { toggleBlocks(args[0] || 'all', false, ctx); } });
112
+ registry.register({ name: 'collapse', description: 'Collapse blocks by type', hidden: true, usage: '[all|thinking|tool|code]', argsHint: '[all|thinking|tool|code]', handler(args, ctx) { toggleBlocks(args[0] || 'all', true, ctx); } });
113
113
 
114
114
  registry.register({
115
115
  name: 'bookmarks',
116
116
  aliases: ['bm'],
117
117
  description: 'List bookmarked blocks',
118
+ hidden: true,
118
119
  handler(_args, ctx) {
119
120
  if (ctx.openBookmarkModal) {
120
121
  ctx.openBookmarkModal();
@@ -145,6 +146,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
145
146
  registry.register({
146
147
  name: 'secrets',
147
148
  description: 'Manage hierarchy-aware secrets, external secret refs, and secure/plaintext storage policy controls',
149
+ hidden: true,
148
150
  usage: 'set <KEY> <value> [--user|--project] [--secure|--plaintext] --yes | link <KEY> <secret-ref> [--user|--project] [--secure|--plaintext] --yes | get <KEY> | test <secret-ref> | providers | list | delete <KEY> [--user|--project] [--secure|--plaintext] --yes',
149
151
  argsHint: '<set|link|get|test|providers|list|delete> [KEY]',
150
152
  async handler(args, ctx) {
@@ -326,6 +328,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
326
328
  registry.register({
327
329
  name: 'media',
328
330
  description: 'Inspect media providers or generate media through configured providers',
331
+ hidden: true,
329
332
  usage: 'providers | generate [--provider <id>] [--model <id>] [--mime <mime>] <prompt> --yes',
330
333
  argsHint: '<providers|generate>',
331
334
  async handler(args, ctx) {
@@ -373,6 +376,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
373
376
  registry.register({
374
377
  name: 'refresh-models',
375
378
  description: 'Refresh model catalog, benchmarks, and token limits',
379
+ hidden: true,
376
380
  async handler(_args, ctx) {
377
381
  const providerApi = requireProviderApi(ctx);
378
382
  let catalogOk = false;
@@ -411,6 +415,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
411
415
  registry.register({
412
416
  name: 'pin',
413
417
  description: 'Pin a model to the favorites list',
418
+ hidden: true,
414
419
  usage: '<model-id>',
415
420
  argsHint: '<model-id>',
416
421
  async handler(args, ctx) {
@@ -445,6 +450,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
445
450
  registry.register({
446
451
  name: 'unpin',
447
452
  description: 'Unpin a model from the favorites list',
453
+ hidden: true,
448
454
  usage: '<model-id>',
449
455
  argsHint: '<model-id>',
450
456
  async handler(args, ctx) {
@@ -455,7 +461,7 @@ export function registerLocalRuntimeCommands(registry: CommandRegistry): void {
455
461
  return;
456
462
  }
457
463
  const favorites = await providerApi.getFavorites();
458
- const pinned = favorites.pinned.find((entry) => entry.registryKey === modelId);
464
+ const pinned = favorites.pinned.find((entry) => entry.registryKey === modelId || entry.modelId === modelId);
459
465
  if (!pinned) {
460
466
  ctx.print(`Model is not pinned: ${modelId}`);
461
467
  return;
@@ -192,6 +192,7 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
192
192
  name: 'mcp',
193
193
  aliases: [],
194
194
  description: 'Manage MCP servers and their tools',
195
+ hidden: true,
195
196
  usage: '[servers|review|tools [<server>]|config|add|remove|reload|auth-review|repair [server]]',
196
197
  argsHint: '[servers|review|tools|config|add --yes|remove --yes]',
197
198
  async handler(args, ctx) {
@@ -339,6 +340,9 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
339
340
  if (serverName || requestedMode) {
340
341
  ctx.print(`Usage: ${MCP_TRUST_COMMAND_USAGE}\nUse /settings -> MCP to explicitly enable allow-all.`);
341
342
  return;
343
+ } else {
344
+ ctx.print(`Usage: ${MCP_TRUST_COMMAND_USAGE}\nUse /settings -> MCP to explicitly enable allow-all.`);
345
+ return;
342
346
  }
343
347
  }
344
348
 
@@ -362,6 +366,9 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
362
366
  if (serverName || requestedRole) {
363
367
  ctx.print(`Usage: ${MCP_ROLE_COMMAND_USAGE}`);
364
368
  return;
369
+ } else {
370
+ ctx.print(`Usage: ${MCP_ROLE_COMMAND_USAGE}`);
371
+ return;
365
372
  }
366
373
  }
367
374
 
@@ -18,8 +18,24 @@ export function registerNotifyRuntimeCommands(registry: CommandRegistry): void {
18
18
  const sub = commandArgs[0];
19
19
 
20
20
  if (!sub || sub === 'list') {
21
+ const showFull = commandArgs.includes('--show') && parsed.yes;
21
22
  if (urls.length === 0) ctx.print('No webhook URLs configured.\nUse /notify add <url>');
22
- else ctx.print(`Webhook URLs (${urls.length})\n${urls.map((u, i) => ` ${i + 1}. ${u}`).join('\n')}`);
23
+ else {
24
+ const display = urls.map((u, i) => {
25
+ if (showFull) return ` ${i + 1}. ${u}`;
26
+ try {
27
+ const parsedUrl = new URL(u);
28
+ const origin = parsedUrl.origin;
29
+ const truncPath = parsedUrl.pathname.length > 12
30
+ ? `${parsedUrl.pathname.slice(0, 12)}…`
31
+ : parsedUrl.pathname;
32
+ return ` ${i + 1}. ${origin}${truncPath} (use /notify list --show --yes to reveal full URL)`;
33
+ } catch {
34
+ return ` ${i + 1}. (invalid URL)`;
35
+ }
36
+ });
37
+ ctx.print(`Webhook URLs (${urls.length})\n${display.join('\n')}`);
38
+ }
23
39
  return;
24
40
  }
25
41
 
@@ -5,6 +5,7 @@ export function registerOnboardingRuntimeCommands(registry: CommandRegistry): vo
5
5
  name: 'setup',
6
6
  aliases: ['onboarding'],
7
7
  description: 'Open the Agent workspace',
8
+ hidden: true,
8
9
  usage: '',
9
10
  async handler(_args, ctx) {
10
11
  if (ctx.executeCommand && await ctx.executeCommand('agent', [])) return;
@@ -123,6 +123,7 @@ export function registerOperatorActionRuntimeCommands(registry: CommandRegistry)
123
123
  name: 'automation',
124
124
  aliases: ['auto'],
125
125
  description: 'Run confirmed connected-host automation actions from the Agent TUI',
126
+ hidden: true,
126
127
  usage: 'job <run|pause|resume> <job-id> --yes | run <cancel|retry> <run-id> --yes | schedule <run|enable|disable|delete> <schedule-id> --yes',
127
128
  argsHint: 'job run <id> --yes | run cancel <id> --yes | schedule disable <id> --yes',
128
129
  async handler(args, ctx) {
@@ -154,6 +154,7 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
154
154
  name: 'context',
155
155
  aliases: ['ctx'],
156
156
  description: 'Inspect context window usage (token breakdown per message)',
157
+ hidden: true,
157
158
  handler: (_args, ctx) => {
158
159
  if (ctx.openContextInspector) {
159
160
  ctx.openContextInspector();
@@ -187,6 +188,7 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
187
188
  name: 'next-error',
188
189
  aliases: ['ne'],
189
190
  description: 'Jump to the next error message in the conversation',
191
+ hidden: true,
190
192
  handler(_args, ctx) {
191
193
  const nextLine = ctx.session.conversationManager.nextErrorLine(ctx.getScrollTop?.() ?? 0);
192
194
  if (nextLine < 0) ctx.print('[No error messages found in conversation]');
@@ -197,6 +199,7 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
197
199
  name: 'prev-error',
198
200
  aliases: ['pe'],
199
201
  description: 'Jump to the previous error message in the conversation',
202
+ hidden: true,
200
203
  handler(_args, ctx) {
201
204
  const prevLine = ctx.session.conversationManager.prevErrorLine(ctx.getScrollTop?.() ?? 0);
202
205
  if (prevLine < 0) ctx.print('[No error messages found in conversation]');
@@ -164,6 +164,7 @@ export function registerPersonasRuntimeCommands(registry: CommandRegistry): void
164
164
  name: 'personas',
165
165
  aliases: ['persona'],
166
166
  description: 'Manage Agent-local personas',
167
+ hidden: true,
167
168
  usage: '[list|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --body <instructions>|update <id> [--name ...] [--description ...] [--body ...]|use <id>|active|clear|review <id>|stale <id> <reason...>|delete <id> --yes]',
168
169
  async handler(args, ctx) {
169
170
  const sub = (args[0] ?? 'list').toLowerCase();
@@ -31,6 +31,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
31
31
  registry.register({
32
32
  name: 'auth',
33
33
  description: 'Review provider auth posture and export redacted auth review bundles',
34
+ hidden: true,
34
35
  usage: '[review|show <provider>|repair <provider>|bundle export <path> --yes|bundle inspect <path>]',
35
36
  async handler(args, ctx) {
36
37
  const parsed = stripYesFlag(args);
@@ -59,11 +60,17 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
59
60
  const serviceRegistry = requireServiceRegistry(ctx);
60
61
  const secretsManager = requireSecretsManager(ctx);
61
62
  if (sub === 'review') {
62
- const snapshot = await buildAuthInspectionSnapshot({
63
- serviceRegistry,
64
- subscriptionManager: subscriptions,
65
- secretsManager,
66
- });
63
+ let snapshot;
64
+ try {
65
+ snapshot = await buildAuthInspectionSnapshot({
66
+ serviceRegistry,
67
+ subscriptionManager: subscriptions,
68
+ secretsManager,
69
+ });
70
+ } catch (error) {
71
+ ctx.print(`Could not build auth review: ${error instanceof Error ? error.message : String(error)}`);
72
+ return;
73
+ }
67
74
  const builtinProviders = listBuiltinSubscriptionProviders().map((entry) => entry.provider);
68
75
  ctx.print([
69
76
  'Auth Review',
@@ -83,11 +90,17 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
83
90
  ctx.print('Usage: /auth show <provider>');
84
91
  return;
85
92
  }
86
- const inspection = await inspectProviderAuth(provider, {
87
- serviceRegistry,
88
- subscriptionManager: subscriptions,
89
- secretsManager,
90
- });
93
+ let inspection;
94
+ try {
95
+ inspection = await inspectProviderAuth(provider, {
96
+ serviceRegistry,
97
+ subscriptionManager: subscriptions,
98
+ secretsManager,
99
+ });
100
+ } catch (error) {
101
+ ctx.print(`Could not inspect auth for ${provider}: ${error instanceof Error ? error.message : String(error)}`);
102
+ return;
103
+ }
91
104
  ctx.print([
92
105
  `Auth Provider ${provider}`,
93
106
  ` configured ${inspection.configured ? 'yes' : 'no'}`,
@@ -112,11 +125,17 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
112
125
  ctx.print('Usage: /auth repair <provider>');
113
126
  return;
114
127
  }
115
- const inspection = await inspectProviderAuth(provider, {
116
- serviceRegistry,
117
- subscriptionManager: subscriptions,
118
- secretsManager,
119
- });
128
+ let inspection;
129
+ try {
130
+ inspection = await inspectProviderAuth(provider, {
131
+ serviceRegistry,
132
+ subscriptionManager: subscriptions,
133
+ secretsManager,
134
+ });
135
+ } catch (error) {
136
+ ctx.print(`Could not inspect auth for repair of ${provider}: ${error instanceof Error ? error.message : String(error)}`);
137
+ return;
138
+ }
120
139
  ctx.print([
121
140
  `Auth Repair ${provider}`,
122
141
  ` configured ${inspection.configured ? 'yes' : 'no'}`,
@@ -158,8 +177,12 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
158
177
  return;
159
178
  }
160
179
  if (mode === 'inspect') {
161
- const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as AuthReviewBundle;
162
- ctx.print(inspectAuthBundle(bundle));
180
+ try {
181
+ const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as AuthReviewBundle;
182
+ ctx.print(inspectAuthBundle(bundle));
183
+ } catch (error) {
184
+ ctx.print(`Could not read that bundle file: ${error instanceof Error ? error.message : String(error)}`);
185
+ }
163
186
  return;
164
187
  }
165
188
  }
@@ -91,6 +91,7 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
91
91
  registry.register({
92
92
  name: 'trust',
93
93
  description: 'Review trust posture and export portable trust bundles',
94
+ hidden: true,
94
95
  usage: '[review|bundle export <path> --yes|bundle inspect <path>]',
95
96
  async handler(args, ctx) {
96
97
  const parsed = stripYesFlag(args);
@@ -122,7 +123,11 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
122
123
  return;
123
124
  }
124
125
  if (mode === 'inspect') {
125
- ctx.print(inspectTrustBundle(shellPaths.resolveWorkspacePath(pathArg!)));
126
+ try {
127
+ ctx.print(inspectTrustBundle(shellPaths.resolveWorkspacePath(pathArg!)));
128
+ } catch (error) {
129
+ ctx.print(`Could not read that bundle file: ${error instanceof Error ? error.message : String(error)}`);
130
+ }
126
131
  return;
127
132
  }
128
133
  }
@@ -4,8 +4,8 @@ import type {
4
4
  ProviderAccountSnapshot,
5
5
  ProviderAuthRoute,
6
6
  ProviderRouteRecord,
7
- } from '../../panels/provider-account-snapshot.ts';
8
- import { buildProviderAccountSnapshot } from '../../panels/provider-account-snapshot.ts';
7
+ } from '../../runtime/provider-account-snapshot.ts';
8
+ import { buildProviderAccountSnapshot } from '../../runtime/provider-account-snapshot.ts';
9
9
  import {
10
10
  requireProvider,
11
11
  requireServiceRegistry,
@@ -45,6 +45,7 @@ export function registerProviderAccountsRuntimeCommands(registry: CommandRegistr
45
45
  name: 'accounts',
46
46
  aliases: ['account'],
47
47
  description: 'Review provider auth routes, subscription windows, and billing-path safety',
48
+ hidden: true,
48
49
  usage: '[review|show <provider>|routes <provider>|repair <provider>]',
49
50
  async handler(args, ctx) {
50
51
  const sub = (args[0] ?? 'review').toLowerCase();
@@ -65,6 +65,7 @@ export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
65
65
  name: 'qrcode',
66
66
  aliases: ['qr', 'pair'],
67
67
  description: 'Print companion pairing details and a QR code',
68
+ hidden: true,
68
69
  usage: '',
69
70
  handler(args, ctx) {
70
71
  const shellPaths = requireShellPaths(ctx);
@@ -413,6 +413,7 @@ export function registerRoutinesRuntimeCommands(registry: CommandRegistry): void
413
413
  name: 'routines',
414
414
  aliases: ['routine'],
415
415
  description: 'Manage Agent-local routines',
416
+ hidden: true,
416
417
  usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]',
417
418
  handler: runRoutinesRuntimeCommand,
418
419
  });