@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,400 @@
1
+
2
+ import { exec } from 'node:child_process';
3
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { arch, hostname, type } from 'node:os';
5
+ import { launchFlagSuffix } from '../launch-env.js';
6
+ import { resolveClientId, rotateClientId } from '../machine-identity.js';
7
+ import { ensureMachineDir, machineFile } from '../machine-layout.js';
8
+ import { resolvePlatformUrl } from '../platform-endpoints.js';
9
+
10
+ const colors = {
11
+ reset: '\x1b[0m',
12
+ bold: '\x1b[1m',
13
+ green: '\x1b[32m',
14
+ yellow: '\x1b[33m',
15
+ blue: '\x1b[34m',
16
+ red: '\x1b[31m',
17
+ dim: '\x1b[2m',
18
+ cyan: '\x1b[36m',
19
+ };
20
+
21
+ function log(msg, color = '') {
22
+ console.log(`${color}${msg}${colors.reset}`);
23
+ }
24
+
25
+ function accountLabel(email) {
26
+ if (!email) return '';
27
+ const at = email.lastIndexOf('@');
28
+ if (at <= 0) return email;
29
+ return email.slice(at + 1).toLowerCase().startsWith('no-email.') ? email.slice(0, at) : email;
30
+ }
31
+
32
+ function applyAppOriginOverride(url) {
33
+ const override = process.env.APP_ORIGIN;
34
+ if (!override) return url;
35
+ try {
36
+ const target = new URL(url);
37
+ const base = new URL(override);
38
+ target.protocol = base.protocol;
39
+ target.host = base.host;
40
+ return target.toString();
41
+ } catch {
42
+ return url;
43
+ }
44
+ }
45
+
46
+ function credentialsFile() {
47
+ const env = process.env.MINIONRY_ENV || 'production';
48
+ return machineFile(env === 'dev' ? 'platformCredentialsDev' : 'platformCredentials');
49
+ }
50
+
51
+ function resolveIdentity() {
52
+ const outcome = resolveClientId();
53
+ if (outcome.rotated) {
54
+ announceRebind();
55
+ }
56
+ return { clientId: outcome.clientId, fingerprint: outcome.fingerprint };
57
+ }
58
+
59
+ function announceRebind() {
60
+ log('');
61
+ log(' This home directory was last used on a different machine.', colors.yellow);
62
+ log(' Registering as a new device so the original keeps its Space.', colors.dim);
63
+ log('');
64
+ }
65
+
66
+ async function loadE2eeIdentityModule() {
67
+ try {
68
+ return await import('../../dist/server/services/e2ee-identity.js');
69
+ } catch {
70
+ try {
71
+ const tsx = await import('tsx/esm/api');
72
+ return await tsx.tsImport('../../server/services/e2ee-identity.ts', import.meta.url);
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+ }
78
+
79
+ async function prepareE2eeIdentity() {
80
+ try {
81
+ const mod = await loadE2eeIdentityModule();
82
+ if (!mod?.ensureE2eeIdentity) return null;
83
+ const status = await mod.ensureE2eeIdentity();
84
+ const key = status?.publicKey;
85
+ return typeof key === 'string' && /^[A-Za-z0-9_-]{43}$/.test(key) ? key : null;
86
+ } catch {
87
+ return null;
88
+ }
89
+ }
90
+
91
+ function isLoggedIn() {
92
+ if (!existsSync(credentialsFile())) {
93
+ return false;
94
+ }
95
+
96
+ try {
97
+ const creds = JSON.parse(readFileSync(credentialsFile(), 'utf-8'));
98
+ return !!(creds.token && creds.userId && creds.email);
99
+ } catch {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ function getCredentials() {
105
+ if (!existsSync(credentialsFile())) {
106
+ return null;
107
+ }
108
+ try {
109
+ return JSON.parse(readFileSync(credentialsFile(), 'utf-8'));
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+
115
+ function saveCredentials(creds) {
116
+ ensureMachineDir('credentials');
117
+ writeFileSync(credentialsFile(), JSON.stringify(creds, null, 2), { mode: 0o600 });
118
+ }
119
+
120
+ function openBrowser(url) {
121
+ let parsed;
122
+ try {
123
+ parsed = new URL(url);
124
+ } catch {
125
+ log(`\n Invalid URL received. Please open this URL manually:`, colors.yellow);
126
+ log(` ${url}\n`, colors.cyan);
127
+ return;
128
+ }
129
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
130
+ log(`\n Unexpected URL protocol. Please open this URL manually:`, colors.yellow);
131
+ log(` ${url}\n`, colors.cyan);
132
+ return;
133
+ }
134
+
135
+ const platform = process.platform;
136
+ let cmd;
137
+
138
+ if (platform === 'darwin') {
139
+ cmd = `open "${parsed.href}"`;
140
+ } else if (platform === 'win32') {
141
+ cmd = `start "" "${parsed.href}"`;
142
+ } else {
143
+ cmd = `xdg-open "${parsed.href}"`;
144
+ }
145
+
146
+ exec(cmd, (err) => {
147
+ if (err) {
148
+ log(`\n Could not open browser automatically.`, colors.yellow);
149
+ log(` Please open this URL manually:`, colors.dim);
150
+ log(` ${url}\n`, colors.cyan);
151
+ }
152
+ });
153
+ }
154
+
155
+
156
+ const SLOW_DOWN_STEP_SECONDS = 5;
157
+
158
+ const MAX_POLL_INTERVAL_SECONDS = 60;
159
+
160
+ const DEFAULT_AUTH_EXPIRY_SECONDS = 900;
161
+
162
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
163
+
164
+ function jitteredMs(seconds) {
165
+ return seconds * 1000 * (0.9 + Math.random() * 0.2);
166
+ }
167
+
168
+ function retryAfterSeconds(response, fallbackSeconds) {
169
+ const parsed = Number.parseInt(response.headers.get('retry-after') ?? '', 10);
170
+ const seconds = Number.isFinite(parsed) && parsed > 0 ? parsed : fallbackSeconds;
171
+ return Math.min(seconds, MAX_POLL_INTERVAL_SECONDS);
172
+ }
173
+
174
+ async function requestDeviceCode(clientId, platformUrl, force = false, e2eePublicKey = null, machineFingerprint = null) {
175
+ const machineHostname = hostname();
176
+ const osType = type().toLowerCase();
177
+ const cpuArch = arch();
178
+ const nodeVersion = process.version;
179
+
180
+ const response = await fetch(`${platformUrl}/api/auth/device/request`, {
181
+ method: 'POST',
182
+ headers: { 'Content-Type': 'application/json' },
183
+ body: JSON.stringify({
184
+ clientId,
185
+ machineHostname,
186
+ osType,
187
+ cpuArch,
188
+ nodeVersion,
189
+ ...(force ? { force: true } : {}),
190
+ ...(e2eePublicKey ? { e2eePublicKey } : {}),
191
+ ...(machineFingerprint ? { machineFingerprint } : {}),
192
+ }),
193
+ });
194
+
195
+ const text = await response.text();
196
+ let data;
197
+ try {
198
+ data = JSON.parse(text);
199
+ } catch (_e) {
200
+ throw new Error(`Server returned invalid JSON (status ${response.status}): ${text.slice(0, 200)}`);
201
+ }
202
+
203
+ if (response.status === 429) {
204
+ const wait = retryAfterSeconds(response, Number(data.retryAfterSeconds) || SLOW_DOWN_STEP_SECONDS);
205
+ throw new Error(`Too many device logins from this network right now. Try again in ${wait}s.`);
206
+ }
207
+
208
+ if (!response.ok) {
209
+ throw new Error(data.error || data.message || 'Failed to request device code');
210
+ }
211
+
212
+ return data;
213
+ }
214
+
215
+ async function pollOnce(platformUrl, deviceCode) {
216
+ let response;
217
+ try {
218
+ response = await fetch(`${platformUrl}/api/auth/device/poll`, {
219
+ method: 'POST',
220
+ headers: { 'Content-Type': 'application/json' },
221
+ body: JSON.stringify({ deviceCode }),
222
+ });
223
+ } catch {
224
+ return null;
225
+ }
226
+
227
+ const text = await response.text();
228
+ try {
229
+ return { response, data: JSON.parse(text) };
230
+ } catch (_e) {
231
+ throw new Error(`Server returned invalid JSON (status ${response.status}): ${text.slice(0, 200)}`);
232
+ }
233
+ }
234
+
235
+ export async function pollForAuth(deviceCode, interval, platformUrl, expiresInSeconds) {
236
+ let intervalSeconds = interval || SLOW_DOWN_STEP_SECONDS;
237
+ const deadline = Date.now() + (expiresInSeconds || DEFAULT_AUTH_EXPIRY_SECONDS) * 1000;
238
+
239
+ while (Date.now() < deadline) {
240
+ await sleep(jitteredMs(intervalSeconds));
241
+
242
+ const result = await pollOnce(platformUrl, deviceCode);
243
+ if (!result) {
244
+ process.stdout.write('x');
245
+ continue;
246
+ }
247
+
248
+ const { response, data } = result;
249
+ if (response.ok) {
250
+ return data;
251
+ }
252
+
253
+ if (response.status === 429) {
254
+ intervalSeconds = retryAfterSeconds(response, intervalSeconds + SLOW_DOWN_STEP_SECONDS);
255
+ process.stdout.write('~');
256
+ continue;
257
+ }
258
+
259
+ switch (data.error) {
260
+ case 'authorization_pending':
261
+ process.stdout.write('.');
262
+ break;
263
+
264
+ case 'slow_down':
265
+ intervalSeconds = Math.min(intervalSeconds + SLOW_DOWN_STEP_SECONDS, MAX_POLL_INTERVAL_SECONDS);
266
+ process.stdout.write('.');
267
+ break;
268
+
269
+ case 'expired_token':
270
+ throw new Error('Authorization request expired. Please try again.');
271
+
272
+ case 'access_denied':
273
+ throw new Error('Authorization denied by user.');
274
+
275
+ default:
276
+ throw new Error(data.error || 'Unknown error during authorization');
277
+ }
278
+ }
279
+
280
+ throw new Error('Authorization timed out. Please try again.');
281
+ }
282
+
283
+ async function deregisterOldDevice(platformUrl) {
284
+ const existingCreds = getCredentials();
285
+ if (!existingCreds?.token) return;
286
+ try {
287
+ await fetch(`${platformUrl}/api/auth/device/deregister`, {
288
+ method: 'POST',
289
+ headers: {
290
+ 'Content-Type': 'application/json',
291
+ 'Authorization': `Bearer ${existingCreds.token}`,
292
+ },
293
+ });
294
+ } catch {
295
+ }
296
+ }
297
+
298
+ async function runDeviceCodeFlow(identity, platformUrl, forceReauth, e2eePublicKey) {
299
+ const { clientId, fingerprint } = identity;
300
+ const { deviceCode, userCode, verificationUrlComplete, interval, expiresIn } = await requestDeviceCode(clientId, platformUrl, forceReauth, e2eePublicKey, fingerprint);
301
+
302
+ const verifyUrl = applyAppOriginOverride(verificationUrlComplete);
303
+
304
+ log(`Your authorization code: ${userCode}`, colors.bold);
305
+ log('');
306
+ log('Opening browser to complete login...', colors.dim);
307
+ log(` If browser doesn't open, visit: ${verifyUrl}`, colors.dim);
308
+ log('');
309
+
310
+ openBrowser(verifyUrl);
311
+
312
+ log(' Waiting for authorization', colors.dim);
313
+ process.stdout.write(' ');
314
+
315
+ const result = await pollForAuth(deviceCode, interval, platformUrl, expiresIn);
316
+
317
+ const credentials = {
318
+ token: result.accessToken,
319
+ userId: result.user.id,
320
+ email: result.user.email,
321
+ name: result.user.name,
322
+ clientId,
323
+ createdAt: new Date().toISOString(),
324
+ };
325
+
326
+ saveCredentials(credentials);
327
+ return result;
328
+ }
329
+
330
+ async function runDeviceCodeFlowWithRecovery(identity, platformUrl, forceReauth, e2eePublicKey) {
331
+ try {
332
+ return await runDeviceCodeFlow(identity, platformUrl, forceReauth, e2eePublicKey);
333
+ } catch (err) {
334
+ if (/client_id_conflict/i.test(err.message)) {
335
+ announceRebind();
336
+ return runDeviceCodeFlow(rotateIdentity(), platformUrl, false, e2eePublicKey);
337
+ }
338
+ if (forceReauth || !/already registered/i.test(err.message)) {
339
+ throw err;
340
+ }
341
+ log(' This machine was already registered — re-authenticating...', colors.dim);
342
+ await deregisterOldDevice(platformUrl);
343
+ return runDeviceCodeFlow(identity, platformUrl, true, e2eePublicKey);
344
+ }
345
+ }
346
+
347
+ function rotateIdentity() {
348
+ const outcome = rotateClientId();
349
+ return { clientId: outcome.clientId, fingerprint: outcome.fingerprint };
350
+ }
351
+
352
+ export async function login(args = [], options = {}) {
353
+ const { inline = false } = options;
354
+ const forceReauth = args.includes('--force') || args.includes('-f');
355
+ const env = process.env.MINIONRY_ENV || 'production';
356
+ const platformUrl = resolvePlatformUrl();
357
+ const envSuffix = launchFlagSuffix(env);
358
+
359
+ if (env !== 'production') {
360
+ log(`[${env.toUpperCase()}] Using ${platformUrl}${process.env.APP_ORIGIN ? ` (web app ${process.env.APP_ORIGIN})` : ''}\n`, colors.yellow);
361
+ }
362
+
363
+ if (!inline && isLoggedIn() && !forceReauth) {
364
+ const creds = getCredentials();
365
+ log(` Already logged in as ${accountLabel(creds.email)}`, colors.green);
366
+ log(` Use "minion logout${envSuffix}" to sign out, or "minion login${envSuffix} --force" to re-authenticate.\n`, colors.dim);
367
+ return false;
368
+ }
369
+
370
+ const identity = resolveIdentity();
371
+
372
+ const e2eePublicKey = await prepareE2eeIdentity();
373
+
374
+ if (forceReauth) {
375
+ await deregisterOldDevice(platformUrl);
376
+ }
377
+
378
+ log('Requesting authorization...', colors.dim);
379
+
380
+ try {
381
+ const result = await runDeviceCodeFlowWithRecovery(identity, platformUrl, forceReauth, e2eePublicKey);
382
+
383
+ log('');
384
+ log('');
385
+ log(` Logged in as ${accountLabel(result.user.email)}`, colors.bold + colors.green);
386
+ log('');
387
+
388
+ return true;
389
+ } catch (err) {
390
+ if (inline) {
391
+ throw err;
392
+ }
393
+ log('');
394
+ log(` Login failed: ${err.message}`, colors.red);
395
+ log('');
396
+ process.exit(1);
397
+ }
398
+ }
399
+
400
+ export default login;
@@ -0,0 +1,93 @@
1
+
2
+ import { existsSync, readFileSync, unlinkSync } from 'node:fs';
3
+ import { APP_NAME } from '../branding.js';
4
+ import { launchFlagSuffix } from '../launch-env.js';
5
+ import { machineFile } from '../machine-layout.js';
6
+ import { resolvePlatformUrl } from '../platform-endpoints.js';
7
+
8
+ const colors = {
9
+ reset: '\x1b[0m',
10
+ bold: '\x1b[1m',
11
+ green: '\x1b[32m',
12
+ yellow: '\x1b[33m',
13
+ red: '\x1b[31m',
14
+ dim: '\x1b[2m',
15
+ cyan: '\x1b[36m',
16
+ };
17
+
18
+ function log(msg, color = '') {
19
+ console.log(`${color}${msg}${colors.reset}`);
20
+ }
21
+
22
+ function credentialsFile() {
23
+ const env = process.env.MINIONRY_ENV || 'production';
24
+ return machineFile(env === 'dev' ? 'platformCredentialsDev' : 'platformCredentials');
25
+ }
26
+
27
+ function getCredentials() {
28
+ if (!existsSync(credentialsFile())) {
29
+ return null;
30
+ }
31
+ try {
32
+ return JSON.parse(readFileSync(credentialsFile(), 'utf-8'));
33
+ } catch {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ async function deregisterDevice(token, platformUrl) {
39
+ try {
40
+ const response = await fetch(`${platformUrl}/api/auth/device/deregister`, {
41
+ method: 'POST',
42
+ headers: {
43
+ 'Content-Type': 'application/json',
44
+ 'Authorization': `Bearer ${token}`,
45
+ },
46
+ });
47
+
48
+ if (!response.ok) {
49
+ const data = await response.json().catch(() => ({}));
50
+ log(` Warning: Could not deregister device from server: ${data.error || response.statusText}`, colors.yellow);
51
+ }
52
+ } catch {
53
+ log(' Warning: Could not reach server to deregister device. Local credentials will still be removed.', colors.yellow);
54
+ }
55
+ }
56
+
57
+ export async function logout() {
58
+ const platformUrl = resolvePlatformUrl();
59
+ const envSuffix = launchFlagSuffix(process.env.MINIONRY_ENV);
60
+
61
+ log(`\n ${APP_NAME} Logout\n`, colors.bold + colors.cyan);
62
+
63
+ const creds = getCredentials();
64
+
65
+ if (!creds) {
66
+ log(' Not currently logged in.', colors.yellow);
67
+ log(` Use "minion login${envSuffix}" to sign in.\n`, colors.dim);
68
+ return;
69
+ }
70
+
71
+ const email = creds.email;
72
+
73
+ try {
74
+ if (creds.token) {
75
+ await deregisterDevice(creds.token, platformUrl);
76
+ }
77
+
78
+ if (existsSync(credentialsFile())) {
79
+ unlinkSync(credentialsFile());
80
+ }
81
+
82
+ log(` Logged out from ${email}`, colors.green);
83
+ log('');
84
+ log(' Your device credentials have been removed.', colors.dim);
85
+ log(` Use "minion login${envSuffix}" to sign in again.\n`, colors.dim);
86
+ } catch (err) {
87
+ log(` Failed to logout: ${err.message}`, colors.red);
88
+ log('');
89
+ process.exit(1);
90
+ }
91
+ }
92
+
93
+ export default logout;
@@ -0,0 +1,211 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+
4
+
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { machineFile, machineRoot } from '../machine-layout.js';
8
+
9
+ const colors = {
10
+ reset: '\x1b[0m',
11
+ bold: '\x1b[1m',
12
+ green: '\x1b[32m',
13
+ yellow: '\x1b[33m',
14
+ red: '\x1b[31m',
15
+ dim: '\x1b[2m',
16
+ cyan: '\x1b[36m',
17
+ };
18
+
19
+ function log(msg, color = '') {
20
+ console.log(`${color}${msg}${colors.reset}`);
21
+ }
22
+
23
+ function readRegistry(registryPath) {
24
+ if (!existsSync(registryPath)) return [];
25
+ try {
26
+ const parsed = JSON.parse(readFileSync(registryPath, 'utf-8'));
27
+ return Array.isArray(parsed) ? parsed : [];
28
+ } catch {
29
+ return [];
30
+ }
31
+ }
32
+
33
+ export function mergeInstanceRows(legacy, current) {
34
+ const byPid = new Map();
35
+ for (const instance of [...legacy, ...current]) {
36
+ if (instance && typeof instance.pid === 'number') byPid.set(instance.pid, instance);
37
+ }
38
+ return [...byPid.values()];
39
+ }
40
+
41
+ function loadInstances() {
42
+ const current = readRegistry(machineFile('instances'));
43
+ const legacy = readRegistry(join(machineRoot(), 'instances.json'));
44
+ return mergeInstanceRows(legacy, current);
45
+ }
46
+
47
+ export function isPidAlive(pid) {
48
+ if (!Number.isInteger(pid) || pid <= 0) return false;
49
+ try {
50
+ process.kill(pid, 0);
51
+ return true;
52
+ } catch (err) {
53
+ return err.code === 'EPERM';
54
+ }
55
+ }
56
+
57
+ export function describeMinions(instances = loadInstances()) {
58
+ return instances
59
+ .map((instance) => ({
60
+ pid: instance.pid,
61
+ port: instance.port,
62
+ environment: instance.environment ?? 'production',
63
+ workingDirectory: instance.workingDirectory ?? '',
64
+ alive: isPidAlive(instance.pid),
65
+ }))
66
+ .sort((a, b) => a.port - b.port);
67
+ }
68
+
69
+ function printNoMinions() {
70
+ log('\n No minion servers registered on this machine.\n', colors.bold);
71
+ log(' Start one:', colors.bold);
72
+ log(' minion', colors.cyan);
73
+ log('');
74
+ }
75
+
76
+ export function listMinions() {
77
+ const rows = describeMinions();
78
+ if (rows.length === 0) {
79
+ printNoMinions();
80
+ return;
81
+ }
82
+
83
+ const headers = ['PID', 'PORT', 'ENVIRONMENT', 'STATUS', 'SPACE'];
84
+ const cells = rows.map((row) => [
85
+ String(row.pid),
86
+ String(row.port),
87
+ row.environment,
88
+ row.alive ? 'running' : 'stale',
89
+ row.workingDirectory,
90
+ ]);
91
+ const widths = headers.map((header, i) => Math.max(header.length, ...cells.map((row) => row[i].length)));
92
+ const line = (row, color = '') =>
93
+ ` ${row.map((cell, i) => `${color}${i === row.length - 1 ? cell : cell.padEnd(widths[i])}${colors.reset}`).join(' ')}`;
94
+
95
+ log('');
96
+ console.log(line(headers, colors.dim));
97
+ for (const row of cells) console.log(line(row));
98
+ log('');
99
+
100
+ const live = rows.filter((row) => row.alive);
101
+ if (live.length > 0) {
102
+ log(' Stop one:', colors.bold);
103
+ log(` minion shutdown ${live[0].pid}`, colors.cyan);
104
+ log('');
105
+ log(' Stop all:', colors.bold);
106
+ log(' minion shutdown all', colors.cyan);
107
+ log('');
108
+ }
109
+
110
+ const stale = rows.length - live.length;
111
+ if (stale > 0) {
112
+ log(` ${stale} row${stale === 1 ? '' : 's'} left behind by a server that died without deregistering.`, colors.dim);
113
+ log(' They hold no port and the next server start clears them.\n', colors.dim);
114
+ }
115
+ }
116
+
117
+ function stopMinion(row) {
118
+ if (!isPidAlive(row.pid)) return 'gone';
119
+ try {
120
+ process.kill(row.pid, 'SIGTERM');
121
+ return 'stopped';
122
+ } catch (err) {
123
+ if (err.code === 'ESRCH') return 'gone';
124
+ if (err.code === 'EPERM') return 'denied';
125
+ throw err;
126
+ }
127
+ }
128
+
129
+ function reportDenied(count) {
130
+ log(` ${count} belong${count === 1 ? 's' : ''} to another user — rerun with sudo to stop ${count === 1 ? 'it' : 'them'}.`, colors.dim);
131
+ }
132
+
133
+ function shutdownAllMinions() {
134
+ const rows = describeMinions();
135
+ const live = rows.filter((row) => row.alive);
136
+ if (live.length === 0) {
137
+ log('\n No minion servers running on this machine.\n', colors.bold);
138
+ return;
139
+ }
140
+
141
+ log('');
142
+ let stopped = 0;
143
+ let denied = 0;
144
+ for (const row of live) {
145
+ const result = stopMinion(row);
146
+ if (result === 'stopped') {
147
+ stopped += 1;
148
+ log(` Stopped ${row.pid} on port ${row.port} (${row.workingDirectory})`, colors.green);
149
+ } else if (result === 'denied') {
150
+ denied += 1;
151
+ log(` Could not stop ${row.pid} on port ${row.port} — permission denied`, colors.red);
152
+ } else {
153
+ log(` ${row.pid} was already gone`, colors.dim);
154
+ }
155
+ }
156
+
157
+ log('');
158
+ log(` Stopped ${stopped} minion server${stopped === 1 ? '' : 's'}.`, colors.bold);
159
+ if (denied > 0) reportDenied(denied);
160
+ log('');
161
+ if (denied > 0) process.exit(1);
162
+ }
163
+
164
+ function printShutdownUsage() {
165
+ log('\n Usage: minion shutdown <pid>', colors.dim);
166
+ log(' minion shutdown all\n', colors.dim);
167
+ log(' Stops a minion server running on this machine. `minion list minions`', colors.dim);
168
+ log(' shows the pids.\n', colors.dim);
169
+ }
170
+
171
+ export function shutdownMinion(args = []) {
172
+ const target = args.find((a) => !a.startsWith('-'));
173
+ if (!target) {
174
+ printShutdownUsage();
175
+ process.exit(1);
176
+ }
177
+
178
+ if (target === 'all') {
179
+ shutdownAllMinions();
180
+ return;
181
+ }
182
+
183
+ const pid = Number(target);
184
+ if (!Number.isInteger(pid) || pid <= 0) {
185
+ log(`\n "${target}" is not a pid.`, colors.red);
186
+ printShutdownUsage();
187
+ process.exit(1);
188
+ }
189
+
190
+ const row = describeMinions().find((candidate) => candidate.pid === pid);
191
+ if (!row) {
192
+ log(`\n No minion server on this machine is registered with pid ${pid}.\n`, colors.red);
193
+ log(' See what is running:', colors.bold);
194
+ log(' minion list minions', colors.cyan);
195
+ log('');
196
+ process.exit(1);
197
+ }
198
+
199
+ const result = stopMinion(row);
200
+ if (result === 'stopped') {
201
+ log(`\n Stopped minion ${pid} on port ${row.port} (${row.workingDirectory}).\n`, colors.green);
202
+ return;
203
+ }
204
+ if (result === 'denied') {
205
+ log(`\n Could not stop ${pid} — permission denied.`, colors.red);
206
+ reportDenied(1);
207
+ log('');
208
+ process.exit(1);
209
+ }
210
+ log(`\n Minion ${pid} was already gone; its registry row is stale.\n`, colors.dim);
211
+ }