@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,219 @@
1
+ import type { CommandContext } from '../input/command-registry.ts';
2
+ import { resolveRuntimeEndpointBinding } from '../cli/endpoints.ts';
3
+ import { AGENT_WORKSPACE_CATEGORIES } from '../input/agent-workspace-categories.ts';
4
+ import { readOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
5
+
6
+ function browserConnectHost(host: string): string {
7
+ if (host === '0.0.0.0' || host === '::') return '127.0.0.1';
8
+ if (host.includes(':') && !host.startsWith('[')) return `[${host}]`;
9
+ return host || '127.0.0.1';
10
+ }
11
+
12
+ const BROWSER_COCKPIT_EXPECTED_LANES = [
13
+ {
14
+ id: 'chat-and-sessions',
15
+ label: 'Chat and sessions',
16
+ categoryIds: ['home', 'conversation'],
17
+ userOutcome: 'Continue normal assistant chat, session review, prompt history, bookmarks, and current work from the browser.',
18
+ },
19
+ {
20
+ id: 'setup-and-settings',
21
+ label: 'Setup and settings',
22
+ categoryIds: ['setup', 'account-model', 'assistant-behavior', 'tools-permissions', 'onboarding-display', 'finish'],
23
+ userOutcome: 'Finish first-run setup, choose models, adjust behavior, review permissions, and close onboarding without returning to terminal-only controls.',
24
+ },
25
+ {
26
+ id: 'mobile-and-channels',
27
+ label: 'Mobile and channels',
28
+ categoryIds: ['onboarding-channels', 'onboarding-voice-media', 'channels', 'voice-media', 'personal-ops'],
29
+ userOutcome: 'Configure mobile-friendly messaging, notification, voice, phone, and daily personal-operation routes from one cockpit.',
30
+ },
31
+ {
32
+ id: 'knowledge-and-memory',
33
+ label: 'Knowledge and memory',
34
+ categoryIds: ['onboarding-context', 'knowledge', 'profiles', 'memory', 'notes', 'personas', 'skills', 'routines'],
35
+ userOutcome: 'Review and curate user context, project knowledge, memories, notes, personas, skills, and routines with browser-native forms.',
36
+ },
37
+ {
38
+ id: 'work-and-automation',
39
+ label: 'Work and automation',
40
+ categoryIds: ['work', 'automation', 'onboarding-automation', 'delegate'],
41
+ userOutcome: 'Approve, supervise, recover, schedule, and delegate autonomous work with touch-friendly controls and receipts.',
42
+ },
43
+ {
44
+ id: 'research-and-artifacts',
45
+ label: 'Research and artifacts',
46
+ categoryIds: ['research', 'documents', 'artifacts'],
47
+ userOutcome: 'Run research, draft documents, review packets, browse artifacts, and export/share deliverables from the browser.',
48
+ },
49
+ {
50
+ id: 'host-and-safety',
51
+ label: 'Host and safety',
52
+ categoryIds: ['tools', 'host'],
53
+ userOutcome: 'Inspect tool trust, MCP posture, connected-host repair, service health, support bundles, and recovery routes.',
54
+ },
55
+ ] as const;
56
+
57
+ function confirmedCategoryRoute(categoryId: string, label: string): string {
58
+ return `agent_harness mode:"open_ui_surface" surfaceId:"agent-workspace" categoryId:"${categoryId}" confirm:true explicitUserRequest:"Open the ${label} workspace."`;
59
+ }
60
+
61
+ function browserCockpitWorkspaceCoverage(enabled: boolean, includeDetails: boolean): Record<string, unknown> {
62
+ const browserStatus = enabled ? 'terminal-first' : 'blocked-by-web-setup';
63
+ const categories = AGENT_WORKSPACE_CATEGORIES.map((category) => ({
64
+ id: category.id,
65
+ label: category.label,
66
+ group: category.group,
67
+ actions: category.actions.length,
68
+ browserStatus,
69
+ browserRoute: null,
70
+ agentRoute: confirmedCategoryRoute(category.id, category.label),
71
+ neededContract: 'connected-host browser-native Agent workspace category route',
72
+ }));
73
+ const categoryById = new Map(categories.map((category) => [category.id, category]));
74
+ return {
75
+ status: enabled ? 'needs-browser-native-category-contracts' : 'web-setup-needed',
76
+ summary: enabled
77
+ ? 'The connected-host web URL is openable, but Agent has not received a published browser-native route contract for workspace categories yet.'
78
+ : 'The connected-host web endpoint is disabled, so browser-native workspace categories cannot be reached yet.',
79
+ categoryCount: categories.length,
80
+ nativeCategoryRoutesPublished: false,
81
+ terminalFallback: 'Every Agent workspace category remains reachable through the TUI Agent Workspace while browser-native category routes are being published.',
82
+ laneCount: BROWSER_COCKPIT_EXPECTED_LANES.length,
83
+ ...(includeDetails ? {
84
+ lanes: BROWSER_COCKPIT_EXPECTED_LANES.map((lane) => ({
85
+ id: lane.id,
86
+ label: lane.label,
87
+ categoryIds: lane.categoryIds,
88
+ userOutcome: lane.userOutcome,
89
+ browserStatus: enabled ? 'needs-browser-native-contract' : 'blocked-by-web-setup',
90
+ agentRoutes: lane.categoryIds
91
+ .map((categoryId) => categoryById.get(categoryId))
92
+ .filter((category): category is NonNullable<typeof category> => Boolean(category))
93
+ .map((category) => category.agentRoute),
94
+ })),
95
+ categories,
96
+ } : {}),
97
+ policy: 'Workspace coverage is a route contract map, not a claim that the connected-host browser already renders these Agent category controls.',
98
+ };
99
+ }
100
+
101
+ function browserCockpitMobileAffordances(enabled: boolean, includeDetails: boolean): Record<string, unknown> {
102
+ const controls = [
103
+ {
104
+ id: 'open-browser-cockpit',
105
+ label: 'Open browser cockpit',
106
+ status: enabled ? 'ready' : 'blocked-by-web-setup',
107
+ modelRoute: 'agent_harness mode:"open_ui_surface" surfaceId:"connected-browser-cockpit" confirm:true explicitUserRequest:"..."',
108
+ },
109
+ {
110
+ id: 'inspect-web-endpoint',
111
+ label: 'Inspect web endpoint',
112
+ status: 'ready',
113
+ modelRoute: 'host action:"service" endpointId:"web" includeParameters:true',
114
+ },
115
+ {
116
+ id: 'inspect-device-map',
117
+ label: 'Inspect device capability map',
118
+ status: 'ready',
119
+ modelRoute: 'agent_harness mode:"pairing_route" pairingRouteId:"browser-cockpit-pwa"',
120
+ },
121
+ {
122
+ id: 'review-web-settings',
123
+ label: 'Review web settings',
124
+ status: 'ready',
125
+ modelRoute: 'settings action:"list" query:"web" includeHidden:true',
126
+ },
127
+ ];
128
+ return {
129
+ status: enabled ? 'openable' : 'setup-needed',
130
+ controlCount: controls.length,
131
+ ...(includeDetails ? { controls } : {}),
132
+ pwaInstall: {
133
+ status: enabled ? 'browser-owned' : 'blocked-by-web-setup',
134
+ note: 'Agent can open the configured URL; installing the PWA remains a browser/connected-host UI action.',
135
+ },
136
+ touchControls: {
137
+ status: 'needs-browser-native-category-contracts',
138
+ note: 'Agent has not received a connected-host contract proving mobile-native controls for chat, setup, approvals, memory, channels, or automation.',
139
+ },
140
+ };
141
+ }
142
+
143
+ function browserCockpitReceipts(context: CommandContext, enabled: boolean, includeDetails: boolean): Record<string, unknown> {
144
+ const marker = (() => {
145
+ try {
146
+ const shellPaths = context.workspace?.shellPaths;
147
+ if (!shellPaths) return { status: 'unavailable', exists: false, reason: 'Agent shell paths are unavailable in this runtime.' };
148
+ const completion = readOnboardingCompletionMarker(shellPaths, 'user');
149
+ return {
150
+ status: completion.exists ? 'complete' : 'missing',
151
+ exists: completion.exists,
152
+ path: completion.path,
153
+ updatedAt: completion.payload?.updatedAt ?? null,
154
+ source: completion.payload?.source ?? null,
155
+ mode: completion.payload?.mode ?? null,
156
+ };
157
+ } catch (error) {
158
+ return {
159
+ status: 'unavailable',
160
+ exists: false,
161
+ reason: error instanceof Error ? error.message : 'Unable to read Agent onboarding completion marker.',
162
+ };
163
+ }
164
+ })();
165
+ return {
166
+ status: marker.exists === true ? 'agent-complete-browser-receipt-missing' : 'needs-agent-closeout-and-browser-receipt',
167
+ agentOnboardingStatus: marker.status,
168
+ browserFirstRunStatus: 'not-published',
169
+ ...(includeDetails ? {
170
+ agentOnboardingCompletion: marker,
171
+ browserFirstRunCompletion: {
172
+ status: 'not-published',
173
+ webEnabled: enabled,
174
+ evidence: null,
175
+ nextStep: 'Publish a connected-host browser/PWA completion receipt before using browser readiness as first-run closeout evidence.',
176
+ },
177
+ } : {}),
178
+ setupCloseoutRoute: 'setup action:"status" includeParameters:true',
179
+ policy: 'Agent reports its own user onboarding marker separately from the connected-host browser/PWA receipt contract so setup closeout does not overclaim browser readiness.',
180
+ };
181
+ }
182
+
183
+ export function connectedBrowserCockpitRoute(context: CommandContext, options: { readonly includeWorkspaceCoverage?: boolean } = {}): Record<string, unknown> {
184
+ const configManager = context.platform?.configManager;
185
+ let enabled = false;
186
+ let binding = { hostMode: 'local', configuredHost: '127.0.0.1', host: '127.0.0.1', port: 3423 };
187
+ let publicBaseUrl = '';
188
+ if (configManager) {
189
+ try {
190
+ enabled = configManager.get('web.enabled') === true;
191
+ binding = resolveRuntimeEndpointBinding(configManager, 'web');
192
+ publicBaseUrl = String(configManager.get('web.publicBaseUrl') ?? '').trim();
193
+ } catch {
194
+ enabled = false;
195
+ }
196
+ }
197
+ const url = publicBaseUrl || `http://${browserConnectHost(binding.host)}:${binding.port}`;
198
+ return {
199
+ enabled,
200
+ readiness: enabled ? 'ready' : 'setup-needed',
201
+ url,
202
+ source: publicBaseUrl ? 'web.publicBaseUrl' : 'web endpoint binding',
203
+ endpoint: {
204
+ id: 'web',
205
+ binding,
206
+ settings: ['web.enabled', 'web.hostMode', 'web.host', 'web.port', 'web.publicBaseUrl'],
207
+ },
208
+ workspaceCoverage: browserCockpitWorkspaceCoverage(enabled, options.includeWorkspaceCoverage === true),
209
+ mobile: browserCockpitMobileAffordances(enabled, options.includeWorkspaceCoverage === true),
210
+ receipts: browserCockpitReceipts(context, enabled, options.includeWorkspaceCoverage === true),
211
+ setupRoutes: {
212
+ inspectEndpoint: 'host action:"service" endpointId:"web" includeParameters:true',
213
+ servicePosture: 'host action:"services" includeParameters:true',
214
+ connectedHostStatus: 'host action:"status" includeParameters:true',
215
+ settings: 'settings action:"list" query:"web" includeHidden:true',
216
+ },
217
+ policy: 'Opens the connected GoodVibes browser cockpit only after explicit user confirmation. Agent does not host a separate browser app or bypass connected-host setup.',
218
+ };
219
+ }
@@ -0,0 +1,338 @@
1
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
2
+ import type { CommandContext } from '../input/command-registry.ts';
3
+
4
+ type BrowserControlStatus = 'ready' | 'attention' | 'setup-needed';
5
+ type BrowserControlDecisionStatus = 'ready-to-inspect-tool' | 'review-connector-first' | 'setup-needed';
6
+
7
+ export interface BrowserControlRouteArgs {
8
+ readonly target?: unknown;
9
+ readonly query?: unknown;
10
+ readonly includeParameters?: unknown;
11
+ }
12
+
13
+ interface BrowserControlMcpServer {
14
+ readonly name: string;
15
+ readonly connected: boolean;
16
+ readonly role: string;
17
+ readonly trustMode: string;
18
+ readonly schemaFreshness: string;
19
+ readonly readiness: 'ready' | 'attention';
20
+ readonly modelRoute: string;
21
+ }
22
+
23
+ interface BrowserControlWorkflow {
24
+ readonly id: string;
25
+ readonly label: string;
26
+ readonly status: BrowserControlStatus;
27
+ readonly summary: string;
28
+ readonly next: string;
29
+ readonly inspectRoute: string;
30
+ readonly setupRoute: string;
31
+ readonly safety: string;
32
+ }
33
+
34
+ interface BrowserControlDecision {
35
+ readonly id: string;
36
+ readonly status: BrowserControlDecisionStatus;
37
+ readonly modelRoute: string;
38
+ readonly userRoute: string;
39
+ readonly nextStep: string;
40
+ readonly reason: string;
41
+ readonly safety: string;
42
+ }
43
+
44
+ export interface BrowserControlPosture {
45
+ readonly status: BrowserControlStatus;
46
+ readonly configured: boolean;
47
+ readonly needsReview: boolean;
48
+ readonly toolMatches: readonly string[];
49
+ readonly mcpServers: readonly BrowserControlMcpServer[];
50
+ readonly workflows: readonly BrowserControlWorkflow[];
51
+ readonly setupChecklist: readonly string[];
52
+ readonly fallbackRoutes: readonly string[];
53
+ readonly executionRoute: string;
54
+ readonly setupRoute: string;
55
+ readonly recommendedRoute: string;
56
+ readonly policy: string;
57
+ }
58
+
59
+ type McpServerRecord = ReturnType<NonNullable<NonNullable<CommandContext['clients']>['mcpApi']>['listServerSecurity']>[number];
60
+
61
+ const BROWSER_CONTROL_TERMS = ['browser', 'desktop', 'computer use', 'screenshot', 'screen recording'];
62
+ const POSTURE_ONLY_TOOL_NAMES = new Set(['agent_harness', 'computer', 'device', 'execution', 'route', 'workspace']);
63
+
64
+ function readString(value: unknown): string {
65
+ return typeof value === 'string' ? value.trim() : '';
66
+ }
67
+
68
+ function quoteRouteValue(value: string): string {
69
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
70
+ }
71
+
72
+ function includesBrowserControlTerm(value: string): boolean {
73
+ const normalized = value.toLowerCase();
74
+ return BROWSER_CONTROL_TERMS.some((term) => normalized.includes(term));
75
+ }
76
+
77
+ function safeToolDefinitions(toolRegistry: ToolRegistry | undefined): readonly ReturnType<ToolRegistry['getToolDefinitions']>[number][] {
78
+ if (!toolRegistry) return [];
79
+ try {
80
+ return toolRegistry.getToolDefinitions();
81
+ } catch {
82
+ return [];
83
+ }
84
+ }
85
+
86
+ function safeMcpServers(context: CommandContext): readonly McpServerRecord[] {
87
+ try {
88
+ const api = context.clients?.mcpApi ?? context.extensions?.mcpRegistry;
89
+ return api?.listServerSecurity?.() ?? [];
90
+ } catch {
91
+ return [];
92
+ }
93
+ }
94
+
95
+ function describeMcpServer(server: McpServerRecord): BrowserControlMcpServer {
96
+ const ready = server.connected && server.schemaFreshness === 'fresh' && server.trustMode !== 'blocked';
97
+ return {
98
+ name: server.name,
99
+ connected: server.connected,
100
+ role: server.role,
101
+ trustMode: server.trustMode,
102
+ schemaFreshness: server.schemaFreshness,
103
+ readiness: ready ? 'ready' : 'attention',
104
+ modelRoute: `agent_harness mode:"mcp_server" mcpServerId:"${server.name}"`,
105
+ };
106
+ }
107
+
108
+ function workflowStatus(configured: boolean, needsReview: boolean): BrowserControlStatus {
109
+ if (configured) return 'ready';
110
+ return needsReview ? 'attention' : 'setup-needed';
111
+ }
112
+
113
+ function browserControlWorkflows(
114
+ configured: boolean,
115
+ needsReview: boolean,
116
+ recommendedRoute: string,
117
+ setupRoute: string,
118
+ ): readonly BrowserControlWorkflow[] {
119
+ const status = workflowStatus(configured, needsReview);
120
+ const inspectRoute = configured ? recommendedRoute : setupRoute;
121
+ const next = configured
122
+ ? 'Inspect the configured tool/server, then run the narrowest browser or desktop action needed for the user request.'
123
+ : needsReview
124
+ ? 'Review trust/schema freshness before treating this browser or desktop connector as usable.'
125
+ : 'Configure a trusted browser/desktop MCP server or first-class tool before attempting live UI control.';
126
+ return [
127
+ {
128
+ id: 'browser-navigation',
129
+ label: 'Browser navigation',
130
+ status,
131
+ summary: 'Drive a real browser only when a trusted browser tool or MCP server is configured.',
132
+ next,
133
+ inspectRoute,
134
+ setupRoute,
135
+ safety: 'Use read-only web/fetch routes for research unless the user explicitly needs live browser state or authentication.',
136
+ },
137
+ {
138
+ id: 'screenshot-observation',
139
+ label: 'Screenshot or screen observation',
140
+ status,
141
+ summary: 'Capture or inspect the screen through configured screenshot/screen-recording tooling.',
142
+ next,
143
+ inspectRoute,
144
+ setupRoute,
145
+ safety: 'Screenshots can expose secrets or private data; inspect setup and ask before capturing sensitive surfaces.',
146
+ },
147
+ {
148
+ id: 'desktop-control',
149
+ label: 'Desktop control',
150
+ status,
151
+ summary: 'Use desktop/computer-control only after trust, host, and confirmation boundaries are clear.',
152
+ next,
153
+ inspectRoute,
154
+ setupRoute,
155
+ safety: 'Desktop actions are external effects; destructive or account-changing actions require explicit user confirmation.',
156
+ },
157
+ ];
158
+ }
159
+
160
+ export function browserControlPosture(context: CommandContext, toolRegistry?: ToolRegistry): BrowserControlPosture {
161
+ const registry = toolRegistry ?? context.extensions?.toolRegistry;
162
+ const toolMatches = safeToolDefinitions(registry)
163
+ .filter((tool) => !POSTURE_ONLY_TOOL_NAMES.has(tool.name))
164
+ .filter((tool) => includesBrowserControlTerm(`${tool.name}\n${tool.description}`))
165
+ .map((tool) => tool.name)
166
+ .sort((left, right) => left.localeCompare(right));
167
+
168
+ const mcpServers = safeMcpServers(context)
169
+ .filter((server) => includesBrowserControlTerm(`${server.name}\n${server.role}`))
170
+ .map(describeMcpServer)
171
+ .sort((left, right) => left.name.localeCompare(right.name));
172
+
173
+ const readyBrowserMcp = mcpServers.some((server) => server.readiness === 'ready');
174
+ const needsReview = mcpServers.some((server) => server.readiness === 'attention');
175
+ const configured = toolMatches.length > 0 || readyBrowserMcp;
176
+ const recommendedRoute = configured
177
+ ? 'execution action:"route" id:"browser-or-desktop-control"'
178
+ : needsReview
179
+ ? 'agent_harness mode:"mcp_servers" query:"browser desktop"'
180
+ : 'agent_harness mode:"mcp_servers" query:"browser desktop"';
181
+ const setupRoute = 'setup action:"item" setupItemId:"browser-desktop-control"';
182
+ return {
183
+ status: configured ? 'ready' : needsReview ? 'attention' : 'setup-needed',
184
+ configured,
185
+ needsReview,
186
+ toolMatches,
187
+ mcpServers,
188
+ workflows: browserControlWorkflows(configured, needsReview, recommendedRoute, setupRoute),
189
+ setupChecklist: [
190
+ 'Inspect browser/desktop MCP servers and first-class tools before attempting live UI control.',
191
+ 'Prefer constrained trust, fresh schemas, and explicit allowed hosts/paths.',
192
+ 'Use web_search or fetch instead when the task only needs public web information.',
193
+ 'Ask for confirmation before screenshots, authenticated browsing, account changes, purchases, sends, or destructive desktop actions.',
194
+ ],
195
+ fallbackRoutes: [
196
+ 'execution action:"route" id:"web-fetch-research"',
197
+ 'agent_harness mode:"mcp_servers" query:"browser desktop"',
198
+ ],
199
+ executionRoute: 'execution action:"route" id:"browser-or-desktop-control"',
200
+ setupRoute,
201
+ recommendedRoute,
202
+ policy: 'Browser and desktop control stays explicit: no live UI control is assumed unless a trusted tool or fresh constrained MCP server is configured.',
203
+ };
204
+ }
205
+
206
+ function workflowSearchText(workflow: BrowserControlWorkflow): string {
207
+ return [
208
+ workflow.id,
209
+ workflow.label,
210
+ workflow.summary,
211
+ workflow.next,
212
+ workflow.safety,
213
+ ].join('\n').toLowerCase();
214
+ }
215
+
216
+ function selectBrowserControlWorkflow(posture: BrowserControlPosture, input: string): BrowserControlWorkflow {
217
+ const normalized = input.toLowerCase();
218
+ if (!normalized) return posture.workflows[0]!;
219
+ const tokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);
220
+ const scored = posture.workflows
221
+ .map((workflow, index) => {
222
+ let score = 0;
223
+ const text = workflowSearchText(workflow);
224
+ if (workflow.id.includes(normalized) || workflow.label.toLowerCase().includes(normalized)) score += 1_000;
225
+ for (const token of tokens) {
226
+ if (workflow.id.includes(token)) score += 250;
227
+ if (workflow.label.toLowerCase().includes(token)) score += 200;
228
+ if (text.includes(token)) score += 40;
229
+ }
230
+ if (workflow.id === 'browser-navigation' && /browse|browser|navigate|url|page|click|form|login|web/.test(normalized)) score += 450;
231
+ if (workflow.id === 'screenshot-observation' && /screenshot|screen|observe|record|capture|visual|see/.test(normalized)) score += 450;
232
+ if (workflow.id === 'desktop-control' && /desktop|computer|app|window|keyboard|mouse|type|os/.test(normalized)) score += 450;
233
+ return { workflow, score, index };
234
+ })
235
+ .sort((left, right) => right.score - left.score || left.index - right.index);
236
+ return scored[0]?.workflow ?? posture.workflows[0]!;
237
+ }
238
+
239
+ function toolCandidateRoutes(toolMatches: readonly string[]): readonly Record<string, unknown>[] {
240
+ return toolMatches.slice(0, 8).map((toolName) => ({
241
+ toolName,
242
+ inspectRoute: `agent_harness mode:"tool" toolName:"${quoteRouteValue(toolName)}" includeParameters:true`,
243
+ modelRoute: `${toolName} ...`,
244
+ safety: 'Inspect the tool schema and policy before invoking a live browser, screenshot, or desktop-control action.',
245
+ }));
246
+ }
247
+
248
+ function mcpCandidateRoutes(mcpServers: readonly BrowserControlMcpServer[]): readonly Record<string, unknown>[] {
249
+ return mcpServers.slice(0, 8).map((server) => ({
250
+ serverName: server.name,
251
+ readiness: server.readiness,
252
+ connected: server.connected,
253
+ trustMode: server.trustMode,
254
+ schemaFreshness: server.schemaFreshness,
255
+ inspectRoute: server.modelRoute,
256
+ safety: 'Review trust and schema freshness before using MCP browser or desktop-control tools.',
257
+ }));
258
+ }
259
+
260
+ function browserControlDecision(
261
+ posture: BrowserControlPosture,
262
+ workflow: BrowserControlWorkflow,
263
+ toolRoutes: readonly Record<string, unknown>[],
264
+ mcpRoutes: readonly Record<string, unknown>[],
265
+ ): BrowserControlDecision {
266
+ const firstToolRoute = readString(toolRoutes[0]?.inspectRoute);
267
+ const firstReadyMcpRoute = readString(mcpRoutes.find((route) => route.readiness === 'ready')?.inspectRoute);
268
+ const firstReviewMcpRoute = readString(mcpRoutes[0]?.inspectRoute);
269
+ if (posture.configured) {
270
+ return {
271
+ id: 'inspect-configured-browser-control',
272
+ status: 'ready-to-inspect-tool',
273
+ modelRoute: firstToolRoute || firstReadyMcpRoute || posture.executionRoute,
274
+ userRoute: 'Agent Workspace -> Work & Approvals or Tools & MCP',
275
+ nextStep: `Inspect the configured ${workflow.label.toLowerCase()} tool/server, then invoke the narrowest live-control tool only if the user request still needs it.`,
276
+ reason: 'A browser/desktop control tool or fresh trusted MCP server is configured.',
277
+ safety: workflow.safety,
278
+ };
279
+ }
280
+ if (posture.needsReview) {
281
+ return {
282
+ id: 'review-browser-control-connector',
283
+ status: 'review-connector-first',
284
+ modelRoute: firstReviewMcpRoute || 'computer action:"mcp" query:"browser desktop" includeParameters:true',
285
+ userRoute: 'Agent Workspace -> Tools & MCP',
286
+ nextStep: 'Review connector trust, connectivity, and schema freshness before treating browser or desktop control as available.',
287
+ reason: 'A browser/desktop connector exists but needs trust, connectivity, or schema review.',
288
+ safety: 'Do not use stale or untrusted browser/desktop connectors for screenshots, authenticated pages, or desktop actions.',
289
+ };
290
+ }
291
+ return {
292
+ id: 'setup-browser-control',
293
+ status: 'setup-needed',
294
+ modelRoute: posture.setupRoute,
295
+ userRoute: 'Agent Workspace -> Setup',
296
+ nextStep: 'Configure a trusted browser/desktop tool or MCP server, or use the public web/fetch fallback when live UI state is not required.',
297
+ reason: 'No trusted browser/desktop control tool or fresh MCP server is configured.',
298
+ safety: 'This planner does not open, observe, or control the browser or desktop.',
299
+ };
300
+ }
301
+
302
+ export function browserControlRouteSummary(
303
+ context: CommandContext,
304
+ toolRegistry: ToolRegistry,
305
+ args: BrowserControlRouteArgs,
306
+ ): Record<string, unknown> {
307
+ const input = readString(args.query) || readString(args.target);
308
+ const includeParameters = args.includeParameters === true;
309
+ const posture = browserControlPosture(context, toolRegistry);
310
+ const workflow = selectBrowserControlWorkflow(posture, input);
311
+ const toolRoutes = toolCandidateRoutes(posture.toolMatches);
312
+ const mcpRoutes = mcpCandidateRoutes(posture.mcpServers);
313
+ const decision = browserControlDecision(posture, workflow, toolRoutes, mcpRoutes);
314
+ return {
315
+ mode: 'browser_control_route',
316
+ request: input || null,
317
+ status: posture.status,
318
+ configured: posture.configured,
319
+ needsReview: posture.needsReview,
320
+ workflow,
321
+ decision,
322
+ toolCandidates: toolRoutes,
323
+ mcpCandidates: mcpRoutes,
324
+ fallbackRoutes: posture.fallbackRoutes,
325
+ routes: {
326
+ controlPosture: 'computer action:"control" includeParameters:true',
327
+ setup: posture.setupRoute,
328
+ mcpReview: 'computer action:"mcp" query:"browser desktop" includeParameters:true',
329
+ publicWebFallback: posture.fallbackRoutes[0] ?? 'execution action:"route" id:"web-fetch-research"',
330
+ },
331
+ ...(includeParameters ? { posture } : {}),
332
+ policy: {
333
+ effect: 'read-only-route-plan',
334
+ boundary: 'This route selects the safest browser/desktop control workflow only. It never opens a browser, captures a screenshot, controls the desktop, or invokes a browser/MCP tool by itself.',
335
+ confirmation: 'Live browser, screenshot, authenticated browsing, account-changing, purchase, send, or destructive desktop actions require the selected tool-specific confirmation boundary and explicit user request.',
336
+ },
337
+ };
338
+ }