@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,86 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { logAppAudit } from './audit.js';
4
+ import { removeAppEndpoints } from './endpoints.js';
5
+ import { clearAllSessionGrants, clearSessionGrants, removeGrant, removeSessionGrantsForApp, } from './grant-store.js';
6
+ import { deregisterLiveSubscription, getLiveRunsForApp, getLiveSubscriptionsForApp, getLiveSubscriptionsForViewer, listLiveSubscriptions, } from './live-registry.js';
7
+ import { SdkMethodError } from './registry.js';
8
+ import { isValidAppId } from './sandbox.js';
9
+ import { dropSdkStream, dropSdkStreamsForApp } from './streams.js';
10
+ export function dropSubscription(sub, auditMethod, cause) {
11
+ deregisterLiveSubscription(sub.requestId);
12
+ dropSdkStream(sub.requestId);
13
+ try {
14
+ sub.teardown();
15
+ }
16
+ catch (error) {
17
+ console.error(`[SdkRevoke] teardown of ${sub.kind} subscription '${sub.requestId}' threw:`, error);
18
+ }
19
+ logAppAudit({
20
+ appId: sub.appId,
21
+ origin: sub.origin,
22
+ method: auditMethod,
23
+ decision: 'allow',
24
+ requestId: sub.requestId,
25
+ spaceKey: sub.spaceKey,
26
+ reason: `dropped ${sub.kind} subscription (${cause})`,
27
+ });
28
+ }
29
+ export function revokeAppGrantsInSpace(appId, spaceKey, notify) {
30
+ const removedPersisted = removeGrant(appId, spaceKey);
31
+ const removedSessionGrants = removeSessionGrantsForApp(appId, spaceKey);
32
+ const runs = getLiveRunsForApp(appId, spaceKey);
33
+ for (const run of runs) {
34
+ try {
35
+ run.cancel();
36
+ }
37
+ catch (error) {
38
+ console.error(`[SdkRevoke] cancel of run '${run.runId}' threw:`, error);
39
+ }
40
+ logAppAudit({
41
+ appId: run.appId,
42
+ origin: run.origin,
43
+ method: 'grants.revoke.runCancelled',
44
+ decision: 'allow',
45
+ requestId: run.requestId,
46
+ spaceKey: run.spaceKey,
47
+ reason: `cancelled run ${run.runId} in tab ${run.tabId} (grant revoked)`,
48
+ });
49
+ }
50
+ const subscriptions = getLiveSubscriptionsForApp(appId, spaceKey);
51
+ for (const sub of subscriptions) {
52
+ dropSubscription(sub, 'grants.revoke.subscriptionDropped', 'grant revoked');
53
+ }
54
+ dropSdkStreamsForApp(appId, spaceKey);
55
+ try {
56
+ removeAppEndpoints(appId, spaceKey, 'grant revoked');
57
+ }
58
+ catch (error) {
59
+ console.error(`[SdkRevoke] removing '${appId}' endpoints threw:`, error instanceof Error ? error.message : error);
60
+ }
61
+ notify?.({ type: 'sdkGrantsChanged', data: { appId, grants: [] }, broadcast: true });
62
+ return {
63
+ revoked: removedPersisted || removedSessionGrants > 0,
64
+ cancelledRuns: runs.length,
65
+ droppedSubscriptions: subscriptions.length,
66
+ };
67
+ }
68
+ export function revokeGrantsHandler(args) {
69
+ const { appId, spaceKey } = args;
70
+ if (!isValidAppId(appId)) {
71
+ throw new SdkMethodError('BAD_REQUEST', `invalid appId '${appId}' — expected the D5 grammar (lowercase [a-z0-9-])`);
72
+ }
73
+ return revokeAppGrantsInSpace(appId, spaceKey, args.notify);
74
+ }
75
+ export function teardownSdkForViewer(viewerId) {
76
+ clearSessionGrants(viewerId);
77
+ for (const sub of getLiveSubscriptionsForViewer(viewerId)) {
78
+ dropSubscription(sub, 'session.end.subscriptionDropped', 'viewer session ended');
79
+ }
80
+ }
81
+ export function teardownSdkOnTransportClose() {
82
+ clearAllSessionGrants();
83
+ for (const sub of listLiveSubscriptions()) {
84
+ dropSubscription(sub, 'session.end.subscriptionDropped', 'transport closed');
85
+ }
86
+ }
@@ -0,0 +1,41 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { isScope } from '@minionry/app-manifest';
4
+ import { spacePath } from '../space-layout.js';
5
+ import { isValidAppId } from './sandbox.js';
6
+ export const WORKSPACE_READ_TOOLS = ['Read', 'Grep', 'Glob', 'LS', 'NotebookRead'];
7
+ export const WORKSPACE_WRITE_TOOLS = ['Write', 'Edit', 'MultiEdit', 'NotebookEdit'];
8
+ export const WORKSPACE_SHELL_TOOLS = ['Bash', 'BashOutput', 'KillBash', 'KillShell'];
9
+ export const WORKSPACE_NOTE_OPEN = '--- Minionry host note ---';
10
+ export const WORKSPACE_NOTE_CLOSE = '--- End host note ---';
11
+ export function buildWorkspaceNote(workingDir) {
12
+ return [
13
+ WORKSPACE_NOTE_OPEN,
14
+ `This session was started by a Workshop app. The Space root is: ${workingDir}`,
15
+ `A path written \`workspace:/<path>\` means \`${workingDir}/<path>\`.`,
16
+ 'Your working directory is the app\'s sandbox, not the Space root — relative paths resolve inside the sandbox, so address Space files by their absolute path.',
17
+ WORKSPACE_NOTE_CLOSE,
18
+ ].join('\n');
19
+ }
20
+ export function deriveRunProfile(input) {
21
+ if (!isValidAppId(input.appId)) {
22
+ throw new Error(`Cannot derive a run profile for invalid appId '${input.appId}' (fail closed)`);
23
+ }
24
+ const scopes = input.grantScopes.filter(isScope);
25
+ const workspaceWrite = scopes.includes('files:workspace:write');
26
+ const workspaceRead = workspaceWrite || scopes.includes('files:workspace:read');
27
+ return {
28
+ appId: input.appId,
29
+ origin: input.origin,
30
+ scopes,
31
+ cwd: spacePath(input.workingDir, 'apps', input.appId, 'data'),
32
+ disallowedTools: [
33
+ ...(workspaceRead ? [] : WORKSPACE_READ_TOOLS),
34
+ ...(workspaceWrite ? [] : [...WORKSPACE_WRITE_TOOLS, ...WORKSPACE_SHELL_TOOLS]),
35
+ ],
36
+ ...(workspaceRead ? { workspaceNote: buildWorkspaceNote(input.workingDir) } : {}),
37
+ };
38
+ }
39
+ export function profileAllowsBrowserControl(profile) {
40
+ return profile.scopes.includes('browser:control');
41
+ }
@@ -0,0 +1,89 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { lstatSync, mkdirSync, realpathSync, writeFileSync } from 'node:fs';
4
+ import { basename, dirname, isAbsolute, join, resolve, sep } from 'node:path';
5
+ import { spacePath } from '../space-layout.js';
6
+ const APP_ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
7
+ export function isValidAppId(appId) {
8
+ return typeof appId === 'string' && APP_ID_PATTERN.test(appId);
9
+ }
10
+ function lexists(path) {
11
+ try {
12
+ lstatSync(path);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ function assertNotSymlink(path) {
20
+ let stat;
21
+ try {
22
+ stat = lstatSync(path);
23
+ }
24
+ catch {
25
+ return;
26
+ }
27
+ if (stat.isSymbolicLink()) {
28
+ throw new Error(`Refusing to provision app sandbox through a symlink: ${path}`);
29
+ }
30
+ }
31
+ export function getAppSandboxPaths(workingDir, appId) {
32
+ if (!isValidAppId(appId)) {
33
+ throw new Error(`Invalid appId '${appId}' — expected the D5 grammar (lowercase [a-z0-9-])`);
34
+ }
35
+ const realWorkingDir = realpathSync(resolve(workingDir));
36
+ const root = spacePath(realWorkingDir, 'apps', appId);
37
+ return { root, dataDir: join(root, 'data'), kvFile: join(root, 'kv.json') };
38
+ }
39
+ export function provisionAppSandbox(workingDir, appId) {
40
+ const paths = getAppSandboxPaths(workingDir, appId);
41
+ const { root, dataDir, kvFile } = paths;
42
+ const appsDir = dirname(root);
43
+ const minionryDir = dirname(appsDir);
44
+ for (const component of [minionryDir, appsDir, root, dataDir, kvFile]) {
45
+ assertNotSymlink(component);
46
+ }
47
+ mkdirSync(dataDir, { recursive: true, mode: 0o700 });
48
+ if (!lexists(kvFile)) {
49
+ try {
50
+ writeFileSync(kvFile, '{}\n', { mode: 0o600, flag: 'wx' });
51
+ }
52
+ catch (err) {
53
+ if (err.code !== 'EEXIST')
54
+ throw err;
55
+ }
56
+ }
57
+ return paths;
58
+ }
59
+ export function resolveWithinRoot(root, targetPath, opts) {
60
+ try {
61
+ const realRoot = realpathSync(resolve(root));
62
+ const resolved = isAbsolute(targetPath) ? resolve(targetPath) : resolve(realRoot, targetPath);
63
+ let probe = resolved;
64
+ const remainder = [];
65
+ while (!lexists(probe)) {
66
+ const parent = dirname(probe);
67
+ if (parent === probe)
68
+ break;
69
+ remainder.unshift(basename(probe));
70
+ probe = parent;
71
+ }
72
+ const realProbe = realpathSync(probe);
73
+ const realResolved = remainder.length > 0 ? join(realProbe, ...remainder) : realProbe;
74
+ if (realResolved !== realRoot && !realResolved.startsWith(realRoot + sep)) {
75
+ if (!opts?.quiet) {
76
+ console.error(`[Sandbox] SECURITY: path escape blocked. Target: "${targetPath}", Resolved: "${realResolved}", Root: "${realRoot}"`);
77
+ }
78
+ return { valid: false, resolvedPath: '', error: 'Access denied: path is outside the app sandbox' };
79
+ }
80
+ return { valid: true, resolvedPath: realResolved };
81
+ }
82
+ catch (error) {
83
+ return {
84
+ valid: false,
85
+ resolvedPath: '',
86
+ error: `Invalid path: ${error instanceof Error ? error.message : String(error)}`,
87
+ };
88
+ }
89
+ }
@@ -0,0 +1,110 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
4
+ import { SdkMethodError } from './registry.js';
5
+ import { getAppSandboxPaths, provisionAppSandbox } from './sandbox.js';
6
+ export const STORAGE_MAX_BYTES = 1024 * 1024;
7
+ export const STORAGE_MAX_KEY_CHARS = 256;
8
+ function paramsObject(params) {
9
+ return typeof params === 'object' && params !== null && !Array.isArray(params)
10
+ ? params
11
+ : {};
12
+ }
13
+ function parseKeyParam(params, method) {
14
+ const raw = paramsObject(params);
15
+ if (typeof raw.key !== 'string' || raw.key === '') {
16
+ throw new SdkMethodError('BAD_REQUEST', `${method} requires params { key } — a non-empty string`);
17
+ }
18
+ if (raw.key.length > STORAGE_MAX_KEY_CHARS) {
19
+ throw new SdkMethodError('BAD_REQUEST', `storage key is ${raw.key.length} chars — exceeds the ${STORAGE_MAX_KEY_CHARS}-char key cap`);
20
+ }
21
+ return raw.key;
22
+ }
23
+ function appKvFile(args) {
24
+ try {
25
+ return provisionAppSandbox(args.workingDir, args.appId).kvFile;
26
+ }
27
+ catch (error) {
28
+ throw new SdkMethodError('INTERNAL', `app sandbox unavailable: ${error instanceof Error ? error.message : String(error)}`);
29
+ }
30
+ }
31
+ function loadStore(kvFile) {
32
+ let content;
33
+ try {
34
+ content = readFileSync(kvFile, 'utf-8');
35
+ }
36
+ catch {
37
+ return Object.create(null);
38
+ }
39
+ try {
40
+ const parsed = JSON.parse(content);
41
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
42
+ return Object.assign(Object.create(null), parsed);
43
+ }
44
+ console.warn(`[SdkStorage] ${kvFile} does not hold a JSON object — treating the store as empty`);
45
+ }
46
+ catch (error) {
47
+ console.warn(`[SdkStorage] ${kvFile} is not valid JSON — treating the store as empty:`, error instanceof Error ? error.message : String(error));
48
+ }
49
+ return Object.create(null);
50
+ }
51
+ function flushStore(kvFile, serialized) {
52
+ const tempFile = `${kvFile}.tmp`;
53
+ try {
54
+ rmSync(tempFile, { force: true });
55
+ writeFileSync(tempFile, `${serialized}\n`, { mode: 0o600, flag: 'wx' });
56
+ renameSync(tempFile, kvFile);
57
+ }
58
+ catch (error) {
59
+ throw new SdkMethodError('INTERNAL', `failed to persist the storage store: ${error instanceof Error ? error.message : String(error)}`);
60
+ }
61
+ }
62
+ function assertJsonSerializable(value, method) {
63
+ let serialized;
64
+ try {
65
+ serialized = JSON.stringify(value);
66
+ }
67
+ catch (error) {
68
+ throw new SdkMethodError('BAD_REQUEST', `${method} value is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`);
69
+ }
70
+ if (serialized === undefined) {
71
+ throw new SdkMethodError('BAD_REQUEST', `${method} value is not JSON-serializable — undefined, functions, and symbols have no JSON form`);
72
+ }
73
+ }
74
+ export function storageGetHandler(args) {
75
+ const key = parseKeyParam(args.params, args.method);
76
+ const value = loadStore(appKvFile(args))[key];
77
+ return value === undefined ? null : value;
78
+ }
79
+ export function storageKeysHandler(args) {
80
+ return Object.keys(loadStore(appKvFile(args)));
81
+ }
82
+ export function storageSetHandler(args) {
83
+ const key = parseKeyParam(args.params, args.method);
84
+ const value = paramsObject(args.params).value;
85
+ assertJsonSerializable(value, args.method);
86
+ const kvFile = appKvFile(args);
87
+ const store = loadStore(kvFile);
88
+ store[key] = value;
89
+ const serialized = JSON.stringify(store);
90
+ const bytes = Buffer.byteLength(serialized, 'utf-8');
91
+ if (bytes > STORAGE_MAX_BYTES) {
92
+ throw new SdkMethodError('QUOTA_EXCEEDED', `serialized store would be ${bytes} bytes — exceeds the ${STORAGE_MAX_BYTES}-byte per-app storage quota`);
93
+ }
94
+ flushStore(kvFile, serialized);
95
+ return null;
96
+ }
97
+ export function storageDeleteHandler(args) {
98
+ const key = parseKeyParam(args.params, args.method);
99
+ const kvFile = appKvFile(args);
100
+ const store = loadStore(kvFile);
101
+ if (!Object.hasOwn(store, key))
102
+ return null;
103
+ delete store[key];
104
+ flushStore(kvFile, JSON.stringify(store));
105
+ return null;
106
+ }
107
+ export function deleteAppStorage(workingDir, appId) {
108
+ const { kvFile } = getAppSandboxPaths(workingDir, appId);
109
+ rmSync(kvFile, { force: true });
110
+ }
@@ -0,0 +1,147 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { SeqEventBuffer } from '../websocket/tab-event-buffer.js';
4
+ import { planSeqReplay } from '../websocket/tab-event-replay.js';
5
+ import { listLiveRuns, listLiveSubscriptions } from './live-registry.js';
6
+ import { SdkMethodError } from './registry.js';
7
+ export const SDK_STREAM_MAX_EVENTS = 1_000;
8
+ export const SDK_STREAM_MAX_AGE_MS = 10 * 60 * 1000;
9
+ export const SDK_STREAM_MAX_BYTES = 1024 * 1024;
10
+ export const SDK_STREAM_MAX_STREAMS = 256;
11
+ export const SDK_STREAM_MAX_TOTAL_BYTES = 32 * 1024 * 1024;
12
+ export const PTY_STREAM_KINDS = new Set(['terminal.attach']);
13
+ const windows = new Map();
14
+ let totalBytes = 0;
15
+ let evictedStreams = 0;
16
+ const newWindowBuffer = () => new SeqEventBuffer(SDK_STREAM_MAX_EVENTS, SDK_STREAM_MAX_AGE_MS, Date.now, SDK_STREAM_MAX_BYTES);
17
+ const newPtyWindowBuffer = () => new SeqEventBuffer(0, 0, Date.now, 0);
18
+ function touch(window) {
19
+ windows.delete(window.requestId);
20
+ windows.set(window.requestId, window);
21
+ }
22
+ function forget(requestId) {
23
+ const window = windows.get(requestId);
24
+ if (!window)
25
+ return false;
26
+ windows.delete(requestId);
27
+ totalBytes -= window.bytes;
28
+ if (totalBytes < 0)
29
+ totalBytes = 0;
30
+ return true;
31
+ }
32
+ function enforceGlobalBudget() {
33
+ while (windows.size > SDK_STREAM_MAX_STREAMS || (totalBytes > SDK_STREAM_MAX_TOTAL_BYTES && windows.size > 0)) {
34
+ const oldest = windows.keys().next();
35
+ if (oldest.done)
36
+ break;
37
+ forget(oldest.value);
38
+ evictedStreams += 1;
39
+ }
40
+ }
41
+ export function recordSdkStreamEvent(identity, event, payload) {
42
+ let window = windows.get(identity.requestId);
43
+ if (!window) {
44
+ const buffer = PTY_STREAM_KINDS.has(identity.kind) ? newPtyWindowBuffer() : newWindowBuffer();
45
+ window = { ...identity, buffer, bytes: 0 };
46
+ windows.set(identity.requestId, window);
47
+ }
48
+ else {
49
+ touch(window);
50
+ }
51
+ const seq = window.buffer.record(event, payload);
52
+ const bytes = window.buffer.byteSize();
53
+ totalBytes += bytes - window.bytes;
54
+ window.bytes = bytes;
55
+ enforceGlobalBudget();
56
+ return seq;
57
+ }
58
+ export function dropSdkStream(requestId) {
59
+ return forget(requestId);
60
+ }
61
+ export function dropSdkStreamsForApp(appId, spaceKey) {
62
+ let dropped = 0;
63
+ for (const window of [...windows.values()]) {
64
+ if (window.appId === appId && window.spaceKey === spaceKey && forget(window.requestId))
65
+ dropped += 1;
66
+ }
67
+ return dropped;
68
+ }
69
+ export function getSdkStreamBudget() {
70
+ let events = 0;
71
+ for (const window of windows.values())
72
+ events += window.buffer.size();
73
+ return {
74
+ streams: windows.size,
75
+ events,
76
+ bytes: totalBytes,
77
+ maxStreams: SDK_STREAM_MAX_STREAMS,
78
+ maxBytes: SDK_STREAM_MAX_TOTAL_BYTES,
79
+ evictedStreams,
80
+ };
81
+ }
82
+ export function resetSdkStreams() {
83
+ windows.clear();
84
+ totalBytes = 0;
85
+ evictedStreams = 0;
86
+ }
87
+ function parseResumeParams(params) {
88
+ if (typeof params !== 'object' || params === null || Array.isArray(params)) {
89
+ throw new SdkMethodError('BAD_REQUEST', 'stream.resume requires params { requestId, afterSeq? } naming the stream to resume');
90
+ }
91
+ const raw = params;
92
+ if (typeof raw.requestId !== 'string' || raw.requestId === '') {
93
+ throw new SdkMethodError('BAD_REQUEST', 'stream.resume requires a non-empty string requestId — the id of the envelope that opened the stream');
94
+ }
95
+ if (raw.afterSeq !== undefined && (typeof raw.afterSeq !== 'number' || !Number.isInteger(raw.afterSeq) || raw.afterSeq < 0)) {
96
+ throw new SdkMethodError('BAD_REQUEST', 'stream.resume afterSeq must be a non-negative integer when present');
97
+ }
98
+ return { requestId: raw.requestId, afterSeq: raw.afterSeq ?? 0 };
99
+ }
100
+ function hasLiveStream(requestId, appId, spaceKey) {
101
+ const owned = (work) => work.requestId === requestId && work.appId === appId && work.spaceKey === spaceKey;
102
+ return (listLiveRuns().some(owned) ||
103
+ listLiveSubscriptions().some((sub) => owned(sub) && !PTY_STREAM_KINDS.has(sub.kind)));
104
+ }
105
+ function streamGap(requestId, afterSeq, detail, recovery = 'Reconcile with a snapshot read (agents.result / pm.getBoard) — the buffered window is bounded by design.') {
106
+ return new SdkMethodError('STREAM_GAP', `stream '${requestId}' cannot be resumed from seq ${afterSeq}: ${detail}. ${recovery}`);
107
+ }
108
+ export function resumeSdkStream(args) {
109
+ const { requestId, appId, spaceKey, afterSeq } = args;
110
+ const window = windows.get(requestId);
111
+ if (!window) {
112
+ if (hasLiveStream(requestId, appId, spaceKey)) {
113
+ return { requestId, fromSeq: afterSeq, events: [], currentSeq: 0 };
114
+ }
115
+ throw streamGap(requestId, afterSeq, 'no buffered window is held for it');
116
+ }
117
+ if (window.appId !== appId || window.spaceKey !== spaceKey) {
118
+ throw streamGap(requestId, afterSeq, 'no buffered window is held for it');
119
+ }
120
+ if (PTY_STREAM_KINDS.has(window.kind)) {
121
+ throw streamGap(requestId, afterSeq, 'pty streams keep no replay window', 'Re-attach to replay the tail from the terminal scrollback — resume is never supported on a pty stream.');
122
+ }
123
+ touch(window);
124
+ const plan = planSeqReplay(window.buffer, afterSeq);
125
+ const bytes = window.buffer.byteSize();
126
+ totalBytes += bytes - window.bytes;
127
+ window.bytes = bytes;
128
+ if (plan.kind === 'gap') {
129
+ throw streamGap(requestId, afterSeq, `events (${afterSeq + 1}..${plan.evictedThroughSeq}) have been evicted from the ` +
130
+ `bounded window (max ${SDK_STREAM_MAX_EVENTS} events / ${SDK_STREAM_MAX_AGE_MS / 60_000} min / ` +
131
+ `${SDK_STREAM_MAX_BYTES} bytes per stream)`);
132
+ }
133
+ return {
134
+ requestId,
135
+ fromSeq: afterSeq,
136
+ events: plan.events.map((buffered) => ({
137
+ seq: buffered.seq,
138
+ event: buffered.type,
139
+ ...(buffered.data !== undefined ? { payload: buffered.data } : {}),
140
+ })),
141
+ currentSeq: window.buffer.currentSeq(),
142
+ };
143
+ }
144
+ export function sdkStreamResumeHandler(args) {
145
+ const { requestId, afterSeq } = parseResumeParams(args.params);
146
+ return resumeSdkStream({ requestId, appId: args.appId, spaceKey: args.spaceKey, afterSeq });
147
+ }
@@ -0,0 +1,201 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { getGrant } from './grant-store.js';
4
+ import { deregisterLiveSubscription, listLiveSubscriptions, registerLiveSubscription } from './live-registry.js';
5
+ import { SdkMethodError } from './registry.js';
6
+ export const SDK_TERMINAL_ID_PREFIX = 'sdk-term-';
7
+ export function isSdkOpenedTerminalId(id) {
8
+ return id.startsWith(SDK_TERMINAL_ID_PREFIX);
9
+ }
10
+ let terminalHost = null;
11
+ export function setSdkTerminalHost(host) {
12
+ terminalHost = host;
13
+ }
14
+ export function resetSdkTerminalHost() {
15
+ terminalHost = null;
16
+ }
17
+ function requireHost(method) {
18
+ if (!terminalHost) {
19
+ throw new SdkMethodError('INTERNAL', `${method}: the terminal host is not wired — the WebSocket handler installs it at startup`);
20
+ }
21
+ return terminalHost;
22
+ }
23
+ function paramsObject(params) {
24
+ return typeof params === 'object' && params !== null && !Array.isArray(params)
25
+ ? params
26
+ : {};
27
+ }
28
+ function requireIdParam(raw, method) {
29
+ const value = raw.id;
30
+ if (typeof value !== 'string' || value === '') {
31
+ throw new SdkMethodError('BAD_REQUEST', `${method} requires params { id } — a non-empty string`);
32
+ }
33
+ return value;
34
+ }
35
+ function requireSizeParam(raw, name, method) {
36
+ const value = raw[name];
37
+ if (typeof value !== 'number' || !Number.isInteger(value) || value < 1 || value > 1000) {
38
+ throw new SdkMethodError('BAD_REQUEST', `${method}: ${name} must be an integer between 1 and 1000`);
39
+ }
40
+ return value;
41
+ }
42
+ function ptyUnavailable(host) {
43
+ return new SdkMethodError('PTY_NOT_AVAILABLE', host.installInstructions());
44
+ }
45
+ function normalizePtyError(error, host) {
46
+ const message = error instanceof Error ? error.message : String(error);
47
+ if (message.startsWith('PTY_NOT_AVAILABLE')) {
48
+ const instructions = message.slice('PTY_NOT_AVAILABLE'.length).replace(/^:/, '').trim();
49
+ throw new SdkMethodError('PTY_NOT_AVAILABLE', instructions || host.installInstructions());
50
+ }
51
+ throw error;
52
+ }
53
+ export function terminalSessionsListHandler(args) {
54
+ return requireHost(args.method).listSessions();
55
+ }
56
+ export function terminalSessionsSubscribeHandler(args) {
57
+ if (listLiveSubscriptions().some((sub) => sub.requestId === args.requestId)) {
58
+ throw new SdkMethodError('BAD_REQUEST', `requestId '${args.requestId}' already holds a live subscription`);
59
+ }
60
+ const host = requireHost(args.method);
61
+ let active = true;
62
+ const unsubscribe = host.subscribeSessions((change) => {
63
+ if (!active)
64
+ return;
65
+ args.emit('sessionChanged', change);
66
+ });
67
+ registerLiveSubscription({
68
+ requestId: args.requestId,
69
+ appId: args.appId,
70
+ origin: args.origin,
71
+ spaceKey: args.spaceKey,
72
+ kind: 'terminal.sessions.subscribe',
73
+ viewerId: getGrant(args.appId, args.spaceKey) ? undefined : args.viewerId,
74
+ teardown: () => {
75
+ active = false;
76
+ unsubscribe();
77
+ },
78
+ });
79
+ return { subscribed: true };
80
+ }
81
+ export function terminalAttachHandler(args) {
82
+ const host = requireHost(args.method);
83
+ const raw = paramsObject(args.params);
84
+ const id = requireIdParam(raw, args.method);
85
+ if (!host.isPtyAvailable())
86
+ throw ptyUnavailable(host);
87
+ if (!host.exists(id)) {
88
+ throw new SdkMethodError('BAD_REQUEST', `${args.method}: no terminal session '${id}' in this Space`);
89
+ }
90
+ if (listLiveSubscriptions().some((sub) => sub.requestId === args.requestId)) {
91
+ throw new SdkMethodError('BAD_REQUEST', `requestId '${args.requestId}' already holds a live subscription`);
92
+ }
93
+ let active = true;
94
+ const detach = host.attach(id, {
95
+ onOutput: (data) => {
96
+ if (active)
97
+ args.emit('output', { data });
98
+ },
99
+ onExit: (exitCode) => {
100
+ if (!active)
101
+ return;
102
+ args.emit('exit', { exitCode });
103
+ active = false;
104
+ detach();
105
+ deregisterLiveSubscription(args.requestId);
106
+ },
107
+ onError: (message) => {
108
+ if (active)
109
+ args.emit('error', { message });
110
+ },
111
+ });
112
+ registerLiveSubscription({
113
+ requestId: args.requestId,
114
+ appId: args.appId,
115
+ origin: args.origin,
116
+ spaceKey: args.spaceKey,
117
+ kind: 'terminal.attach',
118
+ viewerId: getGrant(args.appId, args.spaceKey) ? undefined : args.viewerId,
119
+ teardown: () => {
120
+ active = false;
121
+ detach();
122
+ },
123
+ });
124
+ args.emit('scrollback', { data: host.getScrollback(id) ?? '' });
125
+ return { id };
126
+ }
127
+ export async function terminalOpenHandler(args) {
128
+ const host = requireHost(args.method);
129
+ const raw = paramsObject(args.params);
130
+ const cols = requireSizeParam(raw, 'cols', args.method);
131
+ const rows = requireSizeParam(raw, 'rows', args.method);
132
+ const cwd = typeof raw.cwd === 'string' && raw.cwd !== '' ? raw.cwd : undefined;
133
+ if (listLiveSubscriptions().some((sub) => sub.requestId === args.requestId)) {
134
+ throw new SdkMethodError('BAD_REQUEST', `requestId '${args.requestId}' already holds a live subscription`);
135
+ }
136
+ if (!(await host.ensurePtyAvailable()))
137
+ throw ptyUnavailable(host);
138
+ try {
139
+ const opened = await host.open({ appId: args.appId, cwd, cols, rows, workingDir: args.workingDir });
140
+ const unsubscribeRoster = host.subscribeSessions((change) => {
141
+ if (change.kind === 'closed' && change.id === opened.id) {
142
+ unsubscribeRoster();
143
+ deregisterLiveSubscription(args.requestId);
144
+ }
145
+ });
146
+ registerLiveSubscription({
147
+ requestId: args.requestId,
148
+ appId: args.appId,
149
+ origin: args.origin,
150
+ spaceKey: args.spaceKey,
151
+ kind: 'terminal.open',
152
+ viewerId: getGrant(args.appId, args.spaceKey) ? undefined : args.viewerId,
153
+ teardown: () => {
154
+ unsubscribeRoster();
155
+ if (isSdkOpenedTerminalId(opened.id))
156
+ host.close(opened.id);
157
+ },
158
+ });
159
+ return opened;
160
+ }
161
+ catch (error) {
162
+ normalizePtyError(error, host);
163
+ }
164
+ }
165
+ export function terminalWriteHandler(args) {
166
+ const host = requireHost(args.method);
167
+ const raw = paramsObject(args.params);
168
+ const id = requireIdParam(raw, args.method);
169
+ const data = raw.data;
170
+ const isChunkArray = Array.isArray(data) && data.every((chunk) => typeof chunk === 'string');
171
+ if (typeof data !== 'string' && !isChunkArray) {
172
+ throw new SdkMethodError('BAD_REQUEST', `${args.method} requires params { id, data } — data a string or an array of strings`);
173
+ }
174
+ if (!host.exists(id)) {
175
+ throw new SdkMethodError('BAD_REQUEST', `${args.method}: no terminal session '${id}' in this Space`);
176
+ }
177
+ const input = typeof data === 'string' ? data : data.join('');
178
+ if (input !== '' && !host.write(id, input)) {
179
+ throw new SdkMethodError('INTERNAL', `${args.method}: write to terminal session '${id}' failed`);
180
+ }
181
+ return null;
182
+ }
183
+ export function terminalResizeHandler(args) {
184
+ const host = requireHost(args.method);
185
+ const raw = paramsObject(args.params);
186
+ const id = requireIdParam(raw, args.method);
187
+ const cols = requireSizeParam(raw, 'cols', args.method);
188
+ const rows = requireSizeParam(raw, 'rows', args.method);
189
+ if (!host.exists(id)) {
190
+ throw new SdkMethodError('BAD_REQUEST', `${args.method}: no terminal session '${id}' in this Space`);
191
+ }
192
+ host.resize(id, cols, rows);
193
+ return null;
194
+ }
195
+ export function terminalCloseHandler(args) {
196
+ const host = requireHost(args.method);
197
+ const raw = paramsObject(args.params);
198
+ const id = requireIdParam(raw, args.method);
199
+ host.close(id);
200
+ return null;
201
+ }