@pellux/goodvibes-agent 1.1.6 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/README.md +46 -30
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
  5. package/dist/package/main.js +132662 -91399
  6. package/docs/README.md +14 -7
  7. package/docs/channels-remote-and-api.md +8 -5
  8. package/docs/connected-host.md +14 -12
  9. package/docs/getting-started.md +56 -30
  10. package/docs/knowledge-artifacts-and-multimodal.md +7 -5
  11. package/docs/project-planning.md +2 -2
  12. package/docs/providers-and-routing.md +11 -3
  13. package/docs/tools-and-commands.md +114 -45
  14. package/docs/voice-and-live-tts.md +3 -1
  15. package/package.json +3 -2
  16. package/release/release-notes.md +130 -5
  17. package/release/release-readiness.json +120 -90
  18. package/src/agent/assistant-cockpit.ts +247 -0
  19. package/src/agent/autonomy-schedule-format.ts +96 -0
  20. package/src/agent/autonomy-schedule.ts +514 -0
  21. package/src/agent/channel-delivery-receipts.ts +292 -0
  22. package/src/agent/competitive-feature-inventory.ts +296 -0
  23. package/src/agent/document-registry-types.ts +106 -0
  24. package/src/agent/document-registry.ts +734 -0
  25. package/src/agent/harness-control.ts +2 -2
  26. package/src/agent/memory-prompt.ts +2 -2
  27. package/src/agent/operator-actions.ts +50 -6
  28. package/src/agent/persona-registry.ts +8 -0
  29. package/src/agent/project-context-files.ts +273 -0
  30. package/src/agent/prompt-context-receipts.ts +502 -0
  31. package/src/agent/reminder-schedule-format.ts +16 -2
  32. package/src/agent/research-run-registry.ts +582 -0
  33. package/src/agent/research-source-registry.ts +441 -0
  34. package/src/agent/routine-registry.ts +19 -3
  35. package/src/agent/routine-schedule-format.ts +27 -2
  36. package/src/agent/runtime-profile-starters.ts +7 -0
  37. package/src/agent/runtime-profile.ts +106 -4
  38. package/src/agent/schedule-edit-format.ts +129 -0
  39. package/src/agent/schedule-edit.ts +496 -0
  40. package/src/agent/schedule-next-routes.ts +42 -0
  41. package/src/agent/setup-wizard-checkpoint.ts +140 -0
  42. package/src/agent/setup-wizard.ts +447 -0
  43. package/src/agent/skill-registry-types.ts +102 -0
  44. package/src/agent/skill-registry.ts +81 -107
  45. package/src/agent/vibe-confirmation-routes.ts +62 -0
  46. package/src/agent/vibe-file.ts +285 -0
  47. package/src/cli/agent-knowledge-command.ts +45 -2
  48. package/src/cli/help.ts +3 -0
  49. package/src/cli/profiles-command.ts +25 -11
  50. package/src/config/agent-settings-policy.ts +1 -18
  51. package/src/input/agent-workspace-activation.ts +53 -0
  52. package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
  53. package/src/input/agent-workspace-artifact-metadata.ts +17 -0
  54. package/src/input/agent-workspace-basic-command-editors.ts +5 -1
  55. package/src/input/agent-workspace-categories.ts +153 -155
  56. package/src/input/agent-workspace-channel-triage.ts +481 -0
  57. package/src/input/agent-workspace-channels.ts +263 -0
  58. package/src/input/agent-workspace-command-editor.ts +152 -0
  59. package/src/input/agent-workspace-context-snapshot.ts +349 -0
  60. package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
  61. package/src/input/agent-workspace-document-editor.ts +502 -0
  62. package/src/input/agent-workspace-document-ops-editor.ts +523 -0
  63. package/src/input/agent-workspace-host-category.ts +1 -1
  64. package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
  65. package/src/input/agent-workspace-model-compare-editor.ts +376 -0
  66. package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
  67. package/src/input/agent-workspace-model-compare-types.ts +82 -0
  68. package/src/input/agent-workspace-model-compare-utils.ts +35 -0
  69. package/src/input/agent-workspace-onboarding-categories.ts +141 -0
  70. package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
  71. package/src/input/agent-workspace-operations-command-editors.ts +22 -0
  72. package/src/input/agent-workspace-research-report-editor.ts +212 -0
  73. package/src/input/agent-workspace-research-run-editor.ts +144 -0
  74. package/src/input/agent-workspace-research-source-editor.ts +167 -0
  75. package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
  76. package/src/input/agent-workspace-review-packet-utils.ts +265 -0
  77. package/src/input/agent-workspace-settings.ts +262 -30
  78. package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
  79. package/src/input/agent-workspace-setup-snapshot.ts +198 -0
  80. package/src/input/agent-workspace-setup.ts +34 -1
  81. package/src/input/agent-workspace-snapshot.ts +162 -147
  82. package/src/input/agent-workspace-types.ts +287 -2
  83. package/src/input/agent-workspace.ts +18 -0
  84. package/src/input/command-registry.ts +9 -2
  85. package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
  86. package/src/input/commands/channels-runtime.ts +102 -114
  87. package/src/input/commands/delegation-runtime.ts +87 -24
  88. package/src/input/commands/knowledge-browser-flags.ts +12 -0
  89. package/src/input/commands/knowledge.ts +28 -14
  90. package/src/input/commands/operator-actions-runtime.ts +6 -3
  91. package/src/input/commands/schedule-runtime.ts +71 -14
  92. package/src/input/commands/session-content.ts +2 -2
  93. package/src/input/commands/shell-core.ts +2 -0
  94. package/src/input/commands/vibe-runtime.ts +140 -0
  95. package/src/input/commands.ts +2 -0
  96. package/src/input/connected-host-routes.ts +123 -0
  97. package/src/input/settings-modal-types.ts +14 -0
  98. package/src/main.ts +15 -15
  99. package/src/panels/qr-panel.ts +2 -2
  100. package/src/renderer/agent-workspace-context-lines.ts +686 -0
  101. package/src/renderer/agent-workspace.ts +30 -419
  102. package/src/renderer/settings-modal-helpers.ts +12 -0
  103. package/src/renderer/settings-modal.ts +12 -0
  104. package/src/runtime/bootstrap-command-context.ts +11 -1
  105. package/src/runtime/bootstrap-command-parts.ts +14 -3
  106. package/src/runtime/bootstrap-core.ts +43 -1
  107. package/src/runtime/bootstrap-shell.ts +6 -0
  108. package/src/runtime/bootstrap.ts +113 -30
  109. package/src/runtime/connected-host-auth.ts +3 -2
  110. package/src/runtime/execution-ledger.ts +231 -0
  111. package/src/runtime/services.ts +88 -10
  112. package/src/runtime/tool-permission-safety.ts +287 -0
  113. package/src/shell/session-continuity-hints.ts +39 -0
  114. package/src/tools/agent-artifacts-tool.ts +606 -0
  115. package/src/tools/agent-audit-tool.ts +155 -0
  116. package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
  117. package/src/tools/agent-autonomy-tool.ts +140 -0
  118. package/src/tools/agent-channel-send-tool.ts +24 -2
  119. package/src/tools/agent-channels-tool.ts +140 -0
  120. package/src/tools/agent-computer-tool.ts +168 -0
  121. package/src/tools/agent-context-policy.ts +267 -10
  122. package/src/tools/agent-context-tool.ts +143 -0
  123. package/src/tools/agent-delegation-tool.ts +128 -0
  124. package/src/tools/agent-device-tool.ts +240 -0
  125. package/src/tools/agent-documents-tool.ts +684 -0
  126. package/src/tools/agent-execution-tool.ts +230 -0
  127. package/src/tools/agent-harness-agent-orchestration.ts +703 -0
  128. package/src/tools/agent-harness-autonomy-intake.ts +785 -0
  129. package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
  130. package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
  131. package/src/tools/agent-harness-autonomy-queue.ts +560 -0
  132. package/src/tools/agent-harness-background-processes-types.ts +35 -0
  133. package/src/tools/agent-harness-background-processes.ts +794 -0
  134. package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
  135. package/src/tools/agent-harness-browser-control.ts +338 -0
  136. package/src/tools/agent-harness-channel-metadata.ts +168 -10
  137. package/src/tools/agent-harness-cli-command-policy.ts +110 -0
  138. package/src/tools/agent-harness-command-catalog.ts +4 -2
  139. package/src/tools/agent-harness-command-runner.ts +42 -0
  140. package/src/tools/agent-harness-connected-host-status.ts +7 -4
  141. package/src/tools/agent-harness-delegation-posture.ts +234 -19
  142. package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
  143. package/src/tools/agent-harness-document-ops-types.ts +72 -0
  144. package/src/tools/agent-harness-document-ops.ts +671 -0
  145. package/src/tools/agent-harness-execution-history.ts +489 -0
  146. package/src/tools/agent-harness-execution-posture.ts +382 -0
  147. package/src/tools/agent-harness-file-recovery.ts +135 -0
  148. package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
  149. package/src/tools/agent-harness-learning-curator-common.ts +102 -0
  150. package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
  151. package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
  152. package/src/tools/agent-harness-learning-curator-types.ts +151 -0
  153. package/src/tools/agent-harness-learning-curator.ts +417 -0
  154. package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
  155. package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
  156. package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
  157. package/src/tools/agent-harness-media-posture.ts +208 -2
  158. package/src/tools/agent-harness-memory-posture.ts +556 -0
  159. package/src/tools/agent-harness-metadata.ts +100 -168
  160. package/src/tools/agent-harness-mode-catalog.ts +84 -33
  161. package/src/tools/agent-harness-model-catalog.ts +162 -0
  162. package/src/tools/agent-harness-model-provider-health.ts +186 -0
  163. package/src/tools/agent-harness-model-readiness.ts +406 -0
  164. package/src/tools/agent-harness-model-routing-types.ts +266 -0
  165. package/src/tools/agent-harness-model-routing-utils.ts +30 -0
  166. package/src/tools/agent-harness-model-routing.ts +137 -190
  167. package/src/tools/agent-harness-operator-methods.ts +115 -133
  168. package/src/tools/agent-harness-pairing-posture.ts +431 -18
  169. package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
  170. package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
  171. package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
  172. package/src/tools/agent-harness-personal-ops-records.ts +732 -0
  173. package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
  174. package/src/tools/agent-harness-personal-ops-types.ts +222 -0
  175. package/src/tools/agent-harness-personal-ops.ts +606 -0
  176. package/src/tools/agent-harness-project-context.ts +144 -0
  177. package/src/tools/agent-harness-prompt-context.ts +589 -0
  178. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  179. package/src/tools/agent-harness-release-evidence.ts +9 -7
  180. package/src/tools/agent-harness-release-readiness.ts +9 -7
  181. package/src/tools/agent-harness-research-briefing.ts +427 -0
  182. package/src/tools/agent-harness-research-queue.ts +250 -0
  183. package/src/tools/agent-harness-research-runs.ts +295 -0
  184. package/src/tools/agent-harness-research-workflow.ts +322 -0
  185. package/src/tools/agent-harness-security-posture.ts +2 -2
  186. package/src/tools/agent-harness-service-posture.ts +9 -9
  187. package/src/tools/agent-harness-session-metadata.ts +3 -3
  188. package/src/tools/agent-harness-setup-connected-host.ts +501 -0
  189. package/src/tools/agent-harness-setup-describe.ts +557 -0
  190. package/src/tools/agent-harness-setup-handoffs.ts +502 -0
  191. package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
  192. package/src/tools/agent-harness-setup-plan.ts +253 -0
  193. package/src/tools/agent-harness-setup-posture-types.ts +218 -0
  194. package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
  195. package/src/tools/agent-harness-setup-posture.ts +449 -221
  196. package/src/tools/agent-harness-setup-smoke.ts +508 -0
  197. package/src/tools/agent-harness-sudo-posture.ts +114 -0
  198. package/src/tools/agent-harness-tool-schema.ts +120 -7
  199. package/src/tools/agent-harness-tool-types.ts +78 -0
  200. package/src/tools/agent-harness-tool-utils.ts +43 -0
  201. package/src/tools/agent-harness-tool.ts +311 -370
  202. package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
  203. package/src/tools/agent-harness-ui-surface-types.ts +46 -0
  204. package/src/tools/agent-harness-vibe-health.ts +105 -0
  205. package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
  206. package/src/tools/agent-harness-workspace-actions.ts +114 -8
  207. package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
  208. package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
  209. package/src/tools/agent-host-tool.ts +159 -0
  210. package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
  211. package/src/tools/agent-learning-consolidation-core.ts +327 -0
  212. package/src/tools/agent-learning-consolidation-tool.ts +758 -0
  213. package/src/tools/agent-memory-tool.ts +214 -0
  214. package/src/tools/agent-model-compare-export.ts +315 -0
  215. package/src/tools/agent-model-compare-handoff.ts +592 -0
  216. package/src/tools/agent-model-compare-judgment.ts +633 -0
  217. package/src/tools/agent-model-compare-run.ts +722 -0
  218. package/src/tools/agent-model-compare-tool.ts +698 -0
  219. package/src/tools/agent-model-compare-types.ts +191 -0
  220. package/src/tools/agent-model-compare-utils.ts +93 -0
  221. package/src/tools/agent-models-tool.ts +208 -0
  222. package/src/tools/agent-operator-action-tool.ts +1 -1
  223. package/src/tools/agent-operator-method-tool.ts +643 -0
  224. package/src/tools/agent-personal-ops-tool.ts +197 -0
  225. package/src/tools/agent-policy-explanation.ts +415 -0
  226. package/src/tools/agent-research-report-tool.ts +608 -0
  227. package/src/tools/agent-research-runs-tool.ts +434 -0
  228. package/src/tools/agent-research-sources-tool.ts +443 -0
  229. package/src/tools/agent-research-tool.ts +687 -0
  230. package/src/tools/agent-review-packet-presets-core.ts +757 -0
  231. package/src/tools/agent-review-packet-presets-tool.ts +466 -0
  232. package/src/tools/agent-review-packet-share-tool.ts +305 -0
  233. package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
  234. package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
  235. package/src/tools/agent-route-planner-candidates-work.ts +251 -0
  236. package/src/tools/agent-route-planner-helpers.ts +667 -0
  237. package/src/tools/agent-route-planner.ts +185 -0
  238. package/src/tools/agent-route-tool.ts +105 -0
  239. package/src/tools/agent-schedule-edit-tool.ts +210 -0
  240. package/src/tools/agent-schedule-tool.ts +282 -0
  241. package/src/tools/agent-security-tool.ts +145 -0
  242. package/src/tools/agent-sessions-tool.ts +122 -0
  243. package/src/tools/agent-settings-import-tool.ts +104 -0
  244. package/src/tools/agent-settings-tool.ts +176 -0
  245. package/src/tools/agent-setup-tool.ts +226 -0
  246. package/src/tools/agent-support-tool.ts +122 -0
  247. package/src/tools/agent-terminal-process-tools.ts +167 -0
  248. package/src/tools/agent-tool-policy-guard-types.ts +77 -0
  249. package/src/tools/agent-tool-policy-guard.ts +110 -89
  250. package/src/tools/agent-vibe-tool.ts +297 -0
  251. package/src/tools/agent-work-plan-tool.ts +265 -6
  252. package/src/tools/agent-workspace-tool.ts +305 -0
  253. package/src/tools/artifact-archive.ts +169 -0
  254. package/src/tools/tool-definition-compaction.ts +36 -0
  255. package/src/tools/tool-execution-safety.ts +41 -0
  256. package/src/version.ts +1 -1
@@ -1,15 +1,20 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
1
  import type { CommandRegistry } from '../command-registry.ts';
4
2
  import type { CommandContext } from '../command-registry.ts';
5
- import type { AgentWorkspaceChannelStatus } from '../agent-workspace-channels.ts';
6
- import { buildAgentWorkspaceChannels } from '../agent-workspace-channels.ts';
3
+ import type { AgentWorkspaceChannelSetupGuide, AgentWorkspaceChannelStatus } from '../agent-workspace-channels.ts';
4
+ import { buildAgentWorkspaceChannelTriage, formatAgentWorkspaceChannelTriage } from '../agent-workspace-channel-triage.ts';
5
+ import { buildAgentWorkspaceChannelSetupGuide, buildAgentWorkspaceChannels } from '../agent-workspace-channels.ts';
6
+ import { fetchConnectedHostReadOnlyRoute, formatConnectedHostRouteFailure } from '../connected-host-routes.ts';
7
7
  import {
8
8
  buildAgentChannelDeliveryPreview,
9
9
  deliverAgentChannelMessage,
10
10
  formatAgentChannelDeliveryPreview,
11
11
  formatAgentChannelDeliveryResult,
12
12
  } from '../../agent/channel-delivery.ts';
13
+ import {
14
+ formatAgentChannelDeliveryReceiptLine,
15
+ readAgentChannelDeliveryReceipts,
16
+ recordAgentChannelDeliveryReceipt,
17
+ } from '../../agent/channel-delivery-receipts.ts';
13
18
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
14
19
 
15
20
  type ChannelFilter = 'all' | 'ready' | 'attention';
@@ -26,35 +31,6 @@ interface ChannelSendArgs {
26
31
  readonly errors: readonly string[];
27
32
  }
28
33
 
29
- interface ChannelConnectedHostConnection {
30
- readonly baseUrl: string;
31
- readonly token: string | null;
32
- readonly tokenPath: string;
33
- }
34
-
35
- interface ChannelRouteSuccess {
36
- readonly ok: true;
37
- readonly route: string;
38
- readonly body: unknown;
39
- }
40
-
41
- interface ChannelRouteFailure {
42
- readonly ok: false;
43
- readonly route: string;
44
- readonly kind: 'auth_required' | 'connected_host_unavailable' | 'connected_host_route_unavailable' | 'connected_host_error';
45
- readonly baseUrl: string;
46
- readonly message: string;
47
- }
48
-
49
- type ChannelRouteResult = ChannelRouteSuccess | ChannelRouteFailure;
50
-
51
- const CHANNEL_FAILURE_LABELS: Record<ChannelRouteFailure['kind'], string> = {
52
- auth_required: 'auth required',
53
- connected_host_unavailable: 'connected host unavailable',
54
- connected_host_route_unavailable: 'connected host route unavailable',
55
- connected_host_error: 'connected host error',
56
- };
57
-
58
34
  function isRecord(value: unknown): value is JsonRecord {
59
35
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
60
36
  }
@@ -69,6 +45,13 @@ function readBoolean(record: JsonRecord, key: string, fallback = false): boolean
69
45
  return typeof value === 'boolean' ? value : fallback;
70
46
  }
71
47
 
48
+ function readLimitValue(value: string | undefined, fallback: number): number {
49
+ if (!value) return fallback;
50
+ const parsed = Number(value);
51
+ if (!Number.isFinite(parsed)) return fallback;
52
+ return Math.max(1, Math.min(100, Math.trunc(parsed)));
53
+ }
54
+
72
55
  function readRecordArray(record: JsonRecord, key: string): readonly JsonRecord[] {
73
56
  const value = record[key];
74
57
  return Array.isArray(value) ? value.filter(isRecord) : [];
@@ -126,83 +109,28 @@ function parseChannelSendArgs(args: readonly string[]): ChannelSendArgs {
126
109
  };
127
110
  }
128
111
 
129
- function resolveChannelConnectedHostConnection(context: CommandContext): ChannelConnectedHostConnection {
130
- const hostValue = context.platform?.configManager?.get('controlPlane.host');
131
- const portValue = context.platform?.configManager?.get('controlPlane.port');
132
- const host = typeof hostValue === 'string' && hostValue.trim().length > 0 ? hostValue.trim() : '127.0.0.1';
133
- const port = typeof portValue === 'number' && Number.isFinite(portValue) ? portValue : 3421;
134
- const homeDirectory = context.workspace?.shellPaths?.homeDirectory ?? process.env.HOME ?? '';
135
- const tokenPath = join(homeDirectory, '.goodvibes', 'daemon', 'operator-tokens.json');
136
- if (!existsSync(tokenPath)) return { baseUrl: `http://${host}:${port}`, token: null, tokenPath };
137
- try {
138
- const parsed = JSON.parse(readFileSync(tokenPath, 'utf-8')) as unknown;
139
- const token = isRecord(parsed) && typeof parsed.token === 'string' ? parsed.token : null;
140
- return { baseUrl: `http://${host}:${port}`, token, tokenPath };
141
- } catch {
142
- return { baseUrl: `http://${host}:${port}`, token: null, tokenPath };
143
- }
144
- }
145
-
146
- async function fetchChannelRoute(context: CommandContext, route: string): Promise<ChannelRouteResult> {
147
- const connection = resolveChannelConnectedHostConnection(context);
148
- if (!connection.token) {
149
- return {
150
- ok: false,
151
- route,
152
- kind: 'auth_required',
153
- baseUrl: connection.baseUrl,
154
- message: `No connected-host operator token found at ${connection.tokenPath}`,
155
- };
156
- }
157
-
158
- try {
159
- const response = await fetch(`${connection.baseUrl}${route}`, {
160
- headers: { authorization: `Bearer ${connection.token}` },
161
- });
162
- const text = await response.text();
163
- let body: unknown = text;
164
- if (text.trim().length > 0) {
165
- try {
166
- body = JSON.parse(text) as unknown;
167
- } catch {
168
- body = text;
169
- }
170
- }
171
- if (!response.ok) {
172
- const detail = isRecord(body) && typeof body.error === 'string' ? body.error : text;
173
- return {
174
- ok: false,
175
- route,
176
- kind: response.status === 401 || response.status === 403
177
- ? 'auth_required'
178
- : response.status === 404
179
- ? 'connected_host_route_unavailable'
180
- : 'connected_host_error',
181
- baseUrl: connection.baseUrl,
182
- message: `HTTP ${response.status}${detail ? `: ${detail}` : ''}`,
183
- };
184
- }
185
- return { ok: true, route, body };
186
- } catch (error) {
187
- return {
188
- ok: false,
189
- route,
190
- kind: 'connected_host_unavailable',
191
- baseUrl: connection.baseUrl,
192
- message: error instanceof Error ? error.message : String(error),
193
- };
112
+ function formatChannelDeliveryReceipts(context: CommandContext, limitArg?: string): string {
113
+ const shellPaths = context.workspace?.shellPaths;
114
+ if (!shellPaths) {
115
+ return [
116
+ 'Channel Delivery Receipts',
117
+ ' status unavailable',
118
+ ' reason Agent shell paths are unavailable in this runtime.',
119
+ ].join('\n');
194
120
  }
195
- }
196
-
197
- function formatChannelRouteFailure(title: string, failure: ChannelRouteFailure): string {
121
+ const limit = readLimitValue(limitArg, 10);
122
+ const snapshot = readAgentChannelDeliveryReceipts(shellPaths);
123
+ const receipts = snapshot.receipts.slice(0, limit);
198
124
  return [
199
- `${title}: unavailable`,
200
- ` status: ${CHANNEL_FAILURE_LABELS[failure.kind]}`,
201
- ` kind: ${failure.kind}`,
202
- ` connected host: ${failure.baseUrl}`,
203
- ` route: ${failure.route}`,
204
- ` error: ${failure.message}`,
205
- ' policy: read-only; no channel send/action route was called',
125
+ 'Channel Delivery Receipts',
126
+ ` path ${snapshot.path}`,
127
+ ` total ${snapshot.receipts.length}`,
128
+ ` returned ${receipts.length}`,
129
+ ` status ${snapshot.parseError ? 'attention' : snapshot.exists ? 'ready' : 'empty'}`,
130
+ ...(snapshot.parseError ? [` parse error ${snapshot.parseError}`] : []),
131
+ ' policy confirmed sends only; message bodies and secret-bearing target values are bounded or redacted',
132
+ ...receipts.map((receipt) => ` ${formatAgentChannelDeliveryReceiptLine(receipt)}`),
133
+ ...(receipts.length === 0 ? [' no channel deliveries recorded yet'] : []),
206
134
  ].join('\n');
207
135
  }
208
136
 
@@ -285,6 +213,36 @@ function printChannelDetail(
285
213
  ].join('\n'));
286
214
  }
287
215
 
216
+ function formatGuideStepStatus(status: string): string {
217
+ if (status === 'complete') return '[x]';
218
+ if (status === 'current') return '[>]';
219
+ return '[ ]';
220
+ }
221
+
222
+ function formatChannelSetupGuide(guide: AgentWorkspaceChannelSetupGuide): string {
223
+ const lines = [
224
+ 'Channel Setup Guide',
225
+ ` state: ${guide.status}`,
226
+ ` progress: ${guide.progressLabel}`,
227
+ ` current channel: ${guide.currentChannelLabel ?? 'choose a channel'}${guide.currentChannelId ? ` (${guide.currentChannelId})` : ''}`,
228
+ ` summary: ${guide.summary}`,
229
+ ` ready: ${guide.readyChannels}/${guide.totalChannels}; enabled: ${guide.enabledChannels}; attention: ${guide.attentionChannels}; targets: ${guide.configuredTargets}`,
230
+ ` policy: ${guide.policy}`,
231
+ '',
232
+ ' Steps',
233
+ ];
234
+ for (const step of guide.steps) {
235
+ lines.push(` ${formatGuideStepStatus(step.status)} ${step.label}: ${step.userRoute}`);
236
+ if (step.status === 'current') lines.push(` next: ${step.detail}`);
237
+ }
238
+ lines.push('', ' Channel order');
239
+ for (const channel of guide.channels.slice(0, 10)) {
240
+ lines.push(` - ${channel.label}: ${channel.setupState}; ${channel.summary}; guide ${channel.guideRoute}`);
241
+ }
242
+ if (guide.channels.length > 10) lines.push(` ${guide.channels.length - 10} more channel(s) omitted.`);
243
+ return lines.join('\n');
244
+ }
245
+
288
246
  function formatChannelAccounts(body: unknown): string {
289
247
  const root = isRecord(body) ? body : {};
290
248
  const accounts = readRecordArray(root, 'accounts');
@@ -407,9 +365,9 @@ async function printReadOnlyChannelRoute(
407
365
  route: string,
408
366
  format: (body: unknown) => string,
409
367
  ): Promise<void> {
410
- const result = await fetchChannelRoute(context, route);
368
+ const result = await fetchConnectedHostReadOnlyRoute(context, route);
411
369
  if (!result.ok) {
412
- context.print(formatChannelRouteFailure(title, result));
370
+ context.print(formatConnectedHostRouteFailure(title, result, 'read-only; no channel send/action route was called'));
413
371
  return;
414
372
  }
415
373
  context.print(format(result.body));
@@ -420,8 +378,8 @@ export function registerChannelsRuntimeCommands(registry: CommandRegistry): void
420
378
  name: 'channels',
421
379
  aliases: ['channel'],
422
380
  description: 'Inspect Agent channel readiness or send an explicitly confirmed delivery message',
423
- usage: '[list|readiness|ready|attention|show <id>|send --channel <id> --message <text> --yes|accounts|policies|status|doctor <id>|setup <id>]',
424
- argsHint: 'list|readiness|ready|attention|show|send|accounts|policies|status|doctor|setup',
381
+ usage: '[list|readiness|ready|attention|triage [limit]|guide [id]|show <id>|deliveries [limit]|send --channel <id> --message <text> --yes|accounts|policies|status|doctor <id>|setup <id>]',
382
+ argsHint: 'list|readiness|ready|attention|triage|guide|show|deliveries|send|accounts|policies|status|doctor|setup',
425
383
  async handler(args, ctx) {
426
384
  const channels = buildAgentWorkspaceChannels(ctx);
427
385
  const subcommand = (args[0] ?? 'readiness').trim().toLowerCase();
@@ -441,6 +399,17 @@ export function registerChannelsRuntimeCommands(registry: CommandRegistry): void
441
399
  return;
442
400
  }
443
401
 
402
+ if (subcommand === 'guide' || subcommand === 'setup-guide') {
403
+ const channelId = args[1]?.trim();
404
+ ctx.print(formatChannelSetupGuide(buildAgentWorkspaceChannelSetupGuide(channels, channelId ? { channelId } : {})));
405
+ return;
406
+ }
407
+
408
+ if (subcommand === 'triage' || subcommand === 'inbox') {
409
+ ctx.print(formatAgentWorkspaceChannelTriage(await buildAgentWorkspaceChannelTriage(ctx, { limit: args[1] })));
410
+ return;
411
+ }
412
+
444
413
  if (subcommand === 'show') {
445
414
  const channelId = args[1]?.trim().toLowerCase();
446
415
  if (!channelId) {
@@ -456,6 +425,11 @@ export function registerChannelsRuntimeCommands(registry: CommandRegistry): void
456
425
  return;
457
426
  }
458
427
 
428
+ if (subcommand === 'deliveries' || subcommand === 'receipts') {
429
+ ctx.print(formatChannelDeliveryReceipts(ctx, args[1]));
430
+ return;
431
+ }
432
+
459
433
  if (subcommand === 'send') {
460
434
  const router = ctx.platform.channelDeliveryRouter;
461
435
  if (!router) {
@@ -480,7 +454,21 @@ export function registerChannelsRuntimeCommands(registry: CommandRegistry): void
480
454
  return;
481
455
  }
482
456
  try {
483
- ctx.print(formatAgentChannelDeliveryResult(await deliverAgentChannelMessage(router, parsed)));
457
+ const result = await deliverAgentChannelMessage(router, parsed);
458
+ const lines = [formatAgentChannelDeliveryResult(result)];
459
+ if (ctx.workspace?.shellPaths) {
460
+ try {
461
+ const receipt = recordAgentChannelDeliveryReceipt(ctx.workspace.shellPaths, {
462
+ source: 'command',
463
+ deliveryInput: parsed,
464
+ result,
465
+ });
466
+ lines.push(` receipt ${receipt.id}`);
467
+ } catch (receiptError) {
468
+ lines.push(` receipt unavailable ${receiptError instanceof Error ? receiptError.message : String(receiptError)}`);
469
+ }
470
+ }
471
+ ctx.print(lines.join('\n'));
484
472
  } catch (error) {
485
473
  ctx.print(`[channels] Send failed ${error instanceof Error ? error.message : String(error)}`);
486
474
  }
@@ -517,7 +505,7 @@ export function registerChannelsRuntimeCommands(registry: CommandRegistry): void
517
505
  return;
518
506
  }
519
507
 
520
- ctx.print('Usage: /channels [list|readiness|ready|attention|show <id>|send --channel <id> --message <text> --yes|accounts|policies|status|doctor <id>|setup <id>]');
508
+ ctx.print('Usage: /channels [list|readiness|ready|attention|triage [limit]|guide [id]|show <id>|deliveries [limit]|send --channel <id> --message <text> --yes|accounts|policies|status|doctor <id>|setup <id>]');
521
509
  },
522
510
  });
523
511
  }
@@ -10,31 +10,83 @@ function hasAnyFlag(args: readonly string[], flags: readonly string[]): boolean
10
10
  return flags.some((flag) => hasFlag(args, flag));
11
11
  }
12
12
 
13
- function delegationTaskValues(args: readonly string[]): string[] {
14
- const values: string[] = [];
13
+ interface DelegationCommandInput {
14
+ readonly task: string;
15
+ readonly reviewRequested: boolean;
16
+ readonly reason: string;
17
+ readonly successCriteria: string;
18
+ readonly workspaceHint: string;
19
+ readonly priority: string;
20
+ }
21
+
22
+ function parseDelegationArgs(args: readonly string[], defaultReview: boolean): DelegationCommandInput {
23
+ const taskValues: string[] = [];
24
+ let reason = '';
25
+ let successCriteria = '';
26
+ let workspaceHint = '';
27
+ let priority = '';
15
28
  for (let index = 0; index < args.length; index += 1) {
16
29
  const token = args[index]!;
17
30
  if (token === '--review' || token === '--wrfc') continue;
31
+ if (token === '--reason') {
32
+ reason = args[index + 1]?.trim() ?? '';
33
+ index += 1;
34
+ continue;
35
+ }
36
+ if (token === '--success' || token === '--success-criteria') {
37
+ successCriteria = args[index + 1]?.trim() ?? '';
38
+ index += 1;
39
+ continue;
40
+ }
41
+ if (token === '--workspace' || token === '--worktree') {
42
+ workspaceHint = args[index + 1]?.trim() ?? '';
43
+ index += 1;
44
+ continue;
45
+ }
46
+ if (token === '--priority') {
47
+ priority = args[index + 1]?.trim() ?? '';
48
+ index += 1;
49
+ continue;
50
+ }
18
51
  if (!token.startsWith('--')) {
19
- values.push(token);
52
+ taskValues.push(token);
20
53
  continue;
21
54
  }
22
55
  }
23
- return values;
56
+ return {
57
+ task: taskValues.join(' ').trim(),
58
+ reviewRequested: defaultReview || hasAnyFlag(args, ['--review', '--wrfc']),
59
+ reason,
60
+ successCriteria,
61
+ workspaceHint,
62
+ priority,
63
+ };
24
64
  }
25
65
 
26
- function buildDelegationBody(task: string, reviewRequested: boolean): string {
66
+ function buildDelegationBody(input: DelegationCommandInput): string {
27
67
  return [
28
68
  'GoodVibes Agent explicit build delegation.',
29
69
  '',
30
70
  'Original user ask',
31
- task,
71
+ input.task,
72
+ '',
73
+ 'Delegation reason',
74
+ input.reason || '(not supplied)',
75
+ '',
76
+ 'Success criteria or expected evidence',
77
+ input.successCriteria || '(not supplied)',
78
+ '',
79
+ 'Workspace or worktree hint',
80
+ input.workspaceHint || '(not supplied)',
81
+ '',
82
+ 'Priority or deadline',
83
+ input.priority || '(not supplied)',
32
84
  '',
33
85
  'Agent policy',
34
86
  '- GoodVibes Agent is not the coding TUI.',
35
87
  '- Preserve the full original ask.',
36
88
  '- GoodVibes TUI owns file edits, git/worktree flows, execution isolation UX, and any delegated review owner chain.',
37
- reviewRequested
89
+ input.reviewRequested
38
90
  ? '- Delegated review was explicitly requested by the Agent user for this build/fix/review handoff.'
39
91
  : '- Delegated review was not explicitly requested; do not add review solely because this came from Agent.',
40
92
  ].join('\n');
@@ -42,10 +94,11 @@ function buildDelegationBody(task: string, reviewRequested: boolean): string {
42
94
 
43
95
  export function registerDelegationRuntimeCommands(registry: CommandRegistry): void {
44
96
  const makeHandler = (defaultReview: boolean) => async (args: string[], ctx: CommandContext): Promise<void> => {
45
- const reviewRequested = defaultReview || hasAnyFlag(args, ['--review', '--wrfc']);
46
- const task = delegationTaskValues(args).join(' ').trim();
47
- if (!task) {
48
- ctx.print(defaultReview ? 'Usage: /delegate --review <build/fix/review task>' : 'Usage: /delegate [--review] <build/fix/review task>');
97
+ const input = parseDelegationArgs(args, defaultReview);
98
+ if (!input.task) {
99
+ ctx.print(defaultReview
100
+ ? 'Usage: /delegate --review [--reason <why>] [--success <evidence>] [--workspace <hint>] [--priority <priority>] <build/fix/review task>'
101
+ : 'Usage: /delegate [--review] [--reason <why>] [--success <evidence>] [--workspace <hint>] [--priority <priority>] <build/fix/review task>');
49
102
  return;
50
103
  }
51
104
  const operator = ctx.clients?.operator;
@@ -65,31 +118,39 @@ export function registerDelegationRuntimeCommands(registry: CommandRegistry): vo
65
118
  lastSeenAt: Date.now(),
66
119
  } satisfies SharedSessionParticipant;
67
120
  const session = await operator.sessions.ensureSession({
68
- title: `Agent delegation: ${task.slice(0, 72)}`,
121
+ title: `Agent delegation: ${input.task.slice(0, 72)}`,
69
122
  participant,
70
123
  metadata: {
71
124
  originSurface: 'goodvibes-agent',
72
125
  sourceSessionId: ctx.session.runtime.sessionId,
73
- task,
74
- reviewRequested,
75
- wrfcRequested: reviewRequested,
126
+ task: input.task,
127
+ reviewRequested: input.reviewRequested,
128
+ wrfcRequested: input.reviewRequested,
129
+ delegationReason: input.reason,
130
+ successCriteria: input.successCriteria,
131
+ workspaceHint: input.workspaceHint,
132
+ priority: input.priority,
76
133
  },
77
134
  });
78
135
  await operator.sessions.submitMessage({
79
136
  sessionId: session.id,
80
- body: buildDelegationBody(task, reviewRequested),
137
+ body: buildDelegationBody(input),
81
138
  surfaceKind: participant.surfaceKind,
82
139
  surfaceId: participant.surfaceId,
83
140
  externalId: participant.externalId,
84
141
  displayName: participant.displayName,
85
- title: `Agent delegation: ${task.slice(0, 72)}`,
142
+ title: `Agent delegation: ${input.task.slice(0, 72)}`,
86
143
  metadata: {
87
144
  originSurface: 'goodvibes-agent',
88
145
  sourceSessionId: ctx.session.runtime.sessionId,
89
146
  kind: 'task',
90
- task,
91
- reviewRequested,
92
- wrfcRequested: reviewRequested,
147
+ task: input.task,
148
+ reviewRequested: input.reviewRequested,
149
+ wrfcRequested: input.reviewRequested,
150
+ delegationReason: input.reason,
151
+ successCriteria: input.successCriteria,
152
+ workspaceHint: input.workspaceHint,
153
+ priority: input.priority,
93
154
  },
94
155
  routing: {
95
156
  executionIntent: {
@@ -103,8 +164,10 @@ export function registerDelegationRuntimeCommands(registry: CommandRegistry): vo
103
164
  ctx.print([
104
165
  'Delegation submitted to GoodVibes TUI/shared-session routes.',
105
166
  ` session ${session.id}`,
106
- ` mode ${reviewRequested ? 'delegated review requested' : 'direct build delegation'}`,
107
- ` task ${task}`,
167
+ ` mode ${input.reviewRequested ? 'delegated review requested' : 'direct build delegation'}`,
168
+ ` task ${input.task}`,
169
+ ...(input.reason ? [` reason ${input.reason}`] : []),
170
+ ...(input.successCriteria ? [` success ${input.successCriteria}`] : []),
108
171
  ' next check GoodVibes TUI shared-session/task status for the result.',
109
172
  ].join('\n'));
110
173
  } catch (error) {
@@ -120,8 +183,8 @@ export function registerDelegationRuntimeCommands(registry: CommandRegistry): vo
120
183
  name: 'delegate',
121
184
  aliases: ['build'],
122
185
  description: 'Explicitly delegate build/fix/review work to GoodVibes TUI through shared-session routes',
123
- usage: '[--review] <task>',
124
- argsHint: '[--review] <task>',
186
+ usage: '[--review] [--reason <why>] [--success <evidence>] [--workspace <hint>] [--priority <priority>] <task>',
187
+ argsHint: '[--review] [--reason <why>] [--success <evidence>] [--workspace <hint>] [--priority <priority>] <task>',
125
188
  handler: makeHandler(false),
126
189
  });
127
190
  }
@@ -0,0 +1,12 @@
1
+ import type { BrowserKnowledgeKind, BrowserKnowledgeSourceKind } from '@pellux/goodvibes-sdk/platform/knowledge';
2
+
3
+ const BROWSER_KINDS = ['chrome', 'chromium', 'brave', 'edge', 'vivaldi', 'arc', 'opera', 'firefox', 'zen', 'librewolf', 'waterfox', 'floorp', 'safari', 'orion', 'epiphany'] as const satisfies readonly BrowserKnowledgeKind[];
4
+ const BROWSER_SOURCE_KINDS = ['history', 'bookmark'] as const satisfies readonly BrowserKnowledgeSourceKind[];
5
+
6
+ export function toBrowserKinds(values: readonly string[]): readonly BrowserKnowledgeKind[] {
7
+ return values.filter((value): value is BrowserKnowledgeKind => BROWSER_KINDS.includes(value as BrowserKnowledgeKind));
8
+ }
9
+
10
+ export function toBrowserSourceKinds(values: readonly string[]): readonly BrowserKnowledgeSourceKind[] {
11
+ return values.filter((value): value is BrowserKnowledgeSourceKind => BROWSER_SOURCE_KINDS.includes(value as BrowserKnowledgeSourceKind));
12
+ }
@@ -1,11 +1,9 @@
1
1
  import type { KnowledgeMapResult, KnowledgeService } from '@pellux/goodvibes-sdk/platform/knowledge';
2
- import type { BrowserKnowledgeKind, BrowserKnowledgeSourceKind } from '@pellux/goodvibes-sdk/platform/knowledge';
3
2
  import type { CommandContext, SlashCommand } from '../command-registry.ts';
4
3
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
4
+ import { toBrowserKinds, toBrowserSourceKinds } from './knowledge-browser-flags.ts';
5
5
 
6
6
  const KNOWLEDGE_REVIEW_ACTIONS = ['accept', 'reject', 'resolve', 'reopen', 'edit', 'forget'] as const;
7
- const BROWSER_KINDS = ['chrome', 'chromium', 'brave', 'edge', 'vivaldi', 'arc', 'opera', 'firefox', 'zen', 'librewolf', 'waterfox', 'floorp', 'safari', 'orion', 'epiphany'] as const satisfies readonly BrowserKnowledgeKind[];
8
- const BROWSER_SOURCE_KINDS = ['history', 'bookmark'] as const satisfies readonly BrowserKnowledgeSourceKind[];
9
7
 
10
8
  type KnowledgeReviewAction = typeof KNOWLEDGE_REVIEW_ACTIONS[number];
11
9
  type KnowledgeAskInput = Parameters<KnowledgeService['ask']>[0];
@@ -78,14 +76,6 @@ function readFirstStringListFlag(args: string[], names: readonly string[]): stri
78
76
  return [];
79
77
  }
80
78
 
81
- function toBrowserKinds(values: readonly string[]): readonly BrowserKnowledgeKind[] {
82
- return values.filter((value): value is BrowserKnowledgeKind => BROWSER_KINDS.includes(value as BrowserKnowledgeKind));
83
- }
84
-
85
- function toBrowserSourceKinds(values: readonly string[]): readonly BrowserKnowledgeSourceKind[] {
86
- return values.filter((value): value is BrowserKnowledgeSourceKind => BROWSER_SOURCE_KINDS.includes(value as BrowserKnowledgeSourceKind));
87
- }
88
-
89
79
  function readSinceMsFlag(args: string[]): number | undefined {
90
80
  const raw = readFlag(args, '--since-days');
91
81
  if (!raw) return undefined;
@@ -211,7 +201,7 @@ export const knowledgeCommand: SlashCommand = {
211
201
  aliases: ['know', 'kb'],
212
202
  description: 'Agent Knowledge: isolated Agent-owned status, ask/search, source/node/issue lists, item lookup, map, connectors, ingest, and review queue.',
213
203
  usage: '<subcommand> [args]',
214
- argsHint: 'status|ask|search|list|get|map|connectors|connector|connector-doctor|ingest-url --yes|ingest-file --yes|import-urls --yes|import-bookmarks --yes|import-browser-history --yes|ingest-connector --yes|review-issue --yes|reindex --yes',
204
+ argsHint: 'status|ask|search|list|get|map|connectors|connector|connector-doctor|ingest-url --yes|ingest-file --yes|ingest-artifact --yes|import-urls --yes|import-bookmarks --yes|import-browser-history --yes|ingest-connector --yes|review-issue --yes|reindex --yes',
215
205
  handler: async (args: string[], context: CommandContext): Promise<void> => {
216
206
  if (args.length === 0 && context.openAgentWorkspace) {
217
207
  context.openAgentWorkspace('knowledge');
@@ -295,8 +285,7 @@ export const knowledgeCommand: SlashCommand = {
295
285
  break;
296
286
  }
297
287
 
298
- case 'ingest-file':
299
- case 'ingest-artifact': {
288
+ case 'ingest-file': {
300
289
  const [path] = positionalArgs(rest, ['--title', '--tags', '--folder', '--connector']);
301
290
  if (!path) {
302
291
  context.print('[knowledge] Usage: /knowledge ingest-file <path> [--title <title>] [--tags <a,b>] [--folder <path>] --yes');
@@ -320,6 +309,30 @@ export const knowledgeCommand: SlashCommand = {
320
309
  break;
321
310
  }
322
311
 
312
+ case 'ingest-artifact': {
313
+ const [artifactId] = positionalArgs(rest, ['--title', '--tags', '--folder', '--connector']);
314
+ if (!artifactId) {
315
+ context.print('[knowledge] Usage: /knowledge ingest-artifact <artifactId> [--title <title>] [--tags <a,b>] [--folder <path>] --yes');
316
+ return;
317
+ }
318
+ if (!confirmation.yes) {
319
+ requireYesFlag(context, `ingest artifact into Agent Knowledge ${artifactId}`, '/knowledge ingest-artifact <artifactId> [--title <title>] [--tags <a,b>] [--folder <path>] --yes');
320
+ return;
321
+ }
322
+ const result = await knowledge.ingest.artifact({
323
+ artifactId,
324
+ title: readFlag(rest, '--title'),
325
+ tags: readStringListFlag(rest, '--tags'),
326
+ folderPath: readFlag(rest, '--folder'),
327
+ sessionId: context.session.runtime.sessionId,
328
+ connectorId: readFlag(rest, '--connector') ?? 'goodvibes-agent-artifact-browser',
329
+ });
330
+ context.print(`[knowledge] Ingested ${result.source.id} ${result.source.canonicalUri ?? result.source.sourceUri ?? artifactId}`);
331
+ if (result.source.summary) context.print(` ${result.source.summary}`);
332
+ if (result.artifactId) context.print(` artifact: ${result.artifactId}`);
333
+ break;
334
+ }
335
+
323
336
  case 'import-bookmarks': {
324
337
  const [path] = positionalArgs(rest);
325
338
  if (!path) {
@@ -757,6 +770,7 @@ export const knowledgeCommand: SlashCommand = {
757
770
  ' ask <query> [--limit <n>] [--mode <concise|standard|detailed>]',
758
771
  ' ingest-url <url> [--title <title>] [--tags <a,b>] [--folder <path>] --yes',
759
772
  ' ingest-file <path> [--title <title>] [--tags <a,b>] [--folder <path>] --yes',
773
+ ' ingest-artifact <artifactId> [--title <title>] [--tags <a,b>] [--folder <path>] --yes',
760
774
  ' ingest-connector <connectorId> [--input <json-or-text>|--path <path>|--content <text>] --yes',
761
775
  ' import-bookmarks <path> --yes',
762
776
  ' import-urls <path> --yes',
@@ -98,6 +98,9 @@ function automationActionFromParts(scope: string, verb: string): {
98
98
  if ((scope === 'run' || scope === 'runs') && verb === 'cancel') return { action: 'automation.runs.cancel', targetField: 'runId' };
99
99
  if ((scope === 'run' || scope === 'runs') && verb === 'retry') return { action: 'automation.runs.retry', targetField: 'runId' };
100
100
  if ((scope === 'schedule' || scope === 'schedules') && verb === 'run') return { action: 'schedules.run', targetField: 'scheduleId' };
101
+ if ((scope === 'schedule' || scope === 'schedules') && verb === 'enable') return { action: 'schedules.enable', targetField: 'scheduleId' };
102
+ if ((scope === 'schedule' || scope === 'schedules') && verb === 'disable') return { action: 'schedules.disable', targetField: 'scheduleId' };
103
+ if ((scope === 'schedule' || scope === 'schedules') && (verb === 'delete' || verb === 'remove')) return { action: 'schedules.delete', targetField: 'scheduleId' };
101
104
  return null;
102
105
  }
103
106
 
@@ -120,14 +123,14 @@ export function registerOperatorActionRuntimeCommands(registry: CommandRegistry)
120
123
  name: 'automation',
121
124
  aliases: ['auto'],
122
125
  description: 'Run confirmed connected-host automation actions from the Agent TUI',
123
- usage: 'job <run|pause|resume> <job-id> --yes | run <cancel|retry> <run-id> --yes | schedule run <schedule-id> --yes',
124
- argsHint: 'job run <id> --yes | run cancel <id> --yes | schedule run <id> --yes',
126
+ usage: 'job <run|pause|resume> <job-id> --yes | run <cancel|retry> <run-id> --yes | schedule <run|enable|disable|delete> <schedule-id> --yes',
127
+ argsHint: 'job run <id> --yes | run cancel <id> --yes | schedule disable <id> --yes',
125
128
  async handler(args, ctx) {
126
129
  const scope = (args[0] ?? '').toLowerCase();
127
130
  const verb = (args[1] ?? '').toLowerCase();
128
131
  const targetId = args[2] ?? '';
129
132
  const mapping = automationActionFromParts(scope, verb);
130
- const usage = '/automation job <run|pause|resume> <job-id> --yes | /automation run <cancel|retry> <run-id> --yes | /automation schedule run <schedule-id> --yes';
133
+ const usage = '/automation job <run|pause|resume> <job-id> --yes | /automation run <cancel|retry> <run-id> --yes | /automation schedule <run|enable|disable|delete> <schedule-id> --yes';
131
134
  if (!mapping || !targetId) {
132
135
  ctx.print(`Usage: ${usage}`);
133
136
  return;