@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,328 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { existsSync, mkdirSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
4
+ import { readdir, stat } from 'node:fs/promises';
5
+ import { dirname, join, resolve, sep } from 'node:path';
6
+ import { containsDangerousPatterns, validateBothPathsWithinWorkingDir, validatePathWithinWorkingDir } from './pathUtils.js';
7
+ export const MAX_RESOLVE_TO = 200;
8
+ const STAT_CONCURRENCY = 32;
9
+ const RESOLVE_CONCURRENCY = 4;
10
+ const nameCollator = new Intl.Collator();
11
+ function validateListingTarget(dirPath, workingDir) {
12
+ if (containsDangerousPatterns(dirPath)) {
13
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${dirPath}"`);
14
+ return { ok: false, error: 'Invalid path: contains dangerous patterns' };
15
+ }
16
+ const validation = validatePathWithinWorkingDir(dirPath, workingDir);
17
+ if (!validation.valid) {
18
+ return { ok: false, error: validation.error ?? 'Access denied' };
19
+ }
20
+ return { ok: true, resolvedPath: validation.resolvedPath };
21
+ }
22
+ function workingDirRoots(workingDir) {
23
+ const raw = resolve(workingDir);
24
+ const roots = [raw];
25
+ try {
26
+ const real = realpathSync(raw);
27
+ if (real !== raw)
28
+ roots.push(real);
29
+ }
30
+ catch {
31
+ }
32
+ return roots;
33
+ }
34
+ function relativeToRoots(entryPath, roots) {
35
+ for (const root of roots) {
36
+ if (entryPath.startsWith(root + sep))
37
+ return entryPath.slice(root.length + 1);
38
+ }
39
+ return entryPath;
40
+ }
41
+ function toDirectoryEntry(name, isDir, stats, relativePath) {
42
+ const entry = { name, path: relativePath, type: isDir ? 'directory' : 'file' };
43
+ if (stats) {
44
+ entry.modifiedAt = stats.mtime.toISOString();
45
+ if (!isDir)
46
+ entry.size = stats.size;
47
+ }
48
+ return entry;
49
+ }
50
+ function compareDirectoryEntries(a, b) {
51
+ if (a.type !== b.type)
52
+ return a.type === 'directory' ? -1 : 1;
53
+ return nameCollator.compare(a.name, b.name);
54
+ }
55
+ function listingFailure(error) {
56
+ if (error instanceof Error && 'code' in error) {
57
+ const code = error.code;
58
+ if (code === 'EACCES' || code === 'EPERM')
59
+ return { success: false, error: 'Permission denied' };
60
+ if (code === 'ENOENT')
61
+ return { success: false, error: 'Directory not found' };
62
+ if (code === 'ENOTDIR')
63
+ return { success: false, error: 'Path is not a directory' };
64
+ }
65
+ console.error('[FileService] Error listing directory:', error);
66
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to list directory' };
67
+ }
68
+ async function mapWithConcurrency(items, limit, fn) {
69
+ const results = new Array(items.length);
70
+ let next = 0;
71
+ const worker = async () => {
72
+ while (next < items.length) {
73
+ const index = next++;
74
+ results[index] = await fn(items[index]);
75
+ }
76
+ };
77
+ const workers = Array.from({ length: Math.min(limit, items.length) }, worker);
78
+ await Promise.all(workers);
79
+ return results;
80
+ }
81
+ export function listDirectory(dirPath, workingDir, showHidden = false) {
82
+ const target = validateListingTarget(dirPath, workingDir);
83
+ if (!target.ok)
84
+ return { success: false, error: target.error };
85
+ const resolvedPath = target.resolvedPath;
86
+ try {
87
+ if (!existsSync(resolvedPath)) {
88
+ return { success: false, error: 'Directory not found' };
89
+ }
90
+ if (!statSync(resolvedPath).isDirectory()) {
91
+ return { success: false, error: 'Path is not a directory' };
92
+ }
93
+ const roots = workingDirRoots(workingDir);
94
+ const entries = readdirSync(resolvedPath, { withFileTypes: true })
95
+ .filter(entry => showHidden || !entry.name.startsWith('.'))
96
+ .map(entry => {
97
+ const entryPath = join(resolvedPath, entry.name);
98
+ let stats;
99
+ try {
100
+ stats = statSync(entryPath);
101
+ }
102
+ catch { }
103
+ const isDir = stats ? stats.isDirectory() : entry.isDirectory();
104
+ return toDirectoryEntry(entry.name, isDir, stats, relativeToRoots(entryPath, roots));
105
+ })
106
+ .sort(compareDirectoryEntries);
107
+ return { success: true, entries };
108
+ }
109
+ catch (error) {
110
+ return listingFailure(error);
111
+ }
112
+ }
113
+ export async function listDirectoryAsync(dirPath, workingDir, showHidden = false) {
114
+ const target = validateListingTarget(dirPath, workingDir);
115
+ if (!target.ok)
116
+ return { success: false, error: target.error };
117
+ const resolvedPath = target.resolvedPath;
118
+ try {
119
+ const dirStats = await stat(resolvedPath);
120
+ if (!dirStats.isDirectory()) {
121
+ return { success: false, error: 'Path is not a directory' };
122
+ }
123
+ const roots = workingDirRoots(workingDir);
124
+ const dirents = (await readdir(resolvedPath, { withFileTypes: true }))
125
+ .filter(entry => showHidden || !entry.name.startsWith('.'));
126
+ const entries = await mapWithConcurrency(dirents, STAT_CONCURRENCY, async (entry) => {
127
+ const entryPath = join(resolvedPath, entry.name);
128
+ let stats;
129
+ try {
130
+ stats = await stat(entryPath);
131
+ }
132
+ catch { }
133
+ const isDir = stats ? stats.isDirectory() : entry.isDirectory();
134
+ return toDirectoryEntry(entry.name, isDir, stats, relativeToRoots(entryPath, roots));
135
+ });
136
+ entries.sort(compareDirectoryEntries);
137
+ return { success: true, entries };
138
+ }
139
+ catch (error) {
140
+ return listingFailure(error);
141
+ }
142
+ }
143
+ function normalizeResolveTo(resolveTo, primaryPath) {
144
+ const unique = new Set();
145
+ for (const candidate of resolveTo) {
146
+ if (typeof candidate !== 'string' || candidate === primaryPath)
147
+ continue;
148
+ unique.add(candidate);
149
+ }
150
+ return [...unique]
151
+ .sort((a, b) => depthOf(a) - depthOf(b) || (a < b ? -1 : a > b ? 1 : 0))
152
+ .slice(0, MAX_RESOLVE_TO);
153
+ }
154
+ function depthOf(path) {
155
+ return path.split('/').filter(Boolean).length;
156
+ }
157
+ export async function resolveDirectoryListings(dirPath, resolveTo, workingDir, showHidden = false) {
158
+ const primary = await listDirectoryAsync(dirPath, workingDir, showHidden);
159
+ if (!primary.success)
160
+ return { primary, resolved: [] };
161
+ const targets = normalizeResolveTo(resolveTo, dirPath);
162
+ const resolved = await mapWithConcurrency(targets, RESOLVE_CONCURRENCY, async (path) => {
163
+ const result = await listDirectoryAsync(path, workingDir, showHidden);
164
+ return result.success ? { path, entries: result.entries } : { path, error: result.error };
165
+ });
166
+ return { primary, resolved };
167
+ }
168
+ export function validatePathWithinRoots(filePath, workingDir, extraRoots) {
169
+ const validation = validatePathWithinWorkingDir(filePath, workingDir);
170
+ if (validation.valid)
171
+ return validation;
172
+ for (const root of extraRoots) {
173
+ const alt = validatePathWithinWorkingDir(filePath, root);
174
+ if (alt.valid)
175
+ return alt;
176
+ }
177
+ return validation;
178
+ }
179
+ export function writeFile(filePath, content, workingDir, options) {
180
+ const encoding = options?.encoding;
181
+ if (containsDangerousPatterns(filePath)) {
182
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${filePath}"`);
183
+ return { success: false, error: 'Invalid path: contains dangerous patterns' };
184
+ }
185
+ const validation = validatePathWithinRoots(filePath, workingDir, options?.extraRoots ?? []);
186
+ if (!validation.valid) {
187
+ return { success: false, error: validation.error };
188
+ }
189
+ const resolvedPath = validation.resolvedPath;
190
+ try {
191
+ const parentDir = dirname(resolvedPath);
192
+ if (!existsSync(parentDir))
193
+ mkdirSync(parentDir, { recursive: true });
194
+ if (existsSync(resolvedPath)) {
195
+ const stats = statSync(resolvedPath);
196
+ if (stats.isDirectory()) {
197
+ return { success: false, error: 'Cannot write to a directory' };
198
+ }
199
+ }
200
+ if (encoding === 'base64') {
201
+ writeFileSync(resolvedPath, Buffer.from(content, 'base64'));
202
+ }
203
+ else {
204
+ writeFileSync(resolvedPath, content, 'utf-8');
205
+ }
206
+ return { success: true, path: resolvedPath.replace(`${workingDir}/`, '') };
207
+ }
208
+ catch (error) {
209
+ console.error('[FileService] Error writing file:', error);
210
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to write file' };
211
+ }
212
+ }
213
+ export function createFile(filePath, workingDir) {
214
+ if (containsDangerousPatterns(filePath)) {
215
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${filePath}"`);
216
+ return { success: false, error: 'Invalid path: contains dangerous patterns' };
217
+ }
218
+ const validation = validatePathWithinWorkingDir(filePath, workingDir);
219
+ if (!validation.valid) {
220
+ return { success: false, error: validation.error };
221
+ }
222
+ const resolvedPath = validation.resolvedPath;
223
+ try {
224
+ if (existsSync(resolvedPath)) {
225
+ return { success: false, error: 'File already exists' };
226
+ }
227
+ const parentDir = dirname(resolvedPath);
228
+ if (!existsSync(parentDir))
229
+ mkdirSync(parentDir, { recursive: true });
230
+ writeFileSync(resolvedPath, '', 'utf-8');
231
+ return { success: true, path: resolvedPath.replace(`${workingDir}/`, '') };
232
+ }
233
+ catch (error) {
234
+ console.error('[FileService] Error creating file:', error);
235
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to create file' };
236
+ }
237
+ }
238
+ export function createDirectory(dirPath, workingDir) {
239
+ if (containsDangerousPatterns(dirPath)) {
240
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${dirPath}"`);
241
+ return { success: false, error: 'Invalid path: contains dangerous patterns' };
242
+ }
243
+ const validation = validatePathWithinWorkingDir(dirPath, workingDir);
244
+ if (!validation.valid) {
245
+ return { success: false, error: validation.error };
246
+ }
247
+ const resolvedPath = validation.resolvedPath;
248
+ try {
249
+ if (existsSync(resolvedPath)) {
250
+ const stats = statSync(resolvedPath);
251
+ if (stats.isDirectory()) {
252
+ return { success: false, error: 'Directory already exists' };
253
+ }
254
+ return { success: false, error: 'A file with that name already exists' };
255
+ }
256
+ mkdirSync(resolvedPath, { recursive: true });
257
+ return { success: true, path: resolvedPath.replace(`${workingDir}/`, '') };
258
+ }
259
+ catch (error) {
260
+ console.error('[FileService] Error creating directory:', error);
261
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to create directory' };
262
+ }
263
+ }
264
+ export function deleteFile(targetPath, workingDir) {
265
+ if (containsDangerousPatterns(targetPath)) {
266
+ console.error(`[FileService] SECURITY: Dangerous pattern in path: "${targetPath}"`);
267
+ return { success: false, error: 'Invalid path: contains dangerous patterns' };
268
+ }
269
+ const validation = validatePathWithinWorkingDir(targetPath, workingDir);
270
+ if (!validation.valid) {
271
+ return { success: false, error: validation.error };
272
+ }
273
+ const resolvedPath = validation.resolvedPath;
274
+ if (resolvedPath === workingDir || resolvedPath === `${workingDir}/`) {
275
+ console.error(`[FileService] SECURITY: Attempted to delete working directory: "${resolvedPath}"`);
276
+ return { success: false, error: 'Cannot delete the working directory' };
277
+ }
278
+ try {
279
+ if (!existsSync(resolvedPath)) {
280
+ return { success: false, error: 'File or directory not found' };
281
+ }
282
+ const stats = statSync(resolvedPath);
283
+ if (stats.isDirectory()) {
284
+ rmSync(resolvedPath, { recursive: true });
285
+ }
286
+ else {
287
+ unlinkSync(resolvedPath);
288
+ }
289
+ return { success: true, path: resolvedPath.replace(`${workingDir}/`, '') };
290
+ }
291
+ catch (error) {
292
+ console.error('[FileService] Error deleting file:', error);
293
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to delete' };
294
+ }
295
+ }
296
+ export function renameFile(oldPath, newPath, workingDir) {
297
+ if (containsDangerousPatterns(oldPath)) {
298
+ console.error(`[FileService] SECURITY: Dangerous pattern in source path: "${oldPath}"`);
299
+ return { success: false, error: 'Invalid source path: contains dangerous patterns' };
300
+ }
301
+ if (containsDangerousPatterns(newPath)) {
302
+ console.error(`[FileService] SECURITY: Dangerous pattern in destination path: "${newPath}"`);
303
+ return { success: false, error: 'Invalid destination path: contains dangerous patterns' };
304
+ }
305
+ const validation = validateBothPathsWithinWorkingDir(oldPath, newPath, workingDir);
306
+ if (!validation.valid) {
307
+ return { success: false, error: validation.error };
308
+ }
309
+ const resolvedOldPath = validation.resolvedSourcePath;
310
+ const resolvedNewPath = validation.resolvedDestPath;
311
+ try {
312
+ if (!existsSync(resolvedOldPath)) {
313
+ return { success: false, error: 'Source file or directory not found' };
314
+ }
315
+ if (existsSync(resolvedNewPath)) {
316
+ return { success: false, error: 'Destination already exists' };
317
+ }
318
+ const parentDir = dirname(resolvedNewPath);
319
+ if (!existsSync(parentDir))
320
+ mkdirSync(parentDir, { recursive: true });
321
+ renameSync(resolvedOldPath, resolvedNewPath);
322
+ return { success: true, path: resolvedNewPath.replace(`${workingDir}/`, '') };
323
+ }
324
+ catch (error) {
325
+ console.error('[FileService] Error renaming file:', error);
326
+ return { success: false, error: error instanceof Error ? error.message : 'Failed to rename' };
327
+ }
328
+ }
@@ -0,0 +1,188 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { createReadStream, lstatSync, readdirSync, readFileSync, statSync } from 'node:fs';
4
+ import { dirname, join, relative, sep } from 'node:path';
5
+ import { Zip, ZipDeflate, zipSync } from 'fflate';
6
+ import { isIgnored, parseGitignore } from './websocket/file-utils.js';
7
+ const MAX_ZIP_ENTRIES = 20_000;
8
+ const MAX_ZIP_UNCOMPRESSED_BYTES = 50 * 1024 * 1024;
9
+ export const MAX_STREAMED_ZIP_UNCOMPRESSED_BYTES = 2 * 1024 * 1024 * 1024;
10
+ const STREAM_READ_CHUNK_BYTES = 192 * 1024;
11
+ export class ZipTooLargeError extends Error {
12
+ }
13
+ function addZipEntry(abs, rel, out, budget) {
14
+ budget.entries += 1;
15
+ if (budget.entries > MAX_ZIP_ENTRIES) {
16
+ throw new ZipTooLargeError(`directory has more than ${MAX_ZIP_ENTRIES} files — too large to download as a zip`);
17
+ }
18
+ const bytes = readFileSync(abs);
19
+ budget.bytes += bytes.byteLength;
20
+ if (budget.bytes > MAX_ZIP_UNCOMPRESSED_BYTES) {
21
+ throw new ZipTooLargeError(`directory contents exceed ${MAX_ZIP_UNCOMPRESSED_BYTES} bytes uncompressed — too large to download as a zip`);
22
+ }
23
+ out[rel] = bytes;
24
+ }
25
+ function shouldSkipEntry(entry, rel, gitignorePatterns) {
26
+ if (entry.isSymbolicLink())
27
+ return true;
28
+ if (entry.isDirectory() && entry.name === '.git')
29
+ return true;
30
+ return gitignorePatterns.length > 0 && isIgnored(rel, gitignorePatterns);
31
+ }
32
+ function collectZippableFiles(dir, baseDir, gitignorePatterns, out, budget) {
33
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
34
+ const abs = join(dir, entry.name);
35
+ const rel = relative(baseDir, abs);
36
+ if (shouldSkipEntry(entry, rel, gitignorePatterns))
37
+ continue;
38
+ if (entry.isDirectory()) {
39
+ collectZippableFiles(abs, baseDir, gitignorePatterns, out, budget);
40
+ }
41
+ else if (entry.isFile()) {
42
+ addZipEntry(abs, rel, out, budget);
43
+ }
44
+ }
45
+ }
46
+ export function buildDirectoryZipBuffer(dirPath, options = {}) {
47
+ const gitignorePatterns = parseGitignore(options.gitignoreRoot ?? dirPath);
48
+ const files = {};
49
+ collectZippableFiles(dirPath, dirPath, gitignorePatterns, files, { entries: 0, bytes: 0 });
50
+ return Buffer.from(zipSync(files, { level: 6 }));
51
+ }
52
+ async function runZipStream(roots, baseDir, gitignorePatterns, onChunk, isCancelled) {
53
+ const budget = { entries: 0, bytes: 0 };
54
+ let totalBytes = 0;
55
+ let pending = Promise.resolve();
56
+ let streamError = null;
57
+ const zip = new Zip((err, chunk, _final) => {
58
+ if (err) {
59
+ streamError = err instanceof Error ? err : new Error(String(err));
60
+ return;
61
+ }
62
+ if (chunk.length === 0)
63
+ return;
64
+ totalBytes += chunk.length;
65
+ pending = pending.then(() => onChunk(chunk));
66
+ });
67
+ const asView = (buf) => new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
68
+ async function pushFileChunks(abs, entry) {
69
+ let previous = null;
70
+ for await (const raw of createReadStream(abs, { highWaterMark: STREAM_READ_CHUNK_BYTES })) {
71
+ const chunk = raw;
72
+ if (previous) {
73
+ entry.push(asView(previous), false);
74
+ await pending;
75
+ if (streamError)
76
+ throw streamError;
77
+ }
78
+ previous = chunk;
79
+ }
80
+ entry.push(previous ? asView(previous) : new Uint8Array(0), true);
81
+ await pending;
82
+ if (streamError)
83
+ throw streamError;
84
+ }
85
+ async function addFile(abs, rel) {
86
+ budget.entries += 1;
87
+ if (budget.entries > MAX_ZIP_ENTRIES) {
88
+ throw new ZipTooLargeError(`directory has more than ${MAX_ZIP_ENTRIES} files — too large to download as a zip`);
89
+ }
90
+ const size = statSync(abs).size;
91
+ budget.bytes += size;
92
+ if (budget.bytes > MAX_STREAMED_ZIP_UNCOMPRESSED_BYTES) {
93
+ throw new ZipTooLargeError(`directory contents exceed ${MAX_STREAMED_ZIP_UNCOMPRESSED_BYTES} bytes uncompressed — too large to download as a zip`);
94
+ }
95
+ const entry = new ZipDeflate(rel, { level: 6 });
96
+ zip.add(entry);
97
+ if (size === 0) {
98
+ entry.push(new Uint8Array(0), true);
99
+ await pending;
100
+ if (streamError)
101
+ throw streamError;
102
+ return;
103
+ }
104
+ await pushFileChunks(abs, entry);
105
+ }
106
+ const stopped = () => isCancelled() || streamError !== null;
107
+ async function walk(dir) {
108
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
109
+ if (stopped())
110
+ return;
111
+ const abs = join(dir, entry.name);
112
+ const rel = relative(baseDir, abs);
113
+ if (shouldSkipEntry(entry, rel, gitignorePatterns))
114
+ continue;
115
+ if (entry.isDirectory())
116
+ await walk(abs);
117
+ else if (entry.isFile())
118
+ await addFile(abs, rel);
119
+ }
120
+ }
121
+ for (const root of roots) {
122
+ if (stopped())
123
+ break;
124
+ if (root.isDirectory) {
125
+ await walk(root.abs);
126
+ continue;
127
+ }
128
+ const rel = relative(baseDir, root.abs);
129
+ let lst;
130
+ try {
131
+ lst = lstatSync(root.abs);
132
+ }
133
+ catch {
134
+ continue;
135
+ }
136
+ if (lst.isSymbolicLink())
137
+ continue;
138
+ if (gitignorePatterns.length > 0 && isIgnored(rel, gitignorePatterns))
139
+ continue;
140
+ await addFile(root.abs, rel);
141
+ }
142
+ if (streamError)
143
+ throw streamError;
144
+ if (isCancelled())
145
+ return totalBytes;
146
+ zip.end();
147
+ await pending;
148
+ if (streamError)
149
+ throw streamError;
150
+ return totalBytes;
151
+ }
152
+ export async function streamDirectoryZip(dirPath, onChunk, options = {}) {
153
+ const gitignorePatterns = parseGitignore(options.gitignoreRoot ?? dirPath);
154
+ const isCancelled = options.isCancelled ?? (() => false);
155
+ return runZipStream([{ abs: dirPath, isDirectory: true }], dirPath, gitignorePatterns, onChunk, isCancelled);
156
+ }
157
+ function commonParentDir(absPaths) {
158
+ if (absPaths.length <= 1)
159
+ return dirname(absPaths[0] ?? sep);
160
+ const parts = absPaths.map((p) => p.split(sep));
161
+ const minLen = Math.min(...parts.map((p) => p.length));
162
+ let common = 0;
163
+ for (let i = 0; i < minLen - 1; i++) {
164
+ const segment = parts[0][i];
165
+ if (parts.every((p) => p[i] === segment))
166
+ common = i + 1;
167
+ else
168
+ break;
169
+ }
170
+ return common > 0 ? parts[0].slice(0, common).join(sep) : sep;
171
+ }
172
+ export async function streamPathsZip(absPaths, onChunk, options = {}) {
173
+ const baseDir = commonParentDir(absPaths);
174
+ const gitignorePatterns = parseGitignore(options.gitignoreRoot ?? baseDir);
175
+ const isCancelled = options.isCancelled ?? (() => false);
176
+ const roots = dedupeNestedRoots(absPaths).map((abs) => ({ abs, isDirectory: statSync(abs).isDirectory() }));
177
+ return runZipStream(roots, baseDir, gitignorePatterns, onChunk, isCancelled);
178
+ }
179
+ function dedupeNestedRoots(absPaths) {
180
+ const sorted = [...absPaths].sort((a, b) => a.length - b.length);
181
+ const kept = [];
182
+ for (const path of sorted) {
183
+ if (kept.some((ancestor) => path === ancestor || path.startsWith(ancestor + sep)))
184
+ continue;
185
+ kept.push(path);
186
+ }
187
+ return kept;
188
+ }
@@ -0,0 +1,111 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { readdirSync, statSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ export { createDirectory, createFile, deleteFile, listDirectory, listDirectoryAsync, renameFile, resolveDirectoryListings, writeFile, } from './file-explorer-ops.js';
6
+ export class FileService {
7
+ workingDirectory;
8
+ skipDirs = ['node_modules', '.git', '.minionry', 'dist', 'build', '.next', 'coverage', '.vscode', '.idea'];
9
+ constructor(workingDirectory) {
10
+ this.workingDirectory = workingDirectory;
11
+ }
12
+ getAllFiles(_baseDir = 'working', filter, limit = 10) {
13
+ const directory = this.workingDirectory;
14
+ let files = this.scanDirectory(directory, directory);
15
+ if (filter) {
16
+ files = this.filterAndScore(files, filter);
17
+ }
18
+ if (filter) {
19
+ files.sort((a, b) => (b.score || 0) - (a.score || 0));
20
+ }
21
+ else {
22
+ files.sort((a, b) => {
23
+ if (a.isDirectory && !b.isDirectory)
24
+ return -1;
25
+ if (!a.isDirectory && b.isDirectory)
26
+ return 1;
27
+ return a.name.localeCompare(b.name);
28
+ });
29
+ }
30
+ return files.slice(0, limit);
31
+ }
32
+ scanDirectory(dir, baseDir, results = []) {
33
+ try {
34
+ const dirName = dir.split('/').pop() || '';
35
+ if (this.skipDirs.includes(dirName)) {
36
+ return results;
37
+ }
38
+ const entries = readdirSync(dir, { withFileTypes: true });
39
+ for (const entry of entries) {
40
+ if (entry.name.startsWith('.') || this.skipDirs.includes(entry.name)) {
41
+ continue;
42
+ }
43
+ const fullPath = join(dir, entry.name);
44
+ const relativePath = fullPath.replace(`${baseDir}/`, '');
45
+ results.push({
46
+ name: entry.name,
47
+ path: relativePath,
48
+ isDirectory: entry.isDirectory()
49
+ });
50
+ if (results.length >= 1000) {
51
+ console.warn('[FilesService] Directory scan hit 1000-item limit — results may be incomplete');
52
+ return results;
53
+ }
54
+ if (entry.isDirectory()) {
55
+ this.scanDirectory(fullPath, baseDir, results);
56
+ }
57
+ }
58
+ }
59
+ catch (_error) {
60
+ }
61
+ return results;
62
+ }
63
+ filterAndScore(files, filter) {
64
+ const filterLower = filter.toLowerCase();
65
+ const scoredFiles = [];
66
+ for (const file of files) {
67
+ const nameLower = file.name.toLowerCase();
68
+ const pathLower = file.path.toLowerCase();
69
+ let score = 0;
70
+ if (nameLower.startsWith(filterLower)) {
71
+ score = 1000;
72
+ }
73
+ else if (pathLower.split('/').some(part => part.startsWith(filterLower))) {
74
+ score = 500;
75
+ }
76
+ else if (nameLower.includes(filterLower)) {
77
+ score = 100;
78
+ }
79
+ else if (pathLower.includes(filterLower)) {
80
+ score = 10;
81
+ }
82
+ else {
83
+ continue;
84
+ }
85
+ score += (50 - Math.min(50, file.path.split('/').length * 5));
86
+ scoredFiles.push({
87
+ name: file.name,
88
+ path: file.path,
89
+ isDirectory: file.isDirectory,
90
+ score
91
+ });
92
+ }
93
+ return scoredFiles;
94
+ }
95
+ getFileStats(path, _baseDir = 'working') {
96
+ try {
97
+ const fullPath = join(this.workingDirectory, path);
98
+ const stats = statSync(fullPath);
99
+ return {
100
+ size: stats.size,
101
+ created: stats.birthtime,
102
+ modified: stats.mtime,
103
+ isDirectory: stats.isDirectory(),
104
+ isFile: stats.isFile()
105
+ };
106
+ }
107
+ catch (_error) {
108
+ return null;
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,62 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { executeGitCommand } from './command.js';
4
+ import { BRANCH_LIST_FORMAT, findWorktreePathForBranch, parseBranchList } from './parsers.js';
5
+ import { gitFail, gitOk } from './types.js';
6
+ export async function listBranches({ cwd }) {
7
+ const result = await executeGitCommand(['branch', '-a', `--format=${BRANCH_LIST_FORMAT}`], cwd);
8
+ if (result.exitCode !== 0) {
9
+ return gitFail(result.stderr || 'Failed to list branches');
10
+ }
11
+ const currentBranchResult = await executeGitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);
12
+ const currentBranch = currentBranchResult.stdout.trim() || 'HEAD';
13
+ return gitOk({ branches: parseBranchList(result.stdout), current: currentBranch });
14
+ }
15
+ export async function findOtherWorktreeForBranch({ cwd, branch }) {
16
+ const wtListResult = await executeGitCommand(['worktree', 'list', '--porcelain'], cwd);
17
+ if (wtListResult.exitCode !== 0)
18
+ return null;
19
+ const existingWt = findWorktreePathForBranch(wtListResult.stdout, branch);
20
+ if (!existingWt || existingWt === cwd)
21
+ return null;
22
+ return existingWt;
23
+ }
24
+ export async function checkoutBranch({ cwd, branch, create, startPoint }) {
25
+ const statusResult = await executeGitCommand(['status', '--porcelain'], cwd);
26
+ if (statusResult.stdout.trim()) {
27
+ return gitFail('Commit or stash changes before switching branches');
28
+ }
29
+ const prevResult = await executeGitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);
30
+ const previous = prevResult.stdout.trim();
31
+ const args = create
32
+ ? ['checkout', '-b', branch, ...(startPoint ? [startPoint] : [])]
33
+ : ['checkout', branch];
34
+ const result = await executeGitCommand(args, cwd);
35
+ if (result.exitCode !== 0) {
36
+ return gitFail(result.stderr || 'Failed to checkout branch');
37
+ }
38
+ return gitOk({ previous });
39
+ }
40
+ export async function createBranch({ cwd, name, startPoint, checkout }) {
41
+ const args = ['branch', '--', name, ...(startPoint ? [startPoint] : [])];
42
+ const result = await executeGitCommand(args, cwd);
43
+ if (result.exitCode !== 0) {
44
+ return gitFail(result.stderr || 'Failed to create branch');
45
+ }
46
+ const hashResult = await executeGitCommand(['rev-parse', '--short', name], cwd);
47
+ if (checkout) {
48
+ await executeGitCommand(['checkout', name], cwd);
49
+ }
50
+ return gitOk({ name, hash: hashResult.stdout.trim() });
51
+ }
52
+ export async function deleteBranch({ cwd, name, force }) {
53
+ const currentResult = await executeGitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);
54
+ if (currentResult.stdout.trim() === name) {
55
+ return gitFail('Cannot delete the currently checked out branch');
56
+ }
57
+ const result = await executeGitCommand(['branch', force ? '-D' : '-d', '--', name], cwd);
58
+ if (result.exitCode !== 0) {
59
+ return gitFail(result.stderr || 'Failed to delete branch');
60
+ }
61
+ return gitOk({ name });
62
+ }