@pellux/goodvibes-agent 1.5.5 → 1.5.6

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 (165) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +1 -1
  3. package/dist/package/main.js +94130 -79335
  4. package/docs/tools-and-commands.md +2 -1
  5. package/package.json +6 -3
  6. package/src/agent/autonomy-schedule-format.ts +1 -1
  7. package/src/agent/autonomy-schedule.ts +3 -3
  8. package/src/agent/calendar/calendar-oauth-service.ts +324 -0
  9. package/src/agent/calendar-subscription-registry.ts +497 -0
  10. package/src/agent/email/email-service.ts +57 -0
  11. package/src/agent/email/smtp-client.ts +30 -10
  12. package/src/agent/memory-prompt.ts +143 -12
  13. package/src/agent/operator-actions.ts +26 -22
  14. package/src/agent/prompt-context-receipts.ts +45 -18
  15. package/src/agent/reminder-schedule-format.ts +1 -1
  16. package/src/agent/reminder-schedule.ts +3 -3
  17. package/src/agent/routine-schedule-format.ts +2 -2
  18. package/src/agent/routine-schedule-promotion.ts +5 -5
  19. package/src/agent/routine-schedule-receipts.ts +2 -2
  20. package/src/agent/schedule-edit-format.ts +1 -1
  21. package/src/agent/schedule-edit.ts +5 -5
  22. package/src/agent/session-registration.ts +281 -0
  23. package/src/agent/vibe-file.ts +50 -0
  24. package/src/cli/local-library-command-shared.ts +146 -0
  25. package/src/cli/management.ts +2 -1
  26. package/src/cli/personas-command.ts +252 -0
  27. package/src/cli/resume-relaunch-notice.ts +151 -0
  28. package/src/cli/routines-command.ts +25 -2
  29. package/src/cli/service-posture.ts +3 -2
  30. package/src/cli/skill-bundle-command.ts +175 -0
  31. package/src/cli/skills-command.ts +309 -0
  32. package/src/cli/status.ts +43 -7
  33. package/src/cli/tui-startup.ts +24 -1
  34. package/src/config/agent-settings-policy.ts +0 -1
  35. package/src/config/secret-config.ts +4 -0
  36. package/src/core/conversation-rendering.ts +20 -11
  37. package/src/core/focus-tracker.ts +41 -0
  38. package/src/core/system-message-noise.ts +108 -0
  39. package/src/core/system-message-router.ts +54 -1
  40. package/src/core/thinking-overlay.ts +83 -0
  41. package/src/input/agent-workspace-access-command-editor-submission.ts +75 -108
  42. package/src/input/agent-workspace-access-command-editors.ts +108 -128
  43. package/src/input/agent-workspace-activation.ts +15 -0
  44. package/src/input/agent-workspace-basic-command-editor-submission.ts +292 -513
  45. package/src/input/agent-workspace-basic-command-editors.ts +433 -564
  46. package/src/input/agent-workspace-calendar-connect-editor.ts +116 -0
  47. package/src/input/agent-workspace-calendar-oauth-editor.ts +152 -0
  48. package/src/input/agent-workspace-calendar-subscribe-editor.ts +128 -0
  49. package/src/input/agent-workspace-categories.ts +7 -2
  50. package/src/input/agent-workspace-channel-command-editor-submission.ts +38 -52
  51. package/src/input/agent-workspace-channel-command-editors.ts +42 -46
  52. package/src/input/agent-workspace-command-editor-engine.ts +133 -0
  53. package/src/input/agent-workspace-command-editor.ts +4 -0
  54. package/src/input/agent-workspace-direct-editor-submission.ts +59 -0
  55. package/src/input/agent-workspace-email-connect-editor.ts +162 -0
  56. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +52 -81
  57. package/src/input/agent-workspace-knowledge-command-editors.ts +71 -71
  58. package/src/input/agent-workspace-library-command-editor-submission.ts +10 -28
  59. package/src/input/agent-workspace-library-command-editors.ts +16 -2
  60. package/src/input/agent-workspace-live-counters.ts +55 -0
  61. package/src/input/agent-workspace-mcp-command-editor-submission.ts +60 -82
  62. package/src/input/agent-workspace-mcp-command-editors.ts +52 -0
  63. package/src/input/agent-workspace-media-command-editor-submission.ts +12 -39
  64. package/src/input/agent-workspace-media-command-editors.ts +10 -8
  65. package/src/input/agent-workspace-memory-command-editor-submission.ts +76 -151
  66. package/src/input/agent-workspace-memory-command-editors.ts +116 -141
  67. package/src/input/agent-workspace-operations-command-editor-submission.ts +131 -184
  68. package/src/input/agent-workspace-operations-command-editors.ts +150 -162
  69. package/src/input/agent-workspace-provider-command-editor-submission.ts +60 -106
  70. package/src/input/agent-workspace-provider-command-editors.ts +58 -68
  71. package/src/input/agent-workspace-search.ts +8 -1
  72. package/src/input/agent-workspace-session-command-editor-submission.ts +104 -132
  73. package/src/input/agent-workspace-session-command-editors.ts +160 -195
  74. package/src/input/agent-workspace-settings.ts +40 -1
  75. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +55 -71
  76. package/src/input/agent-workspace-skill-bundle-command-editors.ts +65 -69
  77. package/src/input/agent-workspace-snapshot-builders.ts +431 -0
  78. package/src/input/agent-workspace-snapshot-config.ts +43 -0
  79. package/src/input/agent-workspace-snapshot.ts +198 -432
  80. package/src/input/agent-workspace-task-command-editor-submission.ts +34 -44
  81. package/src/input/agent-workspace-task-command-editors.ts +27 -28
  82. package/src/input/agent-workspace-types.ts +35 -1
  83. package/src/input/agent-workspace.ts +5 -14
  84. package/src/input/command-registry.ts +23 -1
  85. package/src/input/commands/calendar-connect-runtime.ts +226 -0
  86. package/src/input/commands/calendar-runtime.ts +110 -7
  87. package/src/input/commands/calendar-subscription-runtime.ts +225 -0
  88. package/src/input/commands/email-runtime.ts +100 -40
  89. package/src/input/commands/knowledge.ts +1 -1
  90. package/src/input/commands/network-scan-runtime.ts +75 -0
  91. package/src/input/commands/operator-actions-runtime.ts +9 -6
  92. package/src/input/commands/personas-runtime.ts +1 -1
  93. package/src/input/commands/schedule-runtime.ts +4 -4
  94. package/src/input/commands/session-content.ts +13 -1
  95. package/src/input/commands/session-workflow.ts +15 -20
  96. package/src/input/commands/session.ts +3 -1
  97. package/src/input/commands/shell-core.ts +20 -6
  98. package/src/input/commands.ts +2 -2
  99. package/src/input/delete-key-policy.ts +46 -0
  100. package/src/input/feed-context-factory.ts +10 -0
  101. package/src/input/handler-feed.ts +87 -0
  102. package/src/input/handler-modal-routes.ts +6 -1
  103. package/src/input/handler.ts +5 -0
  104. package/src/input/panel-paste-flood-guard.ts +94 -0
  105. package/src/input/settings-modal-types.ts +5 -3
  106. package/src/input/settings-modal.ts +21 -0
  107. package/src/main.ts +36 -36
  108. package/src/permissions/approval-posture.ts +141 -0
  109. package/src/renderer/agent-workspace-context-lines.ts +10 -2
  110. package/src/renderer/compositor.ts +27 -4
  111. package/src/renderer/diff.ts +61 -18
  112. package/src/renderer/fullscreen-primitives.ts +37 -18
  113. package/src/renderer/markdown.ts +20 -10
  114. package/src/renderer/modal-factory.ts +25 -15
  115. package/src/renderer/overlay-box.ts +23 -12
  116. package/src/renderer/process-indicator.ts +8 -3
  117. package/src/renderer/prompt-content-width.ts +16 -0
  118. package/src/renderer/settings-modal-helpers.ts +2 -0
  119. package/src/renderer/settings-modal.ts +2 -0
  120. package/src/renderer/startup-theme-probe.ts +35 -0
  121. package/src/renderer/status-glyphs.ts +11 -15
  122. package/src/renderer/system-message.ts +17 -2
  123. package/src/renderer/term-caps.ts +318 -0
  124. package/src/renderer/terminal-bg-probe.ts +373 -0
  125. package/src/renderer/terminal-escapes.ts +24 -0
  126. package/src/renderer/theme-mode-config.ts +87 -0
  127. package/src/renderer/theme.ts +241 -0
  128. package/src/renderer/thinking.ts +12 -3
  129. package/src/renderer/tool-call.ts +7 -3
  130. package/src/renderer/ui-factory.ts +92 -36
  131. package/src/renderer/ui-primitives.ts +33 -93
  132. package/src/runtime/bootstrap-core.ts +15 -0
  133. package/src/runtime/bootstrap-hook-bridge.ts +6 -0
  134. package/src/runtime/bootstrap-shell.ts +2 -0
  135. package/src/runtime/bootstrap.ts +68 -5
  136. package/src/runtime/calendar-boot-refresh.ts +105 -0
  137. package/src/runtime/lan-scan-consent.ts +253 -0
  138. package/src/runtime/services.ts +127 -2
  139. package/src/runtime/session-spine-rest-transport.ts +160 -0
  140. package/src/runtime/terminal-output-guard.ts +6 -1
  141. package/src/runtime/ui-services.ts +3 -0
  142. package/src/shell/agent-workspace-fullscreen.ts +5 -0
  143. package/src/shell/terminal-focus-mode.ts +120 -0
  144. package/src/shell/ui-openers.ts +13 -4
  145. package/src/tools/agent-harness-autonomy-intake.ts +5 -5
  146. package/src/tools/agent-harness-autonomy-queue.ts +1 -1
  147. package/src/tools/agent-harness-background-processes.ts +2 -1
  148. package/src/tools/agent-harness-metadata.ts +16 -8
  149. package/src/tools/agent-harness-operator-methods.ts +44 -8
  150. package/src/tools/agent-harness-personal-ops-discovery.ts +57 -10
  151. package/src/tools/agent-harness-personal-ops-lanes.ts +17 -5
  152. package/src/tools/agent-harness-personal-ops-operations.ts +7 -7
  153. package/src/tools/agent-harness-personal-ops-types.ts +6 -0
  154. package/src/tools/agent-harness-prompt-context.ts +26 -12
  155. package/src/tools/agent-harness-workspace-actions.ts +4 -0
  156. package/src/tools/agent-local-registry-args.ts +117 -0
  157. package/src/tools/agent-local-registry-memory.ts +227 -0
  158. package/src/tools/agent-local-registry-tool.ts +19 -237
  159. package/src/tools/agent-operator-briefing-tool.ts +2 -2
  160. package/src/tools/agent-operator-method-tool.ts +13 -0
  161. package/src/tools/agent-policy-explanation.ts +39 -4
  162. package/src/tools/agent-schedule-tool.ts +5 -5
  163. package/src/utils/terminal-width.ts +98 -1
  164. package/src/version.ts +1 -1
  165. package/src/cli/local-library-command.ts +0 -825
@@ -1,4 +1,4 @@
1
- import type { AgentWorkspaceActionResult, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
1
+ import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
2
  import { buildAgentWorkspaceAccessCommandEditorSubmission, isAgentWorkspaceAccessCommandSubmissionKind } from './agent-workspace-access-command-editor-submission.ts';
3
3
  import { buildAgentWorkspaceChannelCommandEditorSubmission, isAgentWorkspaceChannelCommandSubmissionKind } from './agent-workspace-channel-command-editor-submission.ts';
4
4
  import { buildAgentWorkspaceDelegationEditorSubmission, isAgentWorkspaceDelegationEditorKind } from './agent-workspace-delegation-editor-submission.ts';
@@ -17,73 +17,50 @@ import { buildAgentWorkspaceTaskCommandEditorSubmission, isAgentWorkspaceTaskCom
17
17
  import { buildAgentWorkspaceWorkPlanEditorSubmission, isAgentWorkspaceWorkPlanEditorKind } from './agent-workspace-workplan-editor-submission.ts';
18
18
  import { buildAgentWorkspaceProfileEditorSubmission, isAgentWorkspaceProfileEditorSubmissionKind } from './agent-workspace-profile-editor-submission.ts';
19
19
  import { quoteSlashCommandArg } from './slash-command-parser.ts';
20
+ import type { AgentWorkspaceCommandEditorSubmission, AgentWorkspaceCommandSubmissionHandler, AgentWorkspaceFieldReader } from './agent-workspace-command-editor-engine.ts';
21
+ import { buildCommandEditorSubmissionFromTable, dispatchCommandEditorSubmission, editorMessageSubmission, isAffirmative } from './agent-workspace-command-editor-engine.ts';
20
22
 
21
- type AgentWorkspaceFieldReader = (fieldId: string) => string;
23
+ export type AgentWorkspaceBasicCommandEditorSubmission = AgentWorkspaceCommandEditorSubmission;
22
24
 
23
- export type AgentWorkspaceBasicCommandEditorSubmission =
24
- | {
25
- readonly kind: 'editor';
26
- readonly editor: AgentWorkspaceLocalEditor;
27
- readonly status: string;
28
- readonly actionResult?: AgentWorkspaceActionResult;
29
- }
30
- | {
31
- readonly kind: 'dispatch';
32
- readonly command: string;
33
- readonly status: string;
34
- readonly actionResult: AgentWorkspaceActionResult;
35
- };
25
+ /** The kinds this module builds a submission for itself (the rest delegate to sibling submission modules). */
26
+ type AgentWorkspaceBasicOwnCommandEditorKind = Extract<
27
+ AgentWorkspaceEditorKind,
28
+ 'knowledge-file' | 'knowledge-urls' | 'knowledge-bookmarks' | 'knowledge-browser-history' | 'knowledge-connector-ingest' | 'knowledge-reindex' | 'tts-prompt' | 'image-input' | 'skill-bundle' | 'skill-discovery-import'
29
+ | 'support-bundle-export' | 'support-bundle-inspect' | 'support-bundle-import'
30
+ | 'subscription-inspect' | 'subscription-login-start' | 'subscription-login-finish' | 'subscription-logout'
31
+ | 'model-pin' | 'model-unpin'
32
+ | 'persona-discovery-import'
33
+ | 'routine-discovery-import'
34
+ | 'skill-standard-import'
35
+ | 'skill-standard-export'
36
+ >;
36
37
 
37
- function isAffirmative(value: string): boolean {
38
- return /^(y|yes|true)$/i.test(value.trim());
38
+ function unconfirmed(editor: AgentWorkspaceLocalEditor, message: string, status: string): AgentWorkspaceCommandEditorSubmission {
39
+ return editorMessageSubmission(editor, message, status);
39
40
  }
40
41
 
41
- export function buildAgentWorkspaceBasicCommandEditorSubmission(
42
- editor: AgentWorkspaceLocalEditor,
43
- readField: AgentWorkspaceFieldReader,
44
- commandDispatchAvailable: boolean,
45
- ): AgentWorkspaceBasicCommandEditorSubmission {
46
- if (!commandDispatchAvailable) {
47
- return {
48
- kind: 'editor',
49
- editor: { ...editor, message: 'Command dispatch is unavailable; this action cannot run from this workspace.' },
50
- status: 'Command dispatch unavailable.',
51
- actionResult: {
52
- kind: 'error',
53
- title: 'Command dispatch unavailable',
54
- detail: 'The Agent workspace cannot hand this action to the shell-owned command router.',
55
- },
56
- };
57
- }
58
- if (editor.kind === 'knowledge-bookmarks') {
42
+ /**
43
+ * The submission data table for the kinds this module builds itself (delegate-task and
44
+ * workplan/notify/secret/profile kinds keep dispatching to their own sibling submission
45
+ * modules below, unchanged). W4-H2: split out of the single ~570-line
46
+ * `buildAgentWorkspaceBasicCommandEditorSubmission` if-chain, mirroring the
47
+ * construction-side split in agent-workspace-basic-command-editors.ts.
48
+ */
49
+ const BASIC_OWN_COMMAND_SUBMISSION_HANDLERS: Readonly<Record<AgentWorkspaceBasicOwnCommandEditorKind, AgentWorkspaceCommandSubmissionHandler>> = {
50
+ 'knowledge-bookmarks': (editor, readField) => {
59
51
  if (!isAffirmative(readField('confirm'))) {
60
- return {
61
- kind: 'editor',
62
- editor: { ...editor, message: 'Bookmark import not confirmed. Type yes, then press Enter.' },
63
- status: 'Agent Knowledge bookmark import not confirmed.',
64
- };
52
+ return unconfirmed(editor, 'Bookmark import not confirmed. Type yes, then press Enter.', 'Agent Knowledge bookmark import not confirmed.');
65
53
  }
66
- const command = `/knowledge import-bookmarks ${quoteSlashCommandArg(readField('path'))} --yes`;
67
- return {
68
- kind: 'dispatch',
69
- command,
70
- status: 'Opening Agent Knowledge bookmark import.',
71
- actionResult: {
72
- kind: 'dispatched',
73
- title: 'Opening Agent Knowledge bookmark import',
74
- detail: 'The workspace handed a confirmed bookmark import command to the shell-owned command router.',
75
- command,
76
- safety: 'safe',
77
- },
78
- };
79
- }
80
- if (editor.kind === 'knowledge-file') {
54
+ return dispatchCommandEditorSubmission(
55
+ `/knowledge import-bookmarks ${quoteSlashCommandArg(readField('path'))} --yes`,
56
+ 'Opening Agent Knowledge bookmark import',
57
+ 'The workspace handed a confirmed bookmark import command to the shell-owned command router.',
58
+ 'safe',
59
+ );
60
+ },
61
+ 'knowledge-file': (editor, readField) => {
81
62
  if (!isAffirmative(readField('confirm'))) {
82
- return {
83
- kind: 'editor',
84
- editor: { ...editor, message: 'File ingest not confirmed. Type yes, then press Enter.' },
85
- status: 'Agent Knowledge file ingest not confirmed.',
86
- };
63
+ return unconfirmed(editor, 'File ingest not confirmed. Type yes, then press Enter.', 'Agent Knowledge file ingest not confirmed.');
87
64
  }
88
65
  const parts = ['/knowledge', 'ingest-file', quoteSlashCommandArg(readField('path'))];
89
66
  const title = readField('title');
@@ -93,52 +70,30 @@ export function buildAgentWorkspaceBasicCommandEditorSubmission(
93
70
  if (tags.length > 0) parts.push('--tags', quoteSlashCommandArg(tags));
94
71
  if (folder.length > 0) parts.push('--folder', quoteSlashCommandArg(folder));
95
72
  parts.push('--yes');
96
- const command = parts.join(' ');
97
- return {
98
- kind: 'dispatch',
99
- command,
100
- status: 'Opening Agent Knowledge file ingest.',
101
- actionResult: {
102
- kind: 'dispatched',
103
- title: 'Opening Agent Knowledge file ingest',
104
- detail: 'The workspace handed a confirmed file ingest command to the shell-owned command router.',
105
- command,
106
- safety: 'safe',
107
- },
108
- };
109
- }
110
- if (editor.kind === 'knowledge-urls') {
73
+ return dispatchCommandEditorSubmission(
74
+ parts.join(' '),
75
+ 'Opening Agent Knowledge file ingest',
76
+ 'The workspace handed a confirmed file ingest command to the shell-owned command router.',
77
+ 'safe',
78
+ );
79
+ },
80
+ 'knowledge-urls': (editor, readField) => {
111
81
  if (!isAffirmative(readField('confirm'))) {
112
- return {
113
- kind: 'editor',
114
- editor: { ...editor, message: 'URL list import not confirmed. Type yes, then press Enter.' },
115
- status: 'Agent Knowledge URL list import not confirmed.',
116
- };
82
+ return unconfirmed(editor, 'URL list import not confirmed. Type yes, then press Enter.', 'Agent Knowledge URL list import not confirmed.');
117
83
  }
118
84
  const parts = ['/knowledge', 'import-urls', quoteSlashCommandArg(readField('path'))];
119
85
  if (isAffirmative(readField('allowPrivateHosts'))) parts.push('--allow-private-hosts');
120
86
  parts.push('--yes');
121
- const command = parts.join(' ');
122
- return {
123
- kind: 'dispatch',
124
- command,
125
- status: 'Opening Agent Knowledge URL list import.',
126
- actionResult: {
127
- kind: 'dispatched',
128
- title: 'Opening Agent Knowledge URL list import',
129
- detail: 'The workspace handed a confirmed URL list import command to the shell-owned command router.',
130
- command,
131
- safety: 'safe',
132
- },
133
- };
134
- }
135
- if (editor.kind === 'knowledge-browser-history') {
87
+ return dispatchCommandEditorSubmission(
88
+ parts.join(' '),
89
+ 'Opening Agent Knowledge URL list import',
90
+ 'The workspace handed a confirmed URL list import command to the shell-owned command router.',
91
+ 'safe',
92
+ );
93
+ },
94
+ 'knowledge-browser-history': (editor, readField) => {
136
95
  if (!isAffirmative(readField('confirm'))) {
137
- return {
138
- kind: 'editor',
139
- editor: { ...editor, message: 'Browser history import not confirmed. Type yes, then press Enter.' },
140
- status: 'Agent Knowledge browser history import not confirmed.',
141
- };
96
+ return unconfirmed(editor, 'Browser history import not confirmed. Type yes, then press Enter.', 'Agent Knowledge browser history import not confirmed.');
142
97
  }
143
98
  const parts = ['/knowledge', 'import-browser-history'];
144
99
  const browsers = readField('browsers');
@@ -150,27 +105,16 @@ export function buildAgentWorkspaceBasicCommandEditorSubmission(
150
105
  if (limit.length > 0) parts.push('--limit', quoteSlashCommandArg(limit));
151
106
  if (sinceDays.length > 0) parts.push('--since-days', quoteSlashCommandArg(sinceDays));
152
107
  parts.push('--yes');
153
- const command = parts.join(' ');
154
- return {
155
- kind: 'dispatch',
156
- command,
157
- status: 'Opening Agent Knowledge browser history import.',
158
- actionResult: {
159
- kind: 'dispatched',
160
- title: 'Opening Agent Knowledge browser history import',
161
- detail: 'The workspace handed a confirmed browser-history import command to the shell-owned command router.',
162
- command,
163
- safety: 'safe',
164
- },
165
- };
166
- }
167
- if (editor.kind === 'knowledge-connector-ingest') {
108
+ return dispatchCommandEditorSubmission(
109
+ parts.join(' '),
110
+ 'Opening Agent Knowledge browser history import',
111
+ 'The workspace handed a confirmed browser-history import command to the shell-owned command router.',
112
+ 'safe',
113
+ );
114
+ },
115
+ 'knowledge-connector-ingest': (editor, readField) => {
168
116
  if (!isAffirmative(readField('confirm'))) {
169
- return {
170
- kind: 'editor',
171
- editor: { ...editor, message: 'Connector ingest not confirmed. Type yes, then press Enter.' },
172
- status: 'Agent Knowledge connector ingest not confirmed.',
173
- };
117
+ return unconfirmed(editor, 'Connector ingest not confirmed. Type yes, then press Enter.', 'Agent Knowledge connector ingest not confirmed.');
174
118
  }
175
119
  const connectorId = readField('connectorId');
176
120
  const input = readField('input');
@@ -182,39 +126,233 @@ export function buildAgentWorkspaceBasicCommandEditorSubmission(
182
126
  if (content.length > 0) parts.push('--content', quoteSlashCommandArg(content));
183
127
  if (isAffirmative(readField('allowPrivateHosts'))) parts.push('--allow-private-hosts');
184
128
  parts.push('--yes');
185
- const command = parts.join(' ');
186
- return {
187
- kind: 'dispatch',
129
+ return dispatchCommandEditorSubmission(
130
+ parts.join(' '),
131
+ 'Opening Agent Knowledge connector ingest',
132
+ 'The workspace handed a confirmed connector ingest command to the shell-owned command router.',
133
+ 'safe',
134
+ );
135
+ },
136
+ 'knowledge-reindex': (editor, readField) => {
137
+ if (!isAffirmative(readField('confirm'))) {
138
+ return unconfirmed(editor, 'Agent Knowledge reindex not confirmed. Type yes, then press Enter.', 'Agent Knowledge reindex not confirmed.');
139
+ }
140
+ return dispatchCommandEditorSubmission(
141
+ '/knowledge reindex --yes',
142
+ 'Opening Agent Knowledge reindex',
143
+ 'The workspace handed a confirmed reindex command to the shell-owned command router.',
144
+ 'safe',
145
+ );
146
+ },
147
+ 'tts-prompt': (_editor, readField) => dispatchCommandEditorSubmission(
148
+ `/tts ${quoteSlashCommandArg(readField('prompt'))}`,
149
+ 'Opening spoken assistant prompt',
150
+ 'The workspace handed a spoken prompt to the shell-owned command router.',
151
+ 'safe',
152
+ ),
153
+ 'image-input': (_editor, readField) => {
154
+ const prompt = readField('prompt');
155
+ const command = prompt.length > 0
156
+ ? `/image ${quoteSlashCommandArg(readField('path'))} ${quoteSlashCommandArg(prompt)}`
157
+ : `/image ${quoteSlashCommandArg(readField('path'))}`;
158
+ return dispatchCommandEditorSubmission(
188
159
  command,
189
- status: 'Opening Agent Knowledge connector ingest.',
190
- actionResult: {
191
- kind: 'dispatched',
192
- title: 'Opening Agent Knowledge connector ingest',
193
- detail: 'The workspace handed a confirmed connector ingest command to the shell-owned command router.',
194
- command,
195
- safety: 'safe',
196
- },
197
- };
198
- }
199
- if (editor.kind === 'knowledge-reindex') {
160
+ 'Opening image input',
161
+ 'The workspace handed an image attachment command to the shell-owned command router.',
162
+ 'safe',
163
+ );
164
+ },
165
+ 'model-pin': (editor, readField) => modelPinUnpin(editor, readField),
166
+ 'model-unpin': (editor, readField) => modelPinUnpin(editor, readField),
167
+ 'support-bundle-export': (editor, readField) => {
168
+ if (!isAffirmative(readField('confirm'))) {
169
+ return unconfirmed(editor, 'Agent support bundle export not confirmed. Type yes, then press Enter.', 'Agent support bundle export not confirmed.');
170
+ }
171
+ return dispatchCommandEditorSubmission(
172
+ `/bundle export ${quoteSlashCommandArg(readField('path'))} --yes`,
173
+ 'Opening Agent support bundle export',
174
+ 'The workspace handed a confirmed support bundle export command to the shell-owned command router.',
175
+ 'safe',
176
+ );
177
+ },
178
+ 'support-bundle-inspect': (_editor, readField) => dispatchCommandEditorSubmission(
179
+ `/bundle inspect ${quoteSlashCommandArg(readField('path'))}`,
180
+ 'Opening Agent support bundle inspection',
181
+ 'The workspace handed a support bundle inspect command to the shell-owned command router.',
182
+ 'read-only',
183
+ ),
184
+ 'support-bundle-import': (editor, readField) => {
185
+ if (!isAffirmative(readField('confirm'))) {
186
+ return unconfirmed(editor, 'Agent support bundle import not confirmed. Type yes, then press Enter.', 'Agent support bundle import not confirmed.');
187
+ }
188
+ return dispatchCommandEditorSubmission(
189
+ `/bundle import ${quoteSlashCommandArg(readField('path'))} --yes`,
190
+ 'Opening Agent support bundle import',
191
+ 'The workspace handed a confirmed support bundle import command to the shell-owned command router.',
192
+ 'safe',
193
+ );
194
+ },
195
+ 'subscription-inspect': (_editor, readField) => dispatchCommandEditorSubmission(
196
+ `/subscription inspect ${quoteSlashCommandArg(readField('provider'))}`,
197
+ 'Opening provider subscription inspection',
198
+ 'The workspace handed a read-only provider subscription inspection command to the shell-owned command router.',
199
+ 'read-only',
200
+ ),
201
+ 'subscription-login-start': (editor, readField) => {
202
+ if (!isAffirmative(readField('confirm'))) {
203
+ return unconfirmed(editor, 'Provider subscription login start not confirmed. Type yes, then press Enter.', 'Provider subscription login start not confirmed.');
204
+ }
205
+ const parts = [
206
+ '/subscription',
207
+ 'login',
208
+ quoteSlashCommandArg(readField('provider')),
209
+ 'start',
210
+ ];
211
+ if (!isAffirmative(readField('openBrowser'))) parts.push('--no-browser');
212
+ parts.push('--manual');
213
+ parts.push('--yes');
214
+ return dispatchCommandEditorSubmission(
215
+ parts.join(' '),
216
+ 'Opening provider subscription login start',
217
+ 'The workspace handed a confirmed subscription-login start command to the shell-owned command router.',
218
+ 'safe',
219
+ );
220
+ },
221
+ 'subscription-login-finish': (editor, readField) => {
222
+ if (!isAffirmative(readField('confirm'))) {
223
+ return unconfirmed(editor, 'Provider subscription login finish not confirmed. Type yes, then press Enter.', 'Provider subscription login finish not confirmed.');
224
+ }
225
+ return dispatchCommandEditorSubmission(
226
+ `/subscription login ${quoteSlashCommandArg(readField('provider'))} finish ${quoteSlashCommandArg(readField('code'))} --yes`,
227
+ 'Opening provider subscription login finish',
228
+ 'The workspace handed a confirmed subscription-login finish command to the shell-owned command router.',
229
+ 'safe',
230
+ );
231
+ },
232
+ 'subscription-logout': (editor, readField) => {
233
+ if (!isAffirmative(readField('confirm'))) {
234
+ return unconfirmed(editor, 'Provider subscription logout not confirmed. Type yes, then press Enter.', 'Provider subscription logout not confirmed.');
235
+ }
236
+ return dispatchCommandEditorSubmission(
237
+ `/subscription logout ${quoteSlashCommandArg(readField('provider'))} --yes`,
238
+ 'Opening provider subscription logout',
239
+ 'The workspace handed a confirmed provider subscription logout command to the shell-owned command router.',
240
+ 'safe',
241
+ );
242
+ },
243
+ 'skill-discovery-import': (editor, readField) => {
244
+ if (!isAffirmative(readField('confirm'))) {
245
+ return unconfirmed(editor, 'Discovered skill import not confirmed. Type yes, then press Enter.', 'Agent skill import not confirmed.');
246
+ }
247
+ const parts = ['/skills', 'import-discovered', quoteSlashCommandArg(readField('name'))];
248
+ if (isAffirmative(readField('enabled'))) parts.push('--enabled');
249
+ parts.push('--yes');
250
+ return dispatchCommandEditorSubmission(
251
+ parts.join(' '),
252
+ 'Opening discovered skill import',
253
+ 'The workspace handed a confirmed local skill import command to the shell-owned command router.',
254
+ 'safe',
255
+ );
256
+ },
257
+ 'persona-discovery-import': (editor, readField) => {
258
+ if (!isAffirmative(readField('confirm'))) {
259
+ return unconfirmed(editor, 'Discovered persona import not confirmed. Type yes, then press Enter.', 'Agent persona import not confirmed.');
260
+ }
261
+ const parts = ['/personas', 'import-discovered', quoteSlashCommandArg(readField('name'))];
262
+ if (isAffirmative(readField('use'))) parts.push('--use');
263
+ parts.push('--yes');
264
+ return dispatchCommandEditorSubmission(
265
+ parts.join(' '),
266
+ 'Opening discovered persona import',
267
+ 'The workspace handed a confirmed local persona import command to the shell-owned command router.',
268
+ 'safe',
269
+ );
270
+ },
271
+ 'skill-standard-import': (editor, readField) => {
272
+ if (!isAffirmative(readField('confirm'))) {
273
+ return unconfirmed(editor, 'Shared skill import not confirmed. Type yes, then press Enter.', 'Shared skill import not confirmed.');
274
+ }
275
+ const parts = ['/skills', 'import-standard', quoteSlashCommandArg(readField('path')), '--yes'];
276
+ return dispatchCommandEditorSubmission(
277
+ parts.join(' '),
278
+ 'Opening shared skill import',
279
+ 'The workspace handed a confirmed shared skill import command to the shell-owned command router.',
280
+ 'safe',
281
+ );
282
+ },
283
+ 'skill-standard-export': (editor, readField) => {
284
+ if (!isAffirmative(readField('confirm'))) {
285
+ return unconfirmed(editor, 'Skill export not confirmed. Type yes, then press Enter.', 'Skill export not confirmed.');
286
+ }
287
+ const parts = ['/skills', 'export-standard', quoteSlashCommandArg(readField('id')), quoteSlashCommandArg(readField('dest')), '--yes'];
288
+ return dispatchCommandEditorSubmission(
289
+ parts.join(' '),
290
+ 'Opening skill export',
291
+ 'The workspace handed a confirmed skill export command to the shell-owned command router.',
292
+ 'safe',
293
+ );
294
+ },
295
+ 'routine-discovery-import': (editor, readField) => {
200
296
  if (!isAffirmative(readField('confirm'))) {
201
- return {
202
- kind: 'editor',
203
- editor: { ...editor, message: 'Agent Knowledge reindex not confirmed. Type yes, then press Enter.' },
204
- status: 'Agent Knowledge reindex not confirmed.',
205
- };
297
+ return unconfirmed(editor, 'Discovered routine import not confirmed. Type yes, then press Enter.', 'Agent routine import not confirmed.');
206
298
  }
207
- const command = '/knowledge reindex --yes';
299
+ const parts = ['/routines', 'import-discovered', quoteSlashCommandArg(readField('name'))];
300
+ if (isAffirmative(readField('enabled'))) parts.push('--enabled');
301
+ parts.push('--yes');
302
+ return dispatchCommandEditorSubmission(
303
+ parts.join(' '),
304
+ 'Opening discovered routine import',
305
+ 'The workspace handed a confirmed local routine import command to the shell-owned command router.',
306
+ 'safe',
307
+ );
308
+ },
309
+ 'skill-bundle': (_editor, readField) => skillBundleCreate(_editor, readField),
310
+ };
311
+
312
+ function modelPinUnpin(editor: AgentWorkspaceLocalEditor, readField: AgentWorkspaceFieldReader): AgentWorkspaceCommandEditorSubmission {
313
+ const pinning = editor.kind === 'model-pin';
314
+ const command = `/${pinning ? 'pin' : 'unpin'} ${quoteSlashCommandArg(readField('model'))}`;
315
+ return dispatchCommandEditorSubmission(
316
+ command,
317
+ pinning ? 'Opening model pin action' : 'Opening model unpin action',
318
+ 'The workspace handed model favorites maintenance to the shell-owned command router.',
319
+ 'safe',
320
+ );
321
+ }
322
+
323
+ function skillBundleCreate(_editor: AgentWorkspaceLocalEditor, readField: AgentWorkspaceFieldReader): AgentWorkspaceCommandEditorSubmission {
324
+ const commandParts = [
325
+ '/skills bundle create',
326
+ '--name',
327
+ quoteSlashCommandArg(readField('name')),
328
+ '--description',
329
+ quoteSlashCommandArg(readField('description')),
330
+ '--skills',
331
+ quoteSlashCommandArg(readField('skills')),
332
+ ];
333
+ if (isAffirmative(readField('enabled'))) commandParts.push('--enabled');
334
+ return dispatchCommandEditorSubmission(
335
+ commandParts.join(' '),
336
+ 'Opening skill bundle creation',
337
+ 'The workspace handed a concrete local skill bundle command to the shell-owned command router.',
338
+ 'safe',
339
+ );
340
+ }
341
+
342
+ export function buildAgentWorkspaceBasicCommandEditorSubmission(
343
+ editor: AgentWorkspaceLocalEditor,
344
+ readField: AgentWorkspaceFieldReader,
345
+ commandDispatchAvailable: boolean,
346
+ ): AgentWorkspaceCommandEditorSubmission {
347
+ if (!commandDispatchAvailable) {
208
348
  return {
209
- kind: 'dispatch',
210
- command,
211
- status: 'Opening Agent Knowledge reindex.',
349
+ kind: 'editor',
350
+ editor: { ...editor, message: 'Command dispatch is unavailable; this action cannot run from this workspace.' },
351
+ status: 'Command dispatch unavailable.',
212
352
  actionResult: {
213
- kind: 'dispatched',
214
- title: 'Opening Agent Knowledge reindex',
215
- detail: 'The workspace handed a confirmed reindex command to the shell-owned command router.',
216
- command,
217
- safety: 'safe',
353
+ kind: 'error',
354
+ title: 'Command dispatch unavailable',
355
+ detail: 'The Agent workspace cannot hand this action to the shell-owned command router.',
218
356
  },
219
357
  };
220
358
  }
@@ -258,374 +396,15 @@ export function buildAgentWorkspaceBasicCommandEditorSubmission(
258
396
  if (isAgentWorkspaceSecretEditorKind(editor.kind)) {
259
397
  return buildAgentWorkspaceSecretEditorSubmission(editor, readField);
260
398
  }
261
- if (editor.kind === 'tts-prompt') {
262
- const command = `/tts ${quoteSlashCommandArg(readField('prompt'))}`;
263
- return {
264
- kind: 'dispatch',
265
- command,
266
- status: 'Opening spoken assistant prompt.',
267
- actionResult: {
268
- kind: 'dispatched',
269
- title: 'Opening spoken assistant prompt',
270
- detail: 'The workspace handed a spoken prompt to the shell-owned command router.',
271
- command,
272
- safety: 'safe',
273
- },
274
- };
275
- }
276
- if (editor.kind === 'image-input') {
277
- const prompt = readField('prompt');
278
- const command = prompt.length > 0
279
- ? `/image ${quoteSlashCommandArg(readField('path'))} ${quoteSlashCommandArg(prompt)}`
280
- : `/image ${quoteSlashCommandArg(readField('path'))}`;
281
- return {
282
- kind: 'dispatch',
283
- command,
284
- status: 'Opening image input.',
285
- actionResult: {
286
- kind: 'dispatched',
287
- title: 'Opening image input',
288
- detail: 'The workspace handed an image attachment command to the shell-owned command router.',
289
- command,
290
- safety: 'safe',
291
- },
292
- };
293
- }
294
- if (editor.kind === 'model-pin' || editor.kind === 'model-unpin') {
295
- const pinning = editor.kind === 'model-pin';
296
- const command = `/${pinning ? 'pin' : 'unpin'} ${quoteSlashCommandArg(readField('model'))}`;
297
- return {
298
- kind: 'dispatch',
299
- command,
300
- status: pinning ? 'Opening model pin action.' : 'Opening model unpin action.',
301
- actionResult: {
302
- kind: 'dispatched',
303
- title: pinning ? 'Opening model pin action' : 'Opening model unpin action',
304
- detail: 'The workspace handed model favorites maintenance to the shell-owned command router.',
305
- command,
306
- safety: 'safe',
307
- },
308
- };
309
- }
310
399
  if (isAgentWorkspaceProfileEditorSubmissionKind(editor.kind)) {
311
400
  return buildAgentWorkspaceProfileEditorSubmission(editor, readField);
312
401
  }
313
- if (editor.kind === 'support-bundle-export') {
314
- if (!isAffirmative(readField('confirm'))) {
315
- return {
316
- kind: 'editor',
317
- editor: { ...editor, message: 'Agent support bundle export not confirmed. Type yes, then press Enter.' },
318
- status: 'Agent support bundle export not confirmed.',
319
- };
320
- }
321
- const command = `/bundle export ${quoteSlashCommandArg(readField('path'))} --yes`;
322
- return {
323
- kind: 'dispatch',
324
- command,
325
- status: 'Opening Agent support bundle export.',
326
- actionResult: {
327
- kind: 'dispatched',
328
- title: 'Opening Agent support bundle export',
329
- detail: 'The workspace handed a confirmed support bundle export command to the shell-owned command router.',
330
- command,
331
- safety: 'safe',
332
- },
333
- };
334
- }
335
- if (editor.kind === 'support-bundle-inspect') {
336
- const command = `/bundle inspect ${quoteSlashCommandArg(readField('path'))}`;
337
- return {
338
- kind: 'dispatch',
339
- command,
340
- status: 'Opening Agent support bundle inspection.',
341
- actionResult: {
342
- kind: 'dispatched',
343
- title: 'Opening Agent support bundle inspection',
344
- detail: 'The workspace handed a support bundle inspect command to the shell-owned command router.',
345
- command,
346
- safety: 'read-only',
347
- },
348
- };
349
- }
350
- if (editor.kind === 'support-bundle-import') {
351
- if (!isAffirmative(readField('confirm'))) {
352
- return {
353
- kind: 'editor',
354
- editor: { ...editor, message: 'Agent support bundle import not confirmed. Type yes, then press Enter.' },
355
- status: 'Agent support bundle import not confirmed.',
356
- };
357
- }
358
- const command = `/bundle import ${quoteSlashCommandArg(readField('path'))} --yes`;
359
- return {
360
- kind: 'dispatch',
361
- command,
362
- status: 'Opening Agent support bundle import.',
363
- actionResult: {
364
- kind: 'dispatched',
365
- title: 'Opening Agent support bundle import',
366
- detail: 'The workspace handed a confirmed support bundle import command to the shell-owned command router.',
367
- command,
368
- safety: 'safe',
369
- },
370
- };
371
- }
372
- if (editor.kind === 'subscription-inspect') {
373
- const command = `/subscription inspect ${quoteSlashCommandArg(readField('provider'))}`;
374
- return {
375
- kind: 'dispatch',
376
- command,
377
- status: 'Opening provider subscription inspection.',
378
- actionResult: {
379
- kind: 'dispatched',
380
- title: 'Opening provider subscription inspection',
381
- detail: 'The workspace handed a read-only provider subscription inspection command to the shell-owned command router.',
382
- command,
383
- safety: 'read-only',
384
- },
385
- };
386
- }
387
- if (editor.kind === 'subscription-login-start') {
388
- if (!isAffirmative(readField('confirm'))) {
389
- return {
390
- kind: 'editor',
391
- editor: { ...editor, message: 'Provider subscription login start not confirmed. Type yes, then press Enter.' },
392
- status: 'Provider subscription login start not confirmed.',
393
- };
394
- }
395
- const parts = [
396
- '/subscription',
397
- 'login',
398
- quoteSlashCommandArg(readField('provider')),
399
- 'start',
400
- ];
401
- if (!isAffirmative(readField('openBrowser'))) parts.push('--no-browser');
402
- parts.push('--manual');
403
- parts.push('--yes');
404
- const command = parts.join(' ');
405
- return {
406
- kind: 'dispatch',
407
- command,
408
- status: 'Opening provider subscription login start.',
409
- actionResult: {
410
- kind: 'dispatched',
411
- title: 'Opening provider subscription login start',
412
- detail: 'The workspace handed a confirmed subscription-login start command to the shell-owned command router.',
413
- command,
414
- safety: 'safe',
415
- },
416
- };
417
- }
418
- if (editor.kind === 'subscription-login-finish') {
419
- if (!isAffirmative(readField('confirm'))) {
420
- return {
421
- kind: 'editor',
422
- editor: { ...editor, message: 'Provider subscription login finish not confirmed. Type yes, then press Enter.' },
423
- status: 'Provider subscription login finish not confirmed.',
424
- };
425
- }
426
- const command = `/subscription login ${quoteSlashCommandArg(readField('provider'))} finish ${quoteSlashCommandArg(readField('code'))} --yes`;
427
- return {
428
- kind: 'dispatch',
429
- command,
430
- status: 'Opening provider subscription login finish.',
431
- actionResult: {
432
- kind: 'dispatched',
433
- title: 'Opening provider subscription login finish',
434
- detail: 'The workspace handed a confirmed subscription-login finish command to the shell-owned command router.',
435
- command,
436
- safety: 'safe',
437
- },
438
- };
439
- }
440
- if (editor.kind === 'subscription-logout') {
441
- if (!isAffirmative(readField('confirm'))) {
442
- return {
443
- kind: 'editor',
444
- editor: { ...editor, message: 'Provider subscription logout not confirmed. Type yes, then press Enter.' },
445
- status: 'Provider subscription logout not confirmed.',
446
- };
447
- }
448
- const command = `/subscription logout ${quoteSlashCommandArg(readField('provider'))} --yes`;
449
- return {
450
- kind: 'dispatch',
451
- command,
452
- status: 'Opening provider subscription logout.',
453
- actionResult: {
454
- kind: 'dispatched',
455
- title: 'Opening provider subscription logout',
456
- detail: 'The workspace handed a confirmed provider subscription logout command to the shell-owned command router.',
457
- command,
458
- safety: 'safe',
459
- },
460
- };
461
- }
462
402
  if (isAgentWorkspaceDelegationEditorKind(editor.kind)) return buildAgentWorkspaceDelegationEditorSubmission(editor, readField);
463
403
  if (isAgentWorkspaceWorkPlanEditorKind(editor.kind)) return buildAgentWorkspaceWorkPlanEditorSubmission(editor, readField);
464
- if (editor.kind === 'skill-discovery-import') {
465
- if (!isAffirmative(readField('confirm'))) {
466
- return {
467
- kind: 'editor',
468
- editor: { ...editor, message: 'Discovered skill import not confirmed. Type yes, then press Enter.' },
469
- status: 'Agent skill import not confirmed.',
470
- };
471
- }
472
- const parts = [
473
- '/skills',
474
- 'import-discovered',
475
- quoteSlashCommandArg(readField('name')),
476
- ];
477
- if (isAffirmative(readField('enabled'))) parts.push('--enabled');
478
- parts.push('--yes');
479
- const command = parts.join(' ');
480
- return {
481
- kind: 'dispatch',
482
- command,
483
- status: 'Opening discovered skill import.',
484
- actionResult: {
485
- kind: 'dispatched',
486
- title: 'Opening discovered skill import',
487
- detail: 'The workspace handed a confirmed local skill import command to the shell-owned command router.',
488
- command,
489
- safety: 'safe',
490
- },
491
- };
492
- }
493
- if (editor.kind === 'persona-discovery-import') {
494
- if (!isAffirmative(readField('confirm'))) {
495
- return {
496
- kind: 'editor',
497
- editor: { ...editor, message: 'Discovered persona import not confirmed. Type yes, then press Enter.' },
498
- status: 'Agent persona import not confirmed.',
499
- };
500
- }
501
- const parts = [
502
- '/personas',
503
- 'import-discovered',
504
- quoteSlashCommandArg(readField('name')),
505
- ];
506
- if (isAffirmative(readField('use'))) parts.push('--use');
507
- parts.push('--yes');
508
- const command = parts.join(' ');
509
- return {
510
- kind: 'dispatch',
511
- command,
512
- status: 'Opening discovered persona import.',
513
- actionResult: {
514
- kind: 'dispatched',
515
- title: 'Opening discovered persona import',
516
- detail: 'The workspace handed a confirmed local persona import command to the shell-owned command router.',
517
- command,
518
- safety: 'safe',
519
- },
520
- };
521
- }
522
- if (editor.kind === 'skill-standard-import') {
523
- if (!isAffirmative(readField('confirm'))) {
524
- return {
525
- kind: 'editor',
526
- editor: { ...editor, message: 'Shared skill import not confirmed. Type yes, then press Enter.' },
527
- status: 'Shared skill import not confirmed.',
528
- };
529
- }
530
- const parts = [
531
- '/skills',
532
- 'import-standard',
533
- quoteSlashCommandArg(readField('path')),
534
- '--yes',
535
- ];
536
- const command = parts.join(' ');
537
- return {
538
- kind: 'dispatch',
539
- command,
540
- status: 'Opening shared skill import.',
541
- actionResult: {
542
- kind: 'dispatched',
543
- title: 'Opening shared skill import',
544
- detail: 'The workspace handed a confirmed shared skill import command to the shell-owned command router.',
545
- command,
546
- safety: 'safe',
547
- },
548
- };
549
- }
550
- if (editor.kind === 'skill-standard-export') {
551
- if (!isAffirmative(readField('confirm'))) {
552
- return {
553
- kind: 'editor',
554
- editor: { ...editor, message: 'Skill export not confirmed. Type yes, then press Enter.' },
555
- status: 'Skill export not confirmed.',
556
- };
557
- }
558
- const parts = [
559
- '/skills',
560
- 'export-standard',
561
- quoteSlashCommandArg(readField('id')),
562
- quoteSlashCommandArg(readField('dest')),
563
- '--yes',
564
- ];
565
- const command = parts.join(' ');
566
- return {
567
- kind: 'dispatch',
568
- command,
569
- status: 'Opening skill export.',
570
- actionResult: {
571
- kind: 'dispatched',
572
- title: 'Opening skill export',
573
- detail: 'The workspace handed a confirmed skill export command to the shell-owned command router.',
574
- command,
575
- safety: 'safe',
576
- },
577
- };
578
- }
579
- if (editor.kind === 'routine-discovery-import') {
580
- if (!isAffirmative(readField('confirm'))) {
581
- return {
582
- kind: 'editor',
583
- editor: { ...editor, message: 'Discovered routine import not confirmed. Type yes, then press Enter.' },
584
- status: 'Agent routine import not confirmed.',
585
- };
586
- }
587
- const parts = [
588
- '/routines',
589
- 'import-discovered',
590
- quoteSlashCommandArg(readField('name')),
591
- ];
592
- if (isAffirmative(readField('enabled'))) parts.push('--enabled');
593
- parts.push('--yes');
594
- const command = parts.join(' ');
595
- return {
596
- kind: 'dispatch',
597
- command,
598
- status: 'Opening discovered routine import.',
599
- actionResult: {
600
- kind: 'dispatched',
601
- title: 'Opening discovered routine import',
602
- detail: 'The workspace handed a confirmed local routine import command to the shell-owned command router.',
603
- command,
604
- safety: 'safe',
605
- },
606
- };
607
- }
608
- const commandParts = [
609
- '/skills bundle create',
610
- '--name',
611
- quoteSlashCommandArg(readField('name')),
612
- '--description',
613
- quoteSlashCommandArg(readField('description')),
614
- '--skills',
615
- quoteSlashCommandArg(readField('skills')),
616
- ];
617
- if (isAffirmative(readField('enabled'))) commandParts.push('--enabled');
618
- const command = commandParts.join(' ');
619
- return {
620
- kind: 'dispatch',
621
- command,
622
- status: 'Opening skill bundle creation.',
623
- actionResult: {
624
- kind: 'dispatched',
625
- title: 'Opening skill bundle creation',
626
- detail: 'The workspace handed a concrete local skill bundle command to the shell-owned command router.',
627
- command,
628
- safety: 'safe',
629
- },
630
- };
404
+ return buildCommandEditorSubmissionFromTable(
405
+ editor.kind as AgentWorkspaceBasicOwnCommandEditorKind,
406
+ editor,
407
+ readField,
408
+ BASIC_OWN_COMMAND_SUBMISSION_HANDLERS,
409
+ );
631
410
  }