@pellux/goodvibes-agent 1.4.4 → 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 +14 -0
  2. package/README.md +7 -7
  3. package/dist/package/main.js +7424 -12241
  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 +40 -125
  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
@@ -6,15 +6,15 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
6
6
  id: 'onboarding-channels',
7
7
  group: 'ONBOARDING',
8
8
  label: 'Messaging',
9
- summary: 'Choose remote channels, then fill only the fields for enabled channels.',
10
- detail: 'Enable the channels you actually want. Channel credentials and default targets are saved as Agent settings or secret refs.',
9
+ summary: 'Connect messaging channels, then check, test, and send from one page.',
10
+ detail: 'Connect a chat app so the assistant can message you and you can reply from your phone. Enable the channels you want, then fill in the credentials for each one.',
11
11
  actions: [
12
- settingAction({ id: 'channel-ntfy-enabled', label: 'Use ntfy', detail: 'Toggle ntfy notifications and chat routing.', key: 'surfaces.ntfy.enabled' }),
12
+ settingAction({ id: 'channel-ntfy-enabled', label: 'Use ntfy', detail: 'Turn on ntfy to get push notifications and send replies from your phone or browser. Fill in the server URL and topics below once enabled.', key: 'surfaces.ntfy.enabled' }),
13
13
  settingAction({ id: 'channel-ntfy-base-url', label: 'ntfy base URL', detail: 'Set the ntfy server URL.', key: 'surfaces.ntfy.baseUrl', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
14
14
  settingAction({ id: 'channel-ntfy-chat-topic', label: 'ntfy chat topic', detail: 'Set the topic routed into active terminal chat.', key: 'surfaces.ntfy.chatTopic', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
15
15
  settingAction({ id: 'channel-ntfy-agent-topic', label: 'ntfy agent topic', detail: 'Set the topic routed to Agent work.', key: 'surfaces.ntfy.agentTopic', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
16
16
  settingAction({ id: 'channel-ntfy-default-topic', label: 'ntfy default topic', detail: 'Set the default outbound notification topic.', key: 'surfaces.ntfy.topic', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
17
- settingAction({ id: 'channel-ntfy-remote-topic', label: 'ntfy remote topic', detail: 'Set the daemon-owned remote chat topic.', key: 'surfaces.ntfy.remoteTopic', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
17
+ settingAction({ id: 'channel-ntfy-remote-topic', label: 'ntfy remote topic', detail: 'Set the assistant service remote chat topic.', key: 'surfaces.ntfy.remoteTopic', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
18
18
  settingAction({ id: 'channel-ntfy-token', label: 'ntfy token', detail: 'Store the ntfy access token or secret reference.', key: 'surfaces.ntfy.token', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
19
19
  settingAction({ id: 'channel-ntfy-priority', label: 'ntfy priority', detail: 'Set default ntfy priority from 1 to 5.', key: 'surfaces.ntfy.defaultPriority', visibleWhenKey: 'surfaces.ntfy.enabled', visibleWhenValue: true }),
20
20
  settingAction({ id: 'channel-slack-enabled', label: 'Use Slack', detail: 'Toggle Slack adapter configuration.', key: 'surfaces.slack.enabled' }),
@@ -51,7 +51,7 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
51
51
  settingAction({ id: 'channel-homeassistant-conversation', label: 'Home automation conversation', detail: 'Set the default conversation id.', key: 'surfaces.homeassistant.defaultConversationId', visibleWhenKey: 'surfaces.homeassistant.enabled', visibleWhenValue: true }),
52
52
  settingAction({ id: 'channel-homeassistant-device-id', label: 'Home automation device ID', detail: 'Set the stable device id exposed to the home automation surface.', key: 'surfaces.homeassistant.deviceId', visibleWhenKey: 'surfaces.homeassistant.enabled', visibleWhenValue: true }),
53
53
  settingAction({ id: 'channel-homeassistant-device-name', label: 'Home automation device name', detail: 'Set the device display name exposed to the home automation surface.', key: 'surfaces.homeassistant.deviceName', visibleWhenKey: 'surfaces.homeassistant.enabled', visibleWhenValue: true }),
54
- settingAction({ id: 'channel-homeassistant-event-type', label: 'Home automation event type', detail: 'Set the event type used for daemon-to-home automation delivery.', key: 'surfaces.homeassistant.eventType', visibleWhenKey: 'surfaces.homeassistant.enabled', visibleWhenValue: true }),
54
+ settingAction({ id: 'channel-homeassistant-event-type', label: 'Home automation event type', detail: 'Set the event type used for home automation delivery.', key: 'surfaces.homeassistant.eventType', visibleWhenKey: 'surfaces.homeassistant.enabled', visibleWhenValue: true }),
55
55
  settingAction({ id: 'channel-homeassistant-session-ttl', label: 'Home automation session TTL', detail: 'Set the idle TTL for remote home automation conversation sessions.', key: 'surfaces.homeassistant.remoteSessionTtlMs', visibleWhenKey: 'surfaces.homeassistant.enabled', visibleWhenValue: true }),
56
56
  settingAction({ id: 'channel-signal-enabled', label: 'Use Signal', detail: 'Toggle Signal bridge delivery.', key: 'surfaces.signal.enabled' }),
57
57
  settingAction({ id: 'channel-signal-bridge', label: 'Signal bridge URL', detail: 'Set the Signal bridge base URL.', key: 'surfaces.signal.bridgeUrl', visibleWhenKey: 'surfaces.signal.enabled', visibleWhenValue: true }),
@@ -71,16 +71,26 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
71
71
  settingAction({ id: 'channel-imessage-account', label: 'iMessage account', detail: 'Set the iMessage account id.', key: 'surfaces.imessage.account', visibleWhenKey: 'surfaces.imessage.enabled', visibleWhenValue: true }),
72
72
  settingAction({ id: 'channel-imessage-token', label: 'iMessage token', detail: 'Store the iMessage bridge token or secret reference.', key: 'surfaces.imessage.token', visibleWhenKey: 'surfaces.imessage.enabled', visibleWhenValue: true }),
73
73
  settingAction({ id: 'channel-imessage-chat', label: 'iMessage chat ID', detail: 'Set the default iMessage chat id.', key: 'surfaces.imessage.defaultChatId', visibleWhenKey: 'surfaces.imessage.enabled', visibleWhenValue: true }),
74
+ { id: 'channel-show', label: 'Check a channel', detail: 'Open a read-only readiness check for one channel.', editorKind: 'channel-show', kind: 'editor', safety: 'read-only' },
75
+ { id: 'channel-doctor', label: 'Diagnose a channel', detail: 'Run read-only delivery diagnostics for one channel.', editorKind: 'channel-doctor', kind: 'editor', safety: 'read-only' },
76
+ { id: 'channel-setup', label: 'Channel setup guide', detail: 'Open step-by-step setup guidance for one channel.', editorKind: 'channel-setup', kind: 'editor', safety: 'read-only' },
77
+ { id: 'channel-send', label: 'Send a message', detail: 'Send one message through a configured channel after confirmation.', editorKind: 'channel-send', kind: 'editor', safety: 'safe' },
78
+ { id: 'notification-send', label: 'Send a notification', detail: 'Send one plain-text notification to your configured targets after confirmation.', editorKind: 'notify-send', kind: 'editor', safety: 'safe' },
79
+ { id: 'notification-add-webhook', label: 'Add notification target', detail: 'Add one webhook target for reminder and routine delivery.', editorKind: 'notify-webhook', kind: 'editor', safety: 'safe' },
80
+ { id: 'notification-remove-webhook', label: 'Remove notification target', detail: 'Remove one webhook notification target after confirmation.', editorKind: 'notify-webhook-remove', kind: 'editor', safety: 'safe' },
81
+ { id: 'notification-clear-webhooks', label: 'Clear notification targets', detail: 'Remove every configured webhook notification target after confirmation.', editorKind: 'notify-webhook-clear', kind: 'editor', safety: 'safe' },
82
+ { id: 'notification-test-webhooks', label: 'Test notification targets', detail: 'Send one test notification to configured targets after typed confirmation.', editorKind: 'notify-webhook-test', kind: 'editor', safety: 'safe' },
83
+ { id: 'channel-safety', label: 'Delivery safety', detail: 'Messages only go out when you explicitly send them. Nothing is delivered silently from this page.', kind: 'guidance', safety: 'blocked' },
74
84
  ],
75
85
  },
76
86
  {
77
87
  id: 'onboarding-voice-media',
78
88
  group: 'ONBOARDING',
79
- label: 'Voice & Phone',
80
- summary: 'Configure voice controls, spoken output, and SMS or phone-call delivery.',
81
- detail: 'Use this page for saved voice/TTS settings and telephony credentials. Generating media is available later from Voice & Media.',
89
+ label: 'Voice & Media',
90
+ summary: 'Voice controls, spoken output, media generation, and phone delivery.',
91
+ detail: 'Let the assistant speak to you, listen for your voice, describe images, or send SMS. Voice, TTS, image input, media generation, and telephony live on this one page. Side effects stay explicit.',
82
92
  actions: [
83
- settingAction({ id: 'voice-enabled', label: 'Use voice controls', detail: 'Toggle the optional local voice control surface.', key: 'ui.voiceEnabled' }),
93
+ settingAction({ id: 'voice-enabled', label: 'Use voice controls', detail: 'Turn on the local voice control surface so the assistant can listen and respond out loud. Requires a microphone and configured TTS provider.', key: 'ui.voiceEnabled' }),
84
94
  settingAction({ id: 'voice-tts-provider', label: 'TTS provider', detail: 'Set the default text-to-speech provider id.', key: 'tts.provider' }),
85
95
  settingAction({ id: 'voice-tts-voice', label: 'TTS voice', detail: 'Set the default text-to-speech voice id.', key: 'tts.voice' }),
86
96
  settingAction({ id: 'telephony-enabled', label: 'Use telephony', detail: 'Toggle SMS, voice call, or telephony bridge delivery.', key: 'surfaces.telephony.enabled' }),
@@ -94,6 +104,15 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
94
104
  settingAction({ id: 'telephony-recipient', label: 'Recipient phone number', detail: 'Set the default telephony recipient number.', key: 'surfaces.telephony.defaultRecipient', visibleWhenKey: 'surfaces.telephony.enabled', visibleWhenValue: true }),
95
105
  settingAction({ id: 'telephony-webhook-secret', label: 'Telephony webhook secret', detail: 'Store the shared telephony webhook secret or secret reference.', key: 'surfaces.telephony.webhookSecret', visibleWhenKey: 'surfaces.telephony.enabled', visibleWhenValue: true }),
96
106
  settingAction({ id: 'telephony-voice-language', label: 'Voice language', detail: 'Set the BCP-47 language code for voice-call text-to-speech.', key: 'surfaces.telephony.voiceLanguage', visibleWhenKey: 'surfaces.telephony.enabled', visibleWhenValue: true }),
107
+ { id: 'voice-enable', label: 'Enable voice', detail: 'Open a confirmed form that enables local voice interaction.', editorKind: 'voice-enable', kind: 'editor', safety: 'safe' },
108
+ { id: 'voice-disable', label: 'Disable voice', detail: 'Open a confirmed form that disables local voice interaction.', editorKind: 'voice-disable', kind: 'editor', safety: 'safe' },
109
+ { id: 'tts-speak', label: 'Speak a prompt', detail: 'Open a prompt form for spoken assistant replies through configured live TTS.', editorKind: 'tts-prompt', kind: 'editor', safety: 'safe' },
110
+ { id: 'image-attach', label: 'Attach image input', detail: 'Open an image form for attaching a real image path and optional prompt.', editorKind: 'image-input', kind: 'editor', safety: 'safe' },
111
+ { id: 'media-generate', label: 'Generate media', detail: 'Open a confirmed prompt form that generates image or video artifacts through configured media providers.', editorKind: 'media-generate', kind: 'editor', safety: 'safe' },
112
+ { id: 'voice-workflow-posture', label: 'Voice readiness', detail: 'Check push-to-talk, voice memo transcription, spoken responses, and wake-word readiness.', kind: 'guidance', safety: 'read-only' },
113
+ { id: 'device-capability-map', label: 'Device capability map', detail: 'Check pairing, mobile command routing, browser, notification, and camera/location readiness for this device.', kind: 'guidance', safety: 'read-only' },
114
+ { id: 'voice-bundle-export', label: 'Export voice bundle', detail: 'Open a confirmed form that exports voice setup state for review.', editorKind: 'voice-bundle-export', kind: 'editor', safety: 'safe' },
115
+ { id: 'voice-bundle-inspect', label: 'Inspect voice bundle', detail: 'Open a form that inspects voice setup state before review.', editorKind: 'voice-bundle-inspect', kind: 'editor', safety: 'read-only' },
97
116
  ],
98
117
  },
99
118
  {
@@ -101,7 +120,7 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
101
120
  group: 'ONBOARDING',
102
121
  label: 'Local Context',
103
122
  summary: 'Create/import memory, personas, skills, routines, notes, and Knowledge.',
104
- detail: 'Use this page to seed the assistant with durable local context. These forms create Agent-owned records or ingest reviewed sources.',
123
+ detail: 'Give the assistant a memory of who you are and what you care about. Create personas, starter memories, skills, and routines, or import context files you already have. These records are stored locally and used on every turn.',
105
124
  actions: [
106
125
  { id: 'context-vibe-status', label: 'Inspect VIBE.md', detail: 'Show project/global VIBE.md personality files, blocked files, and init paths before relying on a custom assistant feel.', kind: 'guidance', safety: 'read-only' },
107
126
  { id: 'context-project-files', label: 'Inspect project context', detail: 'List secret-scanned .hermes.md, HERMES.md, AGENTS.md, CLAUDE.md, SOUL.md, and Cursor context files with blocked/truncated status.', kind: 'guidance', safety: 'read-only' },
@@ -122,20 +141,4 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
122
141
  { id: 'context-knowledge-browser-history', label: 'Import browser history', detail: 'Import local browser history or bookmarks into isolated Agent Knowledge.', editorKind: 'knowledge-browser-history', kind: 'editor', safety: 'safe' },
123
142
  ],
124
143
  },
125
- {
126
- id: 'onboarding-automation',
127
- group: 'ONBOARDING',
128
- label: 'Automation Setup',
129
- summary: 'Set scheduled work limits for reminders and routines.',
130
- detail: 'Use this page to enable automation and set bounded run limits. Creating actual reminders and routines remains a separate confirmed action.',
131
- actions: [
132
- settingAction({ id: 'automation-enabled', label: 'Use automation', detail: 'Toggle the automation subsystem for reminders and scheduled routines.', key: 'automation.enabled' }),
133
- settingAction({ id: 'automation-max-concurrent', label: 'Concurrent runs', detail: 'Set the maximum automation runs that can execute concurrently.', key: 'automation.maxConcurrentRuns', visibleWhenKey: 'automation.enabled', visibleWhenValue: true }),
134
- settingAction({ id: 'automation-history-limit', label: 'Run history limit', detail: 'Set the number of run history entries retained per automation job.', key: 'automation.runHistoryLimit', visibleWhenKey: 'automation.enabled', visibleWhenValue: true }),
135
- settingAction({ id: 'automation-default-timeout', label: 'Default timeout', detail: 'Set the default automation run timeout in milliseconds.', key: 'automation.defaultTimeoutMs', visibleWhenKey: 'automation.enabled', visibleWhenValue: true }),
136
- settingAction({ id: 'automation-catch-up', label: 'Catch-up window', detail: 'Set how long startup should catch up missed automation runs.', key: 'automation.catchUpWindowMinutes', visibleWhenKey: 'automation.enabled', visibleWhenValue: true }),
137
- settingAction({ id: 'automation-failure-cooldown', label: 'Failure cooldown', detail: 'Set the cooldown after a failed automation run.', key: 'automation.failureCooldownMs', visibleWhenKey: 'automation.enabled', visibleWhenValue: true }),
138
- settingAction({ id: 'automation-delete-after-run', label: 'Delete one-shot jobs', detail: 'Toggle deleting one-shot automation jobs after their first successful run.', key: 'automation.deleteAfterRun', visibleWhenKey: 'automation.enabled', visibleWhenValue: true }),
139
- ],
140
- },
141
144
  ];
@@ -1,5 +1,8 @@
1
1
  import type { AgentWorkspaceAction, AgentWorkspaceCategory } from './agent-workspace-types.ts';
2
2
 
3
+ // These are WIZARD-STEP ids (AgentSetupWizardStep.id), NOT normalized plan ids.
4
+ // Do NOT cross-check these against SetupPlanItem ids or PLAN_ITEM_CATEGORY_MAP keys.
5
+ // (Compare: agent-workspace-onboarding-state.ts normalises 'provider-model' → 'provider-access' for plan-layer lookups.)
3
6
  export const ONBOARDING_CRITICAL_STEP_IDS = ['runtime', 'connected-host-auth', 'provider-model'] as const;
4
7
 
5
8
  export const ONBOARDING_COMPLETE_SYNTHETIC_ACTION: AgentWorkspaceAction = {
@@ -13,9 +16,13 @@ export const ONBOARDING_COMPLETE_SYNTHETIC_ACTION: AgentWorkspaceAction = {
13
16
  export function shouldShowOnboardingFinishFooter(
14
17
  category: AgentWorkspaceCategory,
15
18
  baseActions: readonly AgentWorkspaceAction[],
19
+ readyToChat?: boolean,
16
20
  ): boolean {
17
- return (
18
- category.group === 'ONBOARDING'
19
- && baseActions.every((a) => a.kind !== 'onboarding-complete')
20
- );
21
+ if (category.group !== 'ONBOARDING') return false;
22
+ if (baseActions.some((a) => a.kind === 'onboarding-complete')) return false;
23
+ // When readyToChat is explicitly false (we have a valid OnboardingState and the user
24
+ // cannot chat yet), withhold the footer so completion is not premature.
25
+ // When readyToChat is undefined (no OnboardingState available), default to showing.
26
+ if (readyToChat === false) return false;
27
+ return true;
21
28
  }
@@ -0,0 +1,111 @@
1
+ import type { AgentSetupWizardStep } from '../agent/setup-wizard.ts';
2
+ import type { SetupPlanItem } from '../tools/agent-harness-setup-posture-types.ts';
3
+ import type { AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
4
+ import type { OnboardingShellPaths } from '../runtime/onboarding/types.ts';
5
+ import {
6
+ deriveOnboardingState,
7
+ readOnboardingCheckMarker,
8
+ readOnboardingCompletionMarker,
9
+ type OnboardingState,
10
+ } from '../runtime/onboarding/index.ts';
11
+
12
+ /**
13
+ * Adapts an AgentSetupWizardStep to a SetupPlanItem for use with
14
+ * deriveOnboardingState. The wizard uses different IDs for some steps;
15
+ * this adapter normalises the two known divergences:
16
+ * - 'provider-model' (wizard) → 'provider-access' (plan) so readyToChat
17
+ * and PLAN_ITEM_CATEGORY_MAP both resolve correctly.
18
+ * The output ids are PLAN ids (SetupPlanItem.id), not wizard-step ids.
19
+ * Do NOT compare the output ids against ONBOARDING_CRITICAL_STEP_IDS which
20
+ * operates on wizard-step ids (see agent-workspace-onboarding-finish.ts).
21
+ * blocksAutonomy is inferred from sourceStatus: blocked or check items block autonomy.
22
+ * Intentional approximation: AgentSetupWizardStep does not carry the authoritative
23
+ * SetupPlanItem.blocksAutonomy field; the wizard snapshot only exposes sourceStatus,
24
+ * so we derive it from status here rather than threading the real value through.
25
+ */
26
+ function wizardItemToSetupPlanItem(step: AgentSetupWizardStep): SetupPlanItem {
27
+ const id = step.id === 'provider-model' ? 'provider-access' : step.id;
28
+ return {
29
+ id,
30
+ label: step.label,
31
+ status: step.sourceStatus,
32
+ priority: 0,
33
+ // Intentional approximation: AgentSetupWizardStep doesn't carry blocksAutonomy;
34
+ // derive it from sourceStatus since the real value isn't available at this layer.
35
+ blocksAutonomy: step.sourceStatus === 'blocked' || step.sourceStatus === 'check',
36
+ reason: step.detail,
37
+ nextAction: step.userRoute,
38
+ userRoute: step.userRoute,
39
+ modelRoute: step.modelRoute,
40
+ };
41
+ }
42
+
43
+ export interface OnboardingEntryResult {
44
+ /** Category ID to navigate to on entry (undefined = leave as-is). */
45
+ readonly categoryId: string | undefined;
46
+ /** Status message to display. */
47
+ readonly status: string;
48
+ }
49
+
50
+ /**
51
+ * Derives the entry navigation and status message from an OnboardingState.
52
+ * Called by open() in ONBOARDING mode.
53
+ */
54
+ export function deriveOnboardingEntry(obs: OnboardingState): OnboardingEntryResult {
55
+ if (obs.phase === 'in-progress' && obs.currentStepId) {
56
+ const step = obs.steps.find((s) => s.id === obs.currentStepId);
57
+ if (step) return { categoryId: step.categoryId, status: `Picking up where you left off: ${step.label}.` };
58
+ }
59
+ const currentStep = obs.steps.find((s) => s.id === obs.currentStepId);
60
+ const nextHint = currentStep ? ` — ${currentStep.nextLabel}` : '';
61
+ return { categoryId: undefined, status: `${obs.progressLabel}${nextHint}.` };
62
+ }
63
+
64
+ /**
65
+ * Given an OnboardingState, computes the set of ONBOARDING category IDs that are
66
+ * currently unlocked and adds them to the provided mutable revealed set.
67
+ * 'setup' is always present; other categories unlock once their step is ready.
68
+ */
69
+ export function updateRevealedOnboardingCategories(
70
+ obs: OnboardingState,
71
+ revealed: Set<string>,
72
+ ): void {
73
+ revealed.add('setup');
74
+ for (const step of obs.steps) {
75
+ if (step.status === 'ready') revealed.add(step.categoryId);
76
+ }
77
+ if (obs.readyToChat) revealed.add('account-model');
78
+ // Also reveal the active resume target so that navigating to it on re-entry
79
+ // actually works. The resume target is by definition non-ready (it is the
80
+ // first blocker), so it would otherwise be filtered out above. Only adds —
81
+ // preserves monotonicity of the revealed set.
82
+ if (obs.phase === 'in-progress' && obs.currentStepId) {
83
+ const cur = obs.steps.find((s) => s.id === obs.currentStepId);
84
+ if (cur) revealed.add(cur.categoryId);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Derives the current OnboardingState from a runtime snapshot and shell paths.
90
+ * Returns null when no snapshot is available (e.g. context is not fully initialised).
91
+ * Reads check and completion markers from shellPaths when provided.
92
+ */
93
+ export function computeOnboardingStateFromSnapshot(
94
+ snapshot: AgentWorkspaceRuntimeSnapshot | null,
95
+ shellPaths: OnboardingShellPaths | undefined,
96
+ ): OnboardingState | null {
97
+ const wizard = snapshot?.setupWizard;
98
+ if (!wizard?.steps?.length) return null;
99
+
100
+ const plan: SetupPlanItem[] = wizard.steps.map(wizardItemToSetupPlanItem);
101
+
102
+ // Build minimal marker states — default to non-existent when shellPaths is unavailable.
103
+ const checkMarker = shellPaths
104
+ ? readOnboardingCheckMarker(shellPaths, 'user')
105
+ : { scope: 'user' as const, path: '', exists: false, payload: null };
106
+ const completionMarker = shellPaths
107
+ ? readOnboardingCompletionMarker(shellPaths, 'user')
108
+ : { scope: 'user' as const, path: '', exists: false, payload: null };
109
+
110
+ return deriveOnboardingState({ plan, checkMarker, completionMarker });
111
+ }
@@ -0,0 +1,260 @@
1
+ import type { AgentWorkspaceActionResult, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+ import { quoteSlashCommandArg } from './slash-command-parser.ts';
3
+ import type { AgentWorkspaceProfileEditorKind } from './agent-workspace-profile-editors.ts';
4
+
5
+ type AgentWorkspaceFieldReader = (fieldId: string) => string;
6
+
7
+ type AgentWorkspaceProfileEditorSubmissionResult =
8
+ | {
9
+ readonly kind: 'editor';
10
+ readonly editor: AgentWorkspaceLocalEditor;
11
+ readonly status: string;
12
+ readonly actionResult?: AgentWorkspaceActionResult;
13
+ }
14
+ | {
15
+ readonly kind: 'dispatch';
16
+ readonly command: string;
17
+ readonly status: string;
18
+ readonly actionResult: AgentWorkspaceActionResult;
19
+ };
20
+
21
+ function isAffirmative(value: string): boolean {
22
+ return /^(y|yes|true)$/i.test(value.trim());
23
+ }
24
+
25
+ export function isAgentWorkspaceProfileEditorSubmissionKind(kind: string): kind is AgentWorkspaceProfileEditorKind {
26
+ return kind === 'profile-template-export'
27
+ || kind === 'profile-template-import'
28
+ || kind === 'profile-template-show'
29
+ || kind === 'profile-show'
30
+ || kind === 'profile-template-from-discovered'
31
+ || kind === 'profile-from-discovered'
32
+ || kind === 'profile-default'
33
+ || kind === 'profile-default-clear'
34
+ || kind === 'profile-delete';
35
+ }
36
+
37
+ export function buildAgentWorkspaceProfileEditorSubmission(
38
+ editor: AgentWorkspaceLocalEditor,
39
+ readField: AgentWorkspaceFieldReader,
40
+ ): AgentWorkspaceProfileEditorSubmissionResult {
41
+ if (editor.kind === 'profile-template-export') {
42
+ if (!isAffirmative(readField('confirm'))) {
43
+ return {
44
+ kind: 'editor',
45
+ editor: { ...editor, message: 'Starter template export not confirmed. Type yes, then press Enter.' },
46
+ status: 'Agent starter template export not confirmed.',
47
+ };
48
+ }
49
+ const command = `/agent-profile template export ${quoteSlashCommandArg(readField('templateId'))} ${quoteSlashCommandArg(readField('path'))} --yes`;
50
+ return {
51
+ kind: 'dispatch',
52
+ command,
53
+ status: 'Opening Agent starter template export.',
54
+ actionResult: {
55
+ kind: 'dispatched',
56
+ title: 'Opening Agent starter template export',
57
+ detail: 'The workspace handed a confirmed starter template export command to the shell-owned command router.',
58
+ command,
59
+ safety: 'safe',
60
+ },
61
+ };
62
+ }
63
+ if (editor.kind === 'profile-template-import') {
64
+ if (!isAffirmative(readField('confirm'))) {
65
+ return {
66
+ kind: 'editor',
67
+ editor: { ...editor, message: 'Starter template import not confirmed. Type yes, then press Enter.' },
68
+ status: 'Agent starter template import not confirmed.',
69
+ };
70
+ }
71
+ const command = `/agent-profile template import ${quoteSlashCommandArg(readField('path'))} --yes`;
72
+ return {
73
+ kind: 'dispatch',
74
+ command,
75
+ status: 'Opening Agent starter template import.',
76
+ actionResult: {
77
+ kind: 'dispatched',
78
+ title: 'Opening Agent starter template import',
79
+ detail: 'The workspace handed a confirmed starter template import command to the shell-owned command router.',
80
+ command,
81
+ safety: 'safe',
82
+ },
83
+ };
84
+ }
85
+ if (editor.kind === 'profile-template-show') {
86
+ const command = `/agent-profile template show ${quoteSlashCommandArg(readField('id'))}`;
87
+ return {
88
+ kind: 'dispatch',
89
+ command,
90
+ status: 'Opening Agent starter template preview.',
91
+ actionResult: {
92
+ kind: 'dispatched',
93
+ title: 'Opening Agent starter template preview',
94
+ detail: 'The workspace handed a read-only starter template preview command to the shell-owned command router.',
95
+ command,
96
+ safety: 'read-only',
97
+ },
98
+ };
99
+ }
100
+ if (editor.kind === 'profile-show') {
101
+ const command = `/agent-profile show ${quoteSlashCommandArg(readField('profile'))}`;
102
+ return {
103
+ kind: 'dispatch',
104
+ command,
105
+ status: 'Opening Agent profile detail.',
106
+ actionResult: {
107
+ kind: 'dispatched',
108
+ title: 'Opening Agent profile detail',
109
+ detail: 'The workspace handed a read-only Agent profile inspection command to the shell-owned command router.',
110
+ command,
111
+ safety: 'read-only',
112
+ },
113
+ };
114
+ }
115
+ if (editor.kind === 'profile-template-from-discovered') {
116
+ if (!isAffirmative(readField('confirm'))) {
117
+ return {
118
+ kind: 'editor',
119
+ editor: { ...editor, message: 'Starter-from-discovered creation not confirmed. Type yes, then press Enter.' },
120
+ status: 'Agent starter-from-discovered creation not confirmed.',
121
+ };
122
+ }
123
+ const parts = [
124
+ '/agent-profile',
125
+ 'template',
126
+ 'from-discovered',
127
+ quoteSlashCommandArg(readField('id')),
128
+ ];
129
+ const name = readField('name');
130
+ const description = readField('description');
131
+ const persona = readField('persona');
132
+ const skills = readField('skills');
133
+ const routines = readField('routines');
134
+ if (name.length > 0) parts.push('--name', quoteSlashCommandArg(name));
135
+ if (description.length > 0) parts.push('--description', quoteSlashCommandArg(description));
136
+ if (persona.length > 0) parts.push('--persona', quoteSlashCommandArg(persona));
137
+ if (skills.length > 0) parts.push('--skills', quoteSlashCommandArg(skills));
138
+ if (routines.length > 0) parts.push('--routines', quoteSlashCommandArg(routines));
139
+ if (isAffirmative(readField('replace'))) parts.push('--replace');
140
+ parts.push('--yes');
141
+ const command = parts.join(' ');
142
+ return {
143
+ kind: 'dispatch',
144
+ command,
145
+ status: 'Opening Agent starter-from-discovered creation.',
146
+ actionResult: {
147
+ kind: 'dispatched',
148
+ title: 'Opening Agent starter-from-discovered creation',
149
+ detail: 'The workspace handed a confirmed starter creation command to the shell-owned command router.',
150
+ command,
151
+ safety: 'safe',
152
+ },
153
+ };
154
+ }
155
+ if (editor.kind === 'profile-from-discovered') {
156
+ if (!isAffirmative(readField('confirm'))) {
157
+ return {
158
+ kind: 'editor',
159
+ editor: { ...editor, message: 'Profile-from-discovered creation not confirmed. Type yes, then press Enter.' },
160
+ status: 'Agent profile-from-discovered creation not confirmed.',
161
+ };
162
+ }
163
+ const parts = [
164
+ '/agent-profile',
165
+ 'create-from-discovered',
166
+ quoteSlashCommandArg(readField('profile')),
167
+ ];
168
+ const templateId = readField('templateId');
169
+ const name = readField('name');
170
+ const description = readField('description');
171
+ const persona = readField('persona');
172
+ const skills = readField('skills');
173
+ const routines = readField('routines');
174
+ if (templateId.length > 0) parts.push('--template-id', quoteSlashCommandArg(templateId));
175
+ if (name.length > 0) parts.push('--name', quoteSlashCommandArg(name));
176
+ if (description.length > 0) parts.push('--description', quoteSlashCommandArg(description));
177
+ if (persona.length > 0) parts.push('--persona', quoteSlashCommandArg(persona));
178
+ if (skills.length > 0) parts.push('--skills', quoteSlashCommandArg(skills));
179
+ if (routines.length > 0) parts.push('--routines', quoteSlashCommandArg(routines));
180
+ if (isAffirmative(readField('replace'))) parts.push('--replace');
181
+ parts.push('--yes');
182
+ const command = parts.join(' ');
183
+ return {
184
+ kind: 'dispatch',
185
+ command,
186
+ status: 'Opening Agent profile-from-discovered creation.',
187
+ actionResult: {
188
+ kind: 'dispatched',
189
+ title: 'Opening Agent profile-from-discovered creation',
190
+ detail: 'The workspace handed a confirmed discovered-behavior profile creation command to the shell-owned command router.',
191
+ command,
192
+ safety: 'safe',
193
+ },
194
+ };
195
+ }
196
+ if (editor.kind === 'profile-default') {
197
+ if (!isAffirmative(readField('confirm'))) {
198
+ return {
199
+ kind: 'editor',
200
+ editor: { ...editor, message: 'Default Agent profile selection not confirmed. Type yes, then press Enter.' },
201
+ status: 'Default Agent profile selection not confirmed.',
202
+ };
203
+ }
204
+ const command = `/agent-profile use ${quoteSlashCommandArg(readField('profile'))} --yes`;
205
+ return {
206
+ kind: 'dispatch',
207
+ command,
208
+ status: 'Opening default Agent profile selection.',
209
+ actionResult: {
210
+ kind: 'dispatched',
211
+ title: 'Opening default Agent profile selection',
212
+ detail: 'The workspace handed a confirmed default profile selection command to the shell-owned command router.',
213
+ command,
214
+ safety: 'safe',
215
+ },
216
+ };
217
+ }
218
+ if (editor.kind === 'profile-default-clear') {
219
+ if (!isAffirmative(readField('confirm'))) {
220
+ return {
221
+ kind: 'editor',
222
+ editor: { ...editor, message: 'Default Agent profile clear not confirmed. Type yes, then press Enter.' },
223
+ status: 'Default Agent profile clear not confirmed.',
224
+ };
225
+ }
226
+ const command = '/agent-profile default clear --yes';
227
+ return {
228
+ kind: 'dispatch',
229
+ command,
230
+ status: 'Opening default Agent profile clear.',
231
+ actionResult: {
232
+ kind: 'dispatched',
233
+ title: 'Opening default Agent profile clear',
234
+ detail: 'The workspace handed a confirmed default profile clear command to the shell-owned command router.',
235
+ command,
236
+ safety: 'safe',
237
+ },
238
+ };
239
+ }
240
+ if (!isAffirmative(readField('confirm'))) {
241
+ return {
242
+ kind: 'editor',
243
+ editor: { ...editor, message: 'Agent profile delete not confirmed. Type yes, then press Enter.' },
244
+ status: 'Agent profile delete not confirmed.',
245
+ };
246
+ }
247
+ const command = `/agent-profile delete ${quoteSlashCommandArg(readField('profile'))} --yes`;
248
+ return {
249
+ kind: 'dispatch',
250
+ command,
251
+ status: 'Opening Agent profile deletion.',
252
+ actionResult: {
253
+ kind: 'dispatched',
254
+ title: 'Opening Agent profile deletion',
255
+ detail: 'The workspace handed a confirmed profile deletion command to the shell-owned command router.',
256
+ command,
257
+ safety: 'safe',
258
+ },
259
+ };
260
+ }