@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.
- package/LICENSE +14 -0
- package/PRIVACY.md +357 -0
- package/README.md +57 -0
- package/THIRD_PARTY_NOTICES.md +245 -0
- package/bin/branding.js +4 -0
- package/bin/commands/browser-install.js +483 -0
- package/bin/commands/create-sandbox.js +542 -0
- package/bin/commands/fingerprint.js +101 -0
- package/bin/commands/login.js +400 -0
- package/bin/commands/logout.js +93 -0
- package/bin/commands/minions.js +211 -0
- package/bin/commands/sandboxes.js +309 -0
- package/bin/commands/status.js +298 -0
- package/bin/commands/whoami.js +153 -0
- package/bin/launch-env.js +35 -0
- package/bin/machine-identity.js +221 -0
- package/bin/machine-layout.js +200 -0
- package/bin/minion.js +839 -0
- package/bin/platform-endpoints.js +8 -0
- package/bin/postinstall.js +52 -0
- package/bin/pty-doctor.js +326 -0
- package/bin/pty-locator.js +110 -0
- package/bin/pty-provision.js +186 -0
- package/bin/sandbox/Dockerfile +78 -0
- package/bin/sandbox/entrypoint.sh +14 -0
- package/bin/sandbox/install-repo.sh +53 -0
- package/bin/sandbox/seccomp-userns.json +883 -0
- package/bin/sandbox-config.js +306 -0
- package/dist/bin/machine-identity.js +221 -0
- package/dist/bin/machine-layout.js +200 -0
- package/dist/electron-host/agent-lease.js +141 -0
- package/dist/electron-host/dom-driver.js +642 -0
- package/dist/electron-host/ipc-protocol.js +89 -0
- package/dist/electron-host/js-driver.js +216 -0
- package/dist/electron-host/view-manager.js +254 -0
- package/dist/server/cli/engine-resume.js +49 -0
- package/dist/server/cli/eta-estimator.js +278 -0
- package/dist/server/cli/headless/background-activity.js +109 -0
- package/dist/server/cli/headless/claude-invoker-process.js +614 -0
- package/dist/server/cli/headless/claude-invoker-stall.js +150 -0
- package/dist/server/cli/headless/claude-invoker-stream.js +555 -0
- package/dist/server/cli/headless/claude-invoker-tools.js +148 -0
- package/dist/server/cli/headless/claude-invoker.js +151 -0
- package/dist/server/cli/headless/engine-availability.js +92 -0
- package/dist/server/cli/headless/engine-notice.js +185 -0
- package/dist/server/cli/headless/haiku-assessments.js +293 -0
- package/dist/server/cli/headless/headless-logger.js +75 -0
- package/dist/server/cli/headless/index.js +9 -0
- package/dist/server/cli/headless/mcp-config.js +314 -0
- package/dist/server/cli/headless/native-timeout-detector.js +72 -0
- package/dist/server/cli/headless/output-utils.js +71 -0
- package/dist/server/cli/headless/prompt-utils.js +82 -0
- package/dist/server/cli/headless/resilient-runner.js +326 -0
- package/dist/server/cli/headless/retry-strategies.js +292 -0
- package/dist/server/cli/headless/runner.js +245 -0
- package/dist/server/cli/headless/stall-assessor.js +295 -0
- package/dist/server/cli/headless/tool-watchdog.js +447 -0
- package/dist/server/cli/headless/types.js +18 -0
- package/dist/server/cli/history-portability.js +85 -0
- package/dist/server/cli/improvisation-attachments.js +99 -0
- package/dist/server/cli/improvisation-history-store.js +121 -0
- package/dist/server/cli/improvisation-movements.js +137 -0
- package/dist/server/cli/improvisation-output-queue.js +34 -0
- package/dist/server/cli/improvisation-retry.js +8 -0
- package/dist/server/cli/improvisation-session-manager.js +1016 -0
- package/dist/server/cli/improvisation-types.js +31 -0
- package/dist/server/cli/plan-lifecycle.js +72 -0
- package/dist/server/cli/prompt-builders.js +371 -0
- package/dist/server/cli/retry/retry-best-result.js +28 -0
- package/dist/server/cli/retry/retry-context-loss.js +75 -0
- package/dist/server/cli/retry/retry-recovery-strategies.js +213 -0
- package/dist/server/cli/retry/retry-resume-strategy.js +20 -0
- package/dist/server/cli/retry/retry-runner-factory.js +92 -0
- package/dist/server/cli/retry/retry-tool-results.js +22 -0
- package/dist/server/cli/retry/retry-types.js +3 -0
- package/dist/server/engines/EngineEvent.js +57 -0
- package/dist/server/engines/claude/ClaudeCodeEngine.js +316 -0
- package/dist/server/engines/claude/claude-command.js +32 -0
- package/dist/server/engines/codex/CodexEngine.js +469 -0
- package/dist/server/engines/codex/codex-auth.js +203 -0
- package/dist/server/engines/codex/codex-invoker.js +205 -0
- package/dist/server/engines/codex/codex-provision.js +215 -0
- package/dist/server/engines/credentials/credential-probe.js +88 -0
- package/dist/server/engines/credentials/model-profiles.js +249 -0
- package/dist/server/engines/credentials/provider-credentials.js +146 -0
- package/dist/server/engines/engine-event-stream.js +52 -0
- package/dist/server/engines/execution/engine-session.js +380 -0
- package/dist/server/engines/factory.js +42 -0
- package/dist/server/engines/hermes/HermesEngine.js +628 -0
- package/dist/server/engines/hermes/hermes-auth.js +159 -0
- package/dist/server/engines/hermes/hermes-gateway-home.js +271 -0
- package/dist/server/engines/hermes/hermes-invoker.js +350 -0
- package/dist/server/engines/hermes/hermes-provision.js +318 -0
- package/dist/server/engines/read-only.js +20 -0
- package/dist/server/engines/types.js +27 -0
- package/dist/server/handlers/company-execution-registry.js +67 -0
- package/dist/server/handlers/company-handlers.js +514 -0
- package/dist/server/handlers/company-triggers.js +189 -0
- package/dist/server/handlers/company-types.js +3 -0
- package/dist/server/index.js +244 -0
- package/dist/server/mcp/app-tools-bridge.js +110 -0
- package/dist/server/mcp/app-tools-mcp-server.js +99 -0
- package/dist/server/mcp/bouncer-integration.js +744 -0
- package/dist/server/mcp/browser-mcp-server.js +915 -0
- package/dist/server/mcp/browser-redaction.js +103 -0
- package/dist/server/mcp/classifier/BouncerClassifier.js +3 -0
- package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js +212 -0
- package/dist/server/mcp/classifier/factory.js +124 -0
- package/dist/server/mcp/classifier/health.js +54 -0
- package/dist/server/mcp/classifier/telemetry.js +0 -0
- package/dist/server/mcp/company-patterns.js +104 -0
- package/dist/server/mcp/department-profiles.js +133 -0
- package/dist/server/mcp/quality-bridge.js +153 -0
- package/dist/server/mcp/quality-mcp-server.js +105 -0
- package/dist/server/mcp/security-analysis.js +384 -0
- package/dist/server/mcp/security-audit.js +152 -0
- package/dist/server/mcp/security-patterns.js +314 -0
- package/dist/server/mcp/server.js +194 -0
- package/dist/server/mcp/test-utils/agent-simulator.js +301 -0
- package/dist/server/mcp/test-utils/e2e-agent.js +103 -0
- package/dist/server/mcp/test-utils/e2e-capture.js +92 -0
- package/dist/server/mcp/test-utils/e2e-client.js +116 -0
- package/dist/server/mcp/test-utils/e2e-fixtures.js +87 -0
- package/dist/server/mcp/test-utils/e2e-gating.js +8 -0
- package/dist/server/mcp/test-utils/e2e-harness.js +8 -0
- package/dist/server/mcp/test-utils/e2e-scenarios.js +105 -0
- package/dist/server/routes/files.js +18 -0
- package/dist/server/routes/improvise.js +64 -0
- package/dist/server/routes/index.js +7 -0
- package/dist/server/routes/instances.js +41 -0
- package/dist/server/routes/internal.js +900 -0
- package/dist/server/routes/notifications.js +110 -0
- package/dist/server/server-setup.js +282 -0
- package/dist/server/services/agent-push.js +148 -0
- package/dist/server/services/analytics.js +197 -0
- package/dist/server/services/apps/build.js +249 -0
- package/dist/server/services/apps/greenlight.js +199 -0
- package/dist/server/services/apps/install.js +101 -0
- package/dist/server/services/apps/layout.js +35 -0
- package/dist/server/services/apps/serve.js +665 -0
- package/dist/server/services/apps/space-apps.js +248 -0
- package/dist/server/services/auth.js +48 -0
- package/dist/server/services/browser/chrome-sandbox.js +245 -0
- package/dist/server/services/browser/chromium-launch-spec.js +51 -0
- package/dist/server/services/browser/claude-reasoner.js +669 -0
- package/dist/server/services/browser/debug-log.js +3 -0
- package/dist/server/services/browser/driver-state.js +546 -0
- package/dist/server/services/browser/electron-provision.js +256 -0
- package/dist/server/services/browser/host-internal.js +245 -0
- package/dist/server/services/browser/host-mock.js +334 -0
- package/dist/server/services/browser/host-types.js +3 -0
- package/dist/server/services/browser/host.js +1067 -0
- package/dist/server/services/browser/index.js +4 -0
- package/dist/server/services/browser/ipc-client.js +354 -0
- package/dist/server/services/browser/pipewire-sink.js +199 -0
- package/dist/server/services/browser/preflight.js +590 -0
- package/dist/server/services/browser/reasoning-agent.js +659 -0
- package/dist/server/services/browser/sandbox-policy.js +169 -0
- package/dist/server/services/browser/stderr-noise-filter.js +26 -0
- package/dist/server/services/browser/telemetry.js +107 -0
- package/dist/server/services/browser/xvfb-supervisor.js +139 -0
- package/dist/server/services/browser-frame-policy.js +56 -0
- package/dist/server/services/client-id.js +32 -0
- package/dist/server/services/collab/registry.js +408 -0
- package/dist/server/services/collab/session.js +489 -0
- package/dist/server/services/collab/text-diff.js +28 -0
- package/dist/server/services/collab/types.js +19 -0
- package/dist/server/services/e2ee-group-key.js +197 -0
- package/dist/server/services/e2ee-identity.js +203 -0
- package/dist/server/services/file-explorer-ops.js +328 -0
- package/dist/server/services/file-transfer-zip.js +188 -0
- package/dist/server/services/files.js +111 -0
- package/dist/server/services/git/branch-ops.js +62 -0
- package/dist/server/services/git/command.js +68 -0
- package/dist/server/services/git/commit-message.js +74 -0
- package/dist/server/services/git/diff-ops.js +56 -0
- package/dist/server/services/git/haiku.js +76 -0
- package/dist/server/services/git/head-watcher.js +226 -0
- package/dist/server/services/git/index.js +17 -0
- package/dist/server/services/git/log-ops.js +98 -0
- package/dist/server/services/git/merge-ops.js +314 -0
- package/dist/server/services/git/parsers.js +401 -0
- package/dist/server/services/git/remote-ops.js +192 -0
- package/dist/server/services/git/status-ops.js +105 -0
- package/dist/server/services/git/suggestion-ops.js +80 -0
- package/dist/server/services/git/tag-ops.js +36 -0
- package/dist/server/services/git/types.js +4 -0
- package/dist/server/services/git/worktree-ops.js +114 -0
- package/dist/server/services/instances.js +337 -0
- package/dist/server/services/model-catalog.js +247 -0
- package/dist/server/services/observability/posthog.js +153 -0
- package/dist/server/services/pathUtils.js +114 -0
- package/dist/server/services/plan/agent-loader.js +97 -0
- package/dist/server/services/plan/agent-manager.js +363 -0
- package/dist/server/services/plan/agent-resolver.js +74 -0
- package/dist/server/services/plan/agents/assess-stall.md +33 -0
- package/dist/server/services/plan/agents/browser-planner.md +53 -0
- package/dist/server/services/plan/agents/browser-reasoner.md +114 -0
- package/dist/server/services/plan/agents/check-injection.md +95 -0
- package/dist/server/services/plan/agents/classify-error.md +30 -0
- package/dist/server/services/plan/agents/code-review.md +142 -0
- package/dist/server/services/plan/agents/commit-message.md +28 -0
- package/dist/server/services/plan/agents/detect-context-loss.md +30 -0
- package/dist/server/services/plan/agents/execute-issue.md +58 -0
- package/dist/server/services/plan/agents/fix-quality.md +25 -0
- package/dist/server/services/plan/agents/plan-coordinator.md +72 -0
- package/dist/server/services/plan/agents/pr-description.md +29 -0
- package/dist/server/services/plan/agents/retry-task.md +27 -0
- package/dist/server/services/plan/agents/review-code.md +38 -0
- package/dist/server/services/plan/agents/review-quality.md +45 -0
- package/dist/server/services/plan/agents/triage-findings.md +78 -0
- package/dist/server/services/plan/agents/verify-review.md +57 -0
- package/dist/server/services/plan/approval-evaluator.js +143 -0
- package/dist/server/services/plan/board-archive.js +102 -0
- package/dist/server/services/plan/board-config.js +108 -0
- package/dist/server/services/plan/board-export.js +214 -0
- package/dist/server/services/plan/composer-prompt.js +115 -0
- package/dist/server/services/plan/composer.js +664 -0
- package/dist/server/services/plan/config-installer.js +103 -0
- package/dist/server/services/plan/dependency-resolver.js +137 -0
- package/dist/server/services/plan/executor.js +696 -0
- package/dist/server/services/plan/front-matter.js +43 -0
- package/dist/server/services/plan/issue-classification.js +10 -0
- package/dist/server/services/plan/issue-effort.js +182 -0
- package/dist/server/services/plan/issue-loader.js +35 -0
- package/dist/server/services/plan/issue-prompt-builder.js +152 -0
- package/dist/server/services/plan/issue-retry.js +42 -0
- package/dist/server/services/plan/issue-writer.js +102 -0
- package/dist/server/services/plan/metrics-collector.js +272 -0
- package/dist/server/services/plan/output-manager.js +77 -0
- package/dist/server/services/plan/parser-core.js +435 -0
- package/dist/server/services/plan/parser-migration.js +108 -0
- package/dist/server/services/plan/parser.js +258 -0
- package/dist/server/services/plan/plan-runner-factory.js +68 -0
- package/dist/server/services/plan/pm-timeline.js +320 -0
- package/dist/server/services/plan/progress-log.js +101 -0
- package/dist/server/services/plan/prompt-builder.js +142 -0
- package/dist/server/services/plan/quality-delta.js +274 -0
- package/dist/server/services/plan/readiness-planner.js +34 -0
- package/dist/server/services/plan/review-gate.js +409 -0
- package/dist/server/services/plan/review-report.js +134 -0
- package/dist/server/services/plan/review-verdict-stream.js +161 -0
- package/dist/server/services/plan/state-reconciler.js +238 -0
- package/dist/server/services/plan/template-diff.js +175 -0
- package/dist/server/services/plan/template-instantiator.js +516 -0
- package/dist/server/services/plan/template-manifest.js +56 -0
- package/dist/server/services/plan/template-types.js +3 -0
- package/dist/server/services/plan/trigger-evaluator.js +211 -0
- package/dist/server/services/plan/types.js +3 -0
- package/dist/server/services/plan/watcher.js +73 -0
- package/dist/server/services/platform-credentials.js +56 -0
- package/dist/server/services/platform-e2ee.js +421 -0
- package/dist/server/services/platform-envelope.js +102 -0
- package/dist/server/services/platform-heartbeat.js +88 -0
- package/dist/server/services/platform-reconnect.js +60 -0
- package/dist/server/services/platform-token-lifecycle.js +95 -0
- package/dist/server/services/platform-url.js +17 -0
- package/dist/server/services/platform.js +656 -0
- package/dist/server/services/runtime-info.js +9 -0
- package/dist/server/services/schedule/agent-schedule-store.js +232 -0
- package/dist/server/services/schedule/agent-scheduler.js +323 -0
- package/dist/server/services/schedule/daily-timing.js +105 -0
- package/dist/server/services/schedule/quality-schedule-launch.js +11 -0
- package/dist/server/services/schedule/quality-schedule-store.js +211 -0
- package/dist/server/services/schedule/quality-scheduler.js +215 -0
- package/dist/server/services/schedule/run-bootstrap.js +329 -0
- package/dist/server/services/schedule/schedule-store.js +238 -0
- package/dist/server/services/schedule/schedule-wire.js +77 -0
- package/dist/server/services/schedule/scheduler.js +310 -0
- package/dist/server/services/schedule/template-source.js +97 -0
- package/dist/server/services/sdk/agent-sessions.js +264 -0
- package/dist/server/services/sdk/agents.js +557 -0
- package/dist/server/services/sdk/app-endpoints.js +48 -0
- package/dist/server/services/sdk/app-tools.js +303 -0
- package/dist/server/services/sdk/audit.js +48 -0
- package/dist/server/services/sdk/browser-transport.js +188 -0
- package/dist/server/services/sdk/browser.js +605 -0
- package/dist/server/services/sdk/composer.js +129 -0
- package/dist/server/services/sdk/connect.js +273 -0
- package/dist/server/services/sdk/consent-cooldown.js +31 -0
- package/dist/server/services/sdk/endpoint-url.js +141 -0
- package/dist/server/services/sdk/endpoints.js +314 -0
- package/dist/server/services/sdk/file-change-notify.js +36 -0
- package/dist/server/services/sdk/files-app.js +163 -0
- package/dist/server/services/sdk/files-search.js +131 -0
- package/dist/server/services/sdk/files-transfer.js +279 -0
- package/dist/server/services/sdk/files-workspace.js +233 -0
- package/dist/server/services/sdk/git.js +520 -0
- package/dist/server/services/sdk/grant-store.js +318 -0
- package/dist/server/services/sdk/host-ops.js +84 -0
- package/dist/server/services/sdk/inference-claude.js +214 -0
- package/dist/server/services/sdk/inference.js +247 -0
- package/dist/server/services/sdk/live-registry.js +42 -0
- package/dist/server/services/sdk/local-app-bindings.js +71 -0
- package/dist/server/services/sdk/pipeline.js +190 -0
- package/dist/server/services/sdk/pm-execute.js +228 -0
- package/dist/server/services/sdk/pm-planning-tap.js +29 -0
- package/dist/server/services/sdk/pm-schedule.js +165 -0
- package/dist/server/services/sdk/pm.js +634 -0
- package/dist/server/services/sdk/quality-change-notify.js +20 -0
- package/dist/server/services/sdk/quality-schedule.js +165 -0
- package/dist/server/services/sdk/quality.js +602 -0
- package/dist/server/services/sdk/rate-limits.js +198 -0
- package/dist/server/services/sdk/registry.js +597 -0
- package/dist/server/services/sdk/revoke.js +86 -0
- package/dist/server/services/sdk/run-profile.js +41 -0
- package/dist/server/services/sdk/sandbox.js +89 -0
- package/dist/server/services/sdk/storage.js +110 -0
- package/dist/server/services/sdk/streams.js +147 -0
- package/dist/server/services/sdk/terminal.js +201 -0
- package/dist/server/services/sdk/test-utils/workshop-browser-app.js +466 -0
- package/dist/server/services/sentry.js +99 -0
- package/dist/server/services/settings.js +374 -0
- package/dist/server/services/snippets/expander.js +87 -0
- package/dist/server/services/snippets/index.js +6 -0
- package/dist/server/services/snippets/loader.js +119 -0
- package/dist/server/services/snippets/parser.js +52 -0
- package/dist/server/services/snippets/types.js +3 -0
- package/dist/server/services/snippets/watcher.js +60 -0
- package/dist/server/services/space-layout.js +80 -0
- package/dist/server/services/system-prompts.js +219 -0
- package/dist/server/services/terminal/pty-manager.js +206 -0
- package/dist/server/services/terminal/pty-utils.js +150 -0
- package/dist/server/services/timeline/assembler.js +890 -0
- package/dist/server/services/timeline/contract.js +196 -0
- package/dist/server/services/timeline/index.js +4 -0
- package/dist/server/services/websocket/agent-schedule-handlers.js +217 -0
- package/dist/server/services/websocket/apps-handlers.js +399 -0
- package/dist/server/services/websocket/ask-user-question-bridge.js +112 -0
- package/dist/server/services/websocket/autocomplete-index.js +415 -0
- package/dist/server/services/websocket/autocomplete-match.js +243 -0
- package/dist/server/services/websocket/autocomplete.js +407 -0
- package/dist/server/services/websocket/browser-agent-runtime.js +208 -0
- package/dist/server/services/websocket/browser-device-profile.js +46 -0
- package/dist/server/services/websocket/browser-handlers.js +377 -0
- package/dist/server/services/websocket/browser-host-broadcast.js +179 -0
- package/dist/server/services/websocket/browser-ice-config.js +121 -0
- package/dist/server/services/websocket/browser-payloads.js +222 -0
- package/dist/server/services/websocket/browser-viewer-lifecycle.js +84 -0
- package/dist/server/services/websocket/browser-viewer-registry.js +118 -0
- package/dist/server/services/websocket/collab-broadcast.js +11 -0
- package/dist/server/services/websocket/collab-handlers.js +116 -0
- package/dist/server/services/websocket/commit-suggestion-service.js +132 -0
- package/dist/server/services/websocket/debug-log.js +38 -0
- package/dist/server/services/websocket/dispatch-util.js +10 -0
- package/dist/server/services/websocket/engine-auth-handlers.js +323 -0
- package/dist/server/services/websocket/engine-credential-watcher.js +83 -0
- package/dist/server/services/websocket/engine-profile-handlers.js +92 -0
- package/dist/server/services/websocket/file-definition-handlers.js +180 -0
- package/dist/server/services/websocket/file-download-handler.js +291 -0
- package/dist/server/services/websocket/file-explorer-handlers.js +291 -0
- package/dist/server/services/websocket/file-search-handlers.js +267 -0
- package/dist/server/services/websocket/file-share-handlers.js +328 -0
- package/dist/server/services/websocket/file-transfer-http.js +361 -0
- package/dist/server/services/websocket/file-upload-handler.js +267 -0
- package/dist/server/services/websocket/file-utils.js +346 -0
- package/dist/server/services/websocket/git-branch-handlers.js +90 -0
- package/dist/server/services/websocket/git-diff-handlers.js +59 -0
- package/dist/server/services/websocket/git-handlers.js +212 -0
- package/dist/server/services/websocket/git-head-watcher.js +85 -0
- package/dist/server/services/websocket/git-log-handlers.js +104 -0
- package/dist/server/services/websocket/git-pr-handlers.js +56 -0
- package/dist/server/services/websocket/git-tag-handlers.js +53 -0
- package/dist/server/services/websocket/git-utils.js +11 -0
- package/dist/server/services/websocket/git-worktree-handlers.js +521 -0
- package/dist/server/services/websocket/handler-context.js +113 -0
- package/dist/server/services/websocket/handler.js +1197 -0
- package/dist/server/services/websocket/index.js +5 -0
- package/dist/server/services/websocket/movement-written-files.js +26 -0
- package/dist/server/services/websocket/msg-id-tracker.js +48 -0
- package/dist/server/services/websocket/plan-board-handlers.js +410 -0
- package/dist/server/services/websocket/plan-execution-handlers.js +244 -0
- package/dist/server/services/websocket/plan-handlers.js +67 -0
- package/dist/server/services/websocket/plan-helpers.js +161 -0
- package/dist/server/services/websocket/plan-issue-handlers.js +168 -0
- package/dist/server/services/websocket/plan-sprint-handlers.js +190 -0
- package/dist/server/services/websocket/plan-transfer-handlers.js +310 -0
- package/dist/server/services/websocket/pm-timeline-broadcast.js +28 -0
- package/dist/server/services/websocket/post-session-scan.js +132 -0
- package/dist/server/services/websocket/prompt-queue-handlers.js +96 -0
- package/dist/server/services/websocket/quality-agent-cost.js +229 -0
- package/dist/server/services/websocket/quality-agent-notes.js +113 -0
- package/dist/server/services/websocket/quality-change-activity.js +187 -0
- package/dist/server/services/websocket/quality-complexity.js +345 -0
- package/dist/server/services/websocket/quality-dependencies.js +445 -0
- package/dist/server/services/websocket/quality-duplication.js +162 -0
- package/dist/server/services/websocket/quality-eta.js +65 -0
- package/dist/server/services/websocket/quality-fingerprint.js +104 -0
- package/dist/server/services/websocket/quality-grading.js +575 -0
- package/dist/server/services/websocket/quality-handlers.js +48 -0
- package/dist/server/services/websocket/quality-linting.js +270 -0
- package/dist/server/services/websocket/quality-operations.js +54 -0
- package/dist/server/services/websocket/quality-persistence.js +410 -0
- package/dist/server/services/websocket/quality-review-agent.js +526 -0
- package/dist/server/services/websocket/quality-run.js +220 -0
- package/dist/server/services/websocket/quality-secrets.js +0 -0
- package/dist/server/services/websocket/quality-service.js +775 -0
- package/dist/server/services/websocket/quality-tools.js +383 -0
- package/dist/server/services/websocket/quality-triage-agent.js +101 -0
- package/dist/server/services/websocket/quality-types.js +149 -0
- package/dist/server/services/websocket/recommended-answers.js +28 -0
- package/dist/server/services/websocket/schedule-handlers.js +197 -0
- package/dist/server/services/websocket/sdk-agent-host.js +569 -0
- package/dist/server/services/websocket/sdk-browser-host.js +459 -0
- package/dist/server/services/websocket/sdk-composer-host.js +10 -0
- package/dist/server/services/websocket/sdk-git-host.js +115 -0
- package/dist/server/services/websocket/sdk-handlers.js +242 -0
- package/dist/server/services/websocket/sdk-pm-execution-host.js +63 -0
- package/dist/server/services/websocket/sdk-pm-schedule-host.js +21 -0
- package/dist/server/services/websocket/sdk-quality-schedule-host.js +34 -0
- package/dist/server/services/websocket/sdk-terminal-host.js +140 -0
- package/dist/server/services/websocket/session-handlers.js +565 -0
- package/dist/server/services/websocket/session-history.js +335 -0
- package/dist/server/services/websocket/session-initialization.js +315 -0
- package/dist/server/services/websocket/session-registry.js +340 -0
- package/dist/server/services/websocket/session-role-directory.js +39 -0
- package/dist/server/services/websocket/settings-handlers.js +276 -0
- package/dist/server/services/websocket/skill-handlers.js +324 -0
- package/dist/server/services/websocket/skill-watcher.js +83 -0
- package/dist/server/services/websocket/snippet-handlers.js +261 -0
- package/dist/server/services/websocket/tab-broadcast.js +35 -0
- package/dist/server/services/websocket/tab-event-buffer.js +110 -0
- package/dist/server/services/websocket/tab-event-replay.js +47 -0
- package/dist/server/services/websocket/tab-handlers.js +211 -0
- package/dist/server/services/websocket/terminal-handlers.js +268 -0
- package/dist/server/services/websocket/types.js +96 -0
- package/dist/server/types/company-messages.js +102 -0
- package/dist/server/utils/agent-manager.js +202 -0
- package/dist/server/utils/console-timestamps.js +24 -0
- package/dist/server/utils/file-store.js +112 -0
- package/dist/server/utils/paths.js +28 -0
- package/dist/server/utils/port-manager.js +43 -0
- package/dist/server/utils/port.js +204 -0
- package/electron-host/dist/agent-lease.js +141 -0
- package/electron-host/dist/capture-recovery.js +77 -0
- package/electron-host/dist/codec-policy.js +37 -0
- package/electron-host/dist/controller-channel.js +60 -0
- package/electron-host/dist/controller-handlers.js +153 -0
- package/electron-host/dist/device-emulator.js +106 -0
- package/electron-host/dist/dom-driver.js +642 -0
- package/electron-host/dist/domain-registry.js +159 -0
- package/electron-host/dist/domain-validators.js +308 -0
- package/electron-host/dist/editable-focus-reporter.js +143 -0
- package/electron-host/dist/fake-peer.test-util.js +105 -0
- package/electron-host/dist/host-log.js +31 -0
- package/electron-host/dist/host-wire.js +11 -0
- package/electron-host/dist/input-router.js +421 -0
- package/electron-host/dist/ipc-protocol.js +89 -0
- package/electron-host/dist/ipc-server.js +193 -0
- package/electron-host/dist/js-driver.js +216 -0
- package/electron-host/dist/main-guards.js +70 -0
- package/electron-host/dist/main.js +716 -0
- package/electron-host/dist/roster-sync.js +87 -0
- package/electron-host/dist/rpc-context.js +1 -0
- package/electron-host/dist/rpc-tab-methods.js +138 -0
- package/electron-host/dist/rpc-webrtc-methods.js +121 -0
- package/electron-host/dist/screen-capture-cache.js +147 -0
- package/electron-host/dist/sdk-injector.js +166 -0
- package/electron-host/dist/sdp.js +102 -0
- package/electron-host/dist/session-surface.js +78 -0
- package/electron-host/dist/surface-sizing.js +59 -0
- package/electron-host/dist/view-manager.js +254 -0
- package/electron-host/dist/viewer-registry.js +46 -0
- package/electron-host/dist/viewer-session.js +288 -0
- package/electron-host/dist/webrtc-channels.js +14 -0
- package/electron-host/dist/webrtc-controller.js +57 -0
- package/electron-host/dist/webrtc-ice-filter.js +13 -0
- package/electron-host/dist/webrtc-peer.js +45 -0
- package/electron-host/package.json +12 -0
- package/electron-host/tsconfig.json +23 -0
- package/electron-host/webrtc-controller-preload.cjs +3 -0
- package/electron-host/webrtc-controller.html +14 -0
- package/package.json +85 -0
- package/vendor/e2ee/LICENSE +14 -0
- package/vendor/e2ee/package.json +14 -0
- package/vendor/e2ee/src/index.js +310 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Minionry, Inc.
|
|
2
|
+
// SPDX-License-Identifier: LicenseRef-Minionry-Software
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
buildMemoryInspectArgs,
|
|
7
|
+
buildRenameCommands,
|
|
8
|
+
buildSandboxListArgs,
|
|
9
|
+
buildUncapCommands,
|
|
10
|
+
findSandbox,
|
|
11
|
+
formatMemoryCap,
|
|
12
|
+
parseMemoryCaps,
|
|
13
|
+
parseRenameArgs,
|
|
14
|
+
parseRestartArgs,
|
|
15
|
+
parseSandboxRows,
|
|
16
|
+
SANDBOX_IMAGE_TAG,
|
|
17
|
+
sandboxNames,
|
|
18
|
+
sandboxVolume,
|
|
19
|
+
validateSandboxName,
|
|
20
|
+
withoutSeccompProfile,
|
|
21
|
+
} from '../sandbox-config.js';
|
|
22
|
+
import {
|
|
23
|
+
confirm,
|
|
24
|
+
createAsker,
|
|
25
|
+
IMAGE_BUILD_ARGS,
|
|
26
|
+
imagePathFor,
|
|
27
|
+
requireDocker,
|
|
28
|
+
runCapture,
|
|
29
|
+
takenDockerNames,
|
|
30
|
+
} from './create-sandbox.js';
|
|
31
|
+
|
|
32
|
+
const colors = {
|
|
33
|
+
reset: '\x1b[0m',
|
|
34
|
+
bold: '\x1b[1m',
|
|
35
|
+
green: '\x1b[32m',
|
|
36
|
+
yellow: '\x1b[33m',
|
|
37
|
+
red: '\x1b[31m',
|
|
38
|
+
dim: '\x1b[2m',
|
|
39
|
+
cyan: '\x1b[36m',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function log(msg, color = '') {
|
|
43
|
+
console.log(`${color}${msg}${colors.reset}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function loadSandboxes() {
|
|
47
|
+
const listed = await runCapture('docker', buildSandboxListArgs());
|
|
48
|
+
if (!listed.ok) {
|
|
49
|
+
log(`\n Could not list containers: ${listed.stderr.trim() || `docker exited with code ${listed.code}`}\n`, colors.red);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const rows = parseSandboxRows(listed.stdout);
|
|
54
|
+
if (rows.length === 0) return [];
|
|
55
|
+
|
|
56
|
+
const inspected = await runCapture('docker', buildMemoryInspectArgs(rows.map((row) => row.container)));
|
|
57
|
+
const caps = inspected.ok ? parseMemoryCaps(inspected.stdout) : new Map();
|
|
58
|
+
|
|
59
|
+
return rows
|
|
60
|
+
.map((row) => ({ ...row, memoryBytes: caps.get(row.container) ?? 0 }))
|
|
61
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function printNoSandboxes() {
|
|
65
|
+
log('\n No sandboxes on this machine yet.\n', colors.bold);
|
|
66
|
+
log(' Create one:', colors.bold);
|
|
67
|
+
log(' minion create sandbox', colors.cyan);
|
|
68
|
+
log('');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function diskCell(row) {
|
|
72
|
+
if (row.diskGb && row.diskCapped) return `${row.diskGb} GB cap`;
|
|
73
|
+
if (row.diskGb) return `${row.diskGb} GB (not enforced)`;
|
|
74
|
+
return 'uncapped';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function printUncapHelp(capped) {
|
|
78
|
+
const [first, ...rest] = capped;
|
|
79
|
+
log(' A memory cap is fixed for the life of a container. Lift one by replacing the', colors.dim);
|
|
80
|
+
log(' container — its disk volume, and everything in /home/minion, survives:', colors.dim);
|
|
81
|
+
log(` minion restart sandbox ${first.name} --uncap`, colors.cyan);
|
|
82
|
+
if (rest.length > 0) {
|
|
83
|
+
log(` Same for: ${rest.map((row) => row.name).join(', ')}`, colors.dim);
|
|
84
|
+
}
|
|
85
|
+
log('');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function listSandboxes() {
|
|
89
|
+
await requireDocker();
|
|
90
|
+
const sandboxes = await loadSandboxes();
|
|
91
|
+
if (sandboxes.length === 0) {
|
|
92
|
+
printNoSandboxes();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const headers = ['SANDBOX', 'STATUS', 'MEMORY', 'DISK'];
|
|
97
|
+
const rows = sandboxes.map((row) => {
|
|
98
|
+
const cap = formatMemoryCap(row.memoryBytes);
|
|
99
|
+
return [row.name, row.status, cap ? `${cap} cap` : 'uncapped', diskCell(row)];
|
|
100
|
+
});
|
|
101
|
+
const widths = headers.map((header, i) => Math.max(header.length, ...rows.map((cells) => cells[i].length)));
|
|
102
|
+
const line = (cells, color = '') =>
|
|
103
|
+
` ${cells.map((cell, i) => `${color}${i === cells.length - 1 ? cell : cell.padEnd(widths[i])}${colors.reset}`).join(' ')}`;
|
|
104
|
+
|
|
105
|
+
log('');
|
|
106
|
+
console.log(line(headers, colors.dim));
|
|
107
|
+
for (const cells of rows) console.log(line(cells));
|
|
108
|
+
log('');
|
|
109
|
+
log(' Enter one:', colors.bold);
|
|
110
|
+
const running = sandboxes.find((row) => row.status.startsWith('Up')) ?? sandboxes[0];
|
|
111
|
+
log(` docker exec -it ${running.container} zsh`, colors.cyan);
|
|
112
|
+
log('');
|
|
113
|
+
log(' Rename one:', colors.bold);
|
|
114
|
+
log(` minion rename sandbox ${running.name} <new-name>`, colors.cyan);
|
|
115
|
+
log('');
|
|
116
|
+
|
|
117
|
+
const capped = sandboxes.filter((row) => row.memoryBytes > 0);
|
|
118
|
+
if (capped.length > 0) printUncapHelp(capped);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function printCarryOver() {
|
|
122
|
+
log(' The volume is remounted, so /home/minion — the toolchain, your Spaces,', colors.dim);
|
|
123
|
+
log(' everything in it — carries over untouched. Anything installed OUTSIDE', colors.dim);
|
|
124
|
+
log(' /home/minion (apt packages, /etc edits) is not in the volume and would', colors.dim);
|
|
125
|
+
log(' need doing again.\n', colors.dim);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function replaceContainer(sandbox, { commands, explain, confirmText }) {
|
|
129
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
130
|
+
log('\n This replaces the sandbox\'s container, so it asks first — run it from a terminal.\n', colors.red);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!(await runCapture('docker', ['image', 'inspect', SANDBOX_IMAGE_TAG])).ok) {
|
|
135
|
+
log(`\n The ${SANDBOX_IMAGE_TAG} image is gone, so the container cannot be rebuilt.`, colors.red);
|
|
136
|
+
log(' Nothing was changed. Restore the image first, then re-run this:', colors.dim);
|
|
137
|
+
log(` docker build ${IMAGE_BUILD_ARGS.join(' ')}`, colors.cyan);
|
|
138
|
+
log('');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const [remove, run] = commands;
|
|
143
|
+
explain();
|
|
144
|
+
log(` docker ${remove.join(' ')}`, colors.cyan);
|
|
145
|
+
log(` docker ${run.join(' ')}`, colors.cyan);
|
|
146
|
+
log('');
|
|
147
|
+
|
|
148
|
+
const { rl, question } = createAsker();
|
|
149
|
+
const confirmed = await confirm(question, confirmText, { defaultYes: false });
|
|
150
|
+
rl.close();
|
|
151
|
+
if (!confirmed) {
|
|
152
|
+
log('\n Cancelled — nothing was changed.\n', colors.dim);
|
|
153
|
+
process.exit(0);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
log(`\n Replacing ${sandbox.container}...`, colors.bold);
|
|
157
|
+
const removed = await runCapture('docker', remove);
|
|
158
|
+
if (!removed.ok) {
|
|
159
|
+
log(`\n docker rm failed: ${removed.stderr.trim()}`, colors.red);
|
|
160
|
+
log(' The sandbox was left exactly as it was.\n', colors.dim);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let started = await runCapture('docker', run);
|
|
165
|
+
if (!started.ok && /seccomp/i.test(started.stderr)) {
|
|
166
|
+
log(` This Docker daemon rejected the browser seccomp profile — retrying without it: ${started.stderr.trim()}`, colors.yellow);
|
|
167
|
+
await runCapture('docker', ['rm', '-f', run[run.indexOf('--name') + 1]]);
|
|
168
|
+
started = await runCapture('docker', withoutSeccompProfile(run));
|
|
169
|
+
}
|
|
170
|
+
if (!started.ok) {
|
|
171
|
+
log(`\n The container was removed but did not come back: ${started.stderr.trim()}`, colors.red);
|
|
172
|
+
log(' The disk volume is untouched — nothing in /home/minion was lost. Retry with:', colors.dim);
|
|
173
|
+
log(` docker ${run.join(' ')}`, colors.cyan);
|
|
174
|
+
log('');
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function uncapSandbox(sandbox) {
|
|
180
|
+
const cap = formatMemoryCap(sandbox.memoryBytes);
|
|
181
|
+
if (!cap) {
|
|
182
|
+
log(`\n "${sandbox.name}" has no memory cap — nothing to lift.`, colors.dim);
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
await replaceContainer(sandbox, {
|
|
187
|
+
commands: buildUncapCommands(sandbox),
|
|
188
|
+
confirmText: ` Replace "${sandbox.name}" now?`,
|
|
189
|
+
explain: () => {
|
|
190
|
+
log(`\n Sandbox "${sandbox.name}" has a ${cap} memory cap.\n`, colors.bold);
|
|
191
|
+
log(' A cap is fixed for the life of a container, so lifting it means replacing', colors.dim);
|
|
192
|
+
log(' the container.', colors.dim);
|
|
193
|
+
printCarryOver();
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
log(` Sandbox "${sandbox.name}" is running with no memory cap.\n`, colors.bold + colors.green);
|
|
198
|
+
log(' Enter it:', colors.bold);
|
|
199
|
+
log(` docker exec -it ${sandbox.container} zsh`, colors.cyan);
|
|
200
|
+
log('');
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async function resolveSandbox(input) {
|
|
205
|
+
await requireDocker();
|
|
206
|
+
const sandboxes = await loadSandboxes();
|
|
207
|
+
if (sandboxes.length === 0) {
|
|
208
|
+
printNoSandboxes();
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const sandbox = findSandbox(sandboxes, input);
|
|
213
|
+
if (!sandbox) {
|
|
214
|
+
log(`\n No sandbox named "${input}" on this machine.`, colors.red);
|
|
215
|
+
log(` You have: ${sandboxes.map((row) => row.name).join(', ')}\n`, colors.dim);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
return sandbox;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function requireFreeContainerName(newName) {
|
|
222
|
+
const { container } = sandboxNames(newName);
|
|
223
|
+
if (!(await takenDockerNames()).includes(container)) return;
|
|
224
|
+
|
|
225
|
+
log(`\n The name "${newName}" is taken — a container called "${container}" already exists.`, colors.red);
|
|
226
|
+
log(' Nothing was changed. Pick another name, or clear that one first:', colors.dim);
|
|
227
|
+
log(` docker rm -f ${container}`, colors.cyan);
|
|
228
|
+
log('');
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export async function renameSandbox(args = []) {
|
|
233
|
+
const parsed = parseRenameArgs(args);
|
|
234
|
+
if (!parsed.ok) {
|
|
235
|
+
log(`\n ${parsed.error}`, colors.red);
|
|
236
|
+
log(' Usage: minion rename sandbox <current-name> <new-name>', colors.dim);
|
|
237
|
+
log(' See what you have: minion list sandboxes\n', colors.dim);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const invalid = validateSandboxName(parsed.to);
|
|
242
|
+
if (invalid) {
|
|
243
|
+
log(`\n ${invalid}\n`, colors.red);
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const sandbox = await resolveSandbox(parsed.from);
|
|
248
|
+
if (sandbox.name === parsed.to) {
|
|
249
|
+
log(`\n Sandbox "${sandbox.name}" is already called that — nothing to do.\n`, colors.dim);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
await requireFreeContainerName(parsed.to);
|
|
253
|
+
|
|
254
|
+
const wasStopped = !sandbox.status.startsWith('Up');
|
|
255
|
+
|
|
256
|
+
await replaceContainer(sandbox, {
|
|
257
|
+
commands: buildRenameCommands(sandbox, parsed.to),
|
|
258
|
+
confirmText: ` Rename "${sandbox.name}" to "${parsed.to}" now?`,
|
|
259
|
+
explain: () => {
|
|
260
|
+
log(`\n Renaming "${sandbox.name}" to "${parsed.to}" replaces its container.\n`, colors.bold);
|
|
261
|
+
log(' A sandbox\'s name is also its hostname — the machine name it reports to', colors.dim);
|
|
262
|
+
log(' Minionry — and a hostname is fixed for the life of a container, so the', colors.dim);
|
|
263
|
+
log(' container is rebuilt under the new name. Its memory cap, disk cap and', colors.dim);
|
|
264
|
+
log(' restart policy come across unchanged.', colors.dim);
|
|
265
|
+
printCarryOver();
|
|
266
|
+
log(' The disk keeps the name it was made with — Docker cannot rename a volume —', colors.dim);
|
|
267
|
+
log(` which is why the command below still mounts ${sandboxVolume(sandbox)}.`, colors.dim);
|
|
268
|
+
if (sandbox.diskCapped) log(` Its disk image stays at ${imagePathFor(sandbox.name)}.`, colors.dim);
|
|
269
|
+
log('');
|
|
270
|
+
if (wasStopped) log(' The sandbox is stopped; the replacement brings it back up.\n', colors.yellow);
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const renamed = sandboxNames(parsed.to);
|
|
275
|
+
log(` Sandbox "${sandbox.name}" is now "${parsed.to}".\n`, colors.bold + colors.green);
|
|
276
|
+
log(' Enter it:', colors.bold);
|
|
277
|
+
log(` docker exec -it ${renamed.container} zsh`, colors.cyan);
|
|
278
|
+
log('');
|
|
279
|
+
log(` ${colors.dim}Every minion command now takes "${parsed.to}" — "${sandbox.name}" no longer resolves.${colors.reset}`);
|
|
280
|
+
log(` ${colors.dim}Inside the sandbox, re-run "minion" so it re-registers under the new hostname.${colors.reset}`);
|
|
281
|
+
log('');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export async function restartSandbox(args = []) {
|
|
285
|
+
const parsed = parseRestartArgs(args);
|
|
286
|
+
if (!parsed.ok) {
|
|
287
|
+
log(`\n ${parsed.error}`, colors.red);
|
|
288
|
+
log(' Usage: minion restart sandbox <name> [--uncap]', colors.dim);
|
|
289
|
+
log(' See what you have: minion list sandboxes\n', colors.dim);
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const sandbox = await resolveSandbox(parsed.name);
|
|
294
|
+
|
|
295
|
+
if (parsed.uncap && (await uncapSandbox(sandbox))) return;
|
|
296
|
+
|
|
297
|
+
log(`\n Restarting ${sandbox.name}...`, colors.bold);
|
|
298
|
+
const restart = await runCapture('docker', ['restart', sandbox.container]);
|
|
299
|
+
if (!restart.ok) {
|
|
300
|
+
log(`\n docker restart failed: ${restart.stderr.trim()}`, colors.red);
|
|
301
|
+
log(` Inspect it with: docker logs ${sandbox.container}\n`, colors.dim);
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
log(` Sandbox "${sandbox.name}" is running.\n`, colors.bold + colors.green);
|
|
306
|
+
log(' Enter it:', colors.bold);
|
|
307
|
+
log(` docker exec -it ${sandbox.container} zsh`, colors.cyan);
|
|
308
|
+
log('');
|
|
309
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { arch, hostname, type } from 'node:os';
|
|
4
|
+
import { APP_NAME } from '../branding.js';
|
|
5
|
+
import { launchFlagSuffix } from '../launch-env.js';
|
|
6
|
+
import { machineFile } from '../machine-layout.js';
|
|
7
|
+
import { resolvePlatformUrl } from '../platform-endpoints.js';
|
|
8
|
+
|
|
9
|
+
const colors = {
|
|
10
|
+
reset: '\x1b[0m',
|
|
11
|
+
bold: '\x1b[1m',
|
|
12
|
+
green: '\x1b[32m',
|
|
13
|
+
yellow: '\x1b[33m',
|
|
14
|
+
red: '\x1b[31m',
|
|
15
|
+
dim: '\x1b[2m',
|
|
16
|
+
cyan: '\x1b[36m',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function log(msg, color = '') {
|
|
20
|
+
console.log(`${color}${msg}${colors.reset}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function usernameFromEmail(email) {
|
|
24
|
+
if (!email) return '';
|
|
25
|
+
const at = email.lastIndexOf('@');
|
|
26
|
+
return at > 0 ? email.slice(0, at) : email;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const PLATFORM_URL = resolvePlatformUrl();
|
|
30
|
+
|
|
31
|
+
function credentialsFile() {
|
|
32
|
+
const env = process.env.MINIONRY_ENV || 'production';
|
|
33
|
+
return machineFile(env === 'dev' ? 'platformCredentialsDev' : 'platformCredentials');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getCredentials() {
|
|
37
|
+
if (!existsSync(credentialsFile())) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(readFileSync(credentialsFile(), 'utf-8'));
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getClientId() {
|
|
48
|
+
const clientIdFile = machineFile('clientId');
|
|
49
|
+
if (!existsSync(clientIdFile)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return readFileSync(clientIdFile, 'utf-8').trim();
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getE2eePublicKey() {
|
|
60
|
+
const identityFile = machineFile('e2eeIdentity');
|
|
61
|
+
if (!existsSync(identityFile)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const record = JSON.parse(readFileSync(identityFile, 'utf-8'));
|
|
66
|
+
const key = record?.publicKey;
|
|
67
|
+
return typeof key === 'string' && /^[A-Za-z0-9_-]{43}$/.test(key) ? key : null;
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function checkPlatform() {
|
|
74
|
+
try {
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
77
|
+
|
|
78
|
+
const response = await fetch(`${PLATFORM_URL}/health`, {
|
|
79
|
+
signal: controller.signal,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
clearTimeout(timeoutId);
|
|
83
|
+
|
|
84
|
+
if (response.ok) {
|
|
85
|
+
const data = await response.json();
|
|
86
|
+
return { online: true, data };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { online: false, error: `HTTP ${response.status}` };
|
|
90
|
+
} catch (err) {
|
|
91
|
+
return { online: false, error: err.name === 'AbortError' ? 'Timeout' : err.message };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function verifyToken(token) {
|
|
96
|
+
try {
|
|
97
|
+
const controller = new AbortController();
|
|
98
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
99
|
+
|
|
100
|
+
const response = await fetch(`${PLATFORM_URL}/api/auth/device/verify`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: {
|
|
103
|
+
'Authorization': `Bearer ${token}`,
|
|
104
|
+
'Content-Type': 'application/json',
|
|
105
|
+
},
|
|
106
|
+
signal: controller.signal,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
clearTimeout(timeoutId);
|
|
110
|
+
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const data = await response.json();
|
|
113
|
+
return { valid: false, error: data.error };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return await response.json();
|
|
117
|
+
} catch (err) {
|
|
118
|
+
return { valid: false, error: err.name === 'AbortError' ? 'Timeout' : err.message };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function getBrowserStatus() {
|
|
123
|
+
const ctx = readMinionryContext();
|
|
124
|
+
if (!ctx) return { transports: [] };
|
|
125
|
+
|
|
126
|
+
const transports = [];
|
|
127
|
+
for (const instance of ctx.aliveInstances) {
|
|
128
|
+
const data = await fetchBrowserTransport(instance.port, ctx.token);
|
|
129
|
+
if (!data) continue;
|
|
130
|
+
if (Array.isArray(data.transports)) transports.push(...data.transports);
|
|
131
|
+
}
|
|
132
|
+
return { transports };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function readMinionryContext() {
|
|
136
|
+
try {
|
|
137
|
+
const instancesPath = machineFile('instances');
|
|
138
|
+
const tokenPath = machineFile('sessionToken');
|
|
139
|
+
if (!existsSync(instancesPath) || !existsSync(tokenPath)) return null;
|
|
140
|
+
|
|
141
|
+
const instances = JSON.parse(readFileSync(instancesPath, 'utf-8'));
|
|
142
|
+
const token = readFileSync(tokenPath, 'utf-8').trim();
|
|
143
|
+
if (!Array.isArray(instances) || !token) return null;
|
|
144
|
+
|
|
145
|
+
const now = Date.now();
|
|
146
|
+
const aliveInstances = instances.filter(
|
|
147
|
+
(i) => now - i.lastHeartbeat < 2 * 60 * 1000,
|
|
148
|
+
);
|
|
149
|
+
return { token, aliveInstances };
|
|
150
|
+
} catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function fetchBrowserTransport(port, token) {
|
|
156
|
+
try {
|
|
157
|
+
const controller = new AbortController();
|
|
158
|
+
const timeoutId = setTimeout(() => controller.abort(), 1500);
|
|
159
|
+
const res = await fetch(`http://localhost:${port}/api/browser/transport`, {
|
|
160
|
+
headers: { 'x-session-token': token },
|
|
161
|
+
signal: controller.signal,
|
|
162
|
+
});
|
|
163
|
+
clearTimeout(timeoutId);
|
|
164
|
+
if (!res.ok) return null;
|
|
165
|
+
return await res.json();
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const TRANSPORT_LABELS = {
|
|
172
|
+
'webrtc-x11-p2p': 'WebRTC P2P (x11)',
|
|
173
|
+
'webrtc-x11-turn': 'WebRTC TURN (x11)',
|
|
174
|
+
'webrtc-wayland-p2p': 'WebRTC P2P (wayland)',
|
|
175
|
+
'webrtc-wayland-turn': 'WebRTC TURN (wayland)',
|
|
176
|
+
'webrtc-macos-p2p': 'WebRTC P2P (macos)',
|
|
177
|
+
'webrtc-macos-turn': 'WebRTC TURN (macos)',
|
|
178
|
+
cdp: 'CDP screencast (fallback)',
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
function transportLabel(kind) {
|
|
182
|
+
return TRANSPORT_LABELS[kind] ?? kind;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export async function status() {
|
|
186
|
+
const env = process.env.MINIONRY_ENV || 'production';
|
|
187
|
+
const envSuffix = launchFlagSuffix(env);
|
|
188
|
+
|
|
189
|
+
log(`\n ${APP_NAME} Status\n`, colors.bold + colors.cyan);
|
|
190
|
+
|
|
191
|
+
const creds = getCredentials();
|
|
192
|
+
const clientId = getClientId();
|
|
193
|
+
|
|
194
|
+
printDeviceBlock(clientId);
|
|
195
|
+
const platformStatus = await printPlatformBlock();
|
|
196
|
+
if (!(await printAuthBlock(creds, platformStatus, envSuffix))) return;
|
|
197
|
+
printEncryptionBlock();
|
|
198
|
+
await printBrowserBlock();
|
|
199
|
+
printCommandsBlock(envSuffix);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function printEncryptionBlock() {
|
|
203
|
+
const publicKey = getE2eePublicKey();
|
|
204
|
+
log(' Encryption', colors.bold);
|
|
205
|
+
if (publicKey) {
|
|
206
|
+
log(` Status: ${colors.green}End-to-end ready${colors.reset}`, colors.dim);
|
|
207
|
+
log(` Key: ${publicKey.slice(0, 12)}...`, colors.dim);
|
|
208
|
+
log(` ${colors.dim}Run "minion fingerprint" to verify a browser is talking to this machine.${colors.reset}`, colors.dim);
|
|
209
|
+
} else {
|
|
210
|
+
log(` Status: ${colors.yellow}Not set up${colors.reset} (this machine will connect in cleartext)`, colors.dim);
|
|
211
|
+
}
|
|
212
|
+
log('');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function printDeviceBlock(clientId) {
|
|
216
|
+
log(' Device', colors.bold);
|
|
217
|
+
log(` Hostname: ${hostname()}`, colors.dim);
|
|
218
|
+
log(` OS: ${type()} (${arch()})`, colors.dim);
|
|
219
|
+
log(` Node: ${process.version}`, colors.dim);
|
|
220
|
+
log(` Client ID: ${clientId ? `${clientId.slice(0, 8)}...` : 'Not set'}`, colors.dim);
|
|
221
|
+
log('');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async function printPlatformBlock() {
|
|
225
|
+
log(' Platform', colors.bold);
|
|
226
|
+
log(` URL: ${PLATFORM_URL}`, colors.dim);
|
|
227
|
+
process.stdout.write(' Status: Checking...');
|
|
228
|
+
const platformStatus = await checkPlatform();
|
|
229
|
+
process.stdout.write('\r \r');
|
|
230
|
+
|
|
231
|
+
if (platformStatus.online) {
|
|
232
|
+
log(` Status: ${colors.green}Online${colors.reset}`, colors.dim);
|
|
233
|
+
if (platformStatus.data?.relay) {
|
|
234
|
+
const relay = platformStatus.data.relay;
|
|
235
|
+
log(` Apps: ${relay.pairedClients || 0} connected`, colors.dim);
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
log(` Status: ${colors.red}Offline${colors.reset} (${platformStatus.error})`, colors.dim);
|
|
239
|
+
}
|
|
240
|
+
log('');
|
|
241
|
+
return platformStatus;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function printAuthBlock(creds, platformStatus, envSuffix) {
|
|
245
|
+
log(' Authentication', colors.bold);
|
|
246
|
+
if (!creds) {
|
|
247
|
+
log(` Status: ${colors.yellow}Not logged in${colors.reset}`, colors.dim);
|
|
248
|
+
log('');
|
|
249
|
+
log(` Run "minion login${envSuffix}" to authenticate this device.`, colors.dim);
|
|
250
|
+
log('');
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
log(` Username: ${usernameFromEmail(creds.email)}`, colors.dim);
|
|
254
|
+
if (platformStatus.online) {
|
|
255
|
+
await printSessionStatus(creds.token, envSuffix);
|
|
256
|
+
} else {
|
|
257
|
+
log(` Session: ${colors.yellow}Cannot verify (platform offline)${colors.reset}`, colors.dim);
|
|
258
|
+
}
|
|
259
|
+
log('');
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function printBrowserBlock() {
|
|
264
|
+
const browser = await getBrowserStatus();
|
|
265
|
+
if (browser.transports.length === 0) return;
|
|
266
|
+
log(' Browser', colors.bold);
|
|
267
|
+
for (const t of browser.transports) {
|
|
268
|
+
const label = transportLabel(t.kind);
|
|
269
|
+
const reason = t.reason ? ` ${colors.dim}(reason: ${t.reason})${colors.reset}` : '';
|
|
270
|
+
log(` Transport: ${label}${reason}`, colors.dim);
|
|
271
|
+
}
|
|
272
|
+
log('');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function printSessionStatus(token, envSuffix) {
|
|
276
|
+
process.stdout.write(' Session: Verifying...');
|
|
277
|
+
const tokenStatus = await verifyToken(token);
|
|
278
|
+
process.stdout.write('\r \r');
|
|
279
|
+
if (tokenStatus.valid) {
|
|
280
|
+
log(` Session: ${colors.green}Valid${colors.reset}`, colors.dim);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
log(` Session: ${colors.red}Invalid${colors.reset} (${tokenStatus.error})`, colors.dim);
|
|
284
|
+
log('');
|
|
285
|
+
log(` Run "minion login${envSuffix}" to re-authenticate.`, colors.dim);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function printCommandsBlock(envSuffix) {
|
|
289
|
+
log(' Commands', colors.bold);
|
|
290
|
+
log(` minion${envSuffix} Start a machine`, colors.dim);
|
|
291
|
+
log(` minion login${envSuffix} Sign in to your account`, colors.dim);
|
|
292
|
+
log(` minion logout${envSuffix} Sign out`, colors.dim);
|
|
293
|
+
log(` minion whoami${envSuffix} Show account details`, colors.dim);
|
|
294
|
+
log(` minion fingerprint${envSuffix} Verify encryption (safety number)`, colors.dim);
|
|
295
|
+
log('');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export default status;
|