@pellux/goodvibes-agent 1.1.7 → 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 (255) hide show
  1. package/CHANGELOG.md +170 -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 +132577 -91483
  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 +39 -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 +199 -5
  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 +137 -7
  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 +106 -85
  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/version.ts +1 -1
@@ -0,0 +1,140 @@
1
+ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
2
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
3
+ import type { CommandContext, CommandRegistry } from '../input/command-registry.ts';
4
+ import { createAgentHarnessTool } from './agent-harness-tool.ts';
5
+
6
+ type AgentChannelsAction = 'status' | 'channel' | 'setup' | 'triage' | 'deliveries';
7
+
8
+ interface AgentChannelsToolArgs {
9
+ readonly action?: unknown;
10
+ readonly mode?: unknown;
11
+ readonly channelId?: unknown;
12
+ readonly id?: unknown;
13
+ readonly target?: unknown;
14
+ readonly query?: unknown;
15
+ readonly includeParameters?: unknown;
16
+ readonly limit?: unknown;
17
+ }
18
+
19
+ interface AgentChannelsToolDeps {
20
+ readonly commandRegistry: CommandRegistry;
21
+ readonly commandContext: CommandContext;
22
+ readonly toolRegistry: ToolRegistry;
23
+ readonly harnessTool?: Tool;
24
+ }
25
+
26
+ function readString(value: unknown): string {
27
+ return typeof value === 'string' ? value.trim() : '';
28
+ }
29
+
30
+ function normalizeChannelsAction(value: unknown): AgentChannelsAction | null {
31
+ const action = readString(value).toLowerCase().replace(/-/g, '_');
32
+ if (!action) return null;
33
+ if (action === 'status' || action === 'summary' || action === 'list' || action === 'readiness' || action === 'channels') return 'status';
34
+ if (action === 'channel' || action === 'show' || action === 'inspect') return 'channel';
35
+ if (action === 'setup' || action === 'guide' || action === 'setup_guide' || action === 'channel_setup_guide') return 'setup';
36
+ if (action === 'triage' || action === 'inbox' || action === 'blockers' || action === 'retries' || action === 'channel_triage') return 'triage';
37
+ if (action === 'deliveries' || action === 'delivery' || action === 'receipts' || action === 'history' || action === 'channel_deliveries') return 'deliveries';
38
+ return null;
39
+ }
40
+
41
+ function readAction(args: AgentChannelsToolArgs): AgentChannelsAction {
42
+ const explicit = normalizeChannelsAction(args.action) ?? normalizeChannelsAction(args.mode);
43
+ if (explicit) return explicit;
44
+ if (readString(args.channelId) || readString(args.id)) return 'channel';
45
+ return 'status';
46
+ }
47
+
48
+ function compactArgs(entries: Record<string, unknown>): Record<string, unknown> {
49
+ return Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== undefined && value !== ''));
50
+ }
51
+
52
+ function channelIdArg(args: AgentChannelsToolArgs): unknown {
53
+ return readString(args.channelId) || readString(args.id) || undefined;
54
+ }
55
+
56
+ export function createAgentChannelsTool(deps: AgentChannelsToolDeps): Tool {
57
+ const harnessTool = deps.harnessTool ?? createAgentHarnessTool({
58
+ commandRegistry: deps.commandRegistry,
59
+ commandContext: deps.commandContext,
60
+ toolRegistry: deps.toolRegistry,
61
+ });
62
+
63
+ return {
64
+ definition: {
65
+ name: 'channels',
66
+ description: 'Inspect channel readiness, setup, triage, and receipts.',
67
+ parameters: {
68
+ type: 'object',
69
+ properties: {
70
+ action: {
71
+ type: 'string',
72
+ enum: ['status', 'channel', 'setup', 'triage', 'deliveries'],
73
+ description: 'Read channel status, setup, triage, or receipts.',
74
+ },
75
+ mode: { type: 'string', description: 'Alias for action.' },
76
+ channelId: { type: 'string', description: 'Channel id to inspect.' },
77
+ id: { type: 'string', description: 'Alias for channelId.' },
78
+ target: { type: 'string', description: 'Channel lookup target.' },
79
+ query: { type: 'string', description: 'Search text.' },
80
+ includeParameters: { type: 'boolean', description: 'Include route detail and safe config-key names.' },
81
+ limit: { type: 'number', description: 'Maximum triage, delivery, or channel rows.' },
82
+ },
83
+ additionalProperties: false,
84
+ },
85
+ sideEffects: [],
86
+ concurrency: 'parallel',
87
+ },
88
+ execute: async (rawArgs: unknown) => {
89
+ const args = (rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs) ? rawArgs : {}) as AgentChannelsToolArgs;
90
+ const action = readAction(args);
91
+
92
+ if (action === 'channel') {
93
+ return harnessTool.execute(compactArgs({
94
+ mode: 'channel',
95
+ channelId: channelIdArg(args),
96
+ target: args.target,
97
+ query: args.query,
98
+ includeParameters: args.includeParameters,
99
+ }));
100
+ }
101
+ if (action === 'setup') {
102
+ return harnessTool.execute(compactArgs({
103
+ mode: 'channel_setup_guide',
104
+ channelId: channelIdArg(args),
105
+ target: args.target,
106
+ query: args.query,
107
+ includeParameters: args.includeParameters,
108
+ }));
109
+ }
110
+ if (action === 'triage') {
111
+ return harnessTool.execute(compactArgs({
112
+ mode: 'channel_triage',
113
+ limit: args.limit,
114
+ includeParameters: args.includeParameters,
115
+ }));
116
+ }
117
+ if (action === 'deliveries') {
118
+ return harnessTool.execute(compactArgs({
119
+ mode: 'channel_deliveries',
120
+ limit: args.limit,
121
+ includeParameters: args.includeParameters,
122
+ }));
123
+ }
124
+ return harnessTool.execute(compactArgs({
125
+ mode: 'channels',
126
+ query: args.query ?? args.target,
127
+ limit: args.limit,
128
+ includeParameters: args.includeParameters,
129
+ }));
130
+ },
131
+ };
132
+ }
133
+
134
+ export function registerAgentChannelsTool(
135
+ registry: ToolRegistry,
136
+ commandRegistry: CommandRegistry,
137
+ commandContext: CommandContext,
138
+ ): void {
139
+ if (!registry.has('channels')) registry.register(createAgentChannelsTool({ commandRegistry, commandContext, toolRegistry: registry }));
140
+ }
@@ -0,0 +1,168 @@
1
+ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
2
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
3
+ import type { CommandContext, CommandRegistry } from '../input/command-registry.ts';
4
+ import { createAgentHarnessTool } from './agent-harness-tool.ts';
5
+
6
+ type AgentComputerAction =
7
+ | 'status'
8
+ | 'plan'
9
+ | 'control'
10
+ | 'browser'
11
+ | 'open_browser'
12
+ | 'setup'
13
+ | 'mcp';
14
+
15
+ interface AgentComputerToolArgs {
16
+ readonly action?: unknown;
17
+ readonly mode?: unknown;
18
+ readonly target?: unknown;
19
+ readonly query?: unknown;
20
+ readonly includeParameters?: unknown;
21
+ readonly confirm?: unknown;
22
+ readonly explicitUserRequest?: unknown;
23
+ }
24
+
25
+ interface AgentComputerToolDeps {
26
+ readonly commandRegistry: CommandRegistry;
27
+ readonly commandContext: CommandContext;
28
+ readonly toolRegistry: ToolRegistry;
29
+ readonly harnessTool?: Tool;
30
+ }
31
+
32
+ function error(message: string): { readonly success: false; readonly error: string } {
33
+ return { success: false, error: message };
34
+ }
35
+
36
+ function readString(value: unknown): string {
37
+ return typeof value === 'string' ? value.trim() : '';
38
+ }
39
+
40
+ function normalizeComputerAction(value: unknown): AgentComputerAction | null {
41
+ const action = readString(value).toLowerCase().replace(/-/g, '_');
42
+ if (!action) return null;
43
+ if (action === 'status' || action === 'summary' || action === 'overview' || action === 'computer' || action === 'computer_use') return 'status';
44
+ if (action === 'plan' || action === 'route' || action === 'control_plan' || action === 'browser_plan' || action === 'desktop_plan' || action === 'screenshot' || action === 'screen' || action === 'screen_recording' || action === 'observe') return 'plan';
45
+ if (action === 'control' || action === 'browser_control' || action === 'desktop' || action === 'desktop_control') return 'control';
46
+ if (action === 'browser' || action === 'pwa' || action === 'cockpit' || action === 'browser_cockpit' || action === 'web') return 'browser';
47
+ if (action === 'open' || action === 'open_browser' || action === 'open_pwa' || action === 'open_cockpit' || action === 'open_browser_cockpit') return 'open_browser';
48
+ if (action === 'setup' || action === 'configure' || action === 'browser_desktop_control') return 'setup';
49
+ if (action === 'mcp' || action === 'tools' || action === 'servers' || action === 'mcp_servers') return 'mcp';
50
+ return null;
51
+ }
52
+
53
+ function readAction(args: AgentComputerToolArgs): AgentComputerAction | null {
54
+ const explicit = readString(args.action) || readString(args.mode);
55
+ return explicit ? normalizeComputerAction(explicit) : 'status';
56
+ }
57
+
58
+ function compactArgs(entries: Record<string, unknown>): Record<string, unknown> {
59
+ return Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== undefined && value !== ''));
60
+ }
61
+
62
+ function controlArgs(args: AgentComputerToolArgs): Record<string, unknown> {
63
+ return compactArgs({
64
+ mode: 'execution_route',
65
+ executionRouteId: 'browser-or-desktop-control',
66
+ includeParameters: args.includeParameters ?? true,
67
+ });
68
+ }
69
+
70
+ function planArgs(args: AgentComputerToolArgs): Record<string, unknown> {
71
+ const rawAction = readString(args.action) || readString(args.mode);
72
+ const normalizedAction = rawAction.toLowerCase().replace(/-/g, '_');
73
+ const actionAsQuery = ['screenshot', 'screen', 'screen_recording', 'observe'].includes(normalizedAction) ? rawAction : undefined;
74
+ return compactArgs({
75
+ mode: 'browser_control_route',
76
+ query: args.query ?? args.target ?? actionAsQuery,
77
+ includeParameters: args.includeParameters,
78
+ });
79
+ }
80
+
81
+ function browserArgs(args: AgentComputerToolArgs): Record<string, unknown> {
82
+ return compactArgs({
83
+ mode: 'ui_surface',
84
+ surfaceId: 'connected-browser-cockpit',
85
+ includeParameters: args.includeParameters ?? true,
86
+ });
87
+ }
88
+
89
+ function openBrowserArgs(args: AgentComputerToolArgs): Record<string, unknown> {
90
+ return compactArgs({
91
+ mode: 'open_ui_surface',
92
+ surfaceId: 'connected-browser-cockpit',
93
+ confirm: args.confirm,
94
+ explicitUserRequest: args.explicitUserRequest,
95
+ });
96
+ }
97
+
98
+ function setupArgs(args: AgentComputerToolArgs): Record<string, unknown> {
99
+ return compactArgs({
100
+ mode: 'setup_item',
101
+ setupItemId: 'browser-desktop-control',
102
+ includeParameters: args.includeParameters ?? true,
103
+ });
104
+ }
105
+
106
+ function mcpArgs(args: AgentComputerToolArgs): Record<string, unknown> {
107
+ return compactArgs({
108
+ mode: 'mcp_servers',
109
+ query: args.query ?? args.target ?? 'browser desktop',
110
+ includeParameters: args.includeParameters,
111
+ });
112
+ }
113
+
114
+ export function createAgentComputerTool(deps: AgentComputerToolDeps): Tool {
115
+ const harnessTool = deps.harnessTool ?? createAgentHarnessTool({
116
+ commandRegistry: deps.commandRegistry,
117
+ commandContext: deps.commandContext,
118
+ toolRegistry: deps.toolRegistry,
119
+ });
120
+
121
+ return {
122
+ definition: {
123
+ name: 'computer',
124
+ description: 'Inspect/open browser, desktop, and computer-use routes.',
125
+ parameters: {
126
+ type: 'object',
127
+ properties: {
128
+ action: {
129
+ type: 'string',
130
+ enum: ['status', 'plan', 'control', 'browser', 'open_browser', 'setup', 'mcp'],
131
+ description: 'Computer, browser/PWA, setup, MCP, or confirmed open route.',
132
+ },
133
+ mode: { type: 'string', description: 'Alias for action.' },
134
+ target: { type: 'string', description: 'Lookup or search target.' },
135
+ query: { type: 'string', description: 'Search text for MCP review.' },
136
+ includeParameters: { type: 'boolean', description: 'Include detailed route contracts.' },
137
+ confirm: { type: 'boolean', description: 'Required true for visible open actions.' },
138
+ explicitUserRequest: { type: 'string', description: 'User request authorizing a visible open action.' },
139
+ },
140
+ additionalProperties: false,
141
+ },
142
+ sideEffects: ['state'],
143
+ concurrency: 'serial',
144
+ },
145
+ execute: async (rawArgs: unknown) => {
146
+ const args = (rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs) ? rawArgs : {}) as AgentComputerToolArgs;
147
+ const action = readAction(args);
148
+ if (!action) return error('Unknown computer action. Use action:"status" for browser/desktop control posture.');
149
+
150
+ if (action === 'status' || action === 'control') return harnessTool.execute(controlArgs(args));
151
+ if (action === 'plan') return harnessTool.execute(planArgs(args));
152
+ if (action === 'browser') return harnessTool.execute(browserArgs(args));
153
+ if (action === 'open_browser') return harnessTool.execute(openBrowserArgs(args));
154
+ if (action === 'setup') return harnessTool.execute(setupArgs(args));
155
+ if (action === 'mcp') return harnessTool.execute(mcpArgs(args));
156
+
157
+ return error('Unknown computer action. Use action:"status" for browser/desktop control posture.');
158
+ },
159
+ };
160
+ }
161
+
162
+ export function registerAgentComputerTool(
163
+ registry: ToolRegistry,
164
+ commandRegistry: CommandRegistry,
165
+ commandContext: CommandContext,
166
+ ): void {
167
+ if (!registry.has('computer')) registry.register(createAgentComputerTool({ commandRegistry, commandContext, toolRegistry: registry }));
168
+ }
@@ -37,13 +37,13 @@ const CONTEXT_TOOL_FALLBACK = {
37
37
  preferredTool: 'agent_harness',
38
38
  routes: {
39
39
  summary: 'agent_harness mode:"summary"',
40
- capabilities: 'agent_harness mode:"summary" includeParameters:true',
40
+ capabilities: 'goodvibes_context mode:"capabilities"',
41
41
  tools: 'agent_harness mode:"tools"',
42
42
  tool: 'agent_harness mode:"tool"',
43
- settings: 'agent_harness mode:"settings"',
44
- commands: 'agent_harness mode:"commands"',
45
- workspace: 'agent_harness mode:"workspace"',
46
- status: 'agent_harness mode:"connected_host_status"',
43
+ settings: 'settings action:"list"',
44
+ commands: 'workspace action:"commands"',
45
+ workspace: 'workspace action:"status"',
46
+ status: 'host action:"status"',
47
47
  },
48
48
  };
49
49
 
@@ -71,6 +71,8 @@ export function wrapAgentContextToolForAgentPolicy(tool: Tool, registry?: ToolRe
71
71
  tool.execute = async (rawArgs) => {
72
72
  const args = rawArgs as AgentContextArgs;
73
73
  const mode = readAgentContextMode(args.mode);
74
+ if (mode === 'capabilities') return ok(buildAgentCapabilitiesContract(registry));
75
+
74
76
  const harnessMode = agentContextModeToHarnessMode(mode);
75
77
  const harnessTool = registry?.list().find((entry) => entry.definition.name === 'agent_harness');
76
78
  if (!harnessTool) {
@@ -93,7 +95,7 @@ export function wrapAgentContextToolForAgentPolicy(tool: Tool, registry?: ToolRe
93
95
  category: args.category,
94
96
  prefix: args.prefix,
95
97
  includeHidden: args.includeHidden,
96
- includeParameters: mode === 'capabilities' ? true : args.includeParameters,
98
+ includeParameters: args.includeParameters,
97
99
  limit: args.limit,
98
100
  };
99
101
  const result = await harnessTool.execute(dropUndefined(harnessArgs));
@@ -116,7 +118,6 @@ function readAgentContextMode(value: unknown): AgentContextMode {
116
118
  }
117
119
 
118
120
  function agentContextModeToHarnessMode(mode: AgentContextMode): string {
119
- if (mode === 'capabilities') return 'summary';
120
121
  if (mode === 'modes') return 'modes';
121
122
  if (mode === 'tools') return 'tools';
122
123
  if (mode === 'tool') return 'tool';
@@ -129,6 +130,135 @@ function agentContextModeToHarnessMode(mode: AgentContextMode): string {
129
130
  return 'summary';
130
131
  }
131
132
 
133
+ function buildAgentCapabilitiesContract(registry?: ToolRegistry): Record<string, unknown> {
134
+ const availableTools = new Set(safeToolNames(registry));
135
+ const has = (name: string) => availableTools.has(name);
136
+ const optionalTool = (name: string) => has(name) ? name : `${name} (not registered)`;
137
+
138
+ return {
139
+ runtime: 'GoodVibes Agent',
140
+ answerStyle: 'Answer user capability questions from this contract. Do not dump inventory counts.',
141
+ currentContract: {
142
+ autonomy: 'User-directed operator agent. It can inspect, plan, edit, run tools, and perform confirmed effects; it is not an unrestricted background account-creation or self-expansion agent.',
143
+ confirmations: 'External sends, reminders, media generation, settings writes, slash-command execution, workspace actions, packet preset saves, and operator actions require an explicit user request plus confirm:true where the tool requires it.',
144
+ secrets: 'Do not reveal raw secrets. Use configured secret refs, provider accounts, and channel readiness routes.',
145
+ },
146
+ canDoNow: [
147
+ {
148
+ area: 'Project and computer work',
149
+ can: 'Read, search, analyze, edit, and write workspace files; run bounded shell commands; inspect diffs and project structure; recover recent file edit/write snapshots.',
150
+ tools: ['read', 'find', 'analyze', 'inspect', 'edit', 'write', 'exec', optionalTool('execution'), optionalTool('delegation')].filter(has),
151
+ inspect: 'execution action:"status"; delegation action:"status"',
152
+ },
153
+ {
154
+ area: 'Web research',
155
+ can: has('web_search')
156
+ ? 'Brief multi-step research from one read-only queue, plan routes, search the web with bounded evidence, inspect URLs, capture candidate sources in a local review queue, and summarize sourced findings in the main conversation.'
157
+ : 'Web research is not available until the web_search tool is registered.',
158
+ tools: [optionalTool('research'), optionalTool('agent_harness'), optionalTool('web_search'), optionalTool('fetch'), optionalTool('agent_research_runs'), optionalTool('agent_research_sources'), optionalTool('agent_research_report')],
159
+ inspect: 'research action:"briefing" query:"<research request>", action:"plan" for route planning, action:"search" for public source candidates, or action:"runner" for browser-backed readiness',
160
+ },
161
+ {
162
+ area: 'Harness operation',
163
+ can: 'Discover and use harness modes, slash commands, workspace actions, settings, panels, UI surfaces, keybindings, and model tools.',
164
+ tools: [optionalTool('agent_harness'), optionalTool('host'), optionalTool('settings'), 'goodvibes_context'],
165
+ inspect: 'agent_harness mode:"modes" query:"capability"',
166
+ },
167
+ {
168
+ area: 'Memory and knowledge',
169
+ can: 'Use VIBE.md personality files, Agent-local memory, notes, personas, skills, routines, prompt-context inspection, memory/vector posture, learning curator review/proposal queues, confirmed duplicate-consolidation phase helpers, work plans, and isolated Agent Knowledge ask/search/ingest routes.',
170
+ tools: [optionalTool('vibe'), optionalTool('context'), optionalTool('memory'), optionalTool('agent_harness'), optionalTool('agent_local_registry'), optionalTool('agent_learning_consolidation'), optionalTool('agent_work_plan'), optionalTool('agent_knowledge'), optionalTool('agent_knowledge_ingest')],
171
+ inspect: 'vibe action:"status"; context action:"prompt|files"; memory action:"status|curator"',
172
+ },
173
+ {
174
+ area: 'Personal operations',
175
+ can: 'Turn inbox, agenda, task, reminder, note, routine, or delivery requests into the safest visible lane, route, required fields, and confirmation boundary, then inspect the broader operations map without inventing missing connectors.',
176
+ tools: [optionalTool('personal_ops'), optionalTool('autonomy'), optionalTool('agent_harness'), optionalTool('agent_local_registry'), optionalTool('agent_work_plan'), optionalTool('schedule'), optionalTool('agent_autonomy_schedule'), optionalTool('agent_reminder_schedule'), optionalTool('agent_schedule_edit'), optionalTool('agent_channel_send')],
177
+ inspect: 'personal_ops action:"queue" for saved inbox/calendar review queues, action:"intake" query:"<personal request>", or action:"status"',
178
+ },
179
+ {
180
+ area: 'Documents and artifacts',
181
+ can: 'Create, revise, version, review, comment on, suggest changes to, attach or insert saved artifacts into, export Agent document drafts with reviewer appendices, inspect reviewer-readiness preflight, save reusable review packet presets, and share confirmed reviewer packet archive references; browse saved artifacts; track visible research run checkpoints; capture and review research source queues; save sourced research report artifacts; promote reviewed artifacts into isolated Agent Knowledge; handle uploads, source checks, generated media artifacts, and run confirmed blind model comparisons from prompts or saved text artifacts with durable review, side-by-side views, section-jump reviewer handoff diffs, judgment, task/document/benchmark-filtered analytics/synthesis, reviewer handoff, handoff archive with matching route-decision receipt evidence, route-update actions, and leave-unchanged route-decision receipts.',
182
+ tools: [optionalTool('research'), optionalTool('agent_harness'), optionalTool('agent_documents'), optionalTool('agent_review_packet_presets'), optionalTool('agent_review_packet_share'), optionalTool('agent_artifacts'), optionalTool('agent_knowledge'), optionalTool('agent_knowledge_ingest'), optionalTool('agent_media_generate'), optionalTool('agent_model_compare'), optionalTool('agent_research_runs'), optionalTool('agent_research_sources'), optionalTool('agent_research_report')],
183
+ inspect: 'agent_harness mode:"document_ops"',
184
+ },
185
+ {
186
+ area: 'Configured services and messages',
187
+ can: 'Inspect configured channel readiness, visible autonomy queue, and send one confirmed message/notification/reminder/media request or create/edit one confirmed autonomous schedule through configured targets.',
188
+ tools: [optionalTool('autonomy'), optionalTool('device'), optionalTool('agent_channel_send'), optionalTool('agent_notify'), optionalTool('schedule'), optionalTool('agent_autonomy_schedule'), optionalTool('agent_reminder_schedule'), optionalTool('agent_schedule_edit'), optionalTool('agent_media_generate')],
189
+ inspect: 'channels action:"status|triage|deliveries", autonomy action:"queue", or agent_harness mode:"notifications"',
190
+ },
191
+ {
192
+ area: 'Device, voice, and browser surfaces',
193
+ can: 'Inspect companion pairing, mobile/PWA, voice/TTS, notification, browser/desktop-control, and unpublished sensor posture without claiming unavailable device APIs; open the connected browser cockpit or TTS pickers only after confirmation.',
194
+ tools: [optionalTool('computer'), optionalTool('device'), optionalTool('agent_harness'), optionalTool('setup')],
195
+ inspect: 'computer action:"browser|control|setup|mcp"; device action:"status"; voice posture with device action:"voice"',
196
+ },
197
+ {
198
+ area: 'Provider and setup work',
199
+ can: 'Inspect provider accounts, subscriptions, model routing, hardware-scored local model cookbook setup plans, confirmed local server checks, confirmed benchmark action routes, setup posture, service posture, connected-host status, and GoodVibes settings import; apply supported settings changes when explicitly requested.',
200
+ tools: [optionalTool('models'), optionalTool('setup'), optionalTool('host'), optionalTool('settings'), optionalTool('agent_harness'), optionalTool('import_goodvibes_settings')],
201
+ inspect: 'setup action:"status"; use host action:"status|services|methods" for host diagnostics, models action:"status|local|providers" for model/provider catalogs, and settings action:"list|get" for detailed settings',
202
+ },
203
+ ],
204
+ needsSetupOrIntegration: [
205
+ 'Email inbox triage and replies are not a built-in advertised Agent tool in this package; they require a configured plugin, MCP server, or channel/service connector that exposes inbox and send/reply actions.',
206
+ 'New third-party service signup/account creation is not a built-in autonomous flow. The Agent can help fill instructions and run explicit tools, but it should not use local personal information to create accounts without a user-owned integration and confirmation path.',
207
+ 'Long-running autonomous operation requires an explicit schedule, routine, automation, research run, or connected-host route visible in the autonomy queue. The main conversation does not silently create hidden background jobs.',
208
+ 'New capabilities can come from installed plugins, MCP servers, configured services, or code changes; the Agent should inspect what is installed before claiming a capability exists.',
209
+ ],
210
+ commonRoutes: {
211
+ findCapability: 'agent_harness mode:"modes" query:"<task>"',
212
+ executionPosture: 'execution action:"status"; inspect one route with action:"route"; use terminal command:"..." background:true confirm:true explicitUserRequest:"..." for visible tracked long-running commands and process action:"list|poll|log|wait|kill|write" to manage them; inspect tracked processes with action:"processes|process", recent work with action:"history|record", and recovery posture with action:"recovery"; prefer local read/edit/exec for the current workspace, delegation action:"status" for isolation/parallel/remote',
213
+ delegation: 'delegation action:"status"; inspect one route with action:"route" delegationRouteId:"..."; delegated submission uses workspace action:"run" actionId:"delegate-task" or workspace action:"run_command" command:"/delegate ..." only after explicit confirmation',
214
+ fileRecovery: 'execution action:"recovery"; apply one snapshot with agent_harness mode:"run_file_recovery" recoveryAction:"undo|redo" confirm:true explicitUserRequest:"..."',
215
+ personalOps: 'personal_ops action:"briefing"; use action:"queue" for saved inbox/calendar review queues and refresh routes; use action:"intake" query:"<personal request>" to choose the safest lane; inspect one lane with action:"lane" laneId:"..."; run one live inbox/calendar read with action:"read" confirm:true explicitUserRequest:"..."; use schedule action:"list|create|remind|edit|run|pause|resume|delete" for connected schedules/reminders after explicit confirmation',
216
+ promptContext: 'context action:"prompt"; add includeParameters:true only when bounded prompt previews are needed; inspect context files with action:"files|file" and receipts with action:"receipts|receipt"',
217
+ memoryPosture: 'memory action:"status"; inspect one embedding or external-memory provider with action:"provider"; write/rebuild/change routes stay confirmed',
218
+ autonomyIntake: 'autonomy action:"intake" query:"<ongoing work request>"; use returned route and missing fields before creating background work',
219
+ autonomyQueue: 'autonomy action:"queue"; inspect one card with action:"item"; use returned live records/log tails when present',
220
+ setup: 'setup action:"status"; inspect one row with action:"item" setupItemId:"..."; use action:"checkpoint"; confirmed effects use action:"save_checkpoint|clear_checkpoint|token|smoke|finish|import_settings" confirm:true explicitUserRequest:"..."',
221
+ vibe: 'vibe action:"status"; inspect one file with action:"show" scope:"project|global"; confirmed effects use action:"init|import_persona" confirm:true explicitUserRequest:"..."',
222
+ settings: 'settings action:"list"; inspect one setting with action:"get" key:"..."; confirmed changes use action:"set|reset" confirm:true explicitUserRequest:"..."; import existing GoodVibes settings with action:"import" and confirm:true only after approval',
223
+ host: 'host action:"status"; inspect capabilities/services/methods with action:"capabilities|capability|services|service|methods|method"; execute exact daemon operations separately with agent_operator_method after confirmation',
224
+ settingsImport: 'settings action:"import"; previews by default and applies with confirm:true explicitUserRequest:"..." after user approval; import_goodvibes_settings remains available for compatibility',
225
+ computer: 'computer action:"status|plan|control|browser|setup|mcp"; open the connected browser cockpit with action:"open_browser" confirm:true explicitUserRequest:"..."; use this route for browser/PWA, browser/screenshot/desktop-control planning, screen, and computer-use posture',
226
+ device: 'device action:"status"; inspect one capability/route with action:"capability" capabilityId:"..."; inspect voice/media with action:"voice"; inspect one provider with action:"provider"; browser/PWA and desktop-control compatibility routes remain available but computer is the primary route',
227
+ models: 'models action:"status"; inspect one model/local endpoint route with action:"route" modelRouteId:"..."; inspect local cookbook with action:"local"; inspect providers with action:"providers"; inspect one provider with action:"provider" providerId:"..."; run local model server checks with action:"smoke" confirm:true explicitUserRequest:"..."',
228
+ learningCurator: 'memory action:"curator"; inspect one card with action:"candidate"; apply duplicate phases with agent_learning_consolidation mode:"preview|merge|stale|delete|rollback"',
229
+ documentOps: 'agent_harness mode:"document_ops"; inspect one lane with mode:"document_ops_lane"',
230
+ documents: 'agent_documents mode:"list"; show with documentId; confirmed create/update/review/comment/resolveComment/suggest/acceptSuggestion/rejectSuggestion/attachArtifact/insertArtifact/export with confirm:true',
231
+ reviewPacketPresets: 'agent_review_packet_presets mode:"list"; show with artifactId to check missing/superseded ids and reuse routes; refresh stale presets with mode:"refresh" confirm:true explicitUserRequest:"..."; save reusable packet defaults with mode:"save" confirm:true explicitUserRequest:"..."',
232
+ reviewPacketShare: 'agent_review_packet_share archiveArtifactId:"..." channel:"..." confirm:true explicitUserRequest:"..."; sends a plain-text archive reference only',
233
+ artifacts: 'agent_artifacts mode:"list"; inspect with mode:"show"; export one with mode:"export"; package selected ids with mode:"package" or mode:"archive"; promote reviewed artifact ids with agent_knowledge_ingest sourceKind:"artifact"',
234
+ researchWorkflow: 'research action:"briefing" query:"<research request>"; returns one read-only next-action queue across visible runs, sources, saved reports, browser readiness, and exact follow-up routes. Use action:"plan" for route planning, action:"search" for bounded public source candidates, and action:"runner" for browser-backed readiness only',
235
+ researchRuns: 'research action:"runs"; create visible run state with action:"create_run" confirm:true explicitUserRequest:"..."; checkpoint/pause/resume/cancel/complete use confirmed research lifecycle actions; no hidden background work starts from the ledger',
236
+ researchSources: 'research action:"sources"; capture with action:"add_source" confirm:true explicitUserRequest:"..."; review with action:"review_source" confirm:true explicitUserRequest:"..."; bundle with action:"bundle"; no Knowledge ingest occurs unless agent_knowledge_ingest is called separately',
237
+ researchReports: 'research action:"reports" lists saved sourced report artifacts; action:"report_artifact" previews one; save with action:"report" reviewed sources, citation coverage repair metadata, optional requireCitationCoverage:true, confirm:true, and explicitUserRequest',
238
+ localModelCookbook: 'models action:"local"; inspect hardware fit with action:"route" modelRouteId:"local-model-cookbook"; confirmed local server checks use action:"smoke" confirm:true explicitUserRequest:"..."',
239
+ listTools: 'agent_harness mode:"tools" query:"<task>"',
240
+ inspectTool: 'agent_harness mode:"tool" toolName:"<tool>"',
241
+ listCommands: 'workspace action:"commands" query:"<task>"',
242
+ runCommand: 'workspace action:"run_command" command:"/<command> ..." confirm:true explicitUserRequest:"..."',
243
+ listWorkspaceActions: 'workspace action:"actions" query:"<task>"',
244
+ runWorkspaceAction: 'workspace action:"run" actionId:"<id>" confirm:true explicitUserRequest:"..."',
245
+ inspectSettings: 'settings action:"list" query:"<setting>"',
246
+ setSetting: 'settings action:"set" key:"<key>" value:<value> confirm:true explicitUserRequest:"..."',
247
+ webResearch: `multi-step: research action:"briefing" query:"<research request>"; route plan: research action:"plan" query:"<research request>"; public source candidates: research action:"search" query:"<research request>"; browser readiness: research action:"runner"; raw single-shot fallback: ${has('web_search') ? 'web_search query:"<research request>" verbosity:"evidence" maxResults:10 evidenceTopN:3' : 'web_search not registered'}`,
248
+ channels: 'channels action:"status|channel|setup|triage|deliveries"; send with agent_channel_send only after explicit user request',
249
+ },
250
+ registeredModelTools: safeToolNames(registry),
251
+ };
252
+ }
253
+
254
+ function safeToolNames(registry?: ToolRegistry): readonly string[] {
255
+ try {
256
+ return registry?.getToolDefinitions().map((tool) => tool.name).sort((a, b) => a.localeCompare(b)) ?? [];
257
+ } catch {
258
+ return [];
259
+ }
260
+ }
261
+
132
262
  function dropUndefined<T extends Record<string, unknown>>(value: T): Record<string, unknown> {
133
263
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
134
264
  }
@@ -0,0 +1,143 @@
1
+ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
2
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
3
+ import type { CommandContext, CommandRegistry } from '../input/command-registry.ts';
4
+ import { createAgentHarnessTool } from './agent-harness-tool.ts';
5
+
6
+ type AgentContextAction =
7
+ | 'status'
8
+ | 'files'
9
+ | 'file'
10
+ | 'prompt'
11
+ | 'receipts'
12
+ | 'receipt';
13
+
14
+ interface AgentContextToolArgs {
15
+ readonly action?: unknown;
16
+ readonly mode?: unknown;
17
+ readonly contextFileId?: unknown;
18
+ readonly receiptId?: unknown;
19
+ readonly turnId?: unknown;
20
+ readonly outcomeStatus?: unknown;
21
+ readonly target?: unknown;
22
+ readonly query?: unknown;
23
+ readonly includeParameters?: unknown;
24
+ readonly limit?: unknown;
25
+ }
26
+
27
+ interface AgentContextToolDeps {
28
+ readonly commandRegistry: CommandRegistry;
29
+ readonly commandContext: CommandContext;
30
+ readonly toolRegistry: ToolRegistry;
31
+ readonly harnessTool?: Tool;
32
+ }
33
+
34
+ function readString(value: unknown): string {
35
+ return typeof value === 'string' ? value.trim() : '';
36
+ }
37
+
38
+ function normalizeContextAction(value: unknown): AgentContextAction | null {
39
+ const action = readString(value).toLowerCase().replace(/-/g, '_');
40
+ if (!action) return null;
41
+ if (action === 'status' || action === 'summary' || action === 'context' || action === 'current') return 'status';
42
+ if (action === 'files' || action === 'project' || action === 'project_context' || action === 'instructions') return 'files';
43
+ if (action === 'file' || action === 'show' || action === 'project_context_file' || action === 'instruction') return 'file';
44
+ if (action === 'prompt' || action === 'prompt_context' || action === 'composition' || action === 'budget') return 'prompt';
45
+ if (action === 'receipts' || action === 'turns' || action === 'outcomes') return 'receipts';
46
+ if (action === 'receipt' || action === 'turn' || action === 'outcome') return 'receipt';
47
+ return null;
48
+ }
49
+
50
+ function readAction(args: AgentContextToolArgs): AgentContextAction {
51
+ const explicit = normalizeContextAction(args.action) ?? normalizeContextAction(args.mode);
52
+ if (explicit) return explicit;
53
+ if (readString(args.receiptId) || readString(args.turnId) || readString(args.outcomeStatus)) return 'receipt';
54
+ if (readString(args.contextFileId)) return 'file';
55
+ if (readString(args.target) || readString(args.query)) return 'files';
56
+ return 'status';
57
+ }
58
+
59
+ function compactArgs(entries: Record<string, unknown>): Record<string, unknown> {
60
+ return Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== undefined && value !== ''));
61
+ }
62
+
63
+ export function createAgentContextTool(deps: AgentContextToolDeps): Tool {
64
+ const harnessTool = deps.harnessTool ?? createAgentHarnessTool({
65
+ commandRegistry: deps.commandRegistry,
66
+ commandContext: deps.commandContext,
67
+ toolRegistry: deps.toolRegistry,
68
+ });
69
+
70
+ return {
71
+ definition: {
72
+ name: 'context',
73
+ description: 'Inspect project instructions and prompt context.',
74
+ parameters: {
75
+ type: 'object',
76
+ properties: {
77
+ action: {
78
+ type: 'string',
79
+ enum: ['status', 'files', 'file', 'prompt', 'receipts', 'receipt'],
80
+ description: 'Read project files, prompt context, or receipt history.',
81
+ },
82
+ mode: { type: 'string', description: 'Alias for action.' },
83
+ contextFileId: { type: 'string', description: 'Project context file id.' },
84
+ receiptId: { type: 'string', description: 'Prompt context receipt id.' },
85
+ turnId: { type: 'string', description: 'Prompt context turn id.' },
86
+ outcomeStatus: { type: 'string', enum: ['completed', 'error', 'cancelled', 'pending'], description: 'Prompt receipt outcome filter.' },
87
+ target: { type: 'string', description: 'Target file path or context lookup text.' },
88
+ query: { type: 'string', description: 'Search text for context files.' },
89
+ includeParameters: { type: 'boolean', description: 'Include bounded bodies and receipt detail.' },
90
+ limit: { type: 'number', description: 'Maximum prompt receipts to return.' },
91
+ },
92
+ additionalProperties: false,
93
+ },
94
+ sideEffects: [],
95
+ concurrency: 'parallel',
96
+ },
97
+ execute: async (rawArgs: unknown) => {
98
+ const args = (rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs) ? rawArgs : {}) as AgentContextToolArgs;
99
+ const action = readAction(args);
100
+
101
+ if (action === 'files') {
102
+ return harnessTool.execute(compactArgs({
103
+ mode: 'project_context',
104
+ target: args.target,
105
+ query: args.query,
106
+ includeParameters: args.includeParameters,
107
+ }));
108
+ }
109
+ if (action === 'file') {
110
+ return harnessTool.execute(compactArgs({
111
+ mode: 'project_context_file',
112
+ contextFileId: args.contextFileId,
113
+ target: args.target,
114
+ query: args.query,
115
+ includeParameters: args.includeParameters,
116
+ }));
117
+ }
118
+ if (action === 'receipt' || action === 'receipts') {
119
+ return harnessTool.execute(compactArgs({
120
+ mode: 'prompt_context',
121
+ receiptId: args.receiptId,
122
+ turnId: args.turnId,
123
+ outcomeStatus: args.outcomeStatus,
124
+ limit: args.limit,
125
+ includeParameters: action === 'receipt' ? args.includeParameters ?? true : args.includeParameters,
126
+ }));
127
+ }
128
+ return harnessTool.execute(compactArgs({
129
+ mode: 'prompt_context',
130
+ limit: args.limit,
131
+ includeParameters: args.includeParameters,
132
+ }));
133
+ },
134
+ };
135
+ }
136
+
137
+ export function registerAgentContextTool(
138
+ registry: ToolRegistry,
139
+ commandRegistry: CommandRegistry,
140
+ commandContext: CommandContext,
141
+ ): void {
142
+ if (!registry.has('context')) registry.register(createAgentContextTool({ commandRegistry, commandContext, toolRegistry: registry }));
143
+ }