@pellux/goodvibes-agent 1.4.4 → 1.5.1

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 (230) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +52 -7
  3. package/dist/package/main.js +7491 -12253
  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/live-verification/live-verification.json +13 -13
  11. package/release/live-verification/live-verification.md +15 -15
  12. package/release/performance-snapshot.json +2 -2
  13. package/release/release-notes.md +5 -7
  14. package/release/release-readiness.json +6 -6
  15. package/src/agent/behavior-discovery-summary.ts +4 -18
  16. package/src/agent/calendar-registry.ts +322 -0
  17. package/src/agent/competitive-feature-inventory.ts +268 -130
  18. package/src/agent/document-registry.ts +5 -1
  19. package/src/agent/email/email-service.ts +350 -0
  20. package/src/agent/email/imap-client.ts +596 -0
  21. package/src/agent/email/smtp-client.ts +453 -0
  22. package/src/agent/ics-calendar.ts +662 -0
  23. package/src/agent/ics-timezone.ts +172 -0
  24. package/src/agent/markdown-frontmatter.ts +31 -0
  25. package/src/agent/memory-safety.ts +1 -1
  26. package/src/agent/note-registry.ts +3 -9
  27. package/src/agent/persona-discovery.ts +3 -15
  28. package/src/agent/persona-registry.ts +1 -10
  29. package/src/agent/research-source-registry.ts +5 -1
  30. package/src/agent/routine-discovery.ts +3 -15
  31. package/src/agent/runtime-profile.ts +3 -0
  32. package/src/agent/skill-discovery.ts +3 -15
  33. package/src/agent/skill-draft-proposer.ts +203 -0
  34. package/src/agent/skill-draft-runner.ts +201 -0
  35. package/src/agent/skill-registry.ts +36 -1
  36. package/src/agent/skill-standard.ts +99 -0
  37. package/src/agent/vibe-file.ts +7 -22
  38. package/src/cli/completion.ts +1 -1
  39. package/src/cli/config-overrides.ts +10 -1
  40. package/src/cli/redaction.ts +17 -5
  41. package/src/config/provider-model.ts +2 -1
  42. package/src/config/secret-config.ts +13 -6
  43. package/src/core/activity-feed.ts +97 -0
  44. package/src/core/away-digest.ts +161 -0
  45. package/src/core/conversation-rendering.ts +7 -3
  46. package/src/core/conversation.ts +22 -15
  47. package/src/core/hardware-profile.ts +362 -0
  48. package/src/core/last-seen-store.ts +78 -0
  49. package/src/core/plain-language.ts +52 -0
  50. package/src/core/setup-incomplete-hint.ts +90 -0
  51. package/src/core/system-message-router.ts +38 -87
  52. package/src/input/agent-workspace-basic-command-editor-submission.ts +60 -220
  53. package/src/input/agent-workspace-basic-command-editors.ts +39 -141
  54. package/src/input/agent-workspace-categories.ts +40 -125
  55. package/src/input/agent-workspace-command-editor.ts +4 -0
  56. package/src/input/agent-workspace-host-category.ts +0 -5
  57. package/src/input/agent-workspace-local-editor-submission.ts +3 -1
  58. package/src/input/agent-workspace-navigation.ts +10 -3
  59. package/src/input/agent-workspace-onboarding-actions.ts +132 -0
  60. package/src/input/agent-workspace-onboarding-categories.ts +29 -26
  61. package/src/input/agent-workspace-onboarding-finish.ts +11 -4
  62. package/src/input/agent-workspace-onboarding-state.ts +111 -0
  63. package/src/input/agent-workspace-profile-editor-submission.ts +260 -0
  64. package/src/input/agent-workspace-profile-editors.ts +155 -0
  65. package/src/input/agent-workspace-subscription-editor.ts +7 -0
  66. package/src/input/agent-workspace-types.ts +5 -1
  67. package/src/input/agent-workspace.ts +65 -39
  68. package/src/input/command-registry.ts +18 -5
  69. package/src/input/commands/agent-runtime-profile-runtime.ts +2 -1
  70. package/src/input/commands/agent-skills-runtime.ts +60 -3
  71. package/src/input/commands/calendar-runtime.ts +209 -0
  72. package/src/input/commands/channels-runtime.ts +1 -0
  73. package/src/input/commands/command-error.ts +9 -0
  74. package/src/input/commands/compat-runtime.ts +1 -0
  75. package/src/input/commands/config.ts +1 -0
  76. package/src/input/commands/conversation-runtime.ts +1 -1
  77. package/src/input/commands/delegation-runtime.ts +5 -6
  78. package/src/input/commands/email-runtime.ts +387 -0
  79. package/src/input/commands/experience-runtime.ts +17 -4
  80. package/src/input/commands/guidance-runtime.ts +1 -1
  81. package/src/input/commands/health-runtime.ts +6 -1
  82. package/src/input/commands/knowledge-format.ts +73 -0
  83. package/src/input/commands/knowledge.ts +9 -74
  84. package/src/input/commands/local-provider-runtime.ts +2 -1
  85. package/src/input/commands/local-runtime.ts +10 -4
  86. package/src/input/commands/mcp-runtime.ts +7 -0
  87. package/src/input/commands/notify-runtime.ts +17 -1
  88. package/src/input/commands/onboarding-runtime.ts +1 -0
  89. package/src/input/commands/operator-actions-runtime.ts +1 -0
  90. package/src/input/commands/operator-runtime.ts +3 -0
  91. package/src/input/commands/personas-runtime.ts +1 -0
  92. package/src/input/commands/platform-access-runtime.ts +40 -17
  93. package/src/input/commands/product-runtime.ts +6 -1
  94. package/src/input/commands/provider-accounts-runtime.ts +3 -2
  95. package/src/input/commands/qrcode-runtime.ts +1 -0
  96. package/src/input/commands/routines-runtime.ts +1 -0
  97. package/src/input/commands/runtime-services.ts +0 -13
  98. package/src/input/commands/security-runtime.ts +1 -0
  99. package/src/input/commands/session-content.ts +1 -0
  100. package/src/input/commands/shell-core.ts +5 -2
  101. package/src/input/commands/subscription-runtime.ts +33 -9
  102. package/src/input/commands/support-bundle-runtime.ts +8 -1
  103. package/src/input/commands/tasks-runtime.ts +1 -0
  104. package/src/input/commands/tts-runtime.ts +1 -0
  105. package/src/input/commands/vibe-runtime.ts +1 -0
  106. package/src/input/commands.ts +4 -0
  107. package/src/input/feed-context-factory.ts +3 -12
  108. package/src/input/handler-command-route.ts +7 -60
  109. package/src/input/handler-feed-routes.ts +0 -194
  110. package/src/input/handler-feed.ts +2 -54
  111. package/src/input/handler-interactions.ts +0 -2
  112. package/src/input/handler-modal-stack.ts +0 -9
  113. package/src/input/handler-picker-routes.ts +24 -1
  114. package/src/input/handler-shortcuts.ts +11 -40
  115. package/src/input/handler-ui-state.ts +13 -0
  116. package/src/input/handler.ts +8 -35
  117. package/src/input/keybindings.ts +40 -17
  118. package/src/input/model-picker-local-fit.ts +130 -0
  119. package/src/input/shell-passthrough.ts +58 -0
  120. package/src/input/submission-router.ts +0 -5
  121. package/src/main.ts +129 -90
  122. package/src/renderer/activity-sidebar.ts +186 -0
  123. package/src/renderer/agent-workspace-context-lines.ts +5 -48
  124. package/src/renderer/agent-workspace-style.ts +1 -1
  125. package/src/renderer/agent-workspace.ts +14 -2
  126. package/src/renderer/compositor.ts +37 -125
  127. package/src/renderer/conversation-overlays.ts +3 -3
  128. package/src/renderer/help-overlay.ts +7 -5
  129. package/src/renderer/model-workspace.ts +101 -86
  130. package/src/{panels → renderer}/polish.ts +3 -3
  131. package/src/renderer/shell-surface.ts +4 -5
  132. package/src/renderer/status-token.ts +31 -11
  133. package/src/renderer/tab-strip.ts +1 -1
  134. package/src/renderer/tool-call.ts +7 -8
  135. package/src/renderer/tool-labels.ts +92 -0
  136. package/src/renderer/ui-factory.ts +48 -96
  137. package/src/runtime/bootstrap-command-context.ts +0 -5
  138. package/src/runtime/bootstrap-command-parts.ts +6 -15
  139. package/src/runtime/bootstrap-core.ts +34 -13
  140. package/src/runtime/bootstrap-hook-bridge.ts +3 -1
  141. package/src/runtime/bootstrap-shell.ts +3 -50
  142. package/src/runtime/bootstrap.ts +3 -4
  143. package/src/runtime/context.ts +1 -1
  144. package/src/runtime/diagnostics/panels/index.ts +0 -1
  145. package/src/runtime/diagnostics/panels/policy.ts +1 -1
  146. package/src/runtime/execution-ledger.ts +16 -1
  147. package/src/runtime/index.ts +6 -1
  148. package/src/runtime/onboarding/index.ts +1 -0
  149. package/src/runtime/onboarding/onboarding-state.ts +200 -0
  150. package/src/{panels → runtime}/provider-account-snapshot.ts +5 -2
  151. package/src/runtime/services.ts +16 -4
  152. package/src/runtime/terminal-output-guard.ts +7 -0
  153. package/src/runtime/tool-permission-safety.ts +1 -1
  154. package/src/runtime/ui/model-picker/data-provider.ts +1 -1
  155. package/src/runtime/ui/model-picker/health-enrichment.ts +2 -2
  156. package/src/runtime/ui/model-picker/types.ts +2 -2
  157. package/src/runtime/ui/provider-health/data-provider.ts +3 -3
  158. package/src/runtime/ui/provider-health/types.ts +2 -2
  159. package/src/runtime/ui-services.ts +0 -2
  160. package/src/shell/agent-workspace-fullscreen.ts +0 -1
  161. package/src/shell/autonomy-surfacing.ts +272 -0
  162. package/src/shell/session-continuity-hints.ts +0 -6
  163. package/src/shell/startup-wiring.ts +221 -0
  164. package/src/shell/ui-openers.ts +18 -29
  165. package/src/tools/agent-context-policy.ts +1 -1
  166. package/src/tools/agent-harness-background-processes.ts +4 -4
  167. package/src/tools/agent-harness-browser-cockpit-route.ts +3 -3
  168. package/src/tools/agent-harness-command-runner.ts +6 -1
  169. package/src/tools/agent-harness-document-ops.ts +26 -53
  170. package/src/tools/agent-harness-execution-history.ts +1 -13
  171. package/src/tools/agent-harness-execution-posture.ts +0 -15
  172. package/src/tools/agent-harness-keybinding-metadata.ts +28 -29
  173. package/src/tools/agent-harness-local-model-cookbook.ts +24 -1
  174. package/src/tools/agent-harness-metadata.ts +16 -0
  175. package/src/tools/agent-harness-mode-catalog.ts +2 -9
  176. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  177. package/src/tools/agent-harness-setup-posture-utils.ts +1 -1
  178. package/src/tools/agent-harness-tool-schema.ts +13 -14
  179. package/src/tools/agent-harness-tool.ts +27 -23
  180. package/src/tools/agent-harness-ui-surface-metadata.ts +10 -20
  181. package/src/tools/agent-harness-workspace-action-runner.ts +3 -4
  182. package/src/tools/agent-workspace-tool.ts +2 -33
  183. package/src/utils/terminal-width.ts +9 -3
  184. package/src/version.ts +1 -1
  185. package/src/input/agent-workspace-panel-route.ts +0 -44
  186. package/src/input/panel-integration-actions.ts +0 -26
  187. package/src/panels/approval-panel.ts +0 -149
  188. package/src/panels/automation-control-panel.ts +0 -212
  189. package/src/panels/base-panel.ts +0 -254
  190. package/src/panels/builtin/agent.ts +0 -58
  191. package/src/panels/builtin/knowledge.ts +0 -26
  192. package/src/panels/builtin/operations.ts +0 -121
  193. package/src/panels/builtin/session.ts +0 -138
  194. package/src/panels/builtin/shared.ts +0 -275
  195. package/src/panels/builtin/usage.ts +0 -21
  196. package/src/panels/builtin-panels.ts +0 -23
  197. package/src/panels/confirm-state.ts +0 -61
  198. package/src/panels/context-visualizer-panel.ts +0 -204
  199. package/src/panels/cost-tracker-panel.ts +0 -444
  200. package/src/panels/docs-panel.ts +0 -285
  201. package/src/panels/index.ts +0 -25
  202. package/src/panels/knowledge-panel.ts +0 -417
  203. package/src/panels/memory-panel.ts +0 -226
  204. package/src/panels/panel-list-panel.ts +0 -464
  205. package/src/panels/panel-manager.ts +0 -570
  206. package/src/panels/provider-accounts-panel.ts +0 -233
  207. package/src/panels/provider-health-domains.ts +0 -208
  208. package/src/panels/provider-health-panel.ts +0 -720
  209. package/src/panels/provider-health-tracker.ts +0 -115
  210. package/src/panels/provider-stats-panel.ts +0 -366
  211. package/src/panels/qr-panel.ts +0 -207
  212. package/src/panels/schedule-panel.ts +0 -321
  213. package/src/panels/scrollable-list-panel.ts +0 -491
  214. package/src/panels/search-focus.ts +0 -32
  215. package/src/panels/security-panel.ts +0 -295
  216. package/src/panels/session-browser-panel.ts +0 -395
  217. package/src/panels/session-maintenance.ts +0 -125
  218. package/src/panels/subscription-panel.ts +0 -263
  219. package/src/panels/system-messages-panel.ts +0 -230
  220. package/src/panels/tasks-panel.ts +0 -344
  221. package/src/panels/thinking-panel.ts +0 -304
  222. package/src/panels/token-budget-panel.ts +0 -475
  223. package/src/panels/tool-inspector-panel.ts +0 -436
  224. package/src/panels/types.ts +0 -54
  225. package/src/renderer/panel-composite.ts +0 -158
  226. package/src/renderer/panel-tab-bar.ts +0 -69
  227. package/src/renderer/panel-workspace-bar.ts +0 -42
  228. package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
  229. package/src/tools/agent-harness-panel-metadata.ts +0 -211
  230. /package/src/runtime/perf/{panel-health-monitor.ts → component-health.ts} +0 -0
@@ -0,0 +1,155 @@
1
+ import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+
3
+ export type AgentWorkspaceProfileEditorKind = Extract<
4
+ AgentWorkspaceEditorKind,
5
+ | 'profile-template-export'
6
+ | 'profile-template-import'
7
+ | 'profile-template-show'
8
+ | 'profile-show'
9
+ | 'profile-template-from-discovered'
10
+ | 'profile-from-discovered'
11
+ | 'profile-default'
12
+ | 'profile-default-clear'
13
+ | 'profile-delete'
14
+ >;
15
+
16
+ export function isAgentWorkspaceProfileEditorKind(kind: AgentWorkspaceEditorKind): kind is AgentWorkspaceProfileEditorKind {
17
+ return kind === 'profile-template-export'
18
+ || kind === 'profile-template-import'
19
+ || kind === 'profile-template-show'
20
+ || kind === 'profile-show'
21
+ || kind === 'profile-template-from-discovered'
22
+ || kind === 'profile-from-discovered'
23
+ || kind === 'profile-default'
24
+ || kind === 'profile-default-clear'
25
+ || kind === 'profile-delete';
26
+ }
27
+
28
+ export function createAgentWorkspaceProfileEditor(kind: AgentWorkspaceProfileEditorKind): AgentWorkspaceLocalEditor {
29
+ if (kind === 'profile-template-export') {
30
+ return {
31
+ kind,
32
+ mode: 'create',
33
+ title: 'Export Agent Starter Template',
34
+ selectedFieldIndex: 0,
35
+ message: 'Export a starter template JSON file for review and customization. Type yes on the final field to confirm.',
36
+ fields: [
37
+ { id: 'templateId', label: 'Starter id', value: '', required: true, multiline: false, hint: 'Existing starter id from /agent-profile templates.' },
38
+ { id: 'path', label: 'Output path', value: '', required: true, multiline: false, hint: 'Workspace-relative JSON path to write.' },
39
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile template export with --yes.' },
40
+ ],
41
+ };
42
+ }
43
+ if (kind === 'profile-template-import') {
44
+ return {
45
+ kind,
46
+ mode: 'create',
47
+ title: 'Import Agent Starter Template',
48
+ selectedFieldIndex: 0,
49
+ message: 'Import a reviewed starter template JSON file into this Agent home. Type yes on the final field to confirm.',
50
+ fields: [
51
+ { id: 'path', label: 'Template path', value: '', required: true, multiline: false, hint: 'Workspace-relative JSON path to import.' },
52
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile template import with --yes.' },
53
+ ],
54
+ };
55
+ }
56
+ if (kind === 'profile-template-show') {
57
+ return {
58
+ kind,
59
+ mode: 'create',
60
+ title: 'Preview Agent Starter Template',
61
+ selectedFieldIndex: 0,
62
+ message: 'Preview one built-in or local starter template before creating or exporting a profile.',
63
+ fields: [
64
+ { id: 'id', label: 'Starter id', value: '', required: true, multiline: false, hint: 'Starter template id from /agent-profile templates.' },
65
+ ],
66
+ };
67
+ }
68
+ if (kind === 'profile-show') {
69
+ return {
70
+ kind,
71
+ mode: 'create',
72
+ title: 'Show Agent Profile',
73
+ selectedFieldIndex: 0,
74
+ message: 'Show one isolated Agent profile home, starter metadata, and launch command.',
75
+ fields: [
76
+ { id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'Existing isolated Agent profile name from /agent-profile list.' },
77
+ ],
78
+ };
79
+ }
80
+ if (kind === 'profile-template-from-discovered') {
81
+ return {
82
+ kind,
83
+ mode: 'create',
84
+ title: 'Create Starter from Discovered Behavior',
85
+ selectedFieldIndex: 0,
86
+ message: 'Create an Agent-local starter template from reviewed discovered persona, skill, and routine markdown. Type yes on the final field to confirm.',
87
+ fields: [
88
+ { id: 'id', label: 'Starter id', value: '', required: true, multiline: false, hint: 'New local starter id, for example research-desk.' },
89
+ { id: 'name', label: 'Starter name', value: '', required: false, multiline: false, hint: 'Optional display name. Defaults to the selected persona name.' },
90
+ { id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional one-line summary.' },
91
+ { id: 'persona', label: 'Persona', value: '', required: false, multiline: false, hint: 'Optional discovered persona name/path. Blank uses the first discovered persona.' },
92
+ { id: 'skills', label: 'Skills', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered skill names. Blank includes all.' },
93
+ { id: 'routines', label: 'Routines', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered routine names. Blank includes all.' },
94
+ { id: 'replace', label: 'Replace existing', value: 'no', required: false, multiline: false, hint: 'yes/no. Existing starter ids are protected unless this is yes.' },
95
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile template from-discovered with --yes.' },
96
+ ],
97
+ };
98
+ }
99
+ if (kind === 'profile-from-discovered') {
100
+ return {
101
+ kind,
102
+ mode: 'create',
103
+ title: 'Create Profile from Discovered Behavior',
104
+ selectedFieldIndex: 0,
105
+ message: 'Create a local starter template and isolated Agent profile from reviewed discovered behavior markdown. Type yes on the final field to confirm.',
106
+ fields: [
107
+ { id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'New isolated Agent profile name, for example research-desk.' },
108
+ { id: 'templateId', label: 'Starter id', value: '', required: false, multiline: false, hint: 'Optional local starter id. Blank uses the profile name.' },
109
+ { id: 'name', label: 'Starter name', value: '', required: false, multiline: false, hint: 'Optional display name for the generated starter.' },
110
+ { id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional one-line summary.' },
111
+ { id: 'persona', label: 'Persona', value: '', required: false, multiline: false, hint: 'Optional discovered persona name/path. Blank uses the first discovered persona.' },
112
+ { id: 'skills', label: 'Skills', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered skill names. Blank includes all.' },
113
+ { id: 'routines', label: 'Routines', value: '', required: false, multiline: false, hint: 'all or comma-separated discovered routine names. Blank includes all.' },
114
+ { id: 'replace', label: 'Replace starter', value: 'no', required: false, multiline: false, hint: 'yes/no. Existing starter ids are protected unless this is yes.' },
115
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile create-from-discovered with --yes.' },
116
+ ],
117
+ };
118
+ }
119
+ if (kind === 'profile-default') {
120
+ return {
121
+ kind,
122
+ mode: 'update',
123
+ title: 'Use Default Agent Profile',
124
+ selectedFieldIndex: 0,
125
+ message: 'Select which isolated Agent profile the next plain goodvibes-agent run should use. Type yes on the final field to confirm.',
126
+ fields: [
127
+ { id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'Existing isolated Agent profile name from /agent-profile list.' },
128
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile use with --yes.' },
129
+ ],
130
+ };
131
+ }
132
+ if (kind === 'profile-default-clear') {
133
+ return {
134
+ kind,
135
+ mode: 'update',
136
+ title: 'Clear Default Agent Profile',
137
+ selectedFieldIndex: 0,
138
+ message: 'Return the next plain goodvibes-agent run to the base Agent home. Type yes to confirm.',
139
+ fields: [
140
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile default clear with --yes.' },
141
+ ],
142
+ };
143
+ }
144
+ return {
145
+ kind,
146
+ mode: 'delete',
147
+ title: 'Delete Agent Profile',
148
+ selectedFieldIndex: 0,
149
+ message: 'Delete one isolated Agent profile home. Type yes on the final field to confirm.',
150
+ fields: [
151
+ { id: 'profile', label: 'Profile name', value: '', required: true, multiline: false, hint: 'Existing isolated Agent profile name from /agent-profile list.' },
152
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-profile delete with --yes.' },
153
+ ],
154
+ };
155
+ }
@@ -12,6 +12,12 @@ export interface AgentWorkspaceSubscriptionEditorHost {
12
12
  status: string;
13
13
  lastActionResult: AgentWorkspaceActionResult | null;
14
14
  clampSelection(): void;
15
+ /**
16
+ * Called after a successful sign-in so the host can refresh onboarding state
17
+ * and navigate to the next onboarding step (e.g. account-model). Optional —
18
+ * only available when running in ONBOARDING mode.
19
+ */
20
+ onSubscriptionLoginSuccess?(): void;
15
21
  }
16
22
 
17
23
  export type AgentWorkspaceSubscriptionFieldReader = (id: string) => string;
@@ -140,6 +146,7 @@ export async function submitAgentWorkspaceSubscriptionLoginFinishEditor(
140
146
  safety: 'safe',
141
147
  };
142
148
  host.clampSelection();
149
+ host.onSubscriptionLoginSuccess?.();
143
150
  } catch (error) {
144
151
  const detail = error instanceof Error ? error.message : String(error);
145
152
  host.localEditor = { ...editor, message: detail };
@@ -151,6 +151,8 @@ export type AgentWorkspaceEditorKind =
151
151
  | 'persona-discovery-import'
152
152
  | 'routine-discovery-import'
153
153
  | 'skill-discovery-import'
154
+ | 'skill-standard-import'
155
+ | 'skill-standard-export'
154
156
  | 'learned-behavior'
155
157
  | 'profile-template-export'
156
158
  | 'profile-template-import'
@@ -334,7 +336,7 @@ export interface AgentWorkspaceActionSearchResult {
334
336
  export type AgentWorkspaceCommandDispatcher = (command: string, behavior?: 'inline' | 'compose' | 'exit') => void;
335
337
  export type AgentWorkspacePromptDispatcher = (prompt: string) => void;
336
338
 
337
- export type AgentWorkspaceActionResultKind = 'guidance' | 'blocked' | 'dispatched' | 'refreshed' | 'error';
339
+ export type AgentWorkspaceActionResultKind = 'guidance' | 'blocked' | 'dispatched' | 'refreshed' | 'error' | 'recap';
338
340
 
339
341
  export interface AgentWorkspaceActionResult {
340
342
  readonly kind: AgentWorkspaceActionResultKind;
@@ -342,6 +344,8 @@ export interface AgentWorkspaceActionResult {
342
344
  readonly detail: string;
343
345
  readonly command?: string;
344
346
  readonly safety?: AgentWorkspaceAction['safety'];
347
+ /** Lines to display when kind is 'recap'. */
348
+ readonly lines?: readonly string[];
345
349
  }
346
350
 
347
351
  export interface AgentWorkspaceLocalLibraryItem {
@@ -24,7 +24,9 @@ import { buildAgentWorkspaceRuntimeSnapshot } from './agent-workspace-snapshot.t
24
24
  import { submitAgentWorkspaceSubscriptionLoginFinishEditor, submitAgentWorkspaceSubscriptionLoginStartEditor, submitAgentWorkspaceSubscriptionLogoutEditor } from './agent-workspace-subscription-editor.ts';
25
25
  import type { AgentWorkspaceAction, AgentWorkspaceActionResult, AgentWorkspaceActionSearchResult, AgentWorkspaceCategory, AgentWorkspaceCategoryGroup, AgentWorkspaceCommandDispatcher, AgentWorkspaceEditorField, AgentWorkspaceFocusPane, AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem, AgentWorkspaceLocalOperation, AgentWorkspacePromptDispatcher, AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
26
26
  import { ONBOARDING_COMPLETE_SYNTHETIC_ACTION, shouldShowOnboardingFinishFooter } from './agent-workspace-onboarding-finish.ts';
27
- import { writeOnboardingCheckMarker, writeOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
27
+ import { completeOnboardingAction, onSubscriptionLoginSuccessAction } from './agent-workspace-onboarding-actions.ts';
28
+ import { computeOnboardingStateFromSnapshot, deriveOnboardingEntry, updateRevealedOnboardingCategories } from './agent-workspace-onboarding-state.ts';
29
+ import type { OnboardingState } from '../runtime/onboarding/onboarding-state.ts';
28
30
 
29
31
  export type { AgentWorkspaceChannelRisk, AgentWorkspaceChannelStatus } from './agent-workspace-channels.ts';
30
32
  export type { AgentWorkspaceAction, AgentWorkspaceActionResult, AgentWorkspaceActionSearchResult, AgentWorkspaceCategory, AgentWorkspaceCategoryId, AgentWorkspaceCommandDispatcher, AgentWorkspaceEditorField, AgentWorkspaceFocusPane, AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem, AgentWorkspaceLocalOperation, AgentWorkspacePromptDispatcher, AgentWorkspaceRuntimeSnapshot } from './agent-workspace-types.ts';
@@ -48,13 +50,20 @@ export class AgentWorkspace {
48
50
  private dispatchCommand: AgentWorkspaceCommandDispatcher | null = null;
49
51
  private dispatchPrompt: AgentWorkspacePromptDispatcher | null = null;
50
52
  private _onlyGroup: AgentWorkspaceCategoryGroup | null = null;
53
+ private _onboardingState: OnboardingState | null = null;
54
+ private _revealedOnboardingCategoryIds = new Set<string>(); // monotonic reveal set
55
+ private _awaitingRecapDismiss = false; // true while showing recap before final close
51
56
 
52
57
  open(context: CommandContext, dispatchCommand: AgentWorkspaceCommandDispatcher, categoryId?: string, dispatchPrompt?: AgentWorkspacePromptDispatcher, onlyGroup?: AgentWorkspaceCategoryGroup): void {
53
58
  this.context = context;
54
59
  this.dispatchCommand = dispatchCommand;
55
60
  this.dispatchPrompt = dispatchPrompt ?? null;
56
61
  this._onlyGroup = onlyGroup ?? null;
62
+ this._awaitingRecapDismiss = false;
57
63
  this.runtimeSnapshot = buildAgentWorkspaceRuntimeSnapshot(context);
64
+ const shellPaths = context.workspace?.shellPaths;
65
+ this._onboardingState = computeOnboardingStateFromSnapshot(this.runtimeSnapshot, shellPaths);
66
+ if (this._onboardingState) updateRevealedOnboardingCategories(this._onboardingState, this._revealedOnboardingCategoryIds);
58
67
  this.active = true;
59
68
  this.focusPane = 'actions';
60
69
  this.status = 'Ready. Choose an operator flow; ordinary assistant work stays in the main conversation.';
@@ -75,6 +84,14 @@ export class AgentWorkspace {
75
84
  safety: 'safe',
76
85
  };
77
86
  }
87
+ if (onlyGroup === 'ONBOARDING' && this._onboardingState) {
88
+ const entry = deriveOnboardingEntry(this._onboardingState);
89
+ this.status = entry.status;
90
+ if (entry.categoryId) {
91
+ const idx = this.categories.findIndex((c) => c.id === entry.categoryId);
92
+ if (idx >= 0) this.selectedCategoryIndex = idx;
93
+ }
94
+ }
78
95
  this.clampSelection();
79
96
  }
80
97
 
@@ -89,9 +106,21 @@ export class AgentWorkspace {
89
106
  this.actionSearchActive = false;
90
107
  this.actionSearchQuery = '';
91
108
  this._onlyGroup = null;
109
+ this._onboardingState = null;
110
+ this._awaitingRecapDismiss = false;
92
111
  }
93
112
 
94
113
  get categories(): readonly AgentWorkspaceCategory[] {
114
+ if (this._onlyGroup === 'ONBOARDING') {
115
+ // Pure read — reveal set is updated at every _onboardingState assignment
116
+ // (open, onSubscriptionLoginSuccess), not here. Recompute is O(categories)
117
+ // and intentionally simple; the list is small and no caching is needed.
118
+ const onboarding = AGENT_WORKSPACE_CATEGORIES.filter((c) => c.group === 'ONBOARDING');
119
+ if (this._onboardingState) {
120
+ return onboarding.filter((c) => this._revealedOnboardingCategoryIds.has(c.id));
121
+ }
122
+ return onboarding;
123
+ }
95
124
  if (this._onlyGroup) {
96
125
  return AGENT_WORKSPACE_CATEGORIES.filter((category) => category.group === this._onlyGroup);
97
126
  }
@@ -105,7 +134,7 @@ export class AgentWorkspace {
105
134
  get actions(): readonly AgentWorkspaceAction[] {
106
135
  if (this.actionSearchActive) return this.actionSearchResults.map((result) => result.action);
107
136
  const base = this.selectedCategory.actions.filter((action) => isAgentWorkspaceActionVisible(this.context, action));
108
- if (shouldShowOnboardingFinishFooter(this.selectedCategory, base)) {
137
+ if (shouldShowOnboardingFinishFooter(this.selectedCategory, base, this._onlyGroup === 'ONBOARDING' ? this._onboardingState?.readyToChat : undefined)) {
109
138
  return [...base, ONBOARDING_COMPLETE_SYNTHETIC_ACTION];
110
139
  }
111
140
  return base;
@@ -169,21 +198,10 @@ export class AgentWorkspace {
169
198
  this.focusPane = this.focusPane === 'categories' ? 'actions' : 'categories';
170
199
  }
171
200
 
172
- moveUp(): void {
173
- moveAgentWorkspaceSelection(this, -1);
174
- }
175
-
176
- moveDown(): void {
177
- moveAgentWorkspaceSelection(this, 1);
178
- }
179
-
180
- jumpHome(): void {
181
- jumpAgentWorkspaceSelection(this, 'home');
182
- }
183
-
184
- jumpEnd(): void {
185
- jumpAgentWorkspaceSelection(this, 'end');
186
- }
201
+ moveUp(): void { moveAgentWorkspaceSelection(this, -1); }
202
+ moveDown(): void { moveAgentWorkspaceSelection(this, 1); }
203
+ jumpHome(): void { jumpAgentWorkspaceSelection(this, 'home'); }
204
+ jumpEnd(): void { jumpAgentWorkspaceSelection(this, 'end'); }
187
205
 
188
206
  refreshRuntimeSnapshot(): void {
189
207
  if (!this.context) {
@@ -306,6 +324,7 @@ export class AgentWorkspace {
306
324
  clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'persona');
307
325
  clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'skill');
308
326
  clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'routine');
327
+ clampAgentWorkspaceLocalLibrarySelection(this.runtimeSnapshot, this.selectedLibraryItemIndexes, 'profile');
309
328
  }
310
329
 
311
330
  moveLocalLibraryItemSelection(kind: AgentWorkspaceLocalEditorKind, delta: number): void {
@@ -323,30 +342,37 @@ export class AgentWorkspace {
323
342
  }
324
343
 
325
344
  completeOnboarding(): void {
326
- const shellPaths = this.context?.workspace?.shellPaths;
327
- if (!shellPaths) {
328
- this.status = 'Cannot complete onboarding without Agent shell paths.';
329
- this.lastActionResult = {
330
- kind: 'error',
331
- title: 'Onboarding completion unavailable',
332
- detail: 'The Agent workspace cannot locate the user onboarding completion marker path for this runtime.',
333
- safety: 'safe',
334
- };
335
- return;
336
- }
345
+ const result = completeOnboardingAction({
346
+ awaitingRecapDismiss: this._awaitingRecapDismiss,
347
+ runtimeSnapshot: this.runtimeSnapshot,
348
+ shellPaths: this.context?.workspace?.shellPaths,
349
+ dismissAgentWorkspace: this.context?.dismissAgentWorkspace,
350
+ close: () => this.close(),
351
+ });
352
+ if (result.dismissed) return;
353
+ this._awaitingRecapDismiss = result.awaitingRecapDismiss;
354
+ this.status = result.status;
355
+ this.lastActionResult = result.lastActionResult;
356
+ }
337
357
 
338
- try {
339
- const marker = { scope: 'user', source: 'wizard', mode: 'new', workspaceRoot: shellPaths.workingDirectory } as const;
340
- writeOnboardingCheckMarker(shellPaths, marker);
341
- writeOnboardingCompletionMarker(shellPaths, marker);
342
- this.status = 'Onboarding applied and closed.';
343
- this.lastActionResult = { kind: 'refreshed', title: 'Onboarding complete', detail: 'Saved the user onboarding completion marker. Future normal launches start in the main conversation.', safety: 'safe' };
344
- if (!this.context?.dismissAgentWorkspace?.()) this.close();
345
- } catch (error) {
346
- const detail = error instanceof Error ? error.message : String(error);
347
- this.status = 'Onboarding completion failed.';
348
- this.lastActionResult = { kind: 'error', title: 'Onboarding completion failed', detail, safety: 'safe' };
358
+ onSubscriptionLoginSuccess(): void {
359
+ const result = onSubscriptionLoginSuccessAction({
360
+ onlyGroup: this._onlyGroup,
361
+ runtimeSnapshot: this.runtimeSnapshot,
362
+ shellPaths: this.context?.workspace?.shellPaths,
363
+ });
364
+ if (this._onlyGroup !== 'ONBOARDING') return;
365
+ // Update _onboardingState and reveal set FIRST so that this.categories
366
+ // reflects any newly-unlocked lane (e.g. account-model after sign-in)
367
+ // before we try to resolve the target index against the fresh list.
368
+ this._onboardingState = result.onboardingState;
369
+ if (!result.onboardingState) return;
370
+ if (this._onboardingState) updateRevealedOnboardingCategories(this._onboardingState, this._revealedOnboardingCategoryIds);
371
+ if (result.targetCategoryId) {
372
+ const idx = this.categories.findIndex((c) => c.id === result.targetCategoryId);
373
+ if (idx >= 0) this.selectedCategoryIndex = idx;
349
374
  }
375
+ this.status = result.status;
350
376
  }
351
377
 
352
378
  openModelPickerAction(action: AgentWorkspaceAction, requestRender?: () => void): void {
@@ -8,7 +8,6 @@ import type { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
8
8
  import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
9
9
  import type { SelectionItem, SelectionResult, SelectionAction } from './selection-modal.ts';
10
10
  import type { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
11
- import type { PanelManager } from '../panels/panel-manager.ts';
12
11
  import type { KeybindingsManager } from './keybindings.ts';
13
12
  import type { KnowledgeApi } from '@pellux/goodvibes-sdk/platform/knowledge';
14
13
  import type { HookApi } from '@pellux/goodvibes-sdk/platform/hooks';
@@ -124,9 +123,7 @@ export interface CommandShellUiOpeners {
124
123
  openProfilePicker?: () => void;
125
124
  openShortcutsOverlay?: () => void;
126
125
  getScrollTop?: () => number;
127
- openPanelPicker?: () => void;
128
- showPanel?: (panelId: string, pane?: 'top' | 'bottom') => void;
129
- focusPanels?: () => void;
126
+ openWorkspacePicker?: () => void;
130
127
  focusPrompt?: () => void;
131
128
  openMcpWorkspace?: () => void;
132
129
  openAgentWorkspace?: (categoryId?: string) => void;
@@ -134,6 +131,7 @@ export interface CommandShellUiOpeners {
134
131
  openSecurityPanel?: () => void;
135
132
  openKnowledgePanel?: () => void;
136
133
  openSubscriptionPanel?: () => void;
134
+ toggleActivitySidebar?: () => void;
137
135
  }
138
136
 
139
137
  export interface CommandSessionServices {
@@ -159,7 +157,6 @@ export interface CommandProviderServices {
159
157
  export interface CommandWorkspaceUiServices {
160
158
  keybindingsManager?: KeybindingsManager;
161
159
  fileUndoManager?: FileUndoManager;
162
- panelManager?: PanelManager;
163
160
  processManager?: ProcessManager;
164
161
  profileManager?: import('@pellux/goodvibes-sdk/platform/profiles').ProfileManager;
165
162
  bookmarkManager?: import('@pellux/goodvibes-sdk/platform/bookmarks').BookmarkManager;
@@ -243,6 +240,13 @@ export interface SlashCommand {
243
240
  usage?: string;
244
241
  /** Short inline argument hint shown after cursor in dim grey, e.g. "[name]". Falls back to usage if not set. */
245
242
  argsHint?: string;
243
+ /**
244
+ * Hidden commands still run when typed, but stay out of fuzzy autocomplete
245
+ * suggestions. They surface in autocomplete on an exact name or alias match.
246
+ * The /help overlay also filters them. The /commands slash command lists
247
+ * all commands including hidden ones, labeled "(hidden)".
248
+ */
249
+ hidden?: boolean;
246
250
  /** The function executed when the command is invoked. */
247
251
  handler: (args: string[], context: CommandContext) => void | Promise<void>;
248
252
  }
@@ -286,6 +290,11 @@ export class CommandRegistry {
286
290
  return Array.from(this.commands.values());
287
291
  }
288
292
 
293
+ /** Commands that should appear in autocomplete and /help listings. */
294
+ getVisible(): SlashCommand[] {
295
+ return this.getAll().filter((command) => !command.hidden);
296
+ }
297
+
289
298
  /**
290
299
  * list - Compatibility alias for the simpler SDK registry surface.
291
300
  */
@@ -310,6 +319,10 @@ export class CommandRegistry {
310
319
  if (score > bestScore) bestScore = score;
311
320
  }
312
321
 
322
+ // Hidden commands stay out of suggestions until the user types the
323
+ // exact name or alias — they still execute normally.
324
+ if (cmd.hidden && !names.map((n) => n.toLowerCase()).includes(q)) continue;
325
+
313
326
  if (bestScore > 0 || q === '') {
314
327
  results.push({ command: cmd, score: q === '' ? 1 : bestScore });
315
328
  }
@@ -139,6 +139,7 @@ export function registerAgentRuntimeProfileRuntimeCommands(registry: CommandRegi
139
139
  name: 'agent-profile',
140
140
  aliases: ['runtime-profile', 'agent-profiles'],
141
141
  description: 'Manage isolated Agent profiles and starter templates',
142
+ hidden: true,
142
143
  usage: '[list|show|default|use|templates|guide|template show|template export|template import|template from-discovered|create|create-from-discovered|delete]',
143
144
  async handler(args, ctx) {
144
145
  const shellPaths = requireShellPaths(ctx);
@@ -244,7 +245,7 @@ export function registerAgentRuntimeProfileRuntimeCommands(registry: CommandRegi
244
245
  const templateId = commandArgs[2];
245
246
  const pathArg = commandArgs[3];
246
247
  if (!templateId || !pathArg) {
247
- ctx.print('Usage: /agent-profile template export <id> <path> [--include-vibe] --yes');
248
+ ctx.print('Usage: /agent-profile template export <id> <path> [--include-vibe] --yes');
248
249
  return;
249
250
  }
250
251
  if (!parsed.yes) {
@@ -1,3 +1,4 @@
1
+ import { readFileSync } from 'node:fs';
1
2
  import {
2
3
  AgentSkillRegistry,
3
4
  buildAgentSkillRequirements,
@@ -8,6 +9,7 @@ import {
8
9
  type AgentSkillRecord,
9
10
  } from '../../agent/skill-registry.ts';
10
11
  import { discoverSkills, type SkillRecord } from '../../agent/skill-discovery.ts';
12
+ import { parseSkillStandardMarkdown } from '../../agent/skill-standard.ts';
11
13
  import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../../agent/record-labels.ts';
12
14
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
13
15
  import { parseAgentLocalLibraryArgs, type ParsedAgentLocalLibraryArgs } from './agent-local-library-args.ts';
@@ -137,7 +139,7 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
137
139
  const parsed = parseSkillArgs(args);
138
140
  const name = parsed.rest.join(' ').trim();
139
141
  if (!name) {
140
- ctx.print('Usage: /skills import-discovered <name> [--enabled] --yes');
142
+ ctx.print('Usage: /skills import-discovered <name> --yes\n Note: discovered skills import disabled; review then enable via /skills enable <name>.');
141
143
  return;
142
144
  }
143
145
  const discovered = findDiscoveredSkill(await discoverSkills(requireShellPaths(ctx)), name);
@@ -167,11 +169,14 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
167
169
  env: frontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
168
170
  commands: frontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
169
171
  }),
170
- enabled: parsed.flags.get('enabled') === 'true',
172
+ enabled: false,
171
173
  source: 'imported',
172
174
  provenance: `Imported file (${discovered.origin}): ${discovered.path}`,
173
175
  });
174
- ctx.print(formatSkillReceipt('Imported Agent skill', skill, [` enabled ${skill.enabled ? 'yes' : 'no'}`]));
176
+ ctx.print(formatSkillReceipt('Imported Agent skill', skill, [
177
+ ' enabled no — imported disabled (review it, then enable it)',
178
+ ' review pending',
179
+ ]));
175
180
  }
176
181
 
177
182
  function renderBundleList(title: string, registry: AgentSkillRegistry, bundles: readonly AgentSkillBundleRecord[], emptyMessage?: string): string {
@@ -377,6 +382,57 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
377
382
  await importDiscoveredSkill(args.slice(1), ctx, skillRegistry);
378
383
  return;
379
384
  }
385
+ if (sub === 'import-standard') {
386
+ const parsed = parseSkillArgs(args.slice(1));
387
+ const filePath = parsed.rest[0];
388
+ if (!filePath) {
389
+ ctx.print('Usage: /skills import-standard <path/to/SKILL.md> --yes');
390
+ return;
391
+ }
392
+ if (!parsed.yes) {
393
+ ctx.print([
394
+ 'Agent skill standard import preview',
395
+ ` path ${filePath}`,
396
+ ' next rerun with --yes to import into the Agent-local skill registry',
397
+ ].join('\n'));
398
+ return;
399
+ }
400
+ const content = readFileSync(filePath, 'utf-8');
401
+ const parseResult = parseSkillStandardMarkdown(content);
402
+ if ('error' in parseResult) {
403
+ ctx.print(`Skill standard import rejected: ${parseResult.error}`);
404
+ return;
405
+ }
406
+ const skill = skillRegistry.importFromStandard(content);
407
+ ctx.print(formatSkillReceipt('Imported shared skill', skill, [` source ${filePath}`, ` review-state ${skill.reviewState}`]));
408
+ return;
409
+ }
410
+ if (sub === 'export-standard') {
411
+ const parsed = parseSkillArgs(args.slice(1));
412
+ const skillId = parsed.rest[0];
413
+ const destDir = parsed.rest[1];
414
+ if (!skillId || !destDir) {
415
+ ctx.print('Usage: /skills export-standard <id> <dest-directory> --yes');
416
+ return;
417
+ }
418
+ if (!parsed.yes) {
419
+ const skill = skillRegistry.get(skillId);
420
+ if (!skill) {
421
+ ctx.print(`Unknown Agent skill ${skillId}`);
422
+ return;
423
+ }
424
+ ctx.print([
425
+ 'Agent skill standard export preview',
426
+ ` skill ${skill.id} (${skill.name})`,
427
+ ` dest ${destDir}/${skill.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')}/SKILL.md`,
428
+ ' next rerun with --yes to write the file',
429
+ ].join('\n'));
430
+ return;
431
+ }
432
+ const written = skillRegistry.exportToStandard(skillId, destDir);
433
+ ctx.print(`Exported skill to ${written}`);
434
+ return;
435
+ }
380
436
  if (sub === 'list' || sub === 'open') {
381
437
  ctx.print(renderList('Agent Skills', skillRegistry, skillRegistry.list()));
382
438
  return;
@@ -506,6 +562,7 @@ export function registerAgentSkillsRuntimeCommands(registry: CommandRegistry): v
506
562
  name: 'skills',
507
563
  aliases: ['skill', 'agent-skills', 'askills', 'local-skills'],
508
564
  description: 'Manage Agent-local skills',
565
+ hidden: true,
509
566
  usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --procedure <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--procedure ...]|enable <id>|disable <id>|review <id>|stale <id> <reason...>|delete <id> --yes|bundle ...]',
510
567
  handler: runAgentSkillsRuntimeCommand,
511
568
  });