@pellux/goodvibes-agent 1.1.6 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/README.md +46 -30
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
  5. package/dist/package/main.js +132662 -91399
  6. package/docs/README.md +14 -7
  7. package/docs/channels-remote-and-api.md +8 -5
  8. package/docs/connected-host.md +14 -12
  9. package/docs/getting-started.md +56 -30
  10. package/docs/knowledge-artifacts-and-multimodal.md +7 -5
  11. package/docs/project-planning.md +2 -2
  12. package/docs/providers-and-routing.md +11 -3
  13. package/docs/tools-and-commands.md +114 -45
  14. package/docs/voice-and-live-tts.md +3 -1
  15. package/package.json +3 -2
  16. package/release/release-notes.md +130 -5
  17. package/release/release-readiness.json +120 -90
  18. package/src/agent/assistant-cockpit.ts +247 -0
  19. package/src/agent/autonomy-schedule-format.ts +96 -0
  20. package/src/agent/autonomy-schedule.ts +514 -0
  21. package/src/agent/channel-delivery-receipts.ts +292 -0
  22. package/src/agent/competitive-feature-inventory.ts +296 -0
  23. package/src/agent/document-registry-types.ts +106 -0
  24. package/src/agent/document-registry.ts +734 -0
  25. package/src/agent/harness-control.ts +2 -2
  26. package/src/agent/memory-prompt.ts +2 -2
  27. package/src/agent/operator-actions.ts +50 -6
  28. package/src/agent/persona-registry.ts +8 -0
  29. package/src/agent/project-context-files.ts +273 -0
  30. package/src/agent/prompt-context-receipts.ts +502 -0
  31. package/src/agent/reminder-schedule-format.ts +16 -2
  32. package/src/agent/research-run-registry.ts +582 -0
  33. package/src/agent/research-source-registry.ts +441 -0
  34. package/src/agent/routine-registry.ts +19 -3
  35. package/src/agent/routine-schedule-format.ts +27 -2
  36. package/src/agent/runtime-profile-starters.ts +7 -0
  37. package/src/agent/runtime-profile.ts +106 -4
  38. package/src/agent/schedule-edit-format.ts +129 -0
  39. package/src/agent/schedule-edit.ts +496 -0
  40. package/src/agent/schedule-next-routes.ts +42 -0
  41. package/src/agent/setup-wizard-checkpoint.ts +140 -0
  42. package/src/agent/setup-wizard.ts +447 -0
  43. package/src/agent/skill-registry-types.ts +102 -0
  44. package/src/agent/skill-registry.ts +81 -107
  45. package/src/agent/vibe-confirmation-routes.ts +62 -0
  46. package/src/agent/vibe-file.ts +285 -0
  47. package/src/cli/agent-knowledge-command.ts +45 -2
  48. package/src/cli/help.ts +3 -0
  49. package/src/cli/profiles-command.ts +25 -11
  50. package/src/config/agent-settings-policy.ts +1 -18
  51. package/src/input/agent-workspace-activation.ts +53 -0
  52. package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
  53. package/src/input/agent-workspace-artifact-metadata.ts +17 -0
  54. package/src/input/agent-workspace-basic-command-editors.ts +5 -1
  55. package/src/input/agent-workspace-categories.ts +153 -155
  56. package/src/input/agent-workspace-channel-triage.ts +481 -0
  57. package/src/input/agent-workspace-channels.ts +263 -0
  58. package/src/input/agent-workspace-command-editor.ts +152 -0
  59. package/src/input/agent-workspace-context-snapshot.ts +349 -0
  60. package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
  61. package/src/input/agent-workspace-document-editor.ts +502 -0
  62. package/src/input/agent-workspace-document-ops-editor.ts +523 -0
  63. package/src/input/agent-workspace-host-category.ts +1 -1
  64. package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
  65. package/src/input/agent-workspace-model-compare-editor.ts +376 -0
  66. package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
  67. package/src/input/agent-workspace-model-compare-types.ts +82 -0
  68. package/src/input/agent-workspace-model-compare-utils.ts +35 -0
  69. package/src/input/agent-workspace-onboarding-categories.ts +141 -0
  70. package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
  71. package/src/input/agent-workspace-operations-command-editors.ts +22 -0
  72. package/src/input/agent-workspace-research-report-editor.ts +212 -0
  73. package/src/input/agent-workspace-research-run-editor.ts +144 -0
  74. package/src/input/agent-workspace-research-source-editor.ts +167 -0
  75. package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
  76. package/src/input/agent-workspace-review-packet-utils.ts +265 -0
  77. package/src/input/agent-workspace-settings.ts +262 -30
  78. package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
  79. package/src/input/agent-workspace-setup-snapshot.ts +198 -0
  80. package/src/input/agent-workspace-setup.ts +34 -1
  81. package/src/input/agent-workspace-snapshot.ts +162 -147
  82. package/src/input/agent-workspace-types.ts +287 -2
  83. package/src/input/agent-workspace.ts +18 -0
  84. package/src/input/command-registry.ts +9 -2
  85. package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
  86. package/src/input/commands/channels-runtime.ts +102 -114
  87. package/src/input/commands/delegation-runtime.ts +87 -24
  88. package/src/input/commands/knowledge-browser-flags.ts +12 -0
  89. package/src/input/commands/knowledge.ts +28 -14
  90. package/src/input/commands/operator-actions-runtime.ts +6 -3
  91. package/src/input/commands/schedule-runtime.ts +71 -14
  92. package/src/input/commands/session-content.ts +2 -2
  93. package/src/input/commands/shell-core.ts +2 -0
  94. package/src/input/commands/vibe-runtime.ts +140 -0
  95. package/src/input/commands.ts +2 -0
  96. package/src/input/connected-host-routes.ts +123 -0
  97. package/src/input/settings-modal-types.ts +14 -0
  98. package/src/main.ts +15 -15
  99. package/src/panels/qr-panel.ts +2 -2
  100. package/src/renderer/agent-workspace-context-lines.ts +686 -0
  101. package/src/renderer/agent-workspace.ts +30 -419
  102. package/src/renderer/settings-modal-helpers.ts +12 -0
  103. package/src/renderer/settings-modal.ts +12 -0
  104. package/src/runtime/bootstrap-command-context.ts +11 -1
  105. package/src/runtime/bootstrap-command-parts.ts +14 -3
  106. package/src/runtime/bootstrap-core.ts +43 -1
  107. package/src/runtime/bootstrap-shell.ts +6 -0
  108. package/src/runtime/bootstrap.ts +113 -30
  109. package/src/runtime/connected-host-auth.ts +3 -2
  110. package/src/runtime/execution-ledger.ts +231 -0
  111. package/src/runtime/services.ts +88 -10
  112. package/src/runtime/tool-permission-safety.ts +287 -0
  113. package/src/shell/session-continuity-hints.ts +39 -0
  114. package/src/tools/agent-artifacts-tool.ts +606 -0
  115. package/src/tools/agent-audit-tool.ts +155 -0
  116. package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
  117. package/src/tools/agent-autonomy-tool.ts +140 -0
  118. package/src/tools/agent-channel-send-tool.ts +24 -2
  119. package/src/tools/agent-channels-tool.ts +140 -0
  120. package/src/tools/agent-computer-tool.ts +168 -0
  121. package/src/tools/agent-context-policy.ts +267 -10
  122. package/src/tools/agent-context-tool.ts +143 -0
  123. package/src/tools/agent-delegation-tool.ts +128 -0
  124. package/src/tools/agent-device-tool.ts +240 -0
  125. package/src/tools/agent-documents-tool.ts +684 -0
  126. package/src/tools/agent-execution-tool.ts +230 -0
  127. package/src/tools/agent-harness-agent-orchestration.ts +703 -0
  128. package/src/tools/agent-harness-autonomy-intake.ts +785 -0
  129. package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
  130. package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
  131. package/src/tools/agent-harness-autonomy-queue.ts +560 -0
  132. package/src/tools/agent-harness-background-processes-types.ts +35 -0
  133. package/src/tools/agent-harness-background-processes.ts +794 -0
  134. package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
  135. package/src/tools/agent-harness-browser-control.ts +338 -0
  136. package/src/tools/agent-harness-channel-metadata.ts +168 -10
  137. package/src/tools/agent-harness-cli-command-policy.ts +110 -0
  138. package/src/tools/agent-harness-command-catalog.ts +4 -2
  139. package/src/tools/agent-harness-command-runner.ts +42 -0
  140. package/src/tools/agent-harness-connected-host-status.ts +7 -4
  141. package/src/tools/agent-harness-delegation-posture.ts +234 -19
  142. package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
  143. package/src/tools/agent-harness-document-ops-types.ts +72 -0
  144. package/src/tools/agent-harness-document-ops.ts +671 -0
  145. package/src/tools/agent-harness-execution-history.ts +489 -0
  146. package/src/tools/agent-harness-execution-posture.ts +382 -0
  147. package/src/tools/agent-harness-file-recovery.ts +135 -0
  148. package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
  149. package/src/tools/agent-harness-learning-curator-common.ts +102 -0
  150. package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
  151. package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
  152. package/src/tools/agent-harness-learning-curator-types.ts +151 -0
  153. package/src/tools/agent-harness-learning-curator.ts +417 -0
  154. package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
  155. package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
  156. package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
  157. package/src/tools/agent-harness-media-posture.ts +208 -2
  158. package/src/tools/agent-harness-memory-posture.ts +556 -0
  159. package/src/tools/agent-harness-metadata.ts +100 -168
  160. package/src/tools/agent-harness-mode-catalog.ts +84 -33
  161. package/src/tools/agent-harness-model-catalog.ts +162 -0
  162. package/src/tools/agent-harness-model-provider-health.ts +186 -0
  163. package/src/tools/agent-harness-model-readiness.ts +406 -0
  164. package/src/tools/agent-harness-model-routing-types.ts +266 -0
  165. package/src/tools/agent-harness-model-routing-utils.ts +30 -0
  166. package/src/tools/agent-harness-model-routing.ts +137 -190
  167. package/src/tools/agent-harness-operator-methods.ts +115 -133
  168. package/src/tools/agent-harness-pairing-posture.ts +431 -18
  169. package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
  170. package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
  171. package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
  172. package/src/tools/agent-harness-personal-ops-records.ts +732 -0
  173. package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
  174. package/src/tools/agent-harness-personal-ops-types.ts +222 -0
  175. package/src/tools/agent-harness-personal-ops.ts +606 -0
  176. package/src/tools/agent-harness-project-context.ts +144 -0
  177. package/src/tools/agent-harness-prompt-context.ts +589 -0
  178. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  179. package/src/tools/agent-harness-release-evidence.ts +9 -7
  180. package/src/tools/agent-harness-release-readiness.ts +9 -7
  181. package/src/tools/agent-harness-research-briefing.ts +427 -0
  182. package/src/tools/agent-harness-research-queue.ts +250 -0
  183. package/src/tools/agent-harness-research-runs.ts +295 -0
  184. package/src/tools/agent-harness-research-workflow.ts +322 -0
  185. package/src/tools/agent-harness-security-posture.ts +2 -2
  186. package/src/tools/agent-harness-service-posture.ts +9 -9
  187. package/src/tools/agent-harness-session-metadata.ts +3 -3
  188. package/src/tools/agent-harness-setup-connected-host.ts +501 -0
  189. package/src/tools/agent-harness-setup-describe.ts +557 -0
  190. package/src/tools/agent-harness-setup-handoffs.ts +502 -0
  191. package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
  192. package/src/tools/agent-harness-setup-plan.ts +253 -0
  193. package/src/tools/agent-harness-setup-posture-types.ts +218 -0
  194. package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
  195. package/src/tools/agent-harness-setup-posture.ts +449 -221
  196. package/src/tools/agent-harness-setup-smoke.ts +508 -0
  197. package/src/tools/agent-harness-sudo-posture.ts +114 -0
  198. package/src/tools/agent-harness-tool-schema.ts +120 -7
  199. package/src/tools/agent-harness-tool-types.ts +78 -0
  200. package/src/tools/agent-harness-tool-utils.ts +43 -0
  201. package/src/tools/agent-harness-tool.ts +311 -370
  202. package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
  203. package/src/tools/agent-harness-ui-surface-types.ts +46 -0
  204. package/src/tools/agent-harness-vibe-health.ts +105 -0
  205. package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
  206. package/src/tools/agent-harness-workspace-actions.ts +114 -8
  207. package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
  208. package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
  209. package/src/tools/agent-host-tool.ts +159 -0
  210. package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
  211. package/src/tools/agent-learning-consolidation-core.ts +327 -0
  212. package/src/tools/agent-learning-consolidation-tool.ts +758 -0
  213. package/src/tools/agent-memory-tool.ts +214 -0
  214. package/src/tools/agent-model-compare-export.ts +315 -0
  215. package/src/tools/agent-model-compare-handoff.ts +592 -0
  216. package/src/tools/agent-model-compare-judgment.ts +633 -0
  217. package/src/tools/agent-model-compare-run.ts +722 -0
  218. package/src/tools/agent-model-compare-tool.ts +698 -0
  219. package/src/tools/agent-model-compare-types.ts +191 -0
  220. package/src/tools/agent-model-compare-utils.ts +93 -0
  221. package/src/tools/agent-models-tool.ts +208 -0
  222. package/src/tools/agent-operator-action-tool.ts +1 -1
  223. package/src/tools/agent-operator-method-tool.ts +643 -0
  224. package/src/tools/agent-personal-ops-tool.ts +197 -0
  225. package/src/tools/agent-policy-explanation.ts +415 -0
  226. package/src/tools/agent-research-report-tool.ts +608 -0
  227. package/src/tools/agent-research-runs-tool.ts +434 -0
  228. package/src/tools/agent-research-sources-tool.ts +443 -0
  229. package/src/tools/agent-research-tool.ts +687 -0
  230. package/src/tools/agent-review-packet-presets-core.ts +757 -0
  231. package/src/tools/agent-review-packet-presets-tool.ts +466 -0
  232. package/src/tools/agent-review-packet-share-tool.ts +305 -0
  233. package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
  234. package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
  235. package/src/tools/agent-route-planner-candidates-work.ts +251 -0
  236. package/src/tools/agent-route-planner-helpers.ts +667 -0
  237. package/src/tools/agent-route-planner.ts +185 -0
  238. package/src/tools/agent-route-tool.ts +105 -0
  239. package/src/tools/agent-schedule-edit-tool.ts +210 -0
  240. package/src/tools/agent-schedule-tool.ts +282 -0
  241. package/src/tools/agent-security-tool.ts +145 -0
  242. package/src/tools/agent-sessions-tool.ts +122 -0
  243. package/src/tools/agent-settings-import-tool.ts +104 -0
  244. package/src/tools/agent-settings-tool.ts +176 -0
  245. package/src/tools/agent-setup-tool.ts +226 -0
  246. package/src/tools/agent-support-tool.ts +122 -0
  247. package/src/tools/agent-terminal-process-tools.ts +167 -0
  248. package/src/tools/agent-tool-policy-guard-types.ts +77 -0
  249. package/src/tools/agent-tool-policy-guard.ts +110 -89
  250. package/src/tools/agent-vibe-tool.ts +297 -0
  251. package/src/tools/agent-work-plan-tool.ts +265 -6
  252. package/src/tools/agent-workspace-tool.ts +305 -0
  253. package/src/tools/artifact-archive.ts +169 -0
  254. package/src/tools/tool-definition-compaction.ts +36 -0
  255. package/src/tools/tool-execution-safety.ts +41 -0
  256. package/src/version.ts +1 -1
@@ -0,0 +1,185 @@
1
+ import type { CommandContext } from '../input/command-registry.ts';
2
+ import { listHarnessModes } from './agent-harness-mode-catalog.ts';
3
+ import { listWorkspaceActions } from './agent-harness-workspace-actions.ts';
4
+ import { previewHarnessText } from './agent-harness-text.ts';
5
+ import { addSetupModelContextRouteCandidates } from './agent-route-planner-candidates-setup.ts';
6
+ import { addResearchScheduleExecutionRouteCandidates } from './agent-route-planner-candidates-work.ts';
7
+ import { addSurfaceSecurityRouteCandidates } from './agent-route-planner-candidates-surfaces.ts';
8
+ import { autonomousLike, browserCockpitLike, browserControlLike, channelDeliveriesLike, channelSendLike, channelSetupLike, channelTargetFromText, channelTriageLike, directScheduleLike, externalChannelLike, externalMemoryProviderId, externalMemoryProviderLike, fileRecoveryLike, hasAll, hasAny, hostDiagnosticsLike, interactiveProcessCapabilityLike, localModelLike, localModelSmokeLike, mediaGenerationLike, modelProviderId, modelRouteReadinessLike, personalOpsBriefingLike, personalOpsConnectorSetupLike, personalOpsFreshReadLike, personalOpsLaneFromText, personalOpsLike, personalOpsMutationLike, personalOpsQueueLike, processLifecycleLike, providerAccountLike, quote, releaseAuditLike, releaseEvidenceLike, researchRunnerLike, scheduleLike, securityFindingLike, securityPermissionLike, securityPolicyExplainLike, securityPolicyToolTarget, securityStatusLike, sessionMutationLike, sessionWorkspaceLike, simplifiedModeQuery, supportBundleEffectLike, supportBundleLike, ttsProviderLike, visualResearchReportLike, voiceWorkflowLike } from './agent-route-planner-helpers.ts';
9
+
10
+ export interface AgentRoutePlannerArgs {
11
+ readonly query?: unknown;
12
+ readonly target?: unknown;
13
+ readonly includeParameters?: unknown;
14
+ readonly limit?: unknown;
15
+ }
16
+
17
+ export interface RouteCandidateDraft {
18
+ readonly id: string;
19
+ readonly label: string;
20
+ readonly score: number;
21
+ readonly userSurface: string;
22
+ readonly userOutcome: string;
23
+ readonly why: string;
24
+ readonly modelRoute: string;
25
+ readonly inspectRoute: string;
26
+ readonly userRoute?: string;
27
+ readonly requiresConfirmation: boolean;
28
+ readonly missingFields?: readonly string[];
29
+ readonly nextQuestion?: string;
30
+ readonly supportingRoutes?: readonly string[];
31
+ readonly policy?: string;
32
+ }
33
+
34
+ export interface AgentRouteCandidate {
35
+ readonly id: string;
36
+ readonly label: string;
37
+ readonly confidence: 'high' | 'medium' | 'low';
38
+ readonly userSurface: string;
39
+ readonly userOutcome: string;
40
+ readonly why: string;
41
+ readonly modelRoute: string;
42
+ readonly inspectRoute: string;
43
+ readonly userRoute?: string;
44
+ readonly requiresConfirmation: boolean;
45
+ readonly missingFields?: readonly string[];
46
+ readonly nextQuestion?: string;
47
+ readonly supportingRoutes?: readonly string[];
48
+ readonly policy?: string;
49
+ readonly score?: number;
50
+ }
51
+
52
+ function readString(value: unknown): string {
53
+ return typeof value === 'string' ? value.trim() : '';
54
+ }
55
+
56
+ function readLimit(value: unknown, fallback: number): number {
57
+ const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
58
+ if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
59
+ return Math.max(1, Math.min(20, Math.trunc(parsed)));
60
+ }
61
+
62
+ function buildCandidates(request: string): readonly RouteCandidateDraft[] {
63
+ const lower = request.toLowerCase();
64
+ const candidates: RouteCandidateDraft[] = [];
65
+
66
+ const add = (candidate: RouteCandidateDraft): void => {
67
+ candidates.push(candidate);
68
+ };
69
+
70
+ addSetupModelContextRouteCandidates(lower, request, add);
71
+
72
+ addResearchScheduleExecutionRouteCandidates(lower, request, add);
73
+
74
+ addSurfaceSecurityRouteCandidates(lower, request, add);
75
+
76
+ if (candidates.length === 0) {
77
+ add({
78
+ id: 'main-conversation-first',
79
+ label: 'Main conversation first',
80
+ score: 35,
81
+ userSurface: 'Main conversation',
82
+ userOutcome: 'Answer or plan directly before escalating into a specialized tool or workspace.',
83
+ why: 'The request does not clearly need a specialized route yet.',
84
+ modelRoute: 'main conversation',
85
+ inspectRoute: `workspace action:"actions" query:${quote(request, 72)}`,
86
+ userRoute: 'Main conversation',
87
+ requiresConfirmation: false,
88
+ supportingRoutes: [
89
+ `route action:"plan" query:${quote(request, 72)}`,
90
+ `workspace action:"actions" query:${quote(request, 72)}`,
91
+ ],
92
+ policy: 'Stay in the main conversation unless a visible specialized route improves clarity, durability, safety, or autonomy.',
93
+ });
94
+ }
95
+
96
+ return candidates;
97
+ }
98
+
99
+ function confidence(score: number): AgentRouteCandidate['confidence'] {
100
+ if (score >= 80) return 'high';
101
+ if (score >= 50) return 'medium';
102
+ return 'low';
103
+ }
104
+
105
+ function describeCandidate(candidate: RouteCandidateDraft, includeParameters: boolean): AgentRouteCandidate {
106
+ return {
107
+ id: candidate.id,
108
+ label: candidate.label,
109
+ confidence: confidence(candidate.score),
110
+ userSurface: candidate.userSurface,
111
+ userOutcome: candidate.userOutcome,
112
+ why: candidate.why,
113
+ modelRoute: candidate.modelRoute,
114
+ inspectRoute: candidate.inspectRoute,
115
+ ...(candidate.userRoute ? { userRoute: candidate.userRoute } : {}),
116
+ requiresConfirmation: candidate.requiresConfirmation,
117
+ ...(candidate.missingFields?.length ? { missingFields: candidate.missingFields } : {}),
118
+ ...(candidate.nextQuestion ? { nextQuestion: candidate.nextQuestion } : {}),
119
+ ...(candidate.supportingRoutes?.length ? { supportingRoutes: candidate.supportingRoutes } : {}),
120
+ ...(candidate.policy ? { policy: candidate.policy } : {}),
121
+ ...(includeParameters ? { score: candidate.score } : {}),
122
+ };
123
+ }
124
+
125
+ function workspaceMatches(context: CommandContext, request: string, limit: number): readonly Record<string, unknown>[] {
126
+ try {
127
+ return listWorkspaceActions(context, { query: request, limit }).slice(0, limit);
128
+ } catch {
129
+ return [];
130
+ }
131
+ }
132
+
133
+ function modeMatches(request: string, limit: number): readonly Record<string, unknown>[] {
134
+ try {
135
+ const result = listHarnessModes({ query: request, limit }) as { readonly modes?: readonly Record<string, unknown>[] };
136
+ const matches = result.modes?.slice(0, limit) ?? [];
137
+ if (matches.length > 0) return matches;
138
+ const simplified = simplifiedModeQuery(request);
139
+ if (!simplified || simplified === request.toLowerCase()) return [];
140
+ const fallback = listHarnessModes({ query: simplified, limit }) as { readonly modes?: readonly Record<string, unknown>[] };
141
+ return fallback.modes?.slice(0, limit) ?? [];
142
+ } catch {
143
+ return [];
144
+ }
145
+ }
146
+
147
+ export function planAgentTaskRoute(context: CommandContext, args: AgentRoutePlannerArgs): Record<string, unknown> {
148
+ const request = readString(args.query) || readString(args.target);
149
+ if (!request) {
150
+ return {
151
+ status: 'missing_request',
152
+ usage: 'Use route action:"plan" query:"<user task>" to get the preferred GoodVibes Agent route, alternatives, missing fields, and confirmation boundary.',
153
+ examples: [
154
+ 'Fix the failing tests in this repo.',
155
+ 'Triage my inbox and draft replies.',
156
+ 'Run a weekly source-backed research report.',
157
+ 'Why would settings action:set need confirmation?',
158
+ ],
159
+ policy: 'Route planning is read-only. It never runs tools, creates jobs, sends messages, changes settings, or opens UI surfaces.',
160
+ };
161
+ }
162
+
163
+ const includeParameters = args.includeParameters === true;
164
+ const limit = readLimit(args.limit, includeParameters ? 8 : 5);
165
+ const candidates = [...buildCandidates(request)]
166
+ .sort((left, right) => right.score - left.score)
167
+ .slice(0, limit)
168
+ .map((candidate) => describeCandidate(candidate, includeParameters));
169
+ const preferred = candidates[0]!;
170
+ const workspaceActionMatches = workspaceMatches(context, request, includeParameters ? 6 : 3);
171
+ const modes = modeMatches(request, includeParameters ? 6 : 3);
172
+
173
+ return {
174
+ status: 'ready',
175
+ request: previewHarnessText(request, includeParameters ? 220 : 120),
176
+ preferred,
177
+ alternatives: candidates.slice(1),
178
+ nextAction: preferred.requiresConfirmation
179
+ ? 'Inspect the preferred route, collect missing fields, then run the returned confirmed route only after the user explicitly asks for that effect.'
180
+ : 'Use the preferred read-only route first; only move to a confirmed route if the returned plan asks for one and the user requested the effect.',
181
+ workspaceMatches: workspaceActionMatches,
182
+ harnessModeMatches: modes,
183
+ policy: 'GoodVibes Agent routes by user outcome. Package, daemon, TUI, SDK, and host ownership are diagnostic details; the model should choose the visible route that is easiest and safest for the user.',
184
+ };
185
+ }
@@ -0,0 +1,105 @@
1
+ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
2
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
3
+ import type { CommandContext } from '../input/command-registry.ts';
4
+ import { planAgentTaskRoute } from './agent-route-planner.ts';
5
+
6
+ type AgentRouteAction = 'plan' | 'status';
7
+
8
+ interface AgentRouteToolArgs {
9
+ readonly action?: unknown;
10
+ readonly mode?: unknown;
11
+ readonly query?: unknown;
12
+ readonly target?: unknown;
13
+ readonly includeParameters?: unknown;
14
+ readonly limit?: unknown;
15
+ }
16
+
17
+ function readString(value: unknown): string {
18
+ return typeof value === 'string' ? value.trim() : '';
19
+ }
20
+
21
+ function normalizeRouteAction(value: unknown): AgentRouteAction | null {
22
+ const action = readString(value).toLowerCase().replace(/-/g, '_');
23
+ if (!action) return null;
24
+ if (action === 'plan' || action === 'route' || action === 'decide' || action === 'decision' || action === 'task' || action === 'intake') return 'plan';
25
+ if (action === 'status' || action === 'summary' || action === 'help' || action === 'usage') return 'status';
26
+ return null;
27
+ }
28
+
29
+ function readAction(args: AgentRouteToolArgs): AgentRouteAction {
30
+ const explicit = normalizeRouteAction(args.action) ?? normalizeRouteAction(args.mode);
31
+ if (explicit) return explicit;
32
+ if (readString(args.query) || readString(args.target)) return 'plan';
33
+ return 'status';
34
+ }
35
+
36
+ function output(value: unknown): { readonly success: true; readonly output: string } {
37
+ return {
38
+ success: true,
39
+ output: typeof value === 'string' ? value : JSON.stringify(value, null, 2),
40
+ };
41
+ }
42
+
43
+ function status(): Record<string, unknown> {
44
+ return {
45
+ status: 'ready',
46
+ usage: 'Use route action:"plan" query:"<user task>" before choosing a specialized GoodVibes Agent surface.',
47
+ actions: ['plan', 'status'],
48
+ examples: [
49
+ 'route action:"plan" query:"fix the failing tests"',
50
+ 'route action:"plan" query:"check daemon health"',
51
+ 'route action:"plan" query:"change the theme setting"',
52
+ 'route action:"plan" query:"remind me tomorrow to stretch"',
53
+ 'route action:"plan" query:"run pytest in background"',
54
+ 'route action:"plan" query:"run claude code with pty and sudo"',
55
+ 'route action:"plan" query:"undo the last file edit"',
56
+ 'route action:"plan" query:"show current permissions"',
57
+ 'route action:"plan" query:"why was that tool call blocked"',
58
+ 'route action:"plan" query:"export a support bundle"',
59
+ 'route action:"plan" query:"search saved sessions"',
60
+ 'route action:"plan" query:"show release readiness evidence"',
61
+ 'route action:"plan" query:"generate an image of a product dashboard"',
62
+ 'route action:"plan" query:"take a screenshot of the browser dashboard"',
63
+ 'route action:"plan" query:"triage my inbox and draft replies"',
64
+ 'route action:"plan" query:"run a weekly source-backed research report"',
65
+ ],
66
+ policy: 'Route is read-only. It selects visible user-first routes and missing fields but never runs tools, creates jobs, sends messages, changes settings, or opens UI surfaces.',
67
+ };
68
+ }
69
+
70
+ export function createAgentRouteTool(commandContext: CommandContext): Tool {
71
+ return {
72
+ definition: {
73
+ name: 'route',
74
+ description: 'Choose the best visible route for a user task.',
75
+ parameters: {
76
+ type: 'object',
77
+ properties: {
78
+ action: {
79
+ type: 'string',
80
+ enum: ['plan', 'status'],
81
+ description: 'Plan a user-task route or show route-tool usage.',
82
+ },
83
+ mode: { type: 'string', description: 'Alias for action.' },
84
+ query: { type: 'string', description: 'Plain user request to route.' },
85
+ target: { type: 'string', description: 'Alias for query.' },
86
+ includeParameters: { type: 'boolean', description: 'Include scoring and more catalog matches.' },
87
+ limit: { type: 'number', description: 'Maximum candidate routes returned.' },
88
+ },
89
+ additionalProperties: false,
90
+ },
91
+ sideEffects: [],
92
+ concurrency: 'parallel',
93
+ },
94
+ execute: async (rawArgs: unknown) => {
95
+ const args = (rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs) ? rawArgs : {}) as AgentRouteToolArgs;
96
+ const action = readAction(args);
97
+ if (action === 'status') return output(status());
98
+ return output(planAgentTaskRoute(commandContext, args));
99
+ },
100
+ };
101
+ }
102
+
103
+ export function registerAgentRouteTool(registry: ToolRegistry, commandContext: CommandContext): void {
104
+ if (!registry.has('route')) registry.register(createAgentRouteTool(commandContext));
105
+ }
@@ -0,0 +1,210 @@
1
+ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
2
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
3
+ import type { ShellPathService } from '@/runtime/index.ts';
4
+ import {
5
+ buildScheduleEditPreview,
6
+ editConnectedSchedule,
7
+ enrichScheduleEditPreviewFromConnectedHost,
8
+ parseScheduleEditArgs,
9
+ resolveScheduleEditConnectedHostConnection,
10
+ scheduleEditKindFromValue,
11
+ type ScheduleEditResult,
12
+ } from '../agent/schedule-edit.ts';
13
+ import {
14
+ formatScheduleEditFailure,
15
+ formatScheduleEditPreview,
16
+ formatScheduleEditSuccess,
17
+ } from '../agent/schedule-edit-format.ts';
18
+ import type { AgentConnectedHostConfigReader } from '../agent/routine-schedule-promotion.ts';
19
+
20
+ export interface AgentScheduleEditToolArgs {
21
+ readonly scheduleId?: unknown;
22
+ readonly jobId?: unknown;
23
+ readonly scheduleKind?: unknown;
24
+ readonly scheduleValue?: unknown;
25
+ readonly timezone?: unknown;
26
+ readonly staggerMs?: unknown;
27
+ readonly name?: unknown;
28
+ readonly prompt?: unknown;
29
+ readonly task?: unknown;
30
+ readonly successCriteria?: unknown;
31
+ readonly confirm?: unknown;
32
+ readonly explicitUserRequest?: unknown;
33
+ }
34
+
35
+ function readString(value: unknown): string {
36
+ return typeof value === 'string' ? value.trim() : '';
37
+ }
38
+
39
+ function readOptionalString(value: unknown): string | null {
40
+ const text = readString(value);
41
+ return text ? text : null;
42
+ }
43
+
44
+ function readBoolean(value: unknown): boolean {
45
+ return value === true || value === 'true' || value === 'yes';
46
+ }
47
+
48
+ function addOptionalArg(args: string[], flag: string, value: unknown): void {
49
+ const text = readOptionalString(value);
50
+ if (!text) return;
51
+ args.push(flag, text);
52
+ }
53
+
54
+ function addOptionalNumber(args: string[], flag: string, value: unknown): void {
55
+ if (value === undefined || value === null || value === '') return;
56
+ if (typeof value === 'number') {
57
+ args.push(flag, String(value));
58
+ return;
59
+ }
60
+ addOptionalArg(args, flag, value);
61
+ }
62
+
63
+ function buildScheduleEditArgs(rawArgs: AgentScheduleEditToolArgs): readonly string[] {
64
+ const scheduleId = readOptionalString(rawArgs.scheduleId) ?? readOptionalString(rawArgs.jobId);
65
+ const explicitUserRequest = readOptionalString(rawArgs.explicitUserRequest);
66
+ if (!scheduleId) throw new Error('scheduleId is required.');
67
+ if (!explicitUserRequest) throw new Error('explicitUserRequest is required.');
68
+
69
+ const args = [scheduleId, '--explicit-user-request', explicitUserRequest];
70
+ const scheduleKind = scheduleEditKindFromValue(rawArgs.scheduleKind);
71
+ const scheduleValue = readOptionalString(rawArgs.scheduleValue);
72
+ if (scheduleKind && !scheduleValue) throw new Error('scheduleValue is required when scheduleKind is set.');
73
+ if (!scheduleKind && scheduleValue) throw new Error('scheduleKind is required when scheduleValue is set.');
74
+ if (scheduleKind && scheduleValue) args.push(`--${scheduleKind}`, scheduleValue);
75
+
76
+ addOptionalArg(args, '--timezone', rawArgs.timezone);
77
+ addOptionalNumber(args, '--stagger-ms', rawArgs.staggerMs);
78
+ addOptionalArg(args, '--name', rawArgs.name);
79
+ addOptionalArg(args, '--prompt', rawArgs.prompt);
80
+ addOptionalArg(args, '--task', rawArgs.task);
81
+ addOptionalArg(args, '--success-criteria', rawArgs.successCriteria);
82
+ if (readBoolean(rawArgs.confirm)) args.push('--yes');
83
+ return args;
84
+ }
85
+
86
+ function outputForResult(result: ScheduleEditResult): { readonly success: boolean; readonly output?: string; readonly error?: string } {
87
+ if (result.ok) {
88
+ return {
89
+ success: true,
90
+ output: formatScheduleEditSuccess(result),
91
+ };
92
+ }
93
+ return {
94
+ success: false,
95
+ error: formatScheduleEditFailure(result),
96
+ };
97
+ }
98
+
99
+ function confirmationError(preview: ReturnType<typeof buildScheduleEditPreview>): string {
100
+ return [
101
+ formatScheduleEditPreview(preview),
102
+ '',
103
+ 'Model tool confirmation required. Call this tool with confirm:true only when the user explicitly asked GoodVibes Agent to edit this exact schedule.',
104
+ 'Do not infer schedule edits from vague optimization, cleanup, or follow-up suggestions.',
105
+ ].join('\n');
106
+ }
107
+
108
+ export function createAgentScheduleEditTool(
109
+ shellPaths: ShellPathService,
110
+ configManager: AgentConnectedHostConfigReader,
111
+ ): Tool {
112
+ return {
113
+ definition: {
114
+ name: 'agent_schedule_edit',
115
+ description: 'Edit one confirmed connected GoodVibes schedule.',
116
+ parameters: {
117
+ type: 'object',
118
+ properties: {
119
+ scheduleId: {
120
+ type: 'string',
121
+ description: 'Connected schedule id to edit.',
122
+ },
123
+ jobId: {
124
+ type: 'string',
125
+ description: 'Automation job id when known instead of scheduleId.',
126
+ },
127
+ scheduleKind: {
128
+ type: 'string',
129
+ enum: ['at', 'every', 'cron'],
130
+ description: 'Optional replacement schedule kind.',
131
+ },
132
+ scheduleValue: {
133
+ type: 'string',
134
+ description: 'Replacement ISO time, interval, or cron expression.',
135
+ },
136
+ timezone: {
137
+ type: 'string',
138
+ description: 'Optional IANA timezone for cron replacements.',
139
+ },
140
+ staggerMs: {
141
+ type: 'number',
142
+ description: 'Optional cron stagger in milliseconds.',
143
+ },
144
+ name: {
145
+ type: 'string',
146
+ description: 'Optional replacement schedule display name.',
147
+ },
148
+ prompt: {
149
+ type: 'string',
150
+ description: 'Optional exact replacement prompt.',
151
+ },
152
+ task: {
153
+ type: 'string',
154
+ description: 'Optional replacement autonomous task.',
155
+ },
156
+ successCriteria: {
157
+ type: 'string',
158
+ description: 'Required with task; expected run outcome.',
159
+ },
160
+ confirm: {
161
+ type: 'boolean',
162
+ description: 'Required true only when user requested this edit.',
163
+ },
164
+ explicitUserRequest: {
165
+ type: 'string',
166
+ description: 'User request authorizing this schedule edit.',
167
+ },
168
+ },
169
+ required: ['scheduleId', 'confirm', 'explicitUserRequest'],
170
+ additionalProperties: false,
171
+ },
172
+ sideEffects: ['network', 'state'],
173
+ },
174
+ execute: async (rawArgs: unknown) => {
175
+ try {
176
+ const args = rawArgs as AgentScheduleEditToolArgs;
177
+ const parsed = parseScheduleEditArgs(buildScheduleEditArgs(args));
178
+ if (parsed.errors.length > 0) {
179
+ return {
180
+ success: false,
181
+ error: parsed.errors.join('\n'),
182
+ };
183
+ }
184
+ let preview = buildScheduleEditPreview(parsed);
185
+ const connection = resolveScheduleEditConnectedHostConnection(configManager, shellPaths.homeDirectory);
186
+ if (!parsed.yes) {
187
+ preview = await enrichScheduleEditPreviewFromConnectedHost(connection, preview);
188
+ return {
189
+ success: false,
190
+ error: confirmationError(preview),
191
+ };
192
+ }
193
+ return outputForResult(await editConnectedSchedule(connection, preview));
194
+ } catch (error) {
195
+ return {
196
+ success: false,
197
+ error: error instanceof Error ? error.message : String(error),
198
+ };
199
+ }
200
+ },
201
+ };
202
+ }
203
+
204
+ export function registerAgentScheduleEditTool(
205
+ registry: ToolRegistry,
206
+ shellPaths: ShellPathService,
207
+ configManager: AgentConnectedHostConfigReader,
208
+ ): void {
209
+ registry.register(createAgentScheduleEditTool(shellPaths, configManager));
210
+ }