@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,6 @@
1
1
  import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+ import type { AgentWorkspaceEditorSpecEntry } from './agent-workspace-command-editor-engine.ts';
3
+ import { createAgentWorkspaceEditorFromTable } from './agent-workspace-command-editor-engine.ts';
2
4
 
3
5
  export type AgentWorkspaceMemoryCommandEditorKind = Extract<
4
6
  AgentWorkspaceEditorKind,
@@ -29,146 +31,115 @@ export function isAgentWorkspaceMemoryCommandEditorKind(kind: AgentWorkspaceEdit
29
31
  || kind === 'memory-vector-rebuild';
30
32
  }
31
33
 
32
- export function createAgentWorkspaceMemoryCommandEditor(kind: AgentWorkspaceMemoryCommandEditorKind): AgentWorkspaceLocalEditor {
33
- if (kind === 'memory-search') {
34
- return {
35
- kind,
36
- mode: 'create',
37
- title: 'Search Agent Memory',
38
- selectedFieldIndex: 0,
39
- message: 'Search Agent-local memory only. This does not query default knowledge or other product routes.',
40
- fields: [
41
- { id: 'query', label: 'Query', value: '', required: false, multiline: false, hint: 'Optional text query. Blank searches by filters.' },
42
- { id: 'scope', label: 'Scope', value: '', required: false, multiline: false, hint: 'Optional session, project, or team.' },
43
- { id: 'class', label: 'Class', value: '', required: false, multiline: false, hint: 'Optional fact, constraint, pattern, runbook, risk, etc.' },
44
- { id: 'limit', label: 'Limit', value: '', required: false, multiline: false, hint: 'Optional result limit.' },
45
- { id: 'semantic', label: 'Semantic', value: 'no', required: false, multiline: false, hint: 'yes/no. Uses the local vector index when available.' },
46
- ],
47
- };
48
- }
49
- if (kind === 'memory-get') {
50
- return {
51
- kind,
52
- mode: 'create',
53
- title: 'Show Agent Memory',
54
- selectedFieldIndex: 0,
55
- message: 'Show one Agent-local memory record with provenance and links.',
56
- fields: [
57
- { id: 'id', label: 'Memory id', value: '', required: true, multiline: false, hint: 'Existing Agent memory id.' },
58
- ],
59
- };
60
- }
61
- if (kind === 'memory-explain') {
62
- return {
63
- kind,
64
- mode: 'create',
65
- title: 'Explain Memory Selection',
66
- selectedFieldIndex: 0,
67
- message: 'Preview which reviewed Agent-local memory records would be selected for a task.',
68
- fields: [
69
- { id: 'task', label: 'Task', value: '', required: true, multiline: true, hint: 'Task description. Ctrl-J inserts a new line.' },
70
- { id: 'scopes', label: 'Scopes', value: '', required: false, multiline: false, hint: 'Optional comma-separated write scopes.' },
71
- ],
72
- };
73
- }
74
- if (kind === 'memory-promote') {
75
- return {
76
- kind,
77
- mode: 'update',
78
- title: 'Promote Agent Memory',
79
- selectedFieldIndex: 0,
80
- message: 'Promote one Agent-local memory record to another scope. Type yes on the final field to confirm.',
81
- fields: [
82
- { id: 'id', label: 'Memory id', value: '', required: true, multiline: false, hint: 'Existing Agent memory id.' },
83
- { id: 'scope', label: 'Scope', value: '', required: true, multiline: false, hint: 'session, project, or team.' },
84
- { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory promote with --yes.' },
85
- ],
86
- };
87
- }
88
- if (kind === 'memory-link') {
89
- return {
90
- kind,
91
- mode: 'update',
92
- title: 'Link Agent Memories',
93
- selectedFieldIndex: 0,
94
- message: 'Create one directed relation between two Agent-local memory records. Type yes on the final field to confirm.',
95
- fields: [
96
- { id: 'fromId', label: 'From memory id', value: '', required: true, multiline: false, hint: 'Source memory id.' },
97
- { id: 'toId', label: 'To memory id', value: '', required: true, multiline: false, hint: 'Target memory id.' },
98
- { id: 'relation', label: 'Relation', value: '', required: true, multiline: false, hint: 'Short relation label, such as supports, supersedes, or contradicts.' },
99
- { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory link with --yes.' },
100
- ],
101
- };
102
- }
103
- if (kind === 'memory-export') {
104
- return {
105
- kind,
106
- mode: 'create',
107
- title: 'Export Agent Memory Bundle',
108
- selectedFieldIndex: 0,
109
- message: 'Export Agent-local memory records and links to a reviewable JSON bundle. Type yes on the final field to confirm.',
110
- fields: [
111
- { id: 'path', label: 'Output path', value: 'agent-memory-bundle.json', required: true, multiline: false, hint: 'Workspace-relative JSON path to write.' },
112
- { id: 'scope', label: 'Scope', value: '', required: false, multiline: false, hint: 'Optional session, project, or team.' },
113
- { id: 'class', label: 'Class', value: '', required: false, multiline: false, hint: 'Optional fact, constraint, pattern, runbook, risk, etc.' },
114
- { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory export with --yes.' },
115
- ],
116
- };
117
- }
118
- if (kind === 'memory-import') {
119
- return {
120
- kind,
121
- mode: 'update',
122
- title: 'Import Agent Memory Bundle',
123
- selectedFieldIndex: 0,
124
- message: 'Import a reviewed Agent memory bundle into the Agent-local memory registry. Type yes on the final field to confirm.',
125
- fields: [
126
- { id: 'path', label: 'Bundle path', value: 'agent-memory-bundle.json', required: true, multiline: false, hint: 'Workspace-relative JSON bundle path.' },
127
- { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory import with --yes.' },
128
- ],
129
- };
130
- }
131
- if (kind === 'memory-handoff-export') {
132
- return {
133
- kind,
134
- mode: 'create',
135
- title: 'Export Memory Handoff',
136
- selectedFieldIndex: 0,
137
- message: 'Export a scoped Agent memory handoff bundle for review. Type yes on the final field to confirm.',
138
- fields: [
139
- { id: 'path', label: 'Output path', value: 'agent-memory-handoff.json', required: true, multiline: false, hint: 'Workspace-relative JSON path to write.' },
140
- { id: 'scope', label: 'Scope', value: 'team', required: false, multiline: false, hint: 'session, project, or team. Blank defaults to team.' },
141
- { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory handoff-export with --yes.' },
142
- ],
143
- };
144
- }
145
- if (kind === 'memory-handoff-inspect') {
146
- return {
147
- kind,
148
- mode: 'create',
149
- title: 'Inspect Memory Handoff',
150
- selectedFieldIndex: 0,
151
- message: 'Inspect a memory handoff bundle before importing it.',
152
- fields: [
153
- { id: 'path', label: 'Bundle path', value: 'agent-memory-handoff.json', required: true, multiline: false, hint: 'Workspace-relative JSON handoff bundle path.' },
154
- ],
155
- };
156
- }
157
- if (kind === 'memory-handoff-import') {
158
- return {
159
- kind,
160
- mode: 'update',
161
- title: 'Import Memory Handoff',
162
- selectedFieldIndex: 0,
163
- message: 'Import a reviewed memory handoff bundle into Agent-local memory. Type yes on the final field to confirm.',
164
- fields: [
165
- { id: 'path', label: 'Bundle path', value: 'agent-memory-handoff.json', required: true, multiline: false, hint: 'Workspace-relative JSON handoff bundle path.' },
166
- { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory handoff-import with --yes.' },
167
- ],
168
- };
169
- }
170
- return {
171
- kind,
34
+ const MEMORY_COMMAND_EDITOR_SPECS: Readonly<Record<AgentWorkspaceMemoryCommandEditorKind, AgentWorkspaceEditorSpecEntry<AgentWorkspaceMemoryCommandEditorKind>>> = {
35
+ 'memory-search': {
36
+ mode: 'create',
37
+ title: 'Search Agent Memory',
38
+ selectedFieldIndex: 0,
39
+ message: 'Search Agent-local memory only. This does not query default knowledge or other product routes.',
40
+ fields: [
41
+ { id: 'query', label: 'Query', value: '', required: false, multiline: false, hint: 'Optional text query. Blank searches by filters.' },
42
+ { id: 'scope', label: 'Scope', value: '', required: false, multiline: false, hint: 'Optional session, project, or team.' },
43
+ { id: 'class', label: 'Class', value: '', required: false, multiline: false, hint: 'Optional fact, constraint, pattern, runbook, risk, etc.' },
44
+ { id: 'limit', label: 'Limit', value: '', required: false, multiline: false, hint: 'Optional result limit.' },
45
+ { id: 'semantic', label: 'Semantic', value: 'no', required: false, multiline: false, hint: 'yes/no. Uses the local vector index when available.' },
46
+ ],
47
+ },
48
+ 'memory-get': {
49
+ mode: 'create',
50
+ title: 'Show Agent Memory',
51
+ selectedFieldIndex: 0,
52
+ message: 'Show one Agent-local memory record with provenance and links.',
53
+ fields: [
54
+ { id: 'id', label: 'Memory id', value: '', required: true, multiline: false, hint: 'Existing Agent memory id.' },
55
+ ],
56
+ },
57
+ 'memory-explain': {
58
+ mode: 'create',
59
+ title: 'Explain Memory Selection',
60
+ selectedFieldIndex: 0,
61
+ message: 'Preview which reviewed Agent-local memory records would be selected for a task.',
62
+ fields: [
63
+ { id: 'task', label: 'Task', value: '', required: true, multiline: true, hint: 'Task description. Ctrl-J inserts a new line.' },
64
+ { id: 'scopes', label: 'Scopes', value: '', required: false, multiline: false, hint: 'Optional comma-separated write scopes.' },
65
+ ],
66
+ },
67
+ 'memory-promote': {
68
+ mode: 'update',
69
+ title: 'Promote Agent Memory',
70
+ selectedFieldIndex: 0,
71
+ message: 'Promote one Agent-local memory record to another scope. Type yes on the final field to confirm.',
72
+ fields: [
73
+ { id: 'id', label: 'Memory id', value: '', required: true, multiline: false, hint: 'Existing Agent memory id.' },
74
+ { id: 'scope', label: 'Scope', value: '', required: true, multiline: false, hint: 'session, project, or team.' },
75
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory promote with --yes.' },
76
+ ],
77
+ },
78
+ 'memory-link': {
79
+ mode: 'update',
80
+ title: 'Link Agent Memories',
81
+ selectedFieldIndex: 0,
82
+ message: 'Create one directed relation between two Agent-local memory records. Type yes on the final field to confirm.',
83
+ fields: [
84
+ { id: 'fromId', label: 'From memory id', value: '', required: true, multiline: false, hint: 'Source memory id.' },
85
+ { id: 'toId', label: 'To memory id', value: '', required: true, multiline: false, hint: 'Target memory id.' },
86
+ { id: 'relation', label: 'Relation', value: '', required: true, multiline: false, hint: 'Short relation label, such as supports, supersedes, or contradicts.' },
87
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory link with --yes.' },
88
+ ],
89
+ },
90
+ 'memory-export': {
91
+ mode: 'create',
92
+ title: 'Export Agent Memory Bundle',
93
+ selectedFieldIndex: 0,
94
+ message: 'Export Agent-local memory records and links to a reviewable JSON bundle. Type yes on the final field to confirm.',
95
+ fields: [
96
+ { id: 'path', label: 'Output path', value: 'agent-memory-bundle.json', required: true, multiline: false, hint: 'Workspace-relative JSON path to write.' },
97
+ { id: 'scope', label: 'Scope', value: '', required: false, multiline: false, hint: 'Optional session, project, or team.' },
98
+ { id: 'class', label: 'Class', value: '', required: false, multiline: false, hint: 'Optional fact, constraint, pattern, runbook, risk, etc.' },
99
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory export with --yes.' },
100
+ ],
101
+ },
102
+ 'memory-import': {
103
+ mode: 'update',
104
+ title: 'Import Agent Memory Bundle',
105
+ selectedFieldIndex: 0,
106
+ message: 'Import a reviewed Agent memory bundle into the Agent-local memory registry. Type yes on the final field to confirm.',
107
+ fields: [
108
+ { id: 'path', label: 'Bundle path', value: 'agent-memory-bundle.json', required: true, multiline: false, hint: 'Workspace-relative JSON bundle path.' },
109
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory import with --yes.' },
110
+ ],
111
+ },
112
+ 'memory-handoff-export': {
113
+ mode: 'create',
114
+ title: 'Export Memory Handoff',
115
+ selectedFieldIndex: 0,
116
+ message: 'Export a scoped Agent memory handoff bundle for review. Type yes on the final field to confirm.',
117
+ fields: [
118
+ { id: 'path', label: 'Output path', value: 'agent-memory-handoff.json', required: true, multiline: false, hint: 'Workspace-relative JSON path to write.' },
119
+ { id: 'scope', label: 'Scope', value: 'team', required: false, multiline: false, hint: 'session, project, or team. Blank defaults to team.' },
120
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory handoff-export with --yes.' },
121
+ ],
122
+ },
123
+ 'memory-handoff-inspect': {
124
+ mode: 'create',
125
+ title: 'Inspect Memory Handoff',
126
+ selectedFieldIndex: 0,
127
+ message: 'Inspect a memory handoff bundle before importing it.',
128
+ fields: [
129
+ { id: 'path', label: 'Bundle path', value: 'agent-memory-handoff.json', required: true, multiline: false, hint: 'Workspace-relative JSON handoff bundle path.' },
130
+ ],
131
+ },
132
+ 'memory-handoff-import': {
133
+ mode: 'update',
134
+ title: 'Import Memory Handoff',
135
+ selectedFieldIndex: 0,
136
+ message: 'Import a reviewed memory handoff bundle into Agent-local memory. Type yes on the final field to confirm.',
137
+ fields: [
138
+ { id: 'path', label: 'Bundle path', value: 'agent-memory-handoff.json', required: true, multiline: false, hint: 'Workspace-relative JSON handoff bundle path.' },
139
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory handoff-import with --yes.' },
140
+ ],
141
+ },
142
+ 'memory-vector-rebuild': {
172
143
  mode: 'update',
173
144
  title: 'Rebuild Memory Vector Index',
174
145
  selectedFieldIndex: 0,
@@ -176,5 +147,9 @@ export function createAgentWorkspaceMemoryCommandEditor(kind: AgentWorkspaceMemo
176
147
  fields: [
177
148
  { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /memory vector rebuild.' },
178
149
  ],
179
- };
150
+ },
151
+ };
152
+
153
+ export function createAgentWorkspaceMemoryCommandEditor(kind: AgentWorkspaceMemoryCommandEditorKind): AgentWorkspaceLocalEditor {
154
+ return createAgentWorkspaceEditorFromTable(kind, MEMORY_COMMAND_EDITOR_SPECS);
180
155
  }
@@ -1,12 +1,14 @@
1
- import type { AgentWorkspaceActionResult, AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
1
+ import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
2
  import type { AgentWorkspaceOperationsCommandEditorKind } from './agent-workspace-operations-command-editors.ts';
3
3
  import { isAgentWorkspaceOperationsCommandEditorKind } from './agent-workspace-operations-command-editors.ts';
4
4
  import { quoteSlashCommandArg } from './slash-command-parser.ts';
5
+ import type { AgentWorkspaceCommandEditorSubmission, AgentWorkspaceCommandSubmissionHandler, AgentWorkspaceFieldReader } from './agent-workspace-command-editor-engine.ts';
6
+ import { buildCommandEditorSubmissionFromTable, dispatchCommandEditorSubmission, editorMessageSubmission, isAffirmative } from './agent-workspace-command-editor-engine.ts';
5
7
 
6
- type AgentWorkspaceFieldReader = (fieldId: string) => string;
8
+ export type AgentWorkspaceOperationsCommandEditorSubmission = AgentWorkspaceCommandEditorSubmission;
7
9
 
8
- function isAffirmative(value: string): boolean {
9
- return /^(y|yes|true)$/i.test(value.trim());
10
+ function unconfirmed(editor: AgentWorkspaceLocalEditor, message: string): AgentWorkspaceCommandEditorSubmission {
11
+ return editorMessageSubmission(editor, message);
10
12
  }
11
13
 
12
14
  function optionalNoteArgs(value: string): string {
@@ -25,149 +27,57 @@ function optionalCommandArg(flag: string, value: string): string {
25
27
  return trimmed ? ` ${flag} ${quoteSlashCommandArg(trimmed)}` : '';
26
28
  }
27
29
 
28
- function unconfirmed(editor: AgentWorkspaceLocalEditor, message: string): AgentWorkspaceOperationsCommandEditorSubmission {
29
- return {
30
- kind: 'editor',
31
- editor: { ...editor, message },
32
- status: message,
33
- };
34
- }
35
-
36
- export type AgentWorkspaceOperationsCommandEditorSubmission =
37
- | {
38
- readonly kind: 'editor';
39
- readonly editor: AgentWorkspaceLocalEditor;
40
- readonly status: string;
41
- readonly actionResult?: AgentWorkspaceActionResult;
42
- }
43
- | {
44
- readonly kind: 'dispatch';
45
- readonly command: string;
46
- readonly status: string;
47
- readonly actionResult: AgentWorkspaceActionResult;
48
- };
49
-
50
30
  export function isAgentWorkspaceOperationsCommandSubmissionKind(kind: AgentWorkspaceEditorKind): kind is AgentWorkspaceOperationsCommandEditorKind {
51
31
  return isAgentWorkspaceOperationsCommandEditorKind(kind);
52
32
  }
53
33
 
54
- export function buildAgentWorkspaceOperationsCommandEditorSubmission(
55
- editor: AgentWorkspaceLocalEditor,
56
- readField: AgentWorkspaceFieldReader,
57
- ): AgentWorkspaceOperationsCommandEditorSubmission {
58
- if (editor.kind === 'plan-seed') {
34
+ const OPERATIONS_COMMAND_SUBMISSION_HANDLERS: Readonly<Record<AgentWorkspaceOperationsCommandEditorKind, AgentWorkspaceCommandSubmissionHandler>> = {
35
+ 'plan-seed': (_editor, readField) => {
59
36
  const command = `/plan ${quoteSlashCommandArg(readField('goal'))}`;
60
- return {
61
- kind: 'dispatch',
37
+ return dispatchCommandEditorSubmission(
62
38
  command,
63
- status: 'Opening planning goal seeding.',
64
- actionResult: {
65
- kind: 'dispatched',
66
- title: 'Opening planning goal seeding',
67
- detail: 'The workspace handed a concrete planning goal to the shell-owned command router without creating coding-role Agent jobs.',
68
- command,
69
- safety: 'safe',
70
- },
71
- };
72
- }
73
- if (editor.kind === 'plan-approve') {
39
+ 'Opening planning goal seeding',
40
+ 'The workspace handed a concrete planning goal to the shell-owned command router without creating coding-role Agent jobs.',
41
+ 'safe',
42
+ );
43
+ },
44
+ 'plan-approve': (editor, readField) => {
74
45
  if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Planning approval not confirmed. Type yes, then press Enter.');
75
- return {
76
- kind: 'dispatch',
77
- command: '/plan approve --yes',
78
- status: 'Opening planning approval.',
79
- actionResult: {
80
- kind: 'dispatched',
81
- title: 'Opening planning approval',
82
- detail: 'The workspace handed confirmed planning approval to the shell-owned command router.',
83
- command: '/plan approve --yes',
84
- safety: 'safe',
85
- },
86
- };
87
- }
88
- if (editor.kind === 'plan-override') {
46
+ return dispatchCommandEditorSubmission(
47
+ '/plan approve --yes',
48
+ 'Opening planning approval',
49
+ 'The workspace handed confirmed planning approval to the shell-owned command router.',
50
+ 'safe',
51
+ );
52
+ },
53
+ 'plan-override': (editor, readField) => {
89
54
  if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Planning strategy override not confirmed. Type yes, then press Enter.');
90
- const command = `/plan override ${quoteSlashCommandArg(readField('strategy'))} --yes`;
91
- return {
92
- kind: 'dispatch',
93
- command,
94
- status: 'Opening planning strategy override.',
95
- actionResult: {
96
- kind: 'dispatched',
97
- title: 'Opening planning strategy override',
98
- detail: 'The workspace handed a confirmed planning strategy override to the shell-owned command router.',
99
- command,
100
- safety: 'safe',
101
- },
102
- };
103
- }
104
- if (editor.kind === 'plan-clear') {
55
+ return dispatchCommandEditorSubmission(
56
+ `/plan override ${quoteSlashCommandArg(readField('strategy'))} --yes`,
57
+ 'Opening planning strategy override',
58
+ 'The workspace handed a confirmed planning strategy override to the shell-owned command router.',
59
+ 'safe',
60
+ );
61
+ },
62
+ 'plan-clear': (editor, readField) => {
105
63
  if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Planning clear not confirmed. Type yes, then press Enter.');
106
- return {
107
- kind: 'dispatch',
108
- command: '/plan clear --yes',
109
- status: 'Opening planning clear.',
110
- actionResult: {
111
- kind: 'dispatched',
112
- title: 'Opening planning clear',
113
- detail: 'The workspace handed confirmed planning-state clearing to the shell-owned command router.',
114
- command: '/plan clear --yes',
115
- safety: 'safe',
116
- },
117
- };
118
- }
119
- if (editor.kind === 'approval-approve' || editor.kind === 'approval-deny' || editor.kind === 'approval-cancel') {
120
- if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Approval action not confirmed. Type yes, then press Enter.');
121
- const verb = editor.kind.replace('approval-', '');
122
- const command = `/approval ${verb} ${quoteSlashCommandArg(readField('approvalId'))}${optionalNoteArgs(readField('note'))}${optionalRememberArgs(readField('remember'))} --yes`;
123
- const title = `${verb[0]?.toUpperCase() ?? ''}${verb.slice(1)} approval`;
124
- return {
125
- kind: 'dispatch',
126
- command,
127
- status: `${title}.`,
128
- actionResult: {
129
- kind: 'dispatched',
130
- title,
131
- detail: 'The workspace handed an explicit confirmed approval action to the shell-owned command router.',
132
- command,
133
- safety: 'safe',
134
- },
135
- };
136
- }
137
- if (
138
- editor.kind === 'automation-job-run'
139
- || editor.kind === 'automation-job-pause'
140
- || editor.kind === 'automation-job-resume'
141
- || editor.kind === 'automation-run-cancel'
142
- || editor.kind === 'automation-run-retry'
143
- || editor.kind === 'schedule-run'
144
- ) {
145
- if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Automation action not confirmed. Type yes, then press Enter.');
146
- const command = editor.kind === 'automation-job-run'
147
- ? `/automation job run ${quoteSlashCommandArg(readField('jobId'))} --yes`
148
- : editor.kind === 'automation-job-pause'
149
- ? `/automation job pause ${quoteSlashCommandArg(readField('jobId'))} --yes`
150
- : editor.kind === 'automation-job-resume'
151
- ? `/automation job resume ${quoteSlashCommandArg(readField('jobId'))} --yes`
152
- : editor.kind === 'automation-run-cancel'
153
- ? `/automation run cancel ${quoteSlashCommandArg(readField('runId'))} --yes`
154
- : editor.kind === 'automation-run-retry'
155
- ? `/automation run retry ${quoteSlashCommandArg(readField('runId'))} --yes`
156
- : `/automation schedule run ${quoteSlashCommandArg(readField('scheduleId'))} --yes`;
157
- return {
158
- kind: 'dispatch',
159
- command,
160
- status: 'Opening confirmed automation action.',
161
- actionResult: {
162
- kind: 'dispatched',
163
- title: 'Opening confirmed automation action',
164
- detail: 'The workspace handed an explicit connected-host automation action to the shell-owned command router.',
165
- command,
166
- safety: 'safe',
167
- },
168
- };
169
- }
170
- if (editor.kind === 'schedule-edit') {
64
+ return dispatchCommandEditorSubmission(
65
+ '/plan clear --yes',
66
+ 'Opening planning clear',
67
+ 'The workspace handed confirmed planning-state clearing to the shell-owned command router.',
68
+ 'safe',
69
+ );
70
+ },
71
+ 'approval-approve': (editor, readField) => approvalAction(editor, readField),
72
+ 'approval-deny': (editor, readField) => approvalAction(editor, readField),
73
+ 'approval-cancel': (editor, readField) => approvalAction(editor, readField),
74
+ 'automation-job-run': (editor, readField) => automationAction(editor, readField),
75
+ 'automation-job-pause': (editor, readField) => automationAction(editor, readField),
76
+ 'automation-job-resume': (editor, readField) => automationAction(editor, readField),
77
+ 'automation-run-cancel': (editor, readField) => automationAction(editor, readField),
78
+ 'automation-run-retry': (editor, readField) => automationAction(editor, readField),
79
+ 'schedule-run': (editor, readField) => automationAction(editor, readField),
80
+ 'schedule-edit': (editor, readField) => {
171
81
  if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Schedule edit not confirmed. Type yes, then press Enter.');
172
82
  const scheduleKind = readField('scheduleKind').trim();
173
83
  const scheduleValue = readField('scheduleValue').trim();
@@ -202,38 +112,69 @@ export function buildAgentWorkspaceOperationsCommandEditorSubmission(
202
112
  optionalCommandArg('--prompt', readField('prompt')).trim(),
203
113
  '--yes',
204
114
  ].filter(Boolean).join(' ');
205
- return {
206
- kind: 'dispatch',
207
- command,
208
- status: 'Opening confirmed schedule edit.',
209
- actionResult: {
210
- kind: 'dispatched',
211
- title: 'Opening confirmed schedule edit',
212
- detail: 'The workspace handed an explicit connected-host schedule edit to the shell-owned command router.',
213
- command,
214
- safety: 'safe',
215
- },
216
- };
217
- }
218
- if (editor.kind === 'routine-receipt' || editor.kind === 'schedule-receipt') {
219
- const routine = editor.kind === 'routine-receipt';
220
- const command = `/${routine ? 'routines' : 'schedule'} receipt ${quoteSlashCommandArg(readField('receiptId'))}`;
221
- const title = routine ? 'Opening routine receipt' : 'Opening schedule receipt';
222
- return {
223
- kind: 'dispatch',
115
+ return dispatchCommandEditorSubmission(
224
116
  command,
225
- status: `${title}.`,
226
- actionResult: {
227
- kind: 'dispatched',
228
- title,
229
- detail: routine
230
- ? 'The workspace handed read-only routine receipt inspection to the shell-owned command router.'
231
- : 'The workspace handed read-only schedule receipt inspection to the shell-owned command router.',
232
- command,
233
- safety: 'read-only',
234
- },
235
- };
236
- }
117
+ 'Opening confirmed schedule edit',
118
+ 'The workspace handed an explicit connected-host schedule edit to the shell-owned command router.',
119
+ 'safe',
120
+ );
121
+ },
122
+ 'routine-receipt': (editor, readField) => receiptInspection(editor, readField),
123
+ 'schedule-receipt': (editor, readField) => receiptInspection(editor, readField),
124
+ 'health-repair': (editor, readField) => planApprovalHealthShow(editor, readField),
125
+ 'approval-review': (editor, readField) => planApprovalHealthShow(editor, readField),
126
+ 'plan-show': (editor, readField) => planApprovalHealthShow(editor, readField),
127
+ };
128
+
129
+ function approvalAction(editor: AgentWorkspaceLocalEditor, readField: AgentWorkspaceFieldReader): AgentWorkspaceCommandEditorSubmission {
130
+ if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Approval action not confirmed. Type yes, then press Enter.');
131
+ const verb = editor.kind.replace('approval-', '');
132
+ const command = `/approval ${verb} ${quoteSlashCommandArg(readField('approvalId'))}${optionalNoteArgs(readField('note'))}${optionalRememberArgs(readField('remember'))} --yes`;
133
+ const title = `${verb[0]?.toUpperCase() ?? ''}${verb.slice(1)} approval`;
134
+ return dispatchCommandEditorSubmission(
135
+ command,
136
+ title,
137
+ 'The workspace handed an explicit confirmed approval action to the shell-owned command router.',
138
+ 'safe',
139
+ );
140
+ }
141
+
142
+ function automationAction(editor: AgentWorkspaceLocalEditor, readField: AgentWorkspaceFieldReader): AgentWorkspaceCommandEditorSubmission {
143
+ if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Automation action not confirmed. Type yes, then press Enter.');
144
+ const command = editor.kind === 'automation-job-run'
145
+ ? `/automation job run ${quoteSlashCommandArg(readField('jobId'))} --yes`
146
+ : editor.kind === 'automation-job-pause'
147
+ ? `/automation job pause ${quoteSlashCommandArg(readField('jobId'))} --yes`
148
+ : editor.kind === 'automation-job-resume'
149
+ ? `/automation job resume ${quoteSlashCommandArg(readField('jobId'))} --yes`
150
+ : editor.kind === 'automation-run-cancel'
151
+ ? `/automation run cancel ${quoteSlashCommandArg(readField('runId'))} --yes`
152
+ : editor.kind === 'automation-run-retry'
153
+ ? `/automation run retry ${quoteSlashCommandArg(readField('runId'))} --yes`
154
+ : `/automation schedule run ${quoteSlashCommandArg(readField('scheduleId'))} --yes`;
155
+ return dispatchCommandEditorSubmission(
156
+ command,
157
+ 'Opening confirmed automation action',
158
+ 'The workspace handed an explicit connected-host automation action to the shell-owned command router.',
159
+ 'safe',
160
+ );
161
+ }
162
+
163
+ function receiptInspection(editor: AgentWorkspaceLocalEditor, readField: AgentWorkspaceFieldReader): AgentWorkspaceCommandEditorSubmission {
164
+ const routine = editor.kind === 'routine-receipt';
165
+ const command = `/${routine ? 'routines' : 'schedule'} receipt ${quoteSlashCommandArg(readField('receiptId'))}`;
166
+ const title = routine ? 'Opening routine receipt' : 'Opening schedule receipt';
167
+ return dispatchCommandEditorSubmission(
168
+ command,
169
+ title,
170
+ routine
171
+ ? 'The workspace handed read-only routine receipt inspection to the shell-owned command router.'
172
+ : 'The workspace handed read-only schedule receipt inspection to the shell-owned command router.',
173
+ 'read-only',
174
+ );
175
+ }
176
+
177
+ function planApprovalHealthShow(editor: AgentWorkspaceLocalEditor, readField: AgentWorkspaceFieldReader): AgentWorkspaceCommandEditorSubmission {
237
178
  const plan = editor.kind === 'plan-show';
238
179
  const approval = editor.kind === 'approval-review';
239
180
  const command = plan
@@ -242,20 +183,26 @@ export function buildAgentWorkspaceOperationsCommandEditorSubmission(
242
183
  ? `/approval review ${quoteSlashCommandArg(readField('kind'))}`
243
184
  : `/health repair ${quoteSlashCommandArg(readField('domain'))}`;
244
185
  const title = plan ? 'Opening saved plan' : approval ? 'Opening approval review' : 'Opening health repair guidance';
245
- return {
246
- kind: 'dispatch',
186
+ return dispatchCommandEditorSubmission(
247
187
  command,
248
- status: `${title}.`,
249
- actionResult: {
250
- kind: 'dispatched',
251
- title,
252
- detail: plan
253
- ? 'The workspace handed read-only saved-plan inspection to the shell-owned command router.'
254
- : approval
255
- ? 'The workspace handed read-only approval class review to the shell-owned command router.'
256
- : 'The workspace handed read-only health repair guidance to the shell-owned command router.',
257
- command,
258
- safety: 'read-only',
259
- },
260
- };
188
+ title,
189
+ plan
190
+ ? 'The workspace handed read-only saved-plan inspection to the shell-owned command router.'
191
+ : approval
192
+ ? 'The workspace handed read-only approval class review to the shell-owned command router.'
193
+ : 'The workspace handed read-only health repair guidance to the shell-owned command router.',
194
+ 'read-only',
195
+ );
196
+ }
197
+
198
+ export function buildAgentWorkspaceOperationsCommandEditorSubmission(
199
+ editor: AgentWorkspaceLocalEditor,
200
+ readField: AgentWorkspaceFieldReader,
201
+ ): AgentWorkspaceCommandEditorSubmission {
202
+ return buildCommandEditorSubmissionFromTable(
203
+ editor.kind as AgentWorkspaceOperationsCommandEditorKind,
204
+ editor,
205
+ readField,
206
+ OPERATIONS_COMMAND_SUBMISSION_HANDLERS,
207
+ );
261
208
  }