@minionry/minion 0.7.36

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 (476) hide show
  1. package/LICENSE +14 -0
  2. package/PRIVACY.md +357 -0
  3. package/README.md +57 -0
  4. package/THIRD_PARTY_NOTICES.md +245 -0
  5. package/bin/branding.js +4 -0
  6. package/bin/commands/browser-install.js +483 -0
  7. package/bin/commands/create-sandbox.js +542 -0
  8. package/bin/commands/fingerprint.js +101 -0
  9. package/bin/commands/login.js +400 -0
  10. package/bin/commands/logout.js +93 -0
  11. package/bin/commands/minions.js +211 -0
  12. package/bin/commands/sandboxes.js +309 -0
  13. package/bin/commands/status.js +298 -0
  14. package/bin/commands/whoami.js +153 -0
  15. package/bin/launch-env.js +35 -0
  16. package/bin/machine-identity.js +221 -0
  17. package/bin/machine-layout.js +200 -0
  18. package/bin/minion.js +839 -0
  19. package/bin/platform-endpoints.js +8 -0
  20. package/bin/postinstall.js +52 -0
  21. package/bin/pty-doctor.js +326 -0
  22. package/bin/pty-locator.js +110 -0
  23. package/bin/pty-provision.js +186 -0
  24. package/bin/sandbox/Dockerfile +78 -0
  25. package/bin/sandbox/entrypoint.sh +14 -0
  26. package/bin/sandbox/install-repo.sh +53 -0
  27. package/bin/sandbox/seccomp-userns.json +883 -0
  28. package/bin/sandbox-config.js +306 -0
  29. package/dist/bin/machine-identity.js +221 -0
  30. package/dist/bin/machine-layout.js +200 -0
  31. package/dist/electron-host/agent-lease.js +141 -0
  32. package/dist/electron-host/dom-driver.js +642 -0
  33. package/dist/electron-host/ipc-protocol.js +89 -0
  34. package/dist/electron-host/js-driver.js +216 -0
  35. package/dist/electron-host/view-manager.js +254 -0
  36. package/dist/server/cli/engine-resume.js +49 -0
  37. package/dist/server/cli/eta-estimator.js +278 -0
  38. package/dist/server/cli/headless/background-activity.js +109 -0
  39. package/dist/server/cli/headless/claude-invoker-process.js +614 -0
  40. package/dist/server/cli/headless/claude-invoker-stall.js +150 -0
  41. package/dist/server/cli/headless/claude-invoker-stream.js +555 -0
  42. package/dist/server/cli/headless/claude-invoker-tools.js +148 -0
  43. package/dist/server/cli/headless/claude-invoker.js +151 -0
  44. package/dist/server/cli/headless/engine-availability.js +92 -0
  45. package/dist/server/cli/headless/engine-notice.js +185 -0
  46. package/dist/server/cli/headless/haiku-assessments.js +293 -0
  47. package/dist/server/cli/headless/headless-logger.js +75 -0
  48. package/dist/server/cli/headless/index.js +9 -0
  49. package/dist/server/cli/headless/mcp-config.js +314 -0
  50. package/dist/server/cli/headless/native-timeout-detector.js +72 -0
  51. package/dist/server/cli/headless/output-utils.js +71 -0
  52. package/dist/server/cli/headless/prompt-utils.js +82 -0
  53. package/dist/server/cli/headless/resilient-runner.js +326 -0
  54. package/dist/server/cli/headless/retry-strategies.js +292 -0
  55. package/dist/server/cli/headless/runner.js +245 -0
  56. package/dist/server/cli/headless/stall-assessor.js +295 -0
  57. package/dist/server/cli/headless/tool-watchdog.js +447 -0
  58. package/dist/server/cli/headless/types.js +18 -0
  59. package/dist/server/cli/history-portability.js +85 -0
  60. package/dist/server/cli/improvisation-attachments.js +99 -0
  61. package/dist/server/cli/improvisation-history-store.js +121 -0
  62. package/dist/server/cli/improvisation-movements.js +137 -0
  63. package/dist/server/cli/improvisation-output-queue.js +34 -0
  64. package/dist/server/cli/improvisation-retry.js +8 -0
  65. package/dist/server/cli/improvisation-session-manager.js +1016 -0
  66. package/dist/server/cli/improvisation-types.js +31 -0
  67. package/dist/server/cli/plan-lifecycle.js +72 -0
  68. package/dist/server/cli/prompt-builders.js +371 -0
  69. package/dist/server/cli/retry/retry-best-result.js +28 -0
  70. package/dist/server/cli/retry/retry-context-loss.js +75 -0
  71. package/dist/server/cli/retry/retry-recovery-strategies.js +213 -0
  72. package/dist/server/cli/retry/retry-resume-strategy.js +20 -0
  73. package/dist/server/cli/retry/retry-runner-factory.js +92 -0
  74. package/dist/server/cli/retry/retry-tool-results.js +22 -0
  75. package/dist/server/cli/retry/retry-types.js +3 -0
  76. package/dist/server/engines/EngineEvent.js +57 -0
  77. package/dist/server/engines/claude/ClaudeCodeEngine.js +316 -0
  78. package/dist/server/engines/claude/claude-command.js +32 -0
  79. package/dist/server/engines/codex/CodexEngine.js +469 -0
  80. package/dist/server/engines/codex/codex-auth.js +203 -0
  81. package/dist/server/engines/codex/codex-invoker.js +205 -0
  82. package/dist/server/engines/codex/codex-provision.js +215 -0
  83. package/dist/server/engines/credentials/credential-probe.js +88 -0
  84. package/dist/server/engines/credentials/model-profiles.js +249 -0
  85. package/dist/server/engines/credentials/provider-credentials.js +146 -0
  86. package/dist/server/engines/engine-event-stream.js +52 -0
  87. package/dist/server/engines/execution/engine-session.js +380 -0
  88. package/dist/server/engines/factory.js +42 -0
  89. package/dist/server/engines/hermes/HermesEngine.js +628 -0
  90. package/dist/server/engines/hermes/hermes-auth.js +159 -0
  91. package/dist/server/engines/hermes/hermes-gateway-home.js +271 -0
  92. package/dist/server/engines/hermes/hermes-invoker.js +350 -0
  93. package/dist/server/engines/hermes/hermes-provision.js +318 -0
  94. package/dist/server/engines/read-only.js +20 -0
  95. package/dist/server/engines/types.js +27 -0
  96. package/dist/server/handlers/company-execution-registry.js +67 -0
  97. package/dist/server/handlers/company-handlers.js +514 -0
  98. package/dist/server/handlers/company-triggers.js +189 -0
  99. package/dist/server/handlers/company-types.js +3 -0
  100. package/dist/server/index.js +244 -0
  101. package/dist/server/mcp/app-tools-bridge.js +110 -0
  102. package/dist/server/mcp/app-tools-mcp-server.js +99 -0
  103. package/dist/server/mcp/bouncer-integration.js +744 -0
  104. package/dist/server/mcp/browser-mcp-server.js +915 -0
  105. package/dist/server/mcp/browser-redaction.js +103 -0
  106. package/dist/server/mcp/classifier/BouncerClassifier.js +3 -0
  107. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js +212 -0
  108. package/dist/server/mcp/classifier/factory.js +124 -0
  109. package/dist/server/mcp/classifier/health.js +54 -0
  110. package/dist/server/mcp/classifier/telemetry.js +0 -0
  111. package/dist/server/mcp/company-patterns.js +104 -0
  112. package/dist/server/mcp/department-profiles.js +133 -0
  113. package/dist/server/mcp/quality-bridge.js +153 -0
  114. package/dist/server/mcp/quality-mcp-server.js +105 -0
  115. package/dist/server/mcp/security-analysis.js +384 -0
  116. package/dist/server/mcp/security-audit.js +152 -0
  117. package/dist/server/mcp/security-patterns.js +314 -0
  118. package/dist/server/mcp/server.js +194 -0
  119. package/dist/server/mcp/test-utils/agent-simulator.js +301 -0
  120. package/dist/server/mcp/test-utils/e2e-agent.js +103 -0
  121. package/dist/server/mcp/test-utils/e2e-capture.js +92 -0
  122. package/dist/server/mcp/test-utils/e2e-client.js +116 -0
  123. package/dist/server/mcp/test-utils/e2e-fixtures.js +87 -0
  124. package/dist/server/mcp/test-utils/e2e-gating.js +8 -0
  125. package/dist/server/mcp/test-utils/e2e-harness.js +8 -0
  126. package/dist/server/mcp/test-utils/e2e-scenarios.js +105 -0
  127. package/dist/server/routes/files.js +18 -0
  128. package/dist/server/routes/improvise.js +64 -0
  129. package/dist/server/routes/index.js +7 -0
  130. package/dist/server/routes/instances.js +41 -0
  131. package/dist/server/routes/internal.js +900 -0
  132. package/dist/server/routes/notifications.js +110 -0
  133. package/dist/server/server-setup.js +282 -0
  134. package/dist/server/services/agent-push.js +148 -0
  135. package/dist/server/services/analytics.js +197 -0
  136. package/dist/server/services/apps/build.js +249 -0
  137. package/dist/server/services/apps/greenlight.js +199 -0
  138. package/dist/server/services/apps/install.js +101 -0
  139. package/dist/server/services/apps/layout.js +35 -0
  140. package/dist/server/services/apps/serve.js +665 -0
  141. package/dist/server/services/apps/space-apps.js +248 -0
  142. package/dist/server/services/auth.js +48 -0
  143. package/dist/server/services/browser/chrome-sandbox.js +245 -0
  144. package/dist/server/services/browser/chromium-launch-spec.js +51 -0
  145. package/dist/server/services/browser/claude-reasoner.js +669 -0
  146. package/dist/server/services/browser/debug-log.js +3 -0
  147. package/dist/server/services/browser/driver-state.js +546 -0
  148. package/dist/server/services/browser/electron-provision.js +256 -0
  149. package/dist/server/services/browser/host-internal.js +245 -0
  150. package/dist/server/services/browser/host-mock.js +334 -0
  151. package/dist/server/services/browser/host-types.js +3 -0
  152. package/dist/server/services/browser/host.js +1067 -0
  153. package/dist/server/services/browser/index.js +4 -0
  154. package/dist/server/services/browser/ipc-client.js +354 -0
  155. package/dist/server/services/browser/pipewire-sink.js +199 -0
  156. package/dist/server/services/browser/preflight.js +590 -0
  157. package/dist/server/services/browser/reasoning-agent.js +659 -0
  158. package/dist/server/services/browser/sandbox-policy.js +169 -0
  159. package/dist/server/services/browser/stderr-noise-filter.js +26 -0
  160. package/dist/server/services/browser/telemetry.js +107 -0
  161. package/dist/server/services/browser/xvfb-supervisor.js +139 -0
  162. package/dist/server/services/browser-frame-policy.js +56 -0
  163. package/dist/server/services/client-id.js +32 -0
  164. package/dist/server/services/collab/registry.js +408 -0
  165. package/dist/server/services/collab/session.js +489 -0
  166. package/dist/server/services/collab/text-diff.js +28 -0
  167. package/dist/server/services/collab/types.js +19 -0
  168. package/dist/server/services/e2ee-group-key.js +197 -0
  169. package/dist/server/services/e2ee-identity.js +203 -0
  170. package/dist/server/services/file-explorer-ops.js +328 -0
  171. package/dist/server/services/file-transfer-zip.js +188 -0
  172. package/dist/server/services/files.js +111 -0
  173. package/dist/server/services/git/branch-ops.js +62 -0
  174. package/dist/server/services/git/command.js +68 -0
  175. package/dist/server/services/git/commit-message.js +74 -0
  176. package/dist/server/services/git/diff-ops.js +56 -0
  177. package/dist/server/services/git/haiku.js +76 -0
  178. package/dist/server/services/git/head-watcher.js +226 -0
  179. package/dist/server/services/git/index.js +17 -0
  180. package/dist/server/services/git/log-ops.js +98 -0
  181. package/dist/server/services/git/merge-ops.js +314 -0
  182. package/dist/server/services/git/parsers.js +401 -0
  183. package/dist/server/services/git/remote-ops.js +192 -0
  184. package/dist/server/services/git/status-ops.js +105 -0
  185. package/dist/server/services/git/suggestion-ops.js +80 -0
  186. package/dist/server/services/git/tag-ops.js +36 -0
  187. package/dist/server/services/git/types.js +4 -0
  188. package/dist/server/services/git/worktree-ops.js +114 -0
  189. package/dist/server/services/instances.js +337 -0
  190. package/dist/server/services/model-catalog.js +247 -0
  191. package/dist/server/services/observability/posthog.js +153 -0
  192. package/dist/server/services/pathUtils.js +114 -0
  193. package/dist/server/services/plan/agent-loader.js +97 -0
  194. package/dist/server/services/plan/agent-manager.js +363 -0
  195. package/dist/server/services/plan/agent-resolver.js +74 -0
  196. package/dist/server/services/plan/agents/assess-stall.md +33 -0
  197. package/dist/server/services/plan/agents/browser-planner.md +53 -0
  198. package/dist/server/services/plan/agents/browser-reasoner.md +114 -0
  199. package/dist/server/services/plan/agents/check-injection.md +95 -0
  200. package/dist/server/services/plan/agents/classify-error.md +30 -0
  201. package/dist/server/services/plan/agents/code-review.md +142 -0
  202. package/dist/server/services/plan/agents/commit-message.md +28 -0
  203. package/dist/server/services/plan/agents/detect-context-loss.md +30 -0
  204. package/dist/server/services/plan/agents/execute-issue.md +58 -0
  205. package/dist/server/services/plan/agents/fix-quality.md +25 -0
  206. package/dist/server/services/plan/agents/plan-coordinator.md +72 -0
  207. package/dist/server/services/plan/agents/pr-description.md +29 -0
  208. package/dist/server/services/plan/agents/retry-task.md +27 -0
  209. package/dist/server/services/plan/agents/review-code.md +38 -0
  210. package/dist/server/services/plan/agents/review-quality.md +45 -0
  211. package/dist/server/services/plan/agents/triage-findings.md +78 -0
  212. package/dist/server/services/plan/agents/verify-review.md +57 -0
  213. package/dist/server/services/plan/approval-evaluator.js +143 -0
  214. package/dist/server/services/plan/board-archive.js +102 -0
  215. package/dist/server/services/plan/board-config.js +108 -0
  216. package/dist/server/services/plan/board-export.js +214 -0
  217. package/dist/server/services/plan/composer-prompt.js +115 -0
  218. package/dist/server/services/plan/composer.js +664 -0
  219. package/dist/server/services/plan/config-installer.js +103 -0
  220. package/dist/server/services/plan/dependency-resolver.js +137 -0
  221. package/dist/server/services/plan/executor.js +696 -0
  222. package/dist/server/services/plan/front-matter.js +43 -0
  223. package/dist/server/services/plan/issue-classification.js +10 -0
  224. package/dist/server/services/plan/issue-effort.js +182 -0
  225. package/dist/server/services/plan/issue-loader.js +35 -0
  226. package/dist/server/services/plan/issue-prompt-builder.js +152 -0
  227. package/dist/server/services/plan/issue-retry.js +42 -0
  228. package/dist/server/services/plan/issue-writer.js +102 -0
  229. package/dist/server/services/plan/metrics-collector.js +272 -0
  230. package/dist/server/services/plan/output-manager.js +77 -0
  231. package/dist/server/services/plan/parser-core.js +435 -0
  232. package/dist/server/services/plan/parser-migration.js +108 -0
  233. package/dist/server/services/plan/parser.js +258 -0
  234. package/dist/server/services/plan/plan-runner-factory.js +68 -0
  235. package/dist/server/services/plan/pm-timeline.js +320 -0
  236. package/dist/server/services/plan/progress-log.js +101 -0
  237. package/dist/server/services/plan/prompt-builder.js +142 -0
  238. package/dist/server/services/plan/quality-delta.js +274 -0
  239. package/dist/server/services/plan/readiness-planner.js +34 -0
  240. package/dist/server/services/plan/review-gate.js +409 -0
  241. package/dist/server/services/plan/review-report.js +134 -0
  242. package/dist/server/services/plan/review-verdict-stream.js +161 -0
  243. package/dist/server/services/plan/state-reconciler.js +238 -0
  244. package/dist/server/services/plan/template-diff.js +175 -0
  245. package/dist/server/services/plan/template-instantiator.js +516 -0
  246. package/dist/server/services/plan/template-manifest.js +56 -0
  247. package/dist/server/services/plan/template-types.js +3 -0
  248. package/dist/server/services/plan/trigger-evaluator.js +211 -0
  249. package/dist/server/services/plan/types.js +3 -0
  250. package/dist/server/services/plan/watcher.js +73 -0
  251. package/dist/server/services/platform-credentials.js +56 -0
  252. package/dist/server/services/platform-e2ee.js +421 -0
  253. package/dist/server/services/platform-envelope.js +102 -0
  254. package/dist/server/services/platform-heartbeat.js +88 -0
  255. package/dist/server/services/platform-reconnect.js +60 -0
  256. package/dist/server/services/platform-token-lifecycle.js +95 -0
  257. package/dist/server/services/platform-url.js +17 -0
  258. package/dist/server/services/platform.js +656 -0
  259. package/dist/server/services/runtime-info.js +9 -0
  260. package/dist/server/services/schedule/agent-schedule-store.js +232 -0
  261. package/dist/server/services/schedule/agent-scheduler.js +323 -0
  262. package/dist/server/services/schedule/daily-timing.js +105 -0
  263. package/dist/server/services/schedule/quality-schedule-launch.js +11 -0
  264. package/dist/server/services/schedule/quality-schedule-store.js +211 -0
  265. package/dist/server/services/schedule/quality-scheduler.js +215 -0
  266. package/dist/server/services/schedule/run-bootstrap.js +329 -0
  267. package/dist/server/services/schedule/schedule-store.js +238 -0
  268. package/dist/server/services/schedule/schedule-wire.js +77 -0
  269. package/dist/server/services/schedule/scheduler.js +310 -0
  270. package/dist/server/services/schedule/template-source.js +97 -0
  271. package/dist/server/services/sdk/agent-sessions.js +264 -0
  272. package/dist/server/services/sdk/agents.js +557 -0
  273. package/dist/server/services/sdk/app-endpoints.js +48 -0
  274. package/dist/server/services/sdk/app-tools.js +303 -0
  275. package/dist/server/services/sdk/audit.js +48 -0
  276. package/dist/server/services/sdk/browser-transport.js +188 -0
  277. package/dist/server/services/sdk/browser.js +605 -0
  278. package/dist/server/services/sdk/composer.js +129 -0
  279. package/dist/server/services/sdk/connect.js +273 -0
  280. package/dist/server/services/sdk/consent-cooldown.js +31 -0
  281. package/dist/server/services/sdk/endpoint-url.js +141 -0
  282. package/dist/server/services/sdk/endpoints.js +314 -0
  283. package/dist/server/services/sdk/file-change-notify.js +36 -0
  284. package/dist/server/services/sdk/files-app.js +163 -0
  285. package/dist/server/services/sdk/files-search.js +131 -0
  286. package/dist/server/services/sdk/files-transfer.js +279 -0
  287. package/dist/server/services/sdk/files-workspace.js +233 -0
  288. package/dist/server/services/sdk/git.js +520 -0
  289. package/dist/server/services/sdk/grant-store.js +318 -0
  290. package/dist/server/services/sdk/host-ops.js +84 -0
  291. package/dist/server/services/sdk/inference-claude.js +214 -0
  292. package/dist/server/services/sdk/inference.js +247 -0
  293. package/dist/server/services/sdk/live-registry.js +42 -0
  294. package/dist/server/services/sdk/local-app-bindings.js +71 -0
  295. package/dist/server/services/sdk/pipeline.js +190 -0
  296. package/dist/server/services/sdk/pm-execute.js +228 -0
  297. package/dist/server/services/sdk/pm-planning-tap.js +29 -0
  298. package/dist/server/services/sdk/pm-schedule.js +165 -0
  299. package/dist/server/services/sdk/pm.js +634 -0
  300. package/dist/server/services/sdk/quality-change-notify.js +20 -0
  301. package/dist/server/services/sdk/quality-schedule.js +165 -0
  302. package/dist/server/services/sdk/quality.js +602 -0
  303. package/dist/server/services/sdk/rate-limits.js +198 -0
  304. package/dist/server/services/sdk/registry.js +597 -0
  305. package/dist/server/services/sdk/revoke.js +86 -0
  306. package/dist/server/services/sdk/run-profile.js +41 -0
  307. package/dist/server/services/sdk/sandbox.js +89 -0
  308. package/dist/server/services/sdk/storage.js +110 -0
  309. package/dist/server/services/sdk/streams.js +147 -0
  310. package/dist/server/services/sdk/terminal.js +201 -0
  311. package/dist/server/services/sdk/test-utils/workshop-browser-app.js +466 -0
  312. package/dist/server/services/sentry.js +99 -0
  313. package/dist/server/services/settings.js +374 -0
  314. package/dist/server/services/snippets/expander.js +87 -0
  315. package/dist/server/services/snippets/index.js +6 -0
  316. package/dist/server/services/snippets/loader.js +119 -0
  317. package/dist/server/services/snippets/parser.js +52 -0
  318. package/dist/server/services/snippets/types.js +3 -0
  319. package/dist/server/services/snippets/watcher.js +60 -0
  320. package/dist/server/services/space-layout.js +80 -0
  321. package/dist/server/services/system-prompts.js +219 -0
  322. package/dist/server/services/terminal/pty-manager.js +206 -0
  323. package/dist/server/services/terminal/pty-utils.js +150 -0
  324. package/dist/server/services/timeline/assembler.js +890 -0
  325. package/dist/server/services/timeline/contract.js +196 -0
  326. package/dist/server/services/timeline/index.js +4 -0
  327. package/dist/server/services/websocket/agent-schedule-handlers.js +217 -0
  328. package/dist/server/services/websocket/apps-handlers.js +399 -0
  329. package/dist/server/services/websocket/ask-user-question-bridge.js +112 -0
  330. package/dist/server/services/websocket/autocomplete-index.js +415 -0
  331. package/dist/server/services/websocket/autocomplete-match.js +243 -0
  332. package/dist/server/services/websocket/autocomplete.js +407 -0
  333. package/dist/server/services/websocket/browser-agent-runtime.js +208 -0
  334. package/dist/server/services/websocket/browser-device-profile.js +46 -0
  335. package/dist/server/services/websocket/browser-handlers.js +377 -0
  336. package/dist/server/services/websocket/browser-host-broadcast.js +179 -0
  337. package/dist/server/services/websocket/browser-ice-config.js +121 -0
  338. package/dist/server/services/websocket/browser-payloads.js +222 -0
  339. package/dist/server/services/websocket/browser-viewer-lifecycle.js +84 -0
  340. package/dist/server/services/websocket/browser-viewer-registry.js +118 -0
  341. package/dist/server/services/websocket/collab-broadcast.js +11 -0
  342. package/dist/server/services/websocket/collab-handlers.js +116 -0
  343. package/dist/server/services/websocket/commit-suggestion-service.js +132 -0
  344. package/dist/server/services/websocket/debug-log.js +38 -0
  345. package/dist/server/services/websocket/dispatch-util.js +10 -0
  346. package/dist/server/services/websocket/engine-auth-handlers.js +323 -0
  347. package/dist/server/services/websocket/engine-credential-watcher.js +83 -0
  348. package/dist/server/services/websocket/engine-profile-handlers.js +92 -0
  349. package/dist/server/services/websocket/file-definition-handlers.js +180 -0
  350. package/dist/server/services/websocket/file-download-handler.js +291 -0
  351. package/dist/server/services/websocket/file-explorer-handlers.js +291 -0
  352. package/dist/server/services/websocket/file-search-handlers.js +267 -0
  353. package/dist/server/services/websocket/file-share-handlers.js +328 -0
  354. package/dist/server/services/websocket/file-transfer-http.js +361 -0
  355. package/dist/server/services/websocket/file-upload-handler.js +267 -0
  356. package/dist/server/services/websocket/file-utils.js +346 -0
  357. package/dist/server/services/websocket/git-branch-handlers.js +90 -0
  358. package/dist/server/services/websocket/git-diff-handlers.js +59 -0
  359. package/dist/server/services/websocket/git-handlers.js +212 -0
  360. package/dist/server/services/websocket/git-head-watcher.js +85 -0
  361. package/dist/server/services/websocket/git-log-handlers.js +104 -0
  362. package/dist/server/services/websocket/git-pr-handlers.js +56 -0
  363. package/dist/server/services/websocket/git-tag-handlers.js +53 -0
  364. package/dist/server/services/websocket/git-utils.js +11 -0
  365. package/dist/server/services/websocket/git-worktree-handlers.js +521 -0
  366. package/dist/server/services/websocket/handler-context.js +113 -0
  367. package/dist/server/services/websocket/handler.js +1197 -0
  368. package/dist/server/services/websocket/index.js +5 -0
  369. package/dist/server/services/websocket/movement-written-files.js +26 -0
  370. package/dist/server/services/websocket/msg-id-tracker.js +48 -0
  371. package/dist/server/services/websocket/plan-board-handlers.js +410 -0
  372. package/dist/server/services/websocket/plan-execution-handlers.js +244 -0
  373. package/dist/server/services/websocket/plan-handlers.js +67 -0
  374. package/dist/server/services/websocket/plan-helpers.js +161 -0
  375. package/dist/server/services/websocket/plan-issue-handlers.js +168 -0
  376. package/dist/server/services/websocket/plan-sprint-handlers.js +190 -0
  377. package/dist/server/services/websocket/plan-transfer-handlers.js +310 -0
  378. package/dist/server/services/websocket/pm-timeline-broadcast.js +28 -0
  379. package/dist/server/services/websocket/post-session-scan.js +132 -0
  380. package/dist/server/services/websocket/prompt-queue-handlers.js +96 -0
  381. package/dist/server/services/websocket/quality-agent-cost.js +229 -0
  382. package/dist/server/services/websocket/quality-agent-notes.js +113 -0
  383. package/dist/server/services/websocket/quality-change-activity.js +187 -0
  384. package/dist/server/services/websocket/quality-complexity.js +345 -0
  385. package/dist/server/services/websocket/quality-dependencies.js +445 -0
  386. package/dist/server/services/websocket/quality-duplication.js +162 -0
  387. package/dist/server/services/websocket/quality-eta.js +65 -0
  388. package/dist/server/services/websocket/quality-fingerprint.js +104 -0
  389. package/dist/server/services/websocket/quality-grading.js +575 -0
  390. package/dist/server/services/websocket/quality-handlers.js +48 -0
  391. package/dist/server/services/websocket/quality-linting.js +270 -0
  392. package/dist/server/services/websocket/quality-operations.js +54 -0
  393. package/dist/server/services/websocket/quality-persistence.js +410 -0
  394. package/dist/server/services/websocket/quality-review-agent.js +526 -0
  395. package/dist/server/services/websocket/quality-run.js +220 -0
  396. package/dist/server/services/websocket/quality-secrets.js +0 -0
  397. package/dist/server/services/websocket/quality-service.js +775 -0
  398. package/dist/server/services/websocket/quality-tools.js +383 -0
  399. package/dist/server/services/websocket/quality-triage-agent.js +101 -0
  400. package/dist/server/services/websocket/quality-types.js +149 -0
  401. package/dist/server/services/websocket/recommended-answers.js +28 -0
  402. package/dist/server/services/websocket/schedule-handlers.js +197 -0
  403. package/dist/server/services/websocket/sdk-agent-host.js +569 -0
  404. package/dist/server/services/websocket/sdk-browser-host.js +459 -0
  405. package/dist/server/services/websocket/sdk-composer-host.js +10 -0
  406. package/dist/server/services/websocket/sdk-git-host.js +115 -0
  407. package/dist/server/services/websocket/sdk-handlers.js +242 -0
  408. package/dist/server/services/websocket/sdk-pm-execution-host.js +63 -0
  409. package/dist/server/services/websocket/sdk-pm-schedule-host.js +21 -0
  410. package/dist/server/services/websocket/sdk-quality-schedule-host.js +34 -0
  411. package/dist/server/services/websocket/sdk-terminal-host.js +140 -0
  412. package/dist/server/services/websocket/session-handlers.js +565 -0
  413. package/dist/server/services/websocket/session-history.js +335 -0
  414. package/dist/server/services/websocket/session-initialization.js +315 -0
  415. package/dist/server/services/websocket/session-registry.js +340 -0
  416. package/dist/server/services/websocket/session-role-directory.js +39 -0
  417. package/dist/server/services/websocket/settings-handlers.js +276 -0
  418. package/dist/server/services/websocket/skill-handlers.js +324 -0
  419. package/dist/server/services/websocket/skill-watcher.js +83 -0
  420. package/dist/server/services/websocket/snippet-handlers.js +261 -0
  421. package/dist/server/services/websocket/tab-broadcast.js +35 -0
  422. package/dist/server/services/websocket/tab-event-buffer.js +110 -0
  423. package/dist/server/services/websocket/tab-event-replay.js +47 -0
  424. package/dist/server/services/websocket/tab-handlers.js +211 -0
  425. package/dist/server/services/websocket/terminal-handlers.js +268 -0
  426. package/dist/server/services/websocket/types.js +96 -0
  427. package/dist/server/types/company-messages.js +102 -0
  428. package/dist/server/utils/agent-manager.js +202 -0
  429. package/dist/server/utils/console-timestamps.js +24 -0
  430. package/dist/server/utils/file-store.js +112 -0
  431. package/dist/server/utils/paths.js +28 -0
  432. package/dist/server/utils/port-manager.js +43 -0
  433. package/dist/server/utils/port.js +204 -0
  434. package/electron-host/dist/agent-lease.js +141 -0
  435. package/electron-host/dist/capture-recovery.js +77 -0
  436. package/electron-host/dist/codec-policy.js +37 -0
  437. package/electron-host/dist/controller-channel.js +60 -0
  438. package/electron-host/dist/controller-handlers.js +153 -0
  439. package/electron-host/dist/device-emulator.js +106 -0
  440. package/electron-host/dist/dom-driver.js +642 -0
  441. package/electron-host/dist/domain-registry.js +159 -0
  442. package/electron-host/dist/domain-validators.js +308 -0
  443. package/electron-host/dist/editable-focus-reporter.js +143 -0
  444. package/electron-host/dist/fake-peer.test-util.js +105 -0
  445. package/electron-host/dist/host-log.js +31 -0
  446. package/electron-host/dist/host-wire.js +11 -0
  447. package/electron-host/dist/input-router.js +421 -0
  448. package/electron-host/dist/ipc-protocol.js +89 -0
  449. package/electron-host/dist/ipc-server.js +193 -0
  450. package/electron-host/dist/js-driver.js +216 -0
  451. package/electron-host/dist/main-guards.js +70 -0
  452. package/electron-host/dist/main.js +716 -0
  453. package/electron-host/dist/roster-sync.js +87 -0
  454. package/electron-host/dist/rpc-context.js +1 -0
  455. package/electron-host/dist/rpc-tab-methods.js +138 -0
  456. package/electron-host/dist/rpc-webrtc-methods.js +121 -0
  457. package/electron-host/dist/screen-capture-cache.js +147 -0
  458. package/electron-host/dist/sdk-injector.js +166 -0
  459. package/electron-host/dist/sdp.js +102 -0
  460. package/electron-host/dist/session-surface.js +78 -0
  461. package/electron-host/dist/surface-sizing.js +59 -0
  462. package/electron-host/dist/view-manager.js +254 -0
  463. package/electron-host/dist/viewer-registry.js +46 -0
  464. package/electron-host/dist/viewer-session.js +288 -0
  465. package/electron-host/dist/webrtc-channels.js +14 -0
  466. package/electron-host/dist/webrtc-controller.js +57 -0
  467. package/electron-host/dist/webrtc-ice-filter.js +13 -0
  468. package/electron-host/dist/webrtc-peer.js +45 -0
  469. package/electron-host/package.json +12 -0
  470. package/electron-host/tsconfig.json +23 -0
  471. package/electron-host/webrtc-controller-preload.cjs +3 -0
  472. package/electron-host/webrtc-controller.html +14 -0
  473. package/package.json +85 -0
  474. package/vendor/e2ee/LICENSE +14 -0
  475. package/vendor/e2ee/package.json +14 -0
  476. package/vendor/e2ee/src/index.js +310 -0
@@ -0,0 +1,900 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { getConnInfo } from '@hono/node-server/conninfo';
4
+ import { Hono } from 'hono';
5
+ import { invokeExposedAppTool, listExposedAppTools, } from '../mcp/app-tools-bridge.js';
6
+ import { parseQualityCheckPaths, runQualityCheck } from '../mcp/quality-bridge.js';
7
+ import { getBrowserDriverState, INPUT_MUTATING_BROWSER_TOOLS, } from '../services/browser/driver-state.js';
8
+ import { deriveSpaceBrowserAgentId } from '../services/instances.js';
9
+ import { getBouncerSecret, isValidBouncerSecret, registerPendingQuestion, resolveMcpCapability, } from '../services/websocket/ask-user-question-bridge.js';
10
+ import { broadcastAgentTabState } from '../services/websocket/browser-agent-runtime.js';
11
+ import { selectRecommendedAnswers } from '../services/websocket/recommended-answers.js';
12
+ import { broadcastTabEvent } from '../services/websocket/tab-broadcast.js';
13
+ export { getBouncerSecret };
14
+ function parseQuestions(value) {
15
+ if (!Array.isArray(value))
16
+ return null;
17
+ const out = [];
18
+ for (const raw of value) {
19
+ if (!raw || typeof raw !== 'object')
20
+ return null;
21
+ const r = raw;
22
+ if (typeof r.question !== 'string' || typeof r.header !== 'string')
23
+ return null;
24
+ if (!Array.isArray(r.options))
25
+ return null;
26
+ const options = r.options.map((o) => {
27
+ if (!o || typeof o !== 'object')
28
+ return null;
29
+ const oo = o;
30
+ if (typeof oo.label !== 'string')
31
+ return null;
32
+ return {
33
+ label: oo.label,
34
+ description: typeof oo.description === 'string' ? oo.description : '',
35
+ preview: typeof oo.preview === 'string' ? oo.preview : undefined,
36
+ };
37
+ });
38
+ if (options.some((o) => o === null))
39
+ return null;
40
+ out.push({
41
+ question: r.question,
42
+ header: r.header,
43
+ options: options,
44
+ multiSelect: r.multiSelect === true,
45
+ });
46
+ }
47
+ return out;
48
+ }
49
+ function parseAskUserQuestionBody(body) {
50
+ const toolUseId = typeof body.toolUseId === 'string' ? body.toolUseId : '';
51
+ const tabId = typeof body.tabId === 'string' ? body.tabId : '';
52
+ const questions = parseQuestions(body.questions);
53
+ if (!toolUseId || !tabId || !questions || questions.length === 0) {
54
+ return null;
55
+ }
56
+ const timeoutMs = typeof body.timeoutMs === 'number' && body.timeoutMs > 0 ? body.timeoutMs : undefined;
57
+ return { toolUseId, tabId, questions, timeoutMs };
58
+ }
59
+ async function resolveAskUserQuestion(ctx, parsed) {
60
+ const { toolUseId, tabId, questions, timeoutMs } = parsed;
61
+ const payload = { toolUseId, questions };
62
+ broadcastTabEvent(ctx, tabId, 'askUserQuestion', payload);
63
+ try {
64
+ const { answers, timedOut } = await registerPendingQuestion({
65
+ toolUseId,
66
+ tabId,
67
+ questions,
68
+ timeoutMs,
69
+ computeTimeoutAnswers: () => selectRecommendedAnswers(questions),
70
+ });
71
+ if (timedOut) {
72
+ broadcastTabEvent(ctx, tabId, 'askUserQuestionAutoAnswered', { toolUseId, answers });
73
+ }
74
+ return { status: 200, body: { answers } };
75
+ }
76
+ catch (err) {
77
+ const reason = err instanceof Error ? err.message : 'cancelled';
78
+ broadcastTabEvent(ctx, tabId, 'askUserQuestionDismissed', {
79
+ toolUseId,
80
+ reason: reason === 'timeout' ? 'timeout' : 'cancelled',
81
+ });
82
+ const status = reason === 'timeout' ? 504 : 410;
83
+ return { status, body: { error: reason } };
84
+ }
85
+ }
86
+ const CAPABILITY_TOKEN_HEADER = 'x-minionry-capability-token';
87
+ function logContradiction(route, field, claimed, bound) {
88
+ console.error(`[Internal] ${route}: refused — body ${field}=${JSON.stringify(claimed)} contradicts the capability token's ${JSON.stringify(bound)}`);
89
+ }
90
+ function appToolsContextFrom(capability, body, route) {
91
+ if (!capability.spaceDir) {
92
+ console.error(`[Internal] ${route}: refused — the capability token is bound to no Space`);
93
+ return { ok: false };
94
+ }
95
+ if (typeof body.spaceDir === 'string' && body.spaceDir !== capability.spaceDir) {
96
+ logContradiction(route, 'spaceDir', body.spaceDir, capability.spaceDir);
97
+ return { ok: false };
98
+ }
99
+ if (typeof body.onlyAppId === 'string' && body.onlyAppId !== capability.onlyAppId) {
100
+ logContradiction(route, 'onlyAppId', body.onlyAppId, capability.onlyAppId);
101
+ return { ok: false };
102
+ }
103
+ return {
104
+ ok: true,
105
+ ctx: {
106
+ spaceDir: capability.spaceDir,
107
+ ...(capability.onlyAppId ? { onlyAppId: capability.onlyAppId } : {}),
108
+ },
109
+ };
110
+ }
111
+ function qualityContextFrom(capability, body, route) {
112
+ if (!capability.spaceDir) {
113
+ console.error(`[Internal] ${route}: refused — the capability token is bound to no Space`);
114
+ return { ok: false };
115
+ }
116
+ if (!capability.tabId) {
117
+ console.error(`[Internal] ${route}: refused — the capability token is bound to no tab session`);
118
+ return { ok: false };
119
+ }
120
+ if (capability.onlyAppId) {
121
+ console.error(`[Internal] ${route}: refused — an app-confined run is never granted the quality check`);
122
+ return { ok: false };
123
+ }
124
+ if (typeof body.spaceDir === 'string' && body.spaceDir !== capability.spaceDir) {
125
+ logContradiction(route, 'spaceDir', body.spaceDir, capability.spaceDir);
126
+ return { ok: false };
127
+ }
128
+ return { ok: true, spaceRoot: capability.spaceDir, sessionKey: capability.tabId };
129
+ }
130
+ function toErrorBody(err) {
131
+ const e = err;
132
+ const code = typeof e?.code === 'string' ? e.code : 'internal_error';
133
+ const message = typeof e?.message === 'string' ? e.message : 'browser op failed';
134
+ const data = e?.currentOwner !== undefined
135
+ ? { currentOwner: e.currentOwner }
136
+ : e?.details !== undefined
137
+ ? e.details
138
+ : undefined;
139
+ const status = code === 'tab_already_leased'
140
+ ? 409
141
+ : code === 'browser_host_unavailable'
142
+ ? 503
143
+ : code === 'invalid_params'
144
+ ? 400
145
+ : 500;
146
+ return { body: { error: { code, message, ...(data !== undefined ? { data } : {}) } }, status };
147
+ }
148
+ class InvalidParamsError extends Error {
149
+ code = 'invalid_params';
150
+ constructor(message) {
151
+ super(message);
152
+ this.name = 'InvalidParamsError';
153
+ }
154
+ }
155
+ function requireString(params, name) {
156
+ const v = params?.[name];
157
+ if (typeof v !== 'string' || !v) {
158
+ throw new InvalidParamsError(`missing required string param: ${name}`);
159
+ }
160
+ return v;
161
+ }
162
+ function optionalString(params, name) {
163
+ const v = params?.[name];
164
+ if (v === undefined || v === null)
165
+ return undefined;
166
+ if (typeof v !== 'string') {
167
+ throw new InvalidParamsError(`expected string for param: ${name}`);
168
+ }
169
+ return v;
170
+ }
171
+ function viewTabId(host, params) {
172
+ const named = optionalString(params, 'tabId');
173
+ return named ? host.resolveAgentTabId(named) : undefined;
174
+ }
175
+ function requireStringArray(params, name) {
176
+ const v = params?.[name];
177
+ if (!Array.isArray(v) || v.some((x) => typeof x !== 'string')) {
178
+ throw new InvalidParamsError(`missing required string[] param: ${name}`);
179
+ }
180
+ return v;
181
+ }
182
+ function requireFormFields(params, name) {
183
+ const v = params?.[name];
184
+ if (!Array.isArray(v)) {
185
+ throw new InvalidParamsError(`missing required FormField[] param: ${name}`);
186
+ }
187
+ return v.map((raw, i) => {
188
+ if (!raw || typeof raw !== 'object') {
189
+ throw new InvalidParamsError(`${name}[${i}] is not an object`);
190
+ }
191
+ const r = raw;
192
+ if (typeof r.ref !== 'string' || typeof r.value !== 'string') {
193
+ throw new InvalidParamsError(`${name}[${i}] needs string ref + value`);
194
+ }
195
+ return { ref: r.ref, value: r.value };
196
+ });
197
+ }
198
+ export function resolveSpaceAgentId(spaceIdentity) {
199
+ if (spaceIdentity === undefined || spaceIdentity === null)
200
+ return null;
201
+ if (typeof spaceIdentity !== 'object') {
202
+ throw new InvalidParamsError('spaceIdentity must be an object');
203
+ }
204
+ const s = spaceIdentity;
205
+ if (typeof s.clientId !== 'string' || !s.clientId) {
206
+ throw new InvalidParamsError('spaceIdentity.clientId must be a non-empty string');
207
+ }
208
+ if (typeof s.workingDirectory !== 'string' || !s.workingDirectory) {
209
+ throw new InvalidParamsError('spaceIdentity.workingDirectory must be a non-empty string');
210
+ }
211
+ return deriveSpaceBrowserAgentId(s.clientId, s.workingDirectory);
212
+ }
213
+ const BROWSER_OP_HANDLERS = {
214
+ 'agent.tab.lease': (host, p) => {
215
+ const tabId = requireString(p, 'tabId');
216
+ const agentId = requireString(p, 'agentId');
217
+ const planId = optionalString(p, 'planId');
218
+ const ttlMs = typeof p.ttlMs === 'number' ? p.ttlMs : undefined;
219
+ return host.leaseTab({
220
+ tabId,
221
+ agentId,
222
+ ...(planId !== undefined ? { planId } : {}),
223
+ ...(ttlMs !== undefined ? { ttlMs } : {}),
224
+ });
225
+ },
226
+ 'agent.tab.release': (host, p) => {
227
+ const tabId = requireString(p, 'tabId');
228
+ const agentId = requireString(p, 'agentId');
229
+ return host.releaseTab({ tabId, agentId });
230
+ },
231
+ 'agent.tab.heartbeat': (host, p) => {
232
+ const agentId = requireString(p, 'agentId');
233
+ const tabIds = requireStringArray(p, 'tabIds');
234
+ const ttlMs = typeof p.ttlMs === 'number' ? p.ttlMs : undefined;
235
+ return host.heartbeat({
236
+ agentId,
237
+ tabIds,
238
+ ...(ttlMs !== undefined ? { ttlMs } : {}),
239
+ });
240
+ },
241
+ 'agent.tab.list': (host, p) => {
242
+ const filter = {};
243
+ const agentId = optionalString(p, 'agentId');
244
+ const planId = optionalString(p, 'planId');
245
+ if (agentId !== undefined)
246
+ filter.agentId = agentId;
247
+ if (planId !== undefined)
248
+ filter.planId = planId;
249
+ return host.listLeases(filter);
250
+ },
251
+ 'agent.plan.release': (host, p) => {
252
+ const planId = requireString(p, 'planId');
253
+ return host.releasePlan(planId);
254
+ },
255
+ 'tab.open': (host, p) => {
256
+ const url = requireString(p, 'url');
257
+ return host.openTab(url);
258
+ },
259
+ 'tab.close': async (host, p) => {
260
+ const id = requireString(p, 'id');
261
+ await host.closeTab(id);
262
+ return null;
263
+ },
264
+ 'tab.select': async (host, p) => {
265
+ const id = requireString(p, 'id');
266
+ await host.switchTab(id);
267
+ return null;
268
+ },
269
+ 'tab.list': (host, p) => {
270
+ const tabIds = Array.isArray(p.tabIds) ? p.tabIds : [];
271
+ const out = [];
272
+ for (const t of tabIds) {
273
+ if (typeof t !== 'string')
274
+ continue;
275
+ out.push({ tabId: t, info: host.getTabInfo(t) });
276
+ }
277
+ return out;
278
+ },
279
+ 'view.navigate': async (host, p) => {
280
+ const url = requireString(p, 'url');
281
+ await host.navigate(url, viewTabId(host, p));
282
+ return null;
283
+ },
284
+ 'view.back': async (host, p) => {
285
+ await host.goBack(viewTabId(host, p));
286
+ return null;
287
+ },
288
+ 'view.forward': async (host, p) => {
289
+ await host.goForward(viewTabId(host, p));
290
+ return null;
291
+ },
292
+ 'view.reload': async (host, p) => {
293
+ await host.reload(viewTabId(host, p));
294
+ return null;
295
+ },
296
+ 'dom.snapshot': (host, p) => {
297
+ const tabId = requireString(p, 'tabId');
298
+ return host.dom.snapshot({ tabId });
299
+ },
300
+ 'dom.click': async (host, p) => {
301
+ const tabId = requireString(p, 'tabId');
302
+ const ref = requireString(p, 'ref');
303
+ const button = (() => {
304
+ const b = p.button;
305
+ if (b === 'left' || b === 'right' || b === 'middle')
306
+ return b;
307
+ return undefined;
308
+ })();
309
+ const clickCount = typeof p.clickCount === 'number' ? p.clickCount : undefined;
310
+ const agentId = optionalString(p, 'agentId');
311
+ await host.dom.click({
312
+ tabId,
313
+ ref,
314
+ ...(button !== undefined ? { button } : {}),
315
+ ...(clickCount !== undefined ? { clickCount } : {}),
316
+ ...(agentId !== undefined ? { agentId } : {}),
317
+ });
318
+ return null;
319
+ },
320
+ 'dom.type': async (host, p) => {
321
+ const tabId = requireString(p, 'tabId');
322
+ const ref = requireString(p, 'ref');
323
+ const text = requireString(p, 'text');
324
+ const submit = p.submit === true;
325
+ const agentId = optionalString(p, 'agentId');
326
+ await host.dom.type({
327
+ tabId,
328
+ ref,
329
+ text,
330
+ submit,
331
+ ...(agentId !== undefined ? { agentId } : {}),
332
+ });
333
+ return null;
334
+ },
335
+ 'dom.hover': async (host, p) => {
336
+ const tabId = requireString(p, 'tabId');
337
+ const ref = requireString(p, 'ref');
338
+ const agentId = optionalString(p, 'agentId');
339
+ await host.dom.hover({
340
+ tabId,
341
+ ref,
342
+ ...(agentId !== undefined ? { agentId } : {}),
343
+ });
344
+ return null;
345
+ },
346
+ 'dom.press_key': async (host, p) => {
347
+ const tabId = requireString(p, 'tabId');
348
+ const key = requireString(p, 'key');
349
+ const agentId = optionalString(p, 'agentId');
350
+ await host.dom.pressKey({
351
+ tabId,
352
+ key,
353
+ ...(agentId !== undefined ? { agentId } : {}),
354
+ });
355
+ return null;
356
+ },
357
+ 'dom.select_option': async (host, p) => {
358
+ const tabId = requireString(p, 'tabId');
359
+ const ref = requireString(p, 'ref');
360
+ const values = requireStringArray(p, 'values');
361
+ const agentId = optionalString(p, 'agentId');
362
+ await host.dom.selectOption({
363
+ tabId,
364
+ ref,
365
+ values,
366
+ ...(agentId !== undefined ? { agentId } : {}),
367
+ });
368
+ return null;
369
+ },
370
+ 'dom.fill_form': async (host, p) => {
371
+ const tabId = requireString(p, 'tabId');
372
+ const fields = requireFormFields(p, 'fields');
373
+ const agentId = optionalString(p, 'agentId');
374
+ await host.dom.fillForm({
375
+ tabId,
376
+ fields,
377
+ ...(agentId !== undefined ? { agentId } : {}),
378
+ });
379
+ return null;
380
+ },
381
+ 'dom.drag_drop': async (host, p) => {
382
+ const tabId = requireString(p, 'tabId');
383
+ const fromRef = requireString(p, 'fromRef');
384
+ const toRef = requireString(p, 'toRef');
385
+ const agentId = optionalString(p, 'agentId');
386
+ await host.dom.dragDrop({
387
+ tabId,
388
+ fromRef,
389
+ toRef,
390
+ ...(agentId !== undefined ? { agentId } : {}),
391
+ });
392
+ return null;
393
+ },
394
+ 'dom.file_upload': async (host, p) => {
395
+ const tabId = requireString(p, 'tabId');
396
+ const ref = requireString(p, 'ref');
397
+ const paths = requireStringArray(p, 'paths');
398
+ const agentId = optionalString(p, 'agentId');
399
+ await host.dom.fileUpload({
400
+ tabId,
401
+ ref,
402
+ paths,
403
+ ...(agentId !== undefined ? { agentId } : {}),
404
+ });
405
+ return null;
406
+ },
407
+ 'dom.handle_dialog': async (host, p) => {
408
+ const tabId = requireString(p, 'tabId');
409
+ const accept = p.accept === true;
410
+ const promptText = optionalString(p, 'promptText');
411
+ const agentId = optionalString(p, 'agentId');
412
+ await host.dom.handleDialog({
413
+ tabId,
414
+ accept,
415
+ ...(promptText !== undefined ? { promptText } : {}),
416
+ ...(agentId !== undefined ? { agentId } : {}),
417
+ });
418
+ return null;
419
+ },
420
+ 'dom.wait_for': async (host, p) => {
421
+ const tabId = requireString(p, 'tabId');
422
+ const timeoutMs = typeof p.timeoutMs === 'number' ? p.timeoutMs : 5000;
423
+ const pollIntervalMs = typeof p.pollIntervalMs === 'number' ? p.pollIntervalMs : undefined;
424
+ const conditionRaw = p.condition;
425
+ if (!conditionRaw || typeof conditionRaw !== 'object') {
426
+ throw new InvalidParamsError('missing condition for wait_for');
427
+ }
428
+ const condition = conditionRaw.type === 'expression' && typeof conditionRaw.expr === 'string'
429
+ ? { type: 'expression', expr: conditionRaw.expr }
430
+ : conditionRaw.type === 'navigation'
431
+ ? { type: 'navigation' }
432
+ : null;
433
+ if (!condition) {
434
+ throw new InvalidParamsError('wait_for condition must be {type:"expression",expr} or {type:"navigation"}');
435
+ }
436
+ const agentId = optionalString(p, 'agentId');
437
+ await host.dom.waitFor({
438
+ tabId,
439
+ timeoutMs,
440
+ ...(pollIntervalMs !== undefined ? { pollIntervalMs } : {}),
441
+ condition,
442
+ ...(agentId !== undefined ? { agentId } : {}),
443
+ });
444
+ return null;
445
+ },
446
+ 'dom.screenshot': (host, p) => {
447
+ const tabId = requireString(p, 'tabId');
448
+ const format = p.format === 'jpeg' ? 'jpeg' : p.format === 'png' ? 'png' : undefined;
449
+ const quality = typeof p.quality === 'number' ? p.quality : undefined;
450
+ const fullPage = p.fullPage === true;
451
+ const clip = p.clip ?? undefined;
452
+ const clipShape = clip &&
453
+ typeof clip.x === 'number' &&
454
+ typeof clip.y === 'number' &&
455
+ typeof clip.width === 'number' &&
456
+ typeof clip.height === 'number'
457
+ ? {
458
+ x: clip.x,
459
+ y: clip.y,
460
+ width: clip.width,
461
+ height: clip.height,
462
+ }
463
+ : undefined;
464
+ return host.dom.screenshot({
465
+ tabId,
466
+ fullPage,
467
+ ...(format !== undefined ? { format } : {}),
468
+ ...(quality !== undefined ? { quality } : {}),
469
+ ...(clipShape !== undefined ? { clip: clipShape } : {}),
470
+ });
471
+ },
472
+ 'dom.console': (host, p) => {
473
+ const tabId = requireString(p, 'tabId');
474
+ const since = typeof p.since === 'number' ? p.since : undefined;
475
+ return host.dom.console({
476
+ tabId,
477
+ ...(since !== undefined ? { since } : {}),
478
+ });
479
+ },
480
+ 'dom.network': (host, p) => {
481
+ const tabId = requireString(p, 'tabId');
482
+ const since = typeof p.since === 'number' ? p.since : undefined;
483
+ return host.dom.network({
484
+ tabId,
485
+ ...(since !== undefined ? { since } : {}),
486
+ });
487
+ },
488
+ 'js.evaluate': (host, p) => {
489
+ const tabId = requireString(p, 'tabId');
490
+ const expr = requireString(p, 'expr');
491
+ const world = p.world === 'main' ? 'main' : 'isolated';
492
+ const timeoutMs = typeof p.timeoutMs === 'number' ? p.timeoutMs : undefined;
493
+ return host.js.evaluate({
494
+ tabId,
495
+ expr,
496
+ world,
497
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
498
+ });
499
+ },
500
+ };
501
+ export async function dispatchBrowserOp(host, req) {
502
+ const handler = BROWSER_OP_HANDLERS[req.method];
503
+ if (!handler) {
504
+ throw new InvalidParamsError(`unknown browser op method: ${req.method}`);
505
+ }
506
+ return handler(host, req.params ?? {});
507
+ }
508
+ function browserIdentityFrom(capability, body, route) {
509
+ if (!capability.agentId) {
510
+ console.error(`[Internal] ${route}: refused — the capability token is bound to no browser agent`);
511
+ return { ok: false };
512
+ }
513
+ const params = body.params ?? {};
514
+ for (const field of ['agentId', 'planId', 'agentSessionId']) {
515
+ const claimed = params[field];
516
+ if (typeof claimed === 'string' && claimed !== capability[field]) {
517
+ logContradiction(route, `params.${field}`, claimed, capability[field]);
518
+ return { ok: false };
519
+ }
520
+ }
521
+ if (body.spaceIdentity !== undefined && body.spaceIdentity !== null) {
522
+ let derived = null;
523
+ try {
524
+ derived = resolveSpaceAgentId(body.spaceIdentity);
525
+ }
526
+ catch {
527
+ derived = null;
528
+ }
529
+ if (derived !== capability.agentId) {
530
+ logContradiction(route, 'spaceIdentity', body.spaceIdentity, capability.agentId);
531
+ return { ok: false };
532
+ }
533
+ }
534
+ return { ok: true, identity: identityOf(capability, capability.agentId) };
535
+ }
536
+ function identityOf(capability, agentId) {
537
+ return {
538
+ agentId,
539
+ ...(capability.planId ? { planId: capability.planId } : {}),
540
+ ...(capability.defaultTabId ? { defaultTabId: capability.defaultTabId } : {}),
541
+ ...(capability.agentSessionId ? { agentSessionId: capability.agentSessionId } : {}),
542
+ ...(capability.agentLabel ? { agentLabel: capability.agentLabel } : {}),
543
+ };
544
+ }
545
+ function bindBrowserOp(body, identity) {
546
+ const params = { ...(body.params ?? {}) };
547
+ params.agentId = identity.agentId;
548
+ if (identity.planId !== undefined)
549
+ params.planId = identity.planId;
550
+ if (typeof params.tabId !== 'string' || !params.tabId) {
551
+ if (identity.defaultTabId !== undefined)
552
+ params.tabId = identity.defaultTabId;
553
+ else
554
+ delete params.tabId;
555
+ }
556
+ return { method: body.method, params };
557
+ }
558
+ async function reflectBrowserLeaseOp(ctx, host, op, result, identity) {
559
+ try {
560
+ if (op.method === 'agent.tab.lease') {
561
+ const lease = result;
562
+ getBrowserDriverState().setOwner(lease.tabId, leaseOwnerFor(identity, lease.leasedUntil));
563
+ await broadcastLeaseRoster(ctx, host, identity);
564
+ }
565
+ else if (op.method === 'agent.tab.heartbeat') {
566
+ await refreshHeldOwners(host, identity, result.stillLeased);
567
+ }
568
+ else if (op.method === 'agent.tab.release' && result.released) {
569
+ const tabId = op.params?.tabId;
570
+ if (typeof tabId === 'string')
571
+ getBrowserDriverState().clearOwner(tabId);
572
+ await broadcastLeaseRoster(ctx, host, identity);
573
+ }
574
+ }
575
+ catch (err) {
576
+ console.error(`[Internal] /browser/op: ${op.method} succeeded but its owner/roster mirror failed: ${err instanceof Error ? err.message : String(err)}`);
577
+ }
578
+ }
579
+ const AGENT_DRIVING_OPS = {
580
+ 'dom.click': 'browser_click',
581
+ 'dom.type': 'browser_type',
582
+ 'dom.hover': 'browser_hover',
583
+ 'dom.press_key': 'browser_press_key',
584
+ 'dom.select_option': 'browser_select_option',
585
+ 'dom.fill_form': 'browser_fill_form',
586
+ 'dom.drag_drop': 'browser_drag',
587
+ 'dom.file_upload': 'browser_file_upload',
588
+ 'dom.handle_dialog': 'browser_handle_dialog',
589
+ 'view.navigate': 'browser_navigate',
590
+ 'view.back': 'browser_back',
591
+ 'view.forward': 'browser_forward',
592
+ 'view.reload': 'browser_reload',
593
+ };
594
+ function drivenTabId(host, op) {
595
+ const named = op.params?.tabId;
596
+ if (typeof named === 'string' && named)
597
+ return host.resolveAgentTabId(named);
598
+ return op.method.startsWith('dom.') ? null : host.getTabsSnapshot().currentTabId;
599
+ }
600
+ function arbitrationRefusal(host, op) {
601
+ const tool = AGENT_DRIVING_OPS[op.method];
602
+ if (!tool || !INPUT_MUTATING_BROWSER_TOOLS.has(tool))
603
+ return null;
604
+ const tabId = drivenTabId(host, op);
605
+ if (!tabId)
606
+ return null;
607
+ const gate = getBrowserDriverState().gateSync(tabId, tool);
608
+ if (gate.allow)
609
+ return null;
610
+ console.error(`[Internal] /browser/op: ${op.method} on tab ${tabId.slice(0, 8)} deferred by driver arbitration (${gate.state})`);
611
+ return { error: { code: gate.code, message: gate.hint, data: { state: gate.state, since: gate.since } } };
612
+ }
613
+ function reflectAgentDriving(host, op) {
614
+ if (!(op.method in AGENT_DRIVING_OPS))
615
+ return;
616
+ try {
617
+ const tabId = drivenTabId(host, op);
618
+ if (tabId && host.getTabInfo(tabId))
619
+ getBrowserDriverState().recordInput(tabId, 'agent');
620
+ }
621
+ catch (err) {
622
+ console.error(`[Internal] /browser/op: ${op.method} succeeded but its driver-state mark failed: ${err instanceof Error ? err.message : String(err)}`);
623
+ }
624
+ }
625
+ function leaseOwnerFor(identity, leasedUntil) {
626
+ return {
627
+ ownerAgentId: identity.agentId,
628
+ ownerAgentLabel: identity.agentLabel ?? identity.agentId,
629
+ ...(identity.planId ? { planId: identity.planId } : {}),
630
+ leasedUntil,
631
+ ...(identity.agentSessionId ? { ownerSessionId: identity.agentSessionId } : {}),
632
+ };
633
+ }
634
+ function broadcastLeaseRoster(ctx, host, identity) {
635
+ return broadcastAgentTabState(host, ctx, identity.agentId, identity.agentLabel ?? identity.agentId, identity.agentSessionId ? { sessionId: identity.agentSessionId } : {});
636
+ }
637
+ async function refreshHeldOwners(host, identity, stillLeased) {
638
+ if (stillLeased.length === 0)
639
+ return;
640
+ const held = new Set(stillLeased);
641
+ for (const lease of await host.listLeases({ agentId: identity.agentId })) {
642
+ if (held.has(lease.tabId)) {
643
+ getBrowserDriverState().setOwner(lease.tabId, leaseOwnerFor(identity, lease.leasedUntil));
644
+ }
645
+ }
646
+ }
647
+ function isLoopbackAddress(address) {
648
+ if (!address)
649
+ return false;
650
+ if (address === '::1')
651
+ return true;
652
+ const v4 = address.startsWith('::ffff:') ? address.slice('::ffff:'.length) : address;
653
+ return /^127\./.test(v4);
654
+ }
655
+ function remoteAddressOf(c) {
656
+ try {
657
+ return getConnInfo(c).remote.address;
658
+ }
659
+ catch {
660
+ return undefined;
661
+ }
662
+ }
663
+ function requireLoopback() {
664
+ return async (c, next) => {
665
+ if (!isLoopbackAddress(remoteAddressOf(c))) {
666
+ return c.json({ error: 'Forbidden' }, 403);
667
+ }
668
+ await next();
669
+ };
670
+ }
671
+ function requireChildCapability() {
672
+ return async (c, next) => {
673
+ if (!isValidBouncerSecret(c.req.header('x-minionry-bouncer-secret'))) {
674
+ return c.json({ error: 'Forbidden' }, 403);
675
+ }
676
+ if (!resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER))) {
677
+ console.error(`[Internal] ${c.req.path}: refused — no live capability token (absent, unknown, revoked or expired)`);
678
+ return c.json({ error: 'Forbidden' }, 403);
679
+ }
680
+ await next();
681
+ };
682
+ }
683
+ const DECISION_CACHE_MAX_ENTRIES = 1000;
684
+ const DECISION_CACHE_MAX_TTL_MS = 60 * 60 * 1000;
685
+ const decisionCache = new Map();
686
+ function decisionCacheKey(capability, key) {
687
+ return `${capability.spaceDir}\0${capability.tabId ?? ''}\0${key}`;
688
+ }
689
+ export function _resetDecisionCacheForTests() {
690
+ decisionCache.clear();
691
+ }
692
+ function parseVerdict(value) {
693
+ if (!value || typeof value !== 'object' || Array.isArray(value))
694
+ return null;
695
+ const verdict = value;
696
+ if (!['allow', 'warn_allow', 'deny'].includes(String(verdict.decision)))
697
+ return null;
698
+ if (typeof verdict.confidence !== 'number' || !Number.isFinite(verdict.confidence))
699
+ return null;
700
+ return verdict;
701
+ }
702
+ function parseDecisionCachePut(body) {
703
+ if (!body || typeof body !== 'object')
704
+ return null;
705
+ const { key, decision, ttlMs } = body;
706
+ if (typeof key !== 'string' || key.length === 0)
707
+ return null;
708
+ const verdict = parseVerdict(decision);
709
+ if (!verdict)
710
+ return null;
711
+ const requested = typeof ttlMs === 'number' && Number.isFinite(ttlMs) ? ttlMs : DECISION_CACHE_MAX_TTL_MS;
712
+ return { key, decision: verdict, ttlMs: Math.max(0, Math.min(requested, DECISION_CACHE_MAX_TTL_MS)) };
713
+ }
714
+ export function createInternalRoutes(ctx) {
715
+ const app = new Hono();
716
+ app.use('*', requireLoopback());
717
+ app.use('*', requireChildCapability());
718
+ app.get('/bouncer/decision-cache', (c) => {
719
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
720
+ if (!capability) {
721
+ return c.json({ error: 'Forbidden' }, 403);
722
+ }
723
+ const key = c.req.query('key');
724
+ if (!key) {
725
+ return c.json({ error: 'key is required' }, 400);
726
+ }
727
+ const namespaced = decisionCacheKey(capability, key);
728
+ const entry = decisionCache.get(namespaced);
729
+ if (!entry) {
730
+ return c.json({ decision: null });
731
+ }
732
+ if (entry.expiresAt <= Date.now()) {
733
+ decisionCache.delete(namespaced);
734
+ return c.json({ decision: null });
735
+ }
736
+ return c.json({ decision: entry.decision });
737
+ });
738
+ app.put('/bouncer/decision-cache', async (c) => {
739
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
740
+ if (!capability) {
741
+ return c.json({ error: 'Forbidden' }, 403);
742
+ }
743
+ let body;
744
+ try {
745
+ body = await c.req.json();
746
+ }
747
+ catch {
748
+ return c.json({ error: 'Invalid JSON' }, 400);
749
+ }
750
+ const parsed = parseDecisionCachePut(body);
751
+ if (!parsed) {
752
+ return c.json({ error: 'key and a well-formed decision are required' }, 400);
753
+ }
754
+ const namespaced = decisionCacheKey(capability, parsed.key);
755
+ decisionCache.delete(namespaced);
756
+ if (decisionCache.size >= DECISION_CACHE_MAX_ENTRIES) {
757
+ const oldest = decisionCache.keys().next().value;
758
+ if (oldest !== undefined)
759
+ decisionCache.delete(oldest);
760
+ }
761
+ decisionCache.set(namespaced, { decision: parsed.decision, expiresAt: Date.now() + parsed.ttlMs });
762
+ return c.json({ ok: true });
763
+ });
764
+ app.post('/ask-user-question', async (c) => {
765
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
766
+ if (!capability) {
767
+ return c.json({ error: 'Forbidden' }, 403);
768
+ }
769
+ let body;
770
+ try {
771
+ body = (await c.req.json());
772
+ }
773
+ catch {
774
+ return c.json({ error: 'Invalid JSON' }, 400);
775
+ }
776
+ const parsed = parseAskUserQuestionBody(body);
777
+ if (!parsed) {
778
+ return c.json({ error: 'toolUseId, tabId, and non-empty questions[] are required' }, 400);
779
+ }
780
+ if (!capability.tabId || parsed.tabId !== capability.tabId) {
781
+ logContradiction('/ask-user-question', 'tabId', parsed.tabId, capability.tabId);
782
+ return c.json({ error: 'Forbidden' }, 403);
783
+ }
784
+ const { status, body: responseBody } = await resolveAskUserQuestion(ctx, {
785
+ ...parsed,
786
+ tabId: capability.tabId,
787
+ });
788
+ return c.json(responseBody, status);
789
+ });
790
+ app.post('/app-tools/list', async (c) => {
791
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
792
+ if (!capability) {
793
+ return c.json({ error: 'Forbidden' }, 403);
794
+ }
795
+ let body;
796
+ try {
797
+ body = (await c.req.json());
798
+ }
799
+ catch {
800
+ return c.json({ error: 'Invalid JSON' }, 400);
801
+ }
802
+ const resolved = appToolsContextFrom(capability, body, '/app-tools/list');
803
+ if (!resolved.ok) {
804
+ return c.json({ error: 'Forbidden' }, 403);
805
+ }
806
+ return c.json({ tools: listExposedAppTools(resolved.ctx) });
807
+ });
808
+ app.post('/app-tools/call', async (c) => {
809
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
810
+ if (!capability) {
811
+ return c.json({ error: 'Forbidden' }, 403);
812
+ }
813
+ let body;
814
+ try {
815
+ body = (await c.req.json());
816
+ }
817
+ catch {
818
+ return c.json({ error: 'Invalid JSON' }, 400);
819
+ }
820
+ const resolved = appToolsContextFrom(capability, body, '/app-tools/call');
821
+ if (!resolved.ok) {
822
+ return c.json({ error: 'Forbidden' }, 403);
823
+ }
824
+ const name = typeof body.name === 'string' ? body.name : '';
825
+ if (!name) {
826
+ return c.json({ error: 'name is required' }, 400);
827
+ }
828
+ const input = typeof body.input === 'object' && body.input !== null && !Array.isArray(body.input)
829
+ ? body.input
830
+ : {};
831
+ return c.json(await invokeExposedAppTool({ ctx: resolved.ctx, name, input }));
832
+ });
833
+ app.post('/quality/check', async (c) => {
834
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
835
+ if (!capability) {
836
+ return c.json({ error: 'Forbidden' }, 403);
837
+ }
838
+ let body;
839
+ try {
840
+ body = (await c.req.json());
841
+ }
842
+ catch {
843
+ return c.json({ error: 'Invalid JSON' }, 400);
844
+ }
845
+ const resolved = qualityContextFrom(capability, body, '/quality/check');
846
+ if (!resolved.ok) {
847
+ return c.json({ error: 'Forbidden' }, 403);
848
+ }
849
+ const parsed = parseQualityCheckPaths(body);
850
+ if (!parsed.ok) {
851
+ return c.json(parsed);
852
+ }
853
+ return c.json(await runQualityCheck({ spaceRoot: resolved.spaceRoot, paths: parsed.paths, sessionKey: resolved.sessionKey }));
854
+ });
855
+ app.post('/browser/op', async (c) => {
856
+ const capability = resolveMcpCapability(c.req.header(CAPABILITY_TOKEN_HEADER));
857
+ if (!capability) {
858
+ return c.json({ error: 'Forbidden' }, 403);
859
+ }
860
+ let body;
861
+ try {
862
+ body = (await c.req.json());
863
+ }
864
+ catch {
865
+ return c.json({ error: 'Invalid JSON' }, 400);
866
+ }
867
+ if (!body || typeof body.method !== 'string') {
868
+ return c.json({ error: { code: 'invalid_params', message: 'method is required' } }, 400);
869
+ }
870
+ const resolved = browserIdentityFrom(capability, body, '/browser/op');
871
+ if (!resolved.ok) {
872
+ return c.json({ error: 'Forbidden' }, 403);
873
+ }
874
+ const host = ctx.getBrowserHost();
875
+ if (!host) {
876
+ return c.json({
877
+ error: {
878
+ code: 'browser_host_unavailable',
879
+ message: 'BrowserHost is not attached to this CLI server',
880
+ },
881
+ }, 503);
882
+ }
883
+ const bound = bindBrowserOp(body, resolved.identity);
884
+ const refusal = arbitrationRefusal(host, bound);
885
+ if (refusal) {
886
+ return c.json(refusal, 409);
887
+ }
888
+ try {
889
+ const result = await dispatchBrowserOp(host, bound);
890
+ reflectAgentDriving(host, bound);
891
+ await reflectBrowserLeaseOp(ctx, host, bound, result, resolved.identity);
892
+ return c.json({ result });
893
+ }
894
+ catch (err) {
895
+ const { body: errBody, status } = toErrorBody(err);
896
+ return c.json(errBody, status);
897
+ }
898
+ });
899
+ return app;
900
+ }