@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,434 @@
1
+ import type { ShellPathService } from '@/runtime/index.ts';
2
+ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
3
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
4
+ import {
5
+ AgentResearchRunRegistry,
6
+ researchRunLogTail,
7
+ researchRunReportLine,
8
+ type AgentResearchRunCreateInput,
9
+ type AgentResearchRunPhase,
10
+ type AgentResearchRunRecord,
11
+ type AgentResearchRunStatus,
12
+ } from '../agent/research-run-registry.ts';
13
+
14
+ export interface AgentResearchRunsToolArgs {
15
+ readonly mode?: unknown;
16
+ readonly id?: unknown;
17
+ readonly query?: unknown;
18
+ readonly status?: unknown;
19
+ readonly title?: unknown;
20
+ readonly question?: unknown;
21
+ readonly goal?: unknown;
22
+ readonly plan?: unknown;
23
+ readonly phase?: unknown;
24
+ readonly progress?: unknown;
25
+ readonly note?: unknown;
26
+ readonly nextSteps?: unknown;
27
+ readonly sourceIds?: unknown;
28
+ readonly reportArtifactId?: unknown;
29
+ readonly error?: unknown;
30
+ readonly includeCheckpoints?: unknown;
31
+ readonly includeLogTail?: unknown;
32
+ readonly confirm?: unknown;
33
+ readonly explicitUserRequest?: unknown;
34
+ }
35
+
36
+ type AgentResearchRunsMode =
37
+ | 'list'
38
+ | 'search'
39
+ | 'show'
40
+ | 'create'
41
+ | 'start'
42
+ | 'checkpoint'
43
+ | 'pause'
44
+ | 'resume'
45
+ | 'cancel'
46
+ | 'complete'
47
+ | 'fail'
48
+ | 'delete';
49
+
50
+ const MODES: readonly AgentResearchRunsMode[] = [
51
+ 'list',
52
+ 'search',
53
+ 'show',
54
+ 'create',
55
+ 'start',
56
+ 'checkpoint',
57
+ 'pause',
58
+ 'resume',
59
+ 'cancel',
60
+ 'complete',
61
+ 'fail',
62
+ 'delete',
63
+ ];
64
+ const STATUS_VALUES: readonly AgentResearchRunStatus[] = ['planned', 'running', 'paused', 'blocked', 'cancelled', 'completed', 'failed'];
65
+ const PHASE_VALUES: readonly AgentResearchRunPhase[] = ['planning', 'searching', 'reading', 'synthesizing', 'reviewing', 'reporting'];
66
+
67
+ function readString(value: unknown): string {
68
+ return typeof value === 'string' ? value.trim() : '';
69
+ }
70
+
71
+ function readMode(value: unknown): AgentResearchRunsMode {
72
+ return typeof value === 'string' && MODES.includes(value as AgentResearchRunsMode) ? value as AgentResearchRunsMode : 'list';
73
+ }
74
+
75
+ function readStatus(value: unknown): AgentResearchRunStatus | undefined {
76
+ return typeof value === 'string' && STATUS_VALUES.includes(value as AgentResearchRunStatus) ? value as AgentResearchRunStatus : undefined;
77
+ }
78
+
79
+ function readMutableStatus(value: unknown): AgentResearchRunStatus | undefined {
80
+ const status = readStatus(value);
81
+ if (status === 'planned' || status === 'running' || status === 'paused' || status === 'blocked') return status;
82
+ return undefined;
83
+ }
84
+
85
+ function readPhase(value: unknown): AgentResearchRunPhase | undefined {
86
+ return typeof value === 'string' && PHASE_VALUES.includes(value as AgentResearchRunPhase) ? value as AgentResearchRunPhase : undefined;
87
+ }
88
+
89
+ function readProgress(value: unknown): number | undefined {
90
+ if (typeof value === 'number' && Number.isFinite(value)) return Math.max(0, Math.min(100, Math.round(value)));
91
+ if (typeof value !== 'string' || !value.trim()) return undefined;
92
+ const parsed = Number(value);
93
+ return Number.isFinite(parsed) ? Math.max(0, Math.min(100, Math.round(parsed))) : undefined;
94
+ }
95
+
96
+ function readStringList(value: unknown): readonly string[] {
97
+ if (typeof value === 'string') {
98
+ return value.split(/[\n,]/).map((entry) => entry.replace(/^[-*]\s+/, '').trim()).filter(Boolean);
99
+ }
100
+ if (!Array.isArray(value)) return [];
101
+ return value.filter((entry): entry is string => typeof entry === 'string').map((entry) => entry.trim()).filter(Boolean);
102
+ }
103
+
104
+ function output(text: string): { readonly success: true; readonly output: string } {
105
+ return { success: true, output: text };
106
+ }
107
+
108
+ function failure(error: string): { readonly success: false; readonly error: string } {
109
+ return { success: false, error };
110
+ }
111
+
112
+ function requireId(args: AgentResearchRunsToolArgs): string {
113
+ const id = readString(args.id);
114
+ if (!id) throw new Error('id is required.');
115
+ return id;
116
+ }
117
+
118
+ function requireConfirmedWrite(args: AgentResearchRunsToolArgs, action: string): string {
119
+ const explicitUserRequest = readString(args.explicitUserRequest);
120
+ if (!explicitUserRequest) throw new Error(`${action} requires explicitUserRequest with the user's exact request or a short faithful summary.`);
121
+ if (args.confirm !== true) throw new Error(`${action} requires confirm:true after an explicit user request.`);
122
+ return explicitUserRequest;
123
+ }
124
+
125
+ function runOneLine(run: AgentResearchRunRecord): string {
126
+ const artifact = run.reportArtifactId ? ` artifact ${run.reportArtifactId}` : '';
127
+ return `${run.id} ${run.status} ${run.phase} ${run.progress}% sources ${run.sourceIds.length}${artifact} ${run.title}`;
128
+ }
129
+
130
+ function formatRunList(
131
+ title: string,
132
+ runs: readonly AgentResearchRunRecord[],
133
+ includeCheckpoints: boolean,
134
+ ): string {
135
+ if (runs.length === 0) return `${title}\nNo Agent research runs matched.`;
136
+ const lines = [
137
+ title,
138
+ ...runs.map(runOneLine),
139
+ ];
140
+ if (includeCheckpoints) {
141
+ const checkpointLines = runs
142
+ .filter((run) => run.checkpoints.length > 0)
143
+ .flatMap((run) => run.checkpoints.slice(-2).map((checkpoint) => ` ${run.id}/${checkpoint.id} ${checkpoint.status}/${checkpoint.phase} ${checkpoint.progress}% ${checkpoint.note}`));
144
+ if (checkpointLines.length > 0) lines.push('', 'Recent checkpoints', ...checkpointLines);
145
+ }
146
+ return lines.join('\n');
147
+ }
148
+
149
+ function formatRunListWithLogTail(
150
+ title: string,
151
+ runs: readonly AgentResearchRunRecord[],
152
+ includeCheckpoints: boolean,
153
+ includeLogTail: boolean,
154
+ ): string {
155
+ const base = formatRunList(title, runs, includeCheckpoints);
156
+ if (!includeLogTail || runs.length === 0) return base;
157
+ const logTail = runs.flatMap((run) => researchRunLogTail(run, 3).map((line) => ` ${run.id} ${line}`));
158
+ return logTail.length > 0 ? [base, '', 'Recent run log tail', ...logTail].join('\n') : base;
159
+ }
160
+
161
+ function logTailSection(run: AgentResearchRunRecord): readonly string[] {
162
+ const logTail = researchRunLogTail(run, 5);
163
+ return [
164
+ 'Log tail',
165
+ ...(logTail.length > 0 ? logTail.map((line) => `- ${line}`) : ['(none)']),
166
+ '',
167
+ ];
168
+ }
169
+
170
+ function routeString(value: string): string {
171
+ return JSON.stringify(value);
172
+ }
173
+
174
+ function runNextRouteLines(run: AgentResearchRunRecord): readonly string[] {
175
+ const lines = [
176
+ ` inspect research action:"run" runId:${routeString(run.id)}`,
177
+ ` briefing research action:"briefing" target:${routeString(run.id)}`,
178
+ ` workflow research action:"plan" runId:${routeString(run.id)}`,
179
+ ];
180
+ if (run.status === 'planned') {
181
+ lines.push(
182
+ ` start research action:"start_run" id:${routeString(run.id)} confirm:true explicitUserRequest:"..."`,
183
+ ` search research action:"search" runId:${routeString(run.id)} maxResults:5`,
184
+ ` checkpoint research action:"checkpoint" id:${routeString(run.id)} phase:"searching" progress:10 note:"Started source collection." confirm:true explicitUserRequest:"..."`,
185
+ );
186
+ } else if (run.status === 'running') {
187
+ lines.push(
188
+ ` search research action:"search" runId:${routeString(run.id)} maxResults:5`,
189
+ ` sources research action:"sources" query:${routeString(run.question)} includeReportLines:true`,
190
+ ` checkpoint research action:"checkpoint" id:${routeString(run.id)} phase:"reading" progress:${Math.max(run.progress, 25)} note:"Captured and reviewed source candidates." sourceIds:["..."] confirm:true explicitUserRequest:"..."`,
191
+ ` bundle research action:"bundle" query:${routeString(run.question)} includeReportLines:true`,
192
+ ` report research action:"report" question:${routeString(run.question)} sources:[...] visualReport:true requireCitationCoverage:true confirm:true explicitUserRequest:"..."`,
193
+ ` pause research action:"pause" id:${routeString(run.id)} confirm:true explicitUserRequest:"..."`,
194
+ ` cancel research action:"cancel" id:${routeString(run.id)} note:"..." confirm:true explicitUserRequest:"..."`,
195
+ ` complete research action:"complete" id:${routeString(run.id)} reportArtifactId:"..." confirm:true explicitUserRequest:"..."`,
196
+ );
197
+ } else if (run.status === 'paused' || run.status === 'blocked') {
198
+ lines.push(
199
+ ` resume research action:"resume" id:${routeString(run.id)} confirm:true explicitUserRequest:"..."`,
200
+ ` checkpoint research action:"checkpoint" id:${routeString(run.id)} status:"running" phase:${routeString(run.phase)} progress:${run.progress} note:"Resumed with updated next steps." confirm:true explicitUserRequest:"..."`,
201
+ ` cancel research action:"cancel" id:${routeString(run.id)} note:"..." confirm:true explicitUserRequest:"..."`,
202
+ );
203
+ } else if (run.status === 'completed') {
204
+ lines.push(
205
+ ` reports research action:"reports" query:${routeString(run.title)} includeContent:false`,
206
+ ...(run.reportArtifactId ? [
207
+ ` reportArtifact research action:"report_artifact" artifactId:${routeString(run.reportArtifactId)}`,
208
+ ` promoteKnowledge agent_knowledge_ingest sourceKind:"artifact" artifactId:${routeString(run.reportArtifactId)} confirm:true explicitUserRequest:"..."`,
209
+ ] : [
210
+ ` attachReport research action:"complete" id:${routeString(run.id)} reportArtifactId:"..." confirm:true explicitUserRequest:"..."`,
211
+ ]),
212
+ );
213
+ } else {
214
+ lines.push(
215
+ ` list research action:"runs" status:${routeString(run.status)}`,
216
+ ` followup research action:"create_run" question:${routeString(run.question)} plan:["Follow up on the stopped research run."] confirm:true explicitUserRequest:"..."`,
217
+ );
218
+ }
219
+ return lines;
220
+ }
221
+
222
+ function deletedRunRouteLines(run: AgentResearchRunRecord): readonly string[] {
223
+ return [
224
+ ` list research action:"runs"`,
225
+ ` recreate research action:"create_run" title:${routeString(run.title)} question:${routeString(run.question)} plan:["Follow up on the stopped research run."] confirm:true explicitUserRequest:"..."`,
226
+ ];
227
+ }
228
+
229
+ function formatRunDetail(run: AgentResearchRunRecord): string {
230
+ const lines = [
231
+ `Research run ${run.id}`,
232
+ `title ${run.title}`,
233
+ `question ${run.question}`,
234
+ `goal ${run.goal}`,
235
+ `status ${run.status}`,
236
+ `phase ${run.phase}`,
237
+ `progress ${run.progress}%`,
238
+ `sources ${run.sourceIds.join(', ') || '(none)'}`,
239
+ ...(run.reportArtifactId ? [`reportArtifact ${run.reportArtifactId}`] : []),
240
+ `created ${run.createdAt}`,
241
+ `updated ${run.updatedAt}`,
242
+ ...(run.startedAt ? [`started ${run.startedAt}`] : []),
243
+ ...(run.pausedAt ? [`paused ${run.pausedAt}`] : []),
244
+ ...(run.cancelledAt ? [`cancelled ${run.cancelledAt}`] : []),
245
+ ...(run.completedAt ? [`completed ${run.completedAt}`] : []),
246
+ ...(run.failedAt ? [`failed ${run.failedAt}`] : []),
247
+ '',
248
+ 'Plan',
249
+ ...(run.plan.length > 0 ? run.plan.map((step) => `- ${step}`) : ['(none)']),
250
+ '',
251
+ 'Next steps',
252
+ ...(run.nextSteps.length > 0 ? run.nextSteps.map((step) => `- ${step}`) : ['(none)']),
253
+ '',
254
+ ...(run.note ? ['Note', run.note, ''] : []),
255
+ ...(run.error ? ['Error', run.error, ''] : []),
256
+ 'Run line',
257
+ researchRunReportLine(run),
258
+ '',
259
+ 'Checkpoints',
260
+ ...(run.checkpoints.length > 0
261
+ ? run.checkpoints.map((checkpoint) => `- ${checkpoint.id} ${checkpoint.at} ${checkpoint.status}/${checkpoint.phase} ${checkpoint.progress}% ${checkpoint.note}`)
262
+ : ['(none)']),
263
+ '',
264
+ ...logTailSection(run),
265
+ 'Routes',
266
+ `checkpoint research action:"checkpoint" id:"${run.id}" confirm:true explicitUserRequest:"..."`,
267
+ `pause research action:"pause" id:"${run.id}" confirm:true explicitUserRequest:"..."`,
268
+ `resume research action:"resume" id:"${run.id}" confirm:true explicitUserRequest:"..."`,
269
+ `cancel research action:"cancel" id:"${run.id}" note:"..." confirm:true explicitUserRequest:"..."`,
270
+ `complete research action:"complete" id:"${run.id}" reportArtifactId:"..." confirm:true explicitUserRequest:"..."`,
271
+ 'report research action:"report" confirm:true explicitUserRequest:"..."',
272
+ '',
273
+ 'Next routes',
274
+ ...runNextRouteLines(run),
275
+ '',
276
+ 'Policy: research run records are local visible state only; web research, report artifacts, Knowledge ingest, and external sends stay on separate explicit routes.',
277
+ ];
278
+ return lines.join('\n');
279
+ }
280
+
281
+ function formatMutationResult(action: string, run: AgentResearchRunRecord): string {
282
+ const nextRoutes = action.startsWith('Deleted') ? deletedRunRouteLines(run) : runNextRouteLines(run);
283
+ return [
284
+ action,
285
+ ` id ${run.id}`,
286
+ ` status ${run.status}`,
287
+ ` phase ${run.phase}`,
288
+ ` progress ${run.progress}%`,
289
+ ` sources ${run.sourceIds.length}`,
290
+ ` title ${run.title}`,
291
+ ` runLine ${researchRunReportLine(run)}`,
292
+ ' nextRoutes',
293
+ ...nextRoutes,
294
+ ' policy local visible run state only; no web search, Knowledge ingest, artifact save, or external message was sent',
295
+ ].join('\n');
296
+ }
297
+
298
+ function createInput(args: AgentResearchRunsToolArgs, explicitUserRequest: string): AgentResearchRunCreateInput {
299
+ const goal = readString(args.goal);
300
+ const note = readString(args.note);
301
+ return {
302
+ title: readString(args.title),
303
+ question: readString(args.question),
304
+ ...(goal ? { goal } : {}),
305
+ plan: readStringList(args.plan),
306
+ nextSteps: readStringList(args.nextSteps),
307
+ sourceIds: readStringList(args.sourceIds),
308
+ ...(note ? { note } : {}),
309
+ provenance: explicitUserRequest,
310
+ };
311
+ }
312
+
313
+ function createAgentResearchRunsTool(shellPaths?: Pick<ShellPathService, 'resolveProjectPath'>): Tool {
314
+ return {
315
+ definition: {
316
+ name: 'agent_research_runs',
317
+ description: 'Track visible local deep-research run state and checkpoints.',
318
+ parameters: {
319
+ type: 'object',
320
+ properties: {
321
+ mode: { type: 'string', enum: MODES, description: 'Research run operation.' },
322
+ id: { type: 'string', description: 'Research run id or title for show/control/delete.' },
323
+ query: { type: 'string', description: 'Search text for search/list filtering.' },
324
+ status: { type: 'string', enum: STATUS_VALUES, description: 'Optional status filter for list, or non-terminal checkpoint status.' },
325
+ title: { type: 'string', description: 'Short research run title.' },
326
+ question: { type: 'string', description: 'Research question.' },
327
+ goal: { type: 'string', description: 'User-visible outcome for the run.' },
328
+ plan: { type: 'array', items: { type: 'string' }, description: 'Research plan steps.' },
329
+ phase: { type: 'string', enum: PHASE_VALUES, description: 'Current run phase.' },
330
+ progress: { type: 'number', description: '0-100 run progress.' },
331
+ note: { type: 'string', description: 'Checkpoint, pause, cancel, completion, or general note.' },
332
+ nextSteps: { type: 'array', items: { type: 'string' }, description: 'Next visible research steps.' },
333
+ sourceIds: { type: 'array', items: { type: 'string' }, description: 'Project-local research source ids attached to this run.' },
334
+ reportArtifactId: { type: 'string', description: 'Saved report artifact id when completing the run.' },
335
+ error: { type: 'string', description: 'Failure note for fail mode.' },
336
+ includeCheckpoints: { type: 'boolean', description: 'Include recent checkpoint lines in list/search output.' },
337
+ includeLogTail: { type: 'boolean', description: 'Include recent run log tail in list/search output.' },
338
+ confirm: { type: 'boolean', description: 'Required true for local run-state writes.' },
339
+ explicitUserRequest: { type: 'string', description: 'User request authorizing local research run writes.' },
340
+ },
341
+ required: ['mode'],
342
+ additionalProperties: false,
343
+ },
344
+ sideEffects: ['state'],
345
+ concurrency: 'serial',
346
+ },
347
+ execute: async (rawArgs: Record<string, unknown>) => {
348
+ if (!shellPaths) return failure('Research run ledger is unavailable because this runtime did not provide shell paths.');
349
+ const registry = AgentResearchRunRegistry.fromShellPaths(shellPaths);
350
+ const args = rawArgs as AgentResearchRunsToolArgs;
351
+ const mode = readMode(args.mode);
352
+ try {
353
+ if (mode === 'list') {
354
+ const status = readStatus(args.status);
355
+ const runs = registry.list(status);
356
+ return output(formatRunListWithLogTail(
357
+ status ? `Agent research runs (${status})` : 'Agent research runs',
358
+ runs,
359
+ args.includeCheckpoints === true,
360
+ args.includeLogTail === true,
361
+ ));
362
+ }
363
+ if (mode === 'search') {
364
+ const query = readString(args.query);
365
+ return output(formatRunListWithLogTail(`Agent research run search ${query || '(all)'}`, registry.search(query), args.includeCheckpoints === true, args.includeLogTail === true));
366
+ }
367
+ if (mode === 'show') {
368
+ const run = registry.get(requireId(args));
369
+ return run ? output(formatRunDetail(run)) : failure(`Unknown research run ${readString(args.id)}`);
370
+ }
371
+ if (mode === 'create') {
372
+ const explicitUserRequest = requireConfirmedWrite(args, 'Research run creation');
373
+ return output(formatMutationResult('Created Agent research run', registry.create(createInput(args, explicitUserRequest))));
374
+ }
375
+ if (mode === 'start') {
376
+ requireConfirmedWrite(args, 'Research run start');
377
+ return output(formatMutationResult('Started Agent research run', registry.start(requireId(args), readString(args.note))));
378
+ }
379
+ if (mode === 'checkpoint') {
380
+ requireConfirmedWrite(args, 'Research run checkpoint');
381
+ const phase = readPhase(args.phase);
382
+ const status = readMutableStatus(args.status);
383
+ const progress = readProgress(args.progress);
384
+ const note = readString(args.note);
385
+ return output(formatMutationResult('Checkpointed Agent research run', registry.checkpoint(requireId(args), {
386
+ ...(phase ? { phase } : {}),
387
+ ...(status ? { status } : {}),
388
+ ...(progress === undefined ? {} : { progress }),
389
+ note,
390
+ nextSteps: readStringList(args.nextSteps),
391
+ sourceIds: readStringList(args.sourceIds),
392
+ })));
393
+ }
394
+ if (mode === 'pause') {
395
+ requireConfirmedWrite(args, 'Research run pause');
396
+ return output(formatMutationResult('Paused Agent research run', registry.pause(requireId(args), readString(args.note))));
397
+ }
398
+ if (mode === 'resume') {
399
+ requireConfirmedWrite(args, 'Research run resume');
400
+ return output(formatMutationResult('Resumed Agent research run', registry.resume(requireId(args), readString(args.note))));
401
+ }
402
+ if (mode === 'cancel') {
403
+ requireConfirmedWrite(args, 'Research run cancel');
404
+ return output(formatMutationResult('Cancelled Agent research run', registry.cancel(requireId(args), readString(args.note))));
405
+ }
406
+ if (mode === 'complete') {
407
+ requireConfirmedWrite(args, 'Research run completion');
408
+ return output(formatMutationResult('Completed Agent research run', registry.complete(requireId(args), {
409
+ note: readString(args.note),
410
+ reportArtifactId: readString(args.reportArtifactId),
411
+ sourceIds: readStringList(args.sourceIds),
412
+ })));
413
+ }
414
+ if (mode === 'fail') {
415
+ requireConfirmedWrite(args, 'Research run failure');
416
+ return output(formatMutationResult('Failed Agent research run', registry.fail(requireId(args), readString(args.error) || readString(args.note))));
417
+ }
418
+ requireConfirmedWrite(args, 'Research run deletion');
419
+ return output(formatMutationResult('Deleted Agent research run', registry.delete(requireId(args))));
420
+ } catch (error) {
421
+ return failure(error instanceof Error ? error.message : String(error));
422
+ }
423
+ },
424
+ };
425
+ }
426
+
427
+ export { createAgentResearchRunsTool };
428
+
429
+ export function registerAgentResearchRunsTool(
430
+ registry: ToolRegistry,
431
+ shellPaths?: Pick<ShellPathService, 'resolveProjectPath'>,
432
+ ): void {
433
+ registry.register(createAgentResearchRunsTool(shellPaths));
434
+ }